summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/lcd-16bit.c305
1 files changed, 39 insertions, 266 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index 933d02e64a..9e2bf11446 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -34,13 +34,13 @@
34 34
35#define SCROLLABLE_LINES 26 35#define SCROLLABLE_LINES 26
36 36
37#define RGB_PACK(r,g,b) (swap16(((r>>3)<<11)|((g>>2)<<5)|(b>>3))) 37#define RGB_PACK(r,g,b) (htobe16(((r>>3)<<11)|((g>>2)<<5)|(b>>3)))
38 38
39/*** globals ***/ 39/*** globals ***/
40unsigned char lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH*2] __attribute__ ((aligned (2))); 40fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH] __attribute__ ((aligned (2)));
41 41
42static unsigned fg_pattern = 0x0000; /* Black */ 42static unsigned fg_pattern = 0x0000; /* Black */
43static unsigned bg_pattern = 0xbc2d; /* "Rockbox blue" */ 43static unsigned bg_pattern = RGB_PACK(0xb6, 0xc6, 0xe5); /* "Rockbox blue" */
44static int drawmode = DRMODE_SOLID; 44static int drawmode = DRMODE_SOLID;
45static int xmargin = 0; 45static int xmargin = 0;
46static int ymargin = 0; 46static int ymargin = 0;
@@ -155,14 +155,12 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h)
155 155
156static void setpixel(int x, int y) 156static void setpixel(int x, int y)
157{ 157{
158 unsigned short *data = (unsigned short*)&lcd_framebuffer[y][x*2]; 158 lcd_framebuffer[y][x] = fg_pattern;
159 *data = fg_pattern;
160} 159}
161 160
162static void clearpixel(int x, int y) 161static void clearpixel(int x, int y)
163{ 162{
164 unsigned short *data = (unsigned short*)&lcd_framebuffer[y][x*2]; 163 lcd_framebuffer[y][x] = bg_pattern;
165 *data = bg_pattern;
166} 164}
167 165
168static void flippixel(int x, int y) 166static void flippixel(int x, int y)
@@ -184,82 +182,6 @@ lcd_pixelfunc_type* const lcd_pixelfuncs[8] = {
184 nopixel, clearpixel, nopixel, clearpixel 182 nopixel, clearpixel, nopixel, clearpixel
185}; 183};
186 184
187/* 'mask' and 'bits' contain 2 bits per pixel */
188static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
189 ICODE_ATTR;
190static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
191{
192 *address ^= bits & mask;
193}
194
195static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
196 ICODE_ATTR;
197static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
198{
199 (void)bits;
200 if (mask > 0) {
201 *address = bg_pattern;
202 } else {
203 *address = fg_pattern;
204 }
205}
206
207static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
208 ICODE_ATTR;
209static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
210{
211 (void)bits;
212 if (mask > 0) {
213 *address = fg_pattern;
214 } else {
215 *address = bg_pattern;
216 }
217}
218
219static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
220 ICODE_ATTR;
221static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
222{
223 *address = (*address & ~mask) | (bits & mask & fg_pattern)
224 | (~bits & mask & bg_pattern);
225}
226
227static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
228 ICODE_ATTR;
229static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
230{
231 *address ^= ~bits & mask;
232}
233
234static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
235 ICODE_ATTR;
236static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
237{
238 mask &= bits;
239 *address = (*address & ~mask) | (bg_pattern & mask);
240}
241
242static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
243 ICODE_ATTR;
244static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
245{
246 mask &= ~bits;
247 *address = (*address & ~mask) | (fg_pattern & mask);
248}
249
250static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
251 ICODE_ATTR;
252static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
253{
254 *address = (*address & ~mask) | (~bits & mask & fg_pattern)
255 | (bits & mask & bg_pattern);
256}
257
258lcd_blockfunc_type* const lcd_blockfuncs[8] = {
259 flipblock, bgblock, fgblock, solidblock,
260 flipinvblock, bginvblock, fginvblock, solidinvblock
261};
262
263/*** drawing functions ***/ 185/*** drawing functions ***/
264 186
265/* Clear the whole display */ 187/* Clear the whole display */
@@ -267,7 +189,7 @@ void lcd_clear_display(void)
267{ 189{
268 int i; 190 int i;
269 unsigned short bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; 191 unsigned short bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern;
270 unsigned short* addr = (unsigned short*)lcd_framebuffer; 192 unsigned short* addr = (unsigned short *)lcd_framebuffer;
271 193
272 for (i=0;i<LCD_HEIGHT*LCD_WIDTH;i++) { 194 for (i=0;i<LCD_HEIGHT*LCD_WIDTH;i++) {
273 *(addr++)=bits; 195 *(addr++)=bits;
@@ -357,9 +279,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
357void lcd_hline(int x1, int x2, int y) 279void lcd_hline(int x1, int x2, int y)
358{ 280{
359 int x; 281 int x;
360 unsigned char *dst, *dst_end; 282 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode];
361 unsigned mask;
362 lcd_blockfunc_type *bfunc;
363 283
364 /* direction flip */ 284 /* direction flip */
365 if (x2 < x1) 285 if (x2 < x1)
@@ -379,30 +299,23 @@ void lcd_hline(int x1, int x2, int y)
379 if (x2 >= LCD_WIDTH) 299 if (x2 >= LCD_WIDTH)
380 x2 = LCD_WIDTH-1; 300 x2 = LCD_WIDTH-1;
381 301
382 bfunc = lcd_blockfuncs[drawmode];
383 dst = &lcd_framebuffer[y>>2][x1];
384 mask = 3 << (2 * (y & 3));
385
386 dst_end = dst + x2 - x1;
387 do 302 do
388 bfunc(dst++, mask, 0xFFu); 303 pfunc(x1++, y);
389 while (dst <= dst_end); 304 while (x1 <= x2);
390} 305}
391 306
392/* Draw a vertical line (optimised) */ 307/* Draw a vertical line (optimised) */
393void lcd_vline(int x, int y1, int y2) 308void lcd_vline(int x, int y1, int y2)
394{ 309{
395 int ny; 310 int y;
396 unsigned char *dst; 311 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode];
397 unsigned mask, mask_bottom;
398 lcd_blockfunc_type *bfunc;
399 312
400 /* direction flip */ 313 /* direction flip */
401 if (y2 < y1) 314 if (y2 < y1)
402 { 315 {
403 ny = y1; 316 y = y1;
404 y1 = y2; 317 y1 = y2;
405 y2 = ny; 318 y2 = y;
406 } 319 }
407 320
408 /* nothing to draw? */ 321 /* nothing to draw? */
@@ -415,20 +328,10 @@ void lcd_vline(int x, int y1, int y2)
415 if (y2 >= LCD_HEIGHT) 328 if (y2 >= LCD_HEIGHT)
416 y2 = LCD_HEIGHT-1; 329 y2 = LCD_HEIGHT-1;
417 330
418 bfunc = lcd_blockfuncs[drawmode];
419 dst = &lcd_framebuffer[y1>>2][x];
420 ny = y2 - (y1 & ~3);
421 mask = 0xFFu << (2 * (y1 & 3));
422 mask_bottom = 0xFFu >> (2 * (~ny & 3));
423 331
424 for (; ny >= 4; ny -= 4) 332 do
425 { 333 pfunc(x, y1++);
426 bfunc(dst, mask, 0xFFu); 334 while (y1 <= y2);
427 dst += LCD_WIDTH;
428 mask = 0xFFu;
429 }
430 mask &= mask_bottom;
431 bfunc(dst, mask, 0xFFu);
432} 335}
433 336
434/* Draw a rectangular box */ 337/* Draw a rectangular box */
@@ -449,12 +352,8 @@ void lcd_drawrect(int x, int y, int width, int height)
449/* Fill a rectangular area */ 352/* Fill a rectangular area */
450void lcd_fillrect(int x, int y, int width, int height) 353void lcd_fillrect(int x, int y, int width, int height)
451{ 354{
452 int ny; 355 int nx, ny;
453 unsigned char *dst, *dst_end; 356 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode];
454 unsigned mask, mask_bottom;
455 unsigned bits = fg_pattern;
456 lcd_blockfunc_type *bfunc;
457 bool fillopt;
458 357
459 /* nothing to draw? */ 358 /* nothing to draw? */
460 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) 359 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
@@ -476,44 +375,14 @@ void lcd_fillrect(int x, int y, int width, int height)
476 width = LCD_WIDTH - x; 375 width = LCD_WIDTH - x;
477 if (y + height > LCD_HEIGHT) 376 if (y + height > LCD_HEIGHT)
478 height = LCD_HEIGHT - y; 377 height = LCD_HEIGHT - y;
479
480 fillopt = (drawmode & DRMODE_INVERSEVID) ?
481 (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG);
482 if (fillopt &&(drawmode & DRMODE_INVERSEVID))
483 bits = bg_pattern;
484 bfunc = lcd_blockfuncs[drawmode];
485 dst = &lcd_framebuffer[y>>2][x];
486 ny = height - 1 + (y & 3);
487 mask = 0xFFu << (2 * (y & 3));
488 mask_bottom = 0xFFu >> (2 * (~ny & 3));
489
490 for (; ny >= 4; ny -= 4)
491 {
492 if (fillopt && (mask == 0xFFu))
493 memset(dst, bits, width);
494 else
495 {
496 unsigned char *dst_row = dst;
497
498 dst_end = dst_row + width;
499 do
500 bfunc(dst_row++, mask, 0xFFu);
501 while (dst_row < dst_end);
502 }
503
504 dst += LCD_WIDTH;
505 mask = 0xFFu;
506 }
507 mask &= mask_bottom;
508 378
509 if (fillopt && (mask == 0xFFu)) 379 ny = y + height;
510 memset(dst, bits, width); 380 for(;y < ny;y++)
511 else
512 { 381 {
513 dst_end = dst + width; 382 int xc;
514 do 383 nx = x + width;
515 bfunc(dst++, mask, 0xFFu); 384 for(xc = x;xc < nx;xc++)
516 while (dst < dst_end); 385 pfunc(x, y);
517 } 386 }
518} 387}
519 388
@@ -541,7 +410,7 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
541 int out_x; 410 int out_x;
542 int out_y; 411 int out_y;
543 unsigned char pixel; 412 unsigned char pixel;
544 unsigned short* addr; 413 fb_data * addr;
545 414
546 (void)stride; 415 (void)stride;
547 /* nothing to draw? */ 416 /* nothing to draw? */
@@ -575,7 +444,7 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
575 in_y=src_y; 444 in_y=src_y;
576 for (out_y=y;out_y<(y+height);out_y++) { 445 for (out_y=y;out_y<(y+height);out_y++) {
577 pixel=(*src)&masks[in_y]; 446 pixel=(*src)&masks[in_y];
578 addr=(unsigned short*)&lcd_framebuffer[out_y][out_x*2]; 447 addr=&lcd_framebuffer[out_y][out_x];
579 if (pixel > 0) { 448 if (pixel > 0) {
580 *addr=fg_pattern; 449 *addr=fg_pattern;
581 } else { 450 } else {
@@ -595,123 +464,27 @@ void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int heig
595} 464}
596 465
597/* Draw a partial native bitmap */ 466/* Draw a partial native bitmap */
598void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, 467void lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
599 int stride, int x, int y, int width, int height) 468 int stride, int x, int y, int width, int height)
600 ICODE_ATTR; 469 ICODE_ATTR;
601void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, 470void lcd_bitmap_part(const fb_data *src, int src_x, int src_y,
602 int stride, int x, int y, int width, int height) 471 int stride, int x, int y, int width, int height)
603{ 472{
604 int shift, ny; 473 (void)src;
605 unsigned char *dst, *dst_end; 474 (void)src_x;
606 unsigned mask, mask_bottom; 475 (void)src_y;
607 lcd_blockfunc_type *bfunc; 476 (void)stride;
608 477 (void)x;
609 /* nothing to draw? */ 478 (void)y;
610 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) 479 (void)width;
611 || (x + width <= 0) || (y + height <= 0)) 480 (void)height;
612 return;
613
614 /* clipping */
615 if (x < 0)
616 {
617 width += x;
618 src_x -= x;
619 x = 0;
620 }
621 if (y < 0)
622 {
623 height += y;
624 src_y -= y;
625 y = 0;
626 }
627 if (x + width > LCD_WIDTH)
628 width = LCD_WIDTH - x;
629 if (y + height > LCD_HEIGHT)
630 height = LCD_HEIGHT - y;
631
632 src += stride * (src_y >> 2) + src_x; /* move starting point */
633 src_y &= 3;
634 y -= src_y;
635 dst = &lcd_framebuffer[y>>2][x];
636 shift = y & 3;
637 ny = height - 1 + shift + src_y;
638
639 bfunc = lcd_blockfuncs[drawmode];
640 mask = 0xFFu << (2 * (shift + src_y));
641 mask_bottom = 0xFFu >> (2 * (~ny & 3));
642
643 if (shift == 0)
644 {
645 for (; ny >= 4; ny -= 4)
646 {
647 if (mask == 0xFFu)
648 memcpy(dst, src, width);
649 else
650 {
651 const unsigned char *src_row = src;
652 unsigned char *dst_row = dst;
653
654 dst_end = dst_row + width;
655 do
656 bfunc(dst_row++, mask, *src_row++);
657 while (dst_row < dst_end);
658 }
659
660 src += stride;
661 dst += LCD_WIDTH;
662 mask = 0xFFu;
663 }
664 mask &= mask_bottom;
665
666 if (mask == 0xFFu)
667 memcpy(dst, src, width);
668 else
669 {
670 dst_end = dst + width;
671 do
672 bfunc(dst++, mask, *src++);
673 while (dst < dst_end);
674 }
675 }
676 else
677 {
678 shift *= 2;
679 dst_end = dst + width;
680 do
681 {
682 const unsigned char *src_col = src++;
683 unsigned char *dst_col = dst++;
684 unsigned mask_col = mask;
685 unsigned data = 0;
686
687 for (y = ny; y >= 4; y -= 4)
688 {
689 data |= *src_col << shift;
690
691 if (mask_col & 0xFFu)
692 {
693 bfunc(dst_col, mask_col, data);
694 mask_col = 0xFFu;
695 }
696 else
697 mask_col >>= 8;
698
699 src_col += stride;
700 dst_col += LCD_WIDTH;
701 data >>= 8;
702 }
703 data |= *src_col << shift;
704 bfunc(dst_col, mask_col & mask_bottom, data);
705 }
706 while (dst < dst_end);
707 }
708} 481}
709 482
710/* Draw a full native bitmap */ 483/* Draw a full native bitmap */
711void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) 484void lcd_bitmap(const fb_data *src, int x, int y, int width, int height)
712{ 485{
713 unsigned short* s=(unsigned short*)src; 486 fb_data* s=(fb_data *)src;
714 unsigned short* d=(unsigned short*)&lcd_framebuffer[y][x*2]; 487 fb_data* d=&lcd_framebuffer[y][x];
715 int k=LCD_WIDTH-width; 488 int k=LCD_WIDTH-width;
716 int i,j; 489 int i,j;
717 490