summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-scroll.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/lcd-scroll.c')
-rw-r--r--firmware/drivers/lcd-scroll.c111
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 */
58void LCDFN(scroll_stop_viewport_line)(const struct viewport *current_vp, int line) 58void 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 */
90void LCDFN(scroll_stop_viewport)(const struct viewport *current_vp) 87void 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
95void LCDFN(scroll_speed)(int speed) 92void 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
126static 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}