Merge branch 'master' into gsoc-ifdef-cleanup
[kugel-rb.git] / apps / plugins / lib / grey_core.c
blob27f7e585d8a62394e4f48612a6ebc7b85295484c
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 #else /* not yet calibrated targets - generic linear mapping */
302 /* TODO: calibrate iFP7xx */
303 static const unsigned char lcdlinear[256] = {
304 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
305 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
306 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
307 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
308 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
309 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
310 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
311 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
312 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
313 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
314 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
315 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
316 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
317 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
318 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
319 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
321 /* generic default */
322 #define LCD_SCANRATE 70 /* Hz */
324 #endif
325 #else /* SIMULATOR */
326 /* undo a (generic) PC display gamma of 2.0 to simulate target behaviour */
327 static const unsigned char lcdlinear[256] = {
328 0, 16, 23, 28, 32, 36, 39, 42, 45, 48, 50, 53, 55, 58, 60, 62,
329 64, 66, 68, 70, 71, 73, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89,
330 90, 92, 93, 94, 96, 97, 98, 100, 101, 102, 103, 105, 106, 107, 108, 109,
331 111, 112, 113, 114, 115, 116, 117, 118, 119, 121, 122, 123, 124, 125, 126, 127,
332 128, 129, 130, 131, 132, 133, 134, 135, 135, 136, 137, 138, 139, 140, 141, 142,
333 143, 144, 145, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156,
334 156, 157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
335 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 179, 179, 180,
336 181, 181, 182, 183, 183, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190, 191,
337 192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, 201, 201,
338 202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,
339 212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 220, 220, 221,
340 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 228, 228, 229, 229, 230,
341 230, 231, 231, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
342 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,
343 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255
345 #endif /* SIMULATOR */
347 /* Prototypes */
348 static inline void _deferred_update(void) __attribute__ ((always_inline));
349 static int exp_s16p16(int x);
350 static int log_s16p16(int x);
351 static void grey_screendump_hook(int fd);
352 static void fill_gvalues(void);
353 #ifdef SIMULATOR
354 static unsigned long _grey_get_pixel(int x, int y);
355 #else
356 static void _timer_isr(void);
357 #endif
360 #if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
361 static void invert_gvalues(void)
363 unsigned char *val, *end;
364 unsigned char rev_tab[256];
365 unsigned i;
366 unsigned last_i = 0;
367 unsigned x = 0;
368 unsigned last_x;
370 /* Step 1: Calculate a transposed table for undoing the old mapping */
371 for (i = 0; i < 256; i++)
373 last_x = x;
374 x = _grey_info.gvalue[i];
375 if (x > last_x)
377 rev_tab[last_x++] = (last_i + i) / 2;
378 while (x > last_x)
379 rev_tab[last_x++] = i;
380 last_i = i;
383 rev_tab[last_x++] = (last_i + 255) / 2;
384 while (256 > last_x)
385 rev_tab[last_x++] = 255;
387 /* Step 2: Calculate new mapping */
388 fill_gvalues();
390 /* Step 3: Transpose all pixel values */
391 val = _grey_info.values;
392 end = val + _GREY_MULUQ(_grey_info.width, _grey_info.height);
395 *val = _grey_info.gvalue[rev_tab[*val]];
396 while (++val < end);
398 #endif
400 /* Update LCD areas not covered by the greyscale overlay */
401 static inline void _deferred_update(void)
403 int x1 = MAX(_grey_info.x, 0);
404 int x2 = MIN(_grey_info.x + _grey_info.width, LCD_WIDTH);
405 int y1 = MAX(_grey_info.y, 0);
406 int y2 = MIN(_grey_info.y + _grey_info.height, LCD_HEIGHT);
408 if (y1 > 0) /* refresh part above overlay, full width */
409 rb->lcd_update_rect(0, 0, LCD_WIDTH, y1);
411 if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */
412 rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2);
414 if (x1 > 0) /* refresh part to the left of overlay */
415 rb->lcd_update_rect(0, y1, x1, y2 - y1);
417 if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */
418 rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1);
421 #ifdef SIMULATOR
423 /* Callback function for grey_ub_gray_bitmap_part() to read a pixel from the
424 * greybuffer. Note that x and y are in LCD coordinates, not greybuffer
425 * coordinates! */
426 static unsigned long _grey_get_pixel(int x, int y)
428 long val;
429 int xg = x - _grey_info.x;
430 int yg = y - _grey_info.y;
431 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
432 int idx = _grey_info.width * yg + xg;
433 #else /* vertical packing or vertical interleaved */
434 int idx = _grey_info.width * (yg & ~_GREY_BMASK)
435 + (xg << _GREY_BSHIFT) + (~yg & _GREY_BMASK);
436 #endif
438 val = _grey_info.values[idx];
439 #ifdef HAVE_LCD_SPLIT
440 val -= val >> 7;
441 #endif
442 return val;
445 #else /* !SIMULATOR */
447 /* Timer interrupt handler: display next frame */
448 static void _timer_isr(void)
450 #if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
451 unsigned long check = rb->is_backlight_on(true)
452 ? 0 : _GREY_BACKLIGHT_ON;
454 if ((_grey_info.flags & (_GREY_BACKLIGHT_ON|GREY_RAWMAPPED)) == check)
456 _grey_info.flags ^= _GREY_BACKLIGHT_ON;
457 invert_gvalues();
458 return; /* don't overload this timer slot */
460 #endif
461 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
462 rb->lcd_blit_grey_phase(_grey_info.values, _grey_info.phases,
463 _grey_info.bx, _grey_info.y,
464 _grey_info.bwidth, _grey_info.height,
465 _grey_info.width);
466 #else /* vertical packing or vertical interleaved */
467 rb->lcd_blit_grey_phase(_grey_info.values, _grey_info.phases,
468 _grey_info.x, _grey_info.by,
469 _grey_info.width, _grey_info.bheight,
470 _grey_info.width);
471 #endif
473 if (_grey_info.flags & _GREY_DEFERRED_UPDATE) /* lcd_update() requested? */
475 _deferred_update();
476 _grey_info.flags &= ~_GREY_DEFERRED_UPDATE; /* clear request */
480 #endif /* !SIMULATOR */
482 /* fixed point exp() */
483 static int exp_s16p16(int x)
485 int t;
486 int y = 0x00010000;
488 if (x < 0) x += 0xb1721, y >>= 16;
489 t = x - 0x58b91; if (t >= 0) x = t, y <<= 8;
490 t = x - 0x2c5c8; if (t >= 0) x = t, y <<= 4;
491 t = x - 0x162e4; if (t >= 0) x = t, y <<= 2;
492 t = x - 0x0b172; if (t >= 0) x = t, y <<= 1;
493 t = x - 0x067cd; if (t >= 0) x = t, y += y >> 1;
494 t = x - 0x03920; if (t >= 0) x = t, y += y >> 2;
495 t = x - 0x01e27; if (t >= 0) x = t, y += y >> 3;
496 t = x - 0x00f85; if (t >= 0) x = t, y += y >> 4;
497 t = x - 0x007e1; if (t >= 0) x = t, y += y >> 5;
498 t = x - 0x003f8; if (t >= 0) x = t, y += y >> 6;
499 t = x - 0x001fe; if (t >= 0) x = t, y += y >> 7;
500 y += ((y >> 8) * x) >> 8;
502 return y;
505 /* fixed point log() */
506 static int log_s16p16(int x)
508 int t;
509 int y = 0xa65af;
511 if (x < 0x00008000) x <<=16, y -= 0xb1721;
512 if (x < 0x00800000) x <<= 8, y -= 0x58b91;
513 if (x < 0x08000000) x <<= 4, y -= 0x2c5c8;
514 if (x < 0x20000000) x <<= 2, y -= 0x162e4;
515 if (x < 0x40000000) x <<= 1, y -= 0x0b172;
516 t = x + (x >> 1); if ((t & 0x80000000) == 0) x = t, y -= 0x067cd;
517 t = x + (x >> 2); if ((t & 0x80000000) == 0) x = t, y -= 0x03920;
518 t = x + (x >> 3); if ((t & 0x80000000) == 0) x = t, y -= 0x01e27;
519 t = x + (x >> 4); if ((t & 0x80000000) == 0) x = t, y -= 0x00f85;
520 t = x + (x >> 5); if ((t & 0x80000000) == 0) x = t, y -= 0x007e1;
521 t = x + (x >> 6); if ((t & 0x80000000) == 0) x = t, y -= 0x003f8;
522 t = x + (x >> 7); if ((t & 0x80000000) == 0) x = t, y -= 0x001fe;
523 x = 0x80000000 - x;
524 y -= x >> 15;
526 return y;
529 static void fill_gvalues(void)
531 int i;
532 unsigned data;
534 #if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
535 unsigned imask = (_grey_info.flags & _GREY_BACKLIGHT_ON) ? 0xff : 0;
536 #else
537 const unsigned imask = 0;
538 #endif
539 for (i = 0; i < 256; i++)
541 data = exp_s16p16((_GREY_GAMMA * log_s16p16(i * 257 + 1)) >> 8) + 128;
542 data = (data - (data >> 8)) >> 8; /* approx. data /= 257 */
543 data = ((lcdlinear[data ^ imask] ^ imask) << 7) + 127;
544 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8;
545 /* approx. data / 255 */
549 /* Initialise the framework and prepare the greyscale display buffer
551 arguments:
552 gbuf = pointer to the memory area to use (e.g. plugin buffer)
553 gbuf_size = max usable size of the buffer
554 features = flags for requesting features
555 GREY_BUFFERED: use chunky pixel buffering
556 This allows to use all drawing functions, but needs more
557 memory. Unbuffered operation provides only a subset of
558 drawing functions. (only grey_bitmap drawing and scrolling)
559 GREY_RAWMAPPED: no LCD linearisation and gamma correction
560 width = width in pixels (1..LCD_WIDTH)
561 height = height in pixels (1..LCD_HEIGHT)
562 Note that depending on the target LCD, either height or
563 width are rounded up to a multiple of 4 or 8.
565 result:
566 true on success, false on failure
568 If you need info about the memory taken by the greyscale buffer, supply a
569 long* as the last parameter. This long will then contain the number of bytes
570 used. The total memory needed can be calculated as follows:
571 total_mem =
572 width * height * 2 [grey display data]
573 + buffered ? (width * height) : 0 [chunky buffer]
574 + 0..3 [alignment]
576 The function is authentic regarding memory usage on the simulator, even
577 if it doesn't use all of the allocated memory. */
578 bool grey_init(unsigned char *gbuf, long gbuf_size,
579 unsigned features, int width, int height, long *buf_taken)
581 int bdim, i;
582 long plane_size, buftaken;
583 unsigned data;
584 #ifndef SIMULATOR
585 unsigned *dst, *end;
586 #endif
588 if ((unsigned) width > LCD_WIDTH
589 || (unsigned) height > LCD_HEIGHT)
590 return false;
592 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
593 bdim = (width + 7) >> 3;
594 width = bdim << 3;
595 #else /* vertical packing or vertical interleaved */
596 #if (LCD_DEPTH == 1) || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
597 bdim = (height + 7) >> 3;
598 height = bdim << 3;
599 #elif LCD_DEPTH == 2
600 bdim = (height + 3) >> 2;
601 height = bdim << 2;
602 #endif
603 #endif
605 plane_size = _GREY_MULUQ(width, height);
606 #if defined(CPU_COLDFIRE) /* Buffers should be line aligned */ \
607 || defined(CPU_PP) && (NUM_CORES > 1) /* Buffers must be cache line aligned */
608 plane_size += (-plane_size) & 0xf;
609 buftaken = (-(long)gbuf) & 0xf;
610 #else /* Buffers must be 32 bit aligned. */
611 buftaken = (-(long)gbuf) & 3;
612 #endif
613 gbuf += buftaken;
615 if (features & GREY_BUFFERED) /* chunky buffer */
617 _grey_info.buffer = gbuf;
618 gbuf += plane_size;
619 buftaken += plane_size;
621 #if NUM_CORES > 1 /* Values and phases must be uncached when running on COP */
622 if (features & GREY_ON_COP)
623 gbuf = UNCACHED_ADDR(gbuf);
624 #endif
625 _grey_info.values = gbuf;
626 gbuf += plane_size;
627 _grey_info.phases = gbuf;
628 buftaken += 2 * plane_size;
630 if (buftaken > gbuf_size)
631 return false;
633 /* Init to white */
634 rb->memset(_grey_info.values, 0x80, plane_size);
636 #ifndef SIMULATOR
637 /* Init phases with random bits */
638 dst = (unsigned*)(_grey_info.phases);
639 end = (unsigned*)(_grey_info.phases + plane_size);
642 *dst++ = rb->rand();
643 while (dst < end);
644 #endif
646 _grey_info.x = 0;
647 _grey_info.y = 0;
648 _grey_info.width = width;
649 _grey_info.height = height;
650 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
651 _grey_info.bx = 0;
652 _grey_info.bwidth = bdim;
653 #else /* vertical packing or vertical interleaved */
654 _grey_info.by = 0;
655 _grey_info.bheight = bdim;
656 #endif
657 _grey_info.flags = features & 0xff;
658 _grey_info.fg_brightness = 0;
659 _grey_info.bg_brightness = 255;
660 _grey_info.drawmode = DRMODE_SOLID;
661 _grey_info.curfont = FONT_SYSFIXED;
663 /* precalculate the value -> pattern index conversion table, taking
664 linearisation and gamma correction into account */
665 if (features & GREY_RAWMAPPED)
667 for (i = 0; i < 256; i++)
669 data = i << 7;
670 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8;
673 else
675 #if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
676 if (rb->is_backlight_on(true))
677 _grey_info.flags |= _GREY_BACKLIGHT_ON;
678 #endif
679 fill_gvalues();
682 if (buf_taken) /* caller requested info about space taken */
683 *buf_taken = buftaken;
685 return true;
688 /* Release the greyscale display buffer and the library
689 DO CALL either this function or at least grey_show_display(false)
690 before you exit, otherwise nasty things may happen. */
691 void grey_release(void)
693 grey_show(false);
696 /* Switch the greyscale overlay on or off
697 DO NOT call lcd_update() or any other api function that directly accesses
698 the lcd while the greyscale overlay is running! If you need to do
699 lcd_update() to update something outside the greyscale overlay area, use
700 grey_deferred_update() instead.
702 Other functions to avoid are:
703 lcd_blit_mono(), lcd_update_rect(), lcd_set_contrast(),
704 lcd_set_invert_display(), lcd_set_flip() */
705 void grey_show(bool enable)
707 if (enable && !(_grey_info.flags & _GREY_RUNNING))
709 _grey_info.flags |= _GREY_RUNNING;
710 #ifdef SIMULATOR
711 rb->sim_lcd_ex_init(_grey_get_pixel);
712 rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y,
713 _grey_info.width, _grey_info.height);
714 #else /* !SIMULATOR */
715 #ifdef NEED_BOOST
716 rb->cpu_boost(true);
717 #endif
718 #if NUM_CORES > 1
719 rb->timer_register(1, NULL, TIMER_FREQ / LCD_SCANRATE,
720 _timer_isr,
721 (_grey_info.flags & GREY_ON_COP) ? COP : CPU);
722 #else
723 rb->timer_register(1, NULL, TIMER_FREQ / LCD_SCANRATE, _timer_isr);
724 #endif
725 #endif /* !SIMULATOR */
726 rb->screen_dump_set_hook(grey_screendump_hook);
728 else if (!enable && (_grey_info.flags & _GREY_RUNNING))
730 #ifdef SIMULATOR
731 rb->sim_lcd_ex_init(NULL);
732 #else /* !SIMULATOR */
733 rb->timer_unregister();
734 #if NUM_CORES > 1 /* Make sure the ISR has finished before calling lcd_update() */
735 rb->sleep(HZ/100);
736 #endif
737 #ifdef NEED_BOOST
738 rb->cpu_boost(false);
739 #endif
740 #endif /* !SIMULATOR */
741 _grey_info.flags &= ~_GREY_RUNNING;
742 rb->screen_dump_set_hook(NULL);
743 rb->lcd_update(); /* restore whatever there was before */
747 void grey_update_rect(int x, int y, int width, int height)
749 grey_ub_gray_bitmap_part(_grey_info.buffer, x, y, _grey_info.width,
750 x, y, width, height);
753 /* Update the whole greyscale overlay */
754 void grey_update(void)
756 grey_ub_gray_bitmap_part(_grey_info.buffer, 0, 0, _grey_info.width,
757 0, 0, _grey_info.width, _grey_info.height);
760 /* Do an lcd_update() to show changes done by rb->lcd_xxx() functions
761 (in areas of the screen not covered by the greyscale overlay). */
762 void grey_deferred_lcd_update(void)
764 if (_grey_info.flags & _GREY_RUNNING)
766 #ifdef SIMULATOR
767 _deferred_update();
768 #else
769 _grey_info.flags |= _GREY_DEFERRED_UPDATE;
770 #endif
772 else
773 rb->lcd_update();
776 /*** Screenshot ***/
778 #ifdef HAVE_LCD_SPLIT
779 #define NUM_SHADES 128
780 #define BMP_NUMCOLORS 256
781 #else
782 #define NUM_SHADES 129
783 #define BMP_NUMCOLORS 129
784 #endif
786 #define BMP_BPP 8
787 #define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3)
788 #define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
789 #define BMP_DATASIZE (BMP_LINESIZE * (LCD_HEIGHT+LCD_SPLIT_LINES))
790 #define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
792 static const unsigned char bmpheader[] =
794 0x42, 0x4d, /* 'BM' */
795 LE32_CONST(BMP_TOTALSIZE), /* Total file size */
796 0x00, 0x00, 0x00, 0x00, /* Reserved */
797 LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */
799 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
800 LE32_CONST(LCD_WIDTH), /* Width in pixels */
801 LE32_CONST(LCD_HEIGHT+LCD_SPLIT_LINES), /* Height in pixels */
802 0x01, 0x00, /* Number of planes (always 1) */
803 LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */
804 0x00, 0x00, 0x00, 0x00, /* Compression mode, 0 = none */
805 LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */
806 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
807 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
808 LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */
809 LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */
812 #if LCD_DEPTH == 2
813 /* Only defined for positive, non-split LCD for now */
814 static const unsigned char colorindex[4] = {128, 85, 43, 0};
815 #endif
817 /* Hook function for core screen_dump() to save the current display
818 content (b&w and greyscale overlay) to an 8-bit BMP file. */
819 static void grey_screendump_hook(int fd)
821 int i;
822 int y, gx, gy;
823 #if LCD_PIXELFORMAT == VERTICAL_PACKING
824 #if LCD_DEPTH == 1
825 unsigned val;
826 unsigned mask;
827 #elif LCD_DEPTH == 2
828 int shift;
829 #endif
830 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
831 unsigned data;
832 int shift;
833 #endif /* LCD_PIXELFORMAT */
834 fb_data *src;
835 unsigned char *gsrc;
836 unsigned char *dst, *dst_end;
837 unsigned char linebuf[MAX(4*NUM_SHADES,BMP_LINESIZE)];
839 rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */
841 /* build clut */
842 rb->memset(linebuf, 0, 4*NUM_SHADES);
843 dst = linebuf;
845 for (i = 0; i < NUM_SHADES; i++)
847 *dst++ = (_GREY_MULUQ(BLUE_CMP(LCD_BL_BRIGHTCOLOR)
848 -BLUE_CMP(LCD_BL_DARKCOLOR), i) >> 7)
849 + BLUE_CMP(LCD_BL_DARKCOLOR);
850 *dst++ = (_GREY_MULUQ(GREEN_CMP(LCD_BL_BRIGHTCOLOR)
851 -GREEN_CMP(LCD_BL_DARKCOLOR), i) >> 7)
852 + GREEN_CMP(LCD_BL_DARKCOLOR);
853 *dst++ = (_GREY_MULUQ(RED_CMP(LCD_BL_BRIGHTCOLOR)
854 -RED_CMP(LCD_BL_DARKCOLOR), i) >> 7)
855 + RED_CMP(LCD_BL_DARKCOLOR);
856 dst++;
858 rb->write(fd, linebuf, 4*NUM_SHADES);
860 #ifdef HAVE_LCD_SPLIT
861 dst = linebuf;
863 for (i = 0; i <= NUM_SHADES; i++)
865 *dst++ = (_GREY_MULUQ(BLUE_CMP(LCD_BL_BRIGHTCOLOR_2)
866 -BLUE_CMP(LCD_BL_DARKCOLOR_2), i) >> 7)
867 + BLUE_CMP(LCD_BL_DARKCOLOR_2);
868 *dst++ = (_GREY_MULUQ(GREEN_CMP(LCD_BL_BRIGHTCOLOR_2)
869 -GREEN_CMP(LCD_BL_DARKCOLOR_2), i) >> 7)
870 + GREEN_CMP(LCD_BL_DARKCOLOR_2);
871 *dst++ = (_GREY_MULUQ(RED_CMP(LCD_BL_BRIGHTCOLOR_2)
872 -RED_CMP(LCD_BL_DARKCOLOR_2), i) >> 7)
873 + RED_CMP(LCD_BL_DARKCOLOR_2);
874 dst++;
876 rb->write(fd, linebuf, 4*NUM_SHADES);
877 #endif
879 /* BMP image goes bottom -> top */
880 for (y = LCD_HEIGHT - 1; y >= 0; y--)
882 rb->memset(linebuf, 0, BMP_LINESIZE);
884 #if defined(HAVE_LCD_SPLIT) && (LCD_SPLIT_LINES == 2)
885 if (y == LCD_SPLIT_POS - 1)
887 rb->write(fd, linebuf, BMP_LINESIZE);
888 rb->write(fd, linebuf, BMP_LINESIZE);
890 #endif
892 dst = linebuf;
893 dst_end = dst + LCD_WIDTH;
894 gy = y - _grey_info.y;
895 gx = -_grey_info.x;
897 #if LCD_PIXELFORMAT == HORIZONTAL_PACKING
898 gsrc = _grey_info.values + _GREY_MULUQ(_grey_info.width, gy);
900 #if LCD_DEPTH == 2
901 src = rb->lcd_framebuffer + _GREY_MULUQ(LCD_FBWIDTH, y);
905 if (((unsigned)gy < (unsigned)_grey_info.height)
906 && ((unsigned)gx < (unsigned)_grey_info.width))
908 *dst++ = *gsrc++;
909 *dst++ = *gsrc++;
910 *dst++ = *gsrc++;
911 *dst++ = *gsrc++;
913 else
915 unsigned data = *src;
916 *dst++ = colorindex[(data >> 6) & 3];
917 *dst++ = colorindex[(data >> 4) & 3];
918 *dst++ = colorindex[(data >> 2) & 3];
919 *dst++ = colorindex[data & 3];
921 gx++, src++;
923 while (dst < dst_end);
925 #endif /* LCD_DEPTH */
926 #elif LCD_PIXELFORMAT == VERTICAL_PACKING
927 gsrc = _grey_info.values + (~gy & _GREY_BMASK)
928 + _GREY_MULUQ(_grey_info.width, gy & ~_GREY_BMASK);
930 #if LCD_DEPTH == 1
931 mask = BIT_N(y & 7);
932 src = rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3);
936 if (((unsigned)gy < (unsigned)_grey_info.height)
937 && ((unsigned)gx < (unsigned)_grey_info.width))
939 val = *gsrc;
940 #ifdef HAVE_LCD_SPLIT
941 val -= val >> 7;
942 #endif
943 gsrc += _GREY_BSIZE;
945 else
947 #ifdef HAVE_NEGATIVE_LCD
948 val = (*src & mask) ? (NUM_SHADES-1) : 0;
949 #else
950 val = (*src & mask) ? 0 : (NUM_SHADES-1);
951 #endif
953 #ifdef HAVE_LCD_SPLIT
954 if (y < LCD_SPLIT_POS)
955 val |= 0x80;
956 #endif
957 *dst++ = val;
958 gx++, src++;
960 while (dst < dst_end);
962 #elif LCD_DEPTH == 2
963 shift = 2 * (y & 3);
964 src = rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 2);
968 if (((unsigned)gy < (unsigned)_grey_info.height)
969 && ((unsigned)gx < (unsigned)_grey_info.width))
971 *dst++ = *gsrc;
972 gsrc += _GREY_BSIZE;
974 else
976 *dst++ = colorindex[(*src >> shift) & 3];
978 gx++, src++;
980 while (dst < dst_end);
982 #endif /* LCD_DEPTH */
983 #elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
984 gsrc = _grey_info.values + (~gy & _GREY_BMASK)
985 + _GREY_MULUQ(_grey_info.width, gy & ~_GREY_BMASK);
987 #if LCD_DEPTH == 2
988 shift = y & 7;
989 src = rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3);
993 if (((unsigned)gy < (unsigned)_grey_info.height)
994 && ((unsigned)gx < (unsigned)_grey_info.width))
996 *dst++ = *gsrc;
997 gsrc += _GREY_BSIZE;
999 else
1001 data = (*src >> shift) & 0x0101;
1002 *dst++ = colorindex[((data >> 7) | data) & 3];
1004 gx++, src++;
1006 while (dst < dst_end);
1008 #endif /* LCD_DEPTH */
1009 #endif /* LCD_PIXELFORMAT */
1011 rb->write(fd, linebuf, BMP_LINESIZE);