OSDN Git Service

2334af11dde1f645f5f7163b130f37183d74f30a
[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     _LCDPORT_CONT_RS = 0;
121     _LCDPORT_CONT_RW = 1;
122 //    _LCDPORT_CONT_LATCH = b;
123     _ACM1602_TC_WAIT(); // Wait 2.5?us
124
125     _LCDPORT_CONT_EN = 1; // 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     _LCDPORT_CONT_EN = 0; // Disable EN
133 //    _LCDPORT_CONT_LATCH = b;
134     _ACM1602_TC_WAIT(); // Wait 2.5?us
135
136     _LCDPORT_CONT_EN = 1; // Disable EN
137 //    _LCDPORT_CONT_LATCH = b;
138     _ACM1602_TC_WAIT(); // Wait 2.5?us
139
140     _LCDPORT_CONT_EN = 0;; // Disable EN
141 //    _LCDPORT_CONT_LATCH = b;
142     _ACM1602_TC_WAIT(); // Wait 2.5?us
143
144     b = _LCDPORT_TRIS_DATA;
145     b &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
146     _LCDPORT_TRIS_DATA = b;
147     _ACM1602_TC_WAIT(); // Wait 2.5?us
148
149     if((d & _LCDPORT_BUSYMASK) != 0){
150         d = 0xff; // BUSY
151     } else {
152         d = 0;
153     }
154     return d;
155 }
156
157 void lcd_waitbusy(unsigned char addr, unsigned char flag)
158 {
159     unsigned char f,ff;
160     ff = flag;
161     if(ff != 0) ff = 0xff;
162     do {
163         f = lcd_busychk(addr);
164         _ACM1602_SHORT_WAIT(); // Wait 0.1ms
165     } while(f != ff);
166 }
167
168 static void sendcmd(unsigned char addr, unsigned char cmd,unsigned char busyflag)
169 {
170 #ifdef _LCD_IF_4BIT
171     unsigned char b, d;
172     unsigned char h,l;
173
174     h = cmd & 0xf0; // Higher bit is used.
175     l = (cmd & 0x0f) << 4; // Higher bit is used.
176     // Higher NIBBLE
177     if(busyflag != 0) lcd_waitbusy(addr, 0);
178     d = _LCDPORT_TRIS_CONT;
179     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
180     _LCDPORT_TRIS_CONT = d;
181
182     _LCDPORT_CONT_RW = 0;
183     _LCDPORT_CONT_EN = 0;
184     _LCDPORT_CONT_RS = 0;
185     _LCDPORT_CONT_LATCH &= 0x0f; // Upper
186 //    b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
187     _LCDPORT_CONT_LATCH |= h;
188 //    _LCDPORT_CONT_LATCH = b;
189     _ACM1602_TC_WAIT(); // Wait 2.5?us
190
191     _LCDPORT_CONT_EN = 1;
192     //_LCDPORT_CONT_LATCH = b;
193     _ACM1602_TC_WAIT(); // Wait 2.5?us
194
195     _LCDPORT_CONT_EN = 0; // Disable EN
196 //    _LCDPORT_CONT_LATCH = b;
197     _ACM1602_TC_WAIT();
198
199     // Lower NIBBLE
200 //    if(busyflag != 0) lcd_waitbusy(addr, 0);
201 //    d = _LCDPORT_TRIS_CONT;
202 //    d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
203 //    _LCDPORT_TRIS_CONT = d;
204
205     _LCDPORT_CONT_RW = 0;
206     _LCDPORT_CONT_EN = 0;
207     _LCDPORT_CONT_RS = 0;
208     _LCDPORT_CONT_LATCH &= 0x0f; // Lower
209
210     _LCDPORT_CONT_LATCH |= l;
211     _ACM1602_TC_WAIT(); // Wait 2.5?us
212     _LCDPORT_CONT_EN = 1;
213 //    _LCDPORT_CONT_LATCH = b;
214
215     _ACM1602_TC_WAIT(); // Wait 2.5?us
216     _LCDPORT_CONT_EN = 0; // Disable EN
217 //    _LCDPORT_CONT_LATCH = b;
218
219 //    d = _LCDPORT_TRIS_CONT;
220  //   d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
221   //  _LCDPORT_TRIS_CONT = d;
222
223 #else
224     unsigned char b,d;
225
226     if(busyflag != 0) lcd_waitbusy(addr, 0);
227     d = _LCDPORT_TRIS_DATA;
228     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
229     _LCDPORT_TRIS_DATA = d;
230
231     b = _LCDPORT_CONT_LATCH;
232     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
233     _LCDPORT_CONT_LATCH = b;
234
235     _LCDPORT_LATCH_DATA = cmd;
236
237     b |= _LCDPORT_CONT_EN; // Send CMD
238     _LCDPORT_CONT_LATCH = b;
239     _ACM1602_TC_WAIT(); // Wait 2.5?us
240
241     b &= ~_LCDPORT_CONT_EN; // Disable EN
242     _LCDPORT_CONT_LATCH = b;
243
244     d = _LCDPORT_TRIS_DATA;
245     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
246     _LCDPORT_TRIS_DATA = d;
247
248 #endif
249     // End of Command.
250     _ACM1602_SHORT_WAIT(); // Wait 50us
251 }
252
253 static void sendonce(unsigned char addr, unsigned char cmd)
254 {
255 #ifdef _LCD_IF_4BIT
256     unsigned char b, d;
257     unsigned char h;
258
259     h = cmd & 0xf0; // Higher bit is used.
260     // Higher NIBBLE
261     //d = _LCDPORT_TRIS_CONT;
262 //    d = TRIS_D_VAL; // Clear mask for Tristate, direction = write.
263 //    _LCDPORT_TRIS_CONT = d;
264     d = _LCDPORT_TRIS_CONT;
265     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
266     _LCDPORT_TRIS_CONT = d;
267
268     _LCDPORT_CONT_RS = 0;
269     _LCDPORT_CONT_RW = 0;
270     _LCDPORT_CONT_EN = 0; // RS='0',RW='0'
271     _LCDPORT_CONT_LATCH &= 0x0f;
272     _LCDPORT_CONT_LATCH |= h;
273     _ACM1602_TC_WAIT(); // Wait 2.5?us
274
275     _LCDPORT_CONT_EN = 1; // Send CMD
276     _ACM1602_TC_WAIT(); // Wait 2.5?us
277
278     _LCDPORT_CONT_EN = 0; // Disable EN
279     _ACM1602_TC_WAIT();
280
281 //    d = _LCDPORT_TRIS_CONT;
282 //    d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
283 //    _LCDPORT_TRIS_CONT = d;
284
285 #else
286     unsigned char b, d;
287
288     d = _LCDPORT_TRIS_DATA;
289     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
290     _LCDPORT_TRIS_DATA = d;
291
292     b = _LCDPORT_CONT_LATCH;
293     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
294     _LCDPORT_CONT_LATCH = b;
295
296     _LCDPORT_LATCH_DATA = cmd;
297
298     b |= _LCDPORT_CONT_EN; // Send CMD
299     _LCDPORT_CONT_LATCH = b;
300     _ACM1602_TC_WAIT(); // Wait 2.5?us
301
302     b &= ~_LCDPORT_CONT_EN; // Disable EN
303     _LCDPORT_CONT_LATCH = b;
304 //    _ACM1602_TC_WAIT();
305 #endif
306     _ACM1602_SHORT_WAIT(); // Wait 50us
307 }
308
309 static void acm1602_ioinit(unsigned char addr)
310 {
311     unsigned char b;
312
313 //    lcd_waitbusy(0);
314     _ACM1602_LONG_LONG_WAIT();
315 #ifdef _LCD_IF_4BIT
316     _LCDPORT_TRIS_CONT = TRIS_D_VAL;
317
318     _LCDPORT_CONT_RS = 0;
319     _LCDPORT_CONT_RW = 0;
320     _LCDPORT_CONT_EN = 0;
321     _LCDPORT_CONT_LATCH &= ~0xf0;
322 //    _LCDPORT_CONT_LATCH = b;
323   //  _LCDPORT_TRIS_DATA = 0x00; // OUT
324   //  _LCDPORT_LATCH_DATA = 0x00;
325 #else
326     b = _LCDPORT_TRIS_CONT;
327     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
328     _LCDPORT_TRIS_CONT = b; // Clear Tristate bits, output.
329     b = _LCDPORT_CONT_LATCH;
330     b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
331     _LCDPORT_CONT_LATCH = b;
332     _LCDPORT_TRIS_DATA = 0x00; // OUT
333     _LCDPORT_LATCH_DATA = 0x00;
334 #endif
335 }
336
337
338 void acm1602_putchar(unsigned char addr, unsigned char c)
339 {
340     unsigned char b, d;
341 #ifdef _LCD_IF_4BIT
342     unsigned char h, l;
343     h = c & 0xf0;
344     l = (c & 0x0f)<<4;
345
346     lcd_waitbusy(addr, 0);
347 //    d = _LCDPORT_TRIS_CONT;
348 //    d &= 0x00; // Clear mask for Tristate, direction = write.
349     d = TRIS_D_VAL; // ALL OUT
350     _LCDPORT_TRIS_CONT = d;
351     _ACM1602_TC_WAIT(); // Wait 2.5?us
352
353     // Send high nibble
354     //b = _LCDPORT_CONT_LATCH;
355     _LCDPORT_CONT_RW = 0;
356     _LCDPORT_CONT_EN = 0; // DATA=blank,RW='0'
357     _LCDPORT_CONT_LATCH &= ~0xf0;
358     _LCDPORT_CONT_RS = 1; // RS='1"
359 //    _LCDPORT_CONT_LATCH = b;
360     _ACM1602_TC_WAIT(); // Wait 2.5?us
361
362     _LCDPORT_CONT_EN = 1; // Do high write.
363 //    b |= h;
364     _LCDPORT_CONT_LATCH |= h;
365     _ACM1602_TC_WAIT(); // Wait 2.5?us
366
367     _LCDPORT_CONT_EN = 0; // Disable EN
368 //    _LCDPORT_CONT_LATCH = b;
369     _ACM1602_SHORT_WAIT();
370
371 //    lcd_waitbusy(addr, 0);
372     _LCDPORT_CONT_LATCH &= ~0xf0;
373     _LCDPORT_CONT_RS = 1; // RS='1"
374     _ACM1602_TC_WAIT(); // Wait 2.5?us
375
376     _LCDPORT_CONT_LATCH |= l; // Do low write.
377     _LCDPORT_CONT_EN = 1;
378     _ACM1602_TC_WAIT(); // Wait 2.5?us
379
380     _LCDPORT_CONT_EN = 0; // Disable EN
381     _ACM1602_SHORT_WAIT();
382
383
384 #else
385     lcd_waitbusy(addr, 0);
386     d = _LCDPORT_TRIS_DATA;
387     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
388     _LCDPORT_TRIS_DATA = d;
389
390     b = _LCDPORT_CONT_LATCH;
391     b &= ~_LCDPORT_CONT_RW; // ,RW='0'
392     b |= _LCDPORT_CONT_RS; // RS='1"
393     _LCDPORT_LATCH_DATA = c;
394     _LCDPORT_CONT_LATCH = b;
395     _ACM1602_TC_WAIT(); // Wait 2.5?us
396
397     b |= _LCDPORT_CONT_EN; // Send character
398     _LCDPORT_CONT_LATCH = b;
399     _ACM1602_TC_WAIT(); // Wait 2.5?us
400
401     b &= ~_LCDPORT_CONT_EN; // Disable EN
402     _LCDPORT_CONT_LATCH = b;
403     _ACM1602_SHORT_WAIT(); // Wait 0.1ms
404 #endif
405 }
406
407 #if 0
408 unsigned char acm1602_getchar(unsigned char addr)
409 {
410     unsigned char b, d;
411 #ifdef _LCD_IF_4BIT
412     unsigned char h, l;
413
414     lcd_waitbusy(addr, 0);
415     d = _LCDPORT_TRIS_CONT;
416     d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
417     _LCDPORT_TRIS_CONT = d;
418
419     // Recv high nibble
420     b = _LCDPORT_CONT_LATCH;
421     b &= ~(0xf0 | _LCDPORT_CONT_EN); // DATA=blank
422     b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='1", RW='1'
423     _LCDPORT_CONT_LATCH = b;
424     _ACM1602_TC_WAIT(); // Wait 2.5?us
425
426     b |= _LCDPORT_CONT_EN;
427     _LCDPORT_CONT_LATCH = b;
428     _ACM1602_TC_WAIT(); // Wait 2.5?us
429
430     h = _LCDPORT_DATA & 0xf0;
431     _ACM1602_TC_WAIT(); // Wait 2.5?us
432
433     b &= ~_LCDPORT_CONT_EN; // Disable EN
434     _LCDPORT_CONT_LATCH = b;
435     _ACM1602_TC_WAIT();
436
437     lcd_waitbusy(addr, 0);
438     // Recv Low nibble.
439     d = _LCDPORT_TRIS_CONT;
440     d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
441     _LCDPORT_TRIS_CONT = d;
442
443     b = _LCDPORT_CONT_LATCH;
444     b &= ~(0xf0 | _LCDPORT_CONT_EN); // DATA=blank
445     b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='1", RW='1'
446     _LCDPORT_CONT_LATCH = b;
447     _ACM1602_TC_WAIT(); // Wait 2.5?us
448
449     b |= _LCDPORT_CONT_EN;
450     _LCDPORT_CONT_LATCH = b;
451     _ACM1602_TC_WAIT(); // Wait 2.5?us
452
453     l = _LCDPORT_DATA & 0xf0;
454     _ACM1602_TC_WAIT(); // Wait 2.5?us
455
456     b &= ~_LCDPORT_CONT_EN; // Disable EN
457     _LCDPORT_CONT_LATCH = b;
458     _ACM1602_TC_WAIT(); // Wait 2.5?us
459
460     d = _LCDPORT_TRIS_CONT;
461     d &= ~_LCDPORT_READMASK; // Set mask for Tristate, direction = write.
462     _LCDPORT_TRIS_CONT = d;
463
464     _ACM1602_SHORT_WAIT();
465
466     d = h | (l >> 4);
467     return d;
468 #else
469     unsigned char e;
470     lcd_waitbusy(addr, 0);
471     d = _LCDPORT_TRIS_DATA;
472     d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
473     _LCDPORT_TRIS_DATA = d;
474
475     b = _LCDPORT_CONT_LATCH;
476     b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RW=1, RS=1
477     b &= ~_LCDPORT_CONT_EN; // Clear Enable
478     _LCDPORT_CONT_LATCH = b;
479     _ACM1602_TC_WAIT();
480
481     b |= _LCDPORT_CONT_EN; // Send character
482     _LCDPORT_CONT_LATCH = b;
483     _ACM1602_TC_WAIT(); // Wait 2.5?us
484
485     e = _LCDPORT_DATA; // Read BYTE
486     _ACM1602_TC_WAIT();
487
488     b &= ~_LCDPORT_CONT_EN; // Disable EN
489     _LCDPORT_CONT_LATCH = b;
490
491     d = _LCDPORT_TRIS_DATA;
492     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = read.
493     _LCDPORT_TRIS_DATA = d;
494
495     _ACM1602_SHORT_WAIT(); // Wait 0.1ms
496     return e;
497 #endif
498 }
499 #endif
500 #endif
501
502 void acm1602_cls(unsigned char addr)
503 {
504     sendcmd(addr, 0x01, 0xff);
505     _ACM1602_LONG_LONG_WAIT(); // Wait 5ms
506 }
507
508 void acm1602_setdataramaddress(unsigned char addr, unsigned char pos)
509 {
510     unsigned char cmd = (pos & 0x7f) | 0x80;
511     sendcmd(addr, cmd, 0xff);
512 }
513
514 void acm1602_locate_16x2(unsigned char addr, char x, char y)
515 {
516     unsigned char ramaddr;
517     ramaddr = (y == 0)? x & 0x0f : (x & 0x0f) | 0x40;
518     acm1602_setdataramaddress(addr, ramaddr);
519 }
520
521 /*
522  * For using
523  */
524 void acm1602_locate_8x2(unsigned char addr, char x, char y)
525 {
526     unsigned char ramaddr;
527     if((x < 0) || (x > 8)) return;
528     if((y < 0) || (y > 1)) return;
529     ramaddr = (y == 0)? x & 0x0f : (x & 0x0f) | 0x40;
530     acm1602_setdataramaddress(addr, ramaddr);
531 }
532
533 void acm1602_home(unsigned char addr)
534 {
535     sendcmd(addr, 0x02, 0xff);
536     _ACM1602_LONG_LONG_WAIT(); // Wait 5ms
537 }
538
539
540 void acm1602_cursordir(unsigned char addr, unsigned char right)
541 {
542     unsigned char cmd;
543     if(right == 0) {
544         cmd = 0x18;
545     } else {
546         cmd = 0x1c;
547     }
548     sendcmd(addr, cmd, 0xff);
549 }
550
551 void acm1602_setcgramaddress(unsigned char addr, unsigned char pos)
552 {
553     unsigned char cmd = (pos & 0x3f) | 0x40;
554     sendcmd(addr, cmd, 0xff);
555 }
556
557 void acm1602_init(unsigned char addr, unsigned char cls)
558 {
559     acm1602_ioinit(addr);
560 #ifdef _USE_I2C_1602
561     sendcmd(addr,0x01,0x00);
562     sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
563 //    sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
564 #else
565   #ifndef _LCD_IF_4BIT
566     sendonce(addr, 0x38); // 2lines, 8x10dot fonts.
567     sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
568   #else // 4Bit
569     _ACM1602_LONG_LONG_WAIT();
570     sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
571     _ACM1602_SHORT_WAIT();
572     sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
573     _ACM1602_SHORT_WAIT();
574     sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
575     _ACM1602_SHORT_WAIT();
576     sendonce(addr, 0x20); // 2lines, 8x10dot fonts.
577     _ACM1602_SHORT_WAIT();
578     // Send twice on 4Bit Mode.
579 //    sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
580     sendcmd(addr, 0x28, 0xff); // 2lines, 8x5dot fonts.
581   #endif
582 #endif
583 //    sendcmd(addr, 0x08, 0xff); // Display OFF.
584     sendcmd(addr, 0x0c, 0xff); // Display ON.
585     sendcmd(addr, 0x06, 0xff); // Cursor increment,not shift.
586    if(cls == 0){
587         acm1602_home(addr);
588     } else {
589         acm1602_cls(addr);
590     }
591     _ACM1602_LONG_WAIT();
592 //    sendcmd(addr, 0x06, 0xff);
593 }
594
595 /*
596  * Suspend lcd
597  */
598 void acm1602_suspend(unsigned char addr)
599 {
600     sendcmd(addr, 0x08, 0xff);
601     _ACM1602_LONG_WAIT();
602 }
603
604 #ifdef _USE_I2C_1602
605 /*
606  * st7032 extensions.
607  */
608 void st7032_extcmd(unsigned char addr, unsigned char mode, 
609         unsigned char cmd, unsigned char busyf)
610 {
611     unsigned char m = mode & 0x1c;
612     m = m | 0x21;
613     sendcmd(addr, m, busyf); // Shift to IS1
614     sendcmd(addr, cmd, busyf);
615     m &= 0xfe; // Shift to IS0
616     sendcmd(addr, m, busyf);
617 }
618
619 void st7032_setcontrast(unsigned char addr, unsigned char value,
620         unsigned char busyf)
621 {
622     unsigned char val = value & 0x0f;
623     val |= 0x70;
624     st7032_extcmd(addr, 0x38, val, busyf);
625 }
626 #endif