OSDN Git Service

Bug fixed the lcd control.
[bluetank/bluetank.git] / firm / bare_metal / common / lcd.c
1 /**
2  * @file lcd.c
3  * @author Copyright(C) 2012 Shinichiro Nakamura
4  * @brief BlueTank ACB-BF592 Application Sample Codes.
5  */
6
7 /*
8  * ===============================================================
9  *  BlueTank
10  * ===============================================================
11  * Copyright (c) 2012 Shinichiro Nakamura
12  *
13  * Permission is hereby granted, free of charge, to any person
14  * obtaining a copy of this software and associated documentation
15  * files (the "Software"), to deal in the Software without
16  * restriction, including without limitation the rights to use,
17  * copy, modify, merge, publish, distribute, sublicense, and/or
18  * sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following
20  * conditions:
21  *
22  * The above copyright notice and this permission notice shall be
23  * included in all copies or substantial portions of the Software.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
27  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
29  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
30  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
32  * OTHER DEALINGS IN THE SOFTWARE.
33  * ===============================================================
34  */
35
36 #include <cdefBF592-A.h>
37 #include <stdlib.h>
38 #include "lcd.h"
39 #include "bfin_util.h"
40
41 #define PORT_INIT() \
42     do { \
43         *pPORTFIO_DIR |= (PF0 | PF1 | PF2 | PF3 | PF4 | PF5); \
44     } while (0)
45
46 #define DATA(N) \
47     do { \
48         if ((N) & 0x01) { \
49             *pPORTFIO_SET = PF2; \
50         } else { \
51             *pPORTFIO_CLEAR = PF2; \
52         } \
53         if ((N) & 0x02) { \
54             *pPORTFIO_SET = PF3; \
55         } else { \
56             *pPORTFIO_CLEAR = PF3; \
57         } \
58         if ((N) & 0x04) { \
59             *pPORTFIO_SET = PF4; \
60         } else { \
61             *pPORTFIO_CLEAR = PF4; \
62         } \
63         if ((N) & 0x08) { \
64             *pPORTFIO_SET = PF5; \
65         } else { \
66             *pPORTFIO_CLEAR = PF5; \
67         } \
68     } while (0)
69
70 #define RS_ON()     (*pPORTFIO_SET   = PF0)
71 #define RS_OFF()    (*pPORTFIO_CLEAR = PF0)
72 #define E_ON()      (*pPORTFIO_SET   = PF1)
73 #define E_OFF()     (*pPORTFIO_CLEAR = PF1)
74
75 #define DELAY_US(N) bfin_util_usleep(N)
76
77 static void write_command(unsigned char c)
78 {
79     DATA((c >> 4) & 0x0f);
80     DELAY_US(1);
81     E_ON();
82     DELAY_US(1);
83     E_OFF();
84     DELAY_US(1);
85
86     DATA((c >> 0) & 0x0f);
87     DELAY_US(1);
88     E_ON();
89     DELAY_US(1);
90     E_OFF();
91     DELAY_US(1);
92 }
93
94 /**
95  * @brief LCDを初期化する。
96  */
97 void lcd_init(void)
98 {
99     DELAY_US(30000);
100     PORT_INIT();
101
102     E_ON();
103     RS_OFF();
104
105     /*
106      * Function set (Interface is 8bits long.)
107      */
108     DATA(0x03); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(20000);
109     DATA(0x03); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(5000);
110     DATA(0x03); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(100);
111
112     /*
113      * Function set
114      */
115     DATA(0x02); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
116     DATA(0x02); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
117     DATA(0x08); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
118     DELAY_US(50);
119
120     /*
121      * Display ON/OFF Control
122      */
123     DATA(0x00); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
124     DATA(0x0C); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
125     DELAY_US(50);
126
127     /*
128      * Display Clear
129      */
130     DATA(0x00); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
131     DATA(0x01); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
132     DELAY_US(2000);
133
134     /*
135      * Entry Mode Set
136      */
137     DATA(0x00); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
138     DATA(0x06); DELAY_US(1); E_ON(); DELAY_US(1); E_OFF(); DELAY_US(1000);
139     DELAY_US(50);
140 }
141
142 void lcd_clear(void)
143 {
144     RS_OFF();
145     write_command(0x01);
146     DELAY_US(1640);
147 }
148
149 void lcd_cursor_at_home(void)
150 {
151     RS_OFF();
152     write_command(0x02);
153     DELAY_US(1640);
154 }
155
156 void lcd_entry_mode_set(bool increment, bool shifted)
157 {
158     RS_OFF();
159     write_command(0x04
160             | (increment ? (1 << 1) : (0 << 1))
161             | (shifted ? (1 << 0) : (0 << 0)));
162     DELAY_US(50);
163 }
164
165 void lcd_display(bool display, bool cursor, bool blink)
166 {
167     RS_OFF();
168     write_command(0x08
169             | (display ? (1 << 2) : (0 << 2))
170             | (cursor ? (1 << 1) : (0 << 1))
171             | (blink ? (1 << 0) : (0 << 0)));
172     DELAY_US(50);
173 }
174
175 void lcd_cursor_shift(Direction dir)
176 {
177     RS_OFF();
178     write_command(0x10
179             | (0 << 3)
180             | ((Right == dir) ? (1 << 2) : (0 << 2)));
181     DELAY_US(50);
182 }
183
184 void lcd_display_shift(Direction dir)
185 {
186     RS_OFF();
187     write_command(0x10
188             | (1 << 3)
189             | ((Right == dir) ? (1 << 2) : (0 << 2)));
190     DELAY_US(50);
191 }
192
193 void lcd_goto(uint8_t x, uint8_t y)
194 {
195     uint8_t addr = (y * 0xc0) + x;
196     RS_OFF();
197     write_command(0x80
198             | (addr & 0x7f));
199     DELAY_US(50);
200 }
201
202 void lcd_putc(char c)
203 {
204     RS_ON();
205     write_command(c);
206     DELAY_US(50);
207 }
208
209 void lcd_puts(char *str)
210 {
211     while (*str) {
212         lcd_putc(*str);
213         str++;
214     }
215 }
216
217 void lcd_font_init(FontSet *fs)
218 {
219     int i, j;
220     for (i = 0; i < LCD_FONT_CHARS; i++) {
221         for (j = 0; j < LCD_FONT_HEIGHT; j++) {
222             fs->fontlist[i].data[j] = 0x00;
223         }
224     }
225 }
226
227 void lcd_font_set_pixel(
228         FontSet *fs, UserFont index,
229         const int x, const int y, const int on)
230 {
231     if (LCD_FONT_WIDTH <= x) {
232         return;
233     }
234     if (LCD_FONT_HEIGHT <= y) {
235         return;
236     }
237     if (on) {
238         fs->fontlist[(int)index].data[y] |=
239             (1 << (LCD_FONT_WIDTH - x - 1));
240     } else {
241         fs->fontlist[(int)index].data[y] &=
242             ~(1 << (LCD_FONT_WIDTH - x - 1));
243     }
244 }
245
246 #define swap(A,B) \
247     do { \
248         int C = A; \
249         A = B; \
250         B = C; \
251     } while (0)
252
253 void lcd_font_draw_line(
254         FontSet *fs, UserFont index,
255         int x1, int y1,
256         int x2, int y2,
257         int on)
258 {
259     int x;
260     /*
261      * Bresenham's line algorithm
262      */
263     bool steep = abs(y2 - y1) > abs(x2 - x1);
264     if (steep) {
265         swap(x1, y1);
266         swap(x2, y2);
267     }
268     if (x1 > x2) {
269         swap(x1, x2);
270         swap(y1, y2);
271     }
272     int deltax = x2 - x1;
273     int deltay = abs(y2 - y1);
274     int error = deltax / 2;
275     int ystep;
276     int y = y1;
277     if (y1 < y2) {
278         ystep = 1;
279     } else {
280         ystep = -1;
281     }
282     for (x = x1; x <= x2; x++) {
283         if (steep) {
284             lcd_font_set_pixel(fs, index, y, x, on);
285         } else {
286             lcd_font_set_pixel(fs, index, x, y, on);
287         }
288         error = error - deltay;
289         if (error < 0) {
290             y = y + ystep;
291             error = error + deltax;
292         }
293     }
294 }
295
296 void lcd_font_setup_single(FontSet *fs, UserFont index)
297 {
298     uint8_t addr = 8 * (int)index;
299     int i = (int)index, j;
300     for (j = 0; j < LCD_FONT_HEIGHT; j++) {
301         RS_OFF();
302         write_command(0x40 | (addr & 0x3f));
303         DELAY_US(50);
304
305         RS_ON();
306         write_command(fs->fontlist[i].data[j]);
307         DELAY_US(50);
308
309         addr++;
310     }
311 }
312
313 void lcd_font_setup_all(FontSet *fs)
314 {
315     uint8_t addr = 0;
316     int i, j;
317     for (i = 0; i < LCD_FONT_CHARS; i++) {
318         for (j = 0; j < LCD_FONT_HEIGHT; j++) {
319             RS_OFF();
320             write_command(0x40 | (addr & 0x3f));
321             DELAY_US(50);
322
323             RS_ON();
324             write_command(fs->fontlist[i].data[j]);
325             DELAY_US(50);
326
327             addr++;
328         }
329     }
330 }
331