diff options
author | Dave Chapman <dave@dchapman.com> | 2008-01-07 20:34:11 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2008-01-07 20:34:11 +0000 |
commit | 945c8a221ade41c462a93f8452320a806e5645b3 (patch) | |
tree | 2a17823e286e6252e60c44c7f4753d5c18ef5172 /firmware/drivers/lcd-charcell.c | |
parent | 2a8f39820b49f116820356c2ca224f82f2106c21 (diff) | |
download | rockbox-945c8a221ade41c462a93f8452320a806e5645b3.tar.gz rockbox-945c8a221ade41c462a93f8452320a806e5645b3.zip |
Add viewport capabilities to all the LCD drivers, and adapt scrolling code. This is the firmware/ part of FS#8385 - the changes to the WPS code still need more work and will be committed at a later date. NOTE: There are no user-visible changes with this commit - just the infrastructure.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16018 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/lcd-charcell.c')
-rw-r--r-- | firmware/drivers/lcd-charcell.c | 159 |
1 files changed, 119 insertions, 40 deletions
diff --git a/firmware/drivers/lcd-charcell.c b/firmware/drivers/lcd-charcell.c index 0fd41481c5..1bc634cd2f 100644 --- a/firmware/drivers/lcd-charcell.c +++ b/firmware/drivers/lcd-charcell.c | |||
@@ -52,8 +52,17 @@ static unsigned char xfont_variable[VARIABLE_XCHARS][HW_PATTERN_SIZE]; | |||
52 | static bool xfont_variable_locked[VARIABLE_XCHARS]; | 52 | static bool xfont_variable_locked[VARIABLE_XCHARS]; |
53 | static int xspace; /* stores xhcar id of ' ' - often needed */ | 53 | static int xspace; /* stores xhcar id of ' ' - often needed */ |
54 | 54 | ||
55 | static int xmargin = 0; | 55 | static struct viewport default_vp = |
56 | static int ymargin = 0; | 56 | { |
57 | .x = 0, | ||
58 | .y = 0, | ||
59 | .width = LCD_WIDTH, | ||
60 | .height = LCD_HEIGHT, | ||
61 | .xmargin = 0, | ||
62 | .ymargin = 0, | ||
63 | }; | ||
64 | |||
65 | static struct viewport* current_vp = &default_vp; | ||
57 | 66 | ||
58 | /* LCD init */ | 67 | /* LCD init */ |
59 | void lcd_init (void) | 68 | void lcd_init (void) |
@@ -66,22 +75,47 @@ void lcd_init (void) | |||
66 | scroll_init(); | 75 | scroll_init(); |
67 | } | 76 | } |
68 | 77 | ||
78 | /* Viewports */ | ||
79 | |||
80 | void lcd_set_viewport(struct viewport* vp) | ||
81 | { | ||
82 | if (vp == NULL) | ||
83 | current_vp = &default_vp; | ||
84 | else | ||
85 | current_vp = vp; | ||
86 | } | ||
87 | |||
88 | void lcd_update_viewport(void) | ||
89 | { | ||
90 | lcd_update(); | ||
91 | } | ||
92 | |||
69 | /** parameter handling **/ | 93 | /** parameter handling **/ |
70 | 94 | ||
71 | void lcd_setmargins(int x, int y) | 95 | void lcd_setmargins(int x, int y) |
72 | { | 96 | { |
73 | xmargin = x; | 97 | current_vp->xmargin = x; |
74 | ymargin = y; | 98 | current_vp->ymargin = y; |
75 | } | 99 | } |
76 | 100 | ||
77 | int lcd_getxmargin(void) | 101 | int lcd_getxmargin(void) |
78 | { | 102 | { |
79 | return xmargin; | 103 | return current_vp->xmargin; |
80 | } | 104 | } |
81 | 105 | ||
82 | int lcd_getymargin(void) | 106 | int lcd_getymargin(void) |
83 | { | 107 | { |
84 | return ymargin; | 108 | return current_vp->ymargin; |
109 | } | ||
110 | |||
111 | int lcd_getwidth(void) | ||
112 | { | ||
113 | return current_vp->width; | ||
114 | } | ||
115 | |||
116 | int lcd_getheight(void) | ||
117 | { | ||
118 | return current_vp->height; | ||
85 | } | 119 | } |
86 | 120 | ||
87 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) | 121 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) |
@@ -225,7 +259,13 @@ static int map_xchar(int xchar, unsigned char *substitute) | |||
225 | 259 | ||
226 | static void lcd_putxchar(int x, int y, int xchar) | 260 | static void lcd_putxchar(int x, int y, int xchar) |
227 | { | 261 | { |
228 | int lcd_char = lcd_charbuffer[y][x]; | 262 | int lcd_char; |
263 | |||
264 | /* Adjust for viewport */ | ||
265 | x += current_vp->x; | ||
266 | y += current_vp->y; | ||
267 | |||
268 | lcd_char = lcd_charbuffer[y][x]; | ||
229 | 269 | ||
230 | if (lcd_char < lcd_pattern_count) /* old char was soft */ | 270 | if (lcd_char < lcd_pattern_count) /* old char was soft */ |
231 | lcd_patterns[lcd_char].count--; /* decrease old reference count */ | 271 | lcd_patterns[lcd_char].count--; /* decrease old reference count */ |
@@ -283,19 +323,55 @@ void lcd_define_pattern(unsigned long ucs, const char *pattern) | |||
283 | void lcd_clear_display(void) | 323 | void lcd_clear_display(void) |
284 | { | 324 | { |
285 | int x, y; | 325 | int x, y; |
326 | struct viewport* old_vp = current_vp; | ||
286 | 327 | ||
287 | lcd_stop_scroll(); | 328 | lcd_scroll_info.lines = 0; |
288 | lcd_remove_cursor(); | 329 | lcd_remove_cursor(); |
289 | 330 | ||
331 | /* Set the default viewport - required for lcd_putxchar */ | ||
332 | current_vp = &default_vp; | ||
333 | |||
290 | for (x = 0; x < LCD_WIDTH; x++) | 334 | for (x = 0; x < LCD_WIDTH; x++) |
291 | for (y = 0; y < LCD_HEIGHT; y++) | 335 | for (y = 0; y < LCD_HEIGHT; y++) |
292 | lcd_putxchar(x, y, xspace); | 336 | lcd_putxchar(x, y, xspace); |
337 | |||
338 | current_vp = old_vp; | ||
339 | } | ||
340 | |||
341 | /* Clear the current viewport */ | ||
342 | void lcd_clear_viewport(void) | ||
343 | { | ||
344 | int x, y; | ||
345 | |||
346 | if (current_vp == &default_vp) | ||
347 | { | ||
348 | lcd_clear_display(); | ||
349 | } | ||
350 | else | ||
351 | { | ||
352 | /* Remove the cursor if it is within the current viewport */ | ||
353 | if (lcd_cursor.enabled && | ||
354 | (lcd_cursor.x >= current_vp->x) && | ||
355 | (lcd_cursor.x <= current_vp->x + current_vp->width) && | ||
356 | (lcd_cursor.y >= current_vp->y) && | ||
357 | (lcd_cursor.y <= current_vp->y + current_vp->height)) | ||
358 | { | ||
359 | lcd_remove_cursor(); | ||
360 | } | ||
361 | |||
362 | for (x = 0; x < current_vp->width; x++) | ||
363 | for (y = 0; y < current_vp->height; y++) | ||
364 | lcd_putxchar(x, y, xspace); | ||
365 | |||
366 | lcd_scroll_stop(current_vp); | ||
367 | } | ||
293 | } | 368 | } |
294 | 369 | ||
295 | /* Put an unicode character at the given position */ | 370 | /* Put an unicode character at the given position */ |
296 | void lcd_putc(int x, int y, unsigned long ucs) | 371 | void lcd_putc(int x, int y, unsigned long ucs) |
297 | { | 372 | { |
298 | if ((unsigned)x >= LCD_WIDTH || (unsigned)y >= LCD_HEIGHT) | 373 | if ((unsigned)x >= (unsigned)current_vp->width || |
374 | (unsigned)y >= (unsigned)current_vp->height) | ||
299 | return; | 375 | return; |
300 | 376 | ||
301 | lcd_putxchar(x, y, find_xchar(ucs)); | 377 | lcd_putxchar(x, y, find_xchar(ucs)); |
@@ -304,15 +380,16 @@ void lcd_putc(int x, int y, unsigned long ucs) | |||
304 | /* Show cursor (alternating with existing character) at the given position */ | 380 | /* Show cursor (alternating with existing character) at the given position */ |
305 | void lcd_put_cursor(int x, int y, unsigned long cursor_ucs) | 381 | void lcd_put_cursor(int x, int y, unsigned long cursor_ucs) |
306 | { | 382 | { |
307 | if ((unsigned)x >= LCD_WIDTH || (unsigned)y >= LCD_HEIGHT | 383 | if ((unsigned)x >= (unsigned)current_vp->width || |
308 | || lcd_cursor.enabled) | 384 | (unsigned)y >= (unsigned)current_vp->height || |
385 | lcd_cursor.enabled) | ||
309 | return; | 386 | return; |
310 | 387 | ||
311 | lcd_cursor.enabled = true; | 388 | lcd_cursor.enabled = true; |
312 | lcd_cursor.visible = false; | 389 | lcd_cursor.visible = false; |
313 | lcd_cursor.hw_char = map_xchar(find_xchar(cursor_ucs), &lcd_cursor.subst_char); | 390 | lcd_cursor.hw_char = map_xchar(find_xchar(cursor_ucs), &lcd_cursor.subst_char); |
314 | lcd_cursor.x = x; | 391 | lcd_cursor.x = current_vp->x + x; |
315 | lcd_cursor.y = y; | 392 | lcd_cursor.y = current_vp->y + y; |
316 | lcd_cursor.downcount = 0; | 393 | lcd_cursor.downcount = 0; |
317 | lcd_cursor.divider = MAX((HZ/2) / lcd_scroll_info.ticks, 1); | 394 | lcd_cursor.divider = MAX((HZ/2) / lcd_scroll_info.ticks, 1); |
318 | } | 395 | } |
@@ -335,7 +412,7 @@ static int lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
335 | unsigned short ucs; | 412 | unsigned short ucs; |
336 | const unsigned char *utf8 = str; | 413 | const unsigned char *utf8 = str; |
337 | 414 | ||
338 | while (*utf8 && x < LCD_WIDTH) | 415 | while (*utf8 && x < current_vp->width) |
339 | { | 416 | { |
340 | utf8 = utf8decode(utf8, &ucs); | 417 | utf8 = utf8decode(utf8, &ucs); |
341 | 418 | ||
@@ -352,7 +429,7 @@ static int lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
352 | /* Put a string at a given position */ | 429 | /* Put a string at a given position */ |
353 | void lcd_putsxy(int x, int y, const unsigned char *str) | 430 | void lcd_putsxy(int x, int y, const unsigned char *str) |
354 | { | 431 | { |
355 | if ((unsigned)y >= LCD_HEIGHT) | 432 | if ((unsigned)y >= (unsigned)current_vp->height) |
356 | return; | 433 | return; |
357 | 434 | ||
358 | lcd_putsxyofs(x, y, 0, str); | 435 | lcd_putsxyofs(x, y, 0, str); |
@@ -369,17 +446,14 @@ void lcd_puts(int x, int y, const unsigned char *str) | |||
369 | /* Put a string at a given char position, skipping first offset chars */ | 446 | /* Put a string at a given char position, skipping first offset chars */ |
370 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) | 447 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) |
371 | { | 448 | { |
372 | x += xmargin; | 449 | if ((unsigned)y >= (unsigned)current_vp->height) |
373 | y += ymargin; | ||
374 | |||
375 | if ((unsigned)y >= LCD_HEIGHT) | ||
376 | return; | 450 | return; |
377 | 451 | ||
378 | /* make sure scrolling is turned off on the line we are updating */ | 452 | /* make sure scrolling is turned off on the line we are updating */ |
379 | lcd_scroll_info.lines &= ~(1 << y); | 453 | lcd_scroll_stop_line(current_vp, y); |
380 | 454 | ||
381 | x = lcd_putsxyofs(x, y, offset, str); | 455 | x = lcd_putsxyofs(x, y, offset, str); |
382 | while (x < LCD_WIDTH) | 456 | while (x < current_vp->width) |
383 | lcd_putxchar(x++, y, xspace); | 457 | lcd_putxchar(x++, y, xspace); |
384 | } | 458 | } |
385 | 459 | ||
@@ -395,16 +469,22 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, | |||
395 | struct scrollinfo* s; | 469 | struct scrollinfo* s; |
396 | int len; | 470 | int len; |
397 | 471 | ||
398 | if(y>=LCD_SCROLLABLE_LINES) return; | 472 | if ((unsigned)y >= (unsigned)current_vp->height) |
473 | return; | ||
474 | |||
475 | /* remove any previously scrolling line at the same location */ | ||
476 | lcd_scroll_stop_line(current_vp, y); | ||
399 | 477 | ||
400 | s = &lcd_scroll_info.scroll[y]; | 478 | if (lcd_scroll_info.lines >= LCD_SCROLLABLE_LINES) return; |
479 | |||
480 | s = &lcd_scroll_info.scroll[lcd_scroll_info.lines]; | ||
401 | 481 | ||
402 | s->start_tick = current_tick + lcd_scroll_info.delay; | 482 | s->start_tick = current_tick + lcd_scroll_info.delay; |
403 | 483 | ||
404 | lcd_puts_offset(x, y, string, offset); | 484 | lcd_puts_offset(x, y, string, offset); |
405 | len = utf8length(string); | 485 | len = utf8length(string); |
406 | 486 | ||
407 | if (LCD_WIDTH - x - xmargin < len) | 487 | if (current_vp->width - x - current_vp->xmargin < len) |
408 | { | 488 | { |
409 | /* prepare scroll line */ | 489 | /* prepare scroll line */ |
410 | char *end; | 490 | char *end; |
@@ -418,7 +498,7 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, | |||
418 | /* scroll bidirectional or forward only depending on the string width */ | 498 | /* scroll bidirectional or forward only depending on the string width */ |
419 | if (lcd_scroll_info.bidir_limit) | 499 | if (lcd_scroll_info.bidir_limit) |
420 | { | 500 | { |
421 | s->bidir = s->len < (LCD_WIDTH - xmargin) * | 501 | s->bidir = s->len < (current_vp->width - current_vp->xmargin) * |
422 | (100 + lcd_scroll_info.bidir_limit) / 100; | 502 | (100 + lcd_scroll_info.bidir_limit) / 100; |
423 | } | 503 | } |
424 | else | 504 | else |
@@ -432,16 +512,15 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string, | |||
432 | } | 512 | } |
433 | 513 | ||
434 | end = strchr(s->line, '\0'); | 514 | end = strchr(s->line, '\0'); |
435 | strncpy(end, string, utf8seek(s->line, LCD_WIDTH)); | 515 | strncpy(end, string, utf8seek(s->line, current_vp->width)); |
436 | 516 | ||
517 | s->vp = current_vp; | ||
518 | s->y = y; | ||
437 | s->offset = offset; | 519 | s->offset = offset; |
438 | s->startx = xmargin + x; | 520 | s->startx = current_vp->xmargin + x; |
439 | s->backward = false; | 521 | s->backward = false; |
440 | lcd_scroll_info.lines |= (1<<y); | 522 | lcd_scroll_info.lines++; |
441 | } | 523 | } |
442 | else | ||
443 | /* force a bit switch-off since it doesn't scroll */ | ||
444 | lcd_scroll_info.lines &= ~(1<<y); | ||
445 | } | 524 | } |
446 | 525 | ||
447 | void lcd_scroll_fn(void) | 526 | void lcd_scroll_fn(void) |
@@ -450,27 +529,25 @@ void lcd_scroll_fn(void) | |||
450 | int index; | 529 | int index; |
451 | int xpos, ypos; | 530 | int xpos, ypos; |
452 | bool update; | 531 | bool update; |
532 | struct viewport* old_vp = current_vp; | ||
453 | 533 | ||
454 | update = false; | 534 | update = false; |
455 | for (index = 0; index < LCD_SCROLLABLE_LINES; index++) | 535 | for ( index = 0; index < lcd_scroll_info.lines; index++ ) { |
456 | { | ||
457 | /* really scroll? */ | ||
458 | if ((lcd_scroll_info.lines & (1 << index)) == 0) | ||
459 | continue; | ||
460 | |||
461 | s = &lcd_scroll_info.scroll[index]; | 536 | s = &lcd_scroll_info.scroll[index]; |
462 | 537 | ||
463 | /* check pause */ | 538 | /* check pause */ |
464 | if (TIME_BEFORE(current_tick, s->start_tick)) | 539 | if (TIME_BEFORE(current_tick, s->start_tick)) |
465 | continue; | 540 | continue; |
466 | 541 | ||
542 | lcd_set_viewport(s->vp); | ||
543 | |||
467 | if (s->backward) | 544 | if (s->backward) |
468 | s->offset--; | 545 | s->offset--; |
469 | else | 546 | else |
470 | s->offset++; | 547 | s->offset++; |
471 | 548 | ||
472 | xpos = s->startx; | 549 | xpos = s->startx; |
473 | ypos = ymargin + index; | 550 | ypos = current_vp->ymargin + s->y; |
474 | 551 | ||
475 | if (s->bidir) /* scroll bidirectional */ | 552 | if (s->bidir) /* scroll bidirectional */ |
476 | { | 553 | { |
@@ -480,9 +557,9 @@ void lcd_scroll_fn(void) | |||
480 | s->backward = false; | 557 | s->backward = false; |
481 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 558 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
482 | } | 559 | } |
483 | if (s->offset >= s->len - (LCD_WIDTH - xpos)) { | 560 | if (s->offset >= s->len - (current_vp->width - xpos)) { |
484 | /* at end of line */ | 561 | /* at end of line */ |
485 | s->offset = s->len - (LCD_WIDTH - xpos); | 562 | s->offset = s->len - (current_vp->width - xpos); |
486 | s->backward = true; | 563 | s->backward = true; |
487 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; | 564 | s->start_tick = current_tick + lcd_scroll_info.delay * 2; |
488 | } | 565 | } |
@@ -497,6 +574,8 @@ void lcd_scroll_fn(void) | |||
497 | update = true; | 574 | update = true; |
498 | } | 575 | } |
499 | 576 | ||
577 | lcd_set_viewport(old_vp); | ||
578 | |||
500 | if (lcd_cursor.enabled) | 579 | if (lcd_cursor.enabled) |
501 | { | 580 | { |
502 | if (--lcd_cursor.downcount <= 0) | 581 | if (--lcd_cursor.downcount <= 0) |