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 ****************************************************************************/
25 #include "screendump.h"
27 SDL_Surface
* lcd_surface
;
31 SDL_Color lcd_bl_color_dark
= {RED_CMP(LCD_BL_DARKCOLOR
),
32 GREEN_CMP(LCD_BL_DARKCOLOR
),
33 BLUE_CMP(LCD_BL_DARKCOLOR
), 0};
34 SDL_Color lcd_bl_color_bright
= {RED_CMP(LCD_BL_BRIGHTCOLOR
),
35 GREEN_CMP(LCD_BL_BRIGHTCOLOR
),
36 BLUE_CMP(LCD_BL_BRIGHTCOLOR
), 0};
38 SDL_Color lcd_bl_color2_dark
= {RED_CMP(LCD_BL_DARKCOLOR_2
),
39 GREEN_CMP(LCD_BL_DARKCOLOR_2
),
40 BLUE_CMP(LCD_BL_DARKCOLOR_2
), 0};
41 SDL_Color lcd_bl_color2_bright
= {RED_CMP(LCD_BL_BRIGHTCOLOR_2
),
42 GREEN_CMP(LCD_BL_BRIGHTCOLOR_2
),
43 BLUE_CMP(LCD_BL_BRIGHTCOLOR_2
), 0};
45 #endif /* HAVE_BACKLIGHT */
46 SDL_Color lcd_color_dark
= {RED_CMP(LCD_DARKCOLOR
),
47 GREEN_CMP(LCD_DARKCOLOR
),
48 BLUE_CMP(LCD_DARKCOLOR
), 0};
49 SDL_Color lcd_color_bright
= {RED_CMP(LCD_BRIGHTCOLOR
),
50 GREEN_CMP(LCD_BRIGHTCOLOR
),
51 BLUE_CMP(LCD_BRIGHTCOLOR
), 0};
53 SDL_Color lcd_color2_dark
= {RED_CMP(LCD_DARKCOLOR_2
),
54 GREEN_CMP(LCD_DARKCOLOR_2
),
55 BLUE_CMP(LCD_DARKCOLOR_2
), 0};
56 SDL_Color lcd_color2_bright
= {RED_CMP(LCD_BRIGHTCOLOR_2
),
57 GREEN_CMP(LCD_BRIGHTCOLOR_2
),
58 BLUE_CMP(LCD_BRIGHTCOLOR_2
), 0};
62 #define NUM_SHADES 128
64 #define NUM_SHADES 129
67 #else /* LCD_DEPTH > 8 */
69 #ifdef HAVE_TRANSFLECTIVE_LCD
70 #define BACKLIGHT_OFF_ALPHA 85 /* 1/3 brightness */
72 #define BACKLIGHT_OFF_ALPHA 0 /* pitch black */
75 #endif /* LCD_DEPTH */
78 unsigned long (*lcd_ex_getpixel
)(int, int) = NULL
;
79 #endif /* LCD_DEPTH < 8 */
82 /* Only defined for positive, non-split LCD for now */
83 static const unsigned char colorindex
[4] = {128, 85, 43, 0};
86 static unsigned long get_lcd_pixel(int x
, int y
)
89 #ifdef HAVE_NEGATIVE_LCD
90 return (lcd_framebuffer
[y
/8][x
] & (1 << (y
& 7))) ? (NUM_SHADES
-1) : 0;
92 return (lcd_framebuffer
[y
/8][x
] & (1 << (y
& 7))) ? 0 : (NUM_SHADES
-1);
95 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
96 return colorindex
[(lcd_framebuffer
[y
][x
/4] >> (2 * (~x
& 3))) & 3];
97 #elif LCD_PIXELFORMAT == VERTICAL_PACKING
98 return colorindex
[(lcd_framebuffer
[y
/4][x
] >> (2 * (y
& 3))) & 3];
99 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
100 unsigned bits
= (lcd_framebuffer
[y
/8][x
] >> (y
& 7)) & 0x0101;
101 return colorindex
[(bits
| (bits
>> 7)) & 3];
103 #elif LCD_DEPTH == 16
104 #if LCD_PIXELFORMAT == RGB565SWAPPED
105 unsigned bits
= lcd_framebuffer
[y
][x
];
106 return (bits
>> 8) | (bits
<< 8);
108 #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
109 return *(&lcd_framebuffer
[0][0]+LCD_HEIGHT
*x
+y
);
111 return lcd_framebuffer
[y
][x
];
117 void lcd_update(void)
119 /* update a full screen rect */
120 lcd_update_rect(0, 0, LCD_WIDTH
, LCD_HEIGHT
);
123 void lcd_update_rect(int x_start
, int y_start
, int width
, int height
)
125 sdl_update_rect(lcd_surface
, x_start
, y_start
, width
, height
,
126 LCD_WIDTH
, LCD_HEIGHT
, get_lcd_pixel
);
127 sdl_gui_update(lcd_surface
, x_start
, y_start
, width
,
128 height
+ LCD_SPLIT_LINES
, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
129 background
? UI_LCD_POSX
: 0, background
? UI_LCD_POSY
: 0);
132 #ifdef HAVE_BACKLIGHT
133 void sim_backlight(int value
)
137 sdl_set_gradient(lcd_surface
, &lcd_bl_color_dark
,
138 &lcd_bl_color_bright
, 0, NUM_SHADES
);
139 #ifdef HAVE_LCD_SPLIT
140 sdl_set_gradient(lcd_surface
, &lcd_bl_color2_dark
,
141 &lcd_bl_color2_bright
, NUM_SHADES
, NUM_SHADES
);
144 sdl_set_gradient(lcd_surface
, &lcd_color_dark
,
145 &lcd_color_bright
, 0, NUM_SHADES
);
146 #ifdef HAVE_LCD_SPLIT
147 sdl_set_gradient(lcd_surface
, &lcd_color2_dark
,
148 &lcd_color2_bright
, NUM_SHADES
, NUM_SHADES
);
151 #else /* LCD_DEPTH > 8 */
153 SDL_SetAlpha(lcd_surface
, 0, SDL_ALPHA_OPAQUE
); /* full on */
155 SDL_SetAlpha(lcd_surface
, SDL_SRCALPHA
, BACKLIGHT_OFF_ALPHA
);
157 #endif /* LCD_DEPTH */
159 sdl_gui_update(lcd_surface
, 0, 0, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
160 SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
161 background
? UI_LCD_POSX
: 0, background
? UI_LCD_POSY
: 0);
163 #endif /* HAVE_BACKLIGHT */
165 /* initialise simulator lcd driver */
166 void sim_lcd_init(void)
169 lcd_surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
,
170 SIM_LCD_WIDTH
* display_zoom
,
171 SIM_LCD_HEIGHT
* display_zoom
,
172 LCD_DEPTH
, 0, 0, 0, 0);
174 lcd_surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
,
175 SIM_LCD_WIDTH
* display_zoom
,
176 SIM_LCD_HEIGHT
* display_zoom
,
179 #ifdef HAVE_BACKLIGHT
180 sdl_set_gradient(lcd_surface
, &lcd_bl_color_dark
,
181 &lcd_bl_color_bright
, 0, NUM_SHADES
);
182 #ifdef HAVE_LCD_SPLIT
183 sdl_set_gradient(lcd_surface
, &lcd_bl_color2_dark
,
184 &lcd_bl_color2_bright
, NUM_SHADES
, NUM_SHADES
);
186 #else /* !HAVE_BACKLIGHT */
187 sdl_set_gradient(lcd_surface
, &lcd_color_dark
,
188 &lcd_color_bright
, 0, NUM_SHADES
);
189 #ifdef HAVE_LCD_SPLIT
190 sdl_set_gradient(lcd_surface
, &lcd_color2_dark
,
191 &lcd_color2_bright
, NUM_SHADES
, NUM_SHADES
);
193 #endif /* !HAVE_BACKLIGHT */
194 #endif /* LCD_DEPTH */
198 void sim_lcd_ex_init(unsigned long (*getpixel
)(int, int))
200 lcd_ex_getpixel
= getpixel
;
203 void sim_lcd_ex_update_rect(int x_start
, int y_start
, int width
, int height
)
205 if (lcd_ex_getpixel
) {
206 sdl_update_rect(lcd_surface
, x_start
, y_start
, width
, height
,
207 LCD_WIDTH
, LCD_HEIGHT
, lcd_ex_getpixel
);
208 sdl_gui_update(lcd_surface
, x_start
, y_start
, width
,
209 height
+ LCD_SPLIT_LINES
, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
210 background
? UI_LCD_POSX
: 0,
211 background
? UI_LCD_POSY
: 0);
216 #ifdef HAVE_LCD_COLOR
218 * |R| |1.000000 -0.000001 1.402000| |Y'|
219 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
220 * |B| |1.000000 1.772000 0.000000| |Pr|
221 * Scaled, normalized, rounded and tweaked to yield RGB 565:
222 * |R| |74 0 101| |Y' - 16| >> 9
223 * |G| = |74 -24 -51| |Cb - 128| >> 8
224 * |B| |74 128 0| |Cr - 128| >> 9
232 static inline int clamp(int val
, int min
, int max
)
241 void lcd_yuv_set_options(unsigned options
)
246 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
248 void lcd_blit_yuv(unsigned char * const src
[3],
249 int src_x
, int src_y
, int stride
,
250 int x
, int y
, int width
, int height
)
252 const unsigned char *ysrc
, *usrc
, *vsrc
;
254 fb_data
*dst
, *row_end
;
257 /* width and height must be >= 2 and an even number */
259 linecounter
= height
>> 1;
261 #if LCD_WIDTH >= LCD_HEIGHT
262 dst
= &lcd_framebuffer
[y
][x
];
263 row_end
= dst
+ width
;
265 dst
= &lcd_framebuffer
[x
][LCD_WIDTH
- y
- 1];
266 row_end
= dst
+ LCD_WIDTH
* width
;
270 ysrc
= src
[0] + z
+ src_x
;
271 usrc
= src
[1] + (z
>> 2) + (src_x
>> 1);
272 vsrc
= src
[2] + (usrc
- src
[1]);
274 /* stride => amount to jump from end of last row to start of next */
277 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
283 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
285 y
= YFAC
*(*ysrc
++ - 16);
290 guv
= GUFAC
*cb
+ GVFAC
*cr
;
297 if ((unsigned)(r
| g
| b
) > 64*256-1)
299 r
= clamp(r
, 0, 64*256-1);
300 g
= clamp(g
, 0, 64*256-1);
301 b
= clamp(b
, 0, 64*256-1);
304 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
306 #if LCD_WIDTH >= LCD_HEIGHT
312 y
= YFAC
*(*ysrc
++ - 16);
317 if ((unsigned)(r
| g
| b
) > 64*256-1)
319 r
= clamp(r
, 0, 64*256-1);
320 g
= clamp(g
, 0, 64*256-1);
321 b
= clamp(b
, 0, 64*256-1);
324 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
326 #if LCD_WIDTH >= LCD_HEIGHT
332 while (dst
< row_end
);
338 #if LCD_WIDTH >= LCD_HEIGHT
339 row_end
+= LCD_WIDTH
;
340 dst
+= LCD_WIDTH
- width
;
343 dst
-= LCD_WIDTH
*width
+ 1;
348 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
350 y
= YFAC
*(*ysrc
++ - 16);
355 guv
= GUFAC
*cb
+ GVFAC
*cr
;
362 if ((unsigned)(r
| g
| b
) > 64*256-1)
364 r
= clamp(r
, 0, 64*256-1);
365 g
= clamp(g
, 0, 64*256-1);
366 b
= clamp(b
, 0, 64*256-1);
369 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
371 #if LCD_WIDTH >= LCD_HEIGHT
377 y
= YFAC
*(*ysrc
++ - 16);
382 if ((unsigned)(r
| g
| b
) > 64*256-1)
384 r
= clamp(r
, 0, 64*256-1);
385 g
= clamp(g
, 0, 64*256-1);
386 b
= clamp(b
, 0, 64*256-1);
389 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
391 #if LCD_WIDTH >= LCD_HEIGHT
397 while (dst
< row_end
);
403 #if LCD_WIDTH >= LCD_HEIGHT
404 row_end
+= LCD_WIDTH
;
405 dst
+= LCD_WIDTH
- width
;
408 dst
-= LCD_WIDTH
*width
+ 1;
411 while (--linecounter
> 0);
413 #if LCD_WIDTH >= LCD_HEIGHT
414 lcd_update_rect(x
, y
, width
, height
);
416 lcd_update_rect(LCD_WIDTH
- y
- height
, x
, height
, width
);
419 #endif /* HAVE_LCD_COLOR */