diff options
author | Jens Arnold <amiconn@rockbox.org> | 2007-03-31 09:58:49 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2007-03-31 09:58:49 +0000 |
commit | 54ea2e435e1a5688de4e4dcf551a1fc9c1db323f (patch) | |
tree | e8ee4e55a20c872a6c0deff554734038c35dc661 /firmware/drivers | |
parent | 6186b556bdbe97bc3c50dd8feb970590bec2053c (diff) | |
download | rockbox-54ea2e435e1a5688de4e4dcf551a1fc9c1db323f.tar.gz rockbox-54ea2e435e1a5688de4e4dcf551a1fc9c1db323f.zip |
Charcell lcd driver: Preparations for switching to non-immediate LCD updates, using lcd_update() like on bitmap targets. * Added proper clipping. * Simplified simulator code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12979 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/lcd-charcell.c | 194 | ||||
-rw-r--r-- | firmware/drivers/lcd-charset-player.c | 6 |
2 files changed, 83 insertions, 117 deletions
diff --git a/firmware/drivers/lcd-charcell.c b/firmware/drivers/lcd-charcell.c index 76f7cf1b1e..5ddef99655 100644 --- a/firmware/drivers/lcd-charcell.c +++ b/firmware/drivers/lcd-charcell.c | |||
@@ -38,42 +38,21 @@ | |||
38 | 38 | ||
39 | #define NO_PATTERN (-1) | 39 | #define NO_PATTERN (-1) |
40 | 40 | ||
41 | #define SCROLL_MODE_OFF 0 | ||
42 | #define SCROLL_MODE_RUN 1 | ||
43 | |||
44 | /* track usage of user-definable characters */ | ||
45 | struct pattern_info { | ||
46 | short count; | ||
47 | unsigned short xchar; | ||
48 | }; | ||
49 | |||
50 | struct cursor_info { | ||
51 | unsigned char hw_char; | ||
52 | bool enabled; | ||
53 | bool visible; | ||
54 | int x; | ||
55 | int y; | ||
56 | int divider; | ||
57 | int downcount; | ||
58 | }; | ||
59 | |||
60 | static int find_xchar(unsigned long ucs); | 41 | static int find_xchar(unsigned long ucs); |
61 | 42 | ||
62 | /** globals **/ | 43 | /** globals **/ |
63 | 44 | ||
64 | /* The "frame"buffer */ | 45 | /* The "frame"buffer */ |
65 | static unsigned char lcd_buffer[LCD_WIDTH][LCD_HEIGHT]; | 46 | unsigned char lcd_charbuffer[LCD_HEIGHT][LCD_WIDTH]; |
66 | #ifdef SIMULATOR | 47 | struct pattern_info lcd_patterns[MAX_HW_PATTERNS]; |
67 | unsigned char hardware_buffer_lcd[LCD_WIDTH][LCD_HEIGHT]; | 48 | struct cursor_info lcd_cursor; |
68 | #endif | ||
69 | |||
70 | static int xmargin = 0; | ||
71 | static int ymargin = 0; | ||
72 | 49 | ||
73 | static unsigned char xfont_variable[VARIABLE_XCHARS][HW_PATTERN_SIZE]; | 50 | static unsigned char xfont_variable[VARIABLE_XCHARS][HW_PATTERN_SIZE]; |
74 | static bool xfont_variable_locked[VARIABLE_XCHARS]; | 51 | static bool xfont_variable_locked[VARIABLE_XCHARS]; |
75 | static struct pattern_info hw_pattern[MAX_HW_PATTERNS]; | 52 | static int xspace; /* stores xhcar id of ' ' - often needed */ |
76 | static struct cursor_info cursor; | 53 | |
54 | static int xmargin = 0; | ||
55 | static int ymargin = 0; | ||
77 | 56 | ||
78 | /* scrolling */ | 57 | /* scrolling */ |
79 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ | 58 | static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ |
@@ -98,8 +77,9 @@ void lcd_init (void) | |||
98 | { | 77 | { |
99 | lcd_init_device(); | 78 | lcd_init_device(); |
100 | lcd_charset_init(); | 79 | lcd_charset_init(); |
101 | memset(hw_pattern, 0, sizeof(hw_pattern)); | 80 | memset(lcd_patterns, 0, sizeof(lcd_patterns)); |
102 | memset(lcd_buffer, xchar_info[find_xchar(' ')].hw_char, sizeof(lcd_buffer)); | 81 | xspace = find_xchar(' '); |
82 | memset(lcd_charbuffer, xchar_info[xspace].hw_char, sizeof(lcd_charbuffer)); | ||
103 | 83 | ||
104 | create_thread(scroll_thread, scroll_stack, | 84 | create_thread(scroll_thread, scroll_stack, |
105 | sizeof(scroll_stack), scroll_name | 85 | sizeof(scroll_stack), scroll_name |
@@ -165,8 +145,8 @@ static int xchar_to_pat(int xchar) | |||
165 | { | 145 | { |
166 | int i; | 146 | int i; |
167 | 147 | ||
168 | for (i = 0; i < hw_pattern_count; i++) | 148 | for (i = 0; i < lcd_pattern_count; i++) |
169 | if (hw_pattern[i].xchar == xchar) | 149 | if (lcd_patterns[i].xchar == xchar) |
170 | return i; | 150 | return i; |
171 | 151 | ||
172 | return NO_PATTERN; | 152 | return NO_PATTERN; |
@@ -193,27 +173,14 @@ static void lcd_free_pat(int xchar) | |||
193 | substitute = xchar_info[xchar].hw_char; | 173 | substitute = xchar_info[xchar].hw_char; |
194 | 174 | ||
195 | for (x = 0; x < LCD_WIDTH; x++) | 175 | for (x = 0; x < LCD_WIDTH; x++) |
196 | { | ||
197 | for (y = 0; y < LCD_HEIGHT; y++) | 176 | for (y = 0; y < LCD_HEIGHT; y++) |
198 | { | 177 | if (pat == lcd_charbuffer[y][x]) |
199 | if (pat == lcd_buffer[x][y]) | 178 | lcd_charbuffer[y][x] = substitute; |
200 | { | ||
201 | lcd_buffer[x][y] = substitute; | ||
202 | #ifdef SIMULATOR | ||
203 | hardware_buffer_lcd[x][y] = substitute; | ||
204 | #else | ||
205 | lcd_put_hw_char(x, y, substitute); | ||
206 | #endif | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | if (cursor.enabled && pat == cursor.hw_char) | ||
211 | cursor.hw_char = substitute; | ||
212 | 179 | ||
213 | hw_pattern[pat].count = 0; | 180 | if (lcd_cursor.enabled && pat == lcd_cursor.hw_char) |
214 | #ifdef SIMULATOR | 181 | lcd_cursor.hw_char = substitute; |
215 | lcd_update(); | 182 | |
216 | #endif | 183 | lcd_patterns[pat].count = 0; |
217 | } | 184 | } |
218 | } | 185 | } |
219 | 186 | ||
@@ -223,30 +190,30 @@ static int lcd_get_free_pat(int xchar) | |||
223 | 190 | ||
224 | int pat = last_used_pat; /* start from last used pattern */ | 191 | int pat = last_used_pat; /* start from last used pattern */ |
225 | int least_pat = pat; /* pattern with least priority */ | 192 | int least_pat = pat; /* pattern with least priority */ |
226 | int least_priority = xchar_info[hw_pattern[pat].xchar].priority; | 193 | int least_priority = xchar_info[lcd_patterns[pat].xchar].priority; |
227 | int i; | 194 | int i; |
228 | 195 | ||
229 | for (i = 0; i < hw_pattern_count; i++) | 196 | for (i = 0; i < lcd_pattern_count; i++) |
230 | { | 197 | { |
231 | if (++pat >= hw_pattern_count) /* Keep 'pat' within limits */ | 198 | if (++pat >= lcd_pattern_count) /* Keep 'pat' within limits */ |
232 | pat = 0; | 199 | pat = 0; |
233 | 200 | ||
234 | if (hw_pattern[pat].count == 0) | 201 | if (lcd_patterns[pat].count == 0) |
235 | { | 202 | { |
236 | hw_pattern[pat].xchar = xchar; | 203 | lcd_patterns[pat].xchar = xchar; |
237 | last_used_pat = pat; | 204 | last_used_pat = pat; |
238 | return pat; | 205 | return pat; |
239 | } | 206 | } |
240 | if (xchar_info[hw_pattern[pat].xchar].priority < least_priority) | 207 | if (xchar_info[lcd_patterns[pat].xchar].priority < least_priority) |
241 | { | 208 | { |
242 | least_priority = xchar_info[hw_pattern[pat].xchar].priority; | 209 | least_priority = xchar_info[lcd_patterns[pat].xchar].priority; |
243 | least_pat = pat; | 210 | least_pat = pat; |
244 | } | 211 | } |
245 | } | 212 | } |
246 | if (xchar_info[xchar].priority > least_priority) /* prioritized char */ | 213 | if (xchar_info[xchar].priority > least_priority) /* prioritized char */ |
247 | { | 214 | { |
248 | lcd_free_pat(hw_pattern[least_pat].xchar); | 215 | lcd_free_pat(lcd_patterns[least_pat].xchar); |
249 | hw_pattern[least_pat].xchar = xchar; | 216 | lcd_patterns[least_pat].xchar = xchar; |
250 | last_used_pat = least_pat; | 217 | last_used_pat = least_pat; |
251 | return least_pat; | 218 | return least_pat; |
252 | } | 219 | } |
@@ -267,9 +234,10 @@ static int map_xchar(int xchar) | |||
267 | if (pat == NO_PATTERN) /* failed: just use substitute */ | 234 | if (pat == NO_PATTERN) /* failed: just use substitute */ |
268 | return xchar_info[xchar].hw_char; | 235 | return xchar_info[xchar].hw_char; |
269 | else /* define pattern */ | 236 | else /* define pattern */ |
270 | lcd_define_hw_pattern(pat, xchar_to_glyph(xchar)); | 237 | memcpy(lcd_patterns[pat].pattern, xchar_to_glyph(xchar), |
238 | HW_PATTERN_SIZE); | ||
271 | } | 239 | } |
272 | hw_pattern[pat].count++; /* increase reference count */ | 240 | lcd_patterns[pat].count++; /* increase reference count */ |
273 | return pat; | 241 | return pat; |
274 | } | 242 | } |
275 | else /* hardware char */ | 243 | else /* hardware char */ |
@@ -278,18 +246,12 @@ static int map_xchar(int xchar) | |||
278 | 246 | ||
279 | static void lcd_putxchar(int x, int y, int xchar) | 247 | static void lcd_putxchar(int x, int y, int xchar) |
280 | { | 248 | { |
281 | int lcd_char = lcd_buffer[x][y]; | 249 | int lcd_char = lcd_charbuffer[y][x]; |
282 | 250 | ||
283 | if (lcd_char < hw_pattern_count) /* old char was soft */ | 251 | if (lcd_char < lcd_pattern_count) /* old char was soft */ |
284 | hw_pattern[lcd_char].count--; /* decrease old reference count */ | 252 | lcd_patterns[lcd_char].count--; /* decrease old reference count */ |
285 | 253 | ||
286 | lcd_buffer[x][y] = lcd_char = map_xchar(xchar); | 254 | lcd_charbuffer[y][x] = map_xchar(xchar); |
287 | #ifdef SIMULATOR | ||
288 | hardware_buffer_lcd[x][y] = lcd_char; | ||
289 | lcd_update(); | ||
290 | #else | ||
291 | lcd_put_hw_char(x, y, lcd_char); | ||
292 | #endif | ||
293 | } | 255 | } |
294 | 256 | ||
295 | /** user-definable pattern handling **/ | 257 | /** user-definable pattern handling **/ |
@@ -332,7 +294,10 @@ void lcd_define_pattern(unsigned long ucs, const char *pattern) | |||
332 | memcpy(xfont_variable[index & 0x7fff], pattern, HW_PATTERN_SIZE); | 294 | memcpy(xfont_variable[index & 0x7fff], pattern, HW_PATTERN_SIZE); |
333 | pat = xchar_to_pat(xchar); | 295 | pat = xchar_to_pat(xchar); |
334 | if (pat != NO_PATTERN) | 296 | if (pat != NO_PATTERN) |
335 | lcd_define_hw_pattern(pat, pattern); | 297 | { |
298 | memcpy(lcd_patterns[pat].pattern, pattern, HW_PATTERN_SIZE); | ||
299 | lcd_update(); //FIXME: remove when lcd_update() calls are checked all over | ||
300 | } | ||
336 | } | 301 | } |
337 | } | 302 | } |
338 | 303 | ||
@@ -342,14 +307,15 @@ void lcd_define_pattern(unsigned long ucs, const char *pattern) | |||
342 | void lcd_clear_display(void) | 307 | void lcd_clear_display(void) |
343 | { | 308 | { |
344 | int x, y; | 309 | int x, y; |
345 | int xchar = find_xchar(' '); | ||
346 | 310 | ||
347 | lcd_stop_scroll(); | 311 | lcd_stop_scroll(); |
348 | lcd_remove_cursor(); | 312 | lcd_remove_cursor(); |
349 | 313 | ||
350 | for (x = 0; x < LCD_WIDTH; x++) | 314 | for (x = 0; x < LCD_WIDTH; x++) |
351 | for (y = 0; y < LCD_HEIGHT; y++) | 315 | for (y = 0; y < LCD_HEIGHT; y++) |
352 | lcd_putxchar(x, y, xchar); | 316 | lcd_putxchar(x, y, xspace); |
317 | |||
318 | lcd_update(); //FIXME: remove when lcd_update() calls are checked all over | ||
353 | } | 319 | } |
354 | 320 | ||
355 | /* Put an unicode character at the given position */ | 321 | /* Put an unicode character at the given position */ |
@@ -359,38 +325,34 @@ void lcd_putc(int x, int y, unsigned long ucs) | |||
359 | return; | 325 | return; |
360 | 326 | ||
361 | lcd_putxchar(x, y, find_xchar(ucs)); | 327 | lcd_putxchar(x, y, find_xchar(ucs)); |
328 | lcd_update(); //FIXME: remove when lcd_update() calls are checked all over | ||
362 | } | 329 | } |
363 | 330 | ||
364 | /* Show cursor (alternating with existing character) at the given position */ | 331 | /* Show cursor (alternating with existing character) at the given position */ |
365 | void lcd_put_cursor(int x, int y, unsigned long cursor_ucs) | 332 | void lcd_put_cursor(int x, int y, unsigned long cursor_ucs) |
366 | { | 333 | { |
367 | if ((unsigned)x >= LCD_WIDTH || (unsigned)y >= LCD_HEIGHT | 334 | if ((unsigned)x >= LCD_WIDTH || (unsigned)y >= LCD_HEIGHT |
368 | || cursor.enabled) | 335 | || lcd_cursor.enabled) |
369 | return; | 336 | return; |
370 | 337 | ||
371 | cursor.enabled = true; | 338 | lcd_cursor.enabled = true; |
372 | cursor.visible = false; | 339 | lcd_cursor.visible = false; |
373 | cursor.hw_char = map_xchar(find_xchar(cursor_ucs)); | 340 | lcd_cursor.hw_char = map_xchar(find_xchar(cursor_ucs)); |
374 | cursor.x = x; | 341 | lcd_cursor.x = x; |
375 | cursor.y = y; | 342 | lcd_cursor.y = y; |
376 | cursor.downcount = 0; | 343 | lcd_cursor.downcount = 0; |
377 | cursor.divider = 4; | 344 | lcd_cursor.divider = 4; |
378 | } | 345 | } |
379 | 346 | ||
380 | /* Remove the cursor */ | 347 | /* Remove the cursor */ |
381 | void lcd_remove_cursor(void) | 348 | void lcd_remove_cursor(void) |
382 | { | 349 | { |
383 | if (cursor.enabled) | 350 | if (lcd_cursor.enabled) |
384 | { | 351 | { |
385 | if (cursor.hw_char < hw_pattern_count) /* soft char, unmap */ | 352 | if (lcd_cursor.hw_char < lcd_pattern_count) /* soft char, unmap */ |
386 | hw_pattern[cursor.hw_char].count--; | 353 | lcd_patterns[lcd_cursor.hw_char].count--; |
387 | 354 | ||
388 | cursor.enabled = false; | 355 | lcd_cursor.enabled = lcd_cursor.visible = false; |
389 | #ifdef SIMULATOR | ||
390 | hardware_buffer_lcd[cursor.x][cursor.y] = lcd_buffer[cursor.x][cursor.y]; | ||
391 | #else | ||
392 | lcd_put_hw_char(cursor.x, cursor.y, lcd_buffer[cursor.x][cursor.y]); | ||
393 | #endif | ||
394 | } | 356 | } |
395 | } | 357 | } |
396 | 358 | ||
@@ -409,7 +371,7 @@ static int lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
409 | ofs--; | 371 | ofs--; |
410 | continue; | 372 | continue; |
411 | } | 373 | } |
412 | lcd_putc(x++, y, ucs); | 374 | lcd_putxchar(x++, y, find_xchar(ucs)); |
413 | } | 375 | } |
414 | return x; | 376 | return x; |
415 | } | 377 | } |
@@ -417,7 +379,11 @@ static int lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) | |||
417 | /* Put a string at a given position */ | 379 | /* Put a string at a given position */ |
418 | void lcd_putsxy(int x, int y, const unsigned char *str) | 380 | void lcd_putsxy(int x, int y, const unsigned char *str) |
419 | { | 381 | { |
382 | if ((unsigned)y >= LCD_HEIGHT) | ||
383 | return; | ||
384 | |||
420 | lcd_putsxyofs(x, y, 0, str); | 385 | lcd_putsxyofs(x, y, 0, str); |
386 | lcd_update(); //FIXME: remove when lcd_update() calls are checked all over | ||
421 | } | 387 | } |
422 | 388 | ||
423 | /*** Line oriented text output ***/ | 389 | /*** Line oriented text output ***/ |
@@ -431,15 +397,20 @@ void lcd_puts(int x, int y, const unsigned char *str) | |||
431 | /* Put a string at a given char position, skipping first offset chars */ | 397 | /* Put a string at a given char position, skipping first offset chars */ |
432 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) | 398 | void lcd_puts_offset(int x, int y, const unsigned char *str, int offset) |
433 | { | 399 | { |
434 | /* make sure scrolling is turned off on the line we are updating */ | ||
435 | scrolling_lines &= ~(1 << y); | ||
436 | |||
437 | x += xmargin; | 400 | x += xmargin; |
438 | y += ymargin; | 401 | y += ymargin; |
439 | 402 | ||
403 | if ((unsigned)y >= LCD_HEIGHT) | ||
404 | return; | ||
405 | |||
406 | /* make sure scrolling is turned off on the line we are updating */ | ||
407 | scrolling_lines &= ~(1 << y); | ||
408 | |||
440 | x = lcd_putsxyofs(x, y, offset, str); | 409 | x = lcd_putsxyofs(x, y, offset, str); |
441 | while (x < LCD_WIDTH) | 410 | while (x < LCD_WIDTH) |
442 | lcd_putc(x++, y, ' '); | 411 | lcd_putxchar(x++, y, xspace); |
412 | |||
413 | lcd_update(); //FIXME: remove when lcd_update() calls are checked all over | ||
443 | } | 414 | } |
444 | 415 | ||
445 | /** scrolling **/ | 416 | /** scrolling **/ |
@@ -536,12 +507,14 @@ static void scroll_thread(void) | |||
536 | struct scrollinfo* s; | 507 | struct scrollinfo* s; |
537 | int index; | 508 | int index; |
538 | int xpos, ypos; | 509 | int xpos, ypos; |
510 | bool update; | ||
539 | 511 | ||
540 | /* initialize scroll struct array */ | 512 | /* initialize scroll struct array */ |
541 | scrolling_lines = 0; | 513 | scrolling_lines = 0; |
542 | 514 | ||
543 | while (1) | 515 | while (1) |
544 | { | 516 | { |
517 | update = false; | ||
545 | for (index = 0; index < SCROLLABLE_LINES; index++) | 518 | for (index = 0; index < SCROLLABLE_LINES; index++) |
546 | { | 519 | { |
547 | /* really scroll? */ | 520 | /* really scroll? */ |
@@ -585,27 +558,20 @@ static void scroll_thread(void) | |||
585 | s->offset -= s->len; | 558 | s->offset -= s->len; |
586 | } | 559 | } |
587 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | 560 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); |
561 | update = true; | ||
588 | } | 562 | } |
589 | if (cursor.enabled) | 563 | if (lcd_cursor.enabled) |
590 | { | 564 | { |
591 | if (--cursor.downcount < 0) | 565 | if (--lcd_cursor.downcount < 0) |
592 | { | 566 | { |
593 | int lcd_char; | 567 | lcd_cursor.downcount = lcd_cursor.divider; |
594 | 568 | lcd_cursor.visible = !lcd_cursor.visible; | |
595 | cursor.downcount = cursor.divider; | 569 | update = true; |
596 | cursor.visible = !cursor.visible; | ||
597 | lcd_char = cursor.visible ? cursor.hw_char | ||
598 | : lcd_buffer[cursor.x][cursor.y]; | ||
599 | #ifdef SIMULATOR | ||
600 | hardware_buffer_lcd[cursor.x][cursor.y] = lcd_char; | ||
601 | #else | ||
602 | lcd_put_hw_char(cursor.x, cursor.y, lcd_char); | ||
603 | #endif | ||
604 | } | 570 | } |
605 | } | 571 | } |
606 | #ifdef SIMULATOR | 572 | if (update) |
607 | lcd_update(); | 573 | lcd_update(); |
608 | #endif | 574 | |
609 | sleep(scroll_ticks); | 575 | sleep(scroll_ticks); |
610 | } | 576 | } |
611 | } | 577 | } |
diff --git a/firmware/drivers/lcd-charset-player.c b/firmware/drivers/lcd-charset-player.c index 24c0f65ee0..8218535ac2 100644 --- a/firmware/drivers/lcd-charset-player.c +++ b/firmware/drivers/lcd-charset-player.c | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | #include "lcd-charcell.h" | 23 | #include "lcd-charcell.h" |
24 | 24 | ||
25 | int hw_pattern_count; /* actual number of user-definable hw patterns */ | 25 | int lcd_pattern_count; /* actual number of user-definable hw patterns */ |
26 | 26 | ||
27 | const struct xchar_info *xchar_info; | 27 | const struct xchar_info *xchar_info; |
28 | int xchar_info_size; /* number of entries */ | 28 | int xchar_info_size; /* number of entries */ |
@@ -1237,13 +1237,13 @@ void lcd_charset_init(void) | |||
1237 | { | 1237 | { |
1238 | if (is_new_player()) | 1238 | if (is_new_player()) |
1239 | { | 1239 | { |
1240 | hw_pattern_count = 8; | 1240 | lcd_pattern_count = 8; |
1241 | xchar_info = xchar_info_newlcd; | 1241 | xchar_info = xchar_info_newlcd; |
1242 | xchar_info_size = sizeof(xchar_info_newlcd)/sizeof(struct xchar_info); | 1242 | xchar_info_size = sizeof(xchar_info_newlcd)/sizeof(struct xchar_info); |
1243 | } | 1243 | } |
1244 | else /* old lcd */ | 1244 | else /* old lcd */ |
1245 | { | 1245 | { |
1246 | hw_pattern_count = 4; | 1246 | lcd_pattern_count = 4; |
1247 | xchar_info = xchar_info_oldlcd; | 1247 | xchar_info = xchar_info_oldlcd; |
1248 | xchar_info_size = sizeof(xchar_info_oldlcd)/sizeof(struct xchar_info); | 1248 | xchar_info_size = sizeof(xchar_info_oldlcd)/sizeof(struct xchar_info); |
1249 | } | 1249 | } |