3 * I2C/Parallel LCD ACM1602 Handler, variant of ST7066U.
4 * Copyright (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
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.
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,
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.
30 #include "lcd_acm1602.h"
33 static unsigned char lcd_busychk(addr)
38 i2c_writechar(addr | 0x01); // Read
42 _ACM1602_I2C_WAIT(); // 5.5ms
43 if((d & _LCDPORT_BUSYMASK) != 0){
51 void lcd_waitbusy(unsigned char addr, unsigned char flag)
55 if(ff != 0) ff = 0xff;
57 f = lcd_busychk(addr);
58 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
63 static void sendcmd(unsigned char addr, unsigned char cmd, unsigned char busyflag)
67 i2c_writechar(addr & 0xfe);
71 _ACM1602_I2C_WAIT(); // 5.5ms
74 static void sendonce(unsigned char addr, unsigned char cmd)
76 sendcmd(addr, cmd, 0x00);
79 static void acm1602_ioinit(unsigned char addr)
81 _ACM1602_LONG_LONG_WAIT();
85 void acm1602_putchar(unsigned char addr, unsigned char c)
89 i2c_writechar(addr & 0xfe);
90 i2c_writechar(0x80); //Data
91 i2c_writechar(c); // Putchar
93 _ACM1602_I2C_WAIT(); // Wait 50us
97 unsigned char acm1602_getchar(unsigned char addr)
102 i2c_writechar(addr | 0x01); // Read
106 _ACM1602_I2C_WAIT(); // 5.5ms
110 static unsigned char lcd_busychk(unsigned char addr)
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;
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
125 b |= _LCDPORT_CONT_EN; // Send CMD
126 _LCDPORT_CONT_LATCH = b;
127 _ACM1602_TC_WAIT(); // Wait 2.5?us
130 _ACM1602_TC_WAIT(); // Wait 2.5?us
132 b &= ~_LCDPORT_CONT_EN; // Disable EN
133 _LCDPORT_CONT_LATCH = b;
134 _ACM1602_TC_WAIT(); // Wait 2.5?us
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
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
148 if((d & _LCDPORT_BUSYMASK) != 0){
156 void lcd_waitbusy(unsigned char addr, unsigned char flag)
160 if(ff != 0) ff = 0xff;
162 f = lcd_busychk(addr);
163 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
167 static void sendcmd(unsigned char addr, unsigned char cmd,unsigned char busyflag)
173 h = cmd & 0xf0; // Higher bit is used.
174 l = (cmd & 0x0f) << 4; // Higher bit is used.
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;
182 b = _LCDPORT_CONT_LATCH;
183 b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
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;
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"
202 _LCDPORT_CONT_LATCH = b;
203 _ACM1602_TC_WAIT(); // Wait 2.5?us
204 b |= _LCDPORT_CONT_EN;
205 _LCDPORT_CONT_LATCH = b;
207 _ACM1602_TC_WAIT(); // Wait 2.5?us
208 b &= ~_LCDPORT_CONT_EN; // Disable EN
209 _LCDPORT_CONT_LATCH = b;
211 d = _LCDPORT_TRIS_CONT;
212 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
213 _LCDPORT_TRIS_CONT = d;
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;
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;
227 _LCDPORT_LATCH_DATA = cmd;
229 b |= _LCDPORT_CONT_EN; // Send CMD
230 _LCDPORT_CONT_LATCH = b;
231 _ACM1602_TC_WAIT(); // Wait 2.5?us
233 b &= ~_LCDPORT_CONT_EN; // Disable EN
234 _LCDPORT_CONT_LATCH = b;
236 d = _LCDPORT_TRIS_DATA;
237 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
238 _LCDPORT_TRIS_DATA = d;
242 _ACM1602_SHORT_WAIT(); // Wait 50us
245 static void sendonce(unsigned char addr, unsigned char cmd)
251 h = cmd & 0xf0; // Higher bit is used.
253 d = _LCDPORT_TRIS_CONT;
254 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
255 _LCDPORT_TRIS_CONT = d;
257 b = _LCDPORT_CONT_LATCH;
258 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
260 _LCDPORT_CONT_LATCH = b;
261 _ACM1602_TC_WAIT(); // Wait 2.5?us
263 b |= _LCDPORT_CONT_EN; // Send CMD
264 _LCDPORT_CONT_LATCH = b;
265 _ACM1602_TC_WAIT(); // Wait 2.5?us
267 b &= ~_LCDPORT_CONT_EN; // Disable EN
268 _LCDPORT_CONT_LATCH = b;
271 d = _LCDPORT_TRIS_CONT;
272 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
273 _LCDPORT_TRIS_CONT = d;
278 d = _LCDPORT_TRIS_DATA;
279 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
280 _LCDPORT_TRIS_DATA = d;
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;
286 _LCDPORT_LATCH_DATA = cmd;
288 b |= _LCDPORT_CONT_EN; // Send CMD
289 _LCDPORT_CONT_LATCH = b;
290 _ACM1602_TC_WAIT(); // Wait 2.5?us
292 b &= ~_LCDPORT_CONT_EN; // Disable EN
293 _LCDPORT_CONT_LATCH = b;
294 // _ACM1602_TC_WAIT();
296 _ACM1602_SHORT_WAIT(); // Wait 50us
299 static void acm1602_ioinit(unsigned char addr)
304 _ACM1602_LONG_LONG_WAIT();
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.
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;
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;
328 void acm1602_putchar(unsigned char addr, unsigned char c)
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.
340 _LCDPORT_TRIS_CONT = d;
341 _ACM1602_TC_WAIT(); // Wait 2.5?us
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"
348 _LCDPORT_CONT_LATCH = b;
349 _ACM1602_TC_WAIT(); // Wait 2.5?us
351 b |= _LCDPORT_CONT_EN; // Do high write.
352 _LCDPORT_CONT_LATCH = b;
353 _ACM1602_TC_WAIT(); // Wait 2.5?us
355 b &= ~_LCDPORT_CONT_EN; // Disable EN
356 _LCDPORT_CONT_LATCH = b;
357 _ACM1602_SHORT_WAIT();
359 // lcd_waitbusy(addr, 0);
360 b = _LCDPORT_CONT_LATCH;
361 b &= 0x0f; // DATA=blank,RW='0'
362 b |= _LCDPORT_CONT_RS; // RS='1"
364 _LCDPORT_CONT_LATCH = b;
365 _ACM1602_TC_WAIT(); // Wait 2.5?us
367 b |= _LCDPORT_CONT_EN;
368 _LCDPORT_CONT_LATCH = b; // Do low write.
369 _ACM1602_TC_WAIT(); // Wait 2.5?us
371 b &= ~_LCDPORT_CONT_EN; // Disable EN
372 _LCDPORT_CONT_LATCH = b;
373 _ACM1602_TC_WAIT(); // Wait 2.5?us
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;
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
389 b |= _LCDPORT_CONT_EN; // Send character
390 _LCDPORT_CONT_LATCH = b;
391 _ACM1602_TC_WAIT(); // Wait 2.5?us
393 b &= ~_LCDPORT_CONT_EN; // Disable EN
394 _LCDPORT_CONT_LATCH = b;
395 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
399 unsigned char acm1602_getchar(unsigned char addr)
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;
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
417 b |= _LCDPORT_CONT_EN;
418 _LCDPORT_CONT_LATCH = b;
419 _ACM1602_TC_WAIT(); // Wait 2.5?us
421 h = _LCDPORT_DATA & 0xf0;
422 _ACM1602_TC_WAIT(); // Wait 2.5?us
424 b &= ~_LCDPORT_CONT_EN; // Disable EN
425 _LCDPORT_CONT_LATCH = b;
428 lcd_waitbusy(addr, 0);
430 d = _LCDPORT_TRIS_CONT;
431 d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
432 _LCDPORT_TRIS_CONT = d;
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
440 b |= _LCDPORT_CONT_EN;
441 _LCDPORT_CONT_LATCH = b;
442 _ACM1602_TC_WAIT(); // Wait 2.5?us
444 l = _LCDPORT_DATA & 0xf0;
445 _ACM1602_TC_WAIT(); // Wait 2.5?us
447 b &= ~_LCDPORT_CONT_EN; // Disable EN
448 _LCDPORT_CONT_LATCH = b;
449 _ACM1602_TC_WAIT(); // Wait 2.5?us
451 d = _LCDPORT_TRIS_CONT;
452 d &= ~_LCDPORT_READMASK; // Set mask for Tristate, direction = write.
453 _LCDPORT_TRIS_CONT = d;
455 _ACM1602_SHORT_WAIT();
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;
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;
472 b |= _LCDPORT_CONT_EN; // Send character
473 _LCDPORT_CONT_LATCH = b;
474 _ACM1602_TC_WAIT(); // Wait 2.5?us
476 e = _LCDPORT_DATA; // Read BYTE
479 b &= ~_LCDPORT_CONT_EN; // Disable EN
480 _LCDPORT_CONT_LATCH = b;
482 d = _LCDPORT_TRIS_DATA;
483 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = read.
484 _LCDPORT_TRIS_DATA = d;
486 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
493 void acm1602_cls(unsigned char addr)
495 sendcmd(addr, 0x01, 0xff);
496 _ACM1602_LONG_LONG_WAIT(); // Wait 5ms
499 void acm1602_setdataramaddress(unsigned char addr, unsigned char pos)
501 unsigned char cmd = (pos & 0x7f) | 0x80;
502 sendcmd(addr, cmd, 0xff);
505 void acm1602_locate_16x2(unsigned char addr, char x, char y)
507 unsigned char ramaddr;
508 ramaddr = (y == 0)? x & 0x0f : (x & 0x0f) | 0x40;
509 acm1602_setdataramaddress(addr, ramaddr);
515 void acm1602_locate_8x2(unsigned char addr, char x, char y)
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);
524 void acm1602_home(unsigned char addr)
526 sendcmd(addr, 0x02, 0xff);
527 _ACM1602_LONG_LONG_WAIT(); // Wait 5ms
530 void acm1602_printf(unsigned char addr, const char *fmt, ...)
532 char strbuf[32]; // Max 32 bytes.
538 va_start(args, fmt );
539 sprintf(strbuf, args);
541 if((l >= 32) || (l <= 0))return;
542 for(i = 0; i < l; i++) {
543 acm1602_putchar(addr, strbuf[i]);
547 void acm1602_cursordir(unsigned char addr, unsigned char right)
555 sendcmd(addr, cmd, 0xff);
558 void acm1602_setcgramaddress(unsigned char addr, unsigned char pos)
560 unsigned char cmd = (pos & 0x3f) | 0x40;
561 sendcmd(addr, cmd, 0xff);
564 void acm1602_init(unsigned char addr, unsigned char cls)
566 acm1602_ioinit(addr);
568 sendcmd(addr,0x01,0x00);
569 sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
570 // sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
573 sendonce(addr, 0x38); // 2lines, 8x10dot fonts.
574 sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
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.
590 // sendcmd(addr, 0x08, 0xff); // Display OFF.
591 sendcmd(addr, 0x0c, 0xff); // Display ON.
592 sendcmd(addr, 0x06, 0xff); // Cursor increment,not shift.
598 _ACM1602_LONG_WAIT();
599 // sendcmd(addr, 0x06, 0xff);
604 void st7032_extcmd(unsigned char addr, unsigned char mode,
605 unsigned char cmd, unsigned char busyf)
607 unsigned char m = mode & 0x1c;
609 sendcmd(addr, m, busyf); // Shift to IS1
610 sendcmd(addr, cmd, busyf);
611 m &= 0xfe; // Shift to IS0
612 sendcmd(addr, m, busyf);
615 void st7032_setcontrast(unsigned char addr, unsigned char value,
618 unsigned char val = value & 0x0f;
620 st7032_extcmd(addr, 0x38, val, busyf);
623 void acm1602_setbacklight(unsigned char flag)
629 b &= ~_LCDPORT_CONT_BACKLIGHT;
631 b |= _LCDPORT_CONT_BACKLIGHT;
633 _LCDPORT_CONT_LATCH = b;