summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-07-06 22:58:02 +0000
committerJens Arnold <amiconn@rockbox.org>2005-07-06 22:58:02 +0000
commitf894a4c2691fbde1758a05407cb5eadcaec4a6c8 (patch)
tree46cb7ce63c794020175ab251cf0299663be8bf3c /firmware
parent1076eb1d2720b88757616f642be0c39c6a3b76df (diff)
downloadrockbox-f894a4c2691fbde1758a05407cb5eadcaec4a6c8.tar.gz
rockbox-f894a4c2691fbde1758a05407cb5eadcaec4a6c8.zip
4-shades greyscale graphics core for iriver H1x0. 4-grey rockbox logo and light grey background in splash() boxes. Simplified the splash() box creation as the new graphics core does clipping. Adapted screendump feature and added flexible preprocessing to construct the bmp header. Rockboy now uses 4-grey mode as well. 4-grey support for win32 simulator. Fixed win32 player sim to not use double bitmap conversion via a recorder-like framebuffer, and correctly display double-height text. X11 simulator temporarily adapted. The display won't be distorted, but it still shows b&w only.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7046 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/lcd-h100.c370
-rw-r--r--firmware/drivers/lcd-recorder.c2
-rw-r--r--firmware/export/config-player.h1
-rw-r--r--firmware/export/lcd.h21
4 files changed, 307 insertions, 87 deletions
diff --git a/firmware/drivers/lcd-h100.c b/firmware/drivers/lcd-h100.c
index 1a40a2535c..dcc5a42e5d 100644
--- a/firmware/drivers/lcd-h100.c
+++ b/firmware/drivers/lcd-h100.c
@@ -60,8 +60,16 @@
60 60
61/*** globals ***/ 61/*** globals ***/
62 62
63unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH] IDATA_ATTR; 63unsigned char lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH] IDATA_ATTR;
64 64
65/* should be 'const', but this causes a section type conflict */
66static unsigned char dibits[16] IDATA_ATTR = {
67 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
68 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF
69};
70
71static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */
72static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */
65static int drawmode = DRMODE_SOLID; 73static int drawmode = DRMODE_SOLID;
66static int xmargin = 0; 74static int xmargin = 0;
67static int ymargin = 0; 75static int ymargin = 0;
@@ -131,14 +139,8 @@ void lcd_set_flip(bool yesno)
131 * The value must be 0 <= pixels < LCD_HEIGHT. */ 139 * The value must be 0 <= pixels < LCD_HEIGHT. */
132void lcd_roll(int lines) 140void lcd_roll(int lines)
133{ 141{
134 char data[2];
135
136 lines &= LCD_HEIGHT-1; 142 lines &= LCD_HEIGHT-1;
137 data[0] = lines & 0xff; 143 lcd_write_command_ex(LCD_CNTL_DISPLAY_START_LINE, lines, -1);
138 data[1] = lines >> 8;
139
140 lcd_write_command(LCD_CNTL_DISPLAY_START_LINE);
141 lcd_write_data(data, 2);
142} 144}
143 145
144#endif /* !SIMULATOR */ 146#endif /* !SIMULATOR */
@@ -157,15 +159,15 @@ void lcd_init(void)
157{ 159{
158 /* GPO35 is the LCD A0 pin 160 /* GPO35 is the LCD A0 pin
159 GPO46 is LCD RESET */ 161 GPO46 is LCD RESET */
160 GPIO1_OUT |= 0x00004008; 162 or_l(0x00004008, &GPIO1_OUT);
161 GPIO1_ENABLE |= 0x00004008; 163 or_l(0x00004008, &GPIO1_ENABLE);
162 GPIO1_FUNCTION |= 0x00004008; 164 or_l(0x00004008, &GPIO1_FUNCTION);
163 165
164 /* Reset LCD */ 166 /* Reset LCD */
165 sleep(1); 167 sleep(1);
166 GPIO1_OUT &= ~0x00004000; 168 and_l(~0x00004000, &GPIO1_OUT);
167 sleep(1); 169 sleep(1);
168 GPIO1_OUT |= 0x00004000; 170 or_l(0x00004000, &GPIO1_OUT);
169 sleep(1); 171 sleep(1);
170 172
171 lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); /* Normal */ 173 lcd_write_command(LCD_CNTL_COLUMN_ADDRESS_DIR | 0); /* Normal */
@@ -190,7 +192,7 @@ void lcd_init(void)
190 192
191 lcd_write_command_ex(LCD_CNTL_DISPLAY_START_LINE, 0, -1); 193 lcd_write_command_ex(LCD_CNTL_DISPLAY_START_LINE, 0, -1);
192 lcd_write_command_ex(LCD_CNTL_GRAY_SCALE_PATTERN, 0x42, -1); 194 lcd_write_command_ex(LCD_CNTL_GRAY_SCALE_PATTERN, 0x42, -1);
193 lcd_write_command_ex(LCD_CNTL_DISPLAY_MODE, 1, -1); /* Monochrome mode */ 195 lcd_write_command_ex(LCD_CNTL_DISPLAY_MODE, 0, -1); /* Greyscale mode */
194 lcd_write_command(LCD_CNTL_DATA_INPUT_DIR | 0); /* Column mode */ 196 lcd_write_command(LCD_CNTL_DATA_INPUT_DIR | 0); /* Column mode */
195 197
196 lcd_clear_display(); 198 lcd_clear_display();
@@ -204,7 +206,7 @@ void lcd_init(void)
204/*** update functions ***/ 206/*** update functions ***/
205 207
206/* Performance function that works with an external buffer 208/* Performance function that works with an external buffer
207 note that by and bheight are in 8-pixel units! */ 209 note that by and bheight are in 4-pixel units! */
208void lcd_blit(const unsigned char* data, int x, int by, int width, 210void lcd_blit(const unsigned char* data, int x, int by, int width,
209 int bheight, int stride) 211 int bheight, int stride)
210{ 212{
@@ -223,13 +225,13 @@ void lcd_blit(const unsigned char* data, int x, int by, int width,
223 225
224/* Update the display. 226/* Update the display.
225 This must be called after all other LCD functions that change the display. */ 227 This must be called after all other LCD functions that change the display. */
226void lcd_update(void) __attribute__ ((section (".icode"))); 228void lcd_update(void) ICODE_ATTR;
227void lcd_update(void) 229void lcd_update(void)
228{ 230{
229 int y; 231 int y;
230 232
231 /* Copy display bitmap to hardware */ 233 /* Copy display bitmap to hardware */
232 for (y = 0; y < LCD_HEIGHT/8; y++) 234 for (y = 0; y < LCD_HEIGHT/4; y++)
233 { 235 {
234 lcd_write_command_ex(LCD_CNTL_PAGE, y, -1); 236 lcd_write_command_ex(LCD_CNTL_PAGE, y, -1);
235 lcd_write_command_ex(LCD_CNTL_COLUMN, 0, -1); 237 lcd_write_command_ex(LCD_CNTL_COLUMN, 0, -1);
@@ -240,21 +242,21 @@ void lcd_update(void)
240} 242}
241 243
242/* Update a fraction of the display. */ 244/* Update a fraction of the display. */
243void lcd_update_rect(int, int, int, int) __attribute__ ((section (".icode"))); 245void lcd_update_rect(int, int, int, int) ICODE_ATTR;
244void lcd_update_rect(int x, int y, int width, int height) 246void lcd_update_rect(int x, int y, int width, int height)
245{ 247{
246 int ymax; 248 int ymax;
247 249
248 /* The Y coordinates have to work on even 8 pixel rows */ 250 /* The Y coordinates have to work on even 8 pixel rows */
249 ymax = (y + height-1) >> 3; 251 ymax = (y + height-1) >> 2;
250 y >>= 3; 252 y >>= 2;
251 253
252 if(x + width > LCD_WIDTH) 254 if(x + width > LCD_WIDTH)
253 width = LCD_WIDTH - x; 255 width = LCD_WIDTH - x;
254 if (width <= 0) 256 if (width <= 0)
255 return; /* nothing left to do, 0 is harmful to lcd_write_data() */ 257 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
256 if(ymax >= LCD_HEIGHT/8) 258 if(ymax >= LCD_HEIGHT/4)
257 ymax = LCD_HEIGHT/8-1; 259 ymax = LCD_HEIGHT/4-1;
258 260
259 /* Copy specified rectange bitmap to hardware */ 261 /* Copy specified rectange bitmap to hardware */
260 for (; y <= ymax; y++) 262 for (; y <= ymax; y++)
@@ -280,6 +282,26 @@ int lcd_get_drawmode(void)
280 return drawmode; 282 return drawmode;
281} 283}
282 284
285void lcd_set_foreground(int brightness)
286{
287 fg_pattern = 0x55 * (~brightness & 3);
288}
289
290int lcd_get_foreground(void)
291{
292 return ~fg_pattern & 3;
293}
294
295void lcd_set_background(int brightness)
296{
297 bg_pattern = 0x55 * (~brightness & 3);
298}
299
300int lcd_get_background(void)
301{
302 return ~bg_pattern & 3;
303}
304
283void lcd_setmargins(int x, int y) 305void lcd_setmargins(int x, int y)
284{ 306{
285 xmargin = x; 307 xmargin = x;
@@ -310,17 +332,21 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h)
310 332
311static void setpixel(int x, int y) 333static void setpixel(int x, int y)
312{ 334{
313 DRAW_PIXEL(x, y); 335 unsigned char *data = &lcd_framebuffer[y>>2][x];
336 unsigned mask = 3 << (2 * (y & 3));
337 *data = (*data & ~mask) | (fg_pattern & mask);
314} 338}
315 339
316static void clearpixel(int x, int y) 340static void clearpixel(int x, int y)
317{ 341{
318 CLEAR_PIXEL(x, y); 342 unsigned char *data = &lcd_framebuffer[y>>2][x];
343 unsigned mask = 3 << (2 * (y & 3));
344 *data = (*data & ~mask) | (bg_pattern & mask);
319} 345}
320 346
321static void flippixel(int x, int y) 347static void flippixel(int x, int y)
322{ 348{
323 INVERT_PIXEL(x, y); 349 lcd_framebuffer[y>>2][x] ^= 3 << (2 * (y & 3));
324} 350}
325 351
326static void nopixel(int x, int y) 352static void nopixel(int x, int y)
@@ -333,61 +359,68 @@ lcd_pixelfunc_type* lcd_pixelfuncs[8] = {
333 flippixel, nopixel, setpixel, setpixel, 359 flippixel, nopixel, setpixel, setpixel,
334 nopixel, clearpixel, nopixel, clearpixel 360 nopixel, clearpixel, nopixel, clearpixel
335}; 361};
336 362
363/* 'mask' and 'bits' contain 2 bits per pixel */
337static void flipblock(unsigned char *address, unsigned mask, unsigned bits) 364static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
338 __attribute__ ((section(".icode"))); 365 ICODE_ATTR;
339static void flipblock(unsigned char *address, unsigned mask, unsigned bits) 366static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
340{ 367{
341 *address ^= (bits & mask); 368 *address ^= bits & mask;
342} 369}
343 370
344static void bgblock(unsigned char *address, unsigned mask, unsigned bits) 371static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
345 __attribute__ ((section(".icode"))); 372 ICODE_ATTR;
346static void bgblock(unsigned char *address, unsigned mask, unsigned bits) 373static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
347{ 374{
348 *address &= (bits | ~mask); 375 mask &= ~bits;
376 *address = (*address & ~mask) | (bg_pattern & mask);
349} 377}
350 378
351static void fgblock(unsigned char *address, unsigned mask, unsigned bits) 379static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
352 __attribute__ ((section(".icode"))); 380 ICODE_ATTR;
353static void fgblock(unsigned char *address, unsigned mask, unsigned bits) 381static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
354{ 382{
355 *address |= (bits & mask); 383 mask &= bits;
384 *address = (*address & ~mask) | (fg_pattern & mask);
356} 385}
357 386
358static void solidblock(unsigned char *address, unsigned mask, unsigned bits) 387static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
359 __attribute__ ((section(".icode"))); 388 ICODE_ATTR;
360static void solidblock(unsigned char *address, unsigned mask, unsigned bits) 389static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
361{ 390{
362 *address = (*address & ~mask) | (bits & mask); 391 *address = (*address & ~mask) | (bits & mask & fg_pattern)
392 | (~bits & mask & bg_pattern);
363} 393}
364 394
365static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) 395static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
366 __attribute__ ((section(".icode"))); 396 ICODE_ATTR;
367static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) 397static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
368{ 398{
369 *address ^= (~bits & mask); 399 *address ^= ~bits & mask;
370} 400}
371 401
372static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) 402static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
373 __attribute__ ((section(".icode"))); 403 ICODE_ATTR;
374static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) 404static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
375{ 405{
376 *address &= ~(bits & mask); 406 mask &= bits;
407 *address = (*address & ~mask) | (bg_pattern & mask);
377} 408}
378 409
379static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) 410static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
380 __attribute__ ((section(".icode"))); 411 ICODE_ATTR;
381static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) 412static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
382{ 413{
383 *address |= (~bits & mask); 414 mask &= ~bits;
415 *address = (*address & ~mask) | (fg_pattern & mask);
384} 416}
385 417
386static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) 418static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
387 __attribute__ ((section(".icode"))); 419 ICODE_ATTR;
388static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) 420static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
389{ 421{
390 *address = (*address & ~mask) | (~bits & mask); 422 *address = (*address & ~mask) | (~bits & mask & fg_pattern)
423 | (bits & mask & bg_pattern);
391} 424}
392 425
393lcd_blockfunc_type* lcd_blockfuncs[8] = { 426lcd_blockfunc_type* lcd_blockfuncs[8] = {
@@ -400,7 +433,7 @@ lcd_blockfunc_type* lcd_blockfuncs[8] = {
400/* Clear the whole display */ 433/* Clear the whole display */
401void lcd_clear_display(void) 434void lcd_clear_display(void)
402{ 435{
403 unsigned bits = (drawmode & DRMODE_INVERSEVID) ? 0xFFu : 0; 436 unsigned bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern;
404 437
405 memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); 438 memset(lcd_framebuffer, bits, sizeof lcd_framebuffer);
406 scrolling_lines = 0; 439 scrolling_lines = 0;
@@ -511,8 +544,8 @@ void lcd_hline(int x1, int x2, int y)
511 x2 = LCD_WIDTH-1; 544 x2 = LCD_WIDTH-1;
512 545
513 bfunc = lcd_blockfuncs[drawmode]; 546 bfunc = lcd_blockfuncs[drawmode];
514 dst = &lcd_framebuffer[y>>3][x1]; 547 dst = &lcd_framebuffer[y>>2][x1];
515 mask = 1 << (y & 7); 548 mask = 3 << (2 * (y & 3));
516 549
517 dst_end = dst + x2 - x1; 550 dst_end = dst + x2 - x1;
518 do 551 do
@@ -547,12 +580,12 @@ void lcd_vline(int x, int y1, int y2)
547 y2 = LCD_HEIGHT-1; 580 y2 = LCD_HEIGHT-1;
548 581
549 bfunc = lcd_blockfuncs[drawmode]; 582 bfunc = lcd_blockfuncs[drawmode];
550 dst = &lcd_framebuffer[y1>>3][x]; 583 dst = &lcd_framebuffer[y1>>2][x];
551 ny = y2 - (y1 & ~7); 584 ny = y2 - (y1 & ~3);
552 mask = 0xFFu << (y1 & 7); 585 mask = 0xFFu << (2 * (y1 & 3));
553 mask_bottom = 0xFFu >> (7 - (ny & 7)); 586 mask_bottom = 0xFFu >> (2 * (~ny & 3));
554 587
555 for (; ny >= 8; ny -= 8) 588 for (; ny >= 4; ny -= 4)
556 { 589 {
557 bfunc(dst, mask, 0xFFu); 590 bfunc(dst, mask, 0xFFu);
558 dst += LCD_WIDTH; 591 dst += LCD_WIDTH;
@@ -583,7 +616,7 @@ void lcd_fillrect(int x, int y, int width, int height)
583 int ny; 616 int ny;
584 unsigned char *dst, *dst_end; 617 unsigned char *dst, *dst_end;
585 unsigned mask, mask_bottom; 618 unsigned mask, mask_bottom;
586 unsigned bits = 0xFFu; 619 unsigned bits = fg_pattern;
587 lcd_blockfunc_type *bfunc; 620 lcd_blockfunc_type *bfunc;
588 bool fillopt; 621 bool fillopt;
589 622
@@ -611,14 +644,14 @@ void lcd_fillrect(int x, int y, int width, int height)
611 fillopt = (drawmode & DRMODE_INVERSEVID) ? 644 fillopt = (drawmode & DRMODE_INVERSEVID) ?
612 (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); 645 (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG);
613 if (fillopt &&(drawmode & DRMODE_INVERSEVID)) 646 if (fillopt &&(drawmode & DRMODE_INVERSEVID))
614 bits = 0; 647 bits = bg_pattern;
615 bfunc = lcd_blockfuncs[drawmode]; 648 bfunc = lcd_blockfuncs[drawmode];
616 dst = &lcd_framebuffer[y>>3][x]; 649 dst = &lcd_framebuffer[y>>2][x];
617 ny = height - 1 + (y & 7); 650 ny = height - 1 + (y & 3);
618 mask = 0xFFu << (y & 7); 651 mask = 0xFFu << (2 * (y & 3));
619 mask_bottom = 0xFFu >> (7 - (ny & 7)); 652 mask_bottom = 0xFFu >> (2 * (~ny & 3));
620 653
621 for (; ny >= 8; ny -= 8) 654 for (; ny >= 4; ny -= 4)
622 { 655 {
623 if (fillopt && (mask == 0xFFu)) 656 if (fillopt && (mask == 0xFFu))
624 memset(dst, bits, width); 657 memset(dst, bits, width);
@@ -648,7 +681,7 @@ void lcd_fillrect(int x, int y, int width, int height)
648 } 681 }
649} 682}
650 683
651/* About Rockbox' internal bitmap format: 684/* About Rockbox' internal monochrome bitmap format:
652 * 685 *
653 * A bitmap contains one bit for every pixel that defines if that pixel is 686 * A bitmap contains one bit for every pixel that defines if that pixel is
654 * black (1) or white (0). Bits within a byte are arranged vertically, LSB 687 * black (1) or white (0). Bits within a byte are arranged vertically, LSB
@@ -657,12 +690,180 @@ void lcd_fillrect(int x, int y, int width, int height)
657 * byte 1 2nd from left etc. The first row of bytes defines pixel rows 690 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
658 * 0..7, the second row defines pixel row 8..15 etc. 691 * 0..7, the second row defines pixel row 8..15 etc.
659 * 692 *
693 * This is similar to the internal lcd hw format. */
694
695/* Draw a partial monochrome bitmap */
696void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
697 int stride, int x, int y, int width, int height)
698 ICODE_ATTR;
699void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
700 int stride, int x, int y, int width, int height)
701{
702 int shift, ny;
703 unsigned char *dst, *dst_end;
704 unsigned mask, mask_bottom;
705 lcd_blockfunc_type *bfunc;
706
707 /* nothing to draw? */
708 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
709 || (x + width <= 0) || (y + height <= 0))
710 return;
711
712 /* clipping */
713 if (x < 0)
714 {
715 width += x;
716 src_x -= x;
717 x = 0;
718 }
719 if (y < 0)
720 {
721 height += y;
722 src_y -= y;
723 y = 0;
724 }
725 if (x + width > LCD_WIDTH)
726 width = LCD_WIDTH - x;
727 if (y + height > LCD_HEIGHT)
728 height = LCD_HEIGHT - y;
729
730 src += stride * (src_y >> 3) + src_x; /* move starting point */
731 src_y &= 7;
732 y -= src_y;
733 dst = &lcd_framebuffer[y>>2][x];
734 shift = y & 3;
735 ny = height - 1 + shift + src_y;
736
737 bfunc = lcd_blockfuncs[drawmode];
738 mask = 0xFFu << (shift + src_y);
739 mask_bottom = 0xFFu >> (~ny & 7);
740
741 if (shift == 0)
742 {
743 unsigned dmask1, dmask2, data;
744
745 for (; ny >= 8; ny -= 8)
746 {
747 const unsigned char *src_row = src;
748 unsigned char *dst_row = dst + LCD_WIDTH;
749
750 dmask1 = dibits[mask&0x0F];
751 dmask2 = dibits[(mask>>4)&0x0F];
752 dst_end = dst_row + width;
753
754 if (dmask1 != 0)
755 {
756 do
757 {
758 data = *src_row++;
759 bfunc(dst_row - LCD_WIDTH, dmask1, dibits[data&0x0F]);
760 bfunc(dst_row++, dmask2, dibits[(data>>4)&0x0F]);
761 }
762 while (dst_row < dst_end);
763 }
764 else
765 {
766 do
767 bfunc(dst_row++, dmask2, dibits[((*src_row++)>>4)&0x0F]);
768 while (dst_row < dst_end);
769 }
770 src += stride;
771 dst += 2*LCD_WIDTH;
772 mask = 0xFFu;
773 }
774 mask &= mask_bottom;
775 dmask1 = dibits[mask&0x0F];
776 dmask2 = dibits[(mask>>4)&0x0F];
777 dst_end = dst + width;
778
779 if (dmask1 != 0)
780 {
781 if (dmask2 != 0)
782 {
783 do
784 {
785 data = *src++;
786 bfunc(dst, dmask1, dibits[data&0x0F]);
787 bfunc((dst++) + LCD_WIDTH, dmask2, dibits[(data>>4)&0x0F]);
788 }
789 while (dst < dst_end);
790 }
791 else
792 {
793 do
794 bfunc(dst++, dmask1, dibits[(*src++)&0x0F]);
795 while (dst < dst_end);
796 }
797 }
798 else
799 {
800 do
801 bfunc((dst++) + LCD_WIDTH, dmask2, dibits[((*src++)>>4)&0x0F]);
802 while (dst < dst_end);
803 }
804 }
805 else
806 {
807 dst_end = dst + width;
808 do
809 {
810 const unsigned char *src_col = src++;
811 unsigned char *dst_col = dst++;
812 unsigned mask_col = mask;
813 unsigned data = 0;
814
815 for (y = ny; y >= 8; y -= 8)
816 {
817 data |= *src_col << shift;
818
819 if (mask_col & 0xFFu)
820 {
821 if (mask_col & 0x0F)
822 bfunc(dst_col, dibits[mask_col&0x0F], dibits[data&0x0F]);
823 bfunc(dst_col + LCD_WIDTH, dibits[(mask_col>>4)&0x0F],
824 dibits[(data>>4)&0x0F]);
825 mask_col = 0xFFu;
826 }
827 else
828 mask_col >>= 8;
829
830 src_col += stride;
831 dst_col += 2*LCD_WIDTH;
832 data >>= 8;
833 }
834 data |= *src_col << shift;
835 mask_bottom &= mask_col;
836 if (mask_bottom & 0x0F)
837 bfunc(dst_col, dibits[mask_bottom&0x0F], dibits[data&0x0F]);
838 if (mask_bottom & 0xF0)
839 bfunc(dst_col + LCD_WIDTH, dibits[(mask_bottom&0xF0)>>4],
840 dibits[(data>>4)&0x0F]);
841 }
842 while (dst < dst_end);
843 }
844}
845
846/* Draw a full monochrome bitmap */
847void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height)
848{
849 lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height);
850}
851
852/* About Rockbox' internal native bitmap format:
853 *
854 * A bitmap contains two bits for every pixel. 00 = white, 01 = light grey,
855 * 10 = dark grey, 11 = black. Bits within a byte are arranged vertically, LSB
856 * at top.
857 * The bytes are stored in row-major order, with byte 0 being top left,
858 * byte 1 2nd from left etc. The first row of bytes defines pixel rows
859 * 0..3, the second row defines pixel row 4..7 etc.
860 *
660 * This is the same as the internal lcd hw format. */ 861 * This is the same as the internal lcd hw format. */
661 862
662/* Draw a partial bitmap */ 863/* Draw a partial native bitmap */
663void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, 864void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
664 int stride, int x, int y, int width, int height) 865 int stride, int x, int y, int width, int height)
665 __attribute__ ((section(".icode"))); 866 ICODE_ATTR;
666void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, 867void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
667 int stride, int x, int y, int width, int height) 868 int stride, int x, int y, int width, int height)
668{ 869{
@@ -694,32 +895,30 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
694 if (y + height > LCD_HEIGHT) 895 if (y + height > LCD_HEIGHT)
695 height = LCD_HEIGHT - y; 896 height = LCD_HEIGHT - y;
696 897
697 src += stride * (src_y >> 3) + src_x; /* move starting point */ 898 src += stride * (src_y >> 2) + src_x; /* move starting point */
698 src_y &= 7; 899 src_y &= 3;
699 y -= src_y; 900 y -= src_y;
700 dst = &lcd_framebuffer[y>>3][x]; 901 dst = &lcd_framebuffer[y>>2][x];
701 shift = y & 7; 902 shift = y & 3;
702 ny = height - 1 + shift + src_y; 903 ny = height - 1 + shift + src_y;
703 904
704 bfunc = lcd_blockfuncs[drawmode]; 905 bfunc = lcd_blockfuncs[drawmode];
705 mask = 0xFFu << (shift + src_y); 906 mask = 0xFFu << (2 * (shift + src_y));
706 mask_bottom = 0xFFu >> (7 - (ny & 7)); 907 mask_bottom = 0xFFu >> (2 * (~ny & 3));
707 908
708 if (shift == 0) 909 if (shift == 0)
709 { 910 {
710 bool copyopt = (drawmode == DRMODE_SOLID); 911 for (; ny >= 4; ny -= 4)
711
712 for (; ny >= 8; ny -= 8)
713 { 912 {
714 if (copyopt && (mask == 0xFFu)) 913 if (mask == 0xFFu)
715 memcpy(dst, src, width); 914 memcpy(dst, src, width);
716 else 915 else
717 { 916 {
718 const unsigned char *src_row = src; 917 const unsigned char *src_row = src;
719 unsigned char *dst_row = dst; 918 unsigned char *dst_row = dst;
720 919
721 dst_end = dst_row + width; 920 dst_end = dst_row + width;
722 do 921 do
723 bfunc(dst_row++, mask, *src_row++); 922 bfunc(dst_row++, mask, *src_row++);
724 while (dst_row < dst_end); 923 while (dst_row < dst_end);
725 } 924 }
@@ -730,7 +929,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
730 } 929 }
731 mask &= mask_bottom; 930 mask &= mask_bottom;
732 931
733 if (copyopt && (mask == 0xFFu)) 932 if (mask == 0xFFu)
734 memcpy(dst, src, width); 933 memcpy(dst, src, width);
735 else 934 else
736 { 935 {
@@ -742,6 +941,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
742 } 941 }
743 else 942 else
744 { 943 {
944 shift *= 2;
745 dst_end = dst + width; 945 dst_end = dst + width;
746 do 946 do
747 { 947 {
@@ -750,7 +950,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
750 unsigned mask_col = mask; 950 unsigned mask_col = mask;
751 unsigned data = 0; 951 unsigned data = 0;
752 952
753 for (y = ny; y >= 8; y -= 8) 953 for (y = ny; y >= 4; y -= 4)
754 { 954 {
755 data |= *src_col << shift; 955 data |= *src_col << shift;
756 956
@@ -773,7 +973,7 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
773 } 973 }
774} 974}
775 975
776/* Draw a full bitmap */ 976/* Draw a full native bitmap */
777void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) 977void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height)
778{ 978{
779 lcd_bitmap_part(src, 0, 0, width, x, y, width, height); 979 lcd_bitmap_part(src, 0, 0, width, x, y, width, height);
@@ -807,7 +1007,7 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
807 bits = pf->bits + (pf->offset ? 1007 bits = pf->bits + (pf->offset ?
808 pf->offset[ch] : ((pf->height + 7) / 8 * pf->maxwidth * ch)); 1008 pf->offset[ch] : ((pf->height + 7) / 8 * pf->maxwidth * ch));
809 1009
810 lcd_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); 1010 lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height);
811 1011
812 x += width - ofs; 1012 x += width - ofs;
813 ofs = 0; 1013 ofs = 0;
@@ -825,7 +1025,7 @@ void lcd_putsxy(int x, int y, const unsigned char *str)
825void lcd_puts_style(int x, int y, const unsigned char *str, int style) 1025void lcd_puts_style(int x, int y, const unsigned char *str, int style)
826{ 1026{
827 int xpos,ypos,w,h; 1027 int xpos,ypos,w,h;
828 int lastmode = lcd_get_drawmode(); 1028 int lastmode = drawmode;
829 1029
830 /* make sure scrolling is turned off on the line we are updating */ 1030 /* make sure scrolling is turned off on the line we are updating */
831 scrolling_lines &= ~(1 << y); 1031 scrolling_lines &= ~(1 << y);
@@ -837,14 +1037,14 @@ void lcd_puts_style(int x, int y, const unsigned char *str, int style)
837 xpos = xmargin + x*w / strlen(str); 1037 xpos = xmargin + x*w / strlen(str);
838 ypos = ymargin + y*h; 1038 ypos = ymargin + y*h;
839 lcd_putsxy(xpos, ypos, str); 1039 lcd_putsxy(xpos, ypos, str);
840 lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 1040 drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);
841 lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); 1041 lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h);
842 if (style & STYLE_INVERT) 1042 if (style & STYLE_INVERT)
843 { 1043 {
844 lcd_set_drawmode(DRMODE_COMPLEMENT); 1044 drawmode = DRMODE_COMPLEMENT;
845 lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h); 1045 lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h);
846 } 1046 }
847 lcd_set_drawmode(lastmode); 1047 drawmode = lastmode;
848} 1048}
849 1049
850/* put a string at a given char position */ 1050/* put a string at a given char position */
@@ -1006,17 +1206,17 @@ static void scroll_thread(void)
1006 s->offset %= s->width; 1206 s->offset %= s->width;
1007 } 1207 }
1008 1208
1009 lastmode = lcd_get_drawmode(); 1209 lastmode = drawmode;
1010 lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 1210 drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);
1011 lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); 1211 lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
1012 lcd_set_drawmode(DRMODE_SOLID); 1212 drawmode = DRMODE_SOLID;
1013 lcd_putsxyofs(xpos, ypos, s->offset, s->line); 1213 lcd_putsxyofs(xpos, ypos, s->offset, s->line);
1014 if (s->invert) 1214 if (s->invert)
1015 { 1215 {
1016 lcd_set_drawmode(DRMODE_COMPLEMENT); 1216 drawmode = DRMODE_COMPLEMENT;
1017 lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); 1217 lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
1018 } 1218 }
1019 lcd_set_drawmode(lastmode); 1219 drawmode = lastmode;
1020 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); 1220 lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height);
1021 } 1221 }
1022 1222
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c
index b0308c6c77..37a15961d5 100644
--- a/firmware/drivers/lcd-recorder.c
+++ b/firmware/drivers/lcd-recorder.c
@@ -868,7 +868,7 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str)
868 bits = pf->bits + (pf->offset ? 868 bits = pf->bits + (pf->offset ?
869 pf->offset[ch] : ((pf->height + 7) / 8 * pf->maxwidth * ch)); 869 pf->offset[ch] : ((pf->height + 7) / 8 * pf->maxwidth * ch));
870 870
871 lcd_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); 871 lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height);
872 872
873 x += width - ofs; 873 x += width - ofs;
874 ofs = 0; 874 ofs = 0;
diff --git a/firmware/export/config-player.h b/firmware/export/config-player.h
index 464561d90d..57fd7d8d92 100644
--- a/firmware/export/config-player.h
+++ b/firmware/export/config-player.h
@@ -4,6 +4,7 @@
4/* LCD dimensions (for the simulator) */ 4/* LCD dimensions (for the simulator) */
5#define LCD_WIDTH (4*11*6) /* Display width in pixels */ 5#define LCD_WIDTH (4*11*6) /* Display width in pixels */
6#define LCD_HEIGHT (4*16+2*24) /* 4*char + 2*icons */ 6#define LCD_HEIGHT (4*16+2*24) /* 4*char + 2*icons */
7#define LCD_DEPTH 1
7 8
8/* define this if you have the Player's keyboard */ 9/* define this if you have the Player's keyboard */
9#define CONFIG_KEYPAD PLAYER_PAD 10#define CONFIG_KEYPAD PLAYER_PAD
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 5f93e7cbc3..f5f16d0f0a 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -121,7 +121,7 @@ extern void lcd_jump_scroll_delay(int ms);
121#define DRMODE_INVERSEVID 4 /* used as bit modifier for basic modes */ 121#define DRMODE_INVERSEVID 4 /* used as bit modifier for basic modes */
122 122
123/* Low-level drawing function types */ 123/* Low-level drawing function types */
124typedef void lcd_pixelfunc_type(int x, int y); /* for b&w */ 124typedef void lcd_pixelfunc_type(int x, int y);
125typedef void lcd_blockfunc_type(unsigned char *address, unsigned mask, unsigned bits); 125typedef void lcd_blockfunc_type(unsigned char *address, unsigned mask, unsigned bits);
126 126
127#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) 127#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
@@ -131,7 +131,12 @@ typedef void lcd_blockfunc_type(unsigned char *address, unsigned mask, unsigned
131#define INVERT_PIXEL(x,y) lcd_framebuffer[(y)>>3][(x)] ^= (1<<((y)&7)) 131#define INVERT_PIXEL(x,y) lcd_framebuffer[(y)>>3][(x)] ^= (1<<((y)&7))
132 132
133/* Memory copy of display bitmap */ 133/* Memory copy of display bitmap */
134#if LCD_DEPTH == 1
134extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH]; 135extern unsigned char lcd_framebuffer[LCD_HEIGHT/8][LCD_WIDTH];
136#elif LCD_DEPTH == 2
137#define MAX_LEVEL 3
138extern unsigned char lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH];
139#endif
135 140
136extern void lcd_set_invert_display(bool yesno); 141extern void lcd_set_invert_display(bool yesno);
137extern void lcd_set_flip(bool yesno); 142extern void lcd_set_flip(bool yesno);
@@ -165,6 +170,20 @@ extern void lcd_invertscroll(int x, int y);
165extern void lcd_bidir_scroll(int threshold); 170extern void lcd_bidir_scroll(int threshold);
166extern void lcd_scroll_step(int pixels); 171extern void lcd_scroll_step(int pixels);
167 172
173#if LCD_DEPTH > 1
174extern void lcd_set_foreground(int brightness);
175extern int lcd_get_foreground(void);
176extern void lcd_set_background(int brightness);
177extern int lcd_get_background(void);
178extern void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
179 int stride, int x, int y, int width, int height);
180extern void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width,
181 int height);
182#else /* LCD_DEPTH == 1 */
183#define lcd_mono_bitmap lcd_bitmap
184#define lcd_mono_bitmap_part lcd_bitmap_part
185#endif
186
168#endif /* CHARCELLS / BITMAP */ 187#endif /* CHARCELLS / BITMAP */
169 188
170/* internal usage, but in multiple drivers */ 189/* internal usage, but in multiple drivers */