summaryrefslogtreecommitdiff
path: root/firmware/lcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/lcd.c')
-rw-r--r--firmware/lcd.c496
1 files changed, 330 insertions, 166 deletions
diff --git a/firmware/lcd.c b/firmware/lcd.c
index 64d52addcf..5d31529ec0 100644
--- a/firmware/lcd.c
+++ b/firmware/lcd.c
@@ -18,39 +18,203 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19 19
20#include "config.h" 20#include "config.h"
21
22#include "lcd.h" 21#include "lcd.h"
23 22
23#ifndef SIMULATOR
24/*
25 * About /CS,DS,SC,SD
26 * ------------------
27 *
28 * LCD on JBP and JBR uses a SPI protocol to receive orders (SDA and SCK lines)
29 *
30 * - /CS -> Chip Selection line :
31 * 0 : LCD chipset is activated.
32 * - DS -> Data Selection line, latched at the rising edge
33 * of the 8th serial clock (*) :
34 * 0 : instruction register,
35 * 1 : data register;
36 * - SC -> Serial Clock line (SDA).
37 * - SD -> Serial Data line (SCK), latched at the rising edge
38 * of each serial clock (*).
39 *
40 * _ _
41 * /CS \ /
42 * \______________________________________________________/
43 * _____ ____ ____ ____ ____ ____ ____ ____ ____ _____
44 * SD \/ D7 \/ D6 \/ D5 \/ D4 \/ D3 \/ D2 \/ D1 \/ D0 \/
45 * _____/\____/\____/\____/\____/\____/\____/\____/\____/\_____
46 *
47 * _____ _ _ _ _ _ _ _ ________
48 * SC \ * \ * \ * \ * \ * \ * \ * \ *
49 * \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
50 * _ _________________________________________________________
51 * DS \/
52 * _/\_________________________________________________________
53 *
54 */
55
56/*
57 * The only way to do logical operations in an atomic way
58 * on SH1 is using :
59 *
60 * or.b/and.b/tst.b/xor.b #imm,@(r0,gbr)
61 *
62 * but GCC doesn't generate them at all so some assembly
63 * codes are needed here.
64 *
65 * The Global Base Register gbr is expected to be zero
66 * and r0 is the address of one register in the on-chip
67 * peripheral module.
68 *
69 */
70
71 /*
72 * Enter a LCD session :
73 *
74 * QI(LCDR) &= ~(LCD_CS|LCD_DS|LCD_SD|LCD_SC);
75 */
76static void lcd_start (void)
77{
78 asm
79 ("and.b\t%0,@(r0,gbr)"
80 :
81 : /* %0 */ "I"(~(LCD_CS|LCD_DS|LCD_SD|LCD_SC)),
82 /* %1 */ "z"(LCDR));
83}
84
85 /*
86 * Leave a LCD session :
87 *
88 * QI(LCDR) |= LCD_CS|LCD_RS|LCD_SD|LCD_SC;
89 */
90static void lcd_stop (void)
91{
92 asm
93 ("or.b\t%0,@(r0,gbr)"
94 :
95 : /* %0 */ "I"(LCD_CS|LCD_DS|LCD_SD|LCD_SC),
96 /* %1 */ "z"(LCDR));
97}
98
99static void lcd_byte (int byte,int rs)
100 /*
101 * char j = 0x80;
102 * if (rs)
103 * do
104 * {
105 * QI(LCDR) &= ~(LCD_SC|LCD_SD);
106 * if (j & byte)
107 * QI(LCDR) |= LCD_SD;
108 * QI(LCDR) |= LCD_SC|LCD_DS;
109 * }
110 * while ((unsigned char)j >>= 1);
111 * else
112 * do
113 * {
114 * QI(LCDR) &= ~(LCD_SC|LCD_SD|LCD_DS);
115 * if (j & byte)
116 * QI(LCDR) |= LCD_SD;
117 * QI(LCDR) |= LCD_SC;
118 * }
119 * while ((unsigned char)j >>= 1);
120 */
121{
122 if (rs > 0)
123 asm
124 ("shll8\t%0\n"
125 "0:\n\t"
126 "and.b\t%2,@(r0,gbr)\n\t"
127 "shll\t%0\n\t"
128 "bf\t1f\n\t"
129 "or.b\t%3,@(r0,gbr)\n"
130 "1:\n\t"
131 "or.b\t%4,@(r0,gbr)\n"
132 "add\t#-1,%1\n\t"
133 "cmp/pl\t%1\n\t"
134 "bt\t0b"
135 :
136 : /* %0 */ "r"(((unsigned)byte)<<16),
137 /* %1 */ "r"(8),
138 /* %2 */ "I"(~(LCD_SC|LCD_SD)),
139 /* %3 */ "I"(LCD_SD),
140 /* %4 */ "I"(LCD_SC|LCD_DS),
141 /* %5 */ "z"(LCDR));
142 else
143 asm
144 ("shll8\t%0\n"
145 "0:\n\t"
146 "and.b\t%2,@(r0,gbr)\n\t"
147 "shll\t%0\n\t"
148 "bf\t1f\n\t"
149 "or.b\t%3,@(r0,gbr)\n"
150 "1:\n\t"
151 "or.b\t%4,@(r0,gbr)\n"
152 "add\t#-1,%1\n\t"
153 "cmp/pl\t%1\n\t"
154 "bt\t0b"
155 :
156 : /* %0 */ "r"(((unsigned)byte)<<16),
157 /* %1 */ "r"(8),
158 /* %2 */ "I"(~(LCD_SC|LCD_DS|LCD_SD)),
159 /* %3 */ "I"(LCD_SD),
160 /* %4 */ "I"(LCD_SC),
161 /* %5 */ "z"(LCDR));
162}
163
24void lcd_data (int data) 164void lcd_data (int data)
25{ 165{
26 lcd_byte (data,1); 166 lcd_byte (data,1);
27} 167}
28 168
29void lcd_instruction (int instruction) 169void lcd_instruction (int instruction)
30{ 170{
31 lcd_byte (instruction,0); 171 lcd_byte (instruction,0);
32} 172}
33 173
34void lcd_zero (int length) 174void lcd_zero (int length)
35{ 175{
36 length *= 8; 176 length *= 8;
37 while (--length >= 0) 177 while (--length >= 0)
38 lcd_data (0); 178 lcd_data (0);
39} 179}
40 180
41void lcd_fill (int data,int length) 181void lcd_fill (int data,int length)
42{ 182{
43 length *= 8; 183 length *= 8;
44 while (--length >= 0) 184 while (--length >= 0)
45 lcd_data (data); 185 lcd_data (data);
46} 186}
47 187
48void lcd_copy (void *data,int count) 188void lcd_copy (void *data,int count)
49{ 189{
50 while (--count >= 0) 190 while (--count >= 0)
51 lcd_data (*((char *)data)++); 191 lcd_data (*((char *)data)++);
52} 192}
53 193
194static void lcd_goto (int x,int y)
195{
196 lcd_instruction (LCD_CURSOR(x,y));
197}
198
199/*** BACKLIGHT ***/
200
201static void lcd_toggle_backlight (void)
202{
203 PAIOR ^= LCD_BL;
204}
205
206static void lcd_turn_on_backlight (void)
207{
208 PAIOR |= LCD_BL;
209}
210
211static void lcd_turn_off_backlight (void)
212{
213 PAIOR &= ~LCD_BL;
214}
215
216/*** ICONS ***/
217#endif
54 218
55#ifdef HAVE_LCD_CHARCELLS 219#ifdef HAVE_LCD_CHARCELLS
56# ifndef JBP_OLD 220# ifndef JBP_OLD
@@ -109,40 +273,40 @@ static char const lcd_ascii[] =
109 273
110void lcd_puts (char const *string) 274void lcd_puts (char const *string)
111{ 275{
112 while (*string) 276 while (*string)
113 lcd_data (LCD_ASCII(*string++)); 277 lcd_data (LCD_ASCII(*string++));
114} 278}
115 279
116void lcd_putns (char const *string,int n) 280void lcd_putns (char const *string,int n)
117{ 281{
118 while (n--) 282 while (n--)
119 lcd_data (LCD_ASCII(*string++)); 283 lcd_data (LCD_ASCII(*string++));
120} 284}
121 285
122void lcd_putc (int character) 286void lcd_putc (int character)
123{ 287{
124 lcd_data (LCD_ASCII(character)); 288 lcd_data (LCD_ASCII(character));
125} 289}
126 290
127void lcd_pattern (int which,char const *pattern,int count) 291void lcd_pattern (int which,char const *pattern,int count)
128{ 292{
129 lcd_instruction (LCD_PRAM|which); 293 lcd_instruction (LCD_PRAM|which);
130 lcd_copy ((void *)pattern,count); 294 lcd_copy ((void *)pattern,count);
131} 295}
132 296
133void lcd_puthex (unsigned int value,int digits) 297void lcd_puthex (unsigned int value,int digits)
134{ 298{
135 switch (digits) { 299 switch (digits) {
136 case 8: 300 case 8:
137 lcd_puthex (value >> 16,4); 301 lcd_puthex (value >> 16,4);
138 case 4: 302 case 4:
139 lcd_puthex (value >> 8,2); 303 lcd_puthex (value >> 8,2);
140 case 2: 304 case 2:
141 lcd_puthex (value >> 4,1); 305 lcd_puthex (value >> 4,1);
142 case 1: 306 case 1:
143 value &= 15; 307 value &= 15;
144 lcd_putc (value+((value < 10) ? '0' : ('A'-10))); 308 lcd_putc (value+((value < 10) ? '0' : ('A'-10)));
145 } 309 }
146} 310}
147 311
148 312
@@ -216,40 +380,40 @@ void lcd_init (void)
216 */ 380 */
217void lcd_update (void) 381void lcd_update (void)
218{ 382{
219 int x, y; 383 int x, y;
220 384
221 /* Copy display bitmap to hardware */ 385 /* Copy display bitmap to hardware */
222 for (y = 0; y < DISP_Y/8; y++) 386 for (y = 0; y < DISP_Y/8; y++)
223 { 387 {
224 lcd_write (TRUE, LCD_CNTL_PAGE | (y & 0xf)); 388 lcd_write (TRUE, LCD_CNTL_PAGE | (y & 0xf));
225 lcd_write (TRUE, LCD_CNTL_HIGHCOL); 389 lcd_write (TRUE, LCD_CNTL_HIGHCOL);
226 lcd_write (TRUE, LCD_CNTL_LOWCOL); 390 lcd_write (TRUE, LCD_CNTL_LOWCOL);
227 391
228 for (x = 0; x < DISP_X; x++) 392 for (x = 0; x < DISP_X; x++)
229 lcd_write (FALSE, display[x][y]); 393 lcd_write (FALSE, display[x][y]);
230 } 394 }
231} 395}
232 396
233static void lcd_write (BOOL command, int value) 397static void lcd_write (bool command, int value)
234{ 398{
235 int bit; 399 int bit;
236 400
237 /* Enable chip select, set DC if data */ 401 /* Enable chip select, set DC if data */
238 PBDR &= ~(PBDR_LCD_CS1|PBDR_LCD_DC); 402 PBDR &= ~(PBDR_LCD_CS1|PBDR_LCD_DC);
239 if (!command) 403 if (!command)
240 PBDR |= PBDR_LCD_DC; 404 PBDR |= PBDR_LCD_DC;
241 405
242 /* Send each bit, starting with MSB */ 406 /* Send each bit, starting with MSB */
243 for (bit = 0x80; bit > 0; bit >>= 1) 407 for (bit = 0x80; bit > 0; bit >>= 1)
244 { 408 {
245 PBDR &= ~(PBDR_LCD_SDA|PBDR_LCD_SCK); 409 PBDR &= ~(PBDR_LCD_SDA|PBDR_LCD_SCK);
246 if (value & bit) 410 if (value & bit)
247 PBDR |= PBDR_LCD_SDA; 411 PBDR |= PBDR_LCD_SDA;
248 PBDR |= PBDR_LCD_SCK; 412 PBDR |= PBDR_LCD_SCK;
249 } 413 }
250 414
251 /* Disable chip select */ 415 /* Disable chip select */
252 PBDR |= PBDR_LCD_CS1; 416 PBDR |= PBDR_LCD_CS1;
253} 417}
254 418
255#endif /* SIMULATOR */ 419#endif /* SIMULATOR */
@@ -259,8 +423,8 @@ static void lcd_write (BOOL command, int value)
259 */ 423 */
260void lcd_clear_display (void) 424void lcd_clear_display (void)
261{ 425{
262 lcd_position (0, 0, 8); 426 lcd_position (0, 0, 8);
263 memset (display, 0, sizeof display); 427 memset (display, 0, sizeof display);
264} 428}
265 429
266/* 430/*
@@ -268,13 +432,13 @@ void lcd_clear_display (void)
268 */ 432 */
269void lcd_position (int x, int y, int size) 433void lcd_position (int x, int y, int size)
270{ 434{
271 if (x >= 0 && x < DISP_X && y >= 0 && y < DISP_Y) 435 if (x >= 0 && x < DISP_X && y >= 0 && y < DISP_Y)
272 { 436 {
273 lcd_x = x; 437 lcd_x = x;
274 lcd_y = y; 438 lcd_y = y;
275 } 439 }
276 440
277 lcd_size = size; 441 lcd_size = size;
278} 442}
279 443
280/* 444/*
@@ -282,49 +446,49 @@ void lcd_position (int x, int y, int size)
282 */ 446 */
283void lcd_string (const char *str) 447void lcd_string (const char *str)
284{ 448{
285 int x = lcd_x; 449 int x = lcd_x;
286 int nx = lcd_size; 450 int nx = lcd_size;
287 int ny, ch; 451 int ny, ch;
288 const unsigned char *src; 452 const unsigned char *src;
289 453
290 if (nx == 12) 454 if (nx == 12)
291 ny = 16; 455 ny = 16;
292 else if (nx == 8) 456 else if (nx == 8)
293 ny = 12; 457 ny = 12;
294 else 458 else
295 { 459 {
296 nx = 6; 460 nx = 6;
297 ny = 8; 461 ny = 8;
298 } 462 }
299 463
300 while ((ch = *str++) != '\0') 464 while ((ch = *str++) != '\0')
301 { 465 {
302 if (ch == '\n' || lcd_x + nx > DISP_X) 466 if (ch == '\n' || lcd_x + nx > DISP_X)
303 { 467 {
304 /* Wrap to next line */ 468 /* Wrap to next line */
305 lcd_x = x; 469 lcd_x = x;
306 lcd_y += ny; 470 lcd_y += ny;
307 } 471 }
308 472
309 if (lcd_y + ny > DISP_Y) 473 if (lcd_y + ny > DISP_Y)
310 return; 474 return;
311 475
312 /* Limit to char generation table */ 476 /* Limit to char generation table */
313 if (ch >= ASCII_MIN && ch <= ASCII_MAX) 477 if (ch >= ASCII_MIN && ch <= ASCII_MAX)
314 { 478 {
315 if (nx == 12) 479 if (nx == 12)
316 src = char_gen_12x16[ch-ASCII_MIN][0]; 480 src = char_gen_12x16[ch-ASCII_MIN][0];
317 else if (nx == 8) 481 else if (nx == 8)
318 src = char_gen_8x12[ch-ASCII_MIN][0]; 482 src = char_gen_8x12[ch-ASCII_MIN][0];
319 else 483 else
320 src = char_gen_6x8[ch-ASCII_MIN][0]; 484 src = char_gen_6x8[ch-ASCII_MIN][0];
321 485
322 lcd_bitmap (src, lcd_x, lcd_y, nx-1, ny, TRUE); 486 lcd_bitmap (src, lcd_x, lcd_y, nx-1, ny, TRUE);
323 lcd_bitmap (zeros, lcd_x+nx-1, lcd_y, 1, ny, TRUE); 487 lcd_bitmap (zeros, lcd_x+nx-1, lcd_y, 1, ny, TRUE);
324 488
325 lcd_x += nx; 489 lcd_x += nx;
326 } 490 }
327 } 491 }
328} 492}
329 493
330/* 494/*
@@ -334,57 +498,57 @@ void lcd_string (const char *str)
334void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny, 498void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny,
335 bool clear) 499 bool clear)
336{ 500{
337 unsigned char *dst; 501 unsigned char *dst;
338 unsigned char *dst2 = &display[x][y/8]; 502 unsigned char *dst2 = &display[x][y/8];
339 unsigned int data, mask, mask2, mask3, mask4; 503 unsigned int data, mask, mask2, mask3, mask4;
340 int shift = y & 7; 504 int shift = y & 7;
341 505
342 ny += shift; 506 ny += shift;
343 507
344 /* Calculate bit masks */ 508 /* Calculate bit masks */
345 mask4 = ~(0xfe << ((ny-1) & 7)); 509 mask4 = ~(0xfe << ((ny-1) & 7));
346 if (clear) 510 if (clear)
347 { 511 {
348 mask = ~(0xff << shift); 512 mask = ~(0xff << shift);
349 mask2 = 0; 513 mask2 = 0;
350 mask3 = ~mask4; 514 mask3 = ~mask4;
351 if (ny <= 8) 515 if (ny <= 8)
352 mask3 |= mask; 516 mask3 |= mask;
353 } 517 }
354 else 518 else
355 mask = mask2 = mask3 = 0xff; 519 mask = mask2 = mask3 = 0xff;
356 520
357 /* Loop for each column */ 521 /* Loop for each column */
358 for (x = 0; x < nx; x++) 522 for (x = 0; x < nx; x++)
359 { 523 {
360 dst = dst2; 524 dst = dst2;
361 dst2 += DISP_Y/8; 525 dst2 += DISP_Y/8;
362 data = 0; 526 data = 0;
363 y = 0; 527 y = 0;
364 528
365 if (ny > 8) 529 if (ny > 8)
366 { 530 {
367 /* First partial row */ 531 /* First partial row */
368 data = *src++ << shift; 532 data = *src++ << shift;
369 *dst = (*dst & mask) ^ data; 533 *dst = (*dst & mask) ^ data;
370 data >>= 8; 534 data >>= 8;
371 dst++; 535 dst++;
372 536
373 /* Intermediate rows */ 537 /* Intermediate rows */
374 for (y = 8; y < ny-8; y += 8) 538 for (y = 8; y < ny-8; y += 8)
375 { 539 {
376 data |= *src++ << shift; 540 data |= *src++ << shift;
377 *dst = (*dst & mask2) ^ data; 541 *dst = (*dst & mask2) ^ data;
378 data >>= 8; 542 data >>= 8;
379 dst++; 543 dst++;
380 } 544 }
381 } 545 }
382 546
383 /* Last partial row */ 547 /* Last partial row */
384 if (y + shift < ny) 548 if (y + shift < ny)
385 data |= *src++ << shift; 549 data |= *src++ << shift;
386 *dst = (*dst & mask3) ^ (data & mask4); 550 *dst = (*dst & mask3) ^ (data & mask4);
387 } 551 }
388} 552}
389 553
390/* 554/*
@@ -392,9 +556,9 @@ void lcd_bitmap (const unsigned char *src, int x, int y, int nx, int ny,
392 */ 556 */
393void lcd_clearrect (int x, int y, int nx, int ny) 557void lcd_clearrect (int x, int y, int nx, int ny)
394{ 558{
395 int i; 559 int i;
396 for (i = 0; i < nx; i++) 560 for (i = 0; i < nx; i++)
397 lcd_bitmap (zeros, x+i, y, 1, ny, TRUE); 561 lcd_bitmap (zeros, x+i, y, 1, ny, TRUE);
398} 562}
399 563
400/* 564/*
@@ -402,17 +566,17 @@ void lcd_clearrect (int x, int y, int nx, int ny)
402 */ 566 */
403void lcd_fillrect (int x, int y, int nx, int ny) 567void lcd_fillrect (int x, int y, int nx, int ny)
404{ 568{
405 int i; 569 int i;
406 for (i = 0; i < nx; i++) 570 for (i = 0; i < nx; i++)
407 lcd_bitmap (ones, x+i, y, 1, ny, TRUE); 571 lcd_bitmap (ones, x+i, y, 1, ny, TRUE);
408} 572}
409 573
410/* Invert a rectangular area at (x, y), size (nx, ny) */ 574/* Invert a rectangular area at (x, y), size (nx, ny) */
411void lcd_invertrect (int x, int y, int nx, int ny) 575void lcd_invertrect (int x, int y, int nx, int ny)
412{ 576{
413 int i; 577 int i;
414 for (i = 0; i < nx; i++) 578 for (i = 0; i < nx; i++)
415 lcd_bitmap (ones, x+i, y, 1, ny, FALSE); 579 lcd_bitmap (ones, x+i, y, 1, ny, FALSE);
416} 580}
417 581
418#define DRAW_PIXEL(x,y) display[x][y/8] |= (1<<(y%7)) 582#define DRAW_PIXEL(x,y) display[x][y/8] |= (1<<(y%7))