diff options
Diffstat (limited to 'firmware/target/coldfire/iaudio/x5/lcd-x5.c')
-rwxr-xr-x | firmware/target/coldfire/iaudio/x5/lcd-x5.c | 135 |
1 files changed, 31 insertions, 104 deletions
diff --git a/firmware/target/coldfire/iaudio/x5/lcd-x5.c b/firmware/target/coldfire/iaudio/x5/lcd-x5.c index 240b1db586..e1fe23a442 100755 --- a/firmware/target/coldfire/iaudio/x5/lcd-x5.c +++ b/firmware/target/coldfire/iaudio/x5/lcd-x5.c | |||
@@ -100,25 +100,6 @@ static inline void lcd_begin_write_gram(void) | |||
100 | LCD_CMD = R_WRITE_DATA_2_GRAM << 1; | 100 | LCD_CMD = R_WRITE_DATA_2_GRAM << 1; |
101 | } | 101 | } |
102 | 102 | ||
103 | static inline void lcd_write_one(unsigned short px) | ||
104 | { | ||
105 | unsigned short pxsr = px >> 8; | ||
106 | LCD_DATA = pxsr + (pxsr & 0x1F8); | ||
107 | LCD_DATA = px << 1; | ||
108 | } | ||
109 | |||
110 | /* Write two pixels to gram from a long */ | ||
111 | /* called very frequently - inline! */ | ||
112 | static inline void lcd_write_two(unsigned long px2) | ||
113 | { | ||
114 | unsigned short px2sr = px2 >> 24; | ||
115 | LCD_DATA = px2sr + (px2sr & 0x1F8); | ||
116 | LCD_DATA = px2 >> 15; | ||
117 | px2sr = px2 >> 8; | ||
118 | LCD_DATA = px2sr + (px2sr & 0x1F8); | ||
119 | LCD_DATA = px2 << 1; | ||
120 | } | ||
121 | |||
122 | /*** hardware configuration ***/ | 103 | /*** hardware configuration ***/ |
123 | 104 | ||
124 | int lcd_default_contrast(void) | 105 | int lcd_default_contrast(void) |
@@ -423,45 +404,38 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
423 | /*if(display_on)*/ | 404 | /*if(display_on)*/ |
424 | } | 405 | } |
425 | 406 | ||
426 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 407 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. |
427 | /* Assumes YCrCb 4:2:0. */ | 408 | * y should have two lines of Y back to back. |
428 | /* | 409 | * bu and rv should contain the Cb and Cr data for the two lines of Y. |
429 | See http://en.wikipedia.org/wiki/YCbCr | 410 | * Stores bu, guv and rv in repective buffers for use in second line. |
430 | ITU-R BT.601 (formerly CCIR 601): | 411 | */ |
431 | |Y'| | 0.299000 0.587000 0.114000| |R| | 412 | extern void lcd_write_yuv420_lines(const unsigned char *y, |
432 | |Pb| = |-0.168736 -0.331264 0.500000| |G| or 0.564334 * (B - Y') | 413 | unsigned char *bu, unsigned char *guv, unsigned char *rv, |
433 | |Pr| | 0.500000 -0.418688 0.081312| |B| or 0.713267 * (R - Y') | 414 | int width); |
434 | Scaled, normalized and rounded: | 415 | |
435 | |Y'| | 65 129 25| |R| + 16 : 16->235 | 416 | /* Performance function to blit a YUV bitmap directly to the LCD |
436 | |Cb| = |-38 -74 112| |G| + 128 : 16->240 | 417 | * src_x, src_y, width and height should be even and within the LCD's |
437 | |Cr| |112 -94 -18| |B| + 128 : 16->240 | 418 | * boundaries. |
438 | 419 | */ | |
439 | The inverse: | ||
440 | |R| |1.000000 -0.000001 1.402000| |Y'| | ||
441 | |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
442 | |B| |1.000000 1.772000 0.000000| |Pr| | ||
443 | Scaled, normalized, rounded and tweaked to yield RGB 666: | ||
444 | |R| |298 0 409| |Y' - 16| / 1024 | ||
445 | |G| = |298 -100 -208| |Cb - 128| / 1024 | ||
446 | |B| |298 516 0| |Cr - 128| / 1024 | ||
447 | */ | ||
448 | void lcd_yuv_blit(unsigned char * const [3], int, int, int, | ||
449 | int, int, int, int) ICODE_ATTR; | ||
450 | void lcd_yuv_blit(unsigned char * const src[3], | 420 | void lcd_yuv_blit(unsigned char * const src[3], |
451 | int src_x, int src_y, int stride, | 421 | int src_x, int src_y, int stride, |
452 | int x, int y, int width, int height) | 422 | int x, int y, int width, int height) |
453 | { | 423 | { |
424 | /* IRAM Y, Cb/bu, guv and Cb/rv buffers. */ | ||
425 | unsigned char y_ibuf[LCD_WIDTH*2]; | ||
426 | unsigned char bu_ibuf[LCD_WIDTH/2]; | ||
427 | unsigned char guv_ibuf[LCD_WIDTH/2]; | ||
428 | unsigned char rv_ibuf[LCD_WIDTH/2]; | ||
454 | const unsigned char *ysrc, *usrc, *vsrc; | 429 | const unsigned char *ysrc, *usrc, *vsrc; |
455 | int uv_stepper, uv_step, y_end; | 430 | const unsigned char *ysrc_max; |
456 | 431 | ||
457 | if (!display_on) | 432 | if (!display_on) |
458 | return; | 433 | return; |
459 | 434 | ||
460 | width = (width + 1) & ~1; | 435 | width = (width + 1) & ~1; |
461 | height = (height + 1) & ~1; | 436 | height = (height + 1) & ~1; |
462 | y_end = y + height; | ||
463 | 437 | ||
464 | /* Set start position and window */ | 438 | /* Set start position and window */ |
465 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | | 439 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | |
466 | (((y + roll_offset) & 127) + y_offset)); | 440 | (((y + roll_offset) & 127) + y_offset)); |
467 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); | 441 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); |
@@ -471,72 +445,26 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
471 | ysrc = src[0] + src_y*stride + src_x; | 445 | ysrc = src[0] + src_y*stride + src_x; |
472 | usrc = src[1] + (src_y*stride >> 2) + (src_x >> 1); | 446 | usrc = src[1] + (src_y*stride >> 2) + (src_x >> 1); |
473 | vsrc = src[2] + (usrc - src[1]); | 447 | vsrc = src[2] + (usrc - src[1]); |
474 | 448 | ysrc_max = ysrc + height*stride; | |
475 | stride = stride - width; /* Use end of current line->start of next */ | ||
476 | uv_stepper = (stride >> 1) - (width >> 1); | ||
477 | uv_step = uv_stepper - (stride >> 1); | ||
478 | 449 | ||
479 | do | 450 | do |
480 | { | 451 | { |
481 | const unsigned char *ysrc_end = ysrc + width; | 452 | memcpy(y_ibuf, ysrc, width); |
482 | 453 | memcpy(&y_ibuf[width], &ysrc[stride], width); | |
483 | do | 454 | memcpy(bu_ibuf, usrc, width >> 1); |
484 | { | 455 | memcpy(rv_ibuf, vsrc, width >> 1); |
485 | int lum, cb, cr; | 456 | lcd_write_yuv420_lines(y_ibuf, bu_ibuf, guv_ibuf, rv_ibuf, width); |
486 | int rv, guv, bu; | 457 | ysrc += stride << 1; |
487 | int r, g, b; | 458 | usrc += stride >> 1; |
488 | 459 | vsrc += stride >> 1; | |
489 | lum = 298* *ysrc++ - 4768; /* 298*16 */ | ||
490 | cb = *usrc++ - 128; | ||
491 | cr = *vsrc++ - 128; | ||
492 | bu = 516*cb; | ||
493 | guv = -100*cb - 208*cr; | ||
494 | rv = 409*cr; | ||
495 | |||
496 | r = (lum + rv) >> 10; | ||
497 | g = (lum + guv) >> 10; | ||
498 | b = (lum + bu) >> 10; | ||
499 | |||
500 | if ((unsigned)r > 63) | ||
501 | r = (r < 0) ? 0 : 63; | ||
502 | if ((unsigned)g > 63) | ||
503 | g = (g < 0) ? 0 : 63; | ||
504 | if ((unsigned)b > 63) | ||
505 | b = (b < 0) ? 0 : 63; | ||
506 | |||
507 | LCD_DATA = (r << 3) | (g >> 3); | ||
508 | LCD_DATA = (g << 6) | b; | ||
509 | |||
510 | lum = 298* *ysrc++ - 4768; /* 298*16 */ | ||
511 | r = (lum + rv) >> 10; | ||
512 | g = (lum + guv) >> 10; | ||
513 | b = (lum + bu) >> 10; | ||
514 | |||
515 | if ((unsigned)r > 63) | ||
516 | r = (r < 0) ? 0 : 63; | ||
517 | if ((unsigned)g > 63) | ||
518 | g = (g < 0) ? 0 : 63; | ||
519 | if ((unsigned)b > 63) | ||
520 | b = (b < 0) ? 0 : 63; | ||
521 | |||
522 | LCD_DATA = (r << 3) | (g >> 3); | ||
523 | LCD_DATA = (g << 6) | b; | ||
524 | } | ||
525 | while (ysrc < ysrc_end); | ||
526 | |||
527 | usrc += uv_step; | ||
528 | vsrc += uv_step; | ||
529 | uv_step = uv_stepper - uv_step; | ||
530 | |||
531 | ysrc += stride; | ||
532 | } | 460 | } |
533 | while (++y < y_end); | 461 | while (ysrc < ysrc_max); |
534 | } /* lcd_yuv_blit */ | 462 | } /* lcd_yuv_blit */ |
535 | 463 | ||
464 | |||
536 | /* Update the display. | 465 | /* Update the display. |
537 | This must be called after all other LCD functions that change the | 466 | This must be called after all other LCD functions that change the |
538 | lcd frame buffer. */ | 467 | lcd frame buffer. */ |
539 | void lcd_update(void) ICODE_ATTR; | ||
540 | void lcd_update(void) | 468 | void lcd_update(void) |
541 | { | 469 | { |
542 | if (!display_on) | 470 | if (!display_on) |
@@ -554,7 +482,6 @@ void lcd_update(void) | |||
554 | } /* lcd_update */ | 482 | } /* lcd_update */ |
555 | 483 | ||
556 | /* Update a fraction of the display. */ | 484 | /* Update a fraction of the display. */ |
557 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | ||
558 | void lcd_update_rect(int x, int y, int width, int height) | 485 | void lcd_update_rect(int x, int y, int width, int height) |
559 | { | 486 | { |
560 | int ymax; | 487 | int ymax; |