OSDN Git Service

[LCD][BUG] Set correct sequence,OOPs!
[openi2cradio/OpenI2CRadio.git] / lcd_acm1602.c
1 /*
2  * OpenI2CRADIO
3  * I2C/Parallel LCD ACM1602 Handler, variant of ST7066U.
4  * Copyright (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
5  * License: GPL2+LE
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2,
10  *  or (at your option) any later version.
11  *  This library / program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  *  See the GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this library; see the file COPYING. If not, write to the
18  *  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19  *  MA 02110-1301, USA.
20  *
21  *  As a special exception, if you link this(includeed from sdcc) library
22  *  with other files, some of which are compiled with SDCC,
23  *  to produce an executable, this library does not by itself cause
24  *  the resulting executable to be covered by the GNU General Public License.
25  *  This exception does not however invalidate any other reasons why
26  *  the executable file might be covered by the GNU General Public License.
27  */
28
29 #include "iodef.h"
30 #include "lcd_acm1602.h"
31
32 #ifdef _USE_I2C_1602
33 static unsigned char lcd_busychk(addr)
34 {
35     unsigned char b, d;
36     i2c_idle();
37     OPENASMASTER();
38     i2c_writechar(addr | 0x01); // Read
39     i2c_writechar(0x00);
40     d = i2c_readchar();
41     CLOSEASMASTER();
42     _ACM1602_I2C_WAIT(); // 5.5ms
43     if((d & _LCDPORT_BUSYMASK) != 0){
44         d = 0xff; // BUSY
45     } else {
46         d = 0;
47     }
48     return d;
49 }
50
51 void lcd_waitbusy(unsigned char addr, unsigned char flag)
52 {
53     unsigned char f,ff;
54     ff = flag;
55     if(ff != 0) ff = 0xff;
56     do {
57         f = lcd_busychk(addr);
58         _ACM1602_SHORT_WAIT(); // Wait 0.1ms
59     } while(f != ff);
60 }
61
62
63 static void sendcmd(unsigned char addr, unsigned char cmd, unsigned char busyflag)
64 {
65     i2c_idle();
66     OPENASMASTER();
67     i2c_writechar(addr & 0xfe);
68     i2c_writechar(0x00);
69     i2c_writechar(cmd);
70     CLOSEASMASTER();
71     _ACM1602_I2C_WAIT(); // 5.5ms
72 }
73
74 static void sendonce(unsigned char addr, unsigned char cmd)
75 {
76     sendcmd(addr, cmd, 0x00);
77 }
78
79 static void acm1602_ioinit(unsigned char addr)
80 {
81     _ACM1602_LONG_LONG_WAIT();
82     return;
83 }
84
85 void acm1602_putchar(unsigned char addr, unsigned char c)
86 {
87     i2c_idle();
88     OPENASMASTER();
89     i2c_writechar(addr & 0xfe);
90     i2c_writechar(0x80); //Data
91     i2c_writechar(c); // Putchar
92     CLOSEASMASTER();
93     _ACM1602_I2C_WAIT(); // Wait 50us
94 }
95
96
97 unsigned char acm1602_getchar(unsigned char addr)
98 {
99     unsigned char d;
100     i2c_idle();
101     OPENASMASTER();
102     i2c_writechar(addr | 0x01); // Read
103     i2c_writechar(0x80);
104     d = i2c_readchar();
105     CLOSEASMASTER();
106     _ACM1602_I2C_WAIT(); // 5.5ms
107     return d;
108 }
109 #else // Parallel
110 static unsigned char lcd_busychk(unsigned char addr)
111 {
112     unsigned char b, d;
113
114     // Set mask for Tristate.
115     b = _LCDPORT_TRIS_DATA;
116     b |= _LCDPORT_READMASK;// Set mask for Tristate, direction = read.
117     _LCDPORT_TRIS_DATA = b;
118
119     b = _LCDPORT_CONT_LATCH;
120     b &= ~_LCDPORT_CONT_RS;
121     b |= _LCDPORT_CONT_RW;
122     _LCDPORT_CONT_LATCH = b;
123     _ACM1602_TC_WAIT(); // Wait 2.5?us
124
125     b |= _LCDPORT_CONT_EN; // Send CMD
126     _LCDPORT_CONT_LATCH = b;
127     _ACM1602_TC_WAIT(); // Wait 2.5?us
128
129     d = _LCDPORT_DATA;
130     _ACM1602_TC_WAIT(); // Wait 2.5?us
131
132     b &= ~_LCDPORT_CONT_EN; // Disable EN
133     _LCDPORT_CONT_LATCH = b;
134     _ACM1602_TC_WAIT(); // Wait 2.5?us
135
136     b |= _LCDPORT_CONT_EN; // Disable EN
137     _LCDPORT_CONT_LATCH = b;
138     _ACM1602_TC_WAIT(); // Wait 2.5?us
139     b &= ~_LCDPORT_CONT_EN; // Disable EN
140     _LCDPORT_CONT_LATCH = b;
141     _ACM1602_TC_WAIT(); // Wait 2.5?us
142
143     b = _LCDPORT_TRIS_DATA;
144     b &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
145     _LCDPORT_TRIS_DATA = b;
146     _ACM1602_TC_WAIT(); // Wait 2.5?us
147
148     if((d & _LCDPORT_BUSYMASK) != 0){
149         d = 0xff; // BUSY
150     } else {
151         d = 0;
152     }
153     return d;
154 }
155
156 void lcd_waitbusy(unsigned char addr, unsigned char flag)
157 {
158     unsigned char f,ff;
159     ff = flag;
160     if(ff != 0) ff = 0xff;
161     do {
162         f = lcd_busychk(addr);
163         _ACM1602_SHORT_WAIT(); // Wait 0.1ms
164     } while(f != ff);
165 }
166
167 static void sendcmd(unsigned char addr, unsigned char cmd,unsigned char busyflag)
168 {
169 #ifdef _LCD_IF_4BIT
170     unsigned char b, d;
171     unsigned char h,l;
172
173     h = cmd & 0xf0; // Higher bit is used.
174     l = (cmd & 0x0f) << 4; // Higher bit is used.
175     // Higher NIBBLE
176     if(busyflag != 0) lcd_waitbusy(addr, 0);
177     d = _LCDPORT_TRIS_CONT;
178     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
179     _LCDPORT_TRIS_CONT = d;
180
181
182     b = _LCDPORT_CONT_LATCH;
183     b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
184     b |= h;
185     _LCDPORT_CONT_LATCH = b;
186     _ACM1602_TC_WAIT(); // Wait 2.5?us
187     b |= _LCDPORT_CONT_EN;
188     _LCDPORT_CONT_LATCH = b;
189     _ACM1602_TC_WAIT(); // Wait 2.5?us
190     b &= ~_LCDPORT_CONT_EN; // Disable EN
191     _LCDPORT_CONT_LATCH = b;
192     _ACM1602_TC_WAIT();
193
194     // Lower NIBBLE
195 //    if(busyflag != 0) lcd_waitbusy(addr, 0);
196     d = _LCDPORT_TRIS_CONT;
197     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
198     _LCDPORT_TRIS_CONT = d;
199     b = _LCDPORT_CONT_LATCH;
200     b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
201     b |= l;
202     _LCDPORT_CONT_LATCH = b;
203     _ACM1602_TC_WAIT(); // Wait 2.5?us
204     b |= _LCDPORT_CONT_EN;
205     _LCDPORT_CONT_LATCH = b;
206
207     _ACM1602_TC_WAIT(); // Wait 2.5?us
208     b &= ~_LCDPORT_CONT_EN; // Disable EN
209     _LCDPORT_CONT_LATCH = b;
210
211     d = _LCDPORT_TRIS_CONT;
212     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
213     _LCDPORT_TRIS_CONT = d;
214
215 #else
216     unsigned char b,d;
217
218     if(busyflag != 0) lcd_waitbusy(addr, 0);
219     d = _LCDPORT_TRIS_DATA;
220     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
221     _LCDPORT_TRIS_DATA = d;
222
223     b = _LCDPORT_CONT_LATCH;
224     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
225     _LCDPORT_CONT_LATCH = b;
226
227     _LCDPORT_LATCH_DATA = cmd;
228
229     b |= _LCDPORT_CONT_EN; // Send CMD
230     _LCDPORT_CONT_LATCH = b;
231     _ACM1602_TC_WAIT(); // Wait 2.5?us
232
233     b &= ~_LCDPORT_CONT_EN; // Disable EN
234     _LCDPORT_CONT_LATCH = b;
235
236     d = _LCDPORT_TRIS_DATA;
237     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
238     _LCDPORT_TRIS_DATA = d;
239
240 #endif
241     // End of Command.
242     _ACM1602_SHORT_WAIT(); // Wait 50us
243 }
244
245 static void sendonce(unsigned char addr, unsigned char cmd)
246 {
247 #ifdef _LCD_IF_4BIT
248     unsigned char b, d;
249     unsigned char h;
250
251     h = cmd & 0xf0; // Higher bit is used.
252     // Higher NIBBLE
253     d = _LCDPORT_TRIS_CONT;
254     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
255     _LCDPORT_TRIS_CONT = d;
256
257     b = _LCDPORT_CONT_LATCH;
258     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
259     b |= h;
260     _LCDPORT_CONT_LATCH = b;
261     _ACM1602_TC_WAIT(); // Wait 2.5?us
262
263     b |= _LCDPORT_CONT_EN; // Send CMD
264     _LCDPORT_CONT_LATCH = b;
265     _ACM1602_TC_WAIT(); // Wait 2.5?us
266
267     b &= ~_LCDPORT_CONT_EN; // Disable EN
268     _LCDPORT_CONT_LATCH = b;
269     _ACM1602_TC_WAIT();
270
271     d = _LCDPORT_TRIS_CONT;
272     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
273     _LCDPORT_TRIS_CONT = d;
274
275 #else
276     unsigned char b, d;
277
278     d = _LCDPORT_TRIS_DATA;
279     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
280     _LCDPORT_TRIS_DATA = d;
281
282     b = _LCDPORT_CONT_LATCH;
283     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
284     _LCDPORT_CONT_LATCH = b;
285
286     _LCDPORT_LATCH_DATA = cmd;
287
288     b |= _LCDPORT_CONT_EN; // Send CMD
289     _LCDPORT_CONT_LATCH = b;
290     _ACM1602_TC_WAIT(); // Wait 2.5?us
291
292     b &= ~_LCDPORT_CONT_EN; // Disable EN
293     _LCDPORT_CONT_LATCH = b;
294 //    _ACM1602_TC_WAIT();
295 #endif
296     _ACM1602_SHORT_WAIT(); // Wait 50us
297 }
298
299 static void acm1602_ioinit(unsigned char addr)
300 {
301     unsigned char b;
302
303 //    lcd_waitbusy(0);
304     _ACM1602_LONG_LONG_WAIT();
305 #ifdef _LCD_IF_4BIT
306     b = _LCDPORT_TRIS_CONT;
307     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN | 0xf0);
308     _LCDPORT_TRIS_CONT = b; // Clear Tristate bits, output.
309
310     b = _LCDPORT_CONT_LATCH;
311     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN | 0xf0);
312     _LCDPORT_CONT_LATCH = b;
313   //  _LCDPORT_TRIS_DATA = 0x00; // OUT
314   //  _LCDPORT_LATCH_DATA = 0x00;
315 #else
316     b = _LCDPORT_TRIS_CONT;
317     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
318     _LCDPORT_TRIS_CONT = b; // Clear Tristate bits, output.
319     b = _LCDPORT_CONT_LATCH;
320     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
321     _LCDPORT_CONT_LATCH = b;
322     _LCDPORT_TRIS_DATA = 0x00; // OUT
323     _LCDPORT_LATCH_DATA = 0x00;
324 #endif
325 }
326
327
328 void acm1602_putchar(unsigned char addr, unsigned char c)
329 {
330     unsigned char b, d;
331 #ifdef _LCD_IF_4BIT
332     unsigned char h, l;
333     h = c & 0xf0;
334     l = (c & 0x0f)<<4;
335
336     lcd_waitbusy(addr, 0);
337     d = _LCDPORT_TRIS_CONT;
338     d &= ~(_LCDPORT_READMASK | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // Clear mask for Tristate, direction = write.
339     d = 0;
340     _LCDPORT_TRIS_CONT = d;
341     _ACM1602_TC_WAIT(); // Wait 2.5?us
342
343     // Send high nibble
344     b = _LCDPORT_CONT_LATCH;
345     b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN); // DATA=blank,RW='0'
346     b |= _LCDPORT_CONT_RS; // RS='1"
347     b |= h;
348     _LCDPORT_CONT_LATCH = b;
349     _ACM1602_TC_WAIT(); // Wait 2.5?us
350
351     b |= _LCDPORT_CONT_EN; // Do high write.
352     _LCDPORT_CONT_LATCH = b;
353     _ACM1602_TC_WAIT(); // Wait 2.5?us
354
355     b &= ~_LCDPORT_CONT_EN; // Disable EN
356     _LCDPORT_CONT_LATCH = b;
357     _ACM1602_SHORT_WAIT();
358
359 //    lcd_waitbusy(addr, 0);
360     b = _LCDPORT_CONT_LATCH;
361     b &= 0x0f; // DATA=blank,RW='0'
362     b |= _LCDPORT_CONT_RS; // RS='1"
363     b |= l;
364     _LCDPORT_CONT_LATCH = b;
365     _ACM1602_TC_WAIT(); // Wait 2.5?us
366
367     b |= _LCDPORT_CONT_EN;
368     _LCDPORT_CONT_LATCH = b; // Do low write.
369     _ACM1602_TC_WAIT(); // Wait 2.5?us
370
371     b &= ~_LCDPORT_CONT_EN; // Disable EN
372     _LCDPORT_CONT_LATCH = b;
373     _ACM1602_TC_WAIT(); // Wait 2.5?us
374
375
376 #else
377     lcd_waitbusy(addr, 0);
378     d = _LCDPORT_TRIS_DATA;
379     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
380     _LCDPORT_TRIS_DATA = d;
381
382     b = _LCDPORT_CONT_LATCH;
383     b &= ~_LCDPORT_CONT_RW; // ,RW='0'
384     b |= _LCDPORT_CONT_RS; // RS='1"
385     _LCDPORT_LATCH_DATA = c;
386     _LCDPORT_CONT_LATCH = b;
387     _ACM1602_TC_WAIT(); // Wait 2.5?us
388
389     b |= _LCDPORT_CONT_EN; // Send character
390     _LCDPORT_CONT_LATCH = b;
391     _ACM1602_TC_WAIT(); // Wait 2.5?us
392
393     b &= ~_LCDPORT_CONT_EN; // Disable EN
394     _LCDPORT_CONT_LATCH = b;
395     _ACM1602_SHORT_WAIT(); // Wait 0.1ms
396 #endif
397 }
398
399 unsigned char acm1602_getchar(unsigned char addr)
400 {
401     unsigned char b, d;
402 #ifdef _LCD_IF_4BIT
403     unsigned char h, l;
404
405     lcd_waitbusy(addr, 0);
406     d = _LCDPORT_TRIS_CONT;
407     d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
408     _LCDPORT_TRIS_CONT = d;
409
410     // Recv high nibble
411     b = _LCDPORT_CONT_LATCH;
412     b &= ~(0xf0 | _LCDPORT_CONT_EN); // DATA=blank
413     b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='1", RW='1'
414     _LCDPORT_CONT_LATCH = b;
415     _ACM1602_TC_WAIT(); // Wait 2.5?us
416
417     b |= _LCDPORT_CONT_EN;
418     _LCDPORT_CONT_LATCH = b;
419     _ACM1602_TC_WAIT(); // Wait 2.5?us
420
421     h = _LCDPORT_DATA & 0xf0;
422     _ACM1602_TC_WAIT(); // Wait 2.5?us
423
424     b &= ~_LCDPORT_CONT_EN; // Disable EN
425     _LCDPORT_CONT_LATCH = b;
426     _ACM1602_TC_WAIT();
427
428     lcd_waitbusy(addr, 0);
429     // Recv Low nibble.
430     d = _LCDPORT_TRIS_CONT;
431     d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
432     _LCDPORT_TRIS_CONT = d;
433
434     b = _LCDPORT_CONT_LATCH;
435     b &= ~(0xf0 | _LCDPORT_CONT_EN); // DATA=blank
436     b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='1", RW='1'
437     _LCDPORT_CONT_LATCH = b;
438     _ACM1602_TC_WAIT(); // Wait 2.5?us
439
440     b |= _LCDPORT_CONT_EN;
441     _LCDPORT_CONT_LATCH = b;
442     _ACM1602_TC_WAIT(); // Wait 2.5?us
443
444     l = _LCDPORT_DATA & 0xf0;
445     _ACM1602_TC_WAIT(); // Wait 2.5?us
446
447     b &= ~_LCDPORT_CONT_EN; // Disable EN
448     _LCDPORT_CONT_LATCH = b;
449     _ACM1602_TC_WAIT(); // Wait 2.5?us
450
451     d = _LCDPORT_TRIS_CONT;
452     d &= ~_LCDPORT_READMASK; // Set mask for Tristate, direction = write.
453     _LCDPORT_TRIS_CONT = d;
454
455     _ACM1602_SHORT_WAIT();
456
457     d = h | (l >> 4);
458     return d;
459 #else
460     unsigned char e;
461     lcd_waitbusy(addr, 0);
462     d = _LCDPORT_TRIS_DATA;
463     d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
464     _LCDPORT_TRIS_DATA = d;
465
466     b = _LCDPORT_CONT_LATCH;
467     b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RW=1, RS=1
468     b &= ~_LCDPORT_CONT_EN; // Clear Enable
469     _LCDPORT_CONT_LATCH = b;
470     _ACM1602_TC_WAIT();
471
472     b |= _LCDPORT_CONT_EN; // Send character
473     _LCDPORT_CONT_LATCH = b;
474     _ACM1602_TC_WAIT(); // Wait 2.5?us
475
476     e = _LCDPORT_DATA; // Read BYTE
477     _ACM1602_TC_WAIT();
478
479     b &= ~_LCDPORT_CONT_EN; // Disable EN
480     _LCDPORT_CONT_LATCH = b;
481
482     d = _LCDPORT_TRIS_DATA;
483     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = read.
484     _LCDPORT_TRIS_DATA = d;
485
486     _ACM1602_SHORT_WAIT(); // Wait 0.1ms
487     return e;
488 #endif
489 }
490
491 #endif
492
493 void acm1602_cls(unsigned char addr)
494 {
495     sendcmd(addr, 0x01, 0xff);
496     _ACM1602_LONG_LONG_WAIT(); // Wait 5ms
497 }
498
499 void acm1602_setdataramaddress(unsigned char addr, unsigned char pos)
500 {
501     unsigned char cmd = (pos & 0x7f) | 0x80;
502     sendcmd(addr, cmd, 0xff);
503 }
504
505 void acm1602_locate_16x2(unsigned char addr, char x, char y)
506 {
507     unsigned char ramaddr;
508     ramaddr = (y == 0)? x & 0x0f : (x & 0x0f) | 0x40;
509     acm1602_setdataramaddress(addr, ramaddr);
510 }
511
512 /*
513  * For using
514  */
515 void acm1602_locate_8x2(unsigned char addr, char x, char y)
516 {
517     unsigned char ramaddr;
518     if((x < 0) || (x > 8)) return;
519     if((y < 0) || (y > 1)) return;
520     ramaddr = (y == 0)? x & 0x0f : (x & 0x0f) | 0x40;
521     acm1602_setdataramaddress(addr, ramaddr);
522 }
523
524 void acm1602_home(unsigned char addr)
525 {
526     sendcmd(addr, 0x02, 0xff);
527     _ACM1602_LONG_LONG_WAIT(); // Wait 5ms
528 }
529
530 void acm1602_printf(unsigned char addr, const char *fmt, ...)
531 {
532     char strbuf[32]; // Max 32 bytes.
533     va_list args;
534     int i;
535     int l;
536
537     strbuf[0] = '\0';
538     va_start(args, fmt );
539     sprintf(strbuf, args);
540     l = strlen(strbuf);
541     if((l >= 32) || (l <= 0))return;
542     for(i = 0; i < l; i++) {
543         acm1602_putchar(addr, strbuf[i]);
544     }
545 }
546
547 void acm1602_cursordir(unsigned char addr, unsigned char right)
548 {
549     unsigned char cmd;
550     if(right == 0) {
551         cmd = 0x18;
552     } else {
553         cmd = 0x1c;
554     }
555     sendcmd(addr, cmd, 0xff);
556 }
557
558 void acm1602_setcgramaddress(unsigned char addr, unsigned char pos)
559 {
560     unsigned char cmd = (pos & 0x3f) | 0x40;
561     sendcmd(addr, cmd, 0xff);
562 }
563
564 void acm1602_init(unsigned char addr, unsigned char cls)
565 {
566     acm1602_ioinit(addr);
567 #ifdef _USE_I2C_1602
568     sendcmd(addr,0x01,0x00);
569     sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
570 //    sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
571 #else
572   #ifndef _LCD_IF_4BIT
573     sendonce(addr, 0x38); // 2lines, 8x10dot fonts.
574     sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
575   #else // 4Bit
576     _ACM1602_LONG_LONG_WAIT();
577     sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
578     _ACM1602_SHORT_WAIT();
579     sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
580     _ACM1602_SHORT_WAIT();
581     sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
582     _ACM1602_SHORT_WAIT();
583     sendonce(addr, 0x20); // 2lines, 8x10dot fonts.
584     _ACM1602_SHORT_WAIT();
585     // Send twice on 4Bit Mode.
586 //    sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
587     sendcmd(addr, 0x28, 0x00); // 2lines, 8x5dot fonts.
588   #endif
589 #endif
590 //    sendcmd(addr, 0x08, 0xff); // Display OFF.
591     sendcmd(addr, 0x0c, 0xff); // Display ON.
592     sendcmd(addr, 0x06, 0xff); // Cursor increment,not shift.
593    if(cls == 0){
594         acm1602_home(addr);
595     } else {
596         acm1602_cls(addr);
597     }
598     _ACM1602_LONG_WAIT();
599 //    sendcmd(addr, 0x06, 0xff);
600 }
601 /*
602  * st7032 extensions.
603  */
604 void st7032_extcmd(unsigned char addr, unsigned char mode, 
605         unsigned char cmd, unsigned char busyf)
606 {
607     unsigned char m = mode & 0x1c;
608     m = m | 0x21;
609     sendcmd(addr, m, busyf); // Shift to IS1
610     sendcmd(addr, cmd, busyf);
611     m &= 0xfe; // Shift to IS0
612     sendcmd(addr, m, busyf);
613 }
614
615 void st7032_setcontrast(unsigned char addr, unsigned char value,
616         unsigned char busyf)
617 {
618     unsigned char val = value & 0x0f;
619     val |= 0x70;
620     st7032_extcmd(addr, 0x38, val, busyf);
621 }
622
623 void acm1602_setbacklight(unsigned char flag)
624 {
625     unsigned char b;
626
627     b = _LCDPORT_CONT;
628     if(flag == 0){
629         b &= ~_LCDPORT_CONT_BACKLIGHT;
630     } else {
631         b |= _LCDPORT_CONT_BACKLIGHT;
632     }
633     _LCDPORT_CONT_LATCH = b;
634 }