diff options
Diffstat (limited to 'firmware/drivers/lcd-player.c')
-rw-r--r-- | firmware/drivers/lcd-player.c | 830 |
1 files changed, 0 insertions, 830 deletions
diff --git a/firmware/drivers/lcd-player.c b/firmware/drivers/lcd-player.c deleted file mode 100644 index dd99246611..0000000000 --- a/firmware/drivers/lcd-player.c +++ /dev/null | |||
@@ -1,830 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
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 | #include "config.h" | ||
20 | #include "hwcompat.h" | ||
21 | |||
22 | #ifdef HAVE_LCD_CHARCELLS | ||
23 | |||
24 | #include "lcd.h" | ||
25 | #include "kernel.h" | ||
26 | #include "thread.h" | ||
27 | #include <string.h> | ||
28 | #include <stdlib.h> | ||
29 | #include "file.h" | ||
30 | #include "debug.h" | ||
31 | #include "system.h" | ||
32 | #include "font.h" | ||
33 | #include "lcd-player-charset.h" | ||
34 | #include "rbunicode.h" | ||
35 | |||
36 | /*** definitions ***/ | ||
37 | |||
38 | #define OLD_LCD_CONTRAST_SET ((char)0xA8) | ||
39 | #define OLD_LCD_CRAM ((char)0xB0) /* Characters */ | ||
40 | #define OLD_LCD_PRAM ((char)0x80) /* Patterns */ | ||
41 | #define OLD_LCD_IRAM ((char)0xE0) /* Icons */ | ||
42 | |||
43 | #define NEW_LCD_CONTRAST_SET ((char)0x50) | ||
44 | #define NEW_LCD_CRAM ((char)0x80) /* Characters */ | ||
45 | #define NEW_LCD_PRAM ((char)0xC0) /* Patterns */ | ||
46 | #define NEW_LCD_IRAM ((char)0x40) /* Icons */ | ||
47 | #define NEW_LCD_FUNCTION_SET ((char)0x10) | ||
48 | #define NEW_LCD_POWER_SAVE_MODE_OSC_CONTROL_SET ((char)0x0c) | ||
49 | #define NEW_LCD_POWER_CONTROL_REGISTER_SET ((char)0x20) | ||
50 | #define NEW_LCD_DISPLAY_CONTROL_SET ((char)0x28) | ||
51 | |||
52 | #define LCD_CURSOR(x,y) ((char)(lcd_cram+((y)*16+(x)))) | ||
53 | #define LCD_ICON(i) ((char)(lcd_iram+i)) | ||
54 | |||
55 | #define SCROLLABLE_LINES 2 | ||
56 | |||
57 | #define SCROLL_MODE_OFF 0 | ||
58 | #define SCROLL_MODE_PAUSE 1 | ||
59 | #define SCROLL_MODE_RUN 2 | ||
60 | |||
61 | extern unsigned short new_lcd_rocklatin1_to_xlcd[]; | ||
62 | extern unsigned short old_lcd_rocklatin1_to_xlcd[]; | ||
63 | extern const unsigned char lcd_player_extended_lcd_to_rocklatin1[]; | ||
64 | extern unsigned char extended_font_player[NO_EXTENDED_LCD_CHARS][8]; | ||
65 | |||
66 | /*** generic code ***/ | ||
67 | |||
68 | #define MAX_CURSOR_CHARS 8 | ||
69 | struct cursorinfo { | ||
70 | int len; | ||
71 | char text[MAX_CURSOR_CHARS]; | ||
72 | int textpos; | ||
73 | int y_pos; | ||
74 | int x_pos; | ||
75 | int divider; | ||
76 | int downcount; | ||
77 | } cursor; | ||
78 | |||
79 | static void scroll_thread(void); | ||
80 | static char scroll_stack[DEFAULT_STACK_SIZE]; | ||
81 | static const char scroll_name[] = "scroll"; | ||
82 | static int scroll_ticks = 12; /* # of ticks between updates */ | ||
83 | static int scroll_delay = HZ/2; /* delay before starting scroll */ | ||
84 | static int jump_scroll_delay = HZ/4; /* delay between jump scroll jumps */ | ||
85 | static int scroll_spacing = 3; /* spaces between end and start of text */ | ||
86 | static int bidir_limit = 50; /* percent */ | ||
87 | static int jump_scroll = 0; /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */ | ||
88 | |||
89 | static struct scrollinfo scroll[SCROLLABLE_LINES]; | ||
90 | |||
91 | static char extended_chars_mapped[NO_EXTENDED_LCD_CHARS]; | ||
92 | static char extended_pattern_content[8]; /* Which char is mapped in pattern */ | ||
93 | static char extended_pattern_usage[8]; /* Counting number of times used */ | ||
94 | static char pattern_size; /* Last pattern, 3 for old LCD, 7 for new LCD */ | ||
95 | |||
96 | static bool new_lcd; | ||
97 | |||
98 | unsigned short *lcd_ascii; | ||
99 | static char lcd_contrast_set; | ||
100 | static char lcd_cram; | ||
101 | static char lcd_pram; | ||
102 | static char lcd_iram; | ||
103 | |||
104 | unsigned short buffer_xlcd[11][2]; | ||
105 | unsigned short buffer_lcd_mirror[11][2]; | ||
106 | |||
107 | #ifdef SIMULATOR | ||
108 | unsigned char hardware_buffer_lcd[11][2]; | ||
109 | #endif | ||
110 | |||
111 | #define NO_CHAR -1 | ||
112 | |||
113 | static void lcd_free_pat(int map_ch) | ||
114 | { | ||
115 | int x, y; | ||
116 | unsigned char substitute_char; | ||
117 | |||
118 | int pat; | ||
119 | pat=extended_chars_mapped[map_ch]; | ||
120 | if (pat!=NO_CHAR) { | ||
121 | |||
122 | substitute_char=lcd_player_extended_lcd_to_rocklatin1[map_ch]; | ||
123 | |||
124 | /* TODO: use a define for the screen width! */ | ||
125 | for (x=0; x<11; x++) { | ||
126 | /* TODO: use a define for the screen height! */ | ||
127 | for (y=0; y<2; y++) { | ||
128 | if (map_ch==lcd_ascii[buffer_xlcd[x][y]]-512) { | ||
129 | buffer_xlcd[x][y]=substitute_char; | ||
130 | buffer_lcd_mirror[x][y]=substitute_char; | ||
131 | #ifdef SIMULATOR | ||
132 | hardware_buffer_lcd[x][y]=substitute_char; | ||
133 | #else | ||
134 | lcd_write_command_e(LCD_CURSOR(x, y), substitute_char); | ||
135 | #endif | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | extended_chars_mapped[map_ch]=NO_CHAR; | ||
140 | extended_pattern_content[pat]=NO_CHAR; | ||
141 | extended_pattern_usage[pat]=0; | ||
142 | } | ||
143 | #ifdef SIMULATOR | ||
144 | lcd_update(); | ||
145 | #endif | ||
146 | } | ||
147 | |||
148 | static int lcd_get_free_pat(int ch) | ||
149 | { | ||
150 | int pat; | ||
151 | int last_pat=0; | ||
152 | static int last_used_pat=0; | ||
153 | int loop; | ||
154 | |||
155 | pat=last_used_pat; | ||
156 | for (loop=0; loop<=pattern_size; loop++) { | ||
157 | pat=(pat+1)&pattern_size; /* Keep 'pat' within limits */ | ||
158 | if (extended_pattern_usage[pat]==0) { | ||
159 | int map_ch=extended_pattern_content[pat]; | ||
160 | if (map_ch != NO_CHAR) { | ||
161 | extended_chars_mapped[map_ch]=NO_CHAR; | ||
162 | extended_pattern_content[pat]=NO_CHAR; | ||
163 | } | ||
164 | last_used_pat=pat; | ||
165 | return pat; | ||
166 | } | ||
167 | if (extended_pattern_content[pat]>extended_pattern_content[last_pat]) | ||
168 | last_pat=pat; | ||
169 | } | ||
170 | if (ch<32) { /* Prioritized char */ | ||
171 | /* Remove last_pat */ | ||
172 | lcd_free_pat(extended_pattern_content[last_pat]); | ||
173 | last_used_pat=last_pat; | ||
174 | return last_pat; | ||
175 | } | ||
176 | return NO_CHAR; | ||
177 | |||
178 | } | ||
179 | |||
180 | void xlcd_update(void) | ||
181 | { | ||
182 | int x, y; | ||
183 | for (x=0; x<11; x++) { | ||
184 | for (y=0; y<2; y++) { | ||
185 | unsigned short ch=buffer_xlcd[x][y]; | ||
186 | unsigned char hw_ch=0xff; | ||
187 | if (ch==buffer_lcd_mirror[x][y]) | ||
188 | continue; /* No need to redraw */ | ||
189 | buffer_lcd_mirror[x][y]=ch; | ||
190 | if (ch>=256 && ch<512) { | ||
191 | hw_ch=ch-256; | ||
192 | } else { | ||
193 | int map_ch=lcd_ascii[ch]; | ||
194 | if (map_ch<512) { | ||
195 | hw_ch=map_ch; | ||
196 | } | ||
197 | else { | ||
198 | map_ch=map_ch-512; | ||
199 | if (extended_chars_mapped[map_ch]!=NO_CHAR) { | ||
200 | hw_ch=extended_chars_mapped[map_ch]; | ||
201 | extended_pattern_usage[hw_ch]++; | ||
202 | } | ||
203 | else { | ||
204 | int pat; | ||
205 | pat=lcd_get_free_pat(map_ch); | ||
206 | if (pat<0) { | ||
207 | /* Find substitute char */ | ||
208 | map_ch= | ||
209 | lcd_player_extended_lcd_to_rocklatin1[map_ch]; | ||
210 | hw_ch=lcd_ascii[map_ch]; | ||
211 | } else { | ||
212 | #ifdef DEBUG | ||
213 | if (extended_pattern_usage[pat]!=0) { | ||
214 | DEBUGF("***Pattern %d is not zero!\n", pat); | ||
215 | } | ||
216 | #endif | ||
217 | extended_chars_mapped[map_ch]=pat; | ||
218 | extended_pattern_content[pat]=map_ch; | ||
219 | extended_pattern_usage[pat]=1; | ||
220 | lcd_define_hw_pattern(pat*8, | ||
221 | extended_font_player[map_ch], | ||
222 | 8); | ||
223 | hw_ch=pat; | ||
224 | } | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | #ifdef SIMULATOR | ||
229 | hardware_buffer_lcd[x][y]=hw_ch; | ||
230 | #else | ||
231 | lcd_write_command_e(LCD_CURSOR(x,y), hw_ch); | ||
232 | #endif | ||
233 | } | ||
234 | } | ||
235 | lcd_update(); | ||
236 | } | ||
237 | |||
238 | bool lcdx_putc(int x, int y, unsigned short ch) | ||
239 | { | ||
240 | int lcd_char; | ||
241 | if (buffer_xlcd[x][y]==ch) | ||
242 | return false; /* Same char, ignore any update */ | ||
243 | lcd_char=lcd_ascii[buffer_xlcd[x][y]]; | ||
244 | if (lcd_char>=512) { | ||
245 | /* The removed char is a defined pattern, count down the reference. */ | ||
246 | extended_pattern_usage[(int)extended_chars_mapped[lcd_char-512]]--; | ||
247 | #ifdef DEBUG | ||
248 | if (extended_pattern_usage[(int)extended_chars_mapped[lcd_char]]<0) { | ||
249 | DEBUGF("**** Mapped char %02x is less than 0!\n", lcd_char); | ||
250 | } | ||
251 | #endif | ||
252 | } | ||
253 | |||
254 | buffer_xlcd[x][y]=ch; | ||
255 | |||
256 | lcd_char=lcd_ascii[ch]; | ||
257 | if (lcd_char>=256) | ||
258 | return true; /* Caller shall call xlcd_update() when done */ | ||
259 | |||
260 | buffer_lcd_mirror[x][y]=lcd_char; | ||
261 | #ifdef SIMULATOR | ||
262 | hardware_buffer_lcd[x][y]=lcd_char; | ||
263 | #else | ||
264 | lcd_write_command_e(LCD_CURSOR(x, y), lcd_char); | ||
265 | #endif | ||
266 | return false; | ||
267 | } | ||
268 | |||
269 | void lcd_clear_display(void) | ||
270 | { | ||
271 | int i; | ||
272 | bool update=false; | ||
273 | lcd_stop_scroll(); | ||
274 | cursor.len=0; /* Stop cursor */ | ||
275 | for (i=0;i<22;i++) | ||
276 | update|=lcdx_putc(i%11, i/11, ' '); | ||
277 | if (update) | ||
278 | xlcd_update(); | ||
279 | } | ||
280 | |||
281 | static void lcd_puts_cont_scroll(int x, int y, const unsigned char *string) | ||
282 | { | ||
283 | bool update=false; | ||
284 | |||
285 | for (; *string && x<11; x++) | ||
286 | { | ||
287 | /* We should check if char is over 256 */ | ||
288 | update|=lcdx_putc(x, y, *(unsigned char*)string++); | ||
289 | } | ||
290 | |||
291 | for (; x<11; x++) | ||
292 | update|=lcdx_putc(x, y, ' '); | ||
293 | if (update) | ||
294 | xlcd_update(); | ||
295 | #ifdef SIMULATOR | ||
296 | lcd_update(); | ||
297 | #endif | ||
298 | } | ||
299 | void lcd_puts(int x, int y, const unsigned char *string) | ||
300 | { | ||
301 | int i=0; | ||
302 | unsigned short ucs; | ||
303 | const unsigned char *utf8 = string; | ||
304 | unsigned char tmp[12]; | ||
305 | |||
306 | while (*utf8 && i<11) { | ||
307 | utf8 = utf8decode(utf8, &ucs); | ||
308 | if (ucs < 256) | ||
309 | tmp[i++] = ucs; | ||
310 | else | ||
311 | tmp[i++] = '?'; | ||
312 | } | ||
313 | |||
314 | tmp[i] = 0; | ||
315 | |||
316 | scroll[y].mode=SCROLL_MODE_OFF; | ||
317 | return lcd_puts_cont_scroll(x, y, tmp); | ||
318 | } | ||
319 | |||
320 | void lcd_put_cursor(int x, int y, char cursor_char) | ||
321 | { | ||
322 | if (cursor.len == 0) { | ||
323 | cursor.text[0]=buffer_xlcd[x][y]; | ||
324 | cursor.text[1]=cursor_char; | ||
325 | cursor.len=2; | ||
326 | cursor.textpos=0; | ||
327 | cursor.y_pos=y; | ||
328 | cursor.x_pos=x; | ||
329 | cursor.downcount=0; | ||
330 | cursor.divider=4; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | void lcd_remove_cursor(void) | ||
335 | { | ||
336 | if (cursor.len!=0) { | ||
337 | bool up; | ||
338 | cursor.len=0; | ||
339 | up = lcdx_putc(cursor.x_pos, cursor.y_pos, cursor.text[0]); | ||
340 | #ifdef SIMULATOR | ||
341 | if(up) | ||
342 | lcd_update(); | ||
343 | #endif | ||
344 | } | ||
345 | } | ||
346 | |||
347 | void lcd_putc(int x, int y, unsigned short ch) | ||
348 | { | ||
349 | bool update; | ||
350 | if (x<0 || y<0) { | ||
351 | return; | ||
352 | } | ||
353 | update=lcdx_putc(x, y, ch); | ||
354 | |||
355 | if (update) | ||
356 | xlcd_update(); | ||
357 | } | ||
358 | |||
359 | unsigned char lcd_get_locked_pattern(void) | ||
360 | { | ||
361 | unsigned char pat=1; | ||
362 | while (pat<LAST_RESERVED_CHAR) { | ||
363 | if (lcd_ascii[pat]==RESERVED_CHAR) { | ||
364 | lcd_ascii[pat]=0x200+pat; | ||
365 | return pat; | ||
366 | } | ||
367 | pat++; | ||
368 | } | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | void lcd_unlock_pattern(unsigned char pat) | ||
373 | { | ||
374 | lcd_ascii[pat]=RESERVED_CHAR; | ||
375 | lcd_free_pat(pat); | ||
376 | } | ||
377 | |||
378 | void lcd_define_pattern(int pat, const char *pattern) | ||
379 | { | ||
380 | int i; | ||
381 | for (i=0; i<7; i++) { | ||
382 | extended_font_player[pat][i]=pattern[i]; | ||
383 | } | ||
384 | if (extended_chars_mapped[pat]!=NO_CHAR) { | ||
385 | lcd_define_hw_pattern(extended_chars_mapped[pat]*8, pattern, 7); | ||
386 | } | ||
387 | } | ||
388 | |||
389 | #ifndef SIMULATOR | ||
390 | void lcd_define_hw_pattern (int which,const char *pattern,int length) | ||
391 | { | ||
392 | lcd_write_command(lcd_pram | which); | ||
393 | lcd_write_data(pattern, length); | ||
394 | } | ||
395 | |||
396 | void lcd_double_height(bool on) | ||
397 | { | ||
398 | if(new_lcd) | ||
399 | lcd_write_command(on?9:8); | ||
400 | } | ||
401 | |||
402 | static const char icon_pos[] = | ||
403 | { | ||
404 | 0, 0, 0, 0, /* Battery */ | ||
405 | 2, /* USB */ | ||
406 | 3, /* Play */ | ||
407 | 4, /* Record */ | ||
408 | 5, /* Pause */ | ||
409 | 5, /* Audio */ | ||
410 | 6, /* Repeat */ | ||
411 | 7, /* 1 */ | ||
412 | 9, /* Volume */ | ||
413 | 9, /* Volume 1 */ | ||
414 | 9, /* Volume 2 */ | ||
415 | 10, /* Volume 3 */ | ||
416 | 10, /* Volume 4 */ | ||
417 | 10, /* Volume 5 */ | ||
418 | 10, /* Param */ | ||
419 | }; | ||
420 | |||
421 | static const char icon_mask[] = | ||
422 | { | ||
423 | 0x02, 0x08, 0x04, 0x10, /* Battery */ | ||
424 | 0x04, /* USB */ | ||
425 | 0x10, /* Play */ | ||
426 | 0x10, /* Record */ | ||
427 | 0x02, /* Pause */ | ||
428 | 0x10, /* Audio */ | ||
429 | 0x02, /* Repeat */ | ||
430 | 0x01, /* 1 */ | ||
431 | 0x04, /* Volume */ | ||
432 | 0x02, /* Volume 1 */ | ||
433 | 0x01, /* Volume 2 */ | ||
434 | 0x08, /* Volume 3 */ | ||
435 | 0x04, /* Volume 4 */ | ||
436 | 0x01, /* Volume 5 */ | ||
437 | 0x10, /* Param */ | ||
438 | }; | ||
439 | |||
440 | void lcd_icon(int icon, bool enable) | ||
441 | { | ||
442 | static unsigned char icon_mirror[11] = {0}; | ||
443 | int pos, mask; | ||
444 | |||
445 | pos = icon_pos[icon]; | ||
446 | mask = icon_mask[icon]; | ||
447 | |||
448 | if(enable) | ||
449 | icon_mirror[pos] |= mask; | ||
450 | else | ||
451 | icon_mirror[pos] &= ~mask; | ||
452 | |||
453 | lcd_write_command_e(LCD_ICON(pos), icon_mirror[pos]); | ||
454 | } | ||
455 | |||
456 | int lcd_default_contrast(void) | ||
457 | { | ||
458 | return 30; | ||
459 | } | ||
460 | |||
461 | void lcd_set_contrast(int val) | ||
462 | { | ||
463 | lcd_write_command_e(lcd_contrast_set, 31 - val); | ||
464 | } | ||
465 | #endif /* SIMULATOR */ | ||
466 | |||
467 | void lcd_init (void) | ||
468 | { | ||
469 | unsigned char data_vector[64]; | ||
470 | |||
471 | (void)data_vector; | ||
472 | |||
473 | new_lcd = is_new_player(); | ||
474 | memset(extended_chars_mapped, NO_CHAR, sizeof(extended_chars_mapped)); | ||
475 | memset(extended_pattern_content, NO_CHAR,sizeof(extended_pattern_content)); | ||
476 | memset(extended_pattern_usage, 0, sizeof(extended_pattern_usage)); | ||
477 | |||
478 | if(new_lcd) { | ||
479 | lcd_ascii = new_lcd_rocklatin1_to_xlcd; | ||
480 | lcd_contrast_set = NEW_LCD_CONTRAST_SET; | ||
481 | lcd_cram = NEW_LCD_CRAM; | ||
482 | lcd_pram = NEW_LCD_PRAM; | ||
483 | lcd_iram = NEW_LCD_IRAM; | ||
484 | pattern_size=7; /* Last pattern, 7 for new LCD */ | ||
485 | |||
486 | #ifndef SIMULATOR | ||
487 | /* LCD init for cold start */ | ||
488 | PBCR2 &= 0xff00; /* Set PB0..PB3 to GPIO */ | ||
489 | or_b(0x0f, &PBIORL); /* ... output */ | ||
490 | or_b(0x0f, &PBDRL); /* ... and high */ | ||
491 | |||
492 | lcd_write_command(NEW_LCD_FUNCTION_SET + 1); /* CGRAM selected */ | ||
493 | lcd_write_command_e(NEW_LCD_CONTRAST_SET, 0x08); | ||
494 | lcd_write_command(NEW_LCD_POWER_SAVE_MODE_OSC_CONTROL_SET + 2); | ||
495 | /* oscillator on */ | ||
496 | lcd_write_command(NEW_LCD_POWER_CONTROL_REGISTER_SET + 7); | ||
497 | /* opamp buffer + voltage booster on*/ | ||
498 | |||
499 | memset(data_vector, 0x20, 64); | ||
500 | lcd_write_command(NEW_LCD_CRAM); /* Set DDRAM address */ | ||
501 | lcd_write_data(data_vector, 64); /* all spaces */ | ||
502 | |||
503 | memset(data_vector, 0, 64); | ||
504 | lcd_write_command(NEW_LCD_PRAM); /* Set CGRAM address */ | ||
505 | lcd_write_data(data_vector, 64); /* zero out */ | ||
506 | lcd_write_command(NEW_LCD_IRAM); /* Set ICONRAM address */ | ||
507 | lcd_write_data(data_vector, 16); /* zero out */ | ||
508 | |||
509 | lcd_write_command(NEW_LCD_DISPLAY_CONTROL_SET + 1); /* display on */ | ||
510 | #endif /* !SIMULATOR */ | ||
511 | } | ||
512 | else { | ||
513 | lcd_ascii = old_lcd_rocklatin1_to_xlcd; | ||
514 | lcd_contrast_set = OLD_LCD_CONTRAST_SET; | ||
515 | lcd_cram = OLD_LCD_CRAM; | ||
516 | lcd_pram = OLD_LCD_PRAM; | ||
517 | lcd_iram = OLD_LCD_IRAM; | ||
518 | pattern_size=3; /* Last pattern, 3 for old LCD */ | ||
519 | |||
520 | #ifndef SIMULATOR | ||
521 | #if 1 | ||
522 | /* LCD init for cold start */ | ||
523 | PBCR2 &= 0xff00; /* Set PB0..PB3 to GPIO */ | ||
524 | or_b(0x0f, &PBIORL); /* ... output */ | ||
525 | or_b(0x0f, &PBDRL); /* ... and high */ | ||
526 | |||
527 | lcd_write_command(0x61); | ||
528 | lcd_write_command(0x42); | ||
529 | lcd_write_command(0x57); | ||
530 | |||
531 | memset(data_vector, 0x24, 13); | ||
532 | lcd_write_command(OLD_LCD_CRAM); /* Set DDRAM address */ | ||
533 | lcd_write_data(data_vector, 13); /* all spaces */ | ||
534 | lcd_write_command(OLD_LCD_CRAM + 0x10); | ||
535 | lcd_write_data(data_vector, 13); | ||
536 | lcd_write_command(OLD_LCD_CRAM + 0x20); | ||
537 | lcd_write_data(data_vector, 13); | ||
538 | |||
539 | memset(data_vector, 0, 32); | ||
540 | lcd_write_command(OLD_LCD_PRAM); /* Set CGRAM address */ | ||
541 | lcd_write_data(data_vector, 32); /* zero out */ | ||
542 | lcd_write_command(OLD_LCD_IRAM); /* Set ICONRAM address */ | ||
543 | lcd_write_data(data_vector, 13); /* zero out */ | ||
544 | lcd_write_command(OLD_LCD_IRAM + 0x10); | ||
545 | lcd_write_data(data_vector, 13); | ||
546 | |||
547 | lcd_write_command(0x31); | ||
548 | #else | ||
549 | /* archos look-alike code, left here for reference. As soon as the | ||
550 | * rockbox version is confirmed working, this will go away */ | ||
551 | { | ||
552 | int i; | ||
553 | |||
554 | PBCR2 &= 0xc000; | ||
555 | PBIOR |= 0x000f; | ||
556 | PBDR |= 0x0002; | ||
557 | PBDR |= 0x0001; | ||
558 | PBDR |= 0x0004; | ||
559 | PBDR |= 0x0008; | ||
560 | |||
561 | for (i=0; i<200; i++) asm volatile ("nop"); /* wait 100 us */ | ||
562 | |||
563 | PBDR &= 0xfffd; /* CS low (assert) */ | ||
564 | |||
565 | for (i=0; i<100; i++) asm volatile ("nop"); /* wait 50 us */ | ||
566 | |||
567 | lcd_write_command(0x61); | ||
568 | lcd_write_command(0x42); | ||
569 | lcd_write_command(0x57); | ||
570 | |||
571 | memset(data_vector, 0x24, 13); | ||
572 | lcd_write_command(0xb0); /* Set DDRAM address */ | ||
573 | lcd_write_data(data_vector, 13); /* all spaces */ | ||
574 | lcd_write_command(0xc0); | ||
575 | lcd_write_data(data_vector, 13); | ||
576 | lcd_write_command(0xd0); | ||
577 | lcd_write_data(data_vector, 13); | ||
578 | |||
579 | memset(data_vector, 0, 32); | ||
580 | lcd_write_command(0x80); /* Set CGRAM address */ | ||
581 | lcd_write_data(data_vector, 32); /* zero out */ | ||
582 | lcd_write_command(0xe0); /* Set ICONRAM address */ | ||
583 | lcd_write_data(data_vector, 13); /* zero out */ | ||
584 | lcd_write_command(0xf0); | ||
585 | lcd_write_data(data_vector, 13); | ||
586 | |||
587 | for (i=0; i<300000; i++) asm volatile ("nop"); /* wait 150 ms */ | ||
588 | |||
589 | lcd_write_command(0x31); | ||
590 | lcd_write_command_e(0xa8, 0); /* Set contrast control */ | ||
591 | } | ||
592 | #endif | ||
593 | #endif /* !SIMULATOR */ | ||
594 | } | ||
595 | |||
596 | lcd_set_contrast(lcd_default_contrast()); | ||
597 | |||
598 | create_thread(scroll_thread, scroll_stack, | ||
599 | sizeof(scroll_stack), scroll_name IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
600 | IF_COP(, CPU, false)); | ||
601 | } | ||
602 | |||
603 | void lcd_jump_scroll (int mode) /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */ | ||
604 | { | ||
605 | jump_scroll=mode; | ||
606 | } | ||
607 | |||
608 | void lcd_bidir_scroll(int percent) | ||
609 | { | ||
610 | bidir_limit = percent; | ||
611 | } | ||
612 | |||
613 | void lcd_puts_scroll(int x, int y, const unsigned char* string ) | ||
614 | { | ||
615 | struct scrollinfo* s; | ||
616 | int i=0; | ||
617 | unsigned short ucs; | ||
618 | const unsigned char *utf8 = string; | ||
619 | unsigned char tmp[utf8length(string)+1]; | ||
620 | |||
621 | while (*utf8) { | ||
622 | utf8 = utf8decode(utf8, &ucs); | ||
623 | if (ucs < 256) | ||
624 | tmp[i++] = ucs; | ||
625 | else | ||
626 | tmp[i++] = '?'; | ||
627 | } | ||
628 | |||
629 | tmp[i] = 0; | ||
630 | |||
631 | |||
632 | s = &scroll[y]; | ||
633 | |||
634 | lcd_puts_cont_scroll(x,y,tmp); | ||
635 | s->textlen = strlen(tmp); | ||
636 | |||
637 | if ( s->textlen > 11-x ) { | ||
638 | s->mode = SCROLL_MODE_RUN; | ||
639 | s->scroll_start_tick = current_tick + scroll_delay; | ||
640 | s->offset=0; | ||
641 | s->startx=x; | ||
642 | s->starty=y; | ||
643 | s->direction=+1; | ||
644 | s->jump_scroll=0; | ||
645 | s->jump_scroll_steps=0; | ||
646 | if (jump_scroll && jump_scroll_delay<scroll_ticks*(s->textlen-11+x)) { | ||
647 | s->jump_scroll_steps=11-x; | ||
648 | s->jump_scroll=jump_scroll; | ||
649 | } | ||
650 | strncpy(s->text,tmp,sizeof s->text); | ||
651 | s->turn_offset=-1; | ||
652 | if (bidir_limit && (s->textlen < ((11-x)*(100+bidir_limit))/100)) { | ||
653 | s->turn_offset=s->textlen+x-11; | ||
654 | } | ||
655 | else { | ||
656 | for (i=0; i<scroll_spacing && | ||
657 | s->textlen<(int)sizeof(s->text); i++) { | ||
658 | s->text[s->textlen++]=' '; | ||
659 | } | ||
660 | } | ||
661 | if (s->textlen<(int)sizeof(s->text)) | ||
662 | s->text[s->textlen]=' '; | ||
663 | s->text[sizeof s->text - 1] = 0; | ||
664 | } | ||
665 | else | ||
666 | s->mode = SCROLL_MODE_OFF; | ||
667 | } | ||
668 | |||
669 | void lcd_stop_scroll(void) | ||
670 | { | ||
671 | struct scrollinfo* s; | ||
672 | int index; | ||
673 | |||
674 | for ( index = 0; index < SCROLLABLE_LINES; index++ ) { | ||
675 | s = &scroll[index]; | ||
676 | if ( s->mode == SCROLL_MODE_RUN || | ||
677 | s->mode == SCROLL_MODE_PAUSE ) { | ||
678 | /* restore scrolled row */ | ||
679 | lcd_puts(s->startx, s->starty, s->text); | ||
680 | } | ||
681 | } | ||
682 | |||
683 | lcd_update(); | ||
684 | } | ||
685 | |||
686 | static const char scroll_tick_table[16] = { | ||
687 | /* Hz values: | ||
688 | 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ | ||
689 | 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 | ||
690 | }; | ||
691 | |||
692 | void lcd_scroll_speed(int speed) | ||
693 | { | ||
694 | scroll_ticks = scroll_tick_table[speed]; | ||
695 | } | ||
696 | |||
697 | void lcd_scroll_delay(int ms) | ||
698 | { | ||
699 | scroll_delay = ms / (HZ / 10); | ||
700 | } | ||
701 | |||
702 | void lcd_jump_scroll_delay(int ms) | ||
703 | { | ||
704 | jump_scroll_delay = ms / (HZ / 10); | ||
705 | } | ||
706 | |||
707 | static void scroll_thread(void) | ||
708 | { | ||
709 | struct scrollinfo* s; | ||
710 | int index; | ||
711 | int i, o; | ||
712 | bool update; | ||
713 | |||
714 | /* initialize scroll struct array */ | ||
715 | for (index = 0; index < SCROLLABLE_LINES; index++) { | ||
716 | scroll[index].mode = SCROLL_MODE_OFF; | ||
717 | } | ||
718 | |||
719 | while ( 1 ) { | ||
720 | |||
721 | update = false; | ||
722 | |||
723 | for ( index = 0; index < SCROLLABLE_LINES; index++ ) { | ||
724 | s = &scroll[index]; | ||
725 | if ( s->mode == SCROLL_MODE_RUN ) { | ||
726 | if ( TIME_AFTER(current_tick, s->scroll_start_tick) ) { | ||
727 | char buffer[12]; | ||
728 | int jumping_scroll=s->jump_scroll; | ||
729 | update = true; | ||
730 | if (s->jump_scroll) { | ||
731 | |||
732 | /* Find new position to start jump scroll by | ||
733 | * finding last white space within | ||
734 | * jump_scroll_steps */ | ||
735 | int i; | ||
736 | o = s->offset = s->offset + s->jump_scroll_steps; | ||
737 | for (i = 0; i < s->jump_scroll_steps; i++, o--) { | ||
738 | if (o < s->textlen && | ||
739 | ((0x20 <= s->text[o] && s->text[o] <= 0x2f) || s->text[o] == '_')) | ||
740 | { | ||
741 | s->offset = o; | ||
742 | break; | ||
743 | } | ||
744 | } | ||
745 | |||
746 | s->scroll_start_tick = current_tick + | ||
747 | jump_scroll_delay; | ||
748 | /* Eat space */ | ||
749 | while (s->offset < s->textlen && | ||
750 | ((0x20 <= s->text[s->offset] && s->text[s->offset] <= 0x2f) || | ||
751 | s->text[s->offset] == '_')) { | ||
752 | s->offset++; | ||
753 | } | ||
754 | if (s->offset >= s->textlen) { | ||
755 | s->offset=0; | ||
756 | s->scroll_start_tick = current_tick + | ||
757 | scroll_delay; | ||
758 | if (s->jump_scroll != JUMP_SCROLL_ALWAYS) { | ||
759 | s->jump_scroll--; | ||
760 | s->direction=1; | ||
761 | } | ||
762 | } | ||
763 | } else { | ||
764 | if ( s->offset < s->textlen-1 ) { | ||
765 | s->offset+=s->direction; | ||
766 | if (s->offset==0) { | ||
767 | s->direction=+1; | ||
768 | s->scroll_start_tick = current_tick + | ||
769 | scroll_delay; | ||
770 | } else { | ||
771 | if (s->offset == s->turn_offset) { | ||
772 | s->direction=-1; | ||
773 | s->scroll_start_tick = current_tick + | ||
774 | scroll_delay; | ||
775 | } | ||
776 | } | ||
777 | } | ||
778 | else { | ||
779 | s->offset = 0; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | i=0; | ||
784 | o=s->offset; | ||
785 | while (i<11) { | ||
786 | buffer[i++]=s->text[o++]; | ||
787 | if (o==s->textlen /* || (jump_scroll && buffer[i-1] == ' ') */) | ||
788 | break; | ||
789 | } | ||
790 | o=0; | ||
791 | if (s->turn_offset == -1 && !jumping_scroll) { | ||
792 | while (i<11) { | ||
793 | buffer[i++]=s->text[o++]; | ||
794 | } | ||
795 | } else { | ||
796 | while (i<11) { | ||
797 | buffer[i++]=' '; | ||
798 | } | ||
799 | } | ||
800 | buffer[11]=0; | ||
801 | |||
802 | lcd_puts_cont_scroll(s->startx, s->starty, buffer); | ||
803 | } | ||
804 | } | ||
805 | if (cursor.len>0) { | ||
806 | if (cursor.downcount--<0) { | ||
807 | cursor.downcount=cursor.divider; | ||
808 | cursor.textpos++; | ||
809 | if (cursor.textpos>=cursor.len) | ||
810 | cursor.textpos=0; | ||
811 | #ifdef SIMULATOR | ||
812 | lcdx_putc(cursor.x_pos, cursor.y_pos, | ||
813 | cursor.text[cursor.textpos]); | ||
814 | update=true; | ||
815 | #else | ||
816 | update|=lcdx_putc(cursor.x_pos, cursor.y_pos, | ||
817 | cursor.text[cursor.textpos]); | ||
818 | #endif | ||
819 | } | ||
820 | } | ||
821 | if (update) { | ||
822 | lcd_update(); | ||
823 | } | ||
824 | } | ||
825 | |||
826 | sleep(scroll_ticks); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | #endif /* HAVE_LCD_CHARCELLS */ | ||