OSDN Git Service

Added port configuration layer.
[kozos-expbrd/kozos_expbrd.git] / firm / sample1 / bootload / lcd.c
1 #include "lcd.h"
2 #include "defines.h"
3 #include "portconf.h"
4
5 static const uint8 FONT_X = 5;
6 static const uint8 FONT_Y = 7;
7 static const uint16 FONT_MIN_CODE = 0x20;
8 static const uint16 FONT_MAX_CODE = 0x7F;
9
10 #define swap(a,b) {int c=a;a=b;b=c;}
11 #define abs(n) (((int)(n) < 0) ? ((int)(n) * (-1)) : (n))
12
13 #define LCD_ADDR_LEFT   ((volatile uint8 *)0x800000)
14 #define LCD_ADDR_RIGHT  ((volatile uint8 *)0xA00000)
15 #define LCD_AOFS_CMD    (0)
16 #define LCD_AOFS_DAT    (1 << 3)
17
18 #define LCD1_CMD(VAL) \
19   do { \
20     *(LCD_ADDR_LEFT + LCD_AOFS_CMD) = (VAL); \
21   } while (0)
22
23 #define LCD1_DAT_WRITE(VAL) \
24   do { \
25     *(LCD_ADDR_LEFT + LCD_AOFS_DAT) = (VAL); \
26   } while (0)
27
28 #define LCD1_DAT_READ() (*(LCD_ADDR_LEFT + LCD_AOFS_DAT))
29
30 #define LCD2_CMD(VAL) \
31   do { \
32     *(LCD_ADDR_RIGHT + LCD_AOFS_CMD) = (VAL); \
33   } while (0)
34
35 #define LCD2_DAT_WRITE(VAL) \
36   do { \
37     *(LCD_ADDR_RIGHT + LCD_AOFS_DAT) = (VAL); \
38   } while (0)
39
40 #define LCD2_DAT_READ() (*(LCD_ADDR_RIGHT + LCD_AOFS_DAT))
41
42 static const uint8 font5x7_data[] = {
43   0x00, 0x00, 0x00, 0x00, 0x00, // (white space)
44   0x00, 0x00, 0x5F, 0x00, 0x00, // !
45   0x00, 0x07, 0x00, 0x07, 0x00, // "
46   0x14, 0x7F, 0x14, 0x7F, 0x14, // #
47   0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
48   0x23, 0x13, 0x08, 0x64, 0x62, // %
49   0x36, 0x49, 0x55, 0x22, 0x50, // &
50   0x00, 0x05, 0x03, 0x00, 0x00, // '
51   0x00, 0x1C, 0x22, 0x41, 0x00, // (
52   0x00, 0x41, 0x22, 0x1C, 0x00, // )
53   0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
54   0x08, 0x08, 0x3E, 0x08, 0x08, // +
55   0x00, 0x50, 0x30, 0x00, 0x00, // ,
56   0x08, 0x08, 0x08, 0x08, 0x08, // -
57   0x00, 0x60, 0x60, 0x00, 0x00, // .
58   0x20, 0x10, 0x08, 0x04, 0x02, // /
59   0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
60   0x00, 0x42, 0x7F, 0x40, 0x00, // 1
61   0x42, 0x61, 0x51, 0x49, 0x46, // 2
62   0x21, 0x41, 0x45, 0x4B, 0x31, // 3
63   0x18, 0x14, 0x12, 0x7F, 0x10, // 4
64   0x27, 0x45, 0x45, 0x45, 0x39, // 5
65   0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
66   0x01, 0x71, 0x09, 0x05, 0x03, // 7
67   0x36, 0x49, 0x49, 0x49, 0x36, // 8
68   0x06, 0x49, 0x49, 0x29, 0x1E, // 9
69   0x00, 0x36, 0x36, 0x00, 0x00, // :
70   0x00, 0x56, 0x36, 0x00, 0x00, // ;
71   0x00, 0x08, 0x14, 0x22, 0x41, // <
72   0x14, 0x14, 0x14, 0x14, 0x14, // =
73   0x41, 0x22, 0x14, 0x08, 0x00, // >
74   0x02, 0x01, 0x51, 0x09, 0x06, // ?
75   0x32, 0x49, 0x79, 0x41, 0x3E, // @
76   0x7E, 0x11, 0x11, 0x11, 0x7E, // A
77   0x7F, 0x49, 0x49, 0x49, 0x36, // B
78   0x3E, 0x41, 0x41, 0x41, 0x22, // C
79   0x7F, 0x41, 0x41, 0x22, 0x1C, // D
80   0x7F, 0x49, 0x49, 0x49, 0x41, // E
81   0x7F, 0x09, 0x09, 0x01, 0x01, // F
82   0x3E, 0x41, 0x41, 0x51, 0x32, // G
83   0x7F, 0x08, 0x08, 0x08, 0x7F, // H
84   0x00, 0x41, 0x7F, 0x41, 0x00, // I
85   0x20, 0x40, 0x41, 0x3F, 0x01, // J
86   0x7F, 0x08, 0x14, 0x22, 0x41, // K
87   0x7F, 0x40, 0x40, 0x40, 0x40, // L
88   0x7F, 0x02, 0x04, 0x02, 0x7F, // M
89   0x7F, 0x04, 0x08, 0x10, 0x7F, // N
90   0x3E, 0x41, 0x41, 0x41, 0x3E, // O
91   0x7F, 0x09, 0x09, 0x09, 0x06, // P
92   0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
93   0x7F, 0x09, 0x19, 0x29, 0x46, // R
94   0x46, 0x49, 0x49, 0x49, 0x31, // S
95   0x01, 0x01, 0x7F, 0x01, 0x01, // T
96   0x3F, 0x40, 0x40, 0x40, 0x3F, // U
97   0x1F, 0x20, 0x40, 0x20, 0x1F, // V
98   0x7F, 0x20, 0x18, 0x20, 0x7F, // W
99   0x63, 0x14, 0x08, 0x14, 0x63, // X
100   0x03, 0x04, 0x78, 0x04, 0x03, // Y
101   0x61, 0x51, 0x49, 0x45, 0x43, // Z
102   0x00, 0x00, 0x7F, 0x41, 0x41, // [
103   0x02, 0x04, 0x08, 0x10, 0x20, // /
104   0x41, 0x41, 0x7F, 0x00, 0x00, // ]
105   0x04, 0x02, 0x01, 0x02, 0x04, // ^
106   0x40, 0x40, 0x40, 0x40, 0x40, // _
107   0x00, 0x01, 0x02, 0x04, 0x00, // `
108   0x20, 0x54, 0x54, 0x54, 0x78, // a
109   0x7F, 0x48, 0x44, 0x44, 0x38, // b
110   0x38, 0x44, 0x44, 0x44, 0x20, // c
111   0x38, 0x44, 0x44, 0x48, 0x7F, // d
112   0x38, 0x54, 0x54, 0x54, 0x18, // e
113   0x08, 0x7E, 0x09, 0x01, 0x02, // f
114   0x08, 0x14, 0x54, 0x54, 0x3C, // g
115   0x7F, 0x08, 0x04, 0x04, 0x78, // h
116   0x00, 0x44, 0x7D, 0x40, 0x00, // i
117   0x20, 0x40, 0x44, 0x3D, 0x00, // j
118   0x00, 0x7F, 0x10, 0x28, 0x44, // k
119   0x00, 0x41, 0x7F, 0x40, 0x00, // l
120   0x7C, 0x04, 0x18, 0x04, 0x78, // m
121   0x7C, 0x08, 0x04, 0x04, 0x78, // n
122   0x38, 0x44, 0x44, 0x44, 0x38, // o
123   0x7C, 0x14, 0x14, 0x14, 0x08, // p
124   0x08, 0x14, 0x14, 0x18, 0x7C, // q
125   0x7C, 0x08, 0x04, 0x04, 0x08, // r
126   0x48, 0x54, 0x54, 0x54, 0x20, // s
127   0x04, 0x3F, 0x44, 0x40, 0x20, // t
128   0x3C, 0x40, 0x40, 0x20, 0x7C, // u
129   0x1C, 0x20, 0x40, 0x20, 0x1C, // v
130   0x3C, 0x40, 0x30, 0x40, 0x3C, // w
131   0x44, 0x28, 0x10, 0x28, 0x44, // x
132   0x0C, 0x50, 0x50, 0x50, 0x3C, // y
133   0x44, 0x64, 0x54, 0x4C, 0x44, // z
134   0x00, 0x08, 0x36, 0x41, 0x00, // {
135   0x00, 0x00, 0x7F, 0x00, 0x00, // |
136   0x00, 0x41, 0x36, 0x08, 0x00, // }
137   0x08, 0x08, 0x2A, 0x1C, 0x08, // ->
138   0x08, 0x1C, 0x2A, 0x08, 0x08  // <-
139 };
140
141 void lcd_init(void)
142 {
143   *PORTCONF_P4DDR = PORTCONF_P4BIT_LCD_RES | PORTCONF_P4BIT_SDCCS | PORTCONF_P4BIT_VSCCS | PORTCONF_P4BIT_VSDCS | PORTCONF_P4BIT_VSRST;
144
145   /*
146    * L->H : 68K mode.
147    */
148   *PORTCONF_P4DR &= ~PORTCONF_P4BIT_LCD_RES;
149   asm volatile ("nop");
150   asm volatile ("nop");
151   asm volatile ("nop");
152   asm volatile ("nop");
153   *PORTCONF_P4DR |= PORTCONF_P4BIT_LCD_RES;
154
155   *PORTCONF_CSCR = 0x3F;
156
157   LCD1_CMD(0xE2);   // Reset
158   LCD1_CMD(0xA4);   // Static Drive Off
159   LCD1_CMD(0xC0);   // Display Start Line
160   LCD1_CMD(0xAF);   // Display On
161   LCD1_CMD(0xB8);   // Page Address Setup
162   LCD1_CMD(0x00);   // Column Address
163
164   LCD2_CMD(0xE2);   // Reset
165   LCD2_CMD(0xA4);   // Static Drive Off
166   LCD2_CMD(0xC0);   // Display Start Line
167   LCD2_CMD(0xAF);   // Display On
168   LCD2_CMD(0xB8);   // Page Address Setup
169   LCD2_CMD(0x00);   // Column Address
170 }
171
172 void lcd_clear(void)
173 {
174   int p, c;
175
176   for (p = 0; p <= 3; p++) {
177     LCD1_CMD(0xB8 | (p & 0x03));  // Page Address Setup
178     LCD1_CMD(0x00 | (0 & 0x7F));  // Column Address
179     for (c = 0; c < 62; c++) {
180       LCD1_DAT_WRITE(0);
181     }
182
183     LCD2_CMD(0xB8 | (p & 0x03));  // Page Address Setup
184     LCD2_CMD(0x00 | (0 & 0x7F));  // Column Address
185     for (c = 0; c < 62; c++) {
186       LCD2_DAT_WRITE(0);
187     }
188   }
189 }
190
191 void lcd_set_pixel(int x, int y, int reverse)
192 {
193   volatile uint8 dat;
194   int p, c;
195
196   if (x <= 60) {
197     p = y / 8;
198     c = x;
199     LCD1_CMD(0xB8 | (p & 0x03));  // Page Address Setup
200     LCD1_CMD(0x00 | (c & 0x7F));  // Column Address
201     LCD1_CMD(0xE0);
202     dat = LCD1_DAT_READ();    // Dummy Read
203     dat = LCD1_DAT_READ();    // Real Read
204     if (reverse) {
205       dat |= (1 << (y % 8));
206     } else {
207       dat &= ~(1 << (y % 8));
208     }
209     LCD1_DAT_WRITE(dat);
210     LCD1_CMD(0xEE);
211   } else {
212     p = y / 8;
213     c = x - 61;
214     LCD2_CMD(0xB8 | (p & 0x03));  // Page Address Setup
215     LCD2_CMD(0x00 | (c & 0x7F));  // Column Address
216     LCD2_CMD(0xE0);
217     dat = LCD2_DAT_READ();    // Dummy Read
218     dat = LCD2_DAT_READ();    // Real Read
219     if (reverse) {
220       dat |= (1 << (y % 8));
221     } else {
222       dat &= ~(1 << (y % 8));
223     }
224     LCD2_DAT_WRITE(dat);
225     LCD2_CMD(0xEE);
226   }
227 }
228
229 void lcd_draw_line(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 reverse)
230 {
231   int x;
232   /*
233    * Bresenham's line algorithm
234    */
235   uint8 steep = abs(y2 - y1) > abs(x2 - x1);
236   if (steep) {
237     swap(x1, y1);
238     swap(x2, y2);
239   }
240   if (x1 > x2) {
241     swap(x1, x2);
242     swap(y1, y2);
243   }
244   int deltax = x2 - x1;
245   int deltay = abs(y2 - y1);
246   int error = deltax / 2;
247   int ystep;
248   int y = y1;
249   if (y1 < y2) {
250     ystep = 1;
251   } else {
252     ystep = -1;
253   }
254   for (x = x1; x <= x2; x++) {
255     if (steep) {
256       if (reverse) {
257         lcd_set_pixel(y, x, 0);
258       } else {
259         lcd_set_pixel(y, x, 1);
260       }
261     } else {
262       if (reverse) {
263         lcd_set_pixel(x, y, 0);
264       } else {
265         lcd_set_pixel(x, y, 1);
266       }
267     }
268     error = error - deltay;
269     if (error < 0) {
270       y = y + ystep;
271       error = error + deltax;
272     }
273   }
274 }
275
276 void lcd_draw_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 reverse)
277 {
278   int x, y;
279   for (x = x1; x <= x2; x++) {
280     if (reverse) {
281       lcd_set_pixel(x, y1, 0);
282       lcd_set_pixel(x, y2, 0);
283     } else {
284       lcd_set_pixel(x, y1, 1);
285       lcd_set_pixel(x, y2, 1);
286     }
287   }
288   for (y = y1; y <= y2; y++) {
289     if (reverse) {
290       lcd_set_pixel(x1, y, 0);
291       lcd_set_pixel(x2, y, 0);
292     } else {
293       lcd_set_pixel(x1, y, 1);
294       lcd_set_pixel(x2, y, 1);
295     }
296   }
297 }
298
299 void lcd_fill_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 reverse)
300 {
301   int x, y;
302   for (x = x1; x <= x2; x++) {
303     for (y = y1; y <= y2; y++) {
304       if (reverse) {
305         lcd_set_pixel(x, y, 0);
306       } else {
307         lcd_set_pixel(x, y, 1);
308       }
309     }
310   }
311 }
312
313 void lcd_draw_string(uint8 x, uint8 y, char *str, uint8 reverse)
314 {
315   char *p = str;
316   int cnt = 0;
317   while (*p) {
318     lcd_draw_char(x + (FONT_X * cnt), y, *p, reverse);
319     p++;
320     cnt++;
321   }
322 }
323
324 void lcd_draw_char(uint8 x, uint8 y, char c, uint8 reverse)
325 {
326   int i, j;
327   if ((FONT_MIN_CODE <= c) &&(c <= FONT_MAX_CODE)) {
328     int aofs = (c - FONT_MIN_CODE) * FONT_X;
329     for (i = 0; i < FONT_X; i++) {
330       uint8 pat = font5x7_data[aofs + i];
331       for (j = 0; j < FONT_Y; j++) {
332         if (pat & (1 << j)) {
333           if (reverse) {
334             lcd_set_pixel(x + i, y + j, 0);
335           } else {
336             lcd_set_pixel(x + i, y + j, 1);
337           }
338         } else {
339           if (reverse) {
340             lcd_set_pixel(x + i, y + j, 1);
341           } else {
342             lcd_set_pixel(x + i, y + j, 0);
343           }
344         }
345       }
346     }
347   } else {
348     for (i = 0; i < FONT_X; i++) {
349       uint8 pat = (i % 2) ? 0x55 : 0xAA;
350       for (j = 0; j < FONT_Y; j++) {
351         if (pat & (1 << j)) {
352           if (reverse) {
353             lcd_set_pixel(x + i, y + j, 0);
354           } else {
355             lcd_set_pixel(x + i, y + j, 1);
356           }
357         } else {
358           if (reverse) {
359             lcd_set_pixel(x + i, y + j, 1);
360           } else {
361             lcd_set_pixel(x + i, y + j, 0);
362           }
363         }
364       }
365     }
366   }
367 }
368
369 void lcd_draw_checkbox(
370     uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 state, uint8 reverse)
371 {
372   lcd_draw_box(x1, y1, x2, y2, reverse);
373   if (state) {
374     lcd_draw_line(x1, y1, x2, y2, reverse);
375     lcd_draw_line(x1, y2, x2, y1, reverse);
376   }
377 }
378
379 void lcd_draw_progressbar(
380     uint16 x1, uint16 y1, uint16 x2, uint16 y2,
381     int min, int max, int value, uint8 reverse)
382 {
383   lcd_draw_box(x1, y1, x2, y2, reverse);
384   if ((value < min) || (max < value)) {
385     return;
386   }
387   int tmp_max = max - min;
388   int tmp_val = value - min;
389   int pix = ((x2 - x1) * tmp_val) / tmp_max;
390   lcd_fill_box(x1 + 1, y1 + 1, x1 + pix - 1, y2 - 1, reverse);
391   lcd_fill_box(x1 + pix, y1 + 1, x2 - 1, y2 - 1, !reverse);
392 }
393