diff options
Diffstat (limited to 'firmware/drivers/lcd-scroll.c')
-rw-r--r-- | firmware/drivers/lcd-scroll.c | 111 |
1 files changed, 97 insertions, 14 deletions
diff --git a/firmware/drivers/lcd-scroll.c b/firmware/drivers/lcd-scroll.c index ffd4663c79..31c2cf20b0 100644 --- a/firmware/drivers/lcd-scroll.c +++ b/firmware/drivers/lcd-scroll.c | |||
@@ -54,30 +54,27 @@ void LCDFN(scroll_stop)(void) | |||
54 | LCDFN(scroll_info).lines = 0; | 54 | LCDFN(scroll_info).lines = 0; |
55 | } | 55 | } |
56 | 56 | ||
57 | /* Stop scrolling line y in the specified viewport, or all lines if y < 0 */ | 57 | /* Clears scrolling lines that intersect with the area */ |
58 | void LCDFN(scroll_stop_viewport_line)(const struct viewport *current_vp, int line) | 58 | void LCDFN(scroll_stop_viewport_rect)(const struct viewport *vp, int x, int y, int width, int height) |
59 | { | 59 | { |
60 | int i = 0; | 60 | int i = 0; |
61 | |||
62 | while (i < LCDFN(scroll_info).lines) | 61 | while (i < LCDFN(scroll_info).lines) |
63 | { | 62 | { |
64 | struct viewport *vp = LCDFN(scroll_info).scroll[i].vp; | 63 | struct scrollinfo *s = &LCDFN(scroll_info).scroll[i]; |
65 | if (((vp == current_vp)) && | 64 | /* check if the specified area crosses the viewport in some way */ |
66 | ((line < 0) || (LCDFN(scroll_info).scroll[i].y == line))) | 65 | if (s->vp == vp |
66 | && (x < (s->x+s->width) && (x+width) >= s->x) | ||
67 | && (y < (s->y+s->height) && (y+height) >= s->y)) | ||
67 | { | 68 | { |
68 | /* If i is not the last active line in the array, then move | 69 | /* If i is not the last active line in the array, then move |
69 | the last item to position i */ | 70 | the last item to position i. This compacts |
71 | the scroll array at the same time of removing the line */ | ||
70 | if ((i + 1) != LCDFN(scroll_info).lines) | 72 | if ((i + 1) != LCDFN(scroll_info).lines) |
71 | { | 73 | { |
72 | LCDFN(scroll_info).scroll[i] = | 74 | LCDFN(scroll_info).scroll[i] = |
73 | LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines-1]; | 75 | LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines-1]; |
74 | } | 76 | } |
75 | LCDFN(scroll_info).lines--; | 77 | LCDFN(scroll_info).lines--; |
76 | |||
77 | /* A line can only appear once, so we're done, | ||
78 | * unless we are clearing the whole viewport */ | ||
79 | if (line >= 0) | ||
80 | return ; | ||
81 | } | 78 | } |
82 | else | 79 | else |
83 | { | 80 | { |
@@ -87,9 +84,9 @@ void LCDFN(scroll_stop_viewport_line)(const struct viewport *current_vp, int lin | |||
87 | } | 84 | } |
88 | 85 | ||
89 | /* Stop all scrolling lines in the specified viewport */ | 86 | /* Stop all scrolling lines in the specified viewport */ |
90 | void LCDFN(scroll_stop_viewport)(const struct viewport *current_vp) | 87 | void LCDFN(scroll_stop_viewport)(const struct viewport *vp) |
91 | { | 88 | { |
92 | LCDFN(scroll_stop_viewport_line)(current_vp, -1); | 89 | LCDFN(scroll_stop_viewport_rect)(vp, 0, 0, vp->width, vp->height); |
93 | } | 90 | } |
94 | 91 | ||
95 | void LCDFN(scroll_speed)(int speed) | 92 | void LCDFN(scroll_speed)(int speed) |
@@ -125,3 +122,89 @@ void LCDFN(jump_scroll_delay)(int ms) | |||
125 | LCDFN(scroll_info).jump_scroll_delay = ms / (HZ / 10); | 122 | LCDFN(scroll_info).jump_scroll_delay = ms / (HZ / 10); |
126 | } | 123 | } |
127 | #endif | 124 | #endif |
125 | |||
126 | static void LCDFN(scroll_worker)(void) | ||
127 | { | ||
128 | int index, width; | ||
129 | bool makedelay; | ||
130 | static char line_buf[SCROLL_LINE_SIZE]; | ||
131 | bool is_default; | ||
132 | struct scroll_screen_info *si = &LCDFN(scroll_info); | ||
133 | struct scrollinfo *s; | ||
134 | struct viewport *vp; | ||
135 | |||
136 | unsigned fg_pattern, bg_pattern, drawmode; | ||
137 | |||
138 | for ( index = 0; index < si->lines; index++ ) { | ||
139 | s = &si->scroll[index]; | ||
140 | |||
141 | /* check pause */ | ||
142 | if (TIME_BEFORE(current_tick, s->start_tick)) | ||
143 | continue; | ||
144 | |||
145 | s->start_tick = current_tick; | ||
146 | |||
147 | /* this runs out of the ui thread, thus we need to | ||
148 | * save and restore the current viewport since the ui thread | ||
149 | * is unaware of the swapped viewports. the vp must | ||
150 | * be switched early so that lcd_getstringsize() picks the | ||
151 | * correct font */ | ||
152 | vp = LCDFN(get_viewport)(&is_default); | ||
153 | LCDFN(set_viewport)(s->vp); | ||
154 | |||
155 | width = LCDFN(getstringsize)(s->linebuffer, NULL, NULL); | ||
156 | makedelay = false; | ||
157 | |||
158 | if (s->backward) | ||
159 | s->offset -= si->step; | ||
160 | else | ||
161 | s->offset += si->step; | ||
162 | |||
163 | if (s->bidir) { /* scroll bidirectional */ | ||
164 | |||
165 | s->line = s->linebuffer; | ||
166 | if (s->offset <= 0) { | ||
167 | /* at beginning of line */ | ||
168 | s->offset = 0; | ||
169 | s->backward = false; | ||
170 | makedelay = true; | ||
171 | } | ||
172 | else if (s->offset >= width - (s->width - s->x)) { | ||
173 | /* at end of line */ | ||
174 | s->offset = width - (s->width - s->x); | ||
175 | s->backward = true; | ||
176 | makedelay = true; | ||
177 | } | ||
178 | } | ||
179 | else { | ||
180 | |||
181 | snprintf(line_buf, sizeof(line_buf)-1, "%s%s%s", | ||
182 | s->linebuffer, " ", s->linebuffer); | ||
183 | s->line = line_buf; | ||
184 | width += LCDFN(getstringsize)(" ", NULL, NULL); | ||
185 | /* scroll forward the whole time */ | ||
186 | if (s->offset >= width) { | ||
187 | s->offset = 0; | ||
188 | makedelay = true; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | /* Stash and restore these three, so that the scroll_func | ||
193 | * can do whatever it likes without destroying the state */ | ||
194 | fg_pattern = s->vp->fg_pattern; | ||
195 | bg_pattern = s->vp->bg_pattern; | ||
196 | drawmode = s->vp->drawmode; | ||
197 | |||
198 | s->scroll_func(s); | ||
199 | LCDFN(update_viewport_rect)(s->x, s->y, s->width, s->height); | ||
200 | |||
201 | s->vp->fg_pattern = fg_pattern; | ||
202 | s->vp->bg_pattern = bg_pattern; | ||
203 | s->vp->drawmode = drawmode; | ||
204 | |||
205 | LCDFN(set_viewport)(vp); | ||
206 | |||
207 | if (makedelay) | ||
208 | s->start_tick += si->delay + si->ticks; | ||
209 | } | ||
210 | } | ||