diff options
Diffstat (limited to 'firmware/drivers/lcd-h100-remote.c')
-rw-r--r-- | firmware/drivers/lcd-h100-remote.c | 172 |
1 files changed, 123 insertions, 49 deletions
diff --git a/firmware/drivers/lcd-h100-remote.c b/firmware/drivers/lcd-h100-remote.c index f0759d6328..2850712a91 100644 --- a/firmware/drivers/lcd-h100-remote.c +++ b/firmware/drivers/lcd-h100-remote.c | |||
@@ -29,12 +29,9 @@ | |||
29 | #include "system.h" | 29 | #include "system.h" |
30 | #include "font.h" | 30 | #include "font.h" |
31 | 31 | ||
32 | /* All zeros and ones bitmaps for area filling */ | 32 | /* All zeros and ones bitmaps for area filling */ |
33 | static const unsigned char zeros[16] = { | 33 | static const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
34 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 34 | static const unsigned char ones[8] = { |
35 | }; | ||
36 | static const unsigned char ones[16] = { | ||
37 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
38 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | 35 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff |
39 | }; | 36 | }; |
40 | 37 | ||
@@ -66,6 +63,16 @@ struct scrollinfo { | |||
66 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | 63 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ |
67 | 64 | ||
68 | #ifndef SIMULATOR | 65 | #ifndef SIMULATOR |
66 | static int countdown; /* for remote plugging debounce */ | ||
67 | static bool last_remote_status = false; | ||
68 | static bool init_remote = false; /* scroll thread should init lcd */ | ||
69 | static bool remote_initialized = false; | ||
70 | |||
71 | /* cached settings values, for hotplug init */ | ||
72 | static bool cached_invert = false; | ||
73 | static int cached_contrast = 32; | ||
74 | static int cached_roll = 0; | ||
75 | |||
69 | static void scroll_thread(void); | 76 | static void scroll_thread(void); |
70 | static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)]; | 77 | static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)]; |
71 | #endif | 78 | #endif |
@@ -209,18 +216,25 @@ void lcd_remote_write_command_ex(int cmd, int data) | |||
209 | 216 | ||
210 | void lcd_remote_powersave(bool on) | 217 | void lcd_remote_powersave(bool on) |
211 | { | 218 | { |
212 | lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | (on ? 0 : 1)); | 219 | if (remote_initialized) |
213 | lcd_remote_write_command(LCD_REMOTE_CNTL_ENTIRE_ON_OFF | (on ? 1 : 0)); | 220 | { |
221 | lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | (on ? 0 : 1)); | ||
222 | lcd_remote_write_command(LCD_REMOTE_CNTL_ENTIRE_ON_OFF | (on ? 1 : 0)); | ||
223 | } | ||
214 | } | 224 | } |
215 | 225 | ||
216 | void lcd_remote_set_contrast(int val) | 226 | void lcd_remote_set_contrast(int val) |
217 | { | 227 | { |
218 | lcd_remote_write_command_ex(LCD_REMOTE_CNTL_SELECT_VOLTAGE, val); | 228 | cached_contrast = val; |
229 | if (remote_initialized) | ||
230 | lcd_remote_write_command_ex(LCD_REMOTE_CNTL_SELECT_VOLTAGE, val); | ||
219 | } | 231 | } |
220 | 232 | ||
221 | void lcd_remote_set_invert_display(bool yesno) | 233 | void lcd_remote_set_invert_display(bool yesno) |
222 | { | 234 | { |
223 | lcd_remote_write_command(LCD_REMOTE_CNTL_REVERSE_ON_OFF | yesno); | 235 | cached_invert = yesno; |
236 | if (remote_initialized) | ||
237 | lcd_remote_write_command(LCD_REMOTE_CNTL_REVERSE_ON_OFF | yesno); | ||
224 | } | 238 | } |
225 | 239 | ||
226 | int lcd_remote_default_contrast(void) | 240 | int lcd_remote_default_contrast(void) |
@@ -377,42 +391,13 @@ void lcd_remote_clear_display(void) | |||
377 | } | 391 | } |
378 | 392 | ||
379 | #ifndef SIMULATOR | 393 | #ifndef SIMULATOR |
380 | /* | ||
381 | * Update the display. | ||
382 | * This must be called after all other LCD functions that change the display. | ||
383 | */ | ||
384 | void lcd_remote_update (void) __attribute__ ((section (".icode"))); | ||
385 | void lcd_remote_update (void) | ||
386 | { | ||
387 | int y; | ||
388 | 394 | ||
389 | /* Copy display bitmap to hardware */ | 395 | static void remote_lcd_init(void) |
390 | for (y = 0; y < LCD_REMOTE_HEIGHT / 8; y++) | ||
391 | { | ||
392 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); | ||
393 | lcd_remote_write_command_ex(0x10, 0x04); | ||
394 | lcd_remote_write_data(lcd_remote_framebuffer[y], LCD_REMOTE_WIDTH); | ||
395 | } | ||
396 | } | ||
397 | |||
398 | void lcd_remote_init(void) | ||
399 | { | 396 | { |
400 | GPIO_FUNCTION |= 0x10010800; /* GPIO11: Backlight | ||
401 | GPIO16: RS | ||
402 | GPIO28: CLK */ | ||
403 | |||
404 | GPIO1_FUNCTION |= 0x00040004; /* GPIO34: CS | ||
405 | GPIO50: Data */ | ||
406 | GPIO_ENABLE |= 0x10010800; | ||
407 | GPIO1_ENABLE |= 0x00040004; | ||
408 | |||
409 | CLK_LO; | ||
410 | CS_HI; | ||
411 | |||
412 | lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_REVERSE); | 397 | lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_REVERSE); |
413 | lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_REVERSE); | 398 | lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_REVERSE); |
414 | lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0); | 399 | lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0); |
415 | 400 | ||
416 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x5); | 401 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x5); |
417 | sleep(1); | 402 | sleep(1); |
418 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x6); | 403 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x6); |
@@ -426,18 +411,91 @@ void lcd_remote_init(void) | |||
426 | lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line | 411 | lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line |
427 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | 0x0); // page address | 412 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | 0x0); // page address |
428 | lcd_remote_write_command_ex(0x10, 0x00); // Column MSB + LSB | 413 | lcd_remote_write_command_ex(0x10, 0x00); // Column MSB + LSB |
429 | 414 | ||
430 | lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | 1); | 415 | lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | 1); |
431 | 416 | ||
432 | lcd_remote_clear_display(); | 417 | remote_initialized = true; |
433 | lcd_remote_update(); | 418 | |
419 | lcd_remote_set_contrast(cached_contrast); | ||
420 | lcd_remote_set_invert_display(cached_invert); | ||
421 | lcd_remote_roll(cached_roll); | ||
422 | } | ||
423 | |||
424 | static void remote_tick(void) | ||
425 | { | ||
426 | bool current_status; | ||
427 | |||
428 | current_status = ((GPIO_READ & 0x40000000) == 0); | ||
429 | /* Only report when the status has changed */ | ||
430 | if (current_status != last_remote_status) | ||
431 | { | ||
432 | last_remote_status = current_status; | ||
433 | countdown = current_status ? HZ : 1; | ||
434 | } | ||
435 | else | ||
436 | { | ||
437 | /* Count down until it gets negative */ | ||
438 | if (countdown >= 0) | ||
439 | countdown--; | ||
440 | |||
441 | if (countdown == 0) | ||
442 | { | ||
443 | if (current_status) | ||
444 | { | ||
445 | init_remote = true; | ||
446 | /* request init in scroll_thread */ | ||
447 | } | ||
448 | else | ||
449 | { | ||
450 | CLK_LO; | ||
451 | CS_HI; | ||
452 | remote_initialized = false; | ||
453 | } | ||
454 | } | ||
455 | } | ||
456 | } | ||
457 | |||
458 | void lcd_remote_init(void) | ||
459 | { | ||
460 | GPIO_FUNCTION |= 0x10010800; /* GPIO11: Backlight | ||
461 | GPIO16: RS | ||
462 | GPIO28: CLK */ | ||
434 | 463 | ||
464 | GPIO1_FUNCTION |= 0x00040004; /* GPIO34: CS | ||
465 | GPIO50: Data */ | ||
466 | GPIO_ENABLE |= 0x10010800; | ||
467 | GPIO1_ENABLE |= 0x00040004; | ||
468 | |||
469 | lcd_remote_clear_display(); | ||
470 | |||
471 | tick_add_task(remote_tick); | ||
435 | create_thread(scroll_thread, scroll_stack, | 472 | create_thread(scroll_thread, scroll_stack, |
436 | sizeof(scroll_stack), scroll_name); | 473 | sizeof(scroll_stack), scroll_name); |
437 | } | 474 | } |
438 | 475 | ||
439 | 476 | ||
440 | /* | 477 | /* |
478 | * Update the display. | ||
479 | * This must be called after all other LCD functions that change the display. | ||
480 | */ | ||
481 | void lcd_remote_update (void) __attribute__ ((section (".icode"))); | ||
482 | void lcd_remote_update (void) | ||
483 | { | ||
484 | int y; | ||
485 | |||
486 | if (!remote_initialized) | ||
487 | return; | ||
488 | |||
489 | /* Copy display bitmap to hardware */ | ||
490 | for (y = 0; y < LCD_REMOTE_HEIGHT / 8; y++) | ||
491 | { | ||
492 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); | ||
493 | lcd_remote_write_command_ex(0x10, 0x04); | ||
494 | lcd_remote_write_data(lcd_remote_framebuffer[y], LCD_REMOTE_WIDTH); | ||
495 | } | ||
496 | } | ||
497 | |||
498 | /* | ||
441 | * Update a fraction of the display. | 499 | * Update a fraction of the display. |
442 | */ | 500 | */ |
443 | void lcd_remote_update_rect (int, int, int, int) __attribute__ ((section (".icode"))); | 501 | void lcd_remote_update_rect (int, int, int, int) __attribute__ ((section (".icode"))); |
@@ -445,6 +503,9 @@ void lcd_remote_update_rect (int x_start, int y, | |||
445 | int width, int height) | 503 | int width, int height) |
446 | { | 504 | { |
447 | int ymax; | 505 | int ymax; |
506 | |||
507 | if (!remote_initialized) | ||
508 | return; | ||
448 | 509 | ||
449 | /* The Y coordinates have to work on even 8 pixel rows */ | 510 | /* The Y coordinates have to work on even 8 pixel rows */ |
450 | ymax = (y + height-1)/8; | 511 | ymax = (y + height-1)/8; |
@@ -478,13 +539,18 @@ void lcd_remote_update_rect (int x_start, int y, | |||
478 | void lcd_remote_roll(int lines) | 539 | void lcd_remote_roll(int lines) |
479 | { | 540 | { |
480 | char data[2]; | 541 | char data[2]; |
542 | |||
543 | cached_roll = lines; | ||
481 | 544 | ||
482 | lines &= LCD_REMOTE_HEIGHT-1; | 545 | if (remote_initialized) |
483 | data[0] = lines & 0xff; | 546 | { |
484 | data[1] = lines >> 8; | 547 | lines &= LCD_REMOTE_HEIGHT-1; |
548 | data[0] = lines & 0xff; | ||
549 | data[1] = lines >> 8; | ||
485 | 550 | ||
486 | lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line | 551 | lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line |
487 | lcd_remote_write_data(data, 2); | 552 | lcd_remote_write_data(data, 2); |
553 | } | ||
488 | } | 554 | } |
489 | 555 | ||
490 | #endif | 556 | #endif |
@@ -925,6 +991,14 @@ static void scroll_thread(void) | |||
925 | scrolling_lines = 0; | 991 | scrolling_lines = 0; |
926 | 992 | ||
927 | while ( 1 ) { | 993 | while ( 1 ) { |
994 | |||
995 | if (init_remote) /* request to initialize the remote lcd */ | ||
996 | { | ||
997 | init_remote = false; /* clear request */ | ||
998 | remote_lcd_init(); | ||
999 | lcd_remote_update(); | ||
1000 | } | ||
1001 | |||
928 | for ( index = 0; index < SCROLLABLE_LINES; index++ ) { | 1002 | for ( index = 0; index < SCROLLABLE_LINES; index++ ) { |
929 | /* really scroll? */ | 1003 | /* really scroll? */ |
930 | if ( !(scrolling_lines&(1<<index)) ) | 1004 | if ( !(scrolling_lines&(1<<index)) ) |