diff options
-rw-r--r-- | firmware/SOURCES | 4 | ||||
-rw-r--r-- | firmware/drivers/lcd-remote-1bit-v.c (renamed from firmware/drivers/lcd-h100-remote.c) | 636 | ||||
-rw-r--r-- | firmware/export/lcd-remote.h | 12 | ||||
-rw-r--r-- | firmware/target/coldfire/iriver/lcd-remote-iriver.c | 610 | ||||
-rwxr-xr-x | firmware/target/coldfire/iriver/lcd-remote-target.h | 44 |
5 files changed, 685 insertions, 621 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 74955a4d91..03d2b16d1d 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -85,7 +85,7 @@ drivers/lcd-16bit.c | |||
85 | 85 | ||
86 | #ifdef HAVE_REMOTE_LCD | 86 | #ifdef HAVE_REMOTE_LCD |
87 | #if LCD_REMOTE_DEPTH == 1 | 87 | #if LCD_REMOTE_DEPTH == 1 |
88 | drivers/lcd-h100-remote.c | 88 | drivers/lcd-remote-1bit-v.c |
89 | #elif LCD_REMOTE_DEPTH == 2 | 89 | #elif LCD_REMOTE_DEPTH == 2 |
90 | drivers/lcd-remote-2bit-vi.c | 90 | drivers/lcd-remote-2bit-vi.c |
91 | #endif /* LCD_REMOTE_DEPTH */ | 91 | #endif /* LCD_REMOTE_DEPTH */ |
@@ -378,6 +378,7 @@ target/coldfire/iriver/h300/power-h300.c | |||
378 | target/coldfire/ata-as-coldfire.S | 378 | target/coldfire/ata-as-coldfire.S |
379 | target/coldfire/pcf50606-coldfire.c | 379 | target/coldfire/pcf50606-coldfire.c |
380 | target/coldfire/iriver/ata-iriver.c | 380 | target/coldfire/iriver/ata-iriver.c |
381 | target/coldfire/iriver/lcd-remote-iriver.c | ||
381 | target/coldfire/iriver/system-iriver.c | 382 | target/coldfire/iriver/system-iriver.c |
382 | target/coldfire/iriver/h300/adc-h300.c | 383 | target/coldfire/iriver/h300/adc-h300.c |
383 | target/coldfire/iriver/h300/backlight-h300.c | 384 | target/coldfire/iriver/h300/backlight-h300.c |
@@ -397,6 +398,7 @@ target/coldfire/iriver/h100/power-h100.c | |||
397 | #ifndef SIMULATOR | 398 | #ifndef SIMULATOR |
398 | target/coldfire/ata-as-coldfire.S | 399 | target/coldfire/ata-as-coldfire.S |
399 | target/coldfire/iriver/ata-iriver.c | 400 | target/coldfire/iriver/ata-iriver.c |
401 | target/coldfire/iriver/lcd-remote-iriver.c | ||
400 | target/coldfire/iriver/system-iriver.c | 402 | target/coldfire/iriver/system-iriver.c |
401 | target/coldfire/iriver/h100/adc-h100.c | 403 | target/coldfire/iriver/h100/adc-h100.c |
402 | target/coldfire/iriver/h100/backlight-h100.c | 404 | target/coldfire/iriver/h100/backlight-h100.c |
diff --git a/firmware/drivers/lcd-h100-remote.c b/firmware/drivers/lcd-remote-1bit-v.c index e8d22213b8..c81ccc83c9 100644 --- a/firmware/drivers/lcd-h100-remote.c +++ b/firmware/drivers/lcd-remote-1bit-v.c | |||
@@ -32,36 +32,7 @@ | |||
32 | #include "rbunicode.h" | 32 | #include "rbunicode.h" |
33 | #include "bidi.h" | 33 | #include "bidi.h" |
34 | 34 | ||
35 | /*** definitions ***/ | 35 | #define SCROLLABLE_LINES (((LCD_REMOTE_HEIGHT+4)/5 < 32) ? (LCD_REMOTE_HEIGHT+4)/5 : 32) |
36 | |||
37 | #define LCD_REMOTE_CNTL_ADC_NORMAL 0xa0 | ||
38 | #define LCD_REMOTE_CNTL_ADC_REVERSE 0xa1 | ||
39 | #define LCD_REMOTE_CNTL_SHL_NORMAL 0xc0 | ||
40 | #define LCD_REMOTE_CNTL_SHL_REVERSE 0xc8 | ||
41 | #define LCD_REMOTE_CNTL_DISPLAY_ON_OFF 0xae | ||
42 | #define LCD_REMOTE_CNTL_ENTIRE_ON_OFF 0xa4 | ||
43 | #define LCD_REMOTE_CNTL_REVERSE_ON_OFF 0xa6 | ||
44 | #define LCD_REMOTE_CNTL_NOP 0xe3 | ||
45 | #define LCD_REMOTE_CNTL_POWER_CONTROL 0x2b | ||
46 | #define LCD_REMOTE_CNTL_SELECT_REGULATOR 0x20 | ||
47 | #define LCD_REMOTE_CNTL_SELECT_BIAS 0xa2 | ||
48 | #define LCD_REMOTE_CNTL_SELECT_VOLTAGE 0x81 | ||
49 | #define LCD_REMOTE_CNTL_INIT_LINE 0x40 | ||
50 | #define LCD_REMOTE_CNTL_SET_PAGE_ADDRESS 0xB0 | ||
51 | |||
52 | #define LCD_REMOTE_CNTL_HIGHCOL 0x10 /* Upper column address */ | ||
53 | #define LCD_REMOTE_CNTL_LOWCOL 0x00 /* Lower column address */ | ||
54 | |||
55 | #define CS_LO and_l(~0x00000004, &GPIO1_OUT) | ||
56 | #define CS_HI or_l(0x00000004, &GPIO1_OUT) | ||
57 | #define CLK_LO and_l(~0x10000000, &GPIO_OUT) | ||
58 | #define CLK_HI or_l(0x10000000, &GPIO_OUT) | ||
59 | #define DATA_LO and_l(~0x00040000, &GPIO1_OUT) | ||
60 | #define DATA_HI or_l(0x00040000, &GPIO1_OUT) | ||
61 | #define RS_LO and_l(~0x00010000, &GPIO_OUT) | ||
62 | #define RS_HI or_l(0x00010000, &GPIO_OUT) | ||
63 | |||
64 | #define SCROLLABLE_LINES 13 | ||
65 | 36 | ||
66 | /*** globals ***/ | 37 | /*** globals ***/ |
67 | 38 | ||
@@ -73,33 +44,6 @@ static int xmargin = 0; | |||
73 | static int ymargin = 0; | 44 | static int ymargin = 0; |
74 | static int curfont = FONT_SYSFIXED; | 45 | static int curfont = FONT_SYSFIXED; |
75 | 46 | ||
76 | #ifndef SIMULATOR | ||
77 | static int xoffset; /* needed for flip */ | ||
78 | |||
79 | /* timeout counter for deasserting /CS after access, <0 means not counting */ | ||
80 | static int cs_countdown IDATA_ATTR = 0; | ||
81 | #define CS_TIMEOUT (HZ/10) | ||
82 | |||
83 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
84 | /* If set to true, will prevent "ticking" to headphones. */ | ||
85 | static bool emireduce = false; | ||
86 | static int byte_delay = 0; | ||
87 | #endif | ||
88 | |||
89 | /* remote hotplug */ | ||
90 | static struct event_queue remote_scroll_queue; | ||
91 | #define REMOTE_INIT_LCD 1 | ||
92 | #define REMOTE_DEINIT_LCD 2 | ||
93 | |||
94 | static bool remote_initialized = false; | ||
95 | static int _remote_type = REMOTETYPE_UNPLUGGED; | ||
96 | |||
97 | /* cached settings values */ | ||
98 | static bool cached_invert = false; | ||
99 | static bool cached_flip = false; | ||
100 | static int cached_contrast = DEFAULT_REMOTE_CONTRAST_SETTING; | ||
101 | #endif | ||
102 | |||
103 | /* scrolling */ | 47 | /* scrolling */ |
104 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | 48 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ |
105 | static void scroll_thread(void); | 49 | static void scroll_thread(void); |
@@ -117,562 +61,10 @@ static const char scroll_tick_table[16] = { | |||
117 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 | 61 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 |
118 | }; | 62 | }; |
119 | 63 | ||
120 | /*** driver routines ***/ | 64 | /* remote hotplug */ |
121 | |||
122 | #ifndef SIMULATOR | ||
123 | |||
124 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
125 | static inline void _byte_delay(int delay) | ||
126 | { | ||
127 | asm ( | ||
128 | "move.l %[dly], %%d0 \n" | ||
129 | "ble.s 2f \n" | ||
130 | "1: \n" | ||
131 | "subq.l #1, %%d0 \n" | ||
132 | "bne.s 1b \n" | ||
133 | "2: \n" | ||
134 | : /* outputs */ | ||
135 | : /* inputs */ | ||
136 | [dly]"d"(delay) | ||
137 | : /* clobbers */ | ||
138 | "d0" | ||
139 | ); | ||
140 | } | ||
141 | #endif /* HAVE_REMOTE_LCD_TICKING */ | ||
142 | |||
143 | /* Standard low-level byte writer. Requires CLK low on entry */ | ||
144 | static inline void _write_byte(unsigned data) | ||
145 | { | ||
146 | asm volatile ( | ||
147 | "move.l (%[gpo1]), %%d0 \n" /* Get current state of data line */ | ||
148 | "and.l %[dbit], %%d0 \n" | ||
149 | "beq.s 1f \n" /* and set it as previous-state bit */ | ||
150 | "bset #8, %[data] \n" | ||
151 | "1: \n" | ||
152 | "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */ | ||
153 | "lsr.l #1, %%d0 \n" /* with 1's where the data changes from the */ | ||
154 | "eor.l %%d0, %[data] \n" /* previous state, and 0's where it doesn't */ | ||
155 | "swap %[data] \n" /* Shift data to upper byte */ | ||
156 | "lsl.l #8, %[data] \n" | ||
157 | |||
158 | "lsl.l #1,%[data] \n" /* Shift out MSB */ | ||
159 | "bcc.s 1f \n" | ||
160 | "eor.l %[dbit], (%[gpo1]) \n" /* 1: flip DATA */ | ||
161 | "1: \n" | ||
162 | "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */ | ||
163 | "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */ | ||
164 | |||
165 | "lsl.l #1,%[data] \n" /* ..unrolled.. */ | ||
166 | "bcc.s 1f \n" | ||
167 | "eor.l %[dbit], (%[gpo1]) \n" | ||
168 | "1: \n" | ||
169 | "eor.l %[cbit], (%[gpo0]) \n" | ||
170 | "eor.l %[cbit], (%[gpo0]) \n" | ||
171 | |||
172 | "lsl.l #1,%[data] \n" | ||
173 | "bcc.s 1f \n" | ||
174 | "eor.l %[dbit], (%[gpo1]) \n" | ||
175 | "1: \n" | ||
176 | "eor.l %[cbit], (%[gpo0]) \n" | ||
177 | "eor.l %[cbit], (%[gpo0]) \n" | ||
178 | |||
179 | "lsl.l #1,%[data] \n" | ||
180 | "bcc.s 1f \n" | ||
181 | "eor.l %[dbit], (%[gpo1]) \n" | ||
182 | "1: \n" | ||
183 | "eor.l %[cbit], (%[gpo0]) \n" | ||
184 | "eor.l %[cbit], (%[gpo0]) \n" | ||
185 | |||
186 | "lsl.l #1,%[data] \n" | ||
187 | "bcc.s 1f \n" | ||
188 | "eor.l %[dbit], (%[gpo1]) \n" | ||
189 | "1: \n" | ||
190 | "eor.l %[cbit], (%[gpo0]) \n" | ||
191 | "eor.l %[cbit], (%[gpo0]) \n" | ||
192 | |||
193 | "lsl.l #1,%[data] \n" | ||
194 | "bcc.s 1f \n" | ||
195 | "eor.l %[dbit], (%[gpo1]) \n" | ||
196 | "1: \n" | ||
197 | "eor.l %[cbit], (%[gpo0]) \n" | ||
198 | "eor.l %[cbit], (%[gpo0]) \n" | ||
199 | |||
200 | "lsl.l #1,%[data] \n" | ||
201 | "bcc.s 1f \n" | ||
202 | "eor.l %[dbit], (%[gpo1]) \n" | ||
203 | "1: \n" | ||
204 | "eor.l %[cbit], (%[gpo0]) \n" | ||
205 | "eor.l %[cbit], (%[gpo0]) \n" | ||
206 | |||
207 | "lsl.l #1,%[data] \n" | ||
208 | "bcc.s 1f \n" | ||
209 | "eor.l %[dbit], (%[gpo1]) \n" | ||
210 | "1: \n" | ||
211 | "eor.l %[cbit], (%[gpo0]) \n" | ||
212 | "eor.l %[cbit], (%[gpo0]) \n" | ||
213 | : /* outputs */ | ||
214 | [data]"+d"(data) | ||
215 | : /* inputs */ | ||
216 | [gpo0]"a"(&GPIO_OUT), | ||
217 | [cbit]"d"(0x10000000), | ||
218 | [gpo1]"a"(&GPIO1_OUT), | ||
219 | [dbit]"d"(0x00040000) | ||
220 | : /* clobbers */ | ||
221 | "d0" | ||
222 | ); | ||
223 | } | ||
224 | |||
225 | /* Fast low-level byte writer. Don't use with high CPU clock. | ||
226 | * Requires CLK low on entry */ | ||
227 | static inline void _write_fast(unsigned data) | ||
228 | { | ||
229 | asm volatile ( | ||
230 | "move.w %%sr,%%d3 \n" /* Get current interrupt level */ | ||
231 | "move.w #0x2700,%%sr \n" /* Disable interrupts */ | ||
232 | |||
233 | "move.l (%[gpo1]), %%d0 \n" /* Get current state of data port */ | ||
234 | "move.l %%d0, %%d1 \n" | ||
235 | "and.l %[dbit], %%d1 \n" /* Check current state of data line */ | ||
236 | "beq.s 1f \n" /* and set it as previous-state bit */ | ||
237 | "bset #8, %[data] \n" | ||
238 | "1: \n" | ||
239 | "move.l %[data], %%d1 \n" /* Compute the 'bit derivative', i.e. a value */ | ||
240 | "lsr.l #1, %%d1 \n" /* with 1's where the data changes from the */ | ||
241 | "eor.l %%d1, %[data] \n" /* previous state, and 0's where it doesn't */ | ||
242 | "swap %[data] \n" /* Shift data to upper byte */ | ||
243 | "lsl.l #8, %[data] \n" | ||
244 | |||
245 | "move.l (%[gpo0]), %%d1 \n" /* Get current state of clock port */ | ||
246 | "move.l %[cbit], %%d2 \n" /* Precalculate opposite state of clock line */ | ||
247 | "eor.l %%d1, %%d2 \n" | ||
248 | |||
249 | "lsl.l #1,%[data] \n" /* Shift out MSB */ | ||
250 | "bcc.s 1f \n" | ||
251 | "eor.l %[dbit], %%d0 \n" /* 1: flip data bit */ | ||
252 | "move.l %%d0, (%[gpo1]) \n" /* and output new DATA state */ | ||
253 | "1: \n" | ||
254 | "move.l %%d2, (%[gpo0]) \n" /* Set CLK */ | ||
255 | "move.l %%d1, (%[gpo0]) \n" /* Reset CLK */ | ||
256 | |||
257 | "lsl.l #1,%[data] \n" /* ..unrolled.. */ | ||
258 | "bcc.s 1f \n" | ||
259 | "eor.l %[dbit], %%d0 \n" | ||
260 | "move.l %%d0, (%[gpo1]) \n" | ||
261 | "1: \n" | ||
262 | "move.l %%d2, (%[gpo0]) \n" | ||
263 | "move.l %%d1, (%[gpo0]) \n" | ||
264 | |||
265 | "lsl.l #1,%[data] \n" | ||
266 | "bcc.s 1f \n" | ||
267 | "eor.l %[dbit], %%d0 \n" | ||
268 | "move.l %%d0, (%[gpo1]) \n" | ||
269 | "1: \n" | ||
270 | "move.l %%d2, (%[gpo0]) \n" | ||
271 | "move.l %%d1, (%[gpo0]) \n" | ||
272 | |||
273 | "lsl.l #1,%[data] \n" | ||
274 | "bcc.s 1f \n" | ||
275 | "eor.l %[dbit], %%d0 \n" | ||
276 | "move.l %%d0, (%[gpo1]) \n" | ||
277 | "1: \n" | ||
278 | "move.l %%d2, (%[gpo0]) \n" | ||
279 | "move.l %%d1, (%[gpo0]) \n" | ||
280 | |||
281 | "lsl.l #1,%[data] \n" | ||
282 | "bcc.s 1f \n" | ||
283 | "eor.l %[dbit], %%d0 \n" | ||
284 | "move.l %%d0, (%[gpo1]) \n" | ||
285 | "1: \n" | ||
286 | "move.l %%d2, (%[gpo0]) \n" | ||
287 | "move.l %%d1, (%[gpo0]) \n" | ||
288 | |||
289 | "lsl.l #1,%[data] \n" | ||
290 | "bcc.s 1f \n" | ||
291 | "eor.l %[dbit], %%d0 \n" | ||
292 | "move.l %%d0, (%[gpo1]) \n" | ||
293 | "1: \n" | ||
294 | "move.l %%d2, (%[gpo0]) \n" | ||
295 | "move.l %%d1, (%[gpo0]) \n" | ||
296 | |||
297 | "lsl.l #1,%[data] \n" | ||
298 | "bcc.s 1f \n" | ||
299 | "eor.l %[dbit], %%d0 \n" | ||
300 | "move.l %%d0, (%[gpo1]) \n" | ||
301 | "1: \n" | ||
302 | "move.l %%d2, (%[gpo0]) \n" | ||
303 | "move.l %%d1, (%[gpo0]) \n" | ||
304 | |||
305 | "lsl.l #1,%[data] \n" | ||
306 | "bcc.s 1f \n" | ||
307 | "eor.l %[dbit], %%d0 \n" | ||
308 | "move.l %%d0, (%[gpo1]) \n" | ||
309 | "1: \n" | ||
310 | "move.l %%d2, (%[gpo0]) \n" | ||
311 | "move.l %%d1, (%[gpo0]) \n" | ||
312 | |||
313 | "move.w %%d3, %%sr \n" /* Restore interrupt level */ | ||
314 | : /* outputs */ | ||
315 | [data]"+d"(data) | ||
316 | : /* inputs */ | ||
317 | [gpo0]"a"(&GPIO_OUT), | ||
318 | [cbit]"i"(0x10000000), | ||
319 | [gpo1]"a"(&GPIO1_OUT), | ||
320 | [dbit]"d"(0x00040000) | ||
321 | : /* clobbers */ | ||
322 | "d0", "d1", "d2", "d3" | ||
323 | ); | ||
324 | } | ||
325 | |||
326 | void lcd_remote_write_command(int cmd) | ||
327 | { | ||
328 | cs_countdown = 0; | ||
329 | RS_LO; | ||
330 | CS_LO; | ||
331 | |||
332 | _write_byte(cmd); | ||
333 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
334 | _byte_delay(byte_delay - 148); | ||
335 | #endif | ||
336 | |||
337 | cs_countdown = CS_TIMEOUT; | ||
338 | } | ||
339 | |||
340 | void lcd_remote_write_command_ex(int cmd, int data) | ||
341 | { | ||
342 | cs_countdown = 0; | ||
343 | RS_LO; | ||
344 | CS_LO; | ||
345 | |||
346 | _write_byte(cmd); | ||
347 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
348 | _byte_delay(byte_delay - 148); | ||
349 | #endif | ||
350 | _write_byte(data); | ||
351 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
352 | _byte_delay(byte_delay - 148); | ||
353 | #endif | ||
354 | |||
355 | cs_countdown = CS_TIMEOUT; | ||
356 | } | ||
357 | |||
358 | void lcd_remote_write_data(const unsigned char* p_bytes, int count) ICODE_ATTR; | ||
359 | void lcd_remote_write_data(const unsigned char* p_bytes, int count) | ||
360 | { | ||
361 | const unsigned char *p_end = p_bytes + count; | ||
362 | |||
363 | cs_countdown = 0; | ||
364 | RS_HI; | ||
365 | CS_LO; | ||
366 | |||
367 | /* This is safe as long as lcd_remote_write_data() isn't called from within | ||
368 | * an ISR. */ | ||
369 | if (cpu_frequency < 50000000) | ||
370 | { | ||
371 | while (p_bytes < p_end) | ||
372 | { | ||
373 | _write_fast(*p_bytes++); | ||
374 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
375 | _byte_delay(byte_delay - 87); | ||
376 | #endif | ||
377 | } | ||
378 | } | ||
379 | else | ||
380 | { | ||
381 | while (p_bytes < p_end) | ||
382 | { | ||
383 | _write_byte(*p_bytes++); | ||
384 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
385 | _byte_delay(byte_delay - 148); | ||
386 | #endif | ||
387 | } | ||
388 | } | ||
389 | |||
390 | cs_countdown = CS_TIMEOUT; | ||
391 | } | ||
392 | #endif /* !SIMULATOR */ | ||
393 | |||
394 | /*** hardware configuration ***/ | ||
395 | |||
396 | int lcd_remote_default_contrast(void) | ||
397 | { | ||
398 | return DEFAULT_REMOTE_CONTRAST_SETTING; | ||
399 | } | ||
400 | |||
401 | #ifndef SIMULATOR | 65 | #ifndef SIMULATOR |
402 | 66 | struct event_queue remote_scroll_queue; | |
403 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
404 | void lcd_remote_emireduce(bool state) | ||
405 | { | ||
406 | emireduce = state; | ||
407 | } | ||
408 | #endif | ||
409 | |||
410 | void lcd_remote_powersave(bool on) | ||
411 | { | ||
412 | if (remote_initialized) | ||
413 | { | ||
414 | lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | (on ? 0 : 1)); | ||
415 | lcd_remote_write_command(LCD_REMOTE_CNTL_ENTIRE_ON_OFF | (on ? 1 : 0)); | ||
416 | } | ||
417 | } | ||
418 | |||
419 | void lcd_remote_set_contrast(int val) | ||
420 | { | ||
421 | cached_contrast = val; | ||
422 | if (remote_initialized) | ||
423 | lcd_remote_write_command_ex(LCD_REMOTE_CNTL_SELECT_VOLTAGE, val); | ||
424 | } | ||
425 | |||
426 | void lcd_remote_set_invert_display(bool yesno) | ||
427 | { | ||
428 | cached_invert = yesno; | ||
429 | if (remote_initialized) | ||
430 | lcd_remote_write_command(LCD_REMOTE_CNTL_REVERSE_ON_OFF | (yesno?1:0)); | ||
431 | } | ||
432 | |||
433 | /* turn the display upside down (call lcd_remote_update() afterwards) */ | ||
434 | void lcd_remote_set_flip(bool yesno) | ||
435 | { | ||
436 | cached_flip = yesno; | ||
437 | if (yesno) | ||
438 | { | ||
439 | xoffset = 0; | ||
440 | if (remote_initialized) | ||
441 | { | ||
442 | lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_NORMAL); | ||
443 | lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_NORMAL); | ||
444 | } | ||
445 | } | ||
446 | else | ||
447 | { | ||
448 | xoffset = 132 - LCD_REMOTE_WIDTH; | ||
449 | if (remote_initialized) | ||
450 | { | ||
451 | lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_REVERSE); | ||
452 | lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_REVERSE); | ||
453 | } | ||
454 | } | ||
455 | } | ||
456 | |||
457 | /* The actual LCD init */ | ||
458 | static void remote_lcd_init(void) | ||
459 | { | ||
460 | CS_HI; | ||
461 | CLK_LO; | ||
462 | lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0); | ||
463 | |||
464 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x5); | ||
465 | sleep(1); | ||
466 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x6); | ||
467 | sleep(1); | ||
468 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x7); | ||
469 | |||
470 | lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_REGULATOR | 0x4); // 0x4 Select regulator @ 5.0 (default); | ||
471 | |||
472 | sleep(1); | ||
473 | |||
474 | lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line | ||
475 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | 0x0); // page address | ||
476 | lcd_remote_write_command_ex(0x10, 0x00); // Column MSB + LSB | ||
477 | |||
478 | lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | 1); | ||
479 | |||
480 | remote_initialized = true; | ||
481 | |||
482 | lcd_remote_set_flip(cached_flip); | ||
483 | lcd_remote_set_contrast(cached_contrast); | ||
484 | lcd_remote_set_invert_display(cached_invert); | ||
485 | } | ||
486 | |||
487 | bool remote_detect(void) | ||
488 | { | ||
489 | return (GPIO_READ & 0x40000000)?false:true; | ||
490 | } | ||
491 | |||
492 | int remote_type(void) | ||
493 | { | ||
494 | return _remote_type; | ||
495 | } | ||
496 | |||
497 | /* Monitor remote hotswap */ | ||
498 | static void remote_tick(void) | ||
499 | { | ||
500 | static bool last_status = false; | ||
501 | static int countdown = 0; | ||
502 | static int init_delay = 0; | ||
503 | bool current_status; | ||
504 | int val; | ||
505 | int level; | ||
506 | |||
507 | current_status = remote_detect(); | ||
508 | /* Only report when the status has changed */ | ||
509 | if (current_status != last_status) | ||
510 | { | ||
511 | last_status = current_status; | ||
512 | countdown = current_status ? 20*HZ : 1; | ||
513 | } | ||
514 | else | ||
515 | { | ||
516 | /* Count down until it gets negative */ | ||
517 | if (countdown >= 0) | ||
518 | countdown--; | ||
519 | |||
520 | if (current_status) | ||
521 | { | ||
522 | if (!(countdown % 8)) | ||
523 | { | ||
524 | /* Determine which type of remote it is */ | ||
525 | level = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
526 | val = adc_scan(ADC_REMOTEDETECT); | ||
527 | set_irq_level(level); | ||
528 | |||
529 | if (val < ADCVAL_H100_LCD_REMOTE_HOLD) | ||
530 | { | ||
531 | if (val < ADCVAL_H100_LCD_REMOTE) | ||
532 | if (val < ADCVAL_H300_LCD_REMOTE) | ||
533 | _remote_type = REMOTETYPE_H300_LCD; /* hold off */ | ||
534 | else | ||
535 | _remote_type = REMOTETYPE_H100_LCD; /* hold off */ | ||
536 | else | ||
537 | if (val < ADCVAL_H300_LCD_REMOTE_HOLD) | ||
538 | _remote_type = REMOTETYPE_H300_LCD; /* hold on */ | ||
539 | else | ||
540 | _remote_type = REMOTETYPE_H100_LCD; /* hold on */ | ||
541 | |||
542 | if (--init_delay <= 0) | ||
543 | { | ||
544 | queue_post(&remote_scroll_queue, REMOTE_INIT_LCD, 0); | ||
545 | init_delay = 6; | ||
546 | } | ||
547 | } | ||
548 | else | ||
549 | { | ||
550 | _remote_type = REMOTETYPE_H300_NONLCD; /* hold on or off */ | ||
551 | } | ||
552 | } | ||
553 | } | ||
554 | else | ||
555 | { | ||
556 | if (countdown == 0) | ||
557 | { | ||
558 | _remote_type = REMOTETYPE_UNPLUGGED; | ||
559 | |||
560 | queue_post(&remote_scroll_queue, REMOTE_DEINIT_LCD, 0); | ||
561 | } | ||
562 | } | ||
563 | } | ||
564 | |||
565 | /* handle chip select timeout */ | ||
566 | if (cs_countdown >= 0) | ||
567 | cs_countdown--; | ||
568 | if (cs_countdown == 0) | ||
569 | CS_HI; | ||
570 | } | ||
571 | #endif /* !SIMULATOR */ | ||
572 | |||
573 | /* LCD init */ | ||
574 | #ifdef SIMULATOR | ||
575 | |||
576 | void lcd_remote_init(void) | ||
577 | { | ||
578 | create_thread(scroll_thread, scroll_stack, | ||
579 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)); | ||
580 | } | ||
581 | #else /* !SIMULATOR */ | ||
582 | |||
583 | /* Initialise ports and kick off monitor */ | ||
584 | void lcd_remote_init(void) | ||
585 | { | ||
586 | #ifdef IRIVER_H300_SERIES | ||
587 | or_l(0x10010000, &GPIO_FUNCTION); /* GPIO16: RS | ||
588 | GPIO28: CLK */ | ||
589 | |||
590 | or_l(0x00040006, &GPIO1_FUNCTION); /* GPO33: Backlight | ||
591 | GPIO34: CS | ||
592 | GPIO50: Data */ | ||
593 | or_l(0x10010000, &GPIO_ENABLE); | ||
594 | or_l(0x00040006, &GPIO1_ENABLE); | ||
595 | #else | ||
596 | or_l(0x10010800, &GPIO_FUNCTION); /* GPIO11: Backlight | ||
597 | GPIO16: RS | ||
598 | GPIO28: CLK */ | ||
599 | |||
600 | or_l(0x00040004, &GPIO1_FUNCTION); /* GPIO34: CS | ||
601 | GPIO50: Data */ | ||
602 | or_l(0x10010800, &GPIO_ENABLE); | ||
603 | or_l(0x00040004, &GPIO1_ENABLE); | ||
604 | #endif | 67 | #endif |
605 | lcd_remote_clear_display(); | ||
606 | |||
607 | /* private queue */ | ||
608 | queue_init(&remote_scroll_queue, false); | ||
609 | tick_add_task(remote_tick); | ||
610 | create_thread(scroll_thread, scroll_stack, | ||
611 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)); | ||
612 | } | ||
613 | |||
614 | /*** update functions ***/ | ||
615 | |||
616 | /* Update the display. | ||
617 | This must be called after all other LCD functions that change the display. */ | ||
618 | void lcd_remote_update(void) ICODE_ATTR; | ||
619 | void lcd_remote_update(void) | ||
620 | { | ||
621 | int y; | ||
622 | |||
623 | if (!remote_initialized) | ||
624 | return; | ||
625 | |||
626 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
627 | /* Adjust byte delay for emi reduction. */ | ||
628 | byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0; | ||
629 | #endif | ||
630 | |||
631 | /* Copy display bitmap to hardware */ | ||
632 | for (y = 0; y < LCD_REMOTE_FBHEIGHT; y++) | ||
633 | { | ||
634 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); | ||
635 | lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | ((xoffset >> 4) & 0xf)); | ||
636 | lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | (xoffset & 0xf)); | ||
637 | lcd_remote_write_data(lcd_remote_framebuffer[y], LCD_REMOTE_WIDTH); | ||
638 | } | ||
639 | } | ||
640 | |||
641 | /* Update a fraction of the display. */ | ||
642 | void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR; | ||
643 | void lcd_remote_update_rect(int x, int y, int width, int height) | ||
644 | { | ||
645 | int ymax; | ||
646 | |||
647 | if (!remote_initialized) | ||
648 | return; | ||
649 | |||
650 | /* The Y coordinates have to work on even 8 pixel rows */ | ||
651 | ymax = (y + height-1) >> 3; | ||
652 | y >>= 3; | ||
653 | |||
654 | if(x + width > LCD_REMOTE_WIDTH) | ||
655 | width = LCD_REMOTE_WIDTH - x; | ||
656 | if (width <= 0) | ||
657 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | ||
658 | if(ymax >= LCD_REMOTE_FBHEIGHT) | ||
659 | ymax = LCD_REMOTE_FBHEIGHT-1; | ||
660 | |||
661 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
662 | /* Adjust byte delay for emi reduction */ | ||
663 | byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0; | ||
664 | #endif | ||
665 | |||
666 | /* Copy specified rectange bitmap to hardware */ | ||
667 | for (; y <= ymax; y++) | ||
668 | { | ||
669 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); | ||
670 | lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | (((x+xoffset) >> 4) & 0xf)); | ||
671 | lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | ((x+xoffset) & 0xf)); | ||
672 | lcd_remote_write_data(&lcd_remote_framebuffer[y][x], width); | ||
673 | } | ||
674 | } | ||
675 | #endif /* !SIMULATOR */ | ||
676 | 68 | ||
677 | /*** parameter handling ***/ | 69 | /*** parameter handling ***/ |
678 | 70 | ||
@@ -1335,12 +727,12 @@ void lcd_remote_puts_scroll(int x, int y, const unsigned char *string) | |||
1335 | 727 | ||
1336 | void lcd_remote_puts_scroll_style(int x, int y, const unsigned char *string, int style) | 728 | void lcd_remote_puts_scroll_style(int x, int y, const unsigned char *string, int style) |
1337 | { | 729 | { |
1338 | lcd_remote_puts_scroll_style_offset(x, y, string, style, 0); | 730 | lcd_remote_puts_scroll_style_offset(x, y, string, style, 0); |
1339 | } | 731 | } |
1340 | 732 | ||
1341 | void lcd_remote_puts_scroll_offset(int x, int y, const unsigned char *string, int offset) | 733 | void lcd_remote_puts_scroll_offset(int x, int y, const unsigned char *string, int offset) |
1342 | { | 734 | { |
1343 | lcd_remote_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); | 735 | lcd_remote_puts_scroll_style_offset(x, y, string, STYLE_DEFAULT, offset); |
1344 | } | 736 | } |
1345 | 737 | ||
1346 | void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *string, | 738 | void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *string, |
@@ -1430,14 +822,12 @@ static void scroll_thread(void) | |||
1430 | switch (ev.id) | 822 | switch (ev.id) |
1431 | { | 823 | { |
1432 | case REMOTE_INIT_LCD: | 824 | case REMOTE_INIT_LCD: |
1433 | remote_lcd_init(); | 825 | lcd_remote_on(); |
1434 | lcd_remote_update(); | 826 | lcd_remote_update(); |
1435 | break; | 827 | break; |
1436 | 828 | ||
1437 | case REMOTE_DEINIT_LCD: | 829 | case REMOTE_DEINIT_LCD: |
1438 | CLK_LO; | 830 | lcd_remote_off(); |
1439 | CS_HI; | ||
1440 | remote_initialized = false; | ||
1441 | break; | 831 | break; |
1442 | } | 832 | } |
1443 | 833 | ||
@@ -1503,3 +893,15 @@ static void scroll_thread(void) | |||
1503 | } | 893 | } |
1504 | } | 894 | } |
1505 | 895 | ||
896 | /* LCD init */ | ||
897 | void lcd_remote_init(void) | ||
898 | { | ||
899 | #ifndef SIMULATOR | ||
900 | /* Call device specific init */ | ||
901 | lcd_remote_init_device(); | ||
902 | /* private queue */ | ||
903 | queue_init(&remote_scroll_queue, false); | ||
904 | #endif | ||
905 | create_thread(scroll_thread, scroll_stack, | ||
906 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE)); | ||
907 | } | ||
diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h index 7ed52bd188..08accf7116 100644 --- a/firmware/export/lcd-remote.h +++ b/firmware/export/lcd-remote.h | |||
@@ -27,13 +27,20 @@ | |||
27 | 27 | ||
28 | #ifdef HAVE_REMOTE_LCD | 28 | #ifdef HAVE_REMOTE_LCD |
29 | 29 | ||
30 | #if defined(TARGET_TREE) && !defined(SIMULATOR) | ||
31 | #include "lcd-remote-target.h" | ||
32 | #endif | ||
33 | |||
30 | #if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) | 34 | #if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) |
31 | #define REMOTETYPE_UNPLUGGED 0 | 35 | #define REMOTETYPE_UNPLUGGED 0 |
32 | #define REMOTETYPE_H100_LCD 1 | 36 | #define REMOTETYPE_H100_LCD 1 |
33 | #define REMOTETYPE_H300_LCD 2 | 37 | #define REMOTETYPE_H300_LCD 2 |
34 | #define REMOTETYPE_H300_NONLCD 3 | 38 | #define REMOTETYPE_H300_NONLCD 3 |
35 | extern int remote_type(void); | 39 | int remote_type(void); |
36 | extern bool remote_detect(void); | 40 | #endif |
41 | |||
42 | #ifndef SIMULATOR | ||
43 | extern struct event_queue remote_scroll_queue; | ||
37 | #endif | 44 | #endif |
38 | 45 | ||
39 | #define STYLE_DEFAULT 0 | 46 | #define STYLE_DEFAULT 0 |
@@ -105,7 +112,6 @@ extern fb_remote_data lcd_remote_framebuffer[LCD_REMOTE_FBHEIGHT][LCD_REMOTE_FBW | |||
105 | extern void lcd_remote_init(void); | 112 | extern void lcd_remote_init(void); |
106 | extern int lcd_remote_default_contrast(void); | 113 | extern int lcd_remote_default_contrast(void); |
107 | extern void lcd_remote_set_contrast(int val); | 114 | extern void lcd_remote_set_contrast(int val); |
108 | extern void lcd_remote_emireduce(bool state); | ||
109 | 115 | ||
110 | extern void lcd_remote_clear_display(void); | 116 | extern void lcd_remote_clear_display(void); |
111 | extern void lcd_remote_puts(int x, int y, const unsigned char *str); | 117 | extern void lcd_remote_puts(int x, int y, const unsigned char *str); |
diff --git a/firmware/target/coldfire/iriver/lcd-remote-iriver.c b/firmware/target/coldfire/iriver/lcd-remote-iriver.c new file mode 100644 index 0000000000..cdc5acacca --- /dev/null +++ b/firmware/target/coldfire/iriver/lcd-remote-iriver.c | |||
@@ -0,0 +1,610 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 by Richard S. La Charité III | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "config.h" | ||
21 | #include "system.h" | ||
22 | #include "kernel.h" | ||
23 | #include "lcd-remote.h" | ||
24 | |||
25 | /*** definitions ***/ | ||
26 | |||
27 | #define LCD_REMOTE_CNTL_ADC_NORMAL 0xa0 | ||
28 | #define LCD_REMOTE_CNTL_ADC_REVERSE 0xa1 | ||
29 | #define LCD_REMOTE_CNTL_SHL_NORMAL 0xc0 | ||
30 | #define LCD_REMOTE_CNTL_SHL_REVERSE 0xc8 | ||
31 | #define LCD_REMOTE_CNTL_DISPLAY_ON_OFF 0xae | ||
32 | #define LCD_REMOTE_CNTL_ENTIRE_ON_OFF 0xa4 | ||
33 | #define LCD_REMOTE_CNTL_REVERSE_ON_OFF 0xa6 | ||
34 | #define LCD_REMOTE_CNTL_NOP 0xe3 | ||
35 | #define LCD_REMOTE_CNTL_POWER_CONTROL 0x2b | ||
36 | #define LCD_REMOTE_CNTL_SELECT_REGULATOR 0x20 | ||
37 | #define LCD_REMOTE_CNTL_SELECT_BIAS 0xa2 | ||
38 | #define LCD_REMOTE_CNTL_SELECT_VOLTAGE 0x81 | ||
39 | #define LCD_REMOTE_CNTL_INIT_LINE 0x40 | ||
40 | #define LCD_REMOTE_CNTL_SET_PAGE_ADDRESS 0xB0 | ||
41 | |||
42 | #define LCD_REMOTE_CNTL_HIGHCOL 0x10 /* Upper column address */ | ||
43 | #define LCD_REMOTE_CNTL_LOWCOL 0x00 /* Lower column address */ | ||
44 | |||
45 | #define CS_LO and_l(~0x00000004, &GPIO1_OUT) | ||
46 | #define CS_HI or_l(0x00000004, &GPIO1_OUT) | ||
47 | #define CLK_LO and_l(~0x10000000, &GPIO_OUT) | ||
48 | #define CLK_HI or_l(0x10000000, &GPIO_OUT) | ||
49 | #define DATA_LO and_l(~0x00040000, &GPIO1_OUT) | ||
50 | #define DATA_HI or_l(0x00040000, &GPIO1_OUT) | ||
51 | #define RS_LO and_l(~0x00010000, &GPIO_OUT) | ||
52 | #define RS_HI or_l(0x00010000, &GPIO_OUT) | ||
53 | |||
54 | static int xoffset; /* needed for flip */ | ||
55 | |||
56 | /* timeout counter for deasserting /CS after access, <0 means not counting */ | ||
57 | static int cs_countdown IDATA_ATTR = 0; | ||
58 | #define CS_TIMEOUT (HZ/10) | ||
59 | |||
60 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
61 | /* If set to true, will prevent "ticking" to headphones. */ | ||
62 | static bool emireduce = false; | ||
63 | static int byte_delay = 0; | ||
64 | #endif | ||
65 | |||
66 | bool remote_initialized = false; | ||
67 | static int _remote_type = REMOTETYPE_UNPLUGGED; | ||
68 | |||
69 | /* cached settings values */ | ||
70 | static bool cached_invert = false; | ||
71 | static bool cached_flip = false; | ||
72 | static int cached_contrast = DEFAULT_REMOTE_CONTRAST_SETTING; | ||
73 | |||
74 | static void remote_tick(void); | ||
75 | |||
76 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
77 | static inline void _byte_delay(int delay) | ||
78 | { | ||
79 | asm ( | ||
80 | "move.l %[dly], %%d0 \n" | ||
81 | "ble.s 2f \n" | ||
82 | "1: \n" | ||
83 | "subq.l #1, %%d0 \n" | ||
84 | "bne.s 1b \n" | ||
85 | "2: \n" | ||
86 | : /* outputs */ | ||
87 | : /* inputs */ | ||
88 | [dly]"d"(delay) | ||
89 | : /* clobbers */ | ||
90 | "d0" | ||
91 | ); | ||
92 | } | ||
93 | #endif /* HAVE_REMOTE_LCD_TICKING */ | ||
94 | |||
95 | /* Standard low-level byte writer. Requires CLK low on entry */ | ||
96 | static inline void _write_byte(unsigned data) | ||
97 | { | ||
98 | asm volatile ( | ||
99 | "move.l (%[gpo1]), %%d0 \n" /* Get current state of data line */ | ||
100 | "and.l %[dbit], %%d0 \n" | ||
101 | "beq.s 1f \n" /* and set it as previous-state bit */ | ||
102 | "bset #8, %[data] \n" | ||
103 | "1: \n" | ||
104 | "move.l %[data], %%d0 \n" /* Compute the 'bit derivative', i.e. a value */ | ||
105 | "lsr.l #1, %%d0 \n" /* with 1's where the data changes from the */ | ||
106 | "eor.l %%d0, %[data] \n" /* previous state, and 0's where it doesn't */ | ||
107 | "swap %[data] \n" /* Shift data to upper byte */ | ||
108 | "lsl.l #8, %[data] \n" | ||
109 | |||
110 | "lsl.l #1,%[data] \n" /* Shift out MSB */ | ||
111 | "bcc.s 1f \n" | ||
112 | "eor.l %[dbit], (%[gpo1]) \n" /* 1: flip DATA */ | ||
113 | "1: \n" | ||
114 | "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */ | ||
115 | "eor.l %[cbit], (%[gpo0]) \n" /* Flip CLK */ | ||
116 | |||
117 | "lsl.l #1,%[data] \n" /* ..unrolled.. */ | ||
118 | "bcc.s 1f \n" | ||
119 | "eor.l %[dbit], (%[gpo1]) \n" | ||
120 | "1: \n" | ||
121 | "eor.l %[cbit], (%[gpo0]) \n" | ||
122 | "eor.l %[cbit], (%[gpo0]) \n" | ||
123 | |||
124 | "lsl.l #1,%[data] \n" | ||
125 | "bcc.s 1f \n" | ||
126 | "eor.l %[dbit], (%[gpo1]) \n" | ||
127 | "1: \n" | ||
128 | "eor.l %[cbit], (%[gpo0]) \n" | ||
129 | "eor.l %[cbit], (%[gpo0]) \n" | ||
130 | |||
131 | "lsl.l #1,%[data] \n" | ||
132 | "bcc.s 1f \n" | ||
133 | "eor.l %[dbit], (%[gpo1]) \n" | ||
134 | "1: \n" | ||
135 | "eor.l %[cbit], (%[gpo0]) \n" | ||
136 | "eor.l %[cbit], (%[gpo0]) \n" | ||
137 | |||
138 | "lsl.l #1,%[data] \n" | ||
139 | "bcc.s 1f \n" | ||
140 | "eor.l %[dbit], (%[gpo1]) \n" | ||
141 | "1: \n" | ||
142 | "eor.l %[cbit], (%[gpo0]) \n" | ||
143 | "eor.l %[cbit], (%[gpo0]) \n" | ||
144 | |||
145 | "lsl.l #1,%[data] \n" | ||
146 | "bcc.s 1f \n" | ||
147 | "eor.l %[dbit], (%[gpo1]) \n" | ||
148 | "1: \n" | ||
149 | "eor.l %[cbit], (%[gpo0]) \n" | ||
150 | "eor.l %[cbit], (%[gpo0]) \n" | ||
151 | |||
152 | "lsl.l #1,%[data] \n" | ||
153 | "bcc.s 1f \n" | ||
154 | "eor.l %[dbit], (%[gpo1]) \n" | ||
155 | "1: \n" | ||
156 | "eor.l %[cbit], (%[gpo0]) \n" | ||
157 | "eor.l %[cbit], (%[gpo0]) \n" | ||
158 | |||
159 | "lsl.l #1,%[data] \n" | ||
160 | "bcc.s 1f \n" | ||
161 | "eor.l %[dbit], (%[gpo1]) \n" | ||
162 | "1: \n" | ||
163 | "eor.l %[cbit], (%[gpo0]) \n" | ||
164 | "eor.l %[cbit], (%[gpo0]) \n" | ||
165 | : /* outputs */ | ||
166 | [data]"+d"(data) | ||
167 | : /* inputs */ | ||
168 | [gpo0]"a"(&GPIO_OUT), | ||
169 | [cbit]"d"(0x10000000), | ||
170 | [gpo1]"a"(&GPIO1_OUT), | ||
171 | [dbit]"d"(0x00040000) | ||
172 | : /* clobbers */ | ||
173 | "d0" | ||
174 | ); | ||
175 | } | ||
176 | |||
177 | /* Fast low-level byte writer. Don't use with high CPU clock. | ||
178 | * Requires CLK low on entry */ | ||
179 | static inline void _write_fast(unsigned data) | ||
180 | { | ||
181 | asm volatile ( | ||
182 | "move.w %%sr,%%d3 \n" /* Get current interrupt level */ | ||
183 | "move.w #0x2700,%%sr \n" /* Disable interrupts */ | ||
184 | |||
185 | "move.l (%[gpo1]), %%d0 \n" /* Get current state of data port */ | ||
186 | "move.l %%d0, %%d1 \n" | ||
187 | "and.l %[dbit], %%d1 \n" /* Check current state of data line */ | ||
188 | "beq.s 1f \n" /* and set it as previous-state bit */ | ||
189 | "bset #8, %[data] \n" | ||
190 | "1: \n" | ||
191 | "move.l %[data], %%d1 \n" /* Compute the 'bit derivative', i.e. a value */ | ||
192 | "lsr.l #1, %%d1 \n" /* with 1's where the data changes from the */ | ||
193 | "eor.l %%d1, %[data] \n" /* previous state, and 0's where it doesn't */ | ||
194 | "swap %[data] \n" /* Shift data to upper byte */ | ||
195 | "lsl.l #8, %[data] \n" | ||
196 | |||
197 | "move.l (%[gpo0]), %%d1 \n" /* Get current state of clock port */ | ||
198 | "move.l %[cbit], %%d2 \n" /* Precalculate opposite state of clock line */ | ||
199 | "eor.l %%d1, %%d2 \n" | ||
200 | |||
201 | "lsl.l #1,%[data] \n" /* Shift out MSB */ | ||
202 | "bcc.s 1f \n" | ||
203 | "eor.l %[dbit], %%d0 \n" /* 1: flip data bit */ | ||
204 | "move.l %%d0, (%[gpo1]) \n" /* and output new DATA state */ | ||
205 | "1: \n" | ||
206 | "move.l %%d2, (%[gpo0]) \n" /* Set CLK */ | ||
207 | "move.l %%d1, (%[gpo0]) \n" /* Reset CLK */ | ||
208 | |||
209 | "lsl.l #1,%[data] \n" /* ..unrolled.. */ | ||
210 | "bcc.s 1f \n" | ||
211 | "eor.l %[dbit], %%d0 \n" | ||
212 | "move.l %%d0, (%[gpo1]) \n" | ||
213 | "1: \n" | ||
214 | "move.l %%d2, (%[gpo0]) \n" | ||
215 | "move.l %%d1, (%[gpo0]) \n" | ||
216 | |||
217 | "lsl.l #1,%[data] \n" | ||
218 | "bcc.s 1f \n" | ||
219 | "eor.l %[dbit], %%d0 \n" | ||
220 | "move.l %%d0, (%[gpo1]) \n" | ||
221 | "1: \n" | ||
222 | "move.l %%d2, (%[gpo0]) \n" | ||
223 | "move.l %%d1, (%[gpo0]) \n" | ||
224 | |||
225 | "lsl.l #1,%[data] \n" | ||
226 | "bcc.s 1f \n" | ||
227 | "eor.l %[dbit], %%d0 \n" | ||
228 | "move.l %%d0, (%[gpo1]) \n" | ||
229 | "1: \n" | ||
230 | "move.l %%d2, (%[gpo0]) \n" | ||
231 | "move.l %%d1, (%[gpo0]) \n" | ||
232 | |||
233 | "lsl.l #1,%[data] \n" | ||
234 | "bcc.s 1f \n" | ||
235 | "eor.l %[dbit], %%d0 \n" | ||
236 | "move.l %%d0, (%[gpo1]) \n" | ||
237 | "1: \n" | ||
238 | "move.l %%d2, (%[gpo0]) \n" | ||
239 | "move.l %%d1, (%[gpo0]) \n" | ||
240 | |||
241 | "lsl.l #1,%[data] \n" | ||
242 | "bcc.s 1f \n" | ||
243 | "eor.l %[dbit], %%d0 \n" | ||
244 | "move.l %%d0, (%[gpo1]) \n" | ||
245 | "1: \n" | ||
246 | "move.l %%d2, (%[gpo0]) \n" | ||
247 | "move.l %%d1, (%[gpo0]) \n" | ||
248 | |||
249 | "lsl.l #1,%[data] \n" | ||
250 | "bcc.s 1f \n" | ||
251 | "eor.l %[dbit], %%d0 \n" | ||
252 | "move.l %%d0, (%[gpo1]) \n" | ||
253 | "1: \n" | ||
254 | "move.l %%d2, (%[gpo0]) \n" | ||
255 | "move.l %%d1, (%[gpo0]) \n" | ||
256 | |||
257 | "lsl.l #1,%[data] \n" | ||
258 | "bcc.s 1f \n" | ||
259 | "eor.l %[dbit], %%d0 \n" | ||
260 | "move.l %%d0, (%[gpo1]) \n" | ||
261 | "1: \n" | ||
262 | "move.l %%d2, (%[gpo0]) \n" | ||
263 | "move.l %%d1, (%[gpo0]) \n" | ||
264 | |||
265 | "move.w %%d3, %%sr \n" /* Restore interrupt level */ | ||
266 | : /* outputs */ | ||
267 | [data]"+d"(data) | ||
268 | : /* inputs */ | ||
269 | [gpo0]"a"(&GPIO_OUT), | ||
270 | [cbit]"i"(0x10000000), | ||
271 | [gpo1]"a"(&GPIO1_OUT), | ||
272 | [dbit]"d"(0x00040000) | ||
273 | : /* clobbers */ | ||
274 | "d0", "d1", "d2", "d3" | ||
275 | ); | ||
276 | } | ||
277 | |||
278 | void lcd_remote_write_command(int cmd) | ||
279 | { | ||
280 | cs_countdown = 0; | ||
281 | RS_LO; | ||
282 | CS_LO; | ||
283 | |||
284 | _write_byte(cmd); | ||
285 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
286 | _byte_delay(byte_delay - 148); | ||
287 | #endif | ||
288 | |||
289 | cs_countdown = CS_TIMEOUT; | ||
290 | } | ||
291 | |||
292 | void lcd_remote_write_command_ex(int cmd, int data) | ||
293 | { | ||
294 | cs_countdown = 0; | ||
295 | RS_LO; | ||
296 | CS_LO; | ||
297 | |||
298 | _write_byte(cmd); | ||
299 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
300 | _byte_delay(byte_delay - 148); | ||
301 | #endif | ||
302 | _write_byte(data); | ||
303 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
304 | _byte_delay(byte_delay - 148); | ||
305 | #endif | ||
306 | |||
307 | cs_countdown = CS_TIMEOUT; | ||
308 | } | ||
309 | |||
310 | void lcd_remote_write_data(const unsigned char* p_bytes, int count) ICODE_ATTR; | ||
311 | void lcd_remote_write_data(const unsigned char* p_bytes, int count) | ||
312 | { | ||
313 | const unsigned char *p_end = p_bytes + count; | ||
314 | |||
315 | cs_countdown = 0; | ||
316 | RS_HI; | ||
317 | CS_LO; | ||
318 | |||
319 | /* This is safe as long as lcd_remote_write_data() isn't called from within | ||
320 | * an ISR. */ | ||
321 | if (cpu_frequency < 50000000) | ||
322 | { | ||
323 | while (p_bytes < p_end) | ||
324 | { | ||
325 | _write_fast(*p_bytes++); | ||
326 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
327 | _byte_delay(byte_delay - 87); | ||
328 | #endif | ||
329 | } | ||
330 | } | ||
331 | else | ||
332 | { | ||
333 | while (p_bytes < p_end) | ||
334 | { | ||
335 | _write_byte(*p_bytes++); | ||
336 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
337 | _byte_delay(byte_delay - 148); | ||
338 | #endif | ||
339 | } | ||
340 | } | ||
341 | |||
342 | cs_countdown = CS_TIMEOUT; | ||
343 | } | ||
344 | |||
345 | /*** hardware configuration ***/ | ||
346 | |||
347 | int lcd_remote_default_contrast(void) | ||
348 | { | ||
349 | return DEFAULT_REMOTE_CONTRAST_SETTING; | ||
350 | } | ||
351 | |||
352 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
353 | void lcd_remote_emireduce(bool state) | ||
354 | { | ||
355 | emireduce = state; | ||
356 | } | ||
357 | #endif | ||
358 | |||
359 | void lcd_remote_powersave(bool on) | ||
360 | { | ||
361 | if (remote_initialized) | ||
362 | { | ||
363 | lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | (on ? 0 : 1)); | ||
364 | lcd_remote_write_command(LCD_REMOTE_CNTL_ENTIRE_ON_OFF | (on ? 1 : 0)); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | void lcd_remote_set_contrast(int val) | ||
369 | { | ||
370 | cached_contrast = val; | ||
371 | if (remote_initialized) | ||
372 | lcd_remote_write_command_ex(LCD_REMOTE_CNTL_SELECT_VOLTAGE, val); | ||
373 | } | ||
374 | |||
375 | void lcd_remote_set_invert_display(bool yesno) | ||
376 | { | ||
377 | cached_invert = yesno; | ||
378 | if (remote_initialized) | ||
379 | lcd_remote_write_command(LCD_REMOTE_CNTL_REVERSE_ON_OFF | (yesno?1:0)); | ||
380 | } | ||
381 | |||
382 | /* turn the display upside down (call lcd_remote_update() afterwards) */ | ||
383 | void lcd_remote_set_flip(bool yesno) | ||
384 | { | ||
385 | cached_flip = yesno; | ||
386 | if (yesno) | ||
387 | { | ||
388 | xoffset = 0; | ||
389 | if (remote_initialized) | ||
390 | { | ||
391 | lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_NORMAL); | ||
392 | lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_NORMAL); | ||
393 | } | ||
394 | } | ||
395 | else | ||
396 | { | ||
397 | xoffset = 132 - LCD_REMOTE_WIDTH; | ||
398 | if (remote_initialized) | ||
399 | { | ||
400 | lcd_remote_write_command(LCD_REMOTE_CNTL_ADC_REVERSE); | ||
401 | lcd_remote_write_command(LCD_REMOTE_CNTL_SHL_REVERSE); | ||
402 | } | ||
403 | } | ||
404 | } | ||
405 | |||
406 | bool remote_detect(void) | ||
407 | { | ||
408 | return (GPIO_READ & 0x40000000)?false:true; | ||
409 | } | ||
410 | |||
411 | int remote_type(void) | ||
412 | { | ||
413 | return _remote_type; | ||
414 | } | ||
415 | |||
416 | void lcd_remote_init_device(void) | ||
417 | { | ||
418 | #ifdef IRIVER_H300_SERIES | ||
419 | or_l(0x10010000, &GPIO_FUNCTION); /* GPIO16: RS | ||
420 | GPIO28: CLK */ | ||
421 | |||
422 | or_l(0x00040006, &GPIO1_FUNCTION); /* GPO33: Backlight | ||
423 | GPIO34: CS | ||
424 | GPIO50: Data */ | ||
425 | or_l(0x10010000, &GPIO_ENABLE); | ||
426 | or_l(0x00040006, &GPIO1_ENABLE); | ||
427 | #else | ||
428 | or_l(0x10010800, &GPIO_FUNCTION); /* GPIO11: Backlight | ||
429 | GPIO16: RS | ||
430 | GPIO28: CLK */ | ||
431 | |||
432 | or_l(0x00040004, &GPIO1_FUNCTION); /* GPIO34: CS | ||
433 | GPIO50: Data */ | ||
434 | or_l(0x10010800, &GPIO_ENABLE); | ||
435 | or_l(0x00040004, &GPIO1_ENABLE); | ||
436 | #endif | ||
437 | lcd_remote_clear_display(); | ||
438 | tick_add_task(remote_tick); | ||
439 | } | ||
440 | |||
441 | void lcd_remote_on(void) | ||
442 | { | ||
443 | CS_HI; | ||
444 | CLK_LO; | ||
445 | lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_BIAS | 0x0); | ||
446 | |||
447 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x5); | ||
448 | sleep(1); | ||
449 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x6); | ||
450 | sleep(1); | ||
451 | lcd_remote_write_command(LCD_REMOTE_CNTL_POWER_CONTROL | 0x7); | ||
452 | |||
453 | lcd_remote_write_command(LCD_REMOTE_CNTL_SELECT_REGULATOR | 0x4); // 0x4 Select regulator @ 5.0 (default); | ||
454 | |||
455 | sleep(1); | ||
456 | |||
457 | lcd_remote_write_command(LCD_REMOTE_CNTL_INIT_LINE | 0x0); // init line | ||
458 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | 0x0); // page address | ||
459 | lcd_remote_write_command_ex(0x10, 0x00); // Column MSB + LSB | ||
460 | |||
461 | lcd_remote_write_command(LCD_REMOTE_CNTL_DISPLAY_ON_OFF | 1); | ||
462 | |||
463 | remote_initialized = true; | ||
464 | |||
465 | lcd_remote_set_flip(cached_flip); | ||
466 | lcd_remote_set_contrast(cached_contrast); | ||
467 | lcd_remote_set_invert_display(cached_invert); | ||
468 | } | ||
469 | |||
470 | void lcd_remote_off(void) | ||
471 | { | ||
472 | remote_initialized = false; | ||
473 | CLK_LO; | ||
474 | CS_HI; | ||
475 | } | ||
476 | |||
477 | /* Monitor remote hotswap */ | ||
478 | static void remote_tick(void) | ||
479 | { | ||
480 | static bool last_status = false; | ||
481 | static int countdown = 0; | ||
482 | static int init_delay = 0; | ||
483 | bool current_status; | ||
484 | int val; | ||
485 | int level; | ||
486 | |||
487 | current_status = remote_detect(); | ||
488 | /* Only report when the status has changed */ | ||
489 | if (current_status != last_status) | ||
490 | { | ||
491 | last_status = current_status; | ||
492 | countdown = current_status ? 20*HZ : 1; | ||
493 | } | ||
494 | else | ||
495 | { | ||
496 | /* Count down until it gets negative */ | ||
497 | if (countdown >= 0) | ||
498 | countdown--; | ||
499 | |||
500 | if (current_status) | ||
501 | { | ||
502 | if (!(countdown % 8)) | ||
503 | { | ||
504 | /* Determine which type of remote it is */ | ||
505 | level = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
506 | val = adc_scan(ADC_REMOTEDETECT); | ||
507 | set_irq_level(level); | ||
508 | |||
509 | if (val < ADCVAL_H100_LCD_REMOTE_HOLD) | ||
510 | { | ||
511 | if (val < ADCVAL_H100_LCD_REMOTE) | ||
512 | if (val < ADCVAL_H300_LCD_REMOTE) | ||
513 | _remote_type = REMOTETYPE_H300_LCD; /* hold off */ | ||
514 | else | ||
515 | _remote_type = REMOTETYPE_H100_LCD; /* hold off */ | ||
516 | else | ||
517 | if (val < ADCVAL_H300_LCD_REMOTE_HOLD) | ||
518 | _remote_type = REMOTETYPE_H300_LCD; /* hold on */ | ||
519 | else | ||
520 | _remote_type = REMOTETYPE_H100_LCD; /* hold on */ | ||
521 | |||
522 | if (--init_delay <= 0) | ||
523 | { | ||
524 | queue_post(&remote_scroll_queue, REMOTE_INIT_LCD, 0); | ||
525 | init_delay = 6; | ||
526 | } | ||
527 | } | ||
528 | else | ||
529 | { | ||
530 | _remote_type = REMOTETYPE_H300_NONLCD; /* hold on or off */ | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | else | ||
535 | { | ||
536 | if (countdown == 0) | ||
537 | { | ||
538 | _remote_type = REMOTETYPE_UNPLUGGED; | ||
539 | |||
540 | queue_post(&remote_scroll_queue, REMOTE_DEINIT_LCD, 0); | ||
541 | } | ||
542 | } | ||
543 | } | ||
544 | |||
545 | /* handle chip select timeout */ | ||
546 | if (cs_countdown >= 0) | ||
547 | cs_countdown--; | ||
548 | if (cs_countdown == 0) | ||
549 | CS_HI; | ||
550 | } | ||
551 | |||
552 | /* Update the display. | ||
553 | This must be called after all other LCD functions that change the display. */ | ||
554 | void lcd_remote_update(void) ICODE_ATTR; | ||
555 | void lcd_remote_update(void) | ||
556 | { | ||
557 | int y; | ||
558 | |||
559 | if (!remote_initialized) | ||
560 | return; | ||
561 | |||
562 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
563 | /* Adjust byte delay for emi reduction. */ | ||
564 | byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0; | ||
565 | #endif | ||
566 | |||
567 | /* Copy display bitmap to hardware */ | ||
568 | for (y = 0; y < LCD_REMOTE_FBHEIGHT; y++) | ||
569 | { | ||
570 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); | ||
571 | lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | ((xoffset >> 4) & 0xf)); | ||
572 | lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | (xoffset & 0xf)); | ||
573 | lcd_remote_write_data(lcd_remote_framebuffer[y], LCD_REMOTE_WIDTH); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | /* Update a fraction of the display. */ | ||
578 | void lcd_remote_update_rect(int, int, int, int) ICODE_ATTR; | ||
579 | void lcd_remote_update_rect(int x, int y, int width, int height) | ||
580 | { | ||
581 | int ymax; | ||
582 | |||
583 | if (!remote_initialized) | ||
584 | return; | ||
585 | |||
586 | /* The Y coordinates have to work on even 8 pixel rows */ | ||
587 | ymax = (y + height-1) >> 3; | ||
588 | y >>= 3; | ||
589 | |||
590 | if(x + width > LCD_REMOTE_WIDTH) | ||
591 | width = LCD_REMOTE_WIDTH - x; | ||
592 | if (width <= 0) | ||
593 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | ||
594 | if(ymax >= LCD_REMOTE_FBHEIGHT) | ||
595 | ymax = LCD_REMOTE_FBHEIGHT-1; | ||
596 | |||
597 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
598 | /* Adjust byte delay for emi reduction */ | ||
599 | byte_delay = emireduce ? cpu_frequency / 197600 + 28: 0; | ||
600 | #endif | ||
601 | |||
602 | /* Copy specified rectange bitmap to hardware */ | ||
603 | for (; y <= ymax; y++) | ||
604 | { | ||
605 | lcd_remote_write_command(LCD_REMOTE_CNTL_SET_PAGE_ADDRESS | y); | ||
606 | lcd_remote_write_command(LCD_REMOTE_CNTL_HIGHCOL | (((x+xoffset) >> 4) & 0xf)); | ||
607 | lcd_remote_write_command(LCD_REMOTE_CNTL_LOWCOL | ((x+xoffset) & 0xf)); | ||
608 | lcd_remote_write_data(&lcd_remote_framebuffer[y][x], width); | ||
609 | } | ||
610 | } | ||
diff --git a/firmware/target/coldfire/iriver/lcd-remote-target.h b/firmware/target/coldfire/iriver/lcd-remote-target.h new file mode 100755 index 0000000000..a95f9adade --- /dev/null +++ b/firmware/target/coldfire/iriver/lcd-remote-target.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: lcd-remote-target.h 11967 2007-01-09 23:29:07Z linus $ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Jens Arnold | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef LCD_REMOTE_TARGET_H | ||
20 | #define LCD_REMOTE_TARGET_H | ||
21 | |||
22 | #define REMOTE_INIT_LCD 1 | ||
23 | #define REMOTE_DEINIT_LCD 2 | ||
24 | |||
25 | void lcd_remote_write_command(int cmd); | ||
26 | void lcd_remote_write_command_ex(int cmd, int data); | ||
27 | void lcd_remote_write_data(const unsigned char* p_bytes, int count); | ||
28 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
29 | void lcd_remote_emireduce(bool state); | ||
30 | #endif | ||
31 | void lcd_remote_powersave(bool on); | ||
32 | void lcd_remote_set_invert_display(bool yesno); | ||
33 | void lcd_remote_set_flip(bool yesno); | ||
34 | |||
35 | bool remote_detect(void); | ||
36 | void lcd_remote_init_device(void); | ||
37 | void lcd_remote_on(void); | ||
38 | void lcd_remote_off(void); | ||
39 | void lcd_remote_update(void); | ||
40 | void lcd_remote_update_rect(int, int, int, int); | ||
41 | |||
42 | extern bool remote_initialized; | ||
43 | |||
44 | #endif | ||