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 */
52 #define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
53 #define BMP_DATASIZE (DUMP_BMP_LINESIZE * (LCD_HEIGHT+LCD_SPLIT_LINES))
54 #define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
56 static const unsigned char bmpheader
[] =
58 0x42, 0x4d, /* 'BM' */
59 LE32_CONST(BMP_TOTALSIZE
), /* Total file size */
60 0x00, 0x00, 0x00, 0x00, /* Reserved */
61 LE32_CONST(BMP_HEADERSIZE
), /* Offset to start of pixel data */
63 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
64 LE32_CONST(LCD_WIDTH
), /* Width in pixels */
65 LE32_CONST(LCD_HEIGHT
+LCD_SPLIT_LINES
), /* Height in pixels */
66 0x01, 0x00, /* Number of planes (always 1) */
67 LE16_CONST(DUMP_BMP_BPP
), /* Bits per pixel 1/4/8/16/24 */
68 LE32_CONST(BMP_COMPRESSION
),/* Compression mode */
69 LE32_CONST(BMP_DATASIZE
), /* Size of bitmap data */
70 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
71 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
72 LE32_CONST(BMP_NUMCOLORS
), /* Number of used colours */
73 LE32_CONST(BMP_NUMCOLORS
), /* Number of important colours */
76 #ifdef HAVE_NEGATIVE_LCD
77 BMP_COLOR(LCD_BL_DARKCOLOR
),
78 BMP_COLOR(LCD_BL_BRIGHTCOLOR
),
80 BMP_COLOR(LCD_BL_DARKCOLOR_2
),
81 BMP_COLOR(LCD_BL_BRIGHTCOLOR_2
),
83 #else /* positive display */
84 BMP_COLOR(LCD_BL_BRIGHTCOLOR
),
85 BMP_COLOR(LCD_BL_DARKCOLOR
),
86 #endif /* positive display */
88 BMP_COLOR(LCD_BL_BRIGHTCOLOR
),
89 BMP_COLOR_MIX(LCD_BL_BRIGHTCOLOR
, LCD_BL_DARKCOLOR
, 1, 3),
90 BMP_COLOR_MIX(LCD_BL_BRIGHTCOLOR
, LCD_BL_DARKCOLOR
, 2, 3),
91 BMP_COLOR(LCD_BL_DARKCOLOR
),
93 0x00, 0xf8, 0x00, 0x00, /* red bitfield mask */
94 0xe0, 0x07, 0x00, 0x00, /* green bitfield mask */
95 0x1f, 0x00, 0x00, 0x00, /* blue bitfield mask */
99 static void (*screen_dump_hook
)(int fh
) = NULL
;
101 void screen_dump(void)
110 #elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT != HORIZONTAL_PACKING)
115 unsigned char *dst
, *dst_end
;
116 unsigned char linebuf
[DUMP_BMP_LINESIZE
];
117 #elif LCD_DEPTH <= 16
118 unsigned short *dst
, *dst_end
;
119 unsigned short linebuf
[DUMP_BMP_LINESIZE
/2];
123 create_datetime_filename(filename
, "", "dump ", ".bmp", false);
125 create_numbered_filename(filename
, "", "dump_", ".bmp", 4
126 IF_CNFN_NUM_(, NULL
));
129 fd
= creat(filename
, 0666);
133 if (screen_dump_hook
)
135 screen_dump_hook(fd
);
139 write(fd
, bmpheader
, sizeof(bmpheader
));
141 /* BMP image goes bottom up */
142 for (y
= LCD_HEIGHT
- 1; y
>= 0; y
--)
144 memset(linebuf
, 0, DUMP_BMP_LINESIZE
);
146 #if defined(HAVE_LCD_SPLIT) && (LCD_SPLIT_LINES == 2)
147 if (y
== LCD_SPLIT_POS
- 1)
149 write(fd
, linebuf
, DUMP_BMP_LINESIZE
);
150 write(fd
, linebuf
, DUMP_BMP_LINESIZE
);
156 dst_end
= dst
+ LCD_WIDTH
/2;
157 src
= lcd_framebuffer
[y
>> 3];
162 val
= (*src
++ & mask
) ? 0x10 : 0;
163 val
|= (*src
++ & mask
) ? 0x01 : 0;
164 #ifdef HAVE_LCD_SPLIT
165 if (y
< LCD_SPLIT_POS
)
170 while (dst
< dst_end
);
173 dst_end
= dst
+ LCD_WIDTH
/2;
175 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
176 src
= lcd_framebuffer
[y
];
180 unsigned data
= *src
++;
182 *dst
++ = ((data
>> 2) & 0x30) | ((data
>> 4) & 0x03);
183 *dst
++ = ((data
<< 2) & 0x30) | (data
& 0x03);
185 while (dst
< dst_end
);
187 #elif LCD_PIXELFORMAT == VERTICAL_PACKING
188 src
= lcd_framebuffer
[y
>> 2];
193 val
= ((*src
++ >> shift
) & 3) << 4;
194 val
|= ((*src
++ >> shift
) & 3);
197 while (dst
< dst_end
);
199 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
200 src
= lcd_framebuffer
[y
>> 3];
205 unsigned data
= (*src
++ >> shift
) & 0x0101;
207 val
= (((data
>> 7) | data
) & 3) << 4;
208 data
= (*src
++ >> shift
) & 0x0101;
209 val
|= ((data
>> 7) | data
) & 3;
212 while (dst
< dst_end
);
215 #elif LCD_DEPTH == 16
216 dst_end
= dst
+ LCD_WIDTH
;
217 src
= lcd_framebuffer
[y
];
221 #if (LCD_PIXELFORMAT == RGB565SWAPPED)
222 /* iPod LCD data is big endian although the CPU is not */
223 *dst
++ = htobe16(*src
++);
225 *dst
++ = htole16(*src
++);
228 while (dst
< dst_end
);
230 #endif /* LCD_DEPTH */
231 write(fd
, linebuf
, DUMP_BMP_LINESIZE
);
237 void screen_dump_set_hook(void (*hook
)(int fh
))
239 screen_dump_hook
= hook
;
242 #ifdef HAVE_REMOTE_LCD
244 #define RBMP_COMPRESSION 0 /* BI_RGB */
245 #define RBMP_NUMCOLORS (1 << LCD_REMOTE_DEPTH)
247 #define RBMP_LINESIZE ((LCD_REMOTE_WIDTH/2 + 3) & ~3)
249 #define RBMP_HEADERSIZE (54 + 4 * RBMP_NUMCOLORS)
250 #define RBMP_DATASIZE (RBMP_LINESIZE * LCD_REMOTE_HEIGHT)
251 #define RBMP_TOTALSIZE (RBMP_HEADERSIZE + RBMP_DATASIZE)
253 static const unsigned char rbmpheader
[] =
255 0x42, 0x4d, /* 'BM' */
256 LE32_CONST(RBMP_TOTALSIZE
), /* Total file size */
257 0x00, 0x00, 0x00, 0x00, /* Reserved */
258 LE32_CONST(RBMP_HEADERSIZE
), /* Offset to start of pixel data */
260 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
261 LE32_CONST(LCD_REMOTE_WIDTH
), /* Width in pixels */
262 LE32_CONST(LCD_REMOTE_HEIGHT
), /* Height in pixels */
263 0x01, 0x00, /* Number of planes (always 1) */
264 LE16_CONST(RBMP_BPP
), /* Bits per pixel 1/4/8/16/24 */
265 LE32_CONST(RBMP_COMPRESSION
), /* Compression mode */
266 LE32_CONST(RBMP_DATASIZE
), /* Size of bitmap data */
267 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
268 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
269 LE32_CONST(RBMP_NUMCOLORS
), /* Number of used colours */
270 LE32_CONST(RBMP_NUMCOLORS
), /* Number of important colours */
272 #if LCD_REMOTE_DEPTH == 1
273 BMP_COLOR(LCD_REMOTE_BL_BRIGHTCOLOR
),
274 BMP_COLOR(LCD_REMOTE_BL_DARKCOLOR
),
275 #elif LCD_REMOTE_DEPTH == 2
276 BMP_COLOR(LCD_REMOTE_BL_BRIGHTCOLOR
),
277 BMP_COLOR_MIX(LCD_REMOTE_BL_BRIGHTCOLOR
, LCD_REMOTE_BL_DARKCOLOR
, 1, 3),
278 BMP_COLOR_MIX(LCD_REMOTE_BL_BRIGHTCOLOR
, LCD_REMOTE_BL_DARKCOLOR
, 2, 3),
279 BMP_COLOR(LCD_REMOTE_BL_DARKCOLOR
),
283 void remote_screen_dump(void)
286 char filename
[MAX_PATH
];
289 #if LCD_REMOTE_DEPTH == 1
292 #elif LCD_REMOTE_DEPTH == 2
296 unsigned char *dst
, *dst_end
;
297 unsigned char linebuf
[RBMP_LINESIZE
];
300 create_datetime_filename(filename
, "", "rdump ", ".bmp", false);
302 create_numbered_filename(filename
, "", "rdump_", ".bmp", 4
303 IF_CNFN_NUM_(, NULL
));
306 fd
= creat(filename
, 0666);
310 write(fd
, rbmpheader
, sizeof(rbmpheader
));
312 /* BMP image goes bottom up */
313 for (y
= LCD_REMOTE_HEIGHT
- 1; y
>= 0; y
--)
315 memset(linebuf
, 0, RBMP_LINESIZE
);
319 #if LCD_REMOTE_DEPTH == 1
320 dst_end
= dst
+ LCD_REMOTE_WIDTH
/2;
321 src
= lcd_remote_framebuffer
[y
>> 3];
326 val
= (*src
++ & mask
) ? 0x10 : 0;
327 val
|= (*src
++ & mask
) ? 0x01 : 0;
330 while (dst
< dst_end
);
332 #elif LCD_REMOTE_DEPTH == 2
333 dst_end
= dst
+ LCD_REMOTE_WIDTH
/2;
335 #if LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED
336 src
= lcd_remote_framebuffer
[y
>> 3];
341 unsigned data
= (*src
++ >> shift
) & 0x0101;
343 val
= (((data
>> 7) | data
) & 3) << 4;
344 data
= (*src
++ >> shift
) & 0x0101;
345 val
|= ((data
>> 7) | data
) & 3;
348 while (dst
< dst_end
);
351 #endif /* LCD_REMOTE_DEPTH */
352 write(fd
, linebuf
, RBMP_LINESIZE
);
357 #endif /* HAVE_REMOTE_LCD */