summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2006-02-16 20:03:07 +0000
committerJens Arnold <amiconn@rockbox.org>2006-02-16 20:03:07 +0000
commit41e1aa888b9d1fc41aaf158191980cce3e548302 (patch)
tree2f04f7e5a6f93559defdf037b6b918eb44112ac3 /firmware
parent7c64631792f5bb3bd804ff5880808d275be89a4d (diff)
downloadrockbox-41e1aa888b9d1fc41aaf158191980cce3e548302.tar.gz
rockbox-41e1aa888b9d1fc41aaf158191980cce3e548302.zip
Grayscale iPods: Fixed & optimised LCD driver. Further optimisation is possible. * LCD driver now uses proper native bitmaps resembling the LCD internal format. Mono bitmaps are still transposed.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8706 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/lcd-2bit-horz.c261
1 files changed, 188 insertions, 73 deletions
diff --git a/firmware/drivers/lcd-2bit-horz.c b/firmware/drivers/lcd-2bit-horz.c
index 1045ba654b..f9f5152faa 100644
--- a/firmware/drivers/lcd-2bit-horz.c
+++ b/firmware/drivers/lcd-2bit-horz.c
@@ -45,6 +45,10 @@ static const unsigned char dibits[16] ICONST_ATTR = {
45 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF 45 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF
46}; 46};
47 47
48static const unsigned char pixmask[4] ICONST_ATTR = {
49 0x03, 0x0C, 0x30, 0xC0
50};
51
48static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ 52static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */
49static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ 53static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */
50static int drawmode = DRMODE_SOLID; 54static int drawmode = DRMODE_SOLID;
@@ -70,8 +74,6 @@ static const char scroll_tick_table[16] = {
70}; 74};
71 75
72 76
73static unsigned char notmask[4] = { 0xfc, 0xf3, 0xcf, 0x3f };
74
75/* LCD init */ 77/* LCD init */
76void lcd_init(void) 78void lcd_init(void)
77{ 79{
@@ -154,29 +156,23 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h)
154 156
155/*** low-level drawing functions ***/ 157/*** low-level drawing functions ***/
156 158
157static void setpixel_value(int x, int y, unsigned val)
158{
159 unsigned char *data = &lcd_framebuffer[y][x>>2];
160
161 *data = (*data & notmask[x&3]) | (val << ((x&3)<<1));
162}
163
164static void setpixel(int x, int y) 159static void setpixel(int x, int y)
165{ 160{
166 unsigned char *data = &lcd_framebuffer[y][x>>2]; 161 unsigned char *data = &lcd_framebuffer[y][x>>2];
167 162 unsigned mask = pixmask[x & 3];
168 *data = (*data & notmask[x&3]) | (fg_pattern << ((x&3)<<1)); 163 *data = (*data & ~mask) | (fg_pattern & mask);
169} 164}
170 165
171static void clearpixel(int x, int y) 166static void clearpixel(int x, int y)
172{ 167{
173 unsigned char *data = &lcd_framebuffer[y][x>>2]; 168 unsigned char *data = &lcd_framebuffer[y][x>>2];
174*data = (*data & notmask[x&3]) | (bg_pattern << ((x&3)<<1)); 169 unsigned mask = pixmask[x & 3];
170 *data = (*data & ~mask) | (bg_pattern & mask);
175} 171}
176 172
177static void flippixel(int x, int y) 173static void flippixel(int x, int y)
178{ 174{
179 lcd_framebuffer[y][x>>2] ^= 3 << (2 * (x & 3)); 175 lcd_framebuffer[y][x>>2] ^= pixmask[x & 3];
180} 176}
181 177
182static void nopixel(int x, int y) 178static void nopixel(int x, int y)
@@ -190,6 +186,78 @@ lcd_pixelfunc_type* const lcd_pixelfuncs[8] = {
190 nopixel, clearpixel, nopixel, clearpixel 186 nopixel, clearpixel, nopixel, clearpixel
191}; 187};
192 188
189/* 'mask' and 'bits' contain 2 bits per pixel */
190static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
191 ICODE_ATTR;
192static void flipblock(unsigned char *address, unsigned mask, unsigned bits)
193{
194 *address ^= bits & mask;
195}
196
197static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
198 ICODE_ATTR;
199static void bgblock(unsigned char *address, unsigned mask, unsigned bits)
200{
201 mask &= ~bits;
202 *address = (*address & ~mask) | (bg_pattern & mask);
203}
204
205static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
206 ICODE_ATTR;
207static void fgblock(unsigned char *address, unsigned mask, unsigned bits)
208{
209 mask &= bits;
210 *address = (*address & ~mask) | (fg_pattern & mask);
211}
212
213static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
214 ICODE_ATTR;
215static void solidblock(unsigned char *address, unsigned mask, unsigned bits)
216{
217 *address = (*address & ~mask) | (bits & mask & fg_pattern)
218 | (~bits & mask & bg_pattern);
219}
220
221static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
222 ICODE_ATTR;
223static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits)
224{
225 *address ^= ~bits & mask;
226}
227
228static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
229 ICODE_ATTR;
230static void bginvblock(unsigned char *address, unsigned mask, unsigned bits)
231{
232 mask &= bits;
233 *address = (*address & ~mask) | (bg_pattern & mask);
234}
235
236static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
237 ICODE_ATTR;
238static void fginvblock(unsigned char *address, unsigned mask, unsigned bits)
239{
240 mask &= ~bits;
241 *address = (*address & ~mask) | (fg_pattern & mask);
242}
243
244static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
245 ICODE_ATTR;
246static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits)
247{
248 *address = (*address & ~mask) | (~bits & mask & fg_pattern)
249 | (bits & mask & bg_pattern);
250}
251
252lcd_blockfunc_type* const lcd_blockfuncs[8] = {
253 flipblock, bgblock, fgblock, solidblock,
254 flipinvblock, bginvblock, fginvblock, solidinvblock
255};
256
257static inline void setblock(unsigned char *address, unsigned mask, unsigned bits)
258{
259 *address = (*address & ~mask) | (bits & mask);
260}
193 261
194/*** drawing functions ***/ 262/*** drawing functions ***/
195 263
@@ -283,16 +351,17 @@ void lcd_drawline(int x1, int y1, int x2, int y2)
283/* Draw a horizontal line (optimised) */ 351/* Draw a horizontal line (optimised) */
284void lcd_hline(int x1, int x2, int y) 352void lcd_hline(int x1, int x2, int y)
285{ 353{
286 int x; 354 int nx;
287 355 unsigned char *dst;
288 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; 356 unsigned mask, mask_right;
357 lcd_blockfunc_type *bfunc;
289 358
290 /* direction flip */ 359 /* direction flip */
291 if (x2 < x1) 360 if (x2 < x1)
292 { 361 {
293 x = x1; 362 nx = x1;
294 x1 = x2; 363 x1 = x2;
295 x2 = x; 364 x2 = nx;
296 } 365 }
297 366
298 /* nothing to draw? */ 367 /* nothing to draw? */
@@ -305,25 +374,35 @@ void lcd_hline(int x1, int x2, int y)
305 if (x2 >= LCD_WIDTH) 374 if (x2 >= LCD_WIDTH)
306 x2 = LCD_WIDTH-1; 375 x2 = LCD_WIDTH-1;
307 376
308 while(x1 <= x2) { 377 bfunc = lcd_blockfuncs[drawmode];
309 pfunc(x1,y); 378 dst = &lcd_framebuffer[y][x1>>2];
310 ++x1; 379 nx = x2 - (x1 & ~3);
380 mask = 0xFFu << (2 * (x1 & 3));
381 mask_right = 0xFFu >> (2 * (~nx & 3));
382
383 for (; nx >= 4; nx -= 4)
384 {
385 bfunc(dst++, mask, 0xFFu);
386 mask = 0xFFu;
311 } 387 }
388 mask &= mask_right;
389 bfunc(dst, mask, 0xFFu);
312} 390}
313 391
314/* Draw a vertical line (optimised) */ 392/* Draw a vertical line (optimised) */
315void lcd_vline(int x, int y1, int y2) 393void lcd_vline(int x, int y1, int y2)
316{ 394{
317 int ny; 395 int y;
318 396 unsigned char *dst, *dst_end;
319 lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; 397 unsigned mask;
398 lcd_blockfunc_type *bfunc;
320 399
321 /* direction flip */ 400 /* direction flip */
322 if (y2 < y1) 401 if (y2 < y1)
323 { 402 {
324 ny = y1; 403 y = y1;
325 y1 = y2; 404 y1 = y2;
326 y2 = ny; 405 y2 = y;
327 } 406 }
328 407
329 /* nothing to draw? */ 408 /* nothing to draw? */
@@ -336,10 +415,17 @@ void lcd_vline(int x, int y1, int y2)
336 if (y2 >= LCD_HEIGHT) 415 if (y2 >= LCD_HEIGHT)
337 y2 = LCD_HEIGHT-1; 416 y2 = LCD_HEIGHT-1;
338 417
339 418 bfunc = lcd_blockfuncs[drawmode];
340 while(y1++ <= y2) { 419 dst = &lcd_framebuffer[y1][x>>2];
341 pfunc(x, y1); 420 mask = pixmask[x & 3];
421
422 dst_end = dst + (y2 - y1) * (LCD_WIDTH/4);
423 do
424 {
425 bfunc(dst, mask, 0xFFu);
426 dst += (LCD_WIDTH/4);
342 } 427 }
428 while (dst <= dst_end);
343} 429}
344 430
345/* Draw a rectangular box */ 431/* Draw a rectangular box */
@@ -360,8 +446,10 @@ void lcd_drawrect(int x, int y, int width, int height)
360/* Fill a rectangular area */ 446/* Fill a rectangular area */
361void lcd_fillrect(int x, int y, int width, int height) 447void lcd_fillrect(int x, int y, int width, int height)
362{ 448{
363 int ny; 449 int nx;
364 450 unsigned char *dst, *dst_end;
451 unsigned mask, mask_right;
452 lcd_blockfunc_type *bfunc;
365 453
366 /* nothing to draw? */ 454 /* nothing to draw? */
367 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) 455 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
@@ -384,12 +472,36 @@ void lcd_fillrect(int x, int y, int width, int height)
384 if (y + height > LCD_HEIGHT) 472 if (y + height > LCD_HEIGHT)
385 height = LCD_HEIGHT - y; 473 height = LCD_HEIGHT - y;
386 474
387 ny = y; 475 bfunc = lcd_blockfuncs[drawmode];
388 while (ny <= height) 476 dst = &lcd_framebuffer[y][x>>2];
477 nx = width - 1 + (x & 3);
478 mask = 0xFFu << (2 * (x & 3));
479 mask_right = 0xFFu >> (2 * (~nx & 3));
480
481 for (; nx >= 4; nx -= 4)
482 {
483 unsigned char *dst_col = dst;
484
485 dst_end = dst_col + height * (LCD_WIDTH/4);
486 do
487 {
488 bfunc(dst_col, mask, 0xFFu);
489 dst_col += (LCD_WIDTH/4);
490 }
491 while (dst_col < dst_end);
492
493 dst++;
494 mask = 0xFFu;
495 }
496 mask &= mask_right;
497
498 dst_end = dst + height * (LCD_WIDTH/4);
499 do
389 { 500 {
390 lcd_hline (x, width, ny); 501 bfunc(dst, mask, 0xFFu);
391 ny++; 502 dst += (LCD_WIDTH/4);
392 } 503 }
504 while (dst < dst_end);
393} 505}
394 506
395/* About Rockbox' internal monochrome bitmap format: 507/* About Rockbox' internal monochrome bitmap format:
@@ -485,11 +597,10 @@ void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int heig
485/* About Rockbox' internal native bitmap format: 597/* About Rockbox' internal native bitmap format:
486 * 598 *
487 * A bitmap contains two bits for every pixel. 00 = white, 01 = light grey, 599 * A bitmap contains two bits for every pixel. 00 = white, 01 = light grey,
488 * 10 = dark grey, 11 = black. Bits within a byte are arranged vertically, LSB 600 * 10 = dark grey, 11 = black. Bits within a byte are arranged horizontally,
489 * at top. 601 * LSB at the left.
490 * The bytes are stored in row-major order, with byte 0 being top left, 602 * The bytes are stored in row-major order, with byte 0 being top left,
491 * byte 1 2nd from left etc. The first row of bytes defines pixel rows 603 * byte 1 2nd from left etc. Each row of bytes defines one pixel row.
492 * 0..3, the second row defines pixel row 4..7 etc.
493 * 604 *
494 * This is the same as the internal lcd hw format. */ 605 * This is the same as the internal lcd hw format. */
495 606
@@ -500,8 +611,9 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
500void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, 611void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
501 int stride, int x, int y, int width, int height) 612 int stride, int x, int y, int width, int height)
502{ 613{
503 int ny, nx, ymax; 614 int shift, nx;
504 const unsigned char * src_end; 615 unsigned char *dst, *dst_end;
616 unsigned mask, mask_right;
505 617
506 /* nothing to draw? */ 618 /* nothing to draw? */
507 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) 619 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
@@ -526,46 +638,49 @@ void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y,
526 if (y + height > LCD_HEIGHT) 638 if (y + height > LCD_HEIGHT)
527 height = LCD_HEIGHT - y; 639 height = LCD_HEIGHT - y;
528 640
529 src += stride * (src_y >> 3) + src_x; /* move starting point */ 641 stride = (stride + 3) >> 2; /* convert to no. of bytes */
530 src_y &= 7; 642
531 src_end = src + width; 643 src += stride * src_y + (src_x >> 2); /* move starting point */
644 src_x &= 3;
645 x -= src_x;
646 dst = &lcd_framebuffer[y][x>>2];
647 shift = x & 3;
648 nx = width - 1 + shift + src_x;
649
650 mask = 0xFFu << (2 * (shift + src_x));
651 mask_right = 0xFFu >> (2 * (~nx & 3));
532 652
533 nx = x; 653 shift *= 2;
654 dst_end = dst + height * (LCD_WIDTH/4);
534 do 655 do
535 { 656 {
536 const unsigned char *src_col = src++; 657 const unsigned char *src_row = src;
537 unsigned data = *src_col >> src_y; 658 unsigned char *dst_row = dst;
538 int numbits = 8 - src_y; 659 unsigned mask_row = mask;
660 unsigned data = 0;
539 661
540 ymax = y + height; 662 for (x = nx; x >= 4; x -= 4)
541 ny = y;
542 do
543 { 663 {
544 if (data & 0x03) 664 data |= *src_row++ << shift;
545 setpixel_value (nx,ny, 0xFF); 665
546 else 666 if (mask_row & 0xFF)
547 if (data & 0x01)
548 setpixel_value (nx,ny, 0x3F);
549 else
550 if (data & 0x02)
551 setpixel_value (nx,ny, 0xCF);
552 else
553 setpixel_value (nx,ny, 0x00);
554
555 ny++;
556
557 data >>= 2;
558 if (--numbits == 0)
559 { 667 {
560 src_col += stride; 668 setblock(dst_row, mask_row, data);
561 data = *src_col; 669 mask_row = 0xFF;
562 numbits = 4;
563 } 670 }
671 else
672 mask_row >>= 8;
673
674 dst_row++;
675 data >>= 8;
564 } 676 }
565 while (ny < ymax); 677 data |= *src_row << shift;
566 nx++; 678 setblock(dst_row, mask_row & mask_right, data);
679
680 src += stride;
681 dst += (LCD_WIDTH/4);
567 } 682 }
568 while (src < src_end); 683 while (dst < dst_end);
569} 684}
570 685
571/* Draw a full native bitmap */ 686/* Draw a full native bitmap */