diff options
Diffstat (limited to 'uisimulator')
-rw-r--r-- | uisimulator/common/lcd-playersim.c | 432 |
1 files changed, 124 insertions, 308 deletions
diff --git a/uisimulator/common/lcd-playersim.c b/uisimulator/common/lcd-playersim.c index 9ce20b3ec3..a2ff344345 100644 --- a/uisimulator/common/lcd-playersim.c +++ b/uisimulator/common/lcd-playersim.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include "config.h" | 19 | #include "config.h" |
20 | #include "hwcompat.h" | ||
20 | 21 | ||
21 | #include "lcd.h" | 22 | #include "lcd.h" |
22 | #include "kernel.h" | 23 | #include "kernel.h" |
@@ -30,244 +31,19 @@ | |||
30 | 31 | ||
31 | /*** definitions ***/ | 32 | /*** definitions ***/ |
32 | 33 | ||
33 | #define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00) | 34 | #define CHAR_WIDTH 6 |
34 | #define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10) | 35 | #define CHAR_HEIGHT 8 |
35 | #define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20) | 36 | #define ICON_HEIGHT 8 |
36 | #define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28) | 37 | |
37 | #define LCD_SET_DISPLAY_START_LINE ((char)0x40) | ||
38 | #define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81) | ||
39 | #define LCD_SET_SEGMENT_REMAP ((char)0xA0) | ||
40 | #define LCD_SET_LCD_BIAS ((char)0xA2) | ||
41 | #define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4) | ||
42 | #define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5) | ||
43 | #define LCD_SET_NORMAL_DISPLAY ((char)0xA6) | ||
44 | #define LCD_SET_REVERSE_DISPLAY ((char)0xA7) | ||
45 | #define LCD_SET_INDICATOR_OFF ((char)0xAC) | ||
46 | #define LCD_SET_INDICATOR_ON ((char)0xAD) | ||
47 | #define LCD_SET_DISPLAY_OFF ((char)0xAE) | ||
48 | #define LCD_SET_DISPLAY_ON ((char)0xAF) | ||
49 | #define LCD_SET_PAGE_ADDRESS ((char)0xB0) | ||
50 | #define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0) | ||
51 | #define LCD_SET_DISPLAY_OFFSET ((char)0xD3) | ||
52 | #define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0) | ||
53 | #define LCD_SOFTWARE_RESET ((char)0xE2) | ||
54 | #define LCD_NOP ((char)0xE3) | ||
55 | #define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE) | ||
56 | |||
57 | /* LCD command codes */ | ||
58 | #define LCD_CNTL_RESET 0xe2 // Software reset | ||
59 | #define LCD_CNTL_POWER 0x2f // Power control | ||
60 | #define LCD_CNTL_CONTRAST 0x81 // Contrast | ||
61 | #define LCD_CNTL_OUTSCAN 0xc8 // Output scan direction | ||
62 | #define LCD_CNTL_SEGREMAP 0xa1 // Segment remap | ||
63 | #define LCD_CNTL_DISPON 0xaf // Display on | ||
64 | |||
65 | #define LCD_CNTL_PAGE 0xb0 // Page address | ||
66 | #define LCD_CNTL_HIGHCOL 0x10 // Upper column address | ||
67 | #define LCD_CNTL_LOWCOL 0x00 // Lower column address | ||
68 | |||
69 | #define SCROLL_SPACING 3 | ||
70 | |||
71 | struct scrollinfo { | ||
72 | char line[MAX_PATH + LCD_WIDTH/2 + SCROLL_SPACING + 2]; | ||
73 | int len; /* length of line in chars */ | ||
74 | int width; /* length of line in pixels */ | ||
75 | int offset; | ||
76 | int startx; | ||
77 | int starty; | ||
78 | }; | ||
79 | |||
80 | static void scroll_thread(void); | ||
81 | static char scroll_stack[DEFAULT_STACK_SIZE]; | ||
82 | static char scroll_name[] = "scroll"; | ||
83 | static char scroll_speed = 8; /* updates per second */ | ||
84 | static char scroll_step = 6; /* pixels per scroll step */ | ||
85 | static struct scrollinfo scroll; /* only one scroll line at the moment */ | ||
86 | static int scroll_count = 0; | ||
87 | static int xmargin = 0; | ||
88 | static int ymargin = 0; | ||
89 | static int curfont = FONT_SYSFIXED; | ||
90 | |||
91 | #ifdef SIMULATOR | ||
92 | unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8]; | 38 | unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8]; |
93 | #else | ||
94 | static unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8]; | ||
95 | #endif | ||
96 | 39 | ||
97 | /* All zeros and ones bitmaps for area filling */ | 40 | /* All zeros and ones bitmaps for area filling */ |
98 | static unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | 41 | static unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
99 | static unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff, | 42 | static unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff, |
100 | 0xff, 0xff, 0xff, 0xff}; | 43 | 0xff, 0xff, 0xff, 0xff}; |
101 | 44 | ||
102 | void lcd_init(void) | 45 | static int double_height=1; |
103 | { | ||
104 | create_thread(scroll_thread, scroll_stack, | ||
105 | sizeof(scroll_stack), scroll_name); | ||
106 | } | ||
107 | void lcd_clear_display (void) | ||
108 | { | ||
109 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); | ||
110 | } | ||
111 | |||
112 | void lcd_setmargins(int x, int y) | ||
113 | { | ||
114 | xmargin = x; | ||
115 | ymargin = y; | ||
116 | } | ||
117 | |||
118 | int lcd_getxmargin(void) | ||
119 | { | ||
120 | return xmargin; | ||
121 | } | ||
122 | |||
123 | int lcd_getymargin(void) | ||
124 | { | ||
125 | return ymargin; | ||
126 | } | ||
127 | |||
128 | void lcd_setfont(int newfont) | ||
129 | { | ||
130 | curfont = newfont; | ||
131 | } | ||
132 | |||
133 | int lcd_getstringsize(unsigned char *str, int *w, int *h) | ||
134 | { | ||
135 | struct font* pf = font_get(curfont); | ||
136 | int ch; | ||
137 | int width = 0; | ||
138 | |||
139 | while((ch = *str++)) { | ||
140 | /* check input range*/ | ||
141 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | ||
142 | ch = pf->defaultchar; | ||
143 | ch -= pf->firstchar; | ||
144 | |||
145 | /* get proportional width and glyph bits*/ | ||
146 | width += pf->width? pf->width[ch]: pf->maxwidth; | ||
147 | } | ||
148 | if ( w ) | ||
149 | *w = width; | ||
150 | if ( h ) | ||
151 | *h = pf->height; | ||
152 | |||
153 | return width; | ||
154 | } | ||
155 | |||
156 | /* put a string at a given char position */ | ||
157 | void lcd_puts(int x, int y, unsigned char *str) | ||
158 | { | ||
159 | int xpos,ypos,w,h; | ||
160 | |||
161 | #if defined(HAVE_LCD_CHARCELLS) | ||
162 | /* We make the simulator truncate the string if it reaches the right edge, | ||
163 | as otherwise it'll wrap. The real target doesn't wrap. */ | ||
164 | |||
165 | char buffer[12]; | ||
166 | if(strlen(str)+x > 11 ) { | ||
167 | strncpy(buffer, str, sizeof buffer); | ||
168 | buffer[11-x]=0; | ||
169 | str = buffer; | ||
170 | } | ||
171 | xmargin = 0; | ||
172 | ymargin = 8; | ||
173 | #endif | ||
174 | |||
175 | if(!str || !str[0]) | ||
176 | return; | ||
177 | |||
178 | lcd_getstringsize(str, &w, &h); | ||
179 | xpos = xmargin + x*w / strlen(str); | ||
180 | ypos = ymargin + y*h; | ||
181 | lcd_putsxy(xpos, ypos, str); | ||
182 | /* lcd_clearrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); */ | ||
183 | |||
184 | #if defined(HAVE_LCD_CHARCELLS) | ||
185 | /* this function is being used when simulating a charcell LCD and | ||
186 | then we update immediately */ | ||
187 | lcd_update(); | ||
188 | #endif | ||
189 | } | ||
190 | |||
191 | extern char* get_lcd_pattern(int width); | ||
192 | |||
193 | /* put a string at a given pixel position, skipping first ofs pixel columns */ | ||
194 | static void lcd_putsxyofs(int x, int y, int ofs, unsigned char *str) | ||
195 | { | ||
196 | int ch; | ||
197 | struct font* pf = font_get(curfont); | ||
198 | |||
199 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) | ||
200 | { | ||
201 | int width; | ||
202 | |||
203 | /* check input range */ | ||
204 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | ||
205 | #ifndef SIMULATOR | ||
206 | ch = pf->defaultchar; | ||
207 | #else | ||
208 | { | ||
209 | if (ch > 8) | ||
210 | ch = pf->defaultchar; | ||
211 | else | ||
212 | { | ||
213 | char* bm = get_lcd_pattern(ch); | ||
214 | width = 6; | ||
215 | lcd_bitmap(bm, x, y, width, 8, true); | ||
216 | x += width; | ||
217 | continue; | ||
218 | } | ||
219 | } | ||
220 | #endif | ||
221 | ch -= pf->firstchar; | ||
222 | |||
223 | /* no partial-height drawing for now... */ | ||
224 | if (y + pf->height > LCD_HEIGHT) | ||
225 | break; | ||
226 | |||
227 | /* get proportional width and glyph bits */ | ||
228 | width = pf->width ? pf->width[ch] : pf->maxwidth; | ||
229 | width = MIN (width, LCD_WIDTH - x); | ||
230 | |||
231 | if (ofs != 0) | ||
232 | { | ||
233 | if (ofs > width) | ||
234 | { | ||
235 | ofs -= width; | ||
236 | continue; | ||
237 | } | ||
238 | width -= ofs; | ||
239 | } | ||
240 | |||
241 | if (width > 0) | ||
242 | { | ||
243 | int rows = (pf->height + 7) / 8; | ||
244 | bitmap_t* bits = pf->bits + | ||
245 | (pf->offset ? pf->offset[ch] : (pf->height * ch)); | ||
246 | lcd_bitmap (((unsigned char*) bits) + ofs*rows, x, y, | ||
247 | width, pf->height, true); | ||
248 | x += width; | ||
249 | } | ||
250 | ofs = 0; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /* put a string at a given pixel position */ | ||
255 | void lcd_putsxy(int x, int y, unsigned char *str) | ||
256 | { | ||
257 | lcd_putsxyofs(x, y, 0, str); | ||
258 | } | ||
259 | 46 | ||
260 | /* | ||
261 | * All bitmaps have this format: | ||
262 | * Bits within a byte are arranged veritcally, LSB at top. | ||
263 | * Bytes are stored in column-major format, with byte 0 at top left, | ||
264 | * byte 1 is 2nd from top, etc. Bytes following left-most column | ||
265 | * starts 2nd left column, etc. | ||
266 | * | ||
267 | * Note: The HW takes bitmap bytes in row-major order. | ||
268 | * | ||
269 | * Memory copy of display bitmap | ||
270 | */ | ||
271 | 47 | ||
272 | /* | 48 | /* |
273 | * Draw a bitmap at (x, y), size (nx, ny) | 49 | * Draw a bitmap at (x, y), size (nx, ny) |
@@ -575,106 +351,146 @@ void lcd_invertpixel(int x, int y) | |||
575 | INVERT_PIXEL(x,y); | 351 | INVERT_PIXEL(x,y); |
576 | } | 352 | } |
577 | 353 | ||
578 | void lcd_puts_scroll(int x, int y, unsigned char* string ) | 354 | void lcd_clear_display(void) |
579 | { | 355 | { |
580 | struct scrollinfo* s = &scroll; | 356 | memset (lcd_framebuffer, 0, sizeof lcd_framebuffer); |
581 | int w, h; | 357 | } |
582 | 358 | ||
583 | lcd_puts(x,y,string); | 359 | /* put a string at a given pixel position, skipping first ofs pixel columns */ |
584 | lcd_getstringsize(string, &w, &h); | 360 | static void lcd_putsxyofs(int x, int y, int ofs, unsigned char *str) |
361 | { | ||
362 | int ch; | ||
363 | struct font* pf = font_get(2); | ||
585 | 364 | ||
586 | if ((LCD_WIDTH - x*6 - xmargin) < w) | 365 | while ((ch = *str++) != '\0' && x < LCD_WIDTH) |
587 | { | 366 | { |
588 | /* prepare scroll line */ | 367 | int width; |
589 | char *end; | ||
590 | |||
591 | memset(s->line, 0, sizeof s->line); | ||
592 | strcpy(s->line, string); | ||
593 | strcat(s->line, " "); | ||
594 | /* get new width incl. spaces */ | ||
595 | s->width = lcd_getstringsize(s->line, &w, &h); | ||
596 | |||
597 | for (end = s->line; *end; end++); | ||
598 | strncpy(end, string, LCD_WIDTH/2); | ||
599 | |||
600 | s->len = strlen(string); | ||
601 | s->offset = 0; | ||
602 | s->startx = x; | ||
603 | s->starty = y; | ||
604 | scroll_count = 1; | ||
605 | } | ||
606 | } | ||
607 | 368 | ||
369 | /* check input range */ | ||
370 | if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) | ||
371 | ch = pf->defaultchar; | ||
372 | ch -= pf->firstchar; | ||
608 | 373 | ||
609 | void lcd_stop_scroll(void) | 374 | /* no partial-height drawing for now... */ |
610 | { | 375 | if (y + pf->height > LCD_HEIGHT) |
611 | if ( scroll_count ) { | 376 | break; |
612 | int w,h; | 377 | |
613 | struct scrollinfo* s = &scroll; | 378 | /* get proportional width and glyph bits */ |
614 | scroll_count = 0; | 379 | width = pf->width ? pf->width[ch] : pf->maxwidth; |
615 | 380 | width = MIN (width, LCD_WIDTH - x); | |
616 | lcd_getstringsize(s->line, &w, &h); | 381 | |
617 | lcd_clearrect(xmargin + s->startx*w/s->len, | 382 | if (ofs != 0) |
618 | ymargin + s->starty*h, | 383 | { |
619 | LCD_WIDTH - xmargin, | 384 | if (ofs > width) |
620 | h); | 385 | { |
621 | 386 | ofs -= width; | |
622 | /* restore scrolled row */ | 387 | continue; |
623 | lcd_puts(s->startx,s->starty,s->line); | 388 | } |
624 | lcd_update(); | 389 | width -= ofs; |
390 | } | ||
391 | |||
392 | if (width > 0) | ||
393 | { | ||
394 | int rows = (pf->height + 7) / 8; | ||
395 | bitmap_t* bits = pf->bits + | ||
396 | (pf->offset ? pf->offset[ch] : (pf->height * ch)); | ||
397 | lcd_bitmap (((unsigned char*) bits) + ofs*rows, x, y, | ||
398 | width, pf->height, true); | ||
399 | x += width; | ||
400 | } | ||
401 | ofs = 0; | ||
625 | } | 402 | } |
626 | } | 403 | } |
627 | 404 | ||
628 | void lcd_scroll_pause(void) | 405 | /* put a string at a given pixel position */ |
406 | void lcd_putsxy(int x, int y, unsigned char *str) | ||
629 | { | 407 | { |
630 | scroll_count = 0; | 408 | lcd_putsxyofs(x, y, 0, str); |
631 | } | 409 | } |
632 | 410 | ||
633 | void lcd_scroll_resume(void) | 411 | void lcd_puts(int x, int y, unsigned char *str) |
634 | { | 412 | { |
635 | scroll_count = 1; | 413 | int xpos,ypos; |
414 | |||
415 | /* We make the simulator truncate the string if it reaches the right edge, | ||
416 | as otherwise it'll wrap. The real target doesn't wrap. */ | ||
417 | |||
418 | char buffer[12]; | ||
419 | if(strlen(str)+x > 11 ) { | ||
420 | strncpy(buffer, str, sizeof buffer); | ||
421 | buffer[11-x]=0; | ||
422 | str = buffer; | ||
423 | } | ||
424 | |||
425 | xpos = CHAR_WIDTH * x; | ||
426 | ypos = ICON_HEIGHT + CHAR_HEIGHT * y; | ||
427 | lcd_clearrect(xpos, ypos, LCD_WIDTH - xpos, CHAR_HEIGHT * double_height); | ||
428 | lcd_putsxy(xpos, ypos, str); | ||
429 | |||
430 | /* this function is being used when simulating a charcell LCD and | ||
431 | then we update immediately */ | ||
432 | lcd_update(); | ||
636 | } | 433 | } |
637 | 434 | ||
638 | void lcd_scroll_speed(int speed) | 435 | void lcd_double_height(bool on) |
639 | { | 436 | { |
640 | scroll_step = speed; | 437 | double_height = 1; |
438 | if (on) | ||
439 | double_height = 2; | ||
641 | } | 440 | } |
642 | 441 | ||
643 | static void scroll_thread(void) | 442 | static char patterns[8][7]; |
644 | { | ||
645 | struct scrollinfo* s = &scroll; | ||
646 | 443 | ||
647 | while ( 1 ) { | 444 | void lcd_define_pattern(int which, char *pattern, int length) |
648 | if ( !scroll_count ) { | 445 | { |
649 | yield(); | 446 | int i, j; |
650 | continue; | 447 | int pat = which / 8; |
448 | char icon[8]; | ||
449 | memset(icon, 0, sizeof icon); | ||
450 | |||
451 | DEBUGF("Defining pattern %d\n", pat); | ||
452 | for (j = 0; j <= 5; j++) { | ||
453 | for (i = 0; i < length; i++) { | ||
454 | if ((pattern[i])&(1<<(j))) | ||
455 | icon[5-j] |= (1<<(i)); | ||
651 | } | 456 | } |
652 | /* wait 0.5s before starting scroll */ | 457 | } |
653 | if ( scroll_count < scroll_speed/2 ) | 458 | for (i = 0; i <= 5; i++) |
654 | scroll_count++; | 459 | { |
655 | else { | 460 | patterns[pat][i] = icon[i]; |
656 | int w, h; | 461 | } |
657 | int xpos, ypos; | 462 | } |
658 | |||
659 | s->offset += scroll_step; | ||
660 | 463 | ||
661 | if (s->offset >= s->width) | 464 | char* get_lcd_pattern(int which) |
662 | s->offset %= s->width; | 465 | { |
466 | DEBUGF("Get pattern %d\n", which); | ||
467 | return patterns[which]; | ||
468 | } | ||
663 | 469 | ||
664 | lcd_getstringsize(s->line, &w, &h); | 470 | extern void lcd_puts(int x, int y, unsigned char *str); |
665 | xpos = xmargin + s->startx * s->width / s->len; | ||
666 | ypos = ymargin + s->starty * h; | ||
667 | 471 | ||
668 | lcd_clearrect(xpos, ypos, LCD_WIDTH - xmargin, h); | 472 | void lcd_putc(int x, int y, unsigned char ch) |
669 | lcd_putsxyofs(xpos, ypos, s->offset, s->line); | 473 | { |
670 | lcd_update(); | 474 | char str[2]; |
671 | } | 475 | int xpos = x * CHAR_WIDTH; |
672 | sleep(HZ/scroll_speed); | 476 | int ypos = ICON_HEIGHT + y * CHAR_HEIGHT; |
477 | if (ch <= 8) | ||
478 | { | ||
479 | char* bm = get_lcd_pattern(ch); | ||
480 | lcd_bitmap(bm, xpos, ypos, CHAR_WIDTH, CHAR_HEIGHT, true); | ||
481 | return; | ||
673 | } | 482 | } |
674 | } | 483 | if (ch == 137) { |
484 | /* Have no good font yet. Simulate the cursor character. */ | ||
485 | ch = '>'; | ||
486 | } | ||
487 | str[0] = ch; | ||
488 | str[1] = 0; | ||
675 | 489 | ||
676 | /* ----------------------------------------------------------------- | 490 | lcd_clearrect(xpos, ypos, CHAR_WIDTH, CHAR_HEIGHT * double_height); |
677 | * local variables: | 491 | lcd_putsxy(xpos, ypos, str); |
678 | * eval: (load-file "../rockbox-mode.el") | 492 | |
679 | * end: | 493 | /* this function is being used when simulating a charcell LCD and |
680 | */ | 494 | then we update immediately */ |
495 | lcd_update(); | ||
496 | } | ||