summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2006-07-28 12:41:13 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2006-07-28 12:41:13 +0000
commitd17d08c268290b9ffc2f6e62876f1e0a05b56a6e (patch)
tree8536a67ffa5c88f7ec38e5a74046c28705b95220
parent38719f87cbf6cd5fcefafe14780543eb1dad3f63 (diff)
downloadrockbox-d17d08c268290b9ffc2f6e62876f1e0a05b56a6e.tar.gz
rockbox-d17d08c268290b9ffc2f6e62876f1e0a05b56a6e.zip
LCD remote support for iAudio X5
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10352 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/backlight.c20
-rwxr-xr-xfirmware/drivers/lcd-remote-2bit-vi.c123
-rwxr-xr-xfirmware/target/coldfire/iaudio/x5/lcd-remote-target.h6
-rwxr-xr-xfirmware/target/coldfire/iaudio/x5/lcd-remote-x5.c130
4 files changed, 239 insertions, 40 deletions
diff --git a/firmware/backlight.c b/firmware/backlight.c
index 2539bb642a..cd1fbaf1ba 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -336,12 +336,21 @@ static void _backlight_off(void)
336} 336}
337 337
338#ifdef HAVE_REMOTE_LCD 338#ifdef HAVE_REMOTE_LCD
339#ifndef TARGET_TREE 339#ifdef SIMULATOR
340static void __remote_backlight_on(void) 340static void __remote_backlight_on(void)
341{ 341{
342#ifdef SIMULATOR
343 sim_remote_backlight(100); 342 sim_remote_backlight(100);
344#elif defined(IRIVER_H300_SERIES) 343}
344
345static void __remote_backlight_off(void)
346{
347 sim_remote_backlight(0);
348}
349#else
350#ifndef TARGET_TREE
351static void __remote_backlight_on(void)
352{
353#if defined(IRIVER_H300_SERIES)
345 and_l(~0x00000002, &GPIO1_OUT); 354 and_l(~0x00000002, &GPIO1_OUT);
346#else 355#else
347 and_l(~0x00000800, &GPIO_OUT); 356 and_l(~0x00000800, &GPIO_OUT);
@@ -350,9 +359,7 @@ static void __remote_backlight_on(void)
350 359
351static void __remote_backlight_off(void) 360static void __remote_backlight_off(void)
352{ 361{
353#ifdef SIMULATOR 362#if defined(IRIVER_H300_SERIES)
354 sim_remote_backlight(0);
355#elif defined(IRIVER_H300_SERIES)
356 or_l(0x00000002, &GPIO1_OUT); 363 or_l(0x00000002, &GPIO1_OUT);
357#else 364#else
358 or_l(0x00000800, &GPIO_OUT); 365 or_l(0x00000800, &GPIO_OUT);
@@ -360,6 +367,7 @@ static void __remote_backlight_off(void)
360} 367}
361#endif /* TARGET_TREE */ 368#endif /* TARGET_TREE */
362#endif /* HAVE_REMOTE_LCD */ 369#endif /* HAVE_REMOTE_LCD */
370#endif /* SIMULATOR */
363 371
364void backlight_thread(void) 372void backlight_thread(void)
365{ 373{
diff --git a/firmware/drivers/lcd-remote-2bit-vi.c b/firmware/drivers/lcd-remote-2bit-vi.c
index cf486b5d0d..eefbae1de3 100755
--- a/firmware/drivers/lcd-remote-2bit-vi.c
+++ b/firmware/drivers/lcd-remote-2bit-vi.c
@@ -33,6 +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#include "lcd-remote-target.h"
36 37
37#define SCROLLABLE_LINES (((LCD_REMOTE_HEIGHT+4)/5 < 32) ? (LCD_REMOTE_HEIGHT+4)/5 : 32) 38#define SCROLLABLE_LINES (((LCD_REMOTE_HEIGHT+4)/5 < 32) ? (LCD_REMOTE_HEIGHT+4)/5 : 32)
38 39
@@ -67,18 +68,12 @@ static const char scroll_tick_table[16] = {
67 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 68 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
68}; 69};
69 70
70 71/* remote hotplug */
71/* LCD init */ 72#ifndef SIMULATOR
72void lcd_remote_init(void) 73static struct event_queue remote_scroll_queue;
73{ 74#define REMOTE_INIT_LCD 1
74 lcd_remote_clear_display(); 75#define REMOTE_DEINIT_LCD 2
75#if 0 /* FIXME */
76 /* Call device specific init */
77 remote_init();
78#endif 76#endif
79 create_thread(scroll_thread, scroll_stack,
80 sizeof(scroll_stack), scroll_name);
81}
82 77
83/*** parameter handling ***/ 78/*** parameter handling ***/
84 79
@@ -1020,6 +1015,51 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
1020 scrolling_lines &= ~(1<<y); 1015 scrolling_lines &= ~(1<<y);
1021} 1016}
1022 1017
1018#ifndef SIMULATOR
1019/* Monitor remote hotswap */
1020static void remote_tick(void)
1021{
1022 static bool last_status = false;
1023 static int countdown = 0;
1024 static int init_delay = 0;
1025 bool current_status;
1026
1027 current_status = remote_detect();
1028
1029 /* Only report when the status has changed */
1030 if (current_status != last_status)
1031 {
1032 last_status = current_status;
1033 countdown = current_status ? 20*HZ : 1;
1034 }
1035 else
1036 {
1037 /* Count down until it gets negative */
1038 if (countdown >= 0)
1039 countdown--;
1040
1041 if (current_status)
1042 {
1043 if (!(countdown % 8))
1044 {
1045 if (--init_delay <= 0)
1046 {
1047 queue_post(&remote_scroll_queue, REMOTE_INIT_LCD, 0);
1048 init_delay = 6;
1049 }
1050 }
1051 }
1052 else
1053 {
1054 if (countdown == 0)
1055 {
1056 queue_post(&remote_scroll_queue, REMOTE_DEINIT_LCD, 0);
1057 }
1058 }
1059 }
1060}
1061#endif
1062
1023static void scroll_thread(void) 1063static void scroll_thread(void)
1024{ 1064{
1025 struct font* pf; 1065 struct font* pf;
@@ -1027,11 +1067,42 @@ static void scroll_thread(void)
1027 int index; 1067 int index;
1028 int xpos, ypos; 1068 int xpos, ypos;
1029 int lastmode; 1069 int lastmode;
1070 long delay = 0;
1071 long next_tick = current_tick;
1072#ifndef SIMULATOR
1073 struct event ev;
1074#endif
1030 1075
1031 /* initialize scroll struct array */ 1076 /* initialize scroll struct array */
1032 scrolling_lines = 0; 1077 scrolling_lines = 0;
1033 1078
1034 while ( 1 ) { 1079 while ( 1 ) {
1080
1081#ifdef SIMULATOR
1082 sleep(delay);
1083#else
1084 if (remote_initialized)
1085 queue_wait_w_tmo(&remote_scroll_queue, &ev, delay);
1086 else
1087 queue_wait(&remote_scroll_queue, &ev);
1088
1089 switch (ev.id)
1090 {
1091 case REMOTE_INIT_LCD:
1092 lcd_remote_on();
1093 lcd_remote_update();
1094 break;
1095
1096 case REMOTE_DEINIT_LCD:
1097 lcd_remote_off();
1098 break;
1099 }
1100
1101 delay = next_tick - current_tick - 1;
1102 if (delay >= 0)
1103 continue;
1104#endif
1105
1035 for ( index = 0; index < SCROLLABLE_LINES; index++ ) { 1106 for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
1036 /* really scroll? */ 1107 /* really scroll? */
1037 if ( !(scrolling_lines&(1<<index)) ) 1108 if ( !(scrolling_lines&(1<<index)) )
@@ -1080,6 +1151,34 @@ static void scroll_thread(void)
1080 lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); 1151 lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height);
1081 } 1152 }
1082 1153
1083 sleep(scroll_ticks); 1154
1155 next_tick += scroll_ticks;
1156 delay = next_tick - current_tick - 1;
1157 if (delay < 0)
1158 {
1159 next_tick = current_tick + 1;
1160 delay = 0;
1161 }
1084 } 1162 }
1085} 1163}
1164
1165/* LCD init */
1166#ifdef SIMULATOR
1167void lcd_remote_init(void)
1168{
1169 create_thread(scroll_thread, scroll_stack,
1170 sizeof(scroll_stack), scroll_name);
1171}
1172#else
1173void lcd_remote_init(void)
1174{
1175 /* Call device specific init */
1176 lcd_remote_init_device();
1177
1178 lcd_remote_clear_display();
1179 queue_clear(&remote_scroll_queue); /* no queue_init() -- private queue */
1180 tick_add_task(remote_tick);
1181 create_thread(scroll_thread, scroll_stack,
1182 sizeof(scroll_stack), scroll_name);
1183}
1184#endif
diff --git a/firmware/target/coldfire/iaudio/x5/lcd-remote-target.h b/firmware/target/coldfire/iaudio/x5/lcd-remote-target.h
index 72d4ed9fb2..8c20526ff3 100755
--- a/firmware/target/coldfire/iaudio/x5/lcd-remote-target.h
+++ b/firmware/target/coldfire/iaudio/x5/lcd-remote-target.h
@@ -19,12 +19,16 @@
19#ifndef LCD_REMOTE_TARGET_H 19#ifndef LCD_REMOTE_TARGET_H
20#define LCD_REMOTE_TARGET_H 20#define LCD_REMOTE_TARGET_H
21 21
22void lcd_remote_init_device(void);
22void lcd_remote_write_command(int cmd); 23void lcd_remote_write_command(int cmd);
23void lcd_remote_write_command_ex(int cmd, int data); 24void lcd_remote_write_command_ex(int cmd, int data);
24void lcd_remote_write_data(const unsigned char* p_bytes, int count); 25void lcd_remote_write_data(const unsigned char* p_bytes, int count);
25bool remote_detect(void); 26bool remote_detect(void);
26void lcd_remote_powersave(bool on); 27void lcd_remote_powersave(bool on);
27void lcd_remote_set_contrast(int val); 28void lcd_remote_set_contrast(int val);
28void remote_set_row_and_col(int row, int col); 29void lcd_remote_on(void);
30void lcd_remote_off(void);
31
32extern bool remote_initialized;
29 33
30#endif 34#endif
diff --git a/firmware/target/coldfire/iaudio/x5/lcd-remote-x5.c b/firmware/target/coldfire/iaudio/x5/lcd-remote-x5.c
index c1ec00f0e7..586104fc0a 100755
--- a/firmware/target/coldfire/iaudio/x5/lcd-remote-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/lcd-remote-x5.c
@@ -19,6 +19,7 @@
19#include "config.h" 19#include "config.h"
20#include "system.h" 20#include "system.h"
21#include "kernel.h" 21#include "kernel.h"
22#include "lcd-remote.h"
22 23
23/* The LCD in the iAudio M3/M5/X5 remote control is a Tomato LSI 0350 */ 24/* The LCD in the iAudio M3/M5/X5 remote control is a Tomato LSI 0350 */
24 25
@@ -39,6 +40,7 @@
39#define LCD_SET_GRAY 0x88 40#define LCD_SET_GRAY 0x88
40#define LCD_SET_PWM_FRC 0x90 41#define LCD_SET_PWM_FRC 0x90
41#define LCD_SET_POWER_SAVE 0xa8 42#define LCD_SET_POWER_SAVE 0xa8
43#define LCD_REVERSE 0xa6
42 44
43#define CS_LO and_l(~0x00000020, &GPIO1_OUT) 45#define CS_LO and_l(~0x00000020, &GPIO1_OUT)
44#define CS_HI or_l(0x00000020, &GPIO1_OUT) 46#define CS_HI or_l(0x00000020, &GPIO1_OUT)
@@ -51,8 +53,12 @@
51 53
52#define LCD_REMOTE_DEFAULT_CONTRAST 0x18; 54#define LCD_REMOTE_DEFAULT_CONTRAST 0x18;
53 55
56/* cached settings values */
57static bool cached_invert = false;
58static bool cached_flip = false;
54static int cached_contrast = LCD_REMOTE_DEFAULT_CONTRAST; 59static int cached_contrast = LCD_REMOTE_DEFAULT_CONTRAST;
55static bool remote_initialized = false; 60
61bool remote_initialized = false;
56 62
57static void remote_write(unsigned char byte, bool is_command) 63static void remote_write(unsigned char byte, bool is_command)
58{ 64{
@@ -94,13 +100,6 @@ void lcd_remote_write_data(const unsigned char* p_bytes, int count)
94 remote_write(*p_bytes++, false); 100 remote_write(*p_bytes++, false);
95} 101}
96 102
97void remote_set_row_and_col(int row, int col)
98{
99 lcd_remote_write_command(LCD_SET_PAGE | (row & 0xf));
100 lcd_remote_write_command_ex(LCD_SET_COLUMN | ((col >> 4) & 0xf),
101 col & 0xf);
102}
103
104int lcd_remote_default_contrast(void) 103int lcd_remote_default_contrast(void)
105{ 104{
106 return LCD_REMOTE_DEFAULT_CONTRAST; 105 return LCD_REMOTE_DEFAULT_CONTRAST;
@@ -108,24 +107,27 @@ int lcd_remote_default_contrast(void)
108 107
109void lcd_remote_powersave(bool on) 108void lcd_remote_powersave(bool on)
110{ 109{
111 if (on) 110 if(remote_initialized) {
112 lcd_remote_write_command(LCD_SET_POWER_SAVE | 1); 111 if (on)
113 else 112 lcd_remote_write_command(LCD_SET_POWER_SAVE | 1);
114 lcd_remote_write_command(LCD_SET_POWER_SAVE | 1); 113 else
114 lcd_remote_write_command(LCD_SET_POWER_SAVE | 1);
115 }
115} 116}
116 117
117void lcd_remote_set_contrast(int val) 118void lcd_remote_set_contrast(int val)
118{ 119{
119 cached_contrast = val; 120 cached_contrast = val;
120 lcd_remote_write_command_ex(LCD_SET_VOLUME, val); 121 if(remote_initialized)
122 lcd_remote_write_command_ex(LCD_SET_VOLUME, val);
121} 123}
122 124
123bool remote_detect(void) 125bool remote_detect(void)
124{ 126{
125 return (GPIO_READ & 0x01000000); 127 return (GPIO_READ & 0x01000000)?false:true;
126} 128}
127 129
128void remote_init(void) 130void lcd_remote_init_device(void)
129{ 131{
130 or_l(0x0000e000, &GPIO_OUT); 132 or_l(0x0000e000, &GPIO_OUT);
131 or_l(0x0000e000, &GPIO_ENABLE); 133 or_l(0x0000e000, &GPIO_ENABLE);
@@ -135,17 +137,18 @@ void remote_init(void)
135 or_l(0x00000020, &GPIO1_ENABLE); 137 or_l(0x00000020, &GPIO1_ENABLE);
136 or_l(0x00000020, &GPIO1_FUNCTION); 138 or_l(0x00000020, &GPIO1_FUNCTION);
137 139
140 and_l(~0x01000000, &GPIO_OUT);
141 and_l(~0x01000000, &GPIO_ENABLE);
142 or_l(0x01000000, &GPIO_FUNCTION);
143}
144
145void lcd_remote_on(void)
146{
138 sleep(10); 147 sleep(10);
139 148
140 lcd_remote_write_command(LCD_SET_DUTY_RATIO); 149 lcd_remote_write_command(LCD_SET_DUTY_RATIO);
141 lcd_remote_write_command(0x70); /* 1/128 */ 150 lcd_remote_write_command(0x70); /* 1/128 */
142 151
143 lcd_remote_write_command(LCD_SELECT_ADC | 1); /* Reverse direction */
144 lcd_remote_write_command(LCD_SELECT_SHL | 8); /* Reverse direction */
145
146 lcd_remote_write_command(LCD_SET_COM0);
147 lcd_remote_write_command(0x00);
148
149 lcd_remote_write_command(LCD_OSC_ON); 152 lcd_remote_write_command(LCD_OSC_ON);
150 153
151 lcd_remote_write_command(LCD_SELECT_DCDC | 2); /* DC/DC 5xboost */ 154 lcd_remote_write_command(LCD_SELECT_DCDC | 2); /* DC/DC 5xboost */
@@ -173,5 +176,90 @@ void remote_init(void)
173 176
174 remote_initialized = true; 177 remote_initialized = true;
175 178
179 lcd_remote_set_flip(cached_flip);
176 lcd_remote_set_contrast(cached_contrast); 180 lcd_remote_set_contrast(cached_contrast);
181 lcd_remote_set_invert_display(cached_invert);
182}
183
184void lcd_remote_off(void)
185{
186 remote_initialized = false;
187 CS_HI;
188 RS_HI;
189}
190
191/* Update the display.
192 This must be called after all other LCD functions that change the display. */
193void lcd_remote_update(void) ICODE_ATTR;
194void lcd_remote_update(void)
195{
196 int y;
197 if(remote_initialized) {
198 for(y = 0;y < LCD_REMOTE_HEIGHT/8;y++) {
199 /* Copy display bitmap to hardware.
200 The COM48-COM63 lines are not connected so we have to skip
201 them. Further, the column address doesn't wrap, so we
202 have to update one page at a time. */
203 lcd_remote_write_command(LCD_SET_PAGE | (y>5?y+2:y));
204 lcd_remote_write_command_ex(LCD_SET_COLUMN | 0, 0);
205 lcd_remote_write_data((unsigned char *)lcd_remote_framebuffer[y],
206 LCD_REMOTE_WIDTH*2);
207 }
208 }
209}
210
211/* Update a fraction of the display. */
212void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR;
213void lcd_remote_update_rect(int x, int y, int width, int height)
214{
215 if(remote_initialized) {
216 int ymax;
217
218 /* The Y coordinates have to work on even 8 pixel rows */
219 ymax = (y + height-1) >> 3;
220 y >>= 3;
221
222 if(x + width > LCD_REMOTE_WIDTH)
223 width = LCD_REMOTE_WIDTH - x;
224 if (width <= 0)
225 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
226 if(ymax >= LCD_REMOTE_HEIGHT)
227 ymax = LCD_REMOTE_HEIGHT-1;
228
229 /* Copy specified rectangle bitmap to hardware
230 COM48-COM63 are not connected, so we need to skip those */
231 for (; y <= ymax; y++)
232 {
233 lcd_remote_write_command(LCD_SET_PAGE |
234 ((y > 5?y + 2:y) & 0xf));
235 lcd_remote_write_command_ex(LCD_SET_COLUMN | ((x >> 4) & 0xf),
236 x & 0xf);
237
238 lcd_remote_write_data (
239 (unsigned char *)&lcd_remote_framebuffer[y][x], width*2);
240 }
241 }
242}
243
244void lcd_remote_set_invert_display(bool yesno)
245{
246 cached_invert = yesno;
247 if(remote_initialized)
248 lcd_remote_write_command(LCD_REVERSE | yesno);
249}
250
251void lcd_remote_set_flip(bool yesno)
252{
253 cached_flip = yesno;
254 if(remote_initialized) {
255 if(yesno) {
256 lcd_remote_write_command(LCD_SELECT_ADC | 0);
257 lcd_remote_write_command(LCD_SELECT_SHL | 0);
258 lcd_remote_write_command_ex(LCD_SET_COM0, 16);
259 } else {
260 lcd_remote_write_command(LCD_SELECT_ADC | 1);
261 lcd_remote_write_command(LCD_SELECT_SHL | 8);
262 lcd_remote_write_command_ex(LCD_SET_COM0, 0);
263 }
264 }
177} 265}