summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/lcd-16bit.c213
-rw-r--r--firmware/drivers/lcd-1bit-vert.c177
-rw-r--r--firmware/drivers/lcd-2bit-horz.c176
-rw-r--r--firmware/drivers/lcd-2bit-vert.c176
-rw-r--r--firmware/drivers/lcd-charcell.c184
-rw-r--r--firmware/drivers/lcd-remote-1bit-v.c216
-rw-r--r--firmware/drivers/lcd-remote-2bit-vi.c219
7 files changed, 414 insertions, 947 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index 96711248ff..bd5d09368c 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -33,8 +33,7 @@
33#include "font.h" 33#include "font.h"
34#include "rbunicode.h" 34#include "rbunicode.h"
35#include "bidi.h" 35#include "bidi.h"
36 36#include "scroll_engine.h"
37#define SCROLLABLE_LINES ((LCD_HEIGHT+4)/5 < 32 ? (LCD_HEIGHT+4)/5 : 32)
38 37
39enum fill_opt { 38enum fill_opt {
40 OPT_NONE = 0, 39 OPT_NONE = 0,
@@ -62,23 +61,6 @@ static int xmargin = 0;
62static int ymargin = 0; 61static int ymargin = 0;
63static int curfont = FONT_SYSFIXED; 62static int curfont = FONT_SYSFIXED;
64 63
65/* scrolling */
66static volatile int scrolling_lines = 0; /* Bitpattern of which lines are scrolling */
67static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)];
68static const char scroll_name[] = "scroll";
69static void scroll_thread(void);
70static int scroll_ticks = 12; /* # of ticks between updates*/
71static int scroll_delay = HZ/2; /* ticks delay before start */
72static int scroll_step = 6; /* pixels per scroll step */
73static int bidir_limit = 50; /* percent */
74static struct scrollinfo scroll[SCROLLABLE_LINES];
75
76static const char scroll_tick_table[16] = {
77 /* Hz values:
78 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
79 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
80};
81
82/* LCD init */ 64/* LCD init */
83void lcd_init(void) 65void lcd_init(void)
84{ 66{
@@ -86,12 +68,7 @@ void lcd_init(void)
86 68
87 /* Call device specific init */ 69 /* Call device specific init */
88 lcd_init_device(); 70 lcd_init_device();
89 71 scroll_init();
90
91 create_thread(scroll_thread, scroll_stack,
92 sizeof(scroll_stack), scroll_name
93 IF_PRIO(, PRIORITY_USER_INTERFACE)
94 IF_COP(, CPU, false));
95} 72}
96 73
97/*** parameter handling ***/ 74/*** parameter handling ***/
@@ -243,7 +220,8 @@ void lcd_clear_display(void)
243 else 220 else
244 memcpy(dst, lcd_backdrop, sizeof(lcd_framebuffer)); 221 memcpy(dst, lcd_backdrop, sizeof(lcd_framebuffer));
245 } 222 }
246 scrolling_lines = 0; 223
224 lcd_scroll_info.lines = 0;
247} 225}
248 226
249/* Set a single pixel */ 227/* Set a single pixel */
@@ -819,7 +797,7 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str, int style,
819 int oldbgcolor = bg_pattern; 797 int oldbgcolor = bg_pattern;
820 798
821 /* make sure scrolling is turned off on the line we are updating */ 799 /* make sure scrolling is turned off on the line we are updating */
822 scrolling_lines &= ~(1 << y); 800 lcd_scroll_info.lines &= ~(1 << y);
823 801
824 if(!str || !str[0]) 802 if(!str || !str[0])
825 return; 803 return;
@@ -845,46 +823,6 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str, int style,
845} 823}
846 824
847/*** scrolling ***/ 825/*** scrolling ***/
848
849/* Reverse the invert setting of the scrolling line (if any) at given char
850 position. Setting will go into affect next time line scrolls. */
851void lcd_invertscroll(int x, int y)
852{
853 struct scrollinfo* s;
854
855 (void)x;
856
857 if(y>=SCROLLABLE_LINES) return;
858
859 s = &scroll[y];
860 s->invert = !s->invert;
861}
862
863void lcd_stop_scroll(void)
864{
865 scrolling_lines=0;
866}
867
868void lcd_scroll_speed(int speed)
869{
870 scroll_ticks = scroll_tick_table[speed];
871}
872
873void lcd_scroll_step(int step)
874{
875 scroll_step = step;
876}
877
878void lcd_scroll_delay(int ms)
879{
880 scroll_delay = ms / (HZ / 10);
881}
882
883void lcd_bidir_scroll(int percent)
884{
885 bidir_limit = percent;
886}
887
888void lcd_puts_scroll(int x, int y, const unsigned char *string) 826void lcd_puts_scroll(int x, int y, const unsigned char *string)
889{ 827{
890 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); 828 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT);
@@ -906,11 +844,11 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
906 struct scrollinfo* s; 844 struct scrollinfo* s;
907 int w, h; 845 int w, h;
908 846
909 if(y>=SCROLLABLE_LINES) return; 847 if(y>=LCD_SCROLLABLE_LINES) return;
910 848
911 s = &scroll[y]; 849 s = &lcd_scroll_info.scroll[y];
912 850
913 s->start_tick = current_tick + scroll_delay; 851 s->start_tick = current_tick + lcd_scroll_info.delay;
914 s->invert = false; 852 s->invert = false;
915 if (style & STYLE_INVERT) { 853 if (style & STYLE_INVERT) {
916 s->invert = true; 854 s->invert = true;
@@ -931,9 +869,9 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
931 869
932 /* scroll bidirectional or forward only depending on the string 870 /* scroll bidirectional or forward only depending on the string
933 width */ 871 width */
934 if ( bidir_limit ) { 872 if ( lcd_scroll_info.bidir_limit ) {
935 s->bidir = s->width < (LCD_WIDTH - xmargin) * 873 s->bidir = s->width < (LCD_WIDTH - xmargin) *
936 (100 + bidir_limit) / 100; 874 (100 + lcd_scroll_info.bidir_limit) / 100;
937 } 875 }
938 else 876 else
939 s->bidir = false; 877 s->bidir = false;
@@ -951,95 +889,84 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
951 s->offset = offset; 889 s->offset = offset;
952 s->startx = xmargin + x * s->width / s->len; 890 s->startx = xmargin + x * s->width / s->len;
953 s->backward = false; 891 s->backward = false;
954 s->line_colour = (style&STYLE_COLORED)? 892 s->line_color = (style&STYLE_COLORED)?
955 (style&STYLE_COLOR_MASK): -1; 893 (style&STYLE_COLOR_MASK): -1;
956 scrolling_lines |= (1<<y); 894 lcd_scroll_info.lines |= (1<<y);
957 } 895 }
958 else 896 else
959 /* force a bit switch-off since it doesn't scroll */ 897 /* force a bit switch-off since it doesn't scroll */
960 scrolling_lines &= ~(1<<y); 898 lcd_scroll_info.lines &= ~(1<<y);
961} 899}
962 900
963static void scroll_thread(void) 901void lcd_scroll_fn(void)
964{ 902{
965 struct font* pf; 903 struct font* pf;
966 struct scrollinfo* s; 904 struct scrollinfo* s;
967 int index; 905 int index;
968 int xpos, ypos; 906 int xpos, ypos;
969 int lastmode; 907 int lastmode;
970 unsigned old_bgcolour, old_fgcolour; 908 unsigned old_fgcolor = fg_pattern;
909 unsigned old_bgcolor = bg_pattern;
971 910
972 /* initialize scroll struct array */ 911 for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) {
973 scrolling_lines = 0; 912 /* really scroll? */
913 if ((lcd_scroll_info.lines & (1 << index)) == 0)
914 continue;
974 915
975 while ( 1 ) { 916 s = &lcd_scroll_info.scroll[index];
976 if(!lcd_enabled()) { 917
977 sleep(scroll_ticks); 918 /* check pause */
919 if (TIME_BEFORE(current_tick, s->start_tick))
978 continue; 920 continue;
979 } 921
980 old_fgcolour = lcd_get_foreground(); 922 if (s->line_color >= 0) {
981 old_bgcolour = lcd_get_background(); 923 if (s->invert) {
982 for ( index = 0; index < SCROLLABLE_LINES; index++ ) { 924 fg_pattern = old_fgcolor;
983 /* really scroll? */ 925 bg_pattern = s->line_color;
984 if ( !(scrolling_lines&(1<<index)) )
985 continue;
986
987 s = &scroll[index];
988 /* check pause */
989 if (TIME_BEFORE(current_tick, s->start_tick))
990 continue;
991 if (s->line_colour >= 0)
992 {
993 if (s->invert)
994 {
995 lcd_set_foreground(old_fgcolour);
996 lcd_set_background(s->line_colour);
997 }
998 else
999 {
1000 lcd_set_foreground(s->line_colour);
1001 lcd_set_background(old_bgcolour);
1002 }
1003 }
1004
1005 if (s->backward)
1006 s->offset -= scroll_step;
1007 else
1008 s->offset += scroll_step;
1009
1010 pf = font_get(curfont);
1011 xpos = s->startx;
1012 ypos = ymargin + index * pf->height;
1013
1014 if (s->bidir) { /* scroll bidirectional */
1015 if (s->offset <= 0) {
1016 /* at beginning of line */
1017 s->offset = 0;
1018 s->backward = false;
1019 s->start_tick = current_tick + scroll_delay * 2;
1020 }
1021 if (s->offset >= s->width - (LCD_WIDTH - xpos)) {
1022 /* at end of line */
1023 s->offset = s->width - (LCD_WIDTH - xpos);
1024 s->backward = true;
1025 s->start_tick = current_tick + scroll_delay * 2;
1026 }
1027 } 926 }
1028 else { 927 else {
1029 /* scroll forward the whole time */ 928 fg_pattern = s->line_color;
1030 if (s->offset >= s->width) 929 bg_pattern = old_bgcolor;
1031 s->offset %= s->width;
1032 } 930 }
931 }
1033 932
1034 lastmode = drawmode; 933 if (s->backward)
1035 drawmode = s->invert ? 934 s->offset -= lcd_scroll_info.step;
1036 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 935 else
1037 lcd_putsxyofs(xpos, ypos, s->offset, s->line); 936 s->offset += lcd_scroll_info.step;
1038 drawmode = lastmode; 937
1039 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); 938 pf = font_get(curfont);
939 xpos = s->startx;
940 ypos = ymargin + index * pf->height;
941
942 if (s->bidir) { /* scroll bidirectional */
943 if (s->offset <= 0) {
944 /* at beginning of line */
945 s->offset = 0;
946 s->backward = false;
947 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
948 }
949 if (s->offset >= s->width - (LCD_WIDTH - xpos)) {
950 /* at end of line */
951 s->offset = s->width - (LCD_WIDTH - xpos);
952 s->backward = true;
953 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
954 }
955 }
956 else {
957 /* scroll forward the whole time */
958 if (s->offset >= s->width)
959 s->offset %= s->width;
1040 } 960 }
1041 lcd_set_foreground(old_fgcolour); 961
1042 lcd_set_background(old_bgcolour); 962 lastmode = drawmode;
1043 sleep(scroll_ticks); 963 drawmode = s->invert ?
964 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
965 lcd_putsxyofs(xpos, ypos, s->offset, s->line);
966 drawmode = lastmode;
967 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
1044 } 968 }
969
970 fg_pattern = old_fgcolor;
971 bg_pattern = old_bgcolor;
1045} 972}
diff --git a/firmware/drivers/lcd-1bit-vert.c b/firmware/drivers/lcd-1bit-vert.c
index b54238d085..ac50eff95c 100644
--- a/firmware/drivers/lcd-1bit-vert.c
+++ b/firmware/drivers/lcd-1bit-vert.c
@@ -29,10 +29,7 @@
29#include "font.h" 29#include "font.h"
30#include "rbunicode.h" 30#include "rbunicode.h"
31#include "bidi.h" 31#include "bidi.h"
32 32#include "scroll_engine.h"
33/*** definitions ***/
34
35#define SCROLLABLE_LINES ((LCD_HEIGHT+4)/5 < 32 ? (LCD_HEIGHT+4)/5 : 32)
36 33
37/*** globals ***/ 34/*** globals ***/
38 35
@@ -43,32 +40,13 @@ static int xmargin = 0;
43static int ymargin = 0; 40static int ymargin = 0;
44static int curfont = FONT_SYSFIXED; 41static int curfont = FONT_SYSFIXED;
45 42
46/* scrolling */
47static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */
48static void scroll_thread(void);
49static char scroll_stack[DEFAULT_STACK_SIZE];
50static const char scroll_name[] = "scroll";
51static int scroll_ticks = 12; /* # of ticks between updates*/
52static int scroll_delay = HZ/2; /* ticks delay before start */
53static int scroll_step = 6; /* pixels per scroll step */
54static int bidir_limit = 50; /* percent */
55static struct scrollinfo scroll[SCROLLABLE_LINES];
56
57static const char scroll_tick_table[16] = {
58 /* Hz values:
59 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
60 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
61};
62
63/* LCD init */ 43/* LCD init */
64void lcd_init(void) 44void lcd_init(void)
65{ 45{
66 lcd_clear_display(); 46 lcd_clear_display();
67 /* Call device specific init */ 47 /* Call device specific init */
68 lcd_init_device(); 48 lcd_init_device();
69 create_thread(scroll_thread, scroll_stack, 49 scroll_init();
70 sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
71 IF_COP(, CPU, false));
72} 50}
73 51
74/*** parameter handling ***/ 52/*** parameter handling ***/
@@ -104,6 +82,11 @@ void lcd_setfont(int newfont)
104 curfont = newfont; 82 curfont = newfont;
105} 83}
106 84
85int lcd_getfont(void)
86{
87 return curfont;
88}
89
107int lcd_getstringsize(const unsigned char *str, int *w, int *h) 90int lcd_getstringsize(const unsigned char *str, int *w, int *h)
108{ 91{
109 return font_getstringsize(str, w, h, curfont); 92 return font_getstringsize(str, w, h, curfont);
@@ -212,7 +195,7 @@ void lcd_clear_display(void)
212 unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; 195 unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0;
213 196
214 memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); 197 memset(lcd_framebuffer, bits, sizeof lcd_framebuffer);
215 scrolling_lines = 0; 198 lcd_scroll_info.lines = 0;
216} 199}
217 200
218/* Set a single pixel */ 201/* Set a single pixel */
@@ -664,7 +647,7 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str,
664 int lastmode = drawmode; 647 int lastmode = drawmode;
665 648
666 /* make sure scrolling is turned off on the line we are updating */ 649 /* make sure scrolling is turned off on the line we are updating */
667 scrolling_lines &= ~(1 << y); 650 lcd_scroll_info.lines &= ~(1 << y);
668 651
669 if(!str || !str[0]) 652 if(!str || !str[0])
670 return; 653 return;
@@ -682,46 +665,6 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str,
682} 665}
683 666
684/*** scrolling ***/ 667/*** scrolling ***/
685
686/* Reverse the invert setting of the scrolling line (if any) at given char
687 position. Setting will go into affect next time line scrolls. */
688void lcd_invertscroll(int x, int y)
689{
690 struct scrollinfo* s;
691
692 (void)x;
693
694 if(y>=SCROLLABLE_LINES) return;
695
696 s = &scroll[y];
697 s->invert = !s->invert;
698}
699
700void lcd_stop_scroll(void)
701{
702 scrolling_lines=0;
703}
704
705void lcd_scroll_speed(int speed)
706{
707 scroll_ticks = scroll_tick_table[speed];
708}
709
710void lcd_scroll_step(int step)
711{
712 scroll_step = step;
713}
714
715void lcd_scroll_delay(int ms)
716{
717 scroll_delay = ms / (HZ / 10);
718}
719
720void lcd_bidir_scroll(int percent)
721{
722 bidir_limit = percent;
723}
724
725void lcd_puts_scroll(int x, int y, const unsigned char *string) 668void lcd_puts_scroll(int x, int y, const unsigned char *string)
726{ 669{
727 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); 670 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT);
@@ -744,11 +687,11 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
744 struct scrollinfo* s; 687 struct scrollinfo* s;
745 int w, h; 688 int w, h;
746 689
747 if(y>=SCROLLABLE_LINES) return; 690 if(y>=LCD_SCROLLABLE_LINES) return;
748 691
749 s = &scroll[y]; 692 s = &lcd_scroll_info.scroll[y];
750 693
751 s->start_tick = current_tick + scroll_delay; 694 s->start_tick = current_tick + lcd_scroll_info.delay;
752 s->invert = false; 695 s->invert = false;
753 if (style & STYLE_INVERT) { 696 if (style & STYLE_INVERT) {
754 s->invert = true; 697 s->invert = true;
@@ -771,9 +714,9 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
771 714
772 /* scroll bidirectional or forward only depending on the string 715 /* scroll bidirectional or forward only depending on the string
773 width */ 716 width */
774 if ( bidir_limit ) { 717 if ( lcd_scroll_info.bidir_limit ) {
775 s->bidir = s->width < (LCD_WIDTH - xmargin) * 718 s->bidir = s->width < (LCD_WIDTH - xmargin) *
776 (100 + bidir_limit) / 100; 719 (100 + lcd_scroll_info.bidir_limit) / 100;
777 } 720 }
778 else 721 else
779 s->bidir = false; 722 s->bidir = false;
@@ -791,14 +734,14 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
791 s->offset = offset; 734 s->offset = offset;
792 s->startx = xmargin + x * s->width / s->len;; 735 s->startx = xmargin + x * s->width / s->len;;
793 s->backward = false; 736 s->backward = false;
794 scrolling_lines |= (1<<y); 737 lcd_scroll_info.lines |= (1<<y);
795 } 738 }
796 else 739 else
797 /* force a bit switch-off since it doesn't scroll */ 740 /* force a bit switch-off since it doesn't scroll */
798 scrolling_lines &= ~(1<<y); 741 lcd_scroll_info.lines &= ~(1<<y);
799} 742}
800 743
801static void scroll_thread(void) 744void lcd_scroll_fn(void)
802{ 745{
803 struct font* pf; 746 struct font* pf;
804 struct scrollinfo* s; 747 struct scrollinfo* s;
@@ -806,59 +749,51 @@ static void scroll_thread(void)
806 int xpos, ypos; 749 int xpos, ypos;
807 int lastmode; 750 int lastmode;
808 751
809 /* initialize scroll struct array */ 752 for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) {
810 scrolling_lines = 0; 753 /* really scroll? */
811 754 if ((lcd_scroll_info.lines & (1 << index)) == 0)
812 while ( 1 ) { 755 continue;
813 for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
814 /* really scroll? */
815 if ( !(scrolling_lines&(1<<index)) )
816 continue;
817 756
818 s = &scroll[index]; 757 s = &lcd_scroll_info.scroll[index];
819 758
820 /* check pause */ 759 /* check pause */
821 if (TIME_BEFORE(current_tick, s->start_tick)) 760 if (TIME_BEFORE(current_tick, s->start_tick))
822 continue; 761 continue;
823 762
824 if (s->backward) 763 if (s->backward)
825 s->offset -= scroll_step; 764 s->offset -= lcd_scroll_info.step;
826 else 765 else
827 s->offset += scroll_step; 766 s->offset += lcd_scroll_info.step;
828 767
829 pf = font_get(curfont); 768 pf = font_get(curfont);
830 xpos = s->startx; 769 xpos = s->startx;
831 ypos = ymargin + index * pf->height; 770 ypos = ymargin + index * pf->height;
832 771
833 if (s->bidir) { /* scroll bidirectional */ 772 if (s->bidir) { /* scroll bidirectional */
834 if (s->offset <= 0) { 773 if (s->offset <= 0) {
835 /* at beginning of line */ 774 /* at beginning of line */
836 s->offset = 0; 775 s->offset = 0;
837 s->backward = false; 776 s->backward = false;
838 s->start_tick = current_tick + scroll_delay * 2; 777 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
839 }
840 if (s->offset >= s->width - (LCD_WIDTH - xpos)) {
841 /* at end of line */
842 s->offset = s->width - (LCD_WIDTH - xpos);
843 s->backward = true;
844 s->start_tick = current_tick + scroll_delay * 2;
845 }
846 } 778 }
847 else { 779 if (s->offset >= s->width - (LCD_WIDTH - xpos)) {
848 /* scroll forward the whole time */ 780 /* at end of line */
849 if (s->offset >= s->width) 781 s->offset = s->width - (LCD_WIDTH - xpos);
850 s->offset %= s->width; 782 s->backward = true;
783 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
851 } 784 }
852 785 }
853 lastmode = drawmode; 786 else {
854 drawmode = s->invert ? 787 /* scroll forward the whole time */
855 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 788 if (s->offset >= s->width)
856 lcd_putsxyofs(xpos, ypos, s->offset, s->line); 789 s->offset %= s->width;
857 drawmode = lastmode;
858 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
859 } 790 }
860 791
861 sleep(scroll_ticks); 792 lastmode = drawmode;
793 drawmode = s->invert ?
794 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
795 lcd_putsxyofs(xpos, ypos, s->offset, s->line);
796 drawmode = lastmode;
797 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
862 } 798 }
863} 799}
864
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c
index d3d086a9d2..48fd22f703 100644
--- a/firmware/drivers/lcd-2bit-horz.c
+++ b/firmware/drivers/lcd-2bit-horz.c
@@ -33,8 +33,7 @@
33#include "font.h" 33#include "font.h"
34#include "rbunicode.h" 34#include "rbunicode.h"
35#include "bidi.h" 35#include "bidi.h"
36 36#include "scroll_engine.h"
37#define SCROLLABLE_LINES (((LCD_HEIGHT+4)/5 < 32) ? (LCD_HEIGHT+4)/5 : 32)
38 37
39/*** globals ***/ 38/*** globals ***/
40 39
@@ -54,33 +53,13 @@ static int xmargin = 0;
54static int ymargin = 0; 53static int ymargin = 0;
55static int curfont = FONT_SYSFIXED; 54static int curfont = FONT_SYSFIXED;
56 55
57/* scrolling */
58static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */
59static void scroll_thread(void);
60static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)];
61static const char scroll_name[] = "scroll";
62static int scroll_ticks = 12; /* # of ticks between updates*/
63static int scroll_delay = HZ/2; /* ticks delay before start */
64static int scroll_step = 6; /* pixels per scroll step */
65static int bidir_limit = 50; /* percent */
66static struct scrollinfo scroll[SCROLLABLE_LINES];
67
68static const char scroll_tick_table[16] = {
69 /* Hz values:
70 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
71 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
72};
73
74
75/* LCD init */ 56/* LCD init */
76void lcd_init(void) 57void lcd_init(void)
77{ 58{
78 lcd_clear_display(); 59 lcd_clear_display();
79 /* Call device specific init */ 60 /* Call device specific init */
80 lcd_init_device(); 61 lcd_init_device();
81 create_thread(scroll_thread, scroll_stack, 62 scroll_init();
82 sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
83 IF_COP(, CPU, false));
84} 63}
85 64
86/*** parameter handling ***/ 65/*** parameter handling ***/
@@ -143,6 +122,11 @@ void lcd_setfont(int newfont)
143 curfont = newfont; 122 curfont = newfont;
144} 123}
145 124
125int lcd_getfont(void)
126{
127 return curfont;
128}
129
146int lcd_getstringsize(const unsigned char *str, int *w, int *h) 130int lcd_getstringsize(const unsigned char *str, int *w, int *h)
147{ 131{
148 return font_getstringsize(str, w, h, curfont); 132 return font_getstringsize(str, w, h, curfont);
@@ -377,7 +361,8 @@ void lcd_clear_display(void)
377 else 361 else
378 memset(lcd_framebuffer, bg_pattern, sizeof lcd_framebuffer); 362 memset(lcd_framebuffer, bg_pattern, sizeof lcd_framebuffer);
379 } 363 }
380 scrolling_lines = 0; 364
365 lcd_scroll_info.lines = 0;
381} 366}
382 367
383/* Set a single pixel */ 368/* Set a single pixel */
@@ -862,7 +847,7 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str,
862 int lastmode = drawmode; 847 int lastmode = drawmode;
863 848
864 /* make sure scrolling is turned off on the line we are updating */ 849 /* make sure scrolling is turned off on the line we are updating */
865 scrolling_lines &= ~(1 << y); 850 lcd_scroll_info.lines &= ~(1 << y);
866 851
867 if(!str || !str[0]) 852 if(!str || !str[0])
868 return; 853 return;
@@ -880,46 +865,6 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str,
880} 865}
881 866
882/*** scrolling ***/ 867/*** scrolling ***/
883
884/* Reverse the invert setting of the scrolling line (if any) at given char
885 position. Setting will go into affect next time line scrolls. */
886void lcd_invertscroll(int x, int y)
887{
888 struct scrollinfo* s;
889
890 (void)x;
891
892 if(y>=SCROLLABLE_LINES) return;
893
894 s = &scroll[y];
895 s->invert = !s->invert;
896}
897
898void lcd_stop_scroll(void)
899{
900 scrolling_lines=0;
901}
902
903void lcd_scroll_speed(int speed)
904{
905 scroll_ticks = scroll_tick_table[speed];
906}
907
908void lcd_scroll_step(int step)
909{
910 scroll_step = step;
911}
912
913void lcd_scroll_delay(int ms)
914{
915 scroll_delay = ms / (HZ / 10);
916}
917
918void lcd_bidir_scroll(int percent)
919{
920 bidir_limit = percent;
921}
922
923void lcd_puts_scroll(int x, int y, const unsigned char *string) 868void lcd_puts_scroll(int x, int y, const unsigned char *string)
924{ 869{
925 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); 870 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT);
@@ -941,11 +886,11 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
941 struct scrollinfo* s; 886 struct scrollinfo* s;
942 int w, h; 887 int w, h;
943 888
944 if(y>=SCROLLABLE_LINES) return; 889 if(y>=LCD_SCROLLABLE_LINES) return;
945 890
946 s = &scroll[y]; 891 s = &lcd_scroll_info.scroll[y];
947 892
948 s->start_tick = current_tick + scroll_delay; 893 s->start_tick = current_tick + lcd_scroll_info.delay;
949 s->invert = false; 894 s->invert = false;
950 if (style & STYLE_INVERT) { 895 if (style & STYLE_INVERT) {
951 s->invert = true; 896 s->invert = true;
@@ -968,9 +913,9 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
968 913
969 /* scroll bidirectional or forward only depending on the string 914 /* scroll bidirectional or forward only depending on the string
970 width */ 915 width */
971 if ( bidir_limit ) { 916 if ( lcd_scroll_info.bidir_limit ) {
972 s->bidir = s->width < (LCD_WIDTH - xmargin) * 917 s->bidir = s->width < (LCD_WIDTH - xmargin) *
973 (100 + bidir_limit) / 100; 918 (100 + lcd_scroll_info.bidir_limit) / 100;
974 } 919 }
975 else 920 else
976 s->bidir = false; 921 s->bidir = false;
@@ -988,14 +933,14 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
988 s->offset = offset; 933 s->offset = offset;
989 s->startx = xmargin + x * s->width / s->len;; 934 s->startx = xmargin + x * s->width / s->len;;
990 s->backward = false; 935 s->backward = false;
991 scrolling_lines |= (1<<y); 936 lcd_scroll_info.lines |= (1<<y);
992 } 937 }
993 else 938 else
994 /* force a bit switch-off since it doesn't scroll */ 939 /* force a bit switch-off since it doesn't scroll */
995 scrolling_lines &= ~(1<<y); 940 lcd_scroll_info.lines &= ~(1<<y);
996} 941}
997 942
998static void scroll_thread(void) 943void lcd_scroll_fn(void)
999{ 944{
1000 struct font* pf; 945 struct font* pf;
1001 struct scrollinfo* s; 946 struct scrollinfo* s;
@@ -1003,58 +948,51 @@ static void scroll_thread(void)
1003 int xpos, ypos; 948 int xpos, ypos;
1004 int lastmode; 949 int lastmode;
1005 950
1006 /* initialize scroll struct array */ 951 for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) {
1007 scrolling_lines = 0; 952 /* really scroll? */
1008 953 if ((lcd_scroll_info.lines & (1 << index)) == 0)
1009 while ( 1 ) { 954 continue;
1010 for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
1011 /* really scroll? */
1012 if ( !(scrolling_lines&(1<<index)) )
1013 continue;
1014 955
1015 s = &scroll[index]; 956 s = &lcd_scroll_info.scroll[index];
1016 957
1017 /* check pause */ 958 /* check pause */
1018 if (TIME_BEFORE(current_tick, s->start_tick)) 959 if (TIME_BEFORE(current_tick, s->start_tick))
1019 continue; 960 continue;
1020 961
1021 if (s->backward) 962 if (s->backward)
1022 s->offset -= scroll_step; 963 s->offset -= lcd_scroll_info.step;
1023 else 964 else
1024 s->offset += scroll_step; 965 s->offset += lcd_scroll_info.step;
1025 966
1026 pf = font_get(curfont); 967 pf = font_get(curfont);
1027 xpos = s->startx; 968 xpos = s->startx;
1028 ypos = ymargin + index * pf->height; 969 ypos = ymargin + index * pf->height;
1029 970
1030 if (s->bidir) { /* scroll bidirectional */ 971 if (s->bidir) { /* scroll bidirectional */
1031 if (s->offset <= 0) { 972 if (s->offset <= 0) {
1032 /* at beginning of line */ 973 /* at beginning of line */
1033 s->offset = 0; 974 s->offset = 0;
1034 s->backward = false; 975 s->backward = false;
1035 s->start_tick = current_tick + scroll_delay * 2; 976 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
1036 }
1037 if (s->offset >= s->width - (LCD_WIDTH - xpos)) {
1038 /* at end of line */
1039 s->offset = s->width - (LCD_WIDTH - xpos);
1040 s->backward = true;
1041 s->start_tick = current_tick + scroll_delay * 2;
1042 }
1043 } 977 }
1044 else { 978 if (s->offset >= s->width - (LCD_WIDTH - xpos)) {
1045 /* scroll forward the whole time */ 979 /* at end of line */
1046 if (s->offset >= s->width) 980 s->offset = s->width - (LCD_WIDTH - xpos);
1047 s->offset %= s->width; 981 s->backward = true;
982 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
1048 } 983 }
1049 984 }
1050 lastmode = drawmode; 985 else {
1051 drawmode = s->invert ? 986 /* scroll forward the whole time */
1052 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 987 if (s->offset >= s->width)
1053 lcd_putsxyofs(xpos, ypos, s->offset, s->line); 988 s->offset %= s->width;
1054 drawmode = lastmode;
1055 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
1056 } 989 }
1057 990
1058 sleep(scroll_ticks); 991 lastmode = drawmode;
992 drawmode = s->invert ?
993 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
994 lcd_putsxyofs(xpos, ypos, s->offset, s->line);
995 drawmode = lastmode;
996 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
1059 } 997 }
1060} 998}
diff --git a/firmware/drivers/lcd-2bit-vert.c b/firmware/drivers/lcd-2bit-vert.c
index 37abf0496f..751d2a2ad9 100644
--- a/firmware/drivers/lcd-2bit-vert.c
+++ b/firmware/drivers/lcd-2bit-vert.c
@@ -30,10 +30,7 @@
30#include "font.h" 30#include "font.h"
31#include "rbunicode.h" 31#include "rbunicode.h"
32#include "bidi.h" 32#include "bidi.h"
33 33#include "scroll_engine.h"
34/*** definitions ***/
35
36#define SCROLLABLE_LINES ((LCD_HEIGHT+4)/5 < 32 ? (LCD_HEIGHT+4)/5 : 32)
37 34
38/*** globals ***/ 35/*** globals ***/
39 36
@@ -58,32 +55,13 @@ static int xmargin = 0;
58static int ymargin = 0; 55static int ymargin = 0;
59static int curfont = FONT_SYSFIXED; 56static int curfont = FONT_SYSFIXED;
60 57
61/* scrolling */
62static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */
63static void scroll_thread(void);
64static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)];
65static const char scroll_name[] = "scroll";
66static int scroll_ticks = 12; /* # of ticks between updates*/
67static int scroll_delay = HZ/2; /* ticks delay before start */
68static int scroll_step = 6; /* pixels per scroll step */
69static int bidir_limit = 50; /* percent */
70static struct scrollinfo scroll[SCROLLABLE_LINES];
71
72static const char scroll_tick_table[16] = {
73 /* Hz values:
74 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
75 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
76};
77
78/* LCD init */ 58/* LCD init */
79void lcd_init(void) 59void lcd_init(void)
80{ 60{
81 lcd_clear_display(); 61 lcd_clear_display();
82 /* Call device specific init */ 62 /* Call device specific init */
83 lcd_init_device(); 63 lcd_init_device();
84 create_thread(scroll_thread, scroll_stack, 64 scroll_init();
85 sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
86 IF_COP(, CPU, false));
87} 65}
88 66
89/*** parameter handling ***/ 67/*** parameter handling ***/
@@ -146,6 +124,11 @@ void lcd_setfont(int newfont)
146 curfont = newfont; 124 curfont = newfont;
147} 125}
148 126
127int lcd_getfont(void)
128{
129 return curfont;
130}
131
149int lcd_getstringsize(const unsigned char *str, int *w, int *h) 132int lcd_getstringsize(const unsigned char *str, int *w, int *h)
150{ 133{
151 return font_getstringsize(str, w, h, curfont); 134 return font_getstringsize(str, w, h, curfont);
@@ -380,7 +363,8 @@ void lcd_clear_display(void)
380 else 363 else
381 memset(lcd_framebuffer, bg_pattern, sizeof lcd_framebuffer); 364 memset(lcd_framebuffer, bg_pattern, sizeof lcd_framebuffer);
382 } 365 }
383 scrolling_lines = 0; 366
367 lcd_scroll_info.lines = 0;
384} 368}
385 369
386/* Set a single pixel */ 370/* Set a single pixel */
@@ -998,7 +982,7 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str,
998 int lastmode = drawmode; 982 int lastmode = drawmode;
999 983
1000 /* make sure scrolling is turned off on the line we are updating */ 984 /* make sure scrolling is turned off on the line we are updating */
1001 scrolling_lines &= ~(1 << y); 985 lcd_scroll_info.lines &= ~(1 << y);
1002 986
1003 if(!str || !str[0]) 987 if(!str || !str[0])
1004 return; 988 return;
@@ -1017,45 +1001,6 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str,
1017 1001
1018/*** scrolling ***/ 1002/*** scrolling ***/
1019 1003
1020/* Reverse the invert setting of the scrolling line (if any) at given char
1021 position. Setting will go into affect next time line scrolls. */
1022void lcd_invertscroll(int x, int y)
1023{
1024 struct scrollinfo* s;
1025
1026 (void)x;
1027
1028 if(y>=SCROLLABLE_LINES) return;
1029
1030 s = &scroll[y];
1031 s->invert = !s->invert;
1032}
1033
1034void lcd_stop_scroll(void)
1035{
1036 scrolling_lines=0;
1037}
1038
1039void lcd_scroll_speed(int speed)
1040{
1041 scroll_ticks = scroll_tick_table[speed];
1042}
1043
1044void lcd_scroll_step(int step)
1045{
1046 scroll_step = step;
1047}
1048
1049void lcd_scroll_delay(int ms)
1050{
1051 scroll_delay = ms / (HZ / 10);
1052}
1053
1054void lcd_bidir_scroll(int percent)
1055{
1056 bidir_limit = percent;
1057}
1058
1059void lcd_puts_scroll(int x, int y, const unsigned char *string) 1004void lcd_puts_scroll(int x, int y, const unsigned char *string)
1060{ 1005{
1061 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); 1006 lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT);
@@ -1077,11 +1022,11 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
1077 struct scrollinfo* s; 1022 struct scrollinfo* s;
1078 int w, h; 1023 int w, h;
1079 1024
1080 if(y>=SCROLLABLE_LINES) return; 1025 if(y>=LCD_SCROLLABLE_LINES) return;
1081 1026
1082 s = &scroll[y]; 1027 s = &lcd_scroll_info.scroll[y];
1083 1028
1084 s->start_tick = current_tick + scroll_delay; 1029 s->start_tick = current_tick + lcd_scroll_info.delay;
1085 s->invert = false; 1030 s->invert = false;
1086 if (style & STYLE_INVERT) { 1031 if (style & STYLE_INVERT) {
1087 s->invert = true; 1032 s->invert = true;
@@ -1104,9 +1049,9 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
1104 1049
1105 /* scroll bidirectional or forward only depending on the string 1050 /* scroll bidirectional or forward only depending on the string
1106 width */ 1051 width */
1107 if ( bidir_limit ) { 1052 if ( lcd_scroll_info.bidir_limit ) {
1108 s->bidir = s->width < (LCD_WIDTH - xmargin) * 1053 s->bidir = s->width < (LCD_WIDTH - xmargin) *
1109 (100 + bidir_limit) / 100; 1054 (100 + lcd_scroll_info.bidir_limit) / 100;
1110 } 1055 }
1111 else 1056 else
1112 s->bidir = false; 1057 s->bidir = false;
@@ -1124,14 +1069,14 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string,
1124 s->offset = offset; 1069 s->offset = offset;
1125 s->startx = xmargin + x * s->width / s->len; 1070 s->startx = xmargin + x * s->width / s->len;
1126 s->backward = false; 1071 s->backward = false;
1127 scrolling_lines |= (1<<y); 1072 lcd_scroll_info.lines |= (1<<y);
1128 } 1073 }
1129 else 1074 else
1130 /* force a bit switch-off since it doesn't scroll */ 1075 /* force a bit switch-off since it doesn't scroll */
1131 scrolling_lines &= ~(1<<y); 1076 lcd_scroll_info.lines &= ~(1<<y);
1132} 1077}
1133 1078
1134static void scroll_thread(void) 1079void lcd_scroll_fn(void)
1135{ 1080{
1136 struct font* pf; 1081 struct font* pf;
1137 struct scrollinfo* s; 1082 struct scrollinfo* s;
@@ -1139,58 +1084,51 @@ static void scroll_thread(void)
1139 int xpos, ypos; 1084 int xpos, ypos;
1140 int lastmode; 1085 int lastmode;
1141 1086
1142 /* initialize scroll struct array */ 1087 for ( index = 0; index < LCD_SCROLLABLE_LINES; index++ ) {
1143 scrolling_lines = 0; 1088 /* really scroll? */
1144 1089 if ((lcd_scroll_info.lines & (1 << index)) == 0)
1145 while ( 1 ) { 1090 continue;
1146 for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
1147 /* really scroll? */
1148 if ( !(scrolling_lines&(1<<index)) )
1149 continue;
1150 1091
1151 s = &scroll[index]; 1092 s = &lcd_scroll_info.scroll[index];
1152 1093
1153 /* check pause */ 1094 /* check pause */
1154 if (TIME_BEFORE(current_tick, s->start_tick)) 1095 if (TIME_BEFORE(current_tick, s->start_tick))
1155 continue; 1096 continue;
1156 1097
1157 if (s->backward) 1098 if (s->backward)
1158 s->offset -= scroll_step; 1099 s->offset -= lcd_scroll_info.step;
1159 else 1100 else
1160 s->offset += scroll_step; 1101 s->offset += lcd_scroll_info.step;
1161 1102
1162 pf = font_get(curfont); 1103 pf = font_get(curfont);
1163 xpos = s->startx; 1104 xpos = s->startx;
1164 ypos = ymargin + index * pf->height; 1105 ypos = ymargin + index * pf->height;
1165 1106
1166 if (s->bidir) { /* scroll bidirectional */ 1107 if (s->bidir) { /* scroll bidirectional */
1167 if (s->offset <= 0) { 1108 if (s->offset <= 0) {
1168 /* at beginning of line */ 1109 /* at beginning of line */
1169 s->offset = 0; 1110 s->offset = 0;
1170 s->backward = false; 1111 s->backward = false;
1171 s->start_tick = current_tick + scroll_delay * 2; 1112 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
1172 }
1173 if (s->offset >= s->width - (LCD_WIDTH - xpos)) {
1174 /* at end of line */
1175 s->offset = s->width - (LCD_WIDTH - xpos);
1176 s->backward = true;
1177 s->start_tick = current_tick + scroll_delay * 2;
1178 }
1179 } 1113 }
1180 else { 1114 if (s->offset >= s->width - (LCD_WIDTH - xpos)) {
1181 /* scroll forward the whole time */ 1115 /* at end of line */
1182 if (s->offset >= s->width) 1116 s->offset = s->width - (LCD_WIDTH - xpos);
1183 s->offset %= s->width; 1117 s->backward = true;
1118 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
1184 } 1119 }
1185 1120 }
1186 lastmode = drawmode; 1121 else {
1187 drawmode = s->invert ? 1122 /* scroll forward the whole time */
1188 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 1123 if (s->offset >= s->width)
1189 lcd_putsxyofs(xpos, ypos, s->offset, s->line); 1124 s->offset %= s->width;
1190 drawmode = lastmode;
1191 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
1192 } 1125 }
1193 1126
1194 sleep(scroll_ticks); 1127 lastmode = drawmode;
1128 drawmode = s->invert ?
1129 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
1130 lcd_putsxyofs(xpos, ypos, s->offset, s->line);
1131 drawmode = lastmode;
1132 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
1195 } 1133 }
1196} 1134}
diff --git a/firmware/drivers/lcd-charcell.c b/firmware/drivers/lcd-charcell.c
index efc9aa5b1f..0fd41481c5 100644
--- a/firmware/drivers/lcd-charcell.c
+++ b/firmware/drivers/lcd-charcell.c
@@ -29,10 +29,10 @@
29#include "system.h" 29#include "system.h"
30#include "lcd-charcell.h" 30#include "lcd-charcell.h"
31#include "rbunicode.h" 31#include "rbunicode.h"
32#include "scroll_engine.h"
32 33
33/** definitions **/ 34/** definitions **/
34 35
35#define SCROLLABLE_LINES LCD_HEIGHT
36#define VARIABLE_XCHARS 16 /* number of software user-definable characters */ 36#define VARIABLE_XCHARS 16 /* number of software user-definable characters */
37/* There must be mappings for this many characters in the 0xe000 unicode range 37/* There must be mappings for this many characters in the 0xe000 unicode range
38 * in lcd-charset-<target>.c */ 38 * in lcd-charset-<target>.c */
@@ -55,24 +55,6 @@ static int xspace; /* stores xhcar id of ' ' - often needed */
55static int xmargin = 0; 55static int xmargin = 0;
56static int ymargin = 0; 56static int ymargin = 0;
57 57
58/* scrolling */
59static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */
60static void scroll_thread(void);
61static char scroll_stack[DEFAULT_STACK_SIZE];
62static const char scroll_name[] = "scroll";
63static int scroll_ticks = 12; /* # of ticks between updates */
64static int scroll_delay = HZ/2; /* delay before starting scroll */
65static int bidir_limit = 50; /* percent */
66static int jump_scroll_delay = HZ/4; /* delay between jump scroll jumps */
67static int jump_scroll = 0; /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */
68static struct scrollinfo scroll[SCROLLABLE_LINES];
69
70static const char scroll_tick_table[16] = {
71 /* Hz values:
72 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
73 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
74};
75
76/* LCD init */ 58/* LCD init */
77void lcd_init (void) 59void lcd_init (void)
78{ 60{
@@ -81,11 +63,7 @@ void lcd_init (void)
81 memset(lcd_patterns, 0, sizeof(lcd_patterns)); 63 memset(lcd_patterns, 0, sizeof(lcd_patterns));
82 xspace = find_xchar(' '); 64 xspace = find_xchar(' ');
83 memset(lcd_charbuffer, xchar_info[xspace].hw_char, sizeof(lcd_charbuffer)); 65 memset(lcd_charbuffer, xchar_info[xspace].hw_char, sizeof(lcd_charbuffer));
84 66 scroll_init();
85 create_thread(scroll_thread, scroll_stack,
86 sizeof(scroll_stack), scroll_name
87 IF_PRIO(, PRIORITY_USER_INTERFACE)
88 IF_COP(, CPU, false));
89} 67}
90 68
91/** parameter handling **/ 69/** parameter handling **/
@@ -336,7 +314,7 @@ void lcd_put_cursor(int x, int y, unsigned long cursor_ucs)
336 lcd_cursor.x = x; 314 lcd_cursor.x = x;
337 lcd_cursor.y = y; 315 lcd_cursor.y = y;
338 lcd_cursor.downcount = 0; 316 lcd_cursor.downcount = 0;
339 lcd_cursor.divider = MAX((HZ/2) / scroll_ticks, 1); 317 lcd_cursor.divider = MAX((HZ/2) / lcd_scroll_info.ticks, 1);
340} 318}
341 319
342/* Remove the cursor */ 320/* Remove the cursor */
@@ -398,7 +376,7 @@ void lcd_puts_offset(int x, int y, const unsigned char *str, int offset)
398 return; 376 return;
399 377
400 /* make sure scrolling is turned off on the line we are updating */ 378 /* make sure scrolling is turned off on the line we are updating */
401 scrolling_lines &= ~(1 << y); 379 lcd_scroll_info.lines &= ~(1 << y);
402 380
403 x = lcd_putsxyofs(x, y, offset, str); 381 x = lcd_putsxyofs(x, y, offset, str);
404 while (x < LCD_WIDTH) 382 while (x < LCD_WIDTH)
@@ -406,37 +384,6 @@ void lcd_puts_offset(int x, int y, const unsigned char *str, int offset)
406} 384}
407 385
408/** scrolling **/ 386/** scrolling **/
409
410void lcd_stop_scroll(void)
411{
412 scrolling_lines=0;
413}
414
415void lcd_scroll_speed(int speed)
416{
417 scroll_ticks = scroll_tick_table[speed];
418}
419
420void lcd_scroll_delay(int ms)
421{
422 scroll_delay = ms / (HZ / 10);
423}
424
425void lcd_bidir_scroll(int percent)
426{
427 bidir_limit = percent;
428}
429
430void lcd_jump_scroll(int mode) /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */
431{
432 jump_scroll = mode;
433}
434
435void lcd_jump_scroll_delay(int ms)
436{
437 jump_scroll_delay = ms / (HZ / 10);
438}
439
440void lcd_puts_scroll(int x, int y, const unsigned char *string) 387void lcd_puts_scroll(int x, int y, const unsigned char *string)
441{ 388{
442 lcd_puts_scroll_offset(x, y, string, 0); 389 lcd_puts_scroll_offset(x, y, string, 0);
@@ -448,11 +395,11 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string,
448 struct scrollinfo* s; 395 struct scrollinfo* s;
449 int len; 396 int len;
450 397
451 if(y>=SCROLLABLE_LINES) return; 398 if(y>=LCD_SCROLLABLE_LINES) return;
452 399
453 s = &scroll[y]; 400 s = &lcd_scroll_info.scroll[y];
454 401
455 s->start_tick = current_tick + scroll_delay; 402 s->start_tick = current_tick + lcd_scroll_info.delay;
456 403
457 lcd_puts_offset(x, y, string, offset); 404 lcd_puts_offset(x, y, string, offset);
458 len = utf8length(string); 405 len = utf8length(string);
@@ -469,9 +416,10 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string,
469 s->len = utf8length(s->line); 416 s->len = utf8length(s->line);
470 417
471 /* scroll bidirectional or forward only depending on the string width */ 418 /* scroll bidirectional or forward only depending on the string width */
472 if (bidir_limit) 419 if (lcd_scroll_info.bidir_limit)
473 { 420 {
474 s->bidir = s->len < (LCD_WIDTH - xmargin) * (100 + bidir_limit) / 100; 421 s->bidir = s->len < (LCD_WIDTH - xmargin) *
422 (100 + lcd_scroll_info.bidir_limit) / 100;
475 } 423 }
476 else 424 else
477 s->bidir = false; 425 s->bidir = false;
@@ -489,83 +437,77 @@ void lcd_puts_scroll_offset(int x, int y, const unsigned char *string,
489 s->offset = offset; 437 s->offset = offset;
490 s->startx = xmargin + x; 438 s->startx = xmargin + x;
491 s->backward = false; 439 s->backward = false;
492 scrolling_lines |= (1<<y); 440 lcd_scroll_info.lines |= (1<<y);
493 } 441 }
494 else 442 else
495 /* force a bit switch-off since it doesn't scroll */ 443 /* force a bit switch-off since it doesn't scroll */
496 scrolling_lines &= ~(1<<y); 444 lcd_scroll_info.lines &= ~(1<<y);
497} 445}
498 446
499static void scroll_thread(void) 447void lcd_scroll_fn(void)
500{ 448{
501 struct scrollinfo* s; 449 struct scrollinfo* s;
502 int index; 450 int index;
503 int xpos, ypos; 451 int xpos, ypos;
504 bool update; 452 bool update;
505 453
506 /* initialize scroll struct array */ 454 update = false;
507 scrolling_lines = 0; 455 for (index = 0; index < LCD_SCROLLABLE_LINES; index++)
508
509 while (1)
510 { 456 {
511 update = false; 457 /* really scroll? */
512 for (index = 0; index < SCROLLABLE_LINES; index++) 458 if ((lcd_scroll_info.lines & (1 << index)) == 0)
459 continue;
460
461 s = &lcd_scroll_info.scroll[index];
462
463 /* check pause */
464 if (TIME_BEFORE(current_tick, s->start_tick))
465 continue;
466
467 if (s->backward)
468 s->offset--;
469 else
470 s->offset++;
471
472 xpos = s->startx;
473 ypos = ymargin + index;
474
475 if (s->bidir) /* scroll bidirectional */
513 { 476 {
514 /* really scroll? */ 477 if (s->offset <= 0) {
515 if (!(scrolling_lines&(1<<index))) 478 /* at beginning of line */
516 continue; 479 s->offset = 0;
517 480 s->backward = false;
518 s = &scroll[index]; 481 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
519
520 /* check pause */
521 if (TIME_BEFORE(current_tick, s->start_tick))
522 continue;
523
524 if (s->backward)
525 s->offset--;
526 else
527 s->offset++;
528
529 xpos = s->startx;
530 ypos = ymargin + index;
531
532 if (s->bidir) /* scroll bidirectional */
533 {
534 if (s->offset <= 0)
535 {
536 /* at beginning of line */
537 s->offset = 0;
538 s->backward = false;
539 s->start_tick = current_tick + scroll_delay * 2;
540 }
541 if (s->offset >= s->len - (LCD_WIDTH - xpos))
542 {
543 /* at end of line */
544 s->offset = s->len - (LCD_WIDTH - xpos);
545 s->backward = true;
546 s->start_tick = current_tick + scroll_delay * 2;
547 }
548 } 482 }
549 else /* scroll forward the whole time */ 483 if (s->offset >= s->len - (LCD_WIDTH - xpos)) {
550 { 484 /* at end of line */
551 if (s->offset >= s->len) 485 s->offset = s->len - (LCD_WIDTH - xpos);
552 s->offset -= s->len; 486 s->backward = true;
487 s->start_tick = current_tick + lcd_scroll_info.delay * 2;
553 } 488 }
554 lcd_putsxyofs(xpos, ypos, s->offset, s->line);
555 update = true;
556 } 489 }
557 if (lcd_cursor.enabled) 490 else /* scroll forward the whole time */
558 { 491 {
559 if (--lcd_cursor.downcount <= 0) 492 if (s->offset >= s->len)
560 { 493 s->offset -= s->len;
561 lcd_cursor.downcount = lcd_cursor.divider;
562 lcd_cursor.visible = !lcd_cursor.visible;
563 update = true;
564 }
565 } 494 }
566 if (update)
567 lcd_update();
568 495
569 sleep(scroll_ticks); 496 lcd_putsxyofs(xpos, ypos, s->offset, s->line);
497 update = true;
498 }
499
500 if (lcd_cursor.enabled)
501 {
502 if (--lcd_cursor.downcount <= 0)
503 {
504 lcd_cursor.downcount = lcd_cursor.divider;
505 lcd_cursor.visible = !lcd_cursor.visible;
506 update = true;
507 }
570 } 508 }
509
510 if (update)
511 lcd_update();
571} 512}
513
diff --git a/firmware/drivers/lcd-remote-1bit-v.c b/firmware/drivers/lcd-remote-1bit-v.c
index 6b5b1fb42f..1ddd8e5071 100644
--- a/firmware/drivers/lcd-remote-1bit-v.c
+++ b/firmware/drivers/lcd-remote-1bit-v.c
@@ -31,8 +31,7 @@
31#include "font.h" 31#include "font.h"
32#include "rbunicode.h" 32#include "rbunicode.h"
33#include "bidi.h" 33#include "bidi.h"
34 34#include "scroll_engine.h"
35#define SCROLLABLE_LINES (((LCD_REMOTE_HEIGHT+4)/5 < 32) ? (LCD_REMOTE_HEIGHT+4)/5 : 32)
36 35
37/*** globals ***/ 36/*** globals ***/
38 37
@@ -44,28 +43,6 @@ static int xmargin = 0;
44static int ymargin = 0; 43static int ymargin = 0;
45static int curfont = FONT_SYSFIXED; 44static int curfont = FONT_SYSFIXED;
46 45
47/* scrolling */
48static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */
49static void scroll_thread(void);
50static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)];
51static const char scroll_name[] = "remote_scroll";
52static int scroll_ticks = 12; /* # of ticks between updates*/
53static int scroll_delay = HZ/2; /* ticks delay before start */
54static int scroll_step = 6; /* pixels per scroll step */
55static int bidir_limit = 50; /* percent */
56static struct scrollinfo scroll[SCROLLABLE_LINES];
57
58static const char scroll_tick_table[16] = {
59 /* Hz values:
60 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
61 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
62};
63
64/* remote hotplug */
65#ifndef SIMULATOR
66struct event_queue remote_scroll_queue;
67#endif
68
69/*** parameter handling ***/ 46/*** parameter handling ***/
70 47
71void lcd_remote_set_drawmode(int mode) 48void lcd_remote_set_drawmode(int mode)
@@ -94,12 +71,16 @@ int lcd_remote_getymargin(void)
94 return ymargin; 71 return ymargin;
95} 72}
96 73
97
98void lcd_remote_setfont(int newfont) 74void lcd_remote_setfont(int newfont)
99{ 75{
100 curfont = newfont; 76 curfont = newfont;
101} 77}
102 78
79int lcd_remote_getfont(void)
80{
81 return curfont;
82}
83
103int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) 84int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h)
104{ 85{
105 return font_getstringsize(str, w, h, curfont); 86 return font_getstringsize(str, w, h, curfont);
@@ -208,7 +189,7 @@ void lcd_remote_clear_display(void)
208 unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; 189 unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0;
209 190
210 memset(lcd_remote_framebuffer, bits, sizeof lcd_remote_framebuffer); 191 memset(lcd_remote_framebuffer, bits, sizeof lcd_remote_framebuffer);
211 scrolling_lines = 0; 192 lcd_remote_scroll_info.lines = 0;
212} 193}
213 194
214/* Set a single pixel */ 195/* Set a single pixel */
@@ -599,7 +580,7 @@ void lcd_remote_bitmap(const unsigned char *src, int x, int y, int width,
599} 580}
600 581
601/* put a string at a given pixel position, skipping first ofs pixel columns */ 582/* put a string at a given pixel position, skipping first ofs pixel columns */
602static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) 583void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str)
603{ 584{
604 unsigned short ch; 585 unsigned short ch;
605 unsigned short *ucs; 586 unsigned short *ucs;
@@ -664,7 +645,7 @@ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str,
664 int lastmode = drawmode; 645 int lastmode = drawmode;
665 646
666 /* make sure scrolling is turned off on the line we are updating */ 647 /* make sure scrolling is turned off on the line we are updating */
667 scrolling_lines &= ~(1 << y); 648 lcd_remote_scroll_info.lines &= ~(1 << y);
668 649
669 if(!str || !str[0]) 650 if(!str || !str[0])
670 return; 651 return;
@@ -683,45 +664,6 @@ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str,
683 664
684/*** scrolling ***/ 665/*** scrolling ***/
685 666
686/* Reverse the invert setting of the scrolling line (if any) at given char
687 position. Setting will go into affect next time line scrolls. */
688void lcd_remote_invertscroll(int x, int y)
689{
690 struct scrollinfo* s;
691
692 (void)x;
693
694 if(y>=SCROLLABLE_LINES) return;
695
696 s = &scroll[y];
697 s->invert = !s->invert;
698}
699
700void lcd_remote_stop_scroll(void)
701{
702 scrolling_lines=0;
703}
704
705void lcd_remote_scroll_speed(int speed)
706{
707 scroll_ticks = scroll_tick_table[speed];
708}
709
710void lcd_remote_scroll_step(int step)
711{
712 scroll_step = step;
713}
714
715void lcd_remote_scroll_delay(int ms)
716{
717 scroll_delay = ms / (HZ / 10);
718}
719
720void lcd_remote_bidir_scroll(int percent)
721{
722 bidir_limit = percent;
723}
724
725void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) 667void lcd_remote_puts_scroll(int x, int y, const unsigned char *string)
726{ 668{
727 lcd_remote_puts_scroll_style(x, y, string, STYLE_DEFAULT); 669 lcd_remote_puts_scroll_style(x, y, string, STYLE_DEFAULT);
@@ -743,11 +685,11 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
743 struct scrollinfo* s; 685 struct scrollinfo* s;
744 int w, h; 686 int w, h;
745 687
746 if(y>=SCROLLABLE_LINES) return; 688 if(y>=LCD_REMOTE_SCROLLABLE_LINES) return;
747 689
748 s = &scroll[y]; 690 s = &lcd_remote_scroll_info.scroll[y];
749 691
750 s->start_tick = current_tick + scroll_delay; 692 s->start_tick = current_tick + lcd_remote_scroll_info.delay;
751 s->invert = false; 693 s->invert = false;
752 if (style & STYLE_INVERT) { 694 if (style & STYLE_INVERT) {
753 s->invert = true; 695 s->invert = true;
@@ -770,9 +712,9 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
770 712
771 /* scroll bidirectional or forward only depending on the string 713 /* scroll bidirectional or forward only depending on the string
772 width */ 714 width */
773 if ( bidir_limit ) { 715 if ( lcd_remote_scroll_info.bidir_limit ) {
774 s->bidir = s->width < (LCD_REMOTE_WIDTH - xmargin) * 716 s->bidir = s->width < (LCD_REMOTE_WIDTH - xmargin) *
775 (100 + bidir_limit) / 100; 717 (100 + lcd_remote_scroll_info.bidir_limit) / 100;
776 } 718 }
777 else 719 else
778 s->bidir = false; 720 s->bidir = false;
@@ -790,110 +732,67 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
790 s->offset = offset; 732 s->offset = offset;
791 s->startx = xmargin + x * s->width / s->len;; 733 s->startx = xmargin + x * s->width / s->len;;
792 s->backward = false; 734 s->backward = false;
793 scrolling_lines |= (1<<y); 735 lcd_remote_scroll_info.lines |= (1<<y);
794 } 736 }
795 else 737 else
796 /* force a bit switch-off since it doesn't scroll */ 738 /* force a bit switch-off since it doesn't scroll */
797 scrolling_lines &= ~(1<<y); 739 lcd_remote_scroll_info.lines &= ~(1<<y);
798} 740}
799 741
800static void scroll_thread(void) 742void lcd_remote_scroll_fn(void)
801{ 743{
802 struct font* pf; 744 struct font* pf;
803 struct scrollinfo* s; 745 struct scrollinfo* s;
804 long next_tick = current_tick;
805 long delay = 0;
806 int index; 746 int index;
807 int xpos, ypos; 747 int xpos, ypos;
808 int lastmode; 748 int lastmode;
809#ifndef SIMULATOR
810 struct event ev;
811#endif
812
813 /* initialize scroll struct array */
814 scrolling_lines = 0;
815
816 while ( 1 ) {
817
818#ifdef SIMULATOR
819 sleep(delay);
820#else
821 if (remote_initialized)
822 queue_wait_w_tmo(&remote_scroll_queue, &ev, delay);
823 else
824 queue_wait(&remote_scroll_queue, &ev);
825 749
826 switch (ev.id) 750 for ( index = 0; index < LCD_REMOTE_SCROLLABLE_LINES; index++ ) {
827 { 751 /* really scroll? */
828 case REMOTE_INIT_LCD: 752 if ((lcd_remote_scroll_info.lines & (1 << index)) == 0)
829 lcd_remote_on();
830 lcd_remote_update();
831 break;
832
833 case REMOTE_DEINIT_LCD:
834 lcd_remote_off();
835 break;
836 }
837
838 delay = next_tick - current_tick - 1;
839 if (delay >= 0)
840 continue; 753 continue;
841#endif
842 for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
843 /* really scroll? */
844 if ( !(scrolling_lines&(1<<index)) )
845 continue;
846 754
847 s = &scroll[index]; 755 s = &lcd_remote_scroll_info.scroll[index];
848 756
849 /* check pause */ 757 /* check pause */
850 if (TIME_BEFORE(current_tick, s->start_tick)) 758 if (TIME_BEFORE(current_tick, s->start_tick))
851 continue; 759 continue;
852 760
853 if (s->backward) 761 if (s->backward)
854 s->offset -= scroll_step; 762 s->offset -= lcd_remote_scroll_info.step;
855 else 763 else
856 s->offset += scroll_step; 764 s->offset += lcd_remote_scroll_info.step;
857 765
858 pf = font_get(curfont); 766 pf = font_get(curfont);
859 xpos = s->startx; 767 xpos = s->startx;
860 ypos = ymargin + index * pf->height; 768 ypos = ymargin + index * pf->height;
861 769
862 if (s->bidir) { /* scroll bidirectional */ 770 if (s->bidir) { /* scroll bidirectional */
863 if (s->offset <= 0) { 771 if (s->offset <= 0) {
864 /* at beginning of line */ 772 /* at beginning of line */
865 s->offset = 0; 773 s->offset = 0;
866 s->backward = false; 774 s->backward = false;
867 s->start_tick = current_tick + scroll_delay * 2; 775 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2;
868 }
869 if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) {
870 /* at end of line */
871 s->offset = s->width - (LCD_REMOTE_WIDTH - xpos);
872 s->backward = true;
873 s->start_tick = current_tick + scroll_delay * 2;
874 }
875 } 776 }
876 else { 777 if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) {
877 /* scroll forward the whole time */ 778 /* at end of line */
878 if (s->offset >= s->width) 779 s->offset = s->width - (LCD_REMOTE_WIDTH - xpos);
879 s->offset %= s->width; 780 s->backward = true;
781 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2;
880 } 782 }
881
882 lastmode = drawmode;
883 drawmode = s->invert ?
884 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
885 lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line);
886 drawmode = lastmode;
887 lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height);
888 } 783 }
889 784 else {
890 next_tick += scroll_ticks; 785 /* scroll forward the whole time */
891 delay = next_tick - current_tick - 1; 786 if (s->offset >= s->width)
892 if (delay < 0) 787 s->offset %= s->width;
893 {
894 next_tick = current_tick + 1;
895 delay = 0;
896 } 788 }
789
790 lastmode = drawmode;
791 drawmode = s->invert ?
792 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
793 lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line);
794 drawmode = lastmode;
795 lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height);
897 } 796 }
898} 797}
899 798
@@ -903,10 +802,5 @@ void lcd_remote_init(void)
903#ifndef SIMULATOR 802#ifndef SIMULATOR
904 /* Call device specific init */ 803 /* Call device specific init */
905 lcd_remote_init_device(); 804 lcd_remote_init_device();
906 /* private queue */
907 queue_init(&remote_scroll_queue, false);
908#endif 805#endif
909 create_thread(scroll_thread, scroll_stack,
910 sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
911 IF_COP(, CPU, false));
912} 806}
diff --git a/firmware/drivers/lcd-remote-2bit-vi.c b/firmware/drivers/lcd-remote-2bit-vi.c
index 65704f0bd3..21e3ee4aa0 100644
--- a/firmware/drivers/lcd-remote-2bit-vi.c
+++ b/firmware/drivers/lcd-remote-2bit-vi.c
@@ -34,8 +34,7 @@
34#include "rbunicode.h" 34#include "rbunicode.h"
35#include "bidi.h" 35#include "bidi.h"
36#include "lcd-remote-target.h" 36#include "lcd-remote-target.h"
37 37#include "scroll_engine.h"
38#define SCROLLABLE_LINES (((LCD_REMOTE_HEIGHT+4)/5 < 32) ? (LCD_REMOTE_HEIGHT+4)/5 : 32)
39 38
40/*** globals ***/ 39/*** globals ***/
41 40
@@ -54,28 +53,6 @@ static int xmargin = 0;
54static int ymargin = 0; 53static int ymargin = 0;
55static int curfont = FONT_SYSFIXED; 54static int curfont = FONT_SYSFIXED;
56 55
57/* scrolling */
58static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */
59static void scroll_thread(void);
60static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)];
61static const char scroll_name[] = "remote_scroll";
62static int scroll_ticks = 12; /* # of ticks between updates*/
63static int scroll_delay = HZ/2; /* ticks delay before start */
64static int scroll_step = 6; /* pixels per scroll step */
65static int bidir_limit = 50; /* percent */
66static struct scrollinfo scroll[SCROLLABLE_LINES];
67
68static const char scroll_tick_table[16] = {
69 /* Hz values:
70 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
71 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
72};
73
74/* remote hotplug */
75#ifndef SIMULATOR
76struct event_queue remote_scroll_queue;
77#endif
78
79/*** parameter handling ***/ 56/*** parameter handling ***/
80unsigned lcd_remote_color_to_native(unsigned color) 57unsigned lcd_remote_color_to_native(unsigned color)
81{ 58{
@@ -149,6 +126,11 @@ void lcd_remote_setfont(int newfont)
149 curfont = newfont; 126 curfont = newfont;
150} 127}
151 128
129int lcd_remote_getfont(void)
130{
131 return curfont;
132}
133
152int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) 134int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h)
153{ 135{
154 return font_getstringsize(str, w, h, curfont); 136 return font_getstringsize(str, w, h, curfont);
@@ -388,7 +370,8 @@ void lcd_remote_clear_display(void)
388 memset(lcd_remote_framebuffer, bg_pattern, 370 memset(lcd_remote_framebuffer, bg_pattern,
389 sizeof lcd_remote_framebuffer); 371 sizeof lcd_remote_framebuffer);
390 } 372 }
391 scrolling_lines = 0; 373
374 lcd_remote_scroll_info.lines = 0;
392} 375}
393 376
394/* Set a single pixel */ 377/* Set a single pixel */
@@ -935,7 +918,7 @@ void lcd_remote_bitmap(const fb_remote_data *src, int x, int y, int width,
935} 918}
936 919
937/* put a string at a given pixel position, skipping first ofs pixel columns */ 920/* put a string at a given pixel position, skipping first ofs pixel columns */
938static void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str) 921void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str)
939{ 922{
940 unsigned short ch; 923 unsigned short ch;
941 unsigned short *ucs; 924 unsigned short *ucs;
@@ -1000,7 +983,7 @@ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str,
1000 int lastmode = drawmode; 983 int lastmode = drawmode;
1001 984
1002 /* make sure scrolling is turned off on the line we are updating */ 985 /* make sure scrolling is turned off on the line we are updating */
1003 scrolling_lines &= ~(1 << y); 986 lcd_remote_scroll_info.lines &= ~(1 << y);
1004 987
1005 if(!str || !str[0]) 988 if(!str || !str[0])
1006 return; 989 return;
@@ -1018,46 +1001,6 @@ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str,
1018} 1001}
1019 1002
1020/*** scrolling ***/ 1003/*** scrolling ***/
1021
1022/* Reverse the invert setting of the scrolling line (if any) at given char
1023 position. Setting will go into affect next time line scrolls. */
1024void lcd_remote_invertscroll(int x, int y)
1025{
1026 struct scrollinfo* s;
1027
1028 (void)x;
1029
1030 if(y>=SCROLLABLE_LINES) return;
1031
1032 s = &scroll[y];
1033 s->invert = !s->invert;
1034}
1035
1036void lcd_remote_stop_scroll(void)
1037{
1038 scrolling_lines=0;
1039}
1040
1041void lcd_remote_scroll_speed(int speed)
1042{
1043 scroll_ticks = scroll_tick_table[speed];
1044}
1045
1046void lcd_remote_scroll_step(int step)
1047{
1048 scroll_step = step;
1049}
1050
1051void lcd_remote_scroll_delay(int ms)
1052{
1053 scroll_delay = ms / (HZ / 10);
1054}
1055
1056void lcd_remote_bidir_scroll(int percent)
1057{
1058 bidir_limit = percent;
1059}
1060
1061void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) 1004void lcd_remote_puts_scroll(int x, int y, const unsigned char *string)
1062{ 1005{
1063 lcd_remote_puts_scroll_style(x, y, string, STYLE_DEFAULT); 1006 lcd_remote_puts_scroll_style(x, y, string, STYLE_DEFAULT);
@@ -1079,11 +1022,11 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
1079 struct scrollinfo* s; 1022 struct scrollinfo* s;
1080 int w, h; 1023 int w, h;
1081 1024
1082 if(y>=SCROLLABLE_LINES) return; 1025 if(y>=LCD_REMOTE_SCROLLABLE_LINES) return;
1083 1026
1084 s = &scroll[y]; 1027 s = &lcd_remote_scroll_info.scroll[y];
1085 1028
1086 s->start_tick = current_tick + scroll_delay; 1029 s->start_tick = current_tick + lcd_remote_scroll_info.delay;
1087 s->invert = false; 1030 s->invert = false;
1088 if (style & STYLE_INVERT) { 1031 if (style & STYLE_INVERT) {
1089 s->invert = true; 1032 s->invert = true;
@@ -1106,9 +1049,9 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
1106 1049
1107 /* scroll bidirectional or forward only depending on the string 1050 /* scroll bidirectional or forward only depending on the string
1108 width */ 1051 width */
1109 if ( bidir_limit ) { 1052 if ( lcd_remote_scroll_info.bidir_limit ) {
1110 s->bidir = s->width < (LCD_REMOTE_WIDTH - xmargin) * 1053 s->bidir = s->width < (LCD_REMOTE_WIDTH - xmargin) *
1111 (100 + bidir_limit) / 100; 1054 (100 + lcd_remote_scroll_info.bidir_limit) / 100;
1112 } 1055 }
1113 else 1056 else
1114 s->bidir = false; 1057 s->bidir = false;
@@ -1126,112 +1069,67 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
1126 s->offset = offset; 1069 s->offset = offset;
1127 s->startx = xmargin + x * s->width / s->len;; 1070 s->startx = xmargin + x * s->width / s->len;;
1128 s->backward = false; 1071 s->backward = false;
1129 scrolling_lines |= (1<<y); 1072 lcd_remote_scroll_info.lines |= (1<<y);
1130 } 1073 }
1131 else 1074 else
1132 /* force a bit switch-off since it doesn't scroll */ 1075 /* force a bit switch-off since it doesn't scroll */
1133 scrolling_lines &= ~(1<<y); 1076 lcd_remote_scroll_info.lines &= ~(1<<y);
1134} 1077}
1135 1078
1136static void scroll_thread(void) 1079void lcd_remote_scroll_fn(void)
1137{ 1080{
1138 struct font* pf; 1081 struct font* pf;
1139 struct scrollinfo* s; 1082 struct scrollinfo* s;
1140 int index; 1083 int index;
1141 int xpos, ypos; 1084 int xpos, ypos;
1142 int lastmode; 1085 int lastmode;
1143 long delay = 0;
1144 long next_tick = current_tick;
1145#ifndef SIMULATOR
1146 struct event ev;
1147#endif
1148
1149 /* initialize scroll struct array */
1150 scrolling_lines = 0;
1151 1086
1152 while ( 1 ) { 1087 for ( index = 0; index < LCD_REMOTE_SCROLLABLE_LINES; index++ ) {
1153 1088 /* really scroll? */
1154#ifdef SIMULATOR 1089 if ((lcd_remote_scroll_info.lines & (1 << index)) == 0)
1155 sleep(delay);
1156#else
1157 if (remote_initialized)
1158 queue_wait_w_tmo(&remote_scroll_queue, &ev, delay);
1159 else
1160 queue_wait(&remote_scroll_queue, &ev);
1161
1162 switch (ev.id)
1163 {
1164 case REMOTE_INIT_LCD:
1165 lcd_remote_on();
1166 lcd_remote_update();
1167 break;
1168
1169 case REMOTE_DEINIT_LCD:
1170 lcd_remote_off();
1171 break;
1172 }
1173
1174 delay = next_tick - current_tick - 1;
1175 if (delay >= 0)
1176 continue; 1090 continue;
1177#endif
1178 1091
1179 for ( index = 0; index < SCROLLABLE_LINES; index++ ) { 1092 s = &lcd_remote_scroll_info.scroll[index];
1180 /* really scroll? */
1181 if ( !(scrolling_lines&(1<<index)) )
1182 continue;
1183 1093
1184 s = &scroll[index]; 1094 /* check pause */
1185 1095 if (TIME_BEFORE(current_tick, s->start_tick))
1186 /* check pause */ 1096 continue;
1187 if (TIME_BEFORE(current_tick, s->start_tick))
1188 continue;
1189 1097
1190 if (s->backward) 1098 if (s->backward)
1191 s->offset -= scroll_step; 1099 s->offset -= lcd_remote_scroll_info.step;
1192 else 1100 else
1193 s->offset += scroll_step; 1101 s->offset += lcd_remote_scroll_info.step;
1194 1102
1195 pf = font_get(curfont); 1103 pf = font_get(curfont);
1196 xpos = s->startx; 1104 xpos = s->startx;
1197 ypos = ymargin + index * pf->height; 1105 ypos = ymargin + index * pf->height;
1198 1106
1199 if (s->bidir) { /* scroll bidirectional */ 1107 if (s->bidir) { /* scroll bidirectional */
1200 if (s->offset <= 0) { 1108 if (s->offset <= 0) {
1201 /* at beginning of line */ 1109 /* at beginning of line */
1202 s->offset = 0; 1110 s->offset = 0;
1203 s->backward = false; 1111 s->backward = false;
1204 s->start_tick = current_tick + scroll_delay * 2; 1112 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2;
1205 }
1206 if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) {
1207 /* at end of line */
1208 s->offset = s->width - (LCD_REMOTE_WIDTH - xpos);
1209 s->backward = true;
1210 s->start_tick = current_tick + scroll_delay * 2;
1211 }
1212 } 1113 }
1213 else { 1114 if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) {
1214 /* scroll forward the whole time */ 1115 /* at end of line */
1215 if (s->offset >= s->width) 1116 s->offset = s->width - (LCD_REMOTE_WIDTH - xpos);
1216 s->offset %= s->width; 1117 s->backward = true;
1118 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2;
1217 } 1119 }
1218
1219 lastmode = drawmode;
1220 drawmode = s->invert ?
1221 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
1222 lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line);
1223 drawmode = lastmode;
1224 lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height);
1225 } 1120 }
1226 1121 else {
1227 1122 /* scroll forward the whole time */
1228 next_tick += scroll_ticks; 1123 if (s->offset >= s->width)
1229 delay = next_tick - current_tick - 1; 1124 s->offset %= s->width;
1230 if (delay < 0)
1231 {
1232 next_tick = current_tick + 1;
1233 delay = 0;
1234 } 1125 }
1126
1127 lastmode = drawmode;
1128 drawmode = s->invert ?
1129 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
1130 lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line);
1131 drawmode = lastmode;
1132 lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height);
1235 } 1133 }
1236} 1134}
1237 1135
@@ -1241,10 +1139,5 @@ void lcd_remote_init(void)
1241#ifndef SIMULATOR 1139#ifndef SIMULATOR
1242 /* Call device specific init */ 1140 /* Call device specific init */
1243 lcd_remote_init_device(); 1141 lcd_remote_init_device();
1244 /* private queue */
1245 queue_init(&remote_scroll_queue, false);
1246#endif 1142#endif
1247 create_thread(scroll_thread, scroll_stack,
1248 sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)
1249 IF_COP(, CPU, false));
1250} 1143}