Add "elfzip" target to make which creates a zip of all elf files, as mapzip does...
[maemo-rb.git] / apps / plugins / lib / grey_core.c
blobc2e0747718c20bf8bd181fa649ef1ae1f5f783ee
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * New greyscale framework
11 * Core & miscellaneous functions
13 * This is a generic framework to display 129 shades of grey on low-depth
14 * bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins.
16 * Copyright (C) 2008 Jens Arnold
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
26 ****************************************************************************/
28 #include "plugin.h"
29 #include "grey.h"
31 #if defined(HAVE_ADJUSTABLE_CPU_FREQ) && \
32 (defined(CPU_PP) || (CONFIG_LCD == LCD_TL0350A))
33 #define NEED_BOOST
34 #endif
36 #ifndef SIMULATOR
38 #if defined ARCHOS_RECORDER /* verified */ \
39 || defined ARCHOS_FMRECORDER /* should be identical */ \
40 || defined ARCHOS_RECORDERV2 /* should be identical */ \
41 || defined ARCHOS_ONDIOFM /* verified */ \
42 || defined ARCHOS_ONDIOSP /* verified */
43 /* Average measurements of a Recorder v1, an Ondio FM, a backlight-modded
44 * Ondio FM, and an Ondio SP. */
45 static const unsigned char lcdlinear[256] = {
46 5, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 29, 31, 33, 35,
47 37, 39, 40, 42, 43, 45, 46, 48, 49, 50, 51, 53, 54, 55, 57, 58,
48 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 68, 69, 70, 71, 71, 72,
49 73, 74, 74, 75, 76, 77, 77, 78, 79, 79, 80, 80, 81, 81, 82, 82,
50 83, 84, 84, 85, 86, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91,
51 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 98, 98, 99, 100, 100,
52 101, 101, 102, 103, 103, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109,
53 110, 110, 111, 112, 112, 113, 114, 114, 115, 115, 116, 117, 117, 118, 119, 119,
54 120, 120, 121, 122, 123, 123, 124, 125, 126, 126, 127, 128, 129, 129, 130, 131,
55 132, 132, 133, 134, 135, 135, 136, 137, 138, 138, 139, 140, 140, 141, 141, 142,
56 143, 144, 145, 146, 147, 147, 148, 149, 150, 151, 152, 153, 154, 154, 155, 156,
57 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 166, 167, 168, 168, 169, 170,
58 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 184, 185, 186, 187,
59 188, 189, 191, 192, 194, 195, 197, 198, 199, 200, 202, 203, 204, 205, 207, 208,
60 209, 210, 212, 213, 215, 216, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228,
61 229, 230, 232, 233, 234, 235, 237, 238, 239, 240, 242, 243, 244, 246, 247, 248
63 /* The actual LCD scanrate varies a lot with temperature on these targets */
64 #define LCD_SCANRATE 67 /* Hz */
66 #elif defined IAUDIO_M3 /* verified */
67 /* Average measurements of 2 iAudio remotes connected to an M3. */
68 static const unsigned char lcdlinear[256] = {
69 5, 9, 13, 17, 21, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66,
70 70, 73, 76, 78, 80, 82, 84, 86, 88, 90, 91, 92, 94, 95, 96, 97,
71 98, 99, 99, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108,
72 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116,
73 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 121, 122, 122, 123, 123, 123,
74 124, 124, 124, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 129, 129, 129,
75 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 134, 135, 135, 136, 136, 136,
76 137, 137, 137, 138, 138, 139, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143,
77 144, 144, 145, 145, 146, 147, 147, 148, 149, 149, 150, 150, 151, 151, 152, 152,
78 153, 153, 154, 154, 155, 155, 156, 156, 157, 157, 158, 158, 159, 160, 160, 161,
79 162, 162, 163, 164, 164, 165, 166, 167, 168, 168, 169, 169, 170, 171, 171, 172,
80 173, 173, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 182, 182, 183, 184,
81 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 198, 199, 200, 201,
82 202, 203, 204, 205, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219,
83 220, 221, 222, 223, 225, 226, 227, 228, 229, 230, 231, 232, 234, 235, 236, 237,
84 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 249, 250, 251, 252
86 /* The actual LCD scanrate is 3x as high, but 150 Hz or 75 Hz cause a too high
87 * CPU load (> 50 %). Even at 50Hz, greyscale display is rather smooth. Average
88 * from 2 iAudio remotes. */
89 #define LCD_SCANRATE 50 /* Hz */
91 #elif defined IAUDIO_M5 /* verified */
92 /* Measurement of one iAudio M5L */
93 static const unsigned char lcdlinear[256] = {
94 4, 6, 8, 10, 11, 13, 15, 17, 19, 21, 22, 24, 25, 27, 28, 30,
95 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 45, 46, 48, 49, 50, 51,
96 52, 52, 53, 54, 55, 55, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63,
97 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 72, 72,
98 73, 73, 74, 75, 75, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81,
99 82, 82, 83, 84, 84, 85, 86, 86, 87, 87, 88, 89, 89, 90, 91, 91,
100 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 98, 98, 99, 100, 100,
101 101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108,
102 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116,
103 117, 117, 118, 119, 119, 120, 121, 121, 122, 122, 123, 124, 124, 125, 126, 126,
104 127, 127, 128, 129, 130, 130, 131, 132, 133, 133, 134, 135, 135, 136, 137, 137,
105 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 149, 150, 151,
106 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 163, 164, 165, 167, 168, 169,
107 170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198,
108 200, 202, 204, 205, 207, 209, 210, 212, 214, 216, 218, 219, 221, 223, 224, 226,
109 228, 230, 231, 233, 235, 236, 237, 239, 241, 243, 244, 246, 248, 249, 250, 252
111 #define LCD_SCANRATE 73 /* Hz */
113 #elif defined IPOD_1G2G /* verified */
114 /* Average measurements of an iPod 1st Gen (0x00010001) and an iPod 2nd Gen
115 * (0x00020000), measured with both backlight off & backlight on (flipped
116 * curves) and medium load (white background when measuring with backlight on),
117 * as the curve is load dependent (the controller's step-up converter doesn't
118 * provide enough juice). Table is for backlight_off state. */
119 static const unsigned char lcdlinear[256] = {
120 4, 6, 8, 9, 11, 13, 14, 16, 17, 18, 20, 21, 23, 24, 26, 27,
121 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 41, 42, 43, 44,
122 45, 45, 46, 47, 47, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53,
123 54, 54, 54, 55, 55, 56, 56, 56, 57, 57, 57, 58, 58, 59, 59, 59,
124 60, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 65, 65, 65,
125 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73,
126 74, 74, 74, 75, 75, 76, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80,
127 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88,
128 89, 89, 90, 91, 92, 92, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99,
129 100, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108, 109, 109,
130 110, 110, 111, 112, 113, 113, 114, 115, 116, 116, 117, 118, 119, 119, 120, 121,
131 122, 122, 123, 124, 125, 125, 126, 127, 128, 129, 130, 131, 131, 132, 133, 134,
132 135, 137, 138, 139, 141, 142, 144, 145, 146, 147, 149, 150, 151, 152, 154, 155,
133 156, 158, 159, 161, 162, 164, 165, 167, 169, 171, 172, 174, 175, 177, 178, 180,
134 182, 184, 186, 188, 189, 191, 193, 195, 197, 199, 201, 203, 206, 208, 210, 212,
135 214, 217, 219, 221, 224, 226, 229, 231, 233, 236, 238, 240, 243, 245, 247, 250
137 /* Average from an iPod 1st Gen and an iPod 2nd Gen */
138 #define LCD_SCANRATE 96 /* Hz */
140 #elif defined IPOD_MINI2G /* verified */ \
141 || defined IPOD_MINI /* should be identical */ \
142 || defined IPOD_3G /* TODO: verify */ \
143 || defined IPOD_4G /* TODO: verify */
144 /* Measurement of one iPod Mini G2 */
145 static const unsigned char lcdlinear[256] = {
146 2, 5, 7, 10, 12, 15, 17, 20, 22, 24, 26, 28, 30, 32, 34, 36,
147 38, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 52, 53,
148 54, 54, 55, 55, 56, 56, 57, 57, 58, 58, 58, 59, 59, 60, 60, 60,
149 61, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 64, 65, 65, 65, 65,
150 66, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69,
151 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 73, 73, 74, 74, 74,
152 75, 75, 75, 75, 76, 76, 76, 76, 77, 77, 77, 78, 78, 79, 79, 79,
153 80, 80, 80, 81, 81, 82, 82, 82, 83, 83, 83, 84, 84, 85, 85, 85,
154 86, 86, 86, 87, 87, 88, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92,
155 93, 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 99, 99, 100, 101, 101,
156 102, 102, 103, 104, 104, 105, 106, 106, 107, 108, 109, 110, 110, 111, 112, 113,
157 114, 115, 115, 116, 117, 118, 118, 119, 120, 121, 121, 122, 123, 124, 124, 125,
158 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
159 141, 142, 143, 144, 146, 147, 148, 149, 150, 151, 153, 154, 155, 156, 158, 159,
160 160, 162, 163, 165, 166, 168, 169, 171, 172, 175, 177, 180, 182, 185, 187, 190,
161 192, 196, 199, 203, 206, 210, 213, 217, 220, 223, 227, 230, 234, 238, 242, 246
163 /* Average of an iPod Mini G2 and 2 3rd Gen iPods. */
164 #define LCD_SCANRATE 87 /* Hz */
166 #elif defined IRIVER_H100_SERIES /* verified */
167 /* Measurement of one Iriver H140 */
168 static const unsigned char lcdlinear[256] = {
169 5, 8, 12, 15, 18, 22, 25, 28, 31, 34, 36, 39, 42, 44, 47, 50,
170 53, 55, 57, 59, 62, 64, 66, 68, 70, 71, 72, 73, 75, 76, 77, 78,
171 79, 80, 80, 81, 82, 83, 83, 84, 85, 85, 86, 86, 87, 87, 88, 88,
172 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95,
173 96, 96, 96, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 101, 101, 101,
174 102, 102, 102, 103, 103, 104, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108,
175 109, 109, 109, 110, 110, 111, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115,
176 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123,
177 124, 124, 125, 125, 126, 127, 127, 128, 129, 129, 130, 130, 131, 131, 132, 132,
178 133, 133, 134, 135, 135, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141,
179 142, 142, 143, 143, 144, 145, 145, 146, 147, 147, 148, 148, 149, 150, 150, 151,
180 152, 152, 153, 153, 154, 155, 155, 156, 157, 157, 158, 159, 160, 160, 161, 162,
181 163, 164, 165, 166, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
182 178, 179, 181, 182, 183, 184, 186, 187, 188, 189, 191, 192, 193, 194, 196, 197,
183 198, 200, 202, 203, 205, 207, 208, 210, 212, 214, 215, 217, 218, 220, 221, 223,
184 224, 226, 228, 229, 231, 233, 235, 236, 238, 240, 241, 242, 244, 245, 246, 248
186 #define LCD_SCANRATE 70 /* Hz */
188 #elif defined MROBE_100 /* verified */
189 /* Average measurements of 2 m:robe 100 s */
190 static const unsigned char lcdlinear[256] = {
191 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 49, 53, 56, 60, 63, 67,
192 70, 73, 76, 79, 81, 84, 87, 90, 92, 95, 97, 100, 102, 105, 107, 110,
193 112, 114, 116, 118, 119, 121, 123, 125, 126, 128, 130, 131, 133, 135, 136, 138,
194 139, 141, 142, 143, 144, 146, 147, 148, 149, 150, 151, 152, 154, 155, 156, 157,
195 158, 159, 160, 161, 161, 162, 163, 164, 165, 166, 167, 168, 168, 169, 170, 171,
196 172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 178, 178, 179, 180, 180,
197 181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188,
198 189, 189, 190, 190, 191, 191, 192, 192, 193, 193, 193, 194, 194, 195, 195, 195,
199 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 200, 201, 201, 202, 202, 202,
200 203, 203, 204, 204, 205, 205, 206, 206, 207, 207, 207, 208, 208, 209, 209, 209,
201 210, 210, 210, 211, 211, 212, 212, 212, 213, 213, 213, 214, 214, 215, 215, 215,
202 216, 216, 216, 217, 217, 218, 218, 218, 219, 219, 219, 220, 220, 221, 221, 221,
203 222, 222, 222, 223, 223, 224, 224, 224, 225, 225, 225, 226, 226, 227, 227, 227,
204 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 232, 233, 233, 234, 234, 234,
205 235, 235, 235, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 240, 240, 240,
206 241, 241, 242, 242, 243, 243, 244, 244, 247, 248, 248, 249, 250, 250, 251, 252
208 #define LCD_SCANRATE 51 /* Hz */
210 #elif defined SANSA_CLIP /* TODO: calibrate */
211 static const unsigned char lcdlinear[256] = {
212 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
213 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
214 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
215 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
216 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
217 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
218 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
219 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
220 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
221 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
222 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
223 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
224 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
225 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
226 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
227 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
229 #define LCD_SCANRATE 78 /* Hz */
231 #elif defined SANSA_CLIPV2 /* TODO: calibrate */
232 static const unsigned char lcdlinear[256] = {
233 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
234 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
235 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
236 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
237 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
238 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
239 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
240 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
241 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
242 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
243 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
244 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
245 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
246 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
247 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
248 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
250 #define LCD_SCANRATE 74 /* Hz */
252 #elif defined SANSA_CLIPPLUS /* TODO: calibrate */
253 static const unsigned char lcdlinear[256] = {
254 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
255 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
256 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
257 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
258 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
259 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
260 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
261 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
262 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
263 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
264 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
265 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
266 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
267 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
268 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
269 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
271 #define LCD_SCANRATE 80 /* Hz */
273 #elif defined MPIO_HD200
274 /* matrix generated in the following way
275 * 1) run 5 times test_grey
276 * 2) average results (joint points)
277 * 3) plot full matrix obtained by natural cubic b-spline interpolation
278 * 4) hand tweak joint points to smooth the curve
279 * 5) repeat steps 3 and 4 until interpolated curve is smooth
281 static const unsigned char lcdlinear[256] = {
282 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,
283 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15,
284 16, 16, 16, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 21, 21, 21,
285 22, 22, 22, 22, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 26, 26,
286 27, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34,
287 35, 35, 36, 36, 37, 37, 38, 39, 39, 40, 41, 41, 42, 43, 43, 44,
288 45, 45, 46, 46, 47, 48, 49, 49, 50, 51, 51, 52, 53, 53, 54, 55,
289 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63, 64, 64, 65, 66, 67,
290 68, 68, 69, 70, 71, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80,
291 81, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
292 96, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 108, 109, 110, 111,
293 113, 114, 115, 117, 118, 120, 121, 123, 125, 126, 128, 130, 131, 133, 135, 137,
294 139, 140, 142, 144, 146, 147, 149, 151, 152, 154, 156, 157, 159, 161, 162, 164,
295 166, 167, 169, 170, 172, 173, 175, 176, 177, 179, 180, 182, 183, 184, 186, 187,
296 189, 190, 191, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207, 208,
297 210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 224, 225, 227
299 #define LCD_SCANRATE 153 /* Hz */
301 #elif defined MPIO_HD300 /* verified */
302 /* Measurement of one iAudio M5L */
303 static const unsigned char lcdlinear[256] = {
304 4, 6, 8, 10, 11, 13, 15, 17, 19, 21, 22, 24, 25, 27, 28, 30,
305 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 45, 46, 48, 49, 50, 51,
306 52, 52, 53, 54, 55, 55, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63,
307 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 72, 72,
308 73, 73, 74, 75, 75, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81,
309 82, 82, 83, 84, 84, 85, 86, 86, 87, 87, 88, 89, 89, 90, 91, 91,
310 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 98, 98, 99, 100, 100,
311 101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108,
312 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116,
313 117, 117, 118, 119, 119, 120, 121, 121, 122, 122, 123, 124, 124, 125, 126, 126,
314 127, 127, 128, 129, 130, 130, 131, 132, 133, 133, 134, 135, 135, 136, 137, 137,
315 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 149, 150, 151,
316 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 163, 164, 165, 167, 168, 169,
317 170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198,
318 200, 202, 204, 205, 207, 209, 210, 212, 214, 216, 218, 219, 221, 223, 224, 226,
319 228, 230, 231, 233, 235, 236, 237, 239, 241, 243, 244, 246, 248, 249, 250, 252
321 #define LCD_SCANRATE 73 /* Hz */
323 #else /* not yet calibrated targets - generic linear mapping */
324 /* TODO: calibrate iFP7xx */
325 static const unsigned char lcdlinear[256] = {
326 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
327 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
328 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
329 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
330 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
331 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
332 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
333 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
334 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
335 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
336 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
337 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
338 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
339 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
340 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
341 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
343 /* generic default */
344 #define LCD_SCANRATE 70 /* Hz */
346 #endif
347 #else /* SIMULATOR */
348 /* undo a (generic) PC display gamma of 2.0 to simulate target behaviour */
349 static const unsigned char lcdlinear[256] = {
350 0, 16, 23, 28, 32, 36, 39, 42, 45, 48, 50, 53, 55, 58, 60, 62,
351 64, 66, 68, 70, 71, 73, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89,
352 90, 92, 93, 94, 96, 97, 98, 100, 101, 102, 103, 105, 106, 107, 108, 109,
353 111, 112, 113, 114, 115, 116, 117, 118, 119, 121, 122, 123, 124, 125, 126, 127,
354 128, 129, 130, 131, 132, 133, 134, 135, 135, 136, 137, 138, 139, 140, 141, 142,
355 143, 144, 145, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156,
356 156, 157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
357 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 179, 179, 180,
358 181, 181, 182, 183, 183, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190, 191,
359 192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, 201, 201,
360 202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,
361 212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 220, 220, 221,
362 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 228, 228, 229, 229, 230,
363 230, 231, 231, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
364 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,
365 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255
367 #endif /* SIMULATOR */
369 /* Prototypes */
370 static inline void _deferred_update(void) __attribute__ ((always_inline));
371 static int exp_s16p16(int x);
372 static int log_s16p16(int x);
373 static void grey_screendump_hook(int fd);
374 static void fill_gvalues(void);
375 #ifdef SIMULATOR
376 static unsigned long _grey_get_pixel(int x, int y);
377 #else
378 static void _timer_isr(void);
379 #endif
382 #if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
383 static void invert_gvalues(void)
385 unsigned char *val, *end;
386 unsigned char rev_tab[256];
387 unsigned i;
388 unsigned last_i = 0;
389 unsigned x = 0;
390 unsigned last_x;
392 /* Step 1: Calculate a transposed table for undoing the old mapping */
393 for (i = 0; i < 256; i++)
395 last_x = x;
396 x = _grey_info.gvalue[i];
397 if (x > last_x)
399 rev_tab[last_x++] = (last_i + i) / 2;
400 while (x > last_x)
401 rev_tab[last_x++] = i;
402 last_i = i;
405 rev_tab[last_x++] = (last_i + 255) / 2;
406 while (256 > last_x)
407 rev_tab[last_x++] = 255;
409 /* Step 2: Calculate new mapping */
410 fill_gvalues();
412 /* Step 3: Transpose all pixel values */
413 val = _grey_info.values;
414 end = val + _GREY_MULUQ(_grey_info.width, _grey_info.height);
417 *val = _grey_info.gvalue[rev_tab[*val]];
418 while (++val < end);
420 #endif
422 /* Update LCD areas not covered by the greyscale overlay */
423 static inline void _deferred_update(void)
425 int x1 = MAX(_grey_info.x, 0);
426 int x2 = MIN(_grey_info.x + _grey_info.width, LCD_WIDTH);
427 int y1 = MAX(_grey_info.y, 0);
428 int y2 = MIN(_grey_info.y + _grey_info.height, LCD_HEIGHT);
430 if (y1 > 0) /* refresh part above overlay, full width */
431 rb->lcd_update_rect(0, 0, LCD_WIDTH, y1);
433 if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */
434 rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2);
436 if (x1 > 0) /* refresh part to the left of overlay */
437 rb->lcd_update_rect(0, y1, x1, y2 - y1);
439 if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */
440 rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1);
443 #ifdef SIMULATOR
445 /* Callback function for grey_ub_gray_bitmap_part() to read a pixel from the
446 * greybuffer. Note that x and y are in LCD coordinates, not greybuffer
447 * coordinates! */
448 static unsigned long _grey_get_pixel(int x, int y)
450 long val;
451 int xg = x - _grey_info.x;
452 int yg = y - _grey_info.y;
453 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
454 int idx = _grey_info.width * yg + xg;
455 #else /* vertical packing or vertical interleaved */
456 int idx = _grey_info.width * (yg & ~_GREY_BMASK)
457 + (xg << _GREY_BSHIFT) + (~yg & _GREY_BMASK);
458 #endif
460 val = _grey_info.values[idx];
461 #ifdef HAVE_LCD_SPLIT
462 val -= val >> 7;
463 #endif
464 return val;
467 #else /* !SIMULATOR */
469 /* Timer interrupt handler: display next frame */
470 static void _timer_isr(void)
472 #if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
473 unsigned long check = rb->is_backlight_on(true)
474 ? 0 : _GREY_BACKLIGHT_ON;
476 if ((_grey_info.flags & (_GREY_BACKLIGHT_ON|GREY_RAWMAPPED)) == check)
478 _grey_info.flags ^= _GREY_BACKLIGHT_ON;
479 invert_gvalues();
480 return; /* don't overload this timer slot */
482 #endif
483 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
484 rb->lcd_blit_grey_phase(_grey_info.values, _grey_info.phases,
485 _grey_info.bx, _grey_info.y,
486 _grey_info.bwidth, _grey_info.height,
487 _grey_info.width);
488 #else /* vertical packing or vertical interleaved */
489 rb->lcd_blit_grey_phase(_grey_info.values, _grey_info.phases,
490 _grey_info.x, _grey_info.by,
491 _grey_info.width, _grey_info.bheight,
492 _grey_info.width);
493 #endif
495 if (_grey_info.flags & _GREY_DEFERRED_UPDATE) /* lcd_update() requested? */
497 _deferred_update();
498 _grey_info.flags &= ~_GREY_DEFERRED_UPDATE; /* clear request */
502 #endif /* !SIMULATOR */
504 /* fixed point exp() */
505 static int exp_s16p16(int x)
507 int t;
508 int y = 0x00010000;
510 if (x < 0) x += 0xb1721, y >>= 16;
511 t = x - 0x58b91; if (t >= 0) x = t, y <<= 8;
512 t = x - 0x2c5c8; if (t >= 0) x = t, y <<= 4;
513 t = x - 0x162e4; if (t >= 0) x = t, y <<= 2;
514 t = x - 0x0b172; if (t >= 0) x = t, y <<= 1;
515 t = x - 0x067cd; if (t >= 0) x = t, y += y >> 1;
516 t = x - 0x03920; if (t >= 0) x = t, y += y >> 2;
517 t = x - 0x01e27; if (t >= 0) x = t, y += y >> 3;
518 t = x - 0x00f85; if (t >= 0) x = t, y += y >> 4;
519 t = x - 0x007e1; if (t >= 0) x = t, y += y >> 5;
520 t = x - 0x003f8; if (t >= 0) x = t, y += y >> 6;
521 t = x - 0x001fe; if (t >= 0) x = t, y += y >> 7;
522 y += ((y >> 8) * x) >> 8;
524 return y;
527 /* fixed point log() */
528 static int log_s16p16(int x)
530 int t;
531 int y = 0xa65af;
533 if (x < 0x00008000) x <<=16, y -= 0xb1721;
534 if (x < 0x00800000) x <<= 8, y -= 0x58b91;
535 if (x < 0x08000000) x <<= 4, y -= 0x2c5c8;
536 if (x < 0x20000000) x <<= 2, y -= 0x162e4;
537 if (x < 0x40000000) x <<= 1, y -= 0x0b172;
538 t = x + (x >> 1); if ((t & 0x80000000) == 0) x = t, y -= 0x067cd;
539 t = x + (x >> 2); if ((t & 0x80000000) == 0) x = t, y -= 0x03920;
540 t = x + (x >> 3); if ((t & 0x80000000) == 0) x = t, y -= 0x01e27;
541 t = x + (x >> 4); if ((t & 0x80000000) == 0) x = t, y -= 0x00f85;
542 t = x + (x >> 5); if ((t & 0x80000000) == 0) x = t, y -= 0x007e1;
543 t = x + (x >> 6); if ((t & 0x80000000) == 0) x = t, y -= 0x003f8;
544 t = x + (x >> 7); if ((t & 0x80000000) == 0) x = t, y -= 0x001fe;
545 x = 0x80000000 - x;
546 y -= x >> 15;
548 return y;
551 static void fill_gvalues(void)
553 int i;
554 unsigned data;
556 #if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
557 unsigned imask = (_grey_info.flags & _GREY_BACKLIGHT_ON) ? 0xff : 0;
558 #else
559 const unsigned imask = 0;
560 #endif
561 for (i = 0; i < 256; i++)
563 data = exp_s16p16((_GREY_GAMMA * log_s16p16(i * 257 + 1)) >> 8) + 128;
564 data = (data - (data >> 8)) >> 8; /* approx. data /= 257 */
565 data = ((lcdlinear[data ^ imask] ^ imask) << 7) + 127;
566 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8;
567 /* approx. data / 255 */
571 /* Initialise the framework and prepare the greyscale display buffer
573 arguments:
574 gbuf = pointer to the memory area to use (e.g. plugin buffer)
575 gbuf_size = max usable size of the buffer
576 features = flags for requesting features
577 GREY_BUFFERED: use chunky pixel buffering
578 This allows to use all drawing functions, but needs more
579 memory. Unbuffered operation provides only a subset of
580 drawing functions. (only grey_bitmap drawing and scrolling)
581 GREY_RAWMAPPED: no LCD linearisation and gamma correction
582 width = width in pixels (1..LCD_WIDTH)
583 height = height in pixels (1..LCD_HEIGHT)
584 Note that depending on the target LCD, either height or
585 width are rounded up to a multiple of 4 or 8.
587 result:
588 true on success, false on failure
590 If you need info about the memory taken by the greyscale buffer, supply a
591 long* as the last parameter. This long will then contain the number of bytes
592 used. The total memory needed can be calculated as follows:
593 total_mem =
594 width * height * 2 [grey display data]
595 + buffered ? (width * height) : 0 [chunky buffer]
596 + 0..3 [alignment]
598 The function is authentic regarding memory usage on the simulator, even
599 if it doesn't use all of the allocated memory. */
600 bool grey_init(unsigned char *gbuf, long gbuf_size,
601 unsigned features, int width, int height, long *buf_taken)
603 int bdim, i;
604 long plane_size, buftaken;
605 unsigned data;
606 #ifndef SIMULATOR
607 unsigned *dst, *end;
608 #endif
610 if ((unsigned) width > LCD_WIDTH
611 || (unsigned) height > LCD_HEIGHT)
612 return false;
614 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
615 bdim = (width + 7) >> 3;
616 width = bdim << 3;
617 #else /* vertical packing or vertical interleaved */
618 #if (LCD_DEPTH == 1) || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
619 bdim = (height + 7) >> 3;
620 height = bdim << 3;
621 #elif LCD_DEPTH == 2
622 bdim = (height + 3) >> 2;
623 height = bdim << 2;
624 #endif
625 #endif
627 plane_size = _GREY_MULUQ(width, height);
628 #if defined(CPU_COLDFIRE) /* Buffers should be line aligned */ \
629 || defined(CPU_PP) && (NUM_CORES > 1) /* Buffers must be cache line aligned */
630 plane_size += (-plane_size) & 0xf;
631 buftaken = (-(long)gbuf) & 0xf;
632 #else /* Buffers must be 32 bit aligned. */
633 buftaken = (-(long)gbuf) & 3;
634 #endif
635 gbuf += buftaken;
637 if (features & GREY_BUFFERED) /* chunky buffer */
639 _grey_info.buffer = gbuf;
640 gbuf += plane_size;
641 buftaken += plane_size;
643 #if NUM_CORES > 1 /* Values and phases must be uncached when running on COP */
644 if (features & GREY_ON_COP)
645 gbuf = UNCACHED_ADDR(gbuf);
646 #endif
647 _grey_info.values = gbuf;
648 gbuf += plane_size;
649 _grey_info.phases = gbuf;
650 buftaken += 2 * plane_size;
652 if (buftaken > gbuf_size)
653 return false;
655 /* Init to white */
656 rb->memset(_grey_info.values, 0x80, plane_size);
658 #ifndef SIMULATOR
659 /* Init phases with random bits */
660 dst = (unsigned*)(_grey_info.phases);
661 end = (unsigned*)(_grey_info.phases + plane_size);
664 *dst++ = rb->rand();
665 while (dst < end);
666 #endif
668 _grey_info.x = 0;
669 _grey_info.y = 0;
670 _grey_info.width = width;
671 _grey_info.height = height;
672 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
673 _grey_info.bx = 0;
674 _grey_info.bwidth = bdim;
675 #else /* vertical packing or vertical interleaved */
676 _grey_info.by = 0;
677 _grey_info.bheight = bdim;
678 #endif
679 _grey_info.flags = features & 0xff;
680 _grey_info.fg_brightness = 0;
681 _grey_info.bg_brightness = 255;
682 _grey_info.drawmode = DRMODE_SOLID;
683 _grey_info.curfont = FONT_SYSFIXED;
685 /* precalculate the value -> pattern index conversion table, taking
686 linearisation and gamma correction into account */
687 if (features & GREY_RAWMAPPED)
689 for (i = 0; i < 256; i++)
691 data = i << 7;
692 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8;
695 else
697 #if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
698 if (rb->is_backlight_on(true))
699 _grey_info.flags |= _GREY_BACKLIGHT_ON;
700 #endif
701 fill_gvalues();
704 if (buf_taken) /* caller requested info about space taken */
705 *buf_taken = buftaken;
707 return true;
710 /* Release the greyscale display buffer and the library
711 DO CALL either this function or at least grey_show_display(false)
712 before you exit, otherwise nasty things may happen. */
713 void grey_release(void)
715 grey_show(false);
718 /* Switch the greyscale overlay on or off
719 DO NOT call lcd_update() or any other api function that directly accesses
720 the lcd while the greyscale overlay is running! If you need to do
721 lcd_update() to update something outside the greyscale overlay area, use
722 grey_deferred_update() instead.
724 Other functions to avoid are:
725 lcd_blit_mono(), lcd_update_rect(), lcd_set_contrast(),
726 lcd_set_invert_display(), lcd_set_flip() */
727 void grey_show(bool enable)
729 if (enable && !(_grey_info.flags & _GREY_RUNNING))
731 _grey_info.flags |= _GREY_RUNNING;
732 #ifdef SIMULATOR
733 rb->sim_lcd_ex_init(_grey_get_pixel);
734 rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y,
735 _grey_info.width, _grey_info.height);
736 #else /* !SIMULATOR */
737 #ifdef NEED_BOOST
738 rb->cpu_boost(true);
739 #endif
740 #if NUM_CORES > 1
741 rb->timer_register(1, NULL, TIMER_FREQ / LCD_SCANRATE,
742 _timer_isr,
743 (_grey_info.flags & GREY_ON_COP) ? COP : CPU);
744 #else
745 rb->timer_register(1, NULL, TIMER_FREQ / LCD_SCANRATE, _timer_isr);
746 #endif
747 #endif /* !SIMULATOR */
748 rb->screen_dump_set_hook(grey_screendump_hook);
750 else if (!enable && (_grey_info.flags & _GREY_RUNNING))
752 #ifdef SIMULATOR
753 rb->sim_lcd_ex_init(NULL);
754 #else /* !SIMULATOR */
755 rb->timer_unregister();
756 #if NUM_CORES > 1 /* Make sure the ISR has finished before calling lcd_update() */
757 rb->sleep(HZ/100);
758 #endif
759 #ifdef NEED_BOOST
760 rb->cpu_boost(false);
761 #endif
762 #endif /* !SIMULATOR */
763 _grey_info.flags &= ~_GREY_RUNNING;
764 rb->screen_dump_set_hook(NULL);
765 rb->lcd_update(); /* restore whatever there was before */
769 void grey_update_rect(int x, int y, int width, int height)
771 grey_ub_gray_bitmap_part(_grey_info.buffer, x, y, _grey_info.width,
772 x, y, width, height);
775 /* Update the whole greyscale overlay */
776 void grey_update(void)
778 grey_ub_gray_bitmap_part(_grey_info.buffer, 0, 0, _grey_info.width,
779 0, 0, _grey_info.width, _grey_info.height);
782 /* Do an lcd_update() to show changes done by rb->lcd_xxx() functions
783 (in areas of the screen not covered by the greyscale overlay). */
784 void grey_deferred_lcd_update(void)
786 if (_grey_info.flags & _GREY_RUNNING)
788 #ifdef SIMULATOR
789 _deferred_update();
790 #else
791 _grey_info.flags |= _GREY_DEFERRED_UPDATE;
792 #endif
794 else
795 rb->lcd_update();
798 /*** Screenshot ***/
800 #ifdef HAVE_LCD_SPLIT
801 #define NUM_SHADES 128
802 #define BMP_NUMCOLORS 256
803 #else
804 #define NUM_SHADES 129
805 #define BMP_NUMCOLORS 129
806 #endif
808 #define BMP_BPP 8
809 #define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3)
810 #define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
811 #define BMP_DATASIZE (BMP_LINESIZE * (LCD_HEIGHT+LCD_SPLIT_LINES))
812 #define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
814 static const unsigned char bmpheader[] =
816 0x42, 0x4d, /* 'BM' */
817 LE32_CONST(BMP_TOTALSIZE), /* Total file size */
818 0x00, 0x00, 0x00, 0x00, /* Reserved */
819 LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */
821 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
822 LE32_CONST(LCD_WIDTH), /* Width in pixels */
823 LE32_CONST(LCD_HEIGHT+LCD_SPLIT_LINES), /* Height in pixels */
824 0x01, 0x00, /* Number of planes (always 1) */
825 LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */
826 0x00, 0x00, 0x00, 0x00, /* Compression mode, 0 = none */
827 LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */
828 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
829 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
830 LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */
831 LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */
834 #if LCD_DEPTH == 2
835 /* Only defined for positive, non-split LCD for now */
836 static const unsigned char colorindex[4] = {128, 85, 43, 0};
837 #endif
839 /* Hook function for core screen_dump() to save the current display
840 content (b&w and greyscale overlay) to an 8-bit BMP file. */
841 static void grey_screendump_hook(int fd)
843 int i;
844 int y, gx, gy;
845 #if LCD_PIXELFORMAT == VERTICAL_PACKING
846 #if LCD_DEPTH == 1
847 unsigned val;
848 unsigned mask;
849 #elif LCD_DEPTH == 2
850 int shift;
851 #endif
852 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
853 unsigned data;
854 int shift;
855 #endif /* LCD_PIXELFORMAT */
856 fb_data *src;
857 unsigned char *gsrc;
858 unsigned char *dst, *dst_end;
859 unsigned char linebuf[MAX(4*NUM_SHADES,BMP_LINESIZE)];
861 rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */
863 /* build clut */
864 rb->memset(linebuf, 0, 4*NUM_SHADES);
865 dst = linebuf;
867 for (i = 0; i < NUM_SHADES; i++)
869 *dst++ = (_GREY_MULUQ(BLUE_CMP(LCD_BL_BRIGHTCOLOR)
870 -BLUE_CMP(LCD_BL_DARKCOLOR), i) >> 7)
871 + BLUE_CMP(LCD_BL_DARKCOLOR);
872 *dst++ = (_GREY_MULUQ(GREEN_CMP(LCD_BL_BRIGHTCOLOR)
873 -GREEN_CMP(LCD_BL_DARKCOLOR), i) >> 7)
874 + GREEN_CMP(LCD_BL_DARKCOLOR);
875 *dst++ = (_GREY_MULUQ(RED_CMP(LCD_BL_BRIGHTCOLOR)
876 -RED_CMP(LCD_BL_DARKCOLOR), i) >> 7)
877 + RED_CMP(LCD_BL_DARKCOLOR);
878 dst++;
880 rb->write(fd, linebuf, 4*NUM_SHADES);
882 #ifdef HAVE_LCD_SPLIT
883 dst = linebuf;
885 for (i = 0; i <= NUM_SHADES; i++)
887 *dst++ = (_GREY_MULUQ(BLUE_CMP(LCD_BL_BRIGHTCOLOR_2)
888 -BLUE_CMP(LCD_BL_DARKCOLOR_2), i) >> 7)
889 + BLUE_CMP(LCD_BL_DARKCOLOR_2);
890 *dst++ = (_GREY_MULUQ(GREEN_CMP(LCD_BL_BRIGHTCOLOR_2)
891 -GREEN_CMP(LCD_BL_DARKCOLOR_2), i) >> 7)
892 + GREEN_CMP(LCD_BL_DARKCOLOR_2);
893 *dst++ = (_GREY_MULUQ(RED_CMP(LCD_BL_BRIGHTCOLOR_2)
894 -RED_CMP(LCD_BL_DARKCOLOR_2), i) >> 7)
895 + RED_CMP(LCD_BL_DARKCOLOR_2);
896 dst++;
898 rb->write(fd, linebuf, 4*NUM_SHADES);
899 #endif
901 /* BMP image goes bottom -> top */
902 for (y = LCD_HEIGHT - 1; y >= 0; y--)
904 rb->memset(linebuf, 0, BMP_LINESIZE);
906 #if defined(HAVE_LCD_SPLIT) && (LCD_SPLIT_LINES == 2)
907 if (y == LCD_SPLIT_POS - 1)
909 rb->write(fd, linebuf, BMP_LINESIZE);
910 rb->write(fd, linebuf, BMP_LINESIZE);
912 #endif
914 dst = linebuf;
915 dst_end = dst + LCD_WIDTH;
916 gy = y - _grey_info.y;
917 gx = -_grey_info.x;
919 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
920 gsrc = _grey_info.values + _GREY_MULUQ(_grey_info.width, gy);
922 #if LCD_DEPTH == 2
923 src = rb->lcd_framebuffer + _GREY_MULUQ(LCD_FBWIDTH, y);
927 if (((unsigned)gy < (unsigned)_grey_info.height)
928 && ((unsigned)gx < (unsigned)_grey_info.width))
930 *dst++ = *gsrc++;
931 *dst++ = *gsrc++;
932 *dst++ = *gsrc++;
933 *dst++ = *gsrc++;
935 else
937 unsigned data = *src;
938 *dst++ = colorindex[(data >> 6) & 3];
939 *dst++ = colorindex[(data >> 4) & 3];
940 *dst++ = colorindex[(data >> 2) & 3];
941 *dst++ = colorindex[data & 3];
943 gx++, src++;
945 while (dst < dst_end);
947 #endif /* LCD_DEPTH */
948 #elif LCD_PIXELFORMAT == VERTICAL_PACKING
949 gsrc = _grey_info.values + (~gy & _GREY_BMASK)
950 + _GREY_MULUQ(_grey_info.width, gy & ~_GREY_BMASK);
952 #if LCD_DEPTH == 1
953 mask = BIT_N(y & 7);
954 src = rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3);
958 if (((unsigned)gy < (unsigned)_grey_info.height)
959 && ((unsigned)gx < (unsigned)_grey_info.width))
961 val = *gsrc;
962 #ifdef HAVE_LCD_SPLIT
963 val -= val >> 7;
964 #endif
965 gsrc += _GREY_BSIZE;
967 else
969 #ifdef HAVE_NEGATIVE_LCD
970 val = (*src & mask) ? (NUM_SHADES-1) : 0;
971 #else
972 val = (*src & mask) ? 0 : (NUM_SHADES-1);
973 #endif
975 #ifdef HAVE_LCD_SPLIT
976 if (y < LCD_SPLIT_POS)
977 val |= 0x80;
978 #endif
979 *dst++ = val;
980 gx++, src++;
982 while (dst < dst_end);
984 #elif LCD_DEPTH == 2
985 shift = 2 * (y & 3);
986 src = rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 2);
990 if (((unsigned)gy < (unsigned)_grey_info.height)
991 && ((unsigned)gx < (unsigned)_grey_info.width))
993 *dst++ = *gsrc;
994 gsrc += _GREY_BSIZE;
996 else
998 *dst++ = colorindex[(*src >> shift) & 3];
1000 gx++, src++;
1002 while (dst < dst_end);
1004 #endif /* LCD_DEPTH */
1005 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
1006 gsrc = _grey_info.values + (~gy & _GREY_BMASK)
1007 + _GREY_MULUQ(_grey_info.width, gy & ~_GREY_BMASK);
1009 #if LCD_DEPTH == 2
1010 shift = y & 7;
1011 src = rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3);
1015 if (((unsigned)gy < (unsigned)_grey_info.height)
1016 && ((unsigned)gx < (unsigned)_grey_info.width))
1018 *dst++ = *gsrc;
1019 gsrc += _GREY_BSIZE;
1021 else
1023 data = (*src >> shift) & 0x0101;
1024 *dst++ = colorindex[((data >> 7) | data) & 3];
1026 gx++, src++;
1028 while (dst < dst_end);
1030 #endif /* LCD_DEPTH */
1031 #endif /* LCD_PIXELFORMAT */
1033 rb->write(fd, linebuf, BMP_LINESIZE);