1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 Dan Everton
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #include "screendump.h"
28 SDL_Surface
* lcd_surface
;
32 SDL_Color lcd_bl_color_dark
= {RED_CMP(LCD_BL_DARKCOLOR
),
33 GREEN_CMP(LCD_BL_DARKCOLOR
),
34 BLUE_CMP(LCD_BL_DARKCOLOR
), 0};
35 SDL_Color lcd_bl_color_bright
= {RED_CMP(LCD_BL_BRIGHTCOLOR
),
36 GREEN_CMP(LCD_BL_BRIGHTCOLOR
),
37 BLUE_CMP(LCD_BL_BRIGHTCOLOR
), 0};
39 SDL_Color lcd_bl_color2_dark
= {RED_CMP(LCD_BL_DARKCOLOR_2
),
40 GREEN_CMP(LCD_BL_DARKCOLOR_2
),
41 BLUE_CMP(LCD_BL_DARKCOLOR_2
), 0};
42 SDL_Color lcd_bl_color2_bright
= {RED_CMP(LCD_BL_BRIGHTCOLOR_2
),
43 GREEN_CMP(LCD_BL_BRIGHTCOLOR_2
),
44 BLUE_CMP(LCD_BL_BRIGHTCOLOR_2
), 0};
46 #endif /* HAVE_BACKLIGHT */
47 SDL_Color lcd_color_dark
= {RED_CMP(LCD_DARKCOLOR
),
48 GREEN_CMP(LCD_DARKCOLOR
),
49 BLUE_CMP(LCD_DARKCOLOR
), 0};
50 SDL_Color lcd_color_bright
= {RED_CMP(LCD_BRIGHTCOLOR
),
51 GREEN_CMP(LCD_BRIGHTCOLOR
),
52 BLUE_CMP(LCD_BRIGHTCOLOR
), 0};
54 SDL_Color lcd_color2_dark
= {RED_CMP(LCD_DARKCOLOR_2
),
55 GREEN_CMP(LCD_DARKCOLOR_2
),
56 BLUE_CMP(LCD_DARKCOLOR_2
), 0};
57 SDL_Color lcd_color2_bright
= {RED_CMP(LCD_BRIGHTCOLOR_2
),
58 GREEN_CMP(LCD_BRIGHTCOLOR_2
),
59 BLUE_CMP(LCD_BRIGHTCOLOR_2
), 0};
63 #define NUM_SHADES 128
65 #define NUM_SHADES 129
68 #else /* LCD_DEPTH > 8 */
70 #ifdef HAVE_TRANSFLECTIVE_LCD
71 #define BACKLIGHT_OFF_ALPHA 85 /* 1/3 brightness */
73 #define BACKLIGHT_OFF_ALPHA 0 /* pitch black */
76 #endif /* LCD_DEPTH */
79 unsigned long (*lcd_ex_getpixel
)(int, int) = NULL
;
80 #endif /* LCD_DEPTH < 8 */
83 /* Only defined for positive, non-split LCD for now */
84 static const unsigned char colorindex
[4] = {128, 85, 43, 0};
87 static unsigned long get_lcd_pixel(int x
, int y
)
90 #ifdef HAVE_NEGATIVE_LCD
91 return (lcd_framebuffer
[y
/8][x
] & (1 << (y
& 7))) ? (NUM_SHADES
-1) : 0;
93 return (lcd_framebuffer
[y
/8][x
] & (1 << (y
& 7))) ? 0 : (NUM_SHADES
-1);
96 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
97 return colorindex
[(lcd_framebuffer
[y
][x
/4] >> (2 * (~x
& 3))) & 3];
98 #elif LCD_PIXELFORMAT == VERTICAL_PACKING
99 return colorindex
[(lcd_framebuffer
[y
/4][x
] >> (2 * (y
& 3))) & 3];
100 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
101 unsigned bits
= (lcd_framebuffer
[y
/8][x
] >> (y
& 7)) & 0x0101;
102 return colorindex
[(bits
| (bits
>> 7)) & 3];
104 #elif LCD_DEPTH == 16
105 #if LCD_PIXELFORMAT == RGB565SWAPPED
106 unsigned bits
= lcd_framebuffer
[y
][x
];
107 return (bits
>> 8) | (bits
<< 8);
109 #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
110 return *(&lcd_framebuffer
[0][0]+LCD_HEIGHT
*x
+y
);
112 return lcd_framebuffer
[y
][x
];
118 void lcd_update(void)
120 /* update a full screen rect */
121 lcd_update_rect(0, 0, LCD_WIDTH
, LCD_HEIGHT
);
124 void lcd_update_rect(int x_start
, int y_start
, int width
, int height
)
126 sdl_update_rect(lcd_surface
, x_start
, y_start
, width
, height
,
127 LCD_WIDTH
, LCD_HEIGHT
, get_lcd_pixel
);
128 sdl_gui_update(lcd_surface
, x_start
, y_start
, width
,
129 height
+ LCD_SPLIT_LINES
, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
130 background
? UI_LCD_POSX
: 0, background
? UI_LCD_POSY
: 0);
133 #ifdef HAVE_BACKLIGHT
134 void sim_backlight(int value
)
138 sdl_set_gradient(lcd_surface
, &lcd_bl_color_dark
,
139 &lcd_bl_color_bright
, 0, NUM_SHADES
);
140 #ifdef HAVE_LCD_SPLIT
141 sdl_set_gradient(lcd_surface
, &lcd_bl_color2_dark
,
142 &lcd_bl_color2_bright
, NUM_SHADES
, NUM_SHADES
);
145 sdl_set_gradient(lcd_surface
, &lcd_color_dark
,
146 &lcd_color_bright
, 0, NUM_SHADES
);
147 #ifdef HAVE_LCD_SPLIT
148 sdl_set_gradient(lcd_surface
, &lcd_color2_dark
,
149 &lcd_color2_bright
, NUM_SHADES
, NUM_SHADES
);
152 #else /* LCD_DEPTH > 8 */
153 SDL_SetAlpha(lcd_surface
, SDL_SRCALPHA
, (value
* 255) / 100);
154 #endif /* LCD_DEPTH */
156 sdl_gui_update(lcd_surface
, 0, 0, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
157 SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
158 background
? UI_LCD_POSX
: 0, background
? UI_LCD_POSY
: 0);
160 #endif /* HAVE_BACKLIGHT */
162 /* initialise simulator lcd driver */
163 void sim_lcd_init(void)
166 lcd_surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
,
167 SIM_LCD_WIDTH
* display_zoom
,
168 SIM_LCD_HEIGHT
* display_zoom
,
169 LCD_DEPTH
, 0, 0, 0, 0);
171 lcd_surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
,
172 SIM_LCD_WIDTH
* display_zoom
,
173 SIM_LCD_HEIGHT
* display_zoom
,
176 #ifdef HAVE_BACKLIGHT
177 sdl_set_gradient(lcd_surface
, &lcd_bl_color_dark
,
178 &lcd_bl_color_bright
, 0, NUM_SHADES
);
179 #ifdef HAVE_LCD_SPLIT
180 sdl_set_gradient(lcd_surface
, &lcd_bl_color2_dark
,
181 &lcd_bl_color2_bright
, NUM_SHADES
, NUM_SHADES
);
183 #else /* !HAVE_BACKLIGHT */
184 sdl_set_gradient(lcd_surface
, &lcd_color_dark
,
185 &lcd_color_bright
, 0, NUM_SHADES
);
186 #ifdef HAVE_LCD_SPLIT
187 sdl_set_gradient(lcd_surface
, &lcd_color2_dark
,
188 &lcd_color2_bright
, NUM_SHADES
, NUM_SHADES
);
190 #endif /* !HAVE_BACKLIGHT */
191 #endif /* LCD_DEPTH */
195 void sim_lcd_ex_init(unsigned long (*getpixel
)(int, int))
197 lcd_ex_getpixel
= getpixel
;
200 void sim_lcd_ex_update_rect(int x_start
, int y_start
, int width
, int height
)
202 if (lcd_ex_getpixel
) {
203 sdl_update_rect(lcd_surface
, x_start
, y_start
, width
, height
,
204 LCD_WIDTH
, LCD_HEIGHT
, lcd_ex_getpixel
);
205 sdl_gui_update(lcd_surface
, x_start
, y_start
, width
,
206 height
+ LCD_SPLIT_LINES
, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
207 background
? UI_LCD_POSX
: 0,
208 background
? UI_LCD_POSY
: 0);
213 #ifdef HAVE_LCD_COLOR
215 * |R| |1.000000 -0.000001 1.402000| |Y'|
216 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
217 * |B| |1.000000 1.772000 0.000000| |Pr|
218 * Scaled, normalized, rounded and tweaked to yield RGB 565:
219 * |R| |74 0 101| |Y' - 16| >> 9
220 * |G| = |74 -24 -51| |Cb - 128| >> 8
221 * |B| |74 128 0| |Cr - 128| >> 9
229 static inline int clamp(int val
, int min
, int max
)
238 void lcd_yuv_set_options(unsigned options
)
243 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
245 void lcd_blit_yuv(unsigned char * const src
[3],
246 int src_x
, int src_y
, int stride
,
247 int x
, int y
, int width
, int height
)
249 const unsigned char *ysrc
, *usrc
, *vsrc
;
251 fb_data
*dst
, *row_end
;
254 /* width and height must be >= 2 and an even number */
256 linecounter
= height
>> 1;
258 #if LCD_WIDTH >= LCD_HEIGHT
259 dst
= &lcd_framebuffer
[y
][x
];
260 row_end
= dst
+ width
;
262 dst
= &lcd_framebuffer
[x
][LCD_WIDTH
- y
- 1];
263 row_end
= dst
+ LCD_WIDTH
* width
;
267 ysrc
= src
[0] + z
+ src_x
;
268 usrc
= src
[1] + (z
>> 2) + (src_x
>> 1);
269 vsrc
= src
[2] + (usrc
- src
[1]);
271 /* stride => amount to jump from end of last row to start of next */
274 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
280 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
282 y
= YFAC
*(*ysrc
++ - 16);
287 guv
= GUFAC
*cb
+ GVFAC
*cr
;
294 if ((unsigned)(r
| g
| b
) > 64*256-1)
296 r
= clamp(r
, 0, 64*256-1);
297 g
= clamp(g
, 0, 64*256-1);
298 b
= clamp(b
, 0, 64*256-1);
301 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
303 #if LCD_WIDTH >= LCD_HEIGHT
309 y
= YFAC
*(*ysrc
++ - 16);
314 if ((unsigned)(r
| g
| b
) > 64*256-1)
316 r
= clamp(r
, 0, 64*256-1);
317 g
= clamp(g
, 0, 64*256-1);
318 b
= clamp(b
, 0, 64*256-1);
321 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
323 #if LCD_WIDTH >= LCD_HEIGHT
329 while (dst
< row_end
);
335 #if LCD_WIDTH >= LCD_HEIGHT
336 row_end
+= LCD_WIDTH
;
337 dst
+= LCD_WIDTH
- width
;
340 dst
-= LCD_WIDTH
*width
+ 1;
345 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
347 y
= YFAC
*(*ysrc
++ - 16);
352 guv
= GUFAC
*cb
+ GVFAC
*cr
;
359 if ((unsigned)(r
| g
| b
) > 64*256-1)
361 r
= clamp(r
, 0, 64*256-1);
362 g
= clamp(g
, 0, 64*256-1);
363 b
= clamp(b
, 0, 64*256-1);
366 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
368 #if LCD_WIDTH >= LCD_HEIGHT
374 y
= YFAC
*(*ysrc
++ - 16);
379 if ((unsigned)(r
| g
| b
) > 64*256-1)
381 r
= clamp(r
, 0, 64*256-1);
382 g
= clamp(g
, 0, 64*256-1);
383 b
= clamp(b
, 0, 64*256-1);
386 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
388 #if LCD_WIDTH >= LCD_HEIGHT
394 while (dst
< row_end
);
400 #if LCD_WIDTH >= LCD_HEIGHT
401 row_end
+= LCD_WIDTH
;
402 dst
+= LCD_WIDTH
- width
;
405 dst
-= LCD_WIDTH
*width
+ 1;
408 while (--linecounter
> 0);
410 #if LCD_WIDTH >= LCD_HEIGHT
411 lcd_update_rect(x
, y
, width
, height
);
413 lcd_update_rect(LCD_WIDTH
- y
- height
, x
, height
, width
);
416 #endif /* HAVE_LCD_COLOR */