summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-16bit.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/lcd-16bit.c')
-rw-r--r--firmware/drivers/lcd-16bit.c193
1 files changed, 140 insertions, 53 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index 9b700a0669..c3e076b392 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -428,7 +428,6 @@ void lcd_hline(int x1, int x2, int y)
428 unsigned bits = 0; 428 unsigned bits = 0;
429 enum fill_opt fillopt = OPT_NONE; 429 enum fill_opt fillopt = OPT_NONE;
430 fb_data *dst, *dst_end; 430 fb_data *dst, *dst_end;
431 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
432 431
433 /* direction flip */ 432 /* direction flip */
434 if (x2 < x1) 433 if (x2 < x1)
@@ -444,18 +443,7 @@ void lcd_hline(int x1, int x2, int y)
444 (x2 < 0)) 443 (x2 < 0))
445 return; 444 return;
446 445
447 /* clipping */ 446 /* drawmode and optimisation */
448 if (x1 < 0)
449 x1 = 0;
450 if (x2 >= current_vp->width)
451 x2 = current_vp->width-1;
452
453 width = x2 - x1 + 1;
454
455 /* Adjust x1 and y to viewport */
456 x1 += current_vp->x;
457 y += current_vp->y;
458
459 if (current_vp->drawmode & DRMODE_INVERSEVID) 447 if (current_vp->drawmode & DRMODE_INVERSEVID)
460 { 448 {
461 if (current_vp->drawmode & DRMODE_BG) 449 if (current_vp->drawmode & DRMODE_BG)
@@ -477,6 +465,21 @@ void lcd_hline(int x1, int x2, int y)
477 bits = current_vp->fg_pattern; 465 bits = current_vp->fg_pattern;
478 } 466 }
479 } 467 }
468 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
469 return;
470
471 /* clipping */
472 if (x1 < 0)
473 x1 = 0;
474 if (x2 >= current_vp->width)
475 x2 = current_vp->width-1;
476
477 width = x2 - x1 + 1;
478
479 /* Adjust x1 and y to viewport */
480 x1 += current_vp->x;
481 y += current_vp->y;
482
480 dst = LCDADDR(x1, y); 483 dst = LCDADDR(x1, y);
481 484
482 switch (fillopt) 485 switch (fillopt)
@@ -490,11 +493,11 @@ void lcd_hline(int x1, int x2, int y)
490 width * sizeof(fb_data)); 493 width * sizeof(fb_data));
491 break; 494 break;
492 495
493 case OPT_NONE: 496 case OPT_NONE: /* DRMODE_COMPLEMENT */
494 dst_end = dst + width; 497 dst_end = dst + width;
495 do 498 do
496 pfunc(dst++); 499 *dst = ~(*dst);
497 while (dst < dst_end); 500 while (++dst < dst_end);
498 break; 501 break;
499 } 502 }
500} 503}
@@ -558,29 +561,13 @@ void lcd_fillrect(int x, int y, int width, int height)
558 unsigned bits = 0; 561 unsigned bits = 0;
559 enum fill_opt fillopt = OPT_NONE; 562 enum fill_opt fillopt = OPT_NONE;
560 fb_data *dst, *dst_end; 563 fb_data *dst, *dst_end;
561 lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode];
562 564
563 /* nothing to draw? */ 565 /* nothing to draw? */
564 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 566 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
565 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) 567 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
566 return; 568 return;
567 569
568 /* clipping */ 570 /* drawmode and optimisation */
569 if (x < 0)
570 {
571 width += x;
572 x = 0;
573 }
574 if (y < 0)
575 {
576 height += y;
577 y = 0;
578 }
579 if (x + width > current_vp->width)
580 width = current_vp->width - x;
581 if (y + height > current_vp->height)
582 height = current_vp->height - y;
583
584 if (current_vp->drawmode & DRMODE_INVERSEVID) 571 if (current_vp->drawmode & DRMODE_INVERSEVID)
585 { 572 {
586 if (current_vp->drawmode & DRMODE_BG) 573 if (current_vp->drawmode & DRMODE_BG)
@@ -602,6 +589,25 @@ void lcd_fillrect(int x, int y, int width, int height)
602 bits = current_vp->fg_pattern; 589 bits = current_vp->fg_pattern;
603 } 590 }
604 } 591 }
592 if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT)
593 return;
594
595 /* clipping */
596 if (x < 0)
597 {
598 width += x;
599 x = 0;
600 }
601 if (y < 0)
602 {
603 height += y;
604 y = 0;
605 }
606 if (x + width > current_vp->width)
607 width = current_vp->width - x;
608 if (y + height > current_vp->height)
609 height = current_vp->height - y;
610
605 dst = LCDADDR(current_vp->x + x, current_vp->y + y); 611 dst = LCDADDR(current_vp->x + x, current_vp->y + y);
606 dst_end = dst + height * LCD_WIDTH; 612 dst_end = dst + height * LCD_WIDTH;
607 613
@@ -620,12 +626,12 @@ void lcd_fillrect(int x, int y, int width, int height)
620 width * sizeof(fb_data)); 626 width * sizeof(fb_data));
621 break; 627 break;
622 628
623 case OPT_NONE: 629 case OPT_NONE: /* DRMODE_COMPLEMENT */
624 dst_row = dst; 630 dst_row = dst;
625 row_end = dst_row + width; 631 row_end = dst_row + width;
626 do 632 do
627 pfunc(dst_row++); 633 *dst_row = ~(*dst_row);
628 while (dst_row < row_end); 634 while (++dst_row < row_end);
629 break; 635 break;
630 } 636 }
631 dst += LCD_WIDTH; 637 dst += LCD_WIDTH;
@@ -717,7 +723,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
717{ 723{
718 const unsigned char *src_end; 724 const unsigned char *src_end;
719 fb_data *dst, *dst_end; 725 fb_data *dst, *dst_end;
720 lcd_fastpixelfunc_type *fgfunc, *bgfunc; 726 unsigned dmask = 0x100; /* bit 8 == sentinel */
727 int drmode = current_vp->drawmode;
721 728
722 /* nothing to draw? */ 729 /* nothing to draw? */
723 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || 730 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
@@ -745,35 +752,115 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x,
745 src += stride * (src_y >> 3) + src_x; /* move starting point */ 752 src += stride * (src_y >> 3) + src_x; /* move starting point */
746 src_y &= 7; 753 src_y &= 7;
747 src_end = src + width; 754 src_end = src + width;
748
749 dst = LCDADDR(current_vp->x + x, current_vp->y + y); 755 dst = LCDADDR(current_vp->x + x, current_vp->y + y);
750 fgfunc = lcd_fastpixelfuncs[current_vp->drawmode]; 756
751 bgfunc = lcd_fastpixelfuncs[current_vp->drawmode ^ DRMODE_INVERSEVID]; 757 if (drmode & DRMODE_INVERSEVID)
758 {
759 dmask = 0x1ff; /* bit 8 == sentinel */
760 drmode &= DRMODE_SOLID; /* mask out inversevid */
761 }
762
752 do 763 do
753 { 764 {
754 const unsigned char *src_col = src++; 765 const unsigned char *src_col = src++;
755 unsigned data = *src_col >> src_y; 766 unsigned data = (*src_col ^ dmask) >> src_y;
756 fb_data *dst_col = dst++; 767 fb_data *dst_col = dst++;
757 int numbits = 8 - src_y; 768 int fg, bg;
769 long bo;
770
758 dst_end = dst_col + height * LCD_WIDTH; 771 dst_end = dst_col + height * LCD_WIDTH;
759 do 772
773#define UPDATE_SRC do { \
774 data >>= 1; \
775 if (data == 0x001) { \
776 src_col += stride; \
777 data = *src_col ^ dmask; \
778 } \
779 } while (0)
780
781 switch (drmode)
760 { 782 {
761 if (data & 0x01) 783 case DRMODE_COMPLEMENT:
762 fgfunc(dst_col); 784 do
785 {
786 if (data & 0x01)
787 *dst_col = ~(*dst_col);
788
789 dst_col += LCD_WIDTH;
790 UPDATE_SRC;
791 }
792 while (dst_col < dst_end);
793 break;
794
795 case DRMODE_BG:
796 if (lcd_backdrop)
797 {
798 bo = lcd_backdrop_offset;
799 do
800 {
801 if (!(data & 0x01))
802 *dst_col = *(fb_data *)((long)dst_col + bo);
803
804 dst_col += LCD_WIDTH;
805 UPDATE_SRC;
806 }
807 while (dst_col < dst_end);
808 }
763 else 809 else
764 bgfunc(dst_col); 810 {
811 bg = current_vp->bg_pattern;
812 do
813 {
814 if (!(data & 0x01))
815 *dst_col = bg;
816
817 dst_col += LCD_WIDTH;
818 UPDATE_SRC;
819 }
820 while (dst_col < dst_end);
821 }
822 break;
765 823
766 dst_col += LCD_WIDTH; 824 case DRMODE_FG:
825 fg = current_vp->fg_pattern;
826 do
827 {
828 if (data & 0x01)
829 *dst_col = fg;
767 830
768 data >>= 1; 831 dst_col += LCD_WIDTH;
769 if (--numbits == 0) 832 UPDATE_SRC;
833 }
834 while (dst_col < dst_end);
835 break;
836
837 case DRMODE_SOLID:
838 fg = current_vp->fg_pattern;
839 if (lcd_backdrop)
770 { 840 {
771 src_col += stride; 841 bo = lcd_backdrop_offset;
772 data = *src_col; 842 do
773 numbits = 8; 843 {
844 *dst_col = (data & 0x01) ? fg
845 : *(fb_data *)((long)dst_col + bo);
846 dst_col += LCD_WIDTH;
847 UPDATE_SRC;
848 }
849 while (dst_col < dst_end);
774 } 850 }
851 else
852 {
853 bg = current_vp->bg_pattern;
854 do
855 {
856 *dst_col = (data & 0x01) ? fg : bg;
857 dst_col += LCD_WIDTH;
858 UPDATE_SRC;
859 }
860 while (dst_col < dst_end);
861 }
862 break;
775 } 863 }
776 while (dst_col < dst_end);
777 } 864 }
778 while (src < src_end); 865 while (src < src_end);
779} 866}