1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2009 by Jens Arnold
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 ****************************************************************************/
23 #include "screendump.h"
32 #ifdef HAVE_REMOTE_LCD
33 #include "lcd-remote.h"
37 #define BMP_COMPRESSION 3 /* BI_BITFIELDS */
38 #define BMP_NUMCOLORS 3
39 #else /* LCD_DEPTH != 16 */
40 #define BMP_COMPRESSION 0 /* BI_RGB */
43 #define BMP_NUMCOLORS (2 << LCD_DEPTH)
45 #define BMP_NUMCOLORS (1 << LCD_DEPTH)
47 #else /* LCD_DEPTH > 8 */
48 #define BMP_NUMCOLORS 0
49 #endif /* LCD_DEPTH > 8 */
50 #endif /* LCD_DEPTH != 16 */
54 #define BMP_LINESIZE ((LCD_WIDTH/2 + 3) & ~3)
57 #define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3)
60 #define BMP_LINESIZE ((LCD_WIDTH*2 + 3) & ~3)
63 #define BMP_LINESIZE ((LCD_WIDTH*3 + 3) & ~3)
66 #define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
67 #define BMP_DATASIZE (BMP_LINESIZE * (LCD_HEIGHT+LCD_SPLIT_LINES))
68 #define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
70 static const unsigned char bmpheader
[] =
72 0x42, 0x4d, /* 'BM' */
73 LE32_CONST(BMP_TOTALSIZE
), /* Total file size */
74 0x00, 0x00, 0x00, 0x00, /* Reserved */
75 LE32_CONST(BMP_HEADERSIZE
), /* Offset to start of pixel data */
77 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
78 LE32_CONST(LCD_WIDTH
), /* Width in pixels */
79 LE32_CONST(LCD_HEIGHT
+LCD_SPLIT_LINES
), /* Height in pixels */
80 0x01, 0x00, /* Number of planes (always 1) */
81 LE16_CONST(BMP_BPP
), /* Bits per pixel 1/4/8/16/24 */
82 LE32_CONST(BMP_COMPRESSION
),/* Compression mode */
83 LE32_CONST(BMP_DATASIZE
), /* Size of bitmap data */
84 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
85 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
86 LE32_CONST(BMP_NUMCOLORS
), /* Number of used colours */
87 LE32_CONST(BMP_NUMCOLORS
), /* Number of important colours */
90 #ifdef HAVE_NEGATIVE_LCD
91 BMP_COLOR(LCD_BL_DARKCOLOR
),
92 BMP_COLOR(LCD_BL_BRIGHTCOLOR
),
94 BMP_COLOR(LCD_BL_DARKCOLOR_2
),
95 BMP_COLOR(LCD_BL_BRIGHTCOLOR_2
),
97 #else /* positive display */
98 BMP_COLOR(LCD_BL_BRIGHTCOLOR
),
99 BMP_COLOR(LCD_BL_DARKCOLOR
),
100 #endif /* positive display */
102 BMP_COLOR(LCD_BL_BRIGHTCOLOR
),
103 BMP_COLOR_MIX(LCD_BL_BRIGHTCOLOR
, LCD_BL_DARKCOLOR
, 1, 3),
104 BMP_COLOR_MIX(LCD_BL_BRIGHTCOLOR
, LCD_BL_DARKCOLOR
, 2, 3),
105 BMP_COLOR(LCD_BL_DARKCOLOR
),
106 #elif LCD_DEPTH == 16
107 0x00, 0xf8, 0x00, 0x00, /* red bitfield mask */
108 0xe0, 0x07, 0x00, 0x00, /* green bitfield mask */
109 0x1f, 0x00, 0x00, 0x00, /* blue bitfield mask */
113 static void (*screen_dump_hook
)(int fh
) = NULL
;
115 void screen_dump(void)
118 char filename
[MAX_PATH
];
124 #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT != HORIZONTAL_PACKING)
129 unsigned char *dst
, *dst_end
;
130 unsigned char linebuf
[BMP_LINESIZE
];
131 #elif LCD_DEPTH <= 16
132 unsigned short *dst
, *dst_end
;
133 unsigned short linebuf
[BMP_LINESIZE
/2];
137 create_datetime_filename(filename
, "", "dump ", ".bmp", false);
139 create_numbered_filename(filename
, "", "dump_", ".bmp", 4
140 IF_CNFN_NUM_(, NULL
));
143 fd
= creat(filename
, 0666);
147 if (screen_dump_hook
)
149 screen_dump_hook(fd
);
153 write(fd
, bmpheader
, sizeof(bmpheader
));
155 /* BMP image goes bottom up */
156 for (y
= LCD_HEIGHT
- 1; y
>= 0; y
--)
158 memset(linebuf
, 0, BMP_LINESIZE
);
160 #if defined(HAVE_LCD_SPLIT) && (LCD_SPLIT_LINES == 2)
161 if (y
== LCD_SPLIT_POS
- 1)
163 write(fd
, linebuf
, BMP_LINESIZE
);
164 write(fd
, linebuf
, BMP_LINESIZE
);
170 dst_end
= dst
+ LCD_WIDTH
/2;
171 src
= lcd_framebuffer
[y
>> 3];
176 val
= (*src
++ & mask
) ? 0x10 : 0;
177 val
|= (*src
++ & mask
) ? 0x01 : 0;
178 #ifdef HAVE_LCD_SPLIT
179 if (y
< LCD_SPLIT_POS
)
184 while (dst
< dst_end
);
187 dst_end
= dst
+ LCD_WIDTH
/2;
189 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
190 src
= lcd_framebuffer
[y
];
194 unsigned data
= *src
++;
196 *dst
++ = ((data
>> 2) & 0x30) | ((data
>> 4) & 0x03);
197 *dst
++ = ((data
<< 2) & 0x30) | (data
& 0x03);
199 while (dst
< dst_end
);
201 #elif LCD_PIXELFORMAT == VERTICAL_PACKING
202 src
= lcd_framebuffer
[y
>> 2];
207 val
= ((*src
++ >> shift
) & 3) << 4;
208 val
|= ((*src
++ >> shift
) & 3);
211 while (dst
< dst_end
);
213 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
214 src
= lcd_framebuffer
[y
>> 3];
219 unsigned data
= (*src
++ >> shift
) & 0x0101;
221 val
= (((data
>> 7) | data
) & 3) << 4;
222 data
= (*src
++ >> shift
) & 0x0101;
223 val
|= ((data
>> 7) | data
) & 3;
226 while (dst
< dst_end
);
229 #elif LCD_DEPTH == 16
230 dst_end
= dst
+ LCD_WIDTH
;
231 src
= lcd_framebuffer
[y
];
235 #if (LCD_PIXELFORMAT == RGB565SWAPPED)
236 /* iPod LCD data is big endian although the CPU is not */
237 *dst
++ = htobe16(*src
++);
239 *dst
++ = htole16(*src
++);
242 while (dst
< dst_end
);
244 #endif /* LCD_DEPTH */
245 write(fd
, linebuf
, BMP_LINESIZE
);
251 void screen_dump_set_hook(void (*hook
)(int fh
))
253 screen_dump_hook
= hook
;
256 #ifdef HAVE_REMOTE_LCD
258 #define RBMP_COMPRESSION 0 /* BI_RGB */
259 #define RBMP_NUMCOLORS (1 << LCD_REMOTE_DEPTH)
261 #define RBMP_LINESIZE ((LCD_REMOTE_WIDTH/2 + 3) & ~3)
263 #define RBMP_HEADERSIZE (54 + 4 * RBMP_NUMCOLORS)
264 #define RBMP_DATASIZE (RBMP_LINESIZE * LCD_REMOTE_HEIGHT)
265 #define RBMP_TOTALSIZE (RBMP_HEADERSIZE + RBMP_DATASIZE)
267 static const unsigned char rbmpheader
[] =
269 0x42, 0x4d, /* 'BM' */
270 LE32_CONST(RBMP_TOTALSIZE
), /* Total file size */
271 0x00, 0x00, 0x00, 0x00, /* Reserved */
272 LE32_CONST(RBMP_HEADERSIZE
), /* Offset to start of pixel data */
274 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
275 LE32_CONST(LCD_REMOTE_WIDTH
), /* Width in pixels */
276 LE32_CONST(LCD_REMOTE_HEIGHT
), /* Height in pixels */
277 0x01, 0x00, /* Number of planes (always 1) */
278 LE16_CONST(RBMP_BPP
), /* Bits per pixel 1/4/8/16/24 */
279 LE32_CONST(RBMP_COMPRESSION
), /* Compression mode */
280 LE32_CONST(RBMP_DATASIZE
), /* Size of bitmap data */
281 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
282 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
283 LE32_CONST(RBMP_NUMCOLORS
), /* Number of used colours */
284 LE32_CONST(RBMP_NUMCOLORS
), /* Number of important colours */
286 #if LCD_REMOTE_DEPTH == 1
287 BMP_COLOR(LCD_REMOTE_BL_BRIGHTCOLOR
),
288 BMP_COLOR(LCD_REMOTE_BL_DARKCOLOR
),
289 #elif LCD_REMOTE_DEPTH == 2
290 BMP_COLOR(LCD_REMOTE_BL_BRIGHTCOLOR
),
291 BMP_COLOR_MIX(LCD_REMOTE_BL_BRIGHTCOLOR
, LCD_REMOTE_BL_DARKCOLOR
, 1, 3),
292 BMP_COLOR_MIX(LCD_REMOTE_BL_BRIGHTCOLOR
, LCD_REMOTE_BL_DARKCOLOR
, 2, 3),
293 BMP_COLOR(LCD_REMOTE_BL_DARKCOLOR
),
297 void remote_screen_dump(void)
300 char filename
[MAX_PATH
];
303 #if LCD_REMOTE_DEPTH == 1
306 #elif LCD_REMOTE_DEPTH == 2
310 unsigned char *dst
, *dst_end
;
311 unsigned char linebuf
[RBMP_LINESIZE
];
314 create_datetime_filename(filename
, "", "rdump ", ".bmp", false);
316 create_numbered_filename(filename
, "", "rdump_", ".bmp", 4
317 IF_CNFN_NUM_(, NULL
));
320 fd
= creat(filename
, 0666);
324 write(fd
, rbmpheader
, sizeof(rbmpheader
));
326 /* BMP image goes bottom up */
327 for (y
= LCD_REMOTE_HEIGHT
- 1; y
>= 0; y
--)
329 memset(linebuf
, 0, RBMP_LINESIZE
);
333 #if LCD_REMOTE_DEPTH == 1
334 dst_end
= dst
+ LCD_REMOTE_WIDTH
/2;
335 src
= lcd_remote_framebuffer
[y
>> 3];
340 val
= (*src
++ & mask
) ? 0x10 : 0;
341 val
|= (*src
++ & mask
) ? 0x01 : 0;
344 while (dst
< dst_end
);
346 #elif LCD_REMOTE_DEPTH == 2
347 dst_end
= dst
+ LCD_REMOTE_WIDTH
/2;
349 #if LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED
350 src
= lcd_remote_framebuffer
[y
>> 3];
355 unsigned data
= (*src
++ >> shift
) & 0x0101;
357 val
= (((data
>> 7) | data
) & 3) << 4;
358 data
= (*src
++ >> shift
) & 0x0101;
359 val
|= ((data
>> 7) | data
) & 3;
362 while (dst
< dst_end
);
365 #endif /* LCD_REMOTE_DEPTH */
366 write(fd
, linebuf
, RBMP_LINESIZE
);
371 #endif /* HAVE_REMOTE_LCD */