OSDN Git Service

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