blob: 008104a04f28afcda2ef0dfc3d0f213eecc01510 [file] [log] [blame]
Jens Arnoldfeb5b152008-01-04 23:42:38 +00001/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* New greyscale framework
11* Core & miscellaneous functions
12*
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.
15*
16* Copyright (C) 2008 Jens Arnold
17*
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000018* 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.
Jens Arnoldfeb5b152008-01-04 23:42:38 +000022*
23* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24* KIND, either express or implied.
25*
26****************************************************************************/
27
28#include "plugin.h"
29#include "grey.h"
30
Jens Arnold40919d72008-03-25 23:21:36 +000031#if defined(HAVE_ADJUSTABLE_CPU_FREQ) && \
32 (defined(CPU_PP) || (CONFIG_LCD == LCD_TL0350A))
Jens Arnoldfeb5b152008-01-04 23:42:38 +000033#define NEED_BOOST
34#endif
35
Jens Arnoldfeb5b152008-01-04 23:42:38 +000036#ifndef SIMULATOR
37
Jens Arnold5c87a982008-04-02 22:16:14 +000038#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. */
Jens Arnoldfeb5b152008-01-04 23:42:38 +000045static const unsigned char lcdlinear[256] = {
Jens Arnold5c87a982008-04-02 22:16:14 +000046 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,
52101, 101, 102, 103, 103, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109,
53110, 110, 111, 112, 112, 113, 114, 114, 115, 115, 116, 117, 117, 118, 119, 119,
54120, 120, 121, 122, 123, 123, 124, 125, 126, 126, 127, 128, 129, 129, 130, 131,
55132, 132, 133, 134, 135, 135, 136, 137, 138, 138, 139, 140, 140, 141, 141, 142,
56143, 144, 145, 146, 147, 147, 148, 149, 150, 151, 152, 153, 154, 154, 155, 156,
57157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 166, 167, 168, 168, 169, 170,
58171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 184, 185, 186, 187,
59188, 189, 191, 192, 194, 195, 197, 198, 199, 200, 202, 203, 204, 205, 207, 208,
60209, 210, 212, 213, 215, 216, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228,
61229, 230, 232, 233, 234, 235, 237, 238, 239, 240, 242, 243, 244, 246, 247, 248
Jens Arnoldfeb5b152008-01-04 23:42:38 +000062};
Jens Arnold5c87a982008-04-02 22:16:14 +000063/* The actual LCD scanrate varies a lot with temperature on these targets */
64#define LCD_SCANRATE 67 /* Hz */
65
66#elif defined IAUDIO_M3 /* verified */
67/* Average measurements of 2 iAudio remotes connected to an M3. */
Jens Arnoldfeb5b152008-01-04 23:42:38 +000068static const unsigned char lcdlinear[256] = {
Jens Arnold5c87a982008-04-02 22:16:14 +000069 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,
72109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116,
73117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 121, 122, 122, 123, 123, 123,
74124, 124, 124, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 129, 129, 129,
75130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 134, 135, 135, 136, 136, 136,
76137, 137, 137, 138, 138, 139, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143,
77144, 144, 145, 145, 146, 147, 147, 148, 149, 149, 150, 150, 151, 151, 152, 152,
78153, 153, 154, 154, 155, 155, 156, 156, 157, 157, 158, 158, 159, 160, 160, 161,
79162, 162, 163, 164, 164, 165, 166, 167, 168, 168, 169, 169, 170, 171, 171, 172,
80173, 173, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 182, 182, 183, 184,
81185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 198, 199, 200, 201,
82202, 203, 204, 205, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219,
83220, 221, 222, 223, 225, 226, 227, 228, 229, 230, 231, 232, 234, 235, 236, 237,
84238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 249, 250, 251, 252
Jens Arnoldfeb5b152008-01-04 23:42:38 +000085};
Jens Arnold4a6190d2008-05-24 08:53:12 +000086/* 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 */
Jens Arnold5c87a982008-04-02 22:16:14 +000090
91#elif defined IAUDIO_M5 /* verified */
92/* Measurement of one iAudio M5L */
Jens Arnoldfeb5b152008-01-04 23:42:38 +000093static const unsigned char lcdlinear[256] = {
Jens Arnold5c87a982008-04-02 22:16:14 +000094 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,
101101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108,
102109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116,
103117, 117, 118, 119, 119, 120, 121, 121, 122, 122, 123, 124, 124, 125, 126, 126,
104127, 127, 128, 129, 130, 130, 131, 132, 133, 133, 134, 135, 135, 136, 137, 137,
105138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 149, 150, 151,
106152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 163, 164, 165, 167, 168, 169,
107170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198,
108200, 202, 204, 205, 207, 209, 210, 212, 214, 216, 218, 219, 221, 223, 224, 226,
109228, 230, 231, 233, 235, 236, 237, 239, 241, 243, 244, 246, 248, 249, 250, 252
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000110};
Jens Arnold5c87a982008-04-02 22:16:14 +0000111#define LCD_SCANRATE 73 /* Hz */
112
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. */
Jens Arnold40919d72008-03-25 23:21:36 +0000119static const unsigned char lcdlinear[256] = {
Jens Arnold5c87a982008-04-02 22:16:14 +0000120 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,
129100, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108, 109, 109,
130110, 110, 111, 112, 113, 113, 114, 115, 116, 116, 117, 118, 119, 119, 120, 121,
131122, 122, 123, 124, 125, 125, 126, 127, 128, 129, 130, 131, 131, 132, 133, 134,
132135, 137, 138, 139, 141, 142, 144, 145, 146, 147, 149, 150, 151, 152, 154, 155,
133156, 158, 159, 161, 162, 164, 165, 167, 169, 171, 172, 174, 175, 177, 178, 180,
134182, 184, 186, 188, 189, 191, 193, 195, 197, 199, 201, 203, 206, 208, 210, 212,
135214, 217, 219, 221, 224, 226, 229, 231, 233, 236, 238, 240, 243, 245, 247, 250
Jens Arnold40919d72008-03-25 23:21:36 +0000136};
Jens Arnold5c87a982008-04-02 22:16:14 +0000137/* Average from an iPod 1st Gen and an iPod 2nd Gen */
138#define LCD_SCANRATE 96 /* Hz */
139
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 */
145static 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,
156102, 102, 103, 104, 104, 105, 106, 106, 107, 108, 109, 110, 110, 111, 112, 113,
157114, 115, 115, 116, 117, 118, 118, 119, 120, 121, 121, 122, 123, 124, 124, 125,
158126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
159141, 142, 143, 144, 146, 147, 148, 149, 150, 151, 153, 154, 155, 156, 158, 159,
160160, 162, 163, 165, 166, 168, 169, 171, 172, 175, 177, 180, 182, 185, 187, 190,
161192, 196, 199, 203, 206, 210, 213, 217, 220, 223, 227, 230, 234, 238, 242, 246
162};
163/* Average of an iPod Mini G2 and 2 3rd Gen iPods. */
164#define LCD_SCANRATE 87 /* Hz */
165
166#elif defined IRIVER_H100_SERIES /* verified */
167/* Measurement of one Iriver H140 */
168static 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,
174102, 102, 102, 103, 103, 104, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108,
175109, 109, 109, 110, 110, 111, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115,
176116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123,
177124, 124, 125, 125, 126, 127, 127, 128, 129, 129, 130, 130, 131, 131, 132, 132,
178133, 133, 134, 135, 135, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141,
179142, 142, 143, 143, 144, 145, 145, 146, 147, 147, 148, 148, 149, 150, 150, 151,
180152, 152, 153, 153, 154, 155, 155, 156, 157, 157, 158, 159, 160, 160, 161, 162,
181163, 164, 165, 166, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
182178, 179, 181, 182, 183, 184, 186, 187, 188, 189, 191, 192, 193, 194, 196, 197,
183198, 200, 202, 203, 205, 207, 208, 210, 212, 214, 215, 217, 218, 220, 221, 223,
184224, 226, 228, 229, 231, 233, 235, 236, 238, 240, 241, 242, 244, 245, 246, 248
185};
186#define LCD_SCANRATE 70 /* Hz */
187
Jens Arnoldece03122008-04-07 21:14:29 +0000188#elif defined MROBE_100 /* verified */
189/* Average measurements of 2 m:robe 100 s */
190static 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,
193112, 114, 116, 118, 119, 121, 123, 125, 126, 128, 130, 131, 133, 135, 136, 138,
194139, 141, 142, 143, 144, 146, 147, 148, 149, 150, 151, 152, 154, 155, 156, 157,
195158, 159, 160, 161, 161, 162, 163, 164, 165, 166, 167, 168, 168, 169, 170, 171,
196172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 178, 178, 179, 180, 180,
197181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188,
198189, 189, 190, 190, 191, 191, 192, 192, 193, 193, 193, 194, 194, 195, 195, 195,
199196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 200, 201, 201, 202, 202, 202,
200203, 203, 204, 204, 205, 205, 206, 206, 207, 207, 207, 208, 208, 209, 209, 209,
201210, 210, 210, 211, 211, 212, 212, 212, 213, 213, 213, 214, 214, 215, 215, 215,
202216, 216, 216, 217, 217, 218, 218, 218, 219, 219, 219, 220, 220, 221, 221, 221,
203222, 222, 222, 223, 223, 224, 224, 224, 225, 225, 225, 226, 226, 227, 227, 227,
204228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 232, 233, 233, 234, 234, 234,
205235, 235, 235, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 240, 240, 240,
206241, 241, 242, 242, 243, 243, 244, 244, 247, 248, 248, 249, 250, 250, 251, 252
207};
208#define LCD_SCANRATE 51 /* Hz */
209
Jens Arnold5c87a982008-04-02 22:16:14 +0000210#else /* not yet calibrated targets - generic linear mapping */
Jens Arnoldece03122008-04-07 21:14:29 +0000211/* TODO: calibrate iFP7xx */
Jens Arnold5c87a982008-04-02 22:16:14 +0000212static const unsigned char lcdlinear[256] = {
213 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
214 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
215 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
216 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
217 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
218 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
219 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
220112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
221128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
222144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
223160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
224176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
225192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
226208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
227224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
228240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
229};
230/* generic default */
231#define LCD_SCANRATE 70 /* Hz */
232
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000233#endif
234#else /* SIMULATOR */
235/* undo a (generic) PC display gamma of 2.0 to simulate target behaviour */
236static const unsigned char lcdlinear[256] = {
Jens Arnold5c87a982008-04-02 22:16:14 +0000237 0, 16, 23, 28, 32, 36, 39, 42, 45, 48, 50, 53, 55, 58, 60, 62,
238 64, 66, 68, 70, 71, 73, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89,
239 90, 92, 93, 94, 96, 97, 98, 100, 101, 102, 103, 105, 106, 107, 108, 109,
240111, 112, 113, 114, 115, 116, 117, 118, 119, 121, 122, 123, 124, 125, 126, 127,
241128, 129, 130, 131, 132, 133, 134, 135, 135, 136, 137, 138, 139, 140, 141, 142,
242143, 144, 145, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156,
243156, 157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168,
244169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 179, 179, 180,
245181, 181, 182, 183, 183, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190, 191,
246192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, 201, 201,
247202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211,
248212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 220, 220, 221,
249221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 228, 228, 229, 229, 230,
250230, 231, 231, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
251239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247,
252247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000253};
254#endif /* SIMULATOR */
255
256/* Prototypes */
257static inline void _deferred_update(void) __attribute__ ((always_inline));
258static int exp_s16p16(int x);
259static int log_s16p16(int x);
260static void grey_screendump_hook(int fd);
Jens Arnold5c87a982008-04-02 22:16:14 +0000261static void fill_gvalues(void);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000262#ifdef SIMULATOR
263static unsigned long _grey_get_pixel(int x, int y);
264#else
265static void _timer_isr(void);
266#endif
267
Jens Arnold3183b9e2008-04-04 19:14:19 +0000268
Jens Arnold5c87a982008-04-02 22:16:14 +0000269#if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
Jens Arnold5c87a982008-04-02 22:16:14 +0000270static void invert_gvalues(void)
271{
272 unsigned char *val, *end;
273 unsigned char rev_tab[256];
274 unsigned i;
275 unsigned last_i = 0;
276 unsigned x = 0;
277 unsigned last_x;
278
Jens Arnold8f560bc2008-04-05 08:56:43 +0000279 /* Step 1: Calculate a transposed table for undoing the old mapping */
280 for (i = 0; i < 256; i++)
Jens Arnold5c87a982008-04-02 22:16:14 +0000281 {
Jens Arnold8f560bc2008-04-05 08:56:43 +0000282 last_x = x;
283 x = _grey_info.gvalue[i];
284 if (x > last_x)
Jens Arnold5c87a982008-04-02 22:16:14 +0000285 {
Jens Arnold8f560bc2008-04-05 08:56:43 +0000286 rev_tab[last_x++] = (last_i + i) / 2;
287 while (x > last_x)
288 rev_tab[last_x++] = i;
289 last_i = i;
Jens Arnold5c87a982008-04-02 22:16:14 +0000290 }
Jens Arnold5c87a982008-04-02 22:16:14 +0000291 }
Jens Arnold8f560bc2008-04-05 08:56:43 +0000292 rev_tab[last_x++] = (last_i + 255) / 2;
293 while (256 > last_x)
294 rev_tab[last_x++] = 255;
295
296 /* Step 2: Calculate new mapping */
297 fill_gvalues();
298
299 /* Step 3: Transpose all pixel values */
300 val = _grey_info.values;
301 end = val + _GREY_MULUQ(_grey_info.width, _grey_info.height);
302
303 do
304 *val = _grey_info.gvalue[rev_tab[*val]];
305 while (++val < end);
Jens Arnold5c87a982008-04-02 22:16:14 +0000306}
307#endif
308
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000309/* Update LCD areas not covered by the greyscale overlay */
310static inline void _deferred_update(void)
311{
312 int x1 = MAX(_grey_info.x, 0);
313 int x2 = MIN(_grey_info.x + _grey_info.width, LCD_WIDTH);
314 int y1 = MAX(_grey_info.y, 0);
315 int y2 = MIN(_grey_info.y + _grey_info.height, LCD_HEIGHT);
316
317 if (y1 > 0) /* refresh part above overlay, full width */
Jens Arnolda72499a2008-01-13 00:11:43 +0000318 _grey_info.rb->lcd_update_rect(0, 0, LCD_WIDTH, y1);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000319
320 if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */
Jens Arnolda72499a2008-01-13 00:11:43 +0000321 _grey_info.rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000322
323 if (x1 > 0) /* refresh part to the left of overlay */
Jens Arnolda72499a2008-01-13 00:11:43 +0000324 _grey_info.rb->lcd_update_rect(0, y1, x1, y2 - y1);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000325
326 if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */
Jens Arnolda72499a2008-01-13 00:11:43 +0000327 _grey_info.rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000328}
329
Jens Arnoldfa7eb562008-01-13 18:39:09 +0000330#ifdef SIMULATOR
331
332/* Callback function for grey_ub_gray_bitmap_part() to read a pixel from the
333 * greybuffer. Note that x and y are in LCD coordinates, not greybuffer
334 * coordinates! */
335static unsigned long _grey_get_pixel(int x, int y)
336{
337 int xg = x - _grey_info.x;
338 int yg = y - _grey_info.y;
339#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
340 int idx = _grey_info.width * yg + xg;
Jens Arnold40919d72008-03-25 23:21:36 +0000341#else /* vertical packing or vertical interleaved */
Jens Arnoldfa7eb562008-01-13 18:39:09 +0000342 int idx = _grey_info.width * (yg & ~_GREY_BMASK)
343 + (xg << _GREY_BSHIFT) + (~yg & _GREY_BMASK);
344#endif
345
346 return _grey_info.values[idx] + (1 << LCD_DEPTH);
347}
348
349#else /* !SIMULATOR */
350
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000351/* Timer interrupt handler: display next frame */
352static void _timer_isr(void)
353{
Jens Arnold5c87a982008-04-02 22:16:14 +0000354#if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
Jens Arnold3183b9e2008-04-04 19:14:19 +0000355 unsigned long check = _grey_info.rb->is_backlight_on(true)
356 ? 0 : _GREY_BACKLIGHT_ON;
Jens Arnold5c87a982008-04-02 22:16:14 +0000357
Jens Arnold3183b9e2008-04-04 19:14:19 +0000358 if ((_grey_info.flags & (_GREY_BACKLIGHT_ON|GREY_RAWMAPPED)) == check)
Jens Arnold5c87a982008-04-02 22:16:14 +0000359 {
Jens Arnold3183b9e2008-04-04 19:14:19 +0000360 _grey_info.flags ^= _GREY_BACKLIGHT_ON;
Jens Arnold5c87a982008-04-02 22:16:14 +0000361 invert_gvalues();
362 return; /* don't overload this timer slot */
363 }
364#endif
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000365#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
Jens Arnold68a21682008-03-24 00:35:53 +0000366 _grey_info.rb->lcd_blit_grey_phase(_grey_info.values, _grey_info.phases,
Jens Arnolda72499a2008-01-13 00:11:43 +0000367 _grey_info.bx, _grey_info.y,
368 _grey_info.bwidth, _grey_info.height,
369 _grey_info.width);
Jens Arnold40919d72008-03-25 23:21:36 +0000370#else /* vertical packing or vertical interleaved */
Jens Arnold68a21682008-03-24 00:35:53 +0000371 _grey_info.rb->lcd_blit_grey_phase(_grey_info.values, _grey_info.phases,
Jens Arnolda72499a2008-01-13 00:11:43 +0000372 _grey_info.x, _grey_info.by,
373 _grey_info.width, _grey_info.bheight,
374 _grey_info.width);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000375#endif
376
Jens Arnolda72499a2008-01-13 00:11:43 +0000377 if (_grey_info.flags & _GREY_DEFERRED_UPDATE) /* lcd_update() requested? */
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000378 {
379 _deferred_update();
380 _grey_info.flags &= ~_GREY_DEFERRED_UPDATE; /* clear request */
381 }
382}
Jens Arnoldfa7eb562008-01-13 18:39:09 +0000383
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000384#endif /* !SIMULATOR */
385
386/* fixed point exp() */
387static int exp_s16p16(int x)
388{
389 int t;
390 int y = 0x00010000;
Jens Arnolda72499a2008-01-13 00:11:43 +0000391
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000392 if (x < 0) x += 0xb1721, y >>= 16;
393 t = x - 0x58b91; if (t >= 0) x = t, y <<= 8;
394 t = x - 0x2c5c8; if (t >= 0) x = t, y <<= 4;
395 t = x - 0x162e4; if (t >= 0) x = t, y <<= 2;
396 t = x - 0x0b172; if (t >= 0) x = t, y <<= 1;
397 t = x - 0x067cd; if (t >= 0) x = t, y += y >> 1;
398 t = x - 0x03920; if (t >= 0) x = t, y += y >> 2;
399 t = x - 0x01e27; if (t >= 0) x = t, y += y >> 3;
400 t = x - 0x00f85; if (t >= 0) x = t, y += y >> 4;
401 t = x - 0x007e1; if (t >= 0) x = t, y += y >> 5;
402 t = x - 0x003f8; if (t >= 0) x = t, y += y >> 6;
403 t = x - 0x001fe; if (t >= 0) x = t, y += y >> 7;
404 y += ((y >> 8) * x) >> 8;
405
406 return y;
407}
408
409/* fixed point log() */
410static int log_s16p16(int x)
411{
412 int t;
413 int y = 0xa65af;
414
415 if (x < 0x00008000) x <<=16, y -= 0xb1721;
416 if (x < 0x00800000) x <<= 8, y -= 0x58b91;
417 if (x < 0x08000000) x <<= 4, y -= 0x2c5c8;
418 if (x < 0x20000000) x <<= 2, y -= 0x162e4;
419 if (x < 0x40000000) x <<= 1, y -= 0x0b172;
420 t = x + (x >> 1); if ((t & 0x80000000) == 0) x = t, y -= 0x067cd;
421 t = x + (x >> 2); if ((t & 0x80000000) == 0) x = t, y -= 0x03920;
422 t = x + (x >> 3); if ((t & 0x80000000) == 0) x = t, y -= 0x01e27;
423 t = x + (x >> 4); if ((t & 0x80000000) == 0) x = t, y -= 0x00f85;
424 t = x + (x >> 5); if ((t & 0x80000000) == 0) x = t, y -= 0x007e1;
425 t = x + (x >> 6); if ((t & 0x80000000) == 0) x = t, y -= 0x003f8;
426 t = x + (x >> 7); if ((t & 0x80000000) == 0) x = t, y -= 0x001fe;
427 x = 0x80000000 - x;
428 y -= x >> 15;
429
430 return y;
431}
432
Jens Arnold5c87a982008-04-02 22:16:14 +0000433static void fill_gvalues(void)
434{
435 int i;
436 unsigned data;
437
438#if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
Jens Arnold3183b9e2008-04-04 19:14:19 +0000439 unsigned imask = (_grey_info.flags & _GREY_BACKLIGHT_ON) ? 0xff : 0;
Jens Arnold5c87a982008-04-02 22:16:14 +0000440#else
441 const unsigned imask = 0;
442#endif
443 for (i = 0; i < 256; i++)
444 {
445 data = exp_s16p16((_GREY_GAMMA * log_s16p16(i * 257 + 1)) >> 8) + 128;
446 data = (data - (data >> 8)) >> 8; /* approx. data /= 257 */
447 data = ((lcdlinear[data ^ imask] ^ imask) << 7) + 127;
448 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8;
449 /* approx. data / 255 */
450 }
451}
452
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000453/* Initialise the framework and prepare the greyscale display buffer
454
455 arguments:
456 newrb = pointer to plugin api
457 gbuf = pointer to the memory area to use (e.g. plugin buffer)
458 gbuf_size = max usable size of the buffer
Jens Arnold8493f5b2008-03-02 23:31:09 +0000459 features = flags for requesting features
460 GREY_BUFFERED: use chunky pixel buffering
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000461 This allows to use all drawing functions, but needs more
462 memory. Unbuffered operation provides only a subset of
463 drawing functions. (only grey_bitmap drawing and scrolling)
Jens Arnold8493f5b2008-03-02 23:31:09 +0000464 GREY_RAWMAPPED: no LCD linearisation and gamma correction
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000465 width = width in pixels (1..LCD_WIDTH)
466 height = height in pixels (1..LCD_HEIGHT)
467 Note that depending on the target LCD, either height or
468 width are rounded up to a multiple of 4 or 8.
469
470 result:
471 true on success, false on failure
472
473 If you need info about the memory taken by the greyscale buffer, supply a
474 long* as the last parameter. This long will then contain the number of bytes
475 used. The total memory needed can be calculated as follows:
476 total_mem =
477 width * height * 2 [grey display data]
478 + buffered ? (width * height) : 0 [chunky buffer]
479 + 0..3 [alignment]
480
481 The function is authentic regarding memory usage on the simulator, even
482 if it doesn't use all of the allocated memory. */
Steve Bavin65265772008-05-13 09:57:56 +0000483bool grey_init(const struct plugin_api* newrb, unsigned char *gbuf, long gbuf_size,
Jens Arnold8493f5b2008-03-02 23:31:09 +0000484 unsigned features, int width, int height, long *buf_taken)
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000485{
486 int bdim, i;
487 long plane_size, buftaken;
488 unsigned data;
489#ifndef SIMULATOR
Jens Arnold6a56c142008-01-09 23:48:26 +0000490 unsigned *dst, *end;
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000491#endif
492
Jens Arnolda72499a2008-01-13 00:11:43 +0000493 _grey_info.rb = newrb;
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000494
495 if ((unsigned) width > LCD_WIDTH
496 || (unsigned) height > LCD_HEIGHT)
497 return false;
498
499#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
500 bdim = (width + 7) >> 3;
501 width = bdim << 3;
Jens Arnold40919d72008-03-25 23:21:36 +0000502#else /* vertical packing or vertical interleaved */
503#if (LCD_DEPTH == 1) || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000504 bdim = (height + 7) >> 3;
505 height = bdim << 3;
506#elif LCD_DEPTH == 2
507 bdim = (height + 3) >> 2;
508 height = bdim << 2;
509#endif
510#endif
511
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000512 plane_size = _GREY_MULUQ(width, height);
Jens Arnold32bd0f82008-04-04 22:13:53 +0000513#if defined(CPU_COLDFIRE) /* Buffers should be line aligned */ \
514 || defined(CPU_PP) && (NUM_CORES > 1) /* Buffers must be cache line aligned */
515 plane_size += (-plane_size) & 0xf;
Jens Arnold6a56c142008-01-09 23:48:26 +0000516 buftaken = (-(long)gbuf) & 0xf;
Jens Arnold32bd0f82008-04-04 22:13:53 +0000517#else /* Buffers must be 32 bit aligned. */
518 buftaken = (-(long)gbuf) & 3;
Jens Arnold6a56c142008-01-09 23:48:26 +0000519#endif
520 gbuf += buftaken;
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000521
Jens Arnold8493f5b2008-03-02 23:31:09 +0000522 if (features & GREY_BUFFERED) /* chunky buffer */
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000523 {
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000524 _grey_info.buffer = gbuf;
Jens Arnold6a56c142008-01-09 23:48:26 +0000525 gbuf += plane_size;
526 buftaken += plane_size;
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000527 }
Jens Arnold32bd0f82008-04-04 22:13:53 +0000528#if NUM_CORES > 1 /* Values and phases must be uncached when running on COP */
529 if (features & GREY_ON_COP)
530 gbuf = UNCACHED_ADDR(gbuf);
531#endif
Jens Arnold6a56c142008-01-09 23:48:26 +0000532 _grey_info.values = gbuf;
533 gbuf += plane_size;
534 _grey_info.phases = gbuf;
Jens Arnold6a56c142008-01-09 23:48:26 +0000535 buftaken += 2 * plane_size;
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000536
Jens Arnold6a56c142008-01-09 23:48:26 +0000537 if (buftaken > gbuf_size)
538 return false;
Jens Arnolda72499a2008-01-13 00:11:43 +0000539
Jens Arnolddf5c3e12008-01-10 22:51:33 +0000540 /* Init to white */
Jens Arnolda72499a2008-01-13 00:11:43 +0000541 _grey_info.rb->memset(_grey_info.values, 0x80, plane_size);
542
Jens Arnoldfa7eb562008-01-13 18:39:09 +0000543#ifndef SIMULATOR
Jens Arnolddf5c3e12008-01-10 22:51:33 +0000544 /* Init phases with random bits */
Jens Arnold6a56c142008-01-09 23:48:26 +0000545 dst = (unsigned*)(_grey_info.phases);
546 end = (unsigned*)(_grey_info.phases + plane_size);
547
548 do
Jens Arnolda72499a2008-01-13 00:11:43 +0000549 *dst++ = _grey_info.rb->rand();
Jens Arnold6a56c142008-01-09 23:48:26 +0000550 while (dst < end);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000551#endif
552
553 _grey_info.x = 0;
554 _grey_info.y = 0;
555 _grey_info.width = width;
556 _grey_info.height = height;
557#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
558 _grey_info.bx = 0;
559 _grey_info.bwidth = bdim;
Jens Arnold40919d72008-03-25 23:21:36 +0000560#else /* vertical packing or vertical interleaved */
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000561 _grey_info.by = 0;
562 _grey_info.bheight = bdim;
563#endif
Jens Arnold5c87a982008-04-02 22:16:14 +0000564 _grey_info.flags = features & 0xff;
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000565 _grey_info.fg_brightness = 0;
566 _grey_info.bg_brightness = 255;
567 _grey_info.drawmode = DRMODE_SOLID;
568 _grey_info.curfont = FONT_SYSFIXED;
569
Jens Arnold6a56c142008-01-09 23:48:26 +0000570 /* precalculate the value -> pattern index conversion table, taking
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000571 linearisation and gamma correction into account */
Jens Arnold8493f5b2008-03-02 23:31:09 +0000572 if (features & GREY_RAWMAPPED)
Jens Arnold5c87a982008-04-02 22:16:14 +0000573 {
Jens Arnold8493f5b2008-03-02 23:31:09 +0000574 for (i = 0; i < 256; i++)
575 {
576 data = i << 7;
577 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8;
578 }
Jens Arnold5c87a982008-04-02 22:16:14 +0000579 }
Jens Arnold8493f5b2008-03-02 23:31:09 +0000580 else
Jens Arnold5c87a982008-04-02 22:16:14 +0000581 {
582#if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR)
Jens Arnold3183b9e2008-04-04 19:14:19 +0000583 if (_grey_info.rb->is_backlight_on(true))
584 _grey_info.flags |= _GREY_BACKLIGHT_ON;
Jens Arnold5c87a982008-04-02 22:16:14 +0000585#endif
586 fill_gvalues();
587 }
588
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000589 if (buf_taken) /* caller requested info about space taken */
590 *buf_taken = buftaken;
591
592 return true;
593}
594
595/* Release the greyscale display buffer and the library
596 DO CALL either this function or at least grey_show_display(false)
597 before you exit, otherwise nasty things may happen. */
598void grey_release(void)
599{
600 grey_show(false);
601}
602
603/* Switch the greyscale overlay on or off
604 DO NOT call lcd_update() or any other api function that directly accesses
605 the lcd while the greyscale overlay is running! If you need to do
606 lcd_update() to update something outside the greyscale overlay area, use
607 grey_deferred_update() instead.
608
609 Other functions to avoid are:
Jens Arnold68a21682008-03-24 00:35:53 +0000610 lcd_blit_mono(), lcd_update_rect(), lcd_set_contrast(),
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000611 lcd_set_invert_display(), lcd_set_flip() */
612void grey_show(bool enable)
613{
614 if (enable && !(_grey_info.flags & _GREY_RUNNING))
615 {
616 _grey_info.flags |= _GREY_RUNNING;
617#ifdef SIMULATOR
Jens Arnolda72499a2008-01-13 00:11:43 +0000618 _grey_info.rb->sim_lcd_ex_init(129, _grey_get_pixel);
Jens Arnoldfa7eb562008-01-13 18:39:09 +0000619 _grey_info.rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y,
620 _grey_info.width, _grey_info.height);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000621#else /* !SIMULATOR */
622#ifdef NEED_BOOST
Jens Arnolda72499a2008-01-13 00:11:43 +0000623 _grey_info.rb->cpu_boost(true);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000624#endif
Jens Arnold32bd0f82008-04-04 22:13:53 +0000625#if NUM_CORES > 1
626 _grey_info.rb->timer_register(1, NULL, TIMER_FREQ / LCD_SCANRATE,
627 1, _timer_isr,
628 (_grey_info.flags & GREY_ON_COP) ? COP : CPU);
629#else
Jens Arnold5c87a982008-04-02 22:16:14 +0000630 _grey_info.rb->timer_register(1, NULL, TIMER_FREQ / LCD_SCANRATE, 1,
Jens Arnold32bd0f82008-04-04 22:13:53 +0000631 _timer_isr);
632#endif
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000633#endif /* !SIMULATOR */
Jens Arnolda72499a2008-01-13 00:11:43 +0000634 _grey_info.rb->screen_dump_set_hook(grey_screendump_hook);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000635 }
636 else if (!enable && (_grey_info.flags & _GREY_RUNNING))
637 {
638#ifdef SIMULATOR
Jens Arnolda72499a2008-01-13 00:11:43 +0000639 _grey_info.rb->sim_lcd_ex_init(0, NULL);
Jens Arnold1d8312f2008-04-05 09:38:59 +0000640#else /* !SIMULATOR */
Jens Arnolda72499a2008-01-13 00:11:43 +0000641 _grey_info.rb->timer_unregister();
Jens Arnold1d8312f2008-04-05 09:38:59 +0000642#if NUM_CORES > 1 /* Make sure the ISR has finished before calling lcd_update() */
643 _grey_info.rb->sleep(HZ/100);
644#endif
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000645#ifdef NEED_BOOST
Jens Arnolda72499a2008-01-13 00:11:43 +0000646 _grey_info.rb->cpu_boost(false);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000647#endif
Jens Arnold1d8312f2008-04-05 09:38:59 +0000648#endif /* !SIMULATOR */
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000649 _grey_info.flags &= ~_GREY_RUNNING;
Jens Arnolda72499a2008-01-13 00:11:43 +0000650 _grey_info.rb->screen_dump_set_hook(NULL);
651 _grey_info.rb->lcd_update(); /* restore whatever there was before */
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000652 }
653}
654
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000655void grey_update_rect(int x, int y, int width, int height)
656{
Jens Arnoldfa7eb562008-01-13 18:39:09 +0000657 grey_ub_gray_bitmap_part(_grey_info.buffer, x, y, _grey_info.width,
658 x, y, width, height);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000659}
660
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000661/* Update the whole greyscale overlay */
662void grey_update(void)
663{
Jens Arnoldfa7eb562008-01-13 18:39:09 +0000664 grey_ub_gray_bitmap_part(_grey_info.buffer, 0, 0, _grey_info.width,
665 0, 0, _grey_info.width, _grey_info.height);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000666}
667
668/* Do an lcd_update() to show changes done by rb->lcd_xxx() functions
669 (in areas of the screen not covered by the greyscale overlay). */
670void grey_deferred_lcd_update(void)
671{
672 if (_grey_info.flags & _GREY_RUNNING)
673 {
674#ifdef SIMULATOR
675 _deferred_update();
676#else
677 _grey_info.flags |= _GREY_DEFERRED_UPDATE;
678#endif
679 }
680 else
Jens Arnolda72499a2008-01-13 00:11:43 +0000681 _grey_info.rb->lcd_update();
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000682}
683
684/*** Screenshot ***/
685
686#define BMP_FIXEDCOLORS (1 << LCD_DEPTH)
687#define BMP_VARCOLORS 129
688#define BMP_NUMCOLORS (BMP_FIXEDCOLORS + BMP_VARCOLORS)
689#define BMP_BPP 8
690#define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3)
691#define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
692#define BMP_DATASIZE (BMP_LINESIZE * LCD_HEIGHT)
693#define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
694
695#define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff
696#define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff
697
698static const unsigned char bmpheader[] =
699{
700 0x42, 0x4d, /* 'BM' */
701 LE32_CONST(BMP_TOTALSIZE), /* Total file size */
702 0x00, 0x00, 0x00, 0x00, /* Reserved */
703 LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */
704
705 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
706 LE32_CONST(LCD_WIDTH), /* Width in pixels */
707 LE32_CONST(LCD_HEIGHT), /* Height in pixels */
708 0x01, 0x00, /* Number of planes (always 1) */
709 LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */
710 0x00, 0x00, 0x00, 0x00, /* Compression mode, 0 = none */
711 LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */
712 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
713 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
714 LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */
715 LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */
716
717 /* Fixed colours */
718#if LCD_DEPTH == 1
719 0x90, 0xee, 0x90, 0x00, /* Colour #0 */
720 0x00, 0x00, 0x00, 0x00 /* Colour #1 */
721#elif LCD_DEPTH == 2
722 0xe6, 0xd8, 0xad, 0x00, /* Colour #0 */
723 0x99, 0x90, 0x73, 0x00, /* Colour #1 */
724 0x4c, 0x48, 0x39, 0x00, /* Colour #2 */
725 0x00, 0x00, 0x00, 0x00 /* Colour #3 */
726#endif
727};
728
729#if LCD_DEPTH == 1
Robert Kuklaff554e02008-04-08 15:04:26 +0000730#ifdef MROBE_100
731#define BMP_RED 241
732#define BMP_GREEN 6
733#define BMP_BLUE 3
734#define BMP_RED_BASE 94
735#define BMP_GREEN_BASE 2
736#define BMP_BLUE_BASE 2
Robert Kukla306652c2008-04-08 15:25:35 +0000737#else
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000738#define BMP_RED 0x90
739#define BMP_GREEN 0xee
740#define BMP_BLUE 0x90
Robert Kuklaff554e02008-04-08 15:04:26 +0000741#endif
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000742#elif LCD_DEPTH == 2
743#define BMP_RED 0xad
744#define BMP_GREEN 0xd8
745#define BMP_BLUE 0xe6
746#endif
747
748/* Hook function for core screen_dump() to save the current display
749 content (b&w and greyscale overlay) to an 8-bit BMP file. */
750static void grey_screendump_hook(int fd)
751{
752 int i;
753 int x, y, gx, gy;
754#if LCD_PIXELFORMAT == VERTICAL_PACKING
755#if LCD_DEPTH == 1
756 unsigned mask;
757#elif LCD_DEPTH == 2
758 int shift;
759#endif
Jens Arnold40919d72008-03-25 23:21:36 +0000760#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
761 unsigned data;
762 int shift;
763#endif /* LCD_PIXELFORMAT */
764 fb_data *lcdptr;
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000765 unsigned char *clut_entry;
766 unsigned char linebuf[MAX(4*BMP_VARCOLORS,BMP_LINESIZE)];
767
Jens Arnolda72499a2008-01-13 00:11:43 +0000768 _grey_info.rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000769
770 /* build clut */
Jens Arnolda72499a2008-01-13 00:11:43 +0000771 _grey_info.rb->memset(linebuf, 0, 4*BMP_VARCOLORS);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000772 clut_entry = linebuf;
773
774 for (i = 0; i <= 128; i++)
775 {
Robert Kuklaff554e02008-04-08 15:04:26 +0000776#ifdef MROBE_100
777 *clut_entry++ = (_GREY_MULUQ(BMP_BLUE-BMP_BLUE_BASE, i) >> 7) +
778 BMP_BLUE_BASE;
779 *clut_entry++ = (_GREY_MULUQ(BMP_GREEN-BMP_GREEN_BASE, i) >> 7) +
780 BMP_GREEN_BASE;
781 *clut_entry++ = (_GREY_MULUQ(BMP_RED-BMP_RED_BASE, i) >> 7) +
782 BMP_RED_BASE;
783#else
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000784 *clut_entry++ = _GREY_MULUQ(BMP_BLUE, i) >> 7;
785 *clut_entry++ = _GREY_MULUQ(BMP_GREEN, i) >> 7;
786 *clut_entry++ = _GREY_MULUQ(BMP_RED, i) >> 7;
Robert Kuklaff554e02008-04-08 15:04:26 +0000787#endif
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000788 clut_entry++;
789 }
Jens Arnolda72499a2008-01-13 00:11:43 +0000790 _grey_info.rb->write(fd, linebuf, 4*BMP_VARCOLORS);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000791
792 /* BMP image goes bottom -> top */
793 for (y = LCD_HEIGHT - 1; y >= 0; y--)
794 {
Jens Arnolda72499a2008-01-13 00:11:43 +0000795 _grey_info.rb->memset(linebuf, 0, BMP_LINESIZE);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000796
797 gy = y - _grey_info.y;
798#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
799#if LCD_DEPTH == 2
Jens Arnolda72499a2008-01-13 00:11:43 +0000800 lcdptr = _grey_info.rb->lcd_framebuffer + _GREY_MULUQ(LCD_FBWIDTH, y);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000801
802 for (x = 0; x < LCD_WIDTH; x += 4)
803 {
804 gx = x - _grey_info.x;
805
806 if (((unsigned)gy < (unsigned)_grey_info.height)
807 && ((unsigned)gx < (unsigned)_grey_info.width))
808 {
Jens Arnold6a56c142008-01-09 23:48:26 +0000809 unsigned char *src = _grey_info.values
810 + _GREY_MULUQ(_grey_info.width, gy) + gx;
Jens Arnolddf5c3e12008-01-10 22:51:33 +0000811 for (i = 0; i < 4; i++)
812 linebuf[x + i] = BMP_FIXEDCOLORS + *src++;
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000813 }
814 else
815 {
816 unsigned data = *lcdptr;
817 linebuf[x] = (data >> 6) & 3;
818 linebuf[x + 1] = (data >> 4) & 3;
819 linebuf[x + 2] = (data >> 2) & 3;
820 linebuf[x + 3] = data & 3;
821 }
822 lcdptr++;
823 }
824#endif /* LCD_DEPTH */
Jens Arnold40919d72008-03-25 23:21:36 +0000825#elif LCD_PIXELFORMAT == VERTICAL_PACKING
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000826#if LCD_DEPTH == 1
827 mask = 1 << (y & 7);
Jens Arnolda72499a2008-01-13 00:11:43 +0000828 lcdptr = _grey_info.rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000829
830 for (x = 0; x < LCD_WIDTH; x++)
831 {
832 gx = x - _grey_info.x;
833
834 if (((unsigned)gy < (unsigned)_grey_info.height)
835 && ((unsigned)gx < (unsigned)_grey_info.width))
836 {
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000837 linebuf[x] = BMP_FIXEDCOLORS
Jens Arnold6a56c142008-01-09 23:48:26 +0000838 + _grey_info.values[_GREY_MULUQ(_grey_info.width,
Jens Arnolda72499a2008-01-13 00:11:43 +0000839 gy & ~_GREY_BMASK)
840 + (gx << _GREY_BSHIFT)
Jens Arnolddf5c3e12008-01-10 22:51:33 +0000841 + (~gy & _GREY_BMASK)];
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000842 }
843 else
844 {
845 linebuf[x] = (*lcdptr & mask) ? 1 : 0;
846 }
847 lcdptr++;
848 }
849#elif LCD_DEPTH == 2
850 shift = 2 * (y & 3);
Jens Arnolda72499a2008-01-13 00:11:43 +0000851 lcdptr = _grey_info.rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 2);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000852
853 for (x = 0; x < LCD_WIDTH; x++)
854 {
855 gx = x - _grey_info.x;
856
857 if (((unsigned)gy < (unsigned)_grey_info.height)
858 && ((unsigned)gx < (unsigned)_grey_info.width))
859 {
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000860 linebuf[x] = BMP_FIXEDCOLORS
Jens Arnold6a56c142008-01-09 23:48:26 +0000861 + _grey_info.values[_GREY_MULUQ(_grey_info.width,
Jens Arnolddf5c3e12008-01-10 22:51:33 +0000862 gy & ~_GREY_BMASK)
863 + (gx << _GREY_BSHIFT)
864 + (~gy & _GREY_BMASK)];
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000865 }
866 else
867 {
868 linebuf[x] = (*lcdptr >> shift) & 3;
869 }
870 lcdptr++;
871 }
872#endif /* LCD_DEPTH */
Jens Arnold40919d72008-03-25 23:21:36 +0000873#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
874#if LCD_DEPTH == 2
875 shift = y & 7;
876 lcdptr = _grey_info.rb->lcd_framebuffer + _GREY_MULUQ(LCD_WIDTH, y >> 3);
877
878 for (x = 0; x < LCD_WIDTH; x++)
879 {
880 gx = x - _grey_info.x;
881
882 if (((unsigned)gy < (unsigned)_grey_info.height)
883 && ((unsigned)gx < (unsigned)_grey_info.width))
884 {
885 linebuf[x] = BMP_FIXEDCOLORS
886 + _grey_info.values[_GREY_MULUQ(_grey_info.width,
887 gy & ~_GREY_BMASK)
888 + (gx << _GREY_BSHIFT)
889 + (~gy & _GREY_BMASK)];
890 }
891 else
892 {
893 data = (*lcdptr >> shift) & 0x0101;
894 linebuf[x] = ((data >> 7) | data) & 3;
895 }
896 lcdptr++;
897 }
898#endif /* LCD_DEPTH */
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000899#endif /* LCD_PIXELFORMAT */
900
Jens Arnolda72499a2008-01-13 00:11:43 +0000901 _grey_info.rb->write(fd, linebuf, BMP_LINESIZE);
Jens Arnoldfeb5b152008-01-04 23:42:38 +0000902 }
903}