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 */
152 SDL_SetAlpha(lcd_surface
, SDL_SRCALPHA
, (value
* 255) / 100);
153 #endif /* LCD_DEPTH */
155 sdl_gui_update(lcd_surface
, 0, 0, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
156 SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
157 background
? UI_LCD_POSX
: 0, background
? UI_LCD_POSY
: 0);
159 #endif /* HAVE_BACKLIGHT */
161 /* initialise simulator lcd driver */
162 void sim_lcd_init(void)
165 lcd_surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
,
166 SIM_LCD_WIDTH
* display_zoom
,
167 SIM_LCD_HEIGHT
* display_zoom
,
168 LCD_DEPTH
, 0, 0, 0, 0);
170 lcd_surface
= SDL_CreateRGBSurface(SDL_SWSURFACE
,
171 SIM_LCD_WIDTH
* display_zoom
,
172 SIM_LCD_HEIGHT
* display_zoom
,
175 #ifdef HAVE_BACKLIGHT
176 sdl_set_gradient(lcd_surface
, &lcd_bl_color_dark
,
177 &lcd_bl_color_bright
, 0, NUM_SHADES
);
178 #ifdef HAVE_LCD_SPLIT
179 sdl_set_gradient(lcd_surface
, &lcd_bl_color2_dark
,
180 &lcd_bl_color2_bright
, NUM_SHADES
, NUM_SHADES
);
182 #else /* !HAVE_BACKLIGHT */
183 sdl_set_gradient(lcd_surface
, &lcd_color_dark
,
184 &lcd_color_bright
, 0, NUM_SHADES
);
185 #ifdef HAVE_LCD_SPLIT
186 sdl_set_gradient(lcd_surface
, &lcd_color2_dark
,
187 &lcd_color2_bright
, NUM_SHADES
, NUM_SHADES
);
189 #endif /* !HAVE_BACKLIGHT */
190 #endif /* LCD_DEPTH */
194 void sim_lcd_ex_init(unsigned long (*getpixel
)(int, int))
196 lcd_ex_getpixel
= getpixel
;
199 void sim_lcd_ex_update_rect(int x_start
, int y_start
, int width
, int height
)
201 if (lcd_ex_getpixel
) {
202 sdl_update_rect(lcd_surface
, x_start
, y_start
, width
, height
,
203 LCD_WIDTH
, LCD_HEIGHT
, lcd_ex_getpixel
);
204 sdl_gui_update(lcd_surface
, x_start
, y_start
, width
,
205 height
+ LCD_SPLIT_LINES
, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
206 background
? UI_LCD_POSX
: 0,
207 background
? UI_LCD_POSY
: 0);
212 #ifdef HAVE_LCD_COLOR
214 * |R| |1.000000 -0.000001 1.402000| |Y'|
215 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
216 * |B| |1.000000 1.772000 0.000000| |Pr|
217 * Scaled, normalized, rounded and tweaked to yield RGB 565:
218 * |R| |74 0 101| |Y' - 16| >> 9
219 * |G| = |74 -24 -51| |Cb - 128| >> 8
220 * |B| |74 128 0| |Cr - 128| >> 9
228 static inline int clamp(int val
, int min
, int max
)
237 void lcd_yuv_set_options(unsigned options
)
242 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
244 void lcd_blit_yuv(unsigned char * const src
[3],
245 int src_x
, int src_y
, int stride
,
246 int x
, int y
, int width
, int height
)
248 const unsigned char *ysrc
, *usrc
, *vsrc
;
250 fb_data
*dst
, *row_end
;
253 /* width and height must be >= 2 and an even number */
255 linecounter
= height
>> 1;
257 #if LCD_WIDTH >= LCD_HEIGHT
258 dst
= &lcd_framebuffer
[y
][x
];
259 row_end
= dst
+ width
;
261 dst
= &lcd_framebuffer
[x
][LCD_WIDTH
- y
- 1];
262 row_end
= dst
+ LCD_WIDTH
* width
;
266 ysrc
= src
[0] + z
+ src_x
;
267 usrc
= src
[1] + (z
>> 2) + (src_x
>> 1);
268 vsrc
= src
[2] + (usrc
- src
[1]);
270 /* stride => amount to jump from end of last row to start of next */
273 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
279 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
281 y
= YFAC
*(*ysrc
++ - 16);
286 guv
= GUFAC
*cb
+ GVFAC
*cr
;
293 if ((unsigned)(r
| g
| b
) > 64*256-1)
295 r
= clamp(r
, 0, 64*256-1);
296 g
= clamp(g
, 0, 64*256-1);
297 b
= clamp(b
, 0, 64*256-1);
300 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
302 #if LCD_WIDTH >= LCD_HEIGHT
308 y
= YFAC
*(*ysrc
++ - 16);
313 if ((unsigned)(r
| g
| b
) > 64*256-1)
315 r
= clamp(r
, 0, 64*256-1);
316 g
= clamp(g
, 0, 64*256-1);
317 b
= clamp(b
, 0, 64*256-1);
320 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
322 #if LCD_WIDTH >= LCD_HEIGHT
328 while (dst
< row_end
);
334 #if LCD_WIDTH >= LCD_HEIGHT
335 row_end
+= LCD_WIDTH
;
336 dst
+= LCD_WIDTH
- width
;
339 dst
-= LCD_WIDTH
*width
+ 1;
344 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
346 y
= YFAC
*(*ysrc
++ - 16);
351 guv
= GUFAC
*cb
+ GVFAC
*cr
;
358 if ((unsigned)(r
| g
| b
) > 64*256-1)
360 r
= clamp(r
, 0, 64*256-1);
361 g
= clamp(g
, 0, 64*256-1);
362 b
= clamp(b
, 0, 64*256-1);
365 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
367 #if LCD_WIDTH >= LCD_HEIGHT
373 y
= YFAC
*(*ysrc
++ - 16);
378 if ((unsigned)(r
| g
| b
) > 64*256-1)
380 r
= clamp(r
, 0, 64*256-1);
381 g
= clamp(g
, 0, 64*256-1);
382 b
= clamp(b
, 0, 64*256-1);
385 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
387 #if LCD_WIDTH >= LCD_HEIGHT
393 while (dst
< row_end
);
399 #if LCD_WIDTH >= LCD_HEIGHT
400 row_end
+= LCD_WIDTH
;
401 dst
+= LCD_WIDTH
- width
;
404 dst
-= LCD_WIDTH
*width
+ 1;
407 while (--linecounter
> 0);
409 #if LCD_WIDTH >= LCD_HEIGHT
410 lcd_update_rect(x
, y
, width
, height
);
412 lcd_update_rect(LCD_WIDTH
- y
- height
, x
, height
, width
);
415 #endif /* HAVE_LCD_COLOR */