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 ****************************************************************************/
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 return lcd_framebuffer
[y
][x
];
113 void lcd_update(void)
115 /* update a full screen rect */
116 lcd_update_rect(0, 0, LCD_WIDTH
, LCD_HEIGHT
);
119 void lcd_update_rect(int x_start
, int y_start
, int width
, int height
)
121 sdl_update_rect(lcd_surface
, x_start
, y_start
, width
, height
,
122 LCD_WIDTH
, LCD_HEIGHT
, get_lcd_pixel
);
123 sdl_gui_update(lcd_surface
, x_start
, y_start
, width
,
124 height
+ LCD_SPLIT_LINES
, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
125 background
? UI_LCD_POSX
: 0, background
? UI_LCD_POSY
: 0);
128 #ifdef HAVE_BACKLIGHT
129 void sim_backlight(int value
)
133 sdl_set_gradient(lcd_surface
, &lcd_bl_color_dark
,
134 &lcd_bl_color_bright
, 0, NUM_SHADES
);
135 #ifdef HAVE_LCD_SPLIT
136 sdl_set_gradient(lcd_surface
, &lcd_bl_color2_dark
,
137 &lcd_bl_color2_bright
, NUM_SHADES
, NUM_SHADES
);
140 sdl_set_gradient(lcd_surface
, &lcd_color_dark
,
141 &lcd_color_bright
, 0, NUM_SHADES
);
142 #ifdef HAVE_LCD_SPLIT
143 sdl_set_gradient(lcd_surface
, &lcd_color2_dark
,
144 &lcd_color2_bright
, NUM_SHADES
, NUM_SHADES
);
147 #else /* LCD_DEPTH > 8 */
149 SDL_SetAlpha(lcd_surface
, 0, SDL_ALPHA_OPAQUE
); /* full on */
151 SDL_SetAlpha(lcd_surface
, SDL_SRCALPHA
, BACKLIGHT_OFF_ALPHA
);
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
,
177 #ifdef HAVE_BACKLIGHT
178 sdl_set_gradient(lcd_surface
, &lcd_bl_color_dark
,
179 &lcd_bl_color_bright
, 0, NUM_SHADES
);
180 #ifdef HAVE_LCD_SPLIT
181 sdl_set_gradient(lcd_surface
, &lcd_bl_color2_dark
,
182 &lcd_bl_color2_bright
, NUM_SHADES
, NUM_SHADES
);
184 #else /* !HAVE_BACKLIGHT */
185 sdl_set_gradient(lcd_surface
, &lcd_color_dark
,
186 &lcd_color_bright
, 0, NUM_SHADES
);
187 #ifdef HAVE_LCD_SPLIT
188 sdl_set_gradient(lcd_surface
, &lcd_color2_dark
,
189 &lcd_color2_bright
, NUM_SHADES
, NUM_SHADES
);
191 #endif /* !HAVE_BACKLIGHT */
192 #endif /* LCD_DEPTH < 8 */
196 void sim_lcd_ex_init(unsigned long (*getpixel
)(int, int))
198 lcd_ex_getpixel
= getpixel
;
201 void sim_lcd_ex_update_rect(int x_start
, int y_start
, int width
, int height
)
203 if (lcd_ex_getpixel
) {
204 sdl_update_rect(lcd_surface
, x_start
, y_start
, width
, height
,
205 LCD_WIDTH
, LCD_HEIGHT
, lcd_ex_getpixel
);
206 sdl_gui_update(lcd_surface
, x_start
, y_start
, width
,
207 height
+ LCD_SPLIT_LINES
, SIM_LCD_WIDTH
, SIM_LCD_HEIGHT
,
208 background
? UI_LCD_POSX
: 0,
209 background
? UI_LCD_POSY
: 0);
214 #ifdef HAVE_LCD_COLOR
216 * |R| |1.000000 -0.000001 1.402000| |Y'|
217 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
218 * |B| |1.000000 1.772000 0.000000| |Pr|
219 * Scaled, normalized, rounded and tweaked to yield RGB 565:
220 * |R| |74 0 101| |Y' - 16| >> 9
221 * |G| = |74 -24 -51| |Cb - 128| >> 8
222 * |B| |74 128 0| |Cr - 128| >> 9
230 static inline int clamp(int val
, int min
, int max
)
239 void lcd_yuv_set_options(unsigned options
)
244 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
246 void lcd_blit_yuv(unsigned char * const src
[3],
247 int src_x
, int src_y
, int stride
,
248 int x
, int y
, int width
, int height
)
250 const unsigned char *ysrc
, *usrc
, *vsrc
;
252 fb_data
*dst
, *row_end
;
255 /* width and height must be >= 2 and an even number */
257 linecounter
= height
>> 1;
259 #if LCD_WIDTH >= LCD_HEIGHT
260 dst
= &lcd_framebuffer
[y
][x
];
261 row_end
= dst
+ width
;
263 dst
= &lcd_framebuffer
[x
][LCD_WIDTH
- y
- 1];
264 row_end
= dst
+ LCD_WIDTH
* width
;
268 ysrc
= src
[0] + z
+ src_x
;
269 usrc
= src
[1] + (z
>> 2) + (src_x
>> 1);
270 vsrc
= src
[2] + (usrc
- src
[1]);
272 /* stride => amount to jump from end of last row to start of next */
275 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
281 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
283 y
= YFAC
*(*ysrc
++ - 16);
288 guv
= GUFAC
*cb
+ GVFAC
*cr
;
295 if ((unsigned)(r
| g
| b
) > 64*256-1)
297 r
= clamp(r
, 0, 64*256-1);
298 g
= clamp(g
, 0, 64*256-1);
299 b
= clamp(b
, 0, 64*256-1);
302 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
304 #if LCD_WIDTH >= LCD_HEIGHT
310 y
= YFAC
*(*ysrc
++ - 16);
315 if ((unsigned)(r
| g
| b
) > 64*256-1)
317 r
= clamp(r
, 0, 64*256-1);
318 g
= clamp(g
, 0, 64*256-1);
319 b
= clamp(b
, 0, 64*256-1);
322 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
324 #if LCD_WIDTH >= LCD_HEIGHT
330 while (dst
< row_end
);
336 #if LCD_WIDTH >= LCD_HEIGHT
337 row_end
+= LCD_WIDTH
;
338 dst
+= LCD_WIDTH
- width
;
341 dst
-= LCD_WIDTH
*width
+ 1;
346 int y
, cb
, cr
, rv
, guv
, bu
, r
, g
, b
;
348 y
= YFAC
*(*ysrc
++ - 16);
353 guv
= GUFAC
*cb
+ GVFAC
*cr
;
360 if ((unsigned)(r
| g
| b
) > 64*256-1)
362 r
= clamp(r
, 0, 64*256-1);
363 g
= clamp(g
, 0, 64*256-1);
364 b
= clamp(b
, 0, 64*256-1);
367 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
369 #if LCD_WIDTH >= LCD_HEIGHT
375 y
= YFAC
*(*ysrc
++ - 16);
380 if ((unsigned)(r
| g
| b
) > 64*256-1)
382 r
= clamp(r
, 0, 64*256-1);
383 g
= clamp(g
, 0, 64*256-1);
384 b
= clamp(b
, 0, 64*256-1);
387 *dst
= LCD_RGBPACK_LCD(r
>> 9, g
>> 8, b
>> 9);
389 #if LCD_WIDTH >= LCD_HEIGHT
395 while (dst
< row_end
);
401 #if LCD_WIDTH >= LCD_HEIGHT
402 row_end
+= LCD_WIDTH
;
403 dst
+= LCD_WIDTH
- width
;
406 dst
-= LCD_WIDTH
*width
+ 1;
409 while (--linecounter
> 0);
411 #if LCD_WIDTH >= LCD_HEIGHT
412 lcd_update_rect(x
, y
, width
, height
);
414 lcd_update_rect(LCD_WIDTH
- y
- height
, x
, height
, width
);
417 #endif /* HAVE_LCD_COLOR */