summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--uisimulator/common/lcd-playersim.c432
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
71struct 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
80static void scroll_thread(void);
81static char scroll_stack[DEFAULT_STACK_SIZE];
82static char scroll_name[] = "scroll";
83static char scroll_speed = 8; /* updates per second */
84static char scroll_step = 6; /* pixels per scroll step */
85static struct scrollinfo scroll; /* only one scroll line at the moment */
86static int scroll_count = 0;
87static int xmargin = 0;
88static int ymargin = 0;
89static int curfont = FONT_SYSFIXED;
90
91#ifdef SIMULATOR
92unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8]; 38unsigned char lcd_framebuffer[LCD_WIDTH][LCD_HEIGHT/8];
93#else
94static 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 */
98static unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 41static unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
99static unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff, 42static unsigned char ones[8] = { 0xff, 0xff, 0xff, 0xff,
100 0xff, 0xff, 0xff, 0xff}; 43 0xff, 0xff, 0xff, 0xff};
101 44
102void lcd_init(void) 45static int double_height=1;
103{
104 create_thread(scroll_thread, scroll_stack,
105 sizeof(scroll_stack), scroll_name);
106}
107void lcd_clear_display (void)
108{
109 memset (lcd_framebuffer, 0, sizeof lcd_framebuffer);
110}
111
112void lcd_setmargins(int x, int y)
113{
114 xmargin = x;
115 ymargin = y;
116}
117
118int lcd_getxmargin(void)
119{
120 return xmargin;
121}
122
123int lcd_getymargin(void)
124{
125 return ymargin;
126}
127
128void lcd_setfont(int newfont)
129{
130 curfont = newfont;
131}
132
133int 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 */
157void 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
191extern char* get_lcd_pattern(int width);
192
193/* put a string at a given pixel position, skipping first ofs pixel columns */
194static 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 */
255void 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
578void lcd_puts_scroll(int x, int y, unsigned char* string ) 354void 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); 360static 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
609void 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
628void lcd_scroll_pause(void) 405/* put a string at a given pixel position */
406void 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
633void lcd_scroll_resume(void) 411void 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
638void lcd_scroll_speed(int speed) 435void 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
643static void scroll_thread(void) 442static char patterns[8][7];
644{
645 struct scrollinfo* s = &scroll;
646 443
647 while ( 1 ) { 444void 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) 464char* 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); 470extern 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); 472void 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}