diff options
author | Daniel Stenberg <daniel@haxx.se> | 2002-04-11 12:37:49 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2002-04-11 12:37:49 +0000 |
commit | 369ba01afd31d021f16f5c8b68e773f043101ca0 (patch) | |
tree | 0a49bfcb87eaf27506c520bc5e97d34ce0a72d74 /firmware | |
parent | d04a6724dcf671c399e19d5061ddd2ae13c74bd1 (diff) | |
download | rockbox-369ba01afd31d021f16f5c8b68e773f043101ca0.tar.gz rockbox-369ba01afd31d021f16f5c8b68e773f043101ca0.zip |
incorporated Gary's bitmap LCD code, supports SIMULATOR. Seems to work.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@77 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/lcd.c | 356 |
1 files changed, 320 insertions, 36 deletions
diff --git a/firmware/lcd.c b/firmware/lcd.c index 5563bbe881..e8716a95fc 100644 --- a/firmware/lcd.c +++ b/firmware/lcd.c | |||
@@ -20,26 +20,41 @@ | |||
20 | #include "lcd.h" | 20 | #include "lcd.h" |
21 | 21 | ||
22 | void lcd_data (int data) | 22 | void lcd_data (int data) |
23 | { lcd_byte (data,1); } | 23 | { |
24 | lcd_byte (data,1); | ||
25 | } | ||
24 | 26 | ||
25 | void lcd_instruction (int instruction) | 27 | void lcd_instruction (int instruction) |
26 | { lcd_byte (instruction,0); } | 28 | { |
29 | lcd_byte (instruction,0); | ||
30 | } | ||
27 | 31 | ||
28 | void lcd_zero (int length) | 32 | void lcd_zero (int length) |
29 | { length *= 8; while (--length >= 0) lcd_data (0); } | 33 | { |
34 | length *= 8; | ||
35 | while (--length >= 0) | ||
36 | lcd_data (0); | ||
37 | } | ||
30 | 38 | ||
31 | void lcd_fill (int data,int length) | 39 | void lcd_fill (int data,int length) |
32 | { length *= 8; while (--length >= 0) lcd_data (data); } | 40 | { |
41 | length *= 8; | ||
42 | while (--length >= 0) | ||
43 | lcd_data (data); | ||
44 | } | ||
33 | 45 | ||
34 | void lcd_copy (void *data,int count) | 46 | void lcd_copy (void *data,int count) |
35 | { while (--count >= 0) lcd_data (*((char *)data)++); } | 47 | { |
48 | while (--count >= 0) | ||
49 | lcd_data (*((char *)data)++); | ||
50 | } | ||
36 | 51 | ||
37 | 52 | ||
38 | #ifdef JBP | 53 | #ifdef HAVE_LCD_CHARCELLS |
39 | # ifndef JBP_OLD | 54 | # ifndef JBP_OLD |
40 | 55 | ||
41 | static char const lcd_ascii[] = | 56 | static char const lcd_ascii[] = |
42 | { | 57 | { |
43 | /*****************************************************************************************/ | 58 | /*****************************************************************************************/ |
44 | /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ | 59 | /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ |
45 | /* ************************************************************************************/ | 60 | /* ************************************************************************************/ |
@@ -91,45 +106,314 @@ static char const lcd_ascii[] = | |||
91 | # endif | 106 | # endif |
92 | 107 | ||
93 | void lcd_puts (char const *string) | 108 | void lcd_puts (char const *string) |
94 | { | 109 | { |
95 | while (*string) | 110 | while (*string) |
96 | lcd_data (LCD_ASCII(*string++)); | 111 | lcd_data (LCD_ASCII(*string++)); |
97 | } | 112 | } |
98 | 113 | ||
99 | void lcd_putns (char const *string,int n) | 114 | void lcd_putns (char const *string,int n) |
100 | { | 115 | { |
101 | while (n--) | 116 | while (n--) |
102 | lcd_data (LCD_ASCII(*string++)); | 117 | lcd_data (LCD_ASCII(*string++)); |
103 | } | 118 | } |
104 | 119 | ||
105 | void lcd_putc (int character) | 120 | void lcd_putc (int character) |
106 | { | 121 | { |
107 | lcd_data (LCD_ASCII(character)); | 122 | lcd_data (LCD_ASCII(character)); |
108 | } | 123 | } |
109 | 124 | ||
110 | void lcd_pattern (int which,char const *pattern,int count) | 125 | void lcd_pattern (int which,char const *pattern,int count) |
126 | { | ||
127 | lcd_instruction (LCD_PRAM|which); | ||
128 | lcd_copy ((void *)pattern,count); | ||
129 | } | ||
130 | |||
131 | void lcd_puthex (unsigned int value,int digits) | ||
132 | { | ||
133 | switch (digits) { | ||
134 | case 8: | ||
135 | lcd_puthex (value >> 16,4); | ||
136 | case 4: | ||
137 | lcd_puthex (value >> 8,2); | ||
138 | case 2: | ||
139 | lcd_puthex (value >> 4,1); | ||
140 | case 1: | ||
141 | value &= 15; | ||
142 | lcd_putc (value+((value < 10) ? '0' : ('A'-10))); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | |||
147 | /* HAVE_LCD_CHARCELLS */ | ||
148 | #elif defined(HAVE_LCD_BITMAP) | ||
149 | |||
150 | /* | ||
151 | * All bitmaps have this format: | ||
152 | * Bits within a byte are arranged veritcally, LSB at top. | ||
153 | * Bytes are stored in column-major format, with byte 0 at top left, | ||
154 | * byte 1 is 2nd from top, etc. Bytes following left-most column | ||
155 | * starts 2nd left column, etc. | ||
156 | * | ||
157 | * Note: The HW takes bitmap bytes in row-major order. | ||
158 | * | ||
159 | * Memory copy of display bitmap | ||
160 | */ | ||
161 | unsigned char display[DISP_X][DISP_Y/8]; | ||
162 | |||
163 | // | ||
164 | // ASCII character generation tables | ||
165 | // | ||
166 | // This contains only the printable characters (0x20-0x7f). | ||
167 | // Each element in this table is a character pattern bitmap. | ||
168 | // | ||
169 | #define ASCII_MIN 0x20 // First char in table | ||
170 | #define ASCII_MAX 0x7f // Last char in table | ||
171 | |||
172 | extern const unsigned char char_gen_6x8[][5][1]; | ||
173 | extern const unsigned char char_gen_8x12[][7][2]; | ||
174 | extern const unsigned char char_gen_12x16[][11][2]; | ||
175 | |||
176 | |||
177 | /* All zeros and ones bitmaps for area filling */ | ||
178 | static const unsigned char zeros[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
179 | 0x00, 0x00 }; | ||
180 | static const unsigned char ones[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
181 | 0xff, 0xff }; | ||
182 | |||
183 | static int lcd_y; /* Current pixel row */ | ||
184 | static int lcd_x; /* Current pixel column */ | ||
185 | static int lcd_size; /* Current font width */ | ||
186 | |||
187 | #ifndef SIMULATOR | ||
188 | |||
189 | /* | ||
190 | * Initialize LCD | ||
191 | */ | ||
192 | void lcd_init (void) | ||
193 | { | ||
194 | // Initialize PB0-3 as output pins | ||
195 | PBCR2 &= 0xff00; // MD = 00 | ||
196 | PBIOR |= 0x000f; // IOR = 1 | ||
197 | |||
198 | // Initialize LCD | ||
199 | lcd_write (TRUE, LCD_CNTL_RESET); | ||
200 | lcd_write (TRUE, LCD_CNTL_POWER); | ||
201 | lcd_write (TRUE, LCD_CNTL_SEGREMAP); | ||
202 | lcd_write (TRUE, LCD_CNTL_OUTSCAN); | ||
203 | lcd_write (TRUE, LCD_CNTL_CONTRAST); | ||
204 | lcd_write (TRUE, 0x30); // Contrast parameter | ||
205 | lcd_write (TRUE, LCD_CNTL_DISPON); | ||
206 | |||
207 | lcd_clear_display(); | ||
208 | lcd_update(); | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Update the display. | ||
213 | * This must be called after all other LCD funtions that change the display. | ||
214 | */ | ||
215 | void lcd_update (void) | ||
216 | { | ||
217 | int x, y; | ||
218 | |||
219 | /* Copy display bitmap to hardware */ | ||
220 | for (y = 0; y < DISP_Y/8; y++) | ||
111 | { | 221 | { |
112 | lcd_instruction (LCD_PRAM|which); | 222 | lcd_write (TRUE, LCD_CNTL_PAGE | (y & 0xf)); |
113 | lcd_copy ((void *)pattern,count); | 223 | lcd_write (TRUE, LCD_CNTL_HIGHCOL); |
224 | lcd_write (TRUE, LCD_CNTL_LOWCOL); | ||
225 | |||
226 | for (x = 0; x < DISP_X; x++) | ||
227 | lcd_write (FALSE, display[x][y]); | ||
114 | } | 228 | } |
229 | } | ||
115 | 230 | ||
116 | #else | 231 | static void lcd_write (BOOL command, int value) |
117 | # error "JBR : FIX ME" | 232 | { |
118 | #endif | 233 | int bit; |
119 | 234 | ||
120 | void lcd_puthex (unsigned int value,int digits) | 235 | /* Enable chip select, set DC if data */ |
236 | PBDR &= ~(PBDR_LCD_CS1|PBDR_LCD_DC); | ||
237 | if (!command) | ||
238 | PBDR |= PBDR_LCD_DC; | ||
239 | |||
240 | /* Send each bit, starting with MSB */ | ||
241 | for (bit = 0x80; bit > 0; bit >>= 1) | ||
121 | { | 242 | { |
122 | switch (digits) | 243 | PBDR &= ~(PBDR_LCD_SDA|PBDR_LCD_SCK); |
123 | { | 244 | if (value & bit) |
124 | case 8: | 245 | PBDR |= PBDR_LCD_SDA; |
125 | lcd_puthex (value >> 16,4); | 246 | PBDR |= PBDR_LCD_SCK; |
126 | case 4: | ||
127 | lcd_puthex (value >> 8,2); | ||
128 | case 2: | ||
129 | lcd_puthex (value >> 4,1); | ||
130 | case 1: | ||
131 | value &= 15; | ||
132 | lcd_putc (value+((value < 10) ? '0' : ('A'-10))); | ||
133 | } | ||
134 | } | 247 | } |
248 | |||
249 | /* Disable chip select */ | ||
250 | PBDR |= PBDR_LCD_CS1; | ||
251 | } | ||
252 | |||
253 | #endif /* SIMULATOR */ | ||
254 | |||
255 | /* | ||
256 | * Clear the display | ||
257 | */ | ||
258 | void lcd_clear_display (void) | ||
259 | { | ||
260 | lcd_position (0, 0, 8); | ||
261 | memset (display, 0, sizeof display); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Set current x,y position and font size | ||
266 | */ | ||
267 | void lcd_position (int x, int y, int size) | ||
268 | { | ||
269 | if (x >= 0 && x < DISP_X && y >= 0 && y < DISP_Y) | ||
270 | { | ||
271 | lcd_x = x; | ||
272 | lcd_y = y; | ||
273 | } | ||
274 | |||
275 | lcd_size = size; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * Display a string at current position and size | ||
280 | */ | ||
281 | void lcd_string (const char *str) | ||
282 | { | ||
283 | int x = lcd_x; | ||
284 | int nx = lcd_size; | ||
285 | int ny, ch; | ||
286 | const unsigned char *src; | ||
287 | |||
288 | if (nx == 12) | ||
289 | ny = 16; | ||
290 | else if (nx == 8) | ||
291 | ny = 12; | ||
292 | else | ||
293 | { | ||
294 | nx = 6; | ||
295 | ny = 8; | ||
296 | } | ||
297 | |||
298 | while ((ch = *str++) != '\0') | ||
299 | { | ||
300 | if (ch == '\n' || lcd_x + nx > DISP_X) | ||
301 | { | ||
302 | /* Wrap to next line */ | ||
303 | lcd_x = x; | ||
304 | lcd_y += ny; | ||
305 | } | ||
306 | |||
307 | if (lcd_y + ny > DISP_Y) | ||
308 | return; | ||
309 | |||
310 | /* Limit to char generation table */ | ||
311 | if (ch >= ASCII_MIN && ch <= ASCII_MAX) | ||
312 | { | ||
313 | if (nx == 12) | ||
314 | src = char_gen_12x16[ch-ASCII_MIN][0]; | ||
315 | else if (nx == 8) | ||
316 | src = char_gen_8x12[ch-ASCII_MIN][0]; | ||
317 | else | ||
318 | src = char_gen_6x8[ch-ASCII_MIN][0]; | ||
319 | |||
320 | lcd_bitmap (src, lcd_x, lcd_y, nx-1, ny, TRUE); | ||
321 | lcd_bitmap (zeros, lcd_x+nx-1, lcd_y, 1, ny, TRUE); | ||
322 | |||
323 | lcd_x += nx; | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Display a bitmap at (x, y), size (nx, ny) | ||
330 | * clear is TRUE to clear destination area first | ||
331 | */ | ||
332 | void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, | ||
333 | bool clear) | ||
334 | { | ||
335 | unsigned char *dst; | ||
336 | unsigned char *dst2 = &display[x][y/8]; | ||
337 | unsigned int data, mask, mask2, mask3, mask4; | ||
338 | int shift = y & 7; | ||
339 | |||
340 | ny += shift; | ||
341 | |||
342 | /* Calculate bit masks */ | ||
343 | mask4 = ~(0xfe << ((ny-1) & 7)); | ||
344 | if (clear) | ||
345 | { | ||
346 | mask = ~(0xff << shift); | ||
347 | mask2 = 0; | ||
348 | mask3 = ~mask4; | ||
349 | if (ny <= 8) | ||
350 | mask3 |= mask; | ||
351 | } | ||
352 | else | ||
353 | mask = mask2 = mask3 = 0xff; | ||
354 | |||
355 | /* Loop for each column */ | ||
356 | for (x = 0; x < nx; x++) | ||
357 | { | ||
358 | dst = dst2; | ||
359 | dst2 += DISP_Y/8; | ||
360 | data = 0; | ||
361 | y = 0; | ||
362 | |||
363 | if (ny > 8) | ||
364 | { | ||
365 | /* First partial row */ | ||
366 | data = *src++ << shift; | ||
367 | *dst = (*dst & mask) ^ data; | ||
368 | data >>= 8; | ||
369 | dst++; | ||
370 | |||
371 | /* Intermediate rows */ | ||
372 | for (y = 8; y < ny-8; y += 8) | ||
373 | { | ||
374 | data |= *src++ << shift; | ||
375 | *dst = (*dst & mask2) ^ data; | ||
376 | data >>= 8; | ||
377 | dst++; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* Last partial row */ | ||
382 | if (y + shift < ny) | ||
383 | data |= *src++ << shift; | ||
384 | *dst = (*dst & mask3) ^ (data & mask4); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | /* | ||
389 | * Clear a rectangular area at (x, y), size (nx, ny) | ||
390 | */ | ||
391 | void lcd_clearrect (int x, int y, int nx, int ny) | ||
392 | { | ||
393 | int i; | ||
394 | for (i = 0; i < nx; i++) | ||
395 | lcd_bitmap (zeros, x+i, y, 1, ny, TRUE); | ||
396 | } | ||
397 | |||
398 | /* | ||
399 | * Fill a rectangular area at (x, y), size (nx, ny) | ||
400 | */ | ||
401 | void lcd_fillrect (int x, int y, int nx, int ny) | ||
402 | { | ||
403 | int i; | ||
404 | for (i = 0; i < nx; i++) | ||
405 | lcd_bitmap (ones, x+i, y, 1, ny, TRUE); | ||
406 | } | ||
407 | |||
408 | /* Invert a rectangular area at (x, y), size (nx, ny) */ | ||
409 | void lcd_invertrect (int x, int y, int nx, int ny) | ||
410 | { | ||
411 | int i; | ||
412 | for (i = 0; i < nx; i++) | ||
413 | lcd_bitmap (ones, x+i, y, 1, ny, FALSE); | ||
414 | } | ||
415 | |||
416 | #else | ||
417 | /* no LCD defined, no code to use */ | ||
418 | #endif | ||
135 | 419 | ||