diff options
Diffstat (limited to 'firmware/target/coldfire/iaudio/x5/lcd-x5.c')
-rwxr-xr-x | firmware/target/coldfire/iaudio/x5/lcd-x5.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/firmware/target/coldfire/iaudio/x5/lcd-x5.c b/firmware/target/coldfire/iaudio/x5/lcd-x5.c index f66b8801dc..57b4789070 100755 --- a/firmware/target/coldfire/iaudio/x5/lcd-x5.c +++ b/firmware/target/coldfire/iaudio/x5/lcd-x5.c | |||
@@ -423,6 +423,115 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
423 | /*if(display_on)*/ | 423 | /*if(display_on)*/ |
424 | } | 424 | } |
425 | 425 | ||
426 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
427 | /* Assumes YCrCb 4:2:0. */ | ||
428 | /* | ||
429 | See http://en.wikipedia.org/wiki/YCbCr | ||
430 | ITU-R BT.601 (formerly CCIR 601): | ||
431 | |Y'| | 0.299000 0.587000 0.114000| |R| | ||
432 | |Pb| = |-0.168736 -0.331264 0.500000| |G| or 0.564334 * (B - Y') | ||
433 | |Pr| | 0.500000 -0.418688 0.081312| |B| or 0.713267 * (R - Y') | ||
434 | Scaled, normalized and rounded: | ||
435 | |Y'| | 65 129 25| |R| + 16 : 16->235 | ||
436 | |Cb| = |-38 -74 112| |G| + 128 : 16->240 | ||
437 | |Cr| |112 -94 -18| |B| + 128 : 16->240 | ||
438 | |||
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], | ||
451 | int src_x, int src_y, int stride, | ||
452 | int x, int y, int width, int height) | ||
453 | { | ||
454 | const unsigned char *ysrc, *usrc, *vsrc; | ||
455 | int uv_stepper, uv_step, y_end; | ||
456 | |||
457 | if (!display_on) | ||
458 | return; | ||
459 | |||
460 | width = (width + 1) & ~1; | ||
461 | height = (height + 1) & ~1; | ||
462 | y_end = y + height; | ||
463 | |||
464 | /* Set start position and window */ | ||
465 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | | ||
466 | (((y + roll_offset) & 127) + y_offset)); | ||
467 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); | ||
468 | |||
469 | lcd_begin_write_gram(); | ||
470 | |||
471 | ysrc = src[0] + src_y*stride + src_x; | ||
472 | usrc = src[1] + (src_y*stride >> 2) + (src_x >> 1); | ||
473 | vsrc = src[2] + (usrc - src[1]); | ||
474 | |||
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 | |||
479 | do | ||
480 | { | ||
481 | const unsigned char *ysrc_end = ysrc + width; | ||
482 | |||
483 | do | ||
484 | { | ||
485 | int lum, cb, cr; | ||
486 | int rv, guv, bu; | ||
487 | int r, g, b; | ||
488 | |||
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 | } | ||
533 | while (++y < y_end); | ||
534 | } | ||
426 | 535 | ||
427 | /* Update the display. | 536 | /* Update the display. |
428 | This must be called after all other LCD functions that change the | 537 | This must be called after all other LCD functions that change the |