]> git.sur5r.net Git - freertos/blob - Demo/RX200_RX210-RSK_Renesas/RTOSDemo/Renesas-Files/hd44780.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / RX200_RX210-RSK_Renesas / RTOSDemo / Renesas-Files / hd44780.c
1 /*------------------------------------------------------------------------/\r
2 /  EZ-LCD - Generic control module for HD44780 LCDC - R0.01c\r
3 /-------------------------------------------------------------------------/\r
4 /\r
5 /  Copyright (C) 2010, ChaN, all right reserved.\r
6 /\r
7 / * This software is a free software and there is NO WARRANTY.\r
8 / * No restriction on use. You can use, modify and redistribute it for\r
9 /   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.\r
10 / * Redistributions of source code must retain the above copyright notice.\r
11 /\r
12 /-------------------------------------------------------------------------/\r
13 / Nov 12,'10 R0.01c  First release.\r
14 /------------------------------------------------------------------------*/\r
15 #include <machine.h>\r
16 #include "hd44780.h"\r
17 \r
18 /*-------------------------------------------------------------------------*/\r
19 /* Platform dependent macros and functions needed to be modified           */\r
20 /*-------------------------------------------------------------------------*/\r
21 \r
22 /* Bus controls */\r
23 #include "iodefine.h"                   /* Device specific include file */\r
24 #include "rskrx210def.h"\r
25 \r
26 #define IF_BUS          4                       /* Data bus width (4 or 8) */\r
27 #define IF_INIT()       {}                      /* Initialize control port */\r
28 #define E1_HIGH()       LCD_EN = 1      /* Set E(E1) high */\r
29 #define E1_LOW()        LCD_EN = 0  /* Set E(E1) low */\r
30 #define E2_HIGH()                               /* Set E2 high (dual controller only) */\r
31 #define E2_LOW()                                /* Set E2 low (dual controller only) */\r
32 #define RS_HIGH()       LCD_RS = 1      /* Set RS high */\r
33 #define RS_LOW()        LCD_RS = 0      /* Set RS low */\r
34 #define OUT_DATA(d)     LCD_DATA = (d & 0x0F)//LCD_DATA = ((LCD_DATA & 0xF0) | (d & 0x0F))      /* Output a byte d on the data bus (higher 4 bits of d in 4-bit mode) */\r
35 #define IF_DLY60()      {nop();nop();nop(); }                   /* Delay >=60ns (can be blanked for most uC) */\r
36 #define IF_DLY450()     {unsigned long x; for(x=0; x<22; x++){nop();}}                  /* Delay >=450ns@3V, >=250ns@5V */\r
37 #define DELAY_US(n)     {unsigned long x; for(x=0; x<(n*50); x++){nop();}}                      /* Delay n microseconds */\r
38 \r
39 /* Characteristics of LCD module  */\r
40 #define LCD_ETIME_1     1530            /* Execution time of Clear Display command [us] */\r
41 #define LCD_ETIME_2     43                      /* Execution time of other command and data write [us] */\r
42 #define LCD_DLF         2.0                     /* Delay factor (>=2.0) */\r
43 \r
44 \r
45 \r
46 /*-------------------------------------------------------------------------*/\r
47 \r
48 \r
49 #if _LCD_ROWS >= 2 || _LCD_COLS > 8\r
50  #define LCD_IF_2ROW 8          /* 2-row cfg. */\r
51  #if _LCD_ROWS == 1\r
52   #define LCD_IF_SPLIT 1        /* Half split row */\r
53  #else\r
54   #define LCD_IF_SPLIT 0        /* Direct row */\r
55  #endif\r
56 #else\r
57  #define LCD_IF_2ROW 0          /* 1-row cfg. */\r
58 #endif\r
59 \r
60 #if _LCD_ROWS == 4 && _LCD_COLS <= 20\r
61  #define LCD_IF_ALTROW  1       /* Alternate row layout */\r
62 #else\r
63  #define LCD_IF_ALTROW  0       /* Incremental row layout */\r
64 #endif\r
65 \r
66 #if _LCD_ROWS == 4 && _LCD_COLS > 20\r
67  #define LCD_IF_DUAL    1       /* Dual controller */\r
68 #else\r
69  #define LCD_IF_DUAL    0       /* Single controller */\r
70 #endif\r
71 \r
72 #define LCD_DT1         ((uint16_t)(LCD_ETIME_1 * LCD_DLF))\r
73 #define LCD_DT2         ((uint16_t)(LCD_ETIME_2 * LCD_DLF))\r
74 \r
75 \r
76 \r
77 static\r
78 uint8_t Row, Column;    /* Current cursor position */\r
79 #if _USE_CURSOR\r
80 static\r
81 uint8_t Csr;    /* Current cursor state */\r
82 #endif\r
83 \r
84 \r
85 \r
86 \r
87 /*----------------------------------------------*/\r
88 /* Write a byte to the LCD controller           */\r
89 /*----------------------------------------------*/\r
90 \r
91 static\r
92 void lcd_write (\r
93         uint8_t reg,    /* b0:command(0)/data(1), b2..1:E1(2)/E2(1)/both(0)(don't care on single controller), b3:write high nibble only(don't care on 8-bit bus) */\r
94         uint8_t dat             /* Byte to be written */\r
95 )\r
96 {\r
97         if (reg & 1)    /* Select register */\r
98                 RS_HIGH();\r
99         else\r
100                 RS_LOW();\r
101         IF_DLY60();\r
102 \r
103 #if IF_BUS == 4\r
104         if (!(reg & 8)) {\r
105                 OUT_DATA(dat);\r
106 #if LCD_IF_DUAL\r
107                 if (!(reg & 2)) E1_HIGH();\r
108                 if (!(reg & 4)) E2_HIGH();\r
109                 IF_DLY450();\r
110                 E1_LOW();\r
111                 E2_LOW();\r
112 #else\r
113                 E1_HIGH();\r
114                 IF_DLY450();\r
115                 E1_LOW();\r
116 #endif\r
117                 IF_DLY450();\r
118                 dat <<= 4;\r
119         }\r
120 #endif\r
121 \r
122         OUT_DATA(dat);\r
123 #if LCD_IF_DUAL\r
124         if (!(reg & 2)) E1_HIGH();\r
125         if (!(reg & 4)) E2_HIGH();\r
126         IF_DLY450();\r
127         E1_LOW();\r
128         E2_LOW();\r
129 #else\r
130         E1_HIGH();\r
131         IF_DLY450();\r
132         E1_LOW();\r
133 #endif\r
134 \r
135         DELAY_US(LCD_DT2);      /* Always use timer */\r
136 }\r
137 \r
138 \r
139 \r
140 /*-----------------------------------------------------------------------*/\r
141 /* Initialize LCD module                                                 */\r
142 /*-----------------------------------------------------------------------*/\r
143 \r
144 void lcd_init (void)\r
145 {\r
146         uint8_t d;\r
147         \r
148         E1_HIGH();\r
149         DELAY_US(40000);\r
150         E1_LOW();\r
151 \r
152 //      IF_INIT();\r
153 \r
154 //      DELAY_US(40000);\r
155         lcd_write(8, 0x30);\r
156         DELAY_US(4100);\r
157         lcd_write(8, 0x30);\r
158         DELAY_US(100);\r
159         lcd_write(8, 0x30);\r
160 \r
161         d = (IF_BUS == 4 ? 0x20 : 0x30) | LCD_IF_2ROW;\r
162         lcd_write(8, d);\r
163 #if IF_BUS == 4\r
164         lcd_write(0, d);\r
165 #endif\r
166         lcd_write(0, 0x08);\r
167         lcd_write(0, 0x01);\r
168         DELAY_US(LCD_DT1);\r
169         lcd_write(0, 0x06);\r
170         lcd_write(0, 0x0C);\r
171 \r
172         Row = Column = 0;\r
173 #if _USE_CURSOR\r
174         Csr = 0;\r
175 #endif\r
176 }\r
177 \r
178 \r
179 \r
180 /*-----------------------------------------------------------------------*/\r
181 /* Set cursor position                                                   */\r
182 /*-----------------------------------------------------------------------*/\r
183 \r
184 void lcd_locate (\r
185         uint8_t row,    /* Cursor row position (0.._LCD_ROWS-1) */\r
186         uint8_t col             /* Cursor column position (0.._LCD_COLS-1) */\r
187 )\r
188 {\r
189         Row = row; Column = col;\r
190 \r
191         if (row < _LCD_ROWS && col < _LCD_COLS) {\r
192                 if (_LCD_COLS >= 2 && (row & 1)) col += 0x40;\r
193                 if (LCD_IF_SPLIT && col >= _LCD_COLS / 2) col += 0x40 - _LCD_COLS / 2;\r
194                 if (LCD_IF_ALTROW && (row & 2)) col += _LCD_COLS;\r
195                 col |= 0x80;\r
196         } else {\r
197                 col = 0x0C;\r
198         }\r
199 \r
200 #if LCD_IF_DUAL\r
201         if (_USE_CURSOR && !(row &= 2)) row |= 4;\r
202         lcd_write(row, col);\r
203 #if _USE_CURSOR\r
204         if (col != 0x0C) lcd_write(row, Csr | 0x0C);\r
205         row ^= 6;\r
206         lcd_write(row, 0x0C);\r
207 #endif\r
208 #else\r
209         lcd_write(0, col);\r
210 #if _USE_CURSOR\r
211         if (col != 0x0C) lcd_write(0, Csr | 0x0C);\r
212 #endif\r
213 #endif\r
214 }\r
215 \r
216 \r
217 \r
218 /*-----------------------------------------------------------------------*/\r
219 /* Put a character                                                       */\r
220 /*-----------------------------------------------------------------------*/\r
221 \r
222 void lcd_putc (\r
223         uint8_t chr\r
224 )\r
225 {\r
226         if (chr == '\f') {              /* Clear Screen and Return Home */\r
227                 lcd_write(0, 0x01);\r
228                 DELAY_US(LCD_DT1);\r
229                 lcd_locate(0, 0);\r
230                 return;\r
231         }\r
232 \r
233         if (Row >= _LCD_ROWS) return;\r
234 \r
235         if (chr == '\r') {      /* Cursor return */\r
236                 lcd_locate(Row, 0);\r
237                 return;\r
238         }\r
239         if (chr == '\n') {      /* Next row */\r
240                 lcd_locate(Row + 1, 0);\r
241                 return;\r
242         }\r
243         if (chr == '\b') {      /* Cursor back */\r
244                 if (Column)\r
245                         lcd_locate(Row, Column - 1);\r
246                 return;\r
247         }\r
248 \r
249         if (Column >= _LCD_COLS) return;\r
250 \r
251         lcd_write((LCD_IF_DUAL && Row >= 2) ? 3 : 5, chr);\r
252         Column++;\r
253 \r
254         if (LCD_IF_SPLIT && Column == _LCD_COLS / 2)\r
255                 lcd_write(0, 0x40);\r
256 \r
257         if (Column >= _LCD_COLS)\r
258                 lcd_locate(Row + 1, 0);\r
259 }\r
260 \r
261 \r
262 \r
263 /*-----------------------------------------------------------------------*/\r
264 /* Set cursor form                                                       */\r
265 /*-----------------------------------------------------------------------*/\r
266 \r
267 #if _USE_CURSOR\r
268 void lcd_cursor (\r
269         uint8_t stat    /* 0:off, 1:blinking block, 2:under-line */\r
270 )\r
271 {\r
272         Csr = stat & 3;\r
273         lcd_locate(Row, Column);\r
274 }\r
275 #endif\r
276 \r
277 \r
278 \r
279 /*-----------------------------------------------------------------------*/\r
280 /* Register user character pattern                                       */\r
281 /*-----------------------------------------------------------------------*/\r
282 \r
283 #if _USE_CGRAM\r
284 void lcd_setcg (\r
285         uint8_t chr,            /* Character code to be registered (0..7) */\r
286         uint8_t n,                      /* Number of characters to register */\r
287         const uint8_t* p        /* Pointer to the character pattern (8 * n bytes) */\r
288 )\r
289 {\r
290         lcd_write(0, 0x40 | chr * 8);\r
291         n *= 8;\r
292         do\r
293                 lcd_write(1, *p++);\r
294         while (--n);\r
295 \r
296         lcd_locate(Row, Column);\r
297 }\r
298 #endif\r
299 \r
300 \r
301 \r
302 /*-----------------------------------------------------------------------*/\r
303 /* Put a fuel indicator                                                  */\r
304 /*-----------------------------------------------------------------------*/\r
305 \r
306 #if _USE_FUEL && _USE_CGRAM\r
307 void lcd_put_fuel (\r
308         int8_t val,             /* Fuel level (-1:plugged, 0:empty cell, ..., 5:full cell) */\r
309         uint8_t chr             /* User character to use */\r
310 )\r
311 {\r
312         static const uint8_t plg[8] = {10,10,31,31,14,4,7,0};\r
313         uint8_t gfx[8], d, *p;\r
314         int8_t i;\r
315 \r
316 \r
317         if (val >= 0) {         /* Cell (0..5) */\r
318                 p = &gfx[8];\r
319                 *(--p) = 0; *(--p) = 0x1F;\r
320                 for (i = 1; i <= 5; i++) {\r
321                         d = 0x1F;\r
322                         if (val < i) d = (i == 5) ? 0x1B : 0x11;\r
323                         *(--p) = d;\r
324                 }\r
325                 *(--p) = 0x0E;\r
326         } else {                        /* Plug (-1) */\r
327                 p = (uint8_t*)plg;\r
328         }\r
329         lcd_setcg(chr, 1, p);\r
330         lcd_putc(chr);\r
331 }\r
332 \r
333 \r
334 #endif\r
335 \r
336 \r
337 \r
338 /*-----------------------------------------------------------------------*/\r
339 /* Draw bargraph                                                         */\r
340 /*-----------------------------------------------------------------------*/\r
341 \r
342 #if _USE_BAR && _USE_CGRAM\r
343 void lcd_put_bar (\r
344         uint16_t val,   /* Bar length (0 to _MAX_BAR represents bar length from left end) */\r
345         uint8_t width,  /* Display area (number of chars from cursor position) */\r
346         uint8_t chr             /* User character code (2 chars used from this) */\r
347 )\r
348 {\r
349         static const uint8_t ptn[] = {\r
350                 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0x80, 0,\r
351                 0xF0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0,\r
352                 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0\r
353         };\r
354         const uint8_t *pp;\r
355         uint16_t n, m, s, gi;\r
356         uint8_t gfx[16];\r
357 \r
358 \r
359         for (n = 0; n < 16; n++)                /* Register common pattern (space/fill) */\r
360                 gfx[n] = n < 7 ? 0 : 0xFF;\r
361         lcd_setcg(_BASE_GRAPH, 2, gfx);\r
362 \r
363         /* Draw edge pattern into gfx[] */\r
364         val = (unsigned long)val * (width * 18) / (_MAX_BAR + 1);\r
365         pp = &ptn[(val % 3) * 8];               /* Get edge pattern */\r
366         s = val / 3 % 6;                                /* Bit shift */\r
367         for (n = 0; n < 7; n++) {               /* Draw edge pattern into the pattern buffer */\r
368                 m = (*pp++ | 0xFF00) >> s;\r
369                 gfx[n] = m;\r
370                 gfx[n + 8] = m >> 6;\r
371         }\r
372 \r
373         /* Put graphic pattern into the LCD module */\r
374         gi = val / 18;                                          /* Indicator start position */\r
375         for (n = 1; n <= width; n++) {          /* Draw each location in the bargraph */\r
376                 if (n == gi) {                                  /* When edge pattern is exist at the location */\r
377                         m = chr + 1;                            /* A edge pattern */\r
378                 } else {\r
379                         if (n == gi + 1) {\r
380                                 lcd_setcg(chr, 2, gfx); /* Register edge pattern */\r
381                                 m = chr;\r
382                         } else {\r
383                                 m = (n >= gi) ? _BASE_GRAPH : _BASE_GRAPH + 1;  /* A space or fill */\r
384                         }\r
385                 }\r
386                 lcd_putc(m);                                    /* Put the character into the LCD */\r
387         }\r
388 }\r
389 #endif\r
390 \r
391 \r
392 \r
393 /*-----------------------------------------------------------------------*/\r
394 /* Draw point indicator                                                  */\r
395 /*-----------------------------------------------------------------------*/\r
396 \r
397 #if _USE_POINT && _USE_CGRAM\r
398 void lcd_put_point (\r
399         uint16_t val,   /* Dot position (0 to _MAX_POINT represents left end to write end) */\r
400         uint8_t width,  /* Display area (number of chars from cursor position) */\r
401         uint8_t chr             /* User character code (2 chars used from this) */\r
402 )\r
403 {\r
404         static const uint8_t ptn[] = {\r
405                 0x06, 0x0C, 0x0C, 0x0C, 0x18, 0x18, 0x18, 0,\r
406                 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x18, 0x18, 0,\r
407                 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x18, 0\r
408         };\r
409         const uint8_t *pp;\r
410         uint16_t n, m, s, gi;\r
411         uint8_t gfx[16];\r
412 \r
413 \r
414         for (n = 0; n < 16; n++)                /* Register common pattern (space) */\r
415                 gfx[n] = n < 7 ? 0 : 0xFF;\r
416         lcd_setcg(_BASE_GRAPH, 1, gfx);\r
417 \r
418         /* Draw edge pattern into gfx[] */\r
419         val = (uint32_t)val * (width * 18 - 12) / (_MAX_BAR + 1);\r
420         pp = &ptn[(val % 3) * 8];               /* Get edge pattern */\r
421         s = val / 3 % 6;                                /* Bit shift */\r
422         for (n = 0; n < 7; n++) {               /* Draw edge pattern into the pattern buffer */\r
423                 m = *pp++; m <<= 6; m >>= s;\r
424                 gfx[n] = m;\r
425                 gfx[n + 8] = m >> 6;\r
426         }\r
427         lcd_setcg(chr, 2, gfx);                         /* Register dot pattern */\r
428 \r
429         /* Put graphic pattern into the LCD module */\r
430         gi = val / 18;                                          /* Indicator start position */\r
431         for (n = 0; n < width; n++) {           /* Draw each location in the bargraph */\r
432                 if (n == gi) {                                  /* When edge pattern is exist at the location */\r
433                         m = chr + 1;                            /* A edge pattern */\r
434                 } else {\r
435                         if (n == gi + 1)\r
436                                 m = chr;\r
437                         else\r
438                                 m = _BASE_GRAPH;                /* A space */\r
439                 }\r
440                 lcd_putc(m);                                    /* Put the character into the LCD */\r
441         }\r
442 }\r
443 #endif\r
444 \r
445 \r