summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/lcd-bitmap-common.c69
-rw-r--r--firmware/drivers/lcd-scroll.c12
-rw-r--r--firmware/export/lcd-remote.h4
-rw-r--r--firmware/export/lcd.h4
-rw-r--r--firmware/export/scroll_engine.h5
5 files changed, 58 insertions, 36 deletions
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c
index a71f5b2862..22430d4e50 100644
--- a/firmware/drivers/lcd-bitmap-common.c
+++ b/firmware/drivers/lcd-bitmap-common.c
@@ -316,15 +316,19 @@ static struct scrollinfo* find_scrolling_line(int x, int y)
316 316
317void LCDFN(scroll_fn)(struct scrollinfo* s) 317void LCDFN(scroll_fn)(struct scrollinfo* s)
318{ 318{
319 /* with line == NULL when scrolling stops. This scroller
320 * maintains no userdata so there is nothing left to do */
321 if (!s->line)
322 return;
319 /* Fill with background/backdrop to clear area. 323 /* Fill with background/backdrop to clear area.
320 * cannot use clear_viewport_rect() since stops scrolling as well */ 324 * cannot use clear_viewport_rect() since would stop scrolling as well */
321 LCDFN(set_drawmode)(DRMODE_SOLID|DRMODE_INVERSEVID); 325 LCDFN(set_drawmode)(DRMODE_SOLID|DRMODE_INVERSEVID);
322 LCDFN(fillrect)(s->x, s->y, s->width, s->height); 326 LCDFN(fillrect)(s->x, s->y, s->width, s->height);
323 LCDFN(set_drawmode)(DRMODE_SOLID); 327 LCDFN(set_drawmode)(DRMODE_SOLID);
324 LCDFN(putsxyofs)(s->x, s->y, s->offset, s->line); 328 LCDFN(putsxyofs)(s->x, s->y, s->offset, s->line);
325} 329}
326 330
327static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, 331static bool LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
328 int x_offset, 332 int x_offset,
329 bool linebased, 333 bool linebased,
330 void (*scroll_func)(struct scrollinfo *), 334 void (*scroll_func)(struct scrollinfo *),
@@ -336,7 +340,7 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
336 bool restart; 340 bool restart;
337 341
338 if (!string) 342 if (!string)
339 return; 343 return false;
340 344
341 /* prepare rectangle for scrolling. x and y must be calculated early 345 /* prepare rectangle for scrolling. x and y must be calculated early
342 * for find_scrolling_line() to work */ 346 * for find_scrolling_line() to work */
@@ -347,32 +351,25 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
347 width = current_vp->width - x; 351 width = current_vp->width - x;
348 352
349 if (y >= current_vp->height) 353 if (y >= current_vp->height)
350 return; 354 return false;
351 355
352 s = find_scrolling_line(x, y); 356 s = find_scrolling_line(x, y);
353 restart = !s; 357 restart = !s;
354 358
355 if (restart) {
356 /* remove any previously scrolling line at the same location */
357 LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height);
358 LCDFN(putsxyofs)(x, y, x_offset, string);
359
360 if (LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES))
361 return;
362 }
363
364 /* get width (pixeks) of the string */ 359 /* get width (pixeks) of the string */
365 LCDFN(getstringsize)(string, &w, &h); 360 LCDFN(getstringsize)(string, &w, &h);
366 361
367 /* check if scrolling is actually necessary (consider the actual start 362 /* Remove any previously scrolling line at the same location. If
368 * of the line) */ 363 * the string width is too small to scroll the scrolling line is
369 if (width >= w) 364 * cleared as well */
370 return; 365 if (w < width || restart) {
371 366 LCDFN(scroll_stop_viewport_rect)(current_vp, x, y, width, height);
372 if (restart) { 367 LCDFN(putsxyofs)(x, y, x_offset, string);
373 /* prepare scroll line */ 368 /* nothing to scroll, or out of scrolling lines. Either way, get out */
369 if (w < width || LCDFN(scroll_info).lines >= LCDM(SCROLLABLE_LINES))
370 return false;
371 /* else restarting: prepare scroll line */
374 s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines]; 372 s = &LCDFN(scroll_info).scroll[LCDFN(scroll_info).lines];
375 s->start_tick = current_tick + LCDFN(scroll_info).delay;
376 } 373 }
377 374
378 /* copy contents to the line buffer */ 375 /* copy contents to the line buffer */
@@ -385,9 +382,6 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
385 else 382 else
386 s->bidir = false; 383 s->bidir = false;
387 384
388 s->scroll_func = scroll_func;
389 s->userdata = data;
390
391 if (restart) { 385 if (restart) {
392 s->offset = x_offset; 386 s->offset = x_offset;
393 s->backward = false; 387 s->backward = false;
@@ -397,26 +391,41 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string,
397 s->width = width; 391 s->width = width;
398 s->height = height; 392 s->height = height;
399 s->vp = current_vp; 393 s->vp = current_vp;
394 s->start_tick = current_tick + LCDFN(scroll_info).delay;
400 LCDFN(scroll_info).lines++; 395 LCDFN(scroll_info).lines++;
401 } else { 396 } else {
402 /* if only the text was updated render immediately */ 397 /* not restarting, however we are about to assign new userdata;
403 LCDFN(scroll_now(s)); 398 * therefore tell the scroller that it can release the previous userdata */
399 s->line = NULL;
400 s->scroll_func(s);
404 } 401 }
402
403 s->scroll_func = scroll_func;
404 s->userdata = data;
405
406 /* if only the text was updated render immediately */
407 if (!restart)
408 LCDFN(scroll_now(s));
409
410 return true;
405} 411}
406 412
407void LCDFN(putsxy_scroll_func)(int x, int y, const unsigned char *string, 413bool LCDFN(putsxy_scroll_func)(int x, int y, const unsigned char *string,
408 void (*scroll_func)(struct scrollinfo *), 414 void (*scroll_func)(struct scrollinfo *),
409 void *data, int x_offset) 415 void *data, int x_offset)
410{ 416{
417 bool retval = false;
411 if (!scroll_func) 418 if (!scroll_func)
412 LCDFN(putsxyofs)(x, y, x_offset, string); 419 LCDFN(putsxyofs)(x, y, x_offset, string);
413 else 420 else
414 LCDFN(puts_scroll_worker)(x, y, string, x_offset, false, scroll_func, data); 421 retval = LCDFN(puts_scroll_worker)(x, y, string, x_offset, false, scroll_func, data);
422
423 return retval;
415} 424}
416 425
417void LCDFN(puts_scroll)(int x, int y, const unsigned char *string) 426bool LCDFN(puts_scroll)(int x, int y, const unsigned char *string)
418{ 427{
419 LCDFN(puts_scroll_worker)(x, y, string, 0, true, LCDFN(scroll_fn), NULL); 428 return LCDFN(puts_scroll_worker)(x, y, string, 0, true, LCDFN(scroll_fn), NULL);
420} 429}
421 430
422#if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD) 431#if !defined(HAVE_LCD_COLOR) || !defined(MAIN_LCD)
diff --git a/firmware/drivers/lcd-scroll.c b/firmware/drivers/lcd-scroll.c
index a1bde9fe12..5162f9a100 100644
--- a/firmware/drivers/lcd-scroll.c
+++ b/firmware/drivers/lcd-scroll.c
@@ -30,7 +30,7 @@
30#define MAIN_LCD 30#define MAIN_LCD
31#endif 31#endif
32 32
33static struct scrollinfo LCDFN(scroll)[LCD_SCROLLABLE_LINES]; 33static struct scrollinfo LCDFN(scroll)[LCDM(SCROLLABLE_LINES)];
34 34
35struct scroll_screen_info LCDFN(scroll_info) = 35struct scroll_screen_info LCDFN(scroll_info) =
36{ 36{
@@ -51,6 +51,13 @@ struct scroll_screen_info LCDFN(scroll_info) =
51 51
52void LCDFN(scroll_stop)(void) 52void LCDFN(scroll_stop)(void)
53{ 53{
54 for (int i = 0; i < LCDFN(scroll_info).lines; i++)
55 {
56 /* inform scroller about end of scrolling */
57 struct scrollinfo *s = &LCDFN(scroll_info).scroll[i];
58 s->line = NULL;
59 s->scroll_func(s);
60 }
54 LCDFN(scroll_info).lines = 0; 61 LCDFN(scroll_info).lines = 0;
55} 62}
56 63
@@ -66,6 +73,9 @@ void LCDFN(scroll_stop_viewport_rect)(const struct viewport *vp, int x, int y, i
66 && (x < (s->x+s->width) && (x+width) >= s->x) 73 && (x < (s->x+s->width) && (x+width) >= s->x)
67 && (y < (s->y+s->height) && (y+height) >= s->y)) 74 && (y < (s->y+s->height) && (y+height) >= s->y))
68 { 75 {
76 /* inform scroller about end of scrolling */
77 s->line = NULL;
78 s->scroll_func(s);
69 /* If i is not the last active line in the array, then move 79 /* If i is not the last active line in the array, then move
70 the last item to position i. This compacts 80 the last item to position i. This compacts
71 the scroll array at the same time of removing the line */ 81 the scroll array at the same time of removing the line */
diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h
index bc26a23cb7..1819a4de72 100644
--- a/firmware/export/lcd-remote.h
+++ b/firmware/export/lcd-remote.h
@@ -176,8 +176,8 @@ extern void lcd_remote_clear_viewport(void);
176extern void lcd_remote_puts(int x, int y, const unsigned char *str); 176extern void lcd_remote_puts(int x, int y, const unsigned char *str);
177extern void lcd_remote_putsf(int x, int y, const unsigned char *fmt, ...); 177extern void lcd_remote_putsf(int x, int y, const unsigned char *fmt, ...);
178extern void lcd_remote_putc(int x, int y, unsigned short ch); 178extern void lcd_remote_putc(int x, int y, unsigned short ch);
179extern void lcd_remote_puts_scroll(int x, int y, const unsigned char *str); 179extern bool lcd_remote_puts_scroll(int x, int y, const unsigned char *str);
180extern void lcd_remote_putsxy_scroll_func(int x, int y, const unsigned char *string, 180extern bool lcd_remote_putsxy_scroll_func(int x, int y, const unsigned char *string,
181 void (*scroll_func)(struct scrollinfo *), 181 void (*scroll_func)(struct scrollinfo *),
182 void *data, int x_offset); 182 void *data, int x_offset);
183 183
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 87476d9dda..386ac5a8bf 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -179,8 +179,8 @@ extern void lcd_putsxy_style_offset(int x, int y, const unsigned char *str,
179extern void lcd_puts(int x, int y, const unsigned char *string); 179extern void lcd_puts(int x, int y, const unsigned char *string);
180extern void lcd_putsf(int x, int y, const unsigned char *fmt, ...); 180extern void lcd_putsf(int x, int y, const unsigned char *fmt, ...);
181extern void lcd_putc(int x, int y, unsigned long ucs); 181extern void lcd_putc(int x, int y, unsigned long ucs);
182extern void lcd_puts_scroll(int x, int y, const unsigned char* string); 182extern bool lcd_puts_scroll(int x, int y, const unsigned char* string);
183extern void lcd_putsxy_scroll_func(int x, int y, const unsigned char *string, 183extern bool lcd_putsxy_scroll_func(int x, int y, const unsigned char *string,
184 void (*scroll_func)(struct scrollinfo *), 184 void (*scroll_func)(struct scrollinfo *),
185 void *data, int x_offset); 185 void *data, int x_offset);
186 186
diff --git a/firmware/export/scroll_engine.h b/firmware/export/scroll_engine.h
index 64e1d6d6ae..ce230a218c 100644
--- a/firmware/export/scroll_engine.h
+++ b/firmware/export/scroll_engine.h
@@ -79,7 +79,10 @@ struct scrollinfo
79 bool bidir; 79 bool bidir;
80 long start_tick; 80 long start_tick;
81 81
82 /* support for custom scrolling functions */ 82 /* support for custom scrolling functions,
83 * must be called with ::line == NULL to indicate that the line
84 * stops scrolling or when the userdata pointer is going to be changed
85 * (the custom scroller can release the userdata then) */
83 void (*scroll_func)(struct scrollinfo *s); 86 void (*scroll_func)(struct scrollinfo *s);
84 void *userdata; 87 void *userdata;
85}; 88};