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(void)
38 if((d & _LCDPORT_BUSYMASK) != 0){
46 static void lcd_waitbusy(unsigned char flag)
50 if(ff != 0) ff = 0xff;
53 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
58 static void sendcmd(unsigned char addr, unsigned char cmd, unsigned char busyflag)
66 _ACM1602_I2C_WAIT(); // 0.2ms
69 static void sendonce(unsigned char addr, unsigned char cmd)
71 sendcmd(addr, cmd, 0x00);
74 static void acm1602_ioinit(unsigned char addr)
76 _ACM1602_LONG_LONG_WAIT();
80 void acm1602_putchar(unsigned char addr, unsigned char c)
85 i2c_writechar(0x80); //Data
86 i2c_writechar(c); // Putchar
88 _ACM1602_SHORT_WAIT(); // Wait 50us
91 unsigned char acm1602_getchar(unsigned char addr)
97 static unsigned char lcd_busychk(void)
101 // Set mask for Tristate.
102 b = _LCDPORT_TRIS_DATA;
103 b |= _LCDPORT_READMASK;// Set mask for Tristate, direction = read.
104 _LCDPORT_TRIS_DATA = b;
106 b = _LCDPORT_CONT_LATCH;
107 b &= ~_LCDPORT_CONT_RS;
108 b |= _LCDPORT_CONT_RW;
109 _LCDPORT_CONT_LATCH = b;
110 b |= _LCDPORT_CONT_EN; // Send CMD
111 _LCDPORT_CONT_LATCH = b;
112 _ACM1602_TC_WAIT(); // Wait 2.5?us
114 b &= ~_LCDPORT_CONT_EN; // Disable EN
115 _LCDPORT_CONT_LATCH = b;
117 b = _LCDPORT_TRIS_DATA;
118 b &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
119 _LCDPORT_TRIS_DATA = b;
121 if((d & _LCDPORT_BUSYMASK) != 0){
129 static void lcd_waitbusy(unsigned char flag)
133 if(ff != 0) ff = 0xff;
136 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
140 static void sendcmd(unsigned char addr, unsigned char cmd,unsigned char busyflag)
146 h = cmd & 0xf0; // Higher bit is used.
147 l = (cmd & 0x0f) << 4; // Higher bit is used.
149 if(busyflag != 0) lcd_waitbusy(0);
150 d = _LCDPORT_TRIS_CONT;
151 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
152 _LCDPORT_TRIS_CONT = d;
155 b = _LCDPORT_CONT_LATCH;
156 b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
158 _LCDPORT_CONT_LATCH = b;
159 _ACM1602_TC_WAIT(); // Wait 2.5?us
160 b |= _LCDPORT_CONT_EN;
161 _LCDPORT_CONT_LATCH = b;
162 _ACM1602_TC_WAIT(); // Wait 2.5?us
163 b &= ~_LCDPORT_CONT_EN; // Disable EN
164 _LCDPORT_CONT_LATCH = b;
168 if(busyflag != 0) lcd_waitbusy(0);
169 d = _LCDPORT_TRIS_CONT;
170 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
171 _LCDPORT_TRIS_CONT = d;
172 b = _LCDPORT_CONT_LATCH;
173 b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
175 _LCDPORT_CONT_LATCH = b;
176 _ACM1602_TC_WAIT(); // Wait 2.5?us
177 b |= _LCDPORT_CONT_EN;
178 _LCDPORT_CONT_LATCH = b;
179 _ACM1602_TC_WAIT(); // Wait 2.5?us
180 b &= ~_LCDPORT_CONT_EN; // Disable EN
181 _LCDPORT_CONT_LATCH = b;
183 d = _LCDPORT_TRIS_CONT;
184 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
185 _LCDPORT_TRIS_CONT = d;
190 if(busyflag != 0) lcd_waitbusy(0);
191 d = _LCDPORT_TRIS_DATA;
192 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
193 _LCDPORT_TRIS_DATA = d;
195 b = _LCDPORT_CONT_LATCH;
196 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
197 _LCDPORT_CONT_LATCH = b;
199 _LCDPORT_LATCH_DATA = cmd;
201 b |= _LCDPORT_CONT_EN; // Send CMD
202 _LCDPORT_CONT_LATCH = b;
203 _ACM1602_TC_WAIT(); // Wait 2.5?us
205 b &= ~_LCDPORT_CONT_EN; // Disable EN
206 _LCDPORT_CONT_LATCH = b;
208 d = _LCDPORT_TRIS_DATA;
209 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
210 _LCDPORT_TRIS_DATA = d;
214 _ACM1602_SHORT_WAIT(); // Wait 50us
217 static void sendonce(unsigned char addr, unsigned char cmd)
223 h = cmd & 0xf0; // Higher bit is used.
225 d = _LCDPORT_TRIS_CONT;
226 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
227 _LCDPORT_TRIS_CONT = d;
229 b = _LCDPORT_CONT_LATCH;
230 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
232 _LCDPORT_CONT_LATCH = b;
234 b |= _LCDPORT_CONT_EN; // Send CMD
235 _LCDPORT_CONT_LATCH = b;
236 _ACM1602_TC_WAIT(); // Wait 2.5?us
238 b &= ~_LCDPORT_CONT_EN; // Disable EN
239 _LCDPORT_CONT_LATCH = b;
242 d = _LCDPORT_TRIS_CONT;
243 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
244 _LCDPORT_TRIS_CONT = d;
249 d = _LCDPORT_TRIS_DATA;
250 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
251 _LCDPORT_TRIS_DATA = d;
253 b = _LCDPORT_CONT_LATCH;
254 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
255 _LCDPORT_CONT_LATCH = b;
257 _LCDPORT_LATCH_DATA = cmd;
259 b |= _LCDPORT_CONT_EN; // Send CMD
260 _LCDPORT_CONT_LATCH = b;
261 _ACM1602_TC_WAIT(); // Wait 2.5?us
263 b &= ~_LCDPORT_CONT_EN; // Disable EN
264 _LCDPORT_CONT_LATCH = b;
265 // _ACM1602_TC_WAIT();
267 _ACM1602_SHORT_WAIT(); // Wait 50us
270 static void acm1602_ioinit(unsigned char addr)
275 _ACM1602_LONG_LONG_WAIT();
277 b = _LCDPORT_TRIS_CONT;
278 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN | 0xf0);
279 _LCDPORT_TRIS_CONT = b; // Clear Tristate bits, output.
281 b = _LCDPORT_CONT_LATCH;
282 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN | 0xf0);
283 _LCDPORT_CONT_LATCH = b;
285 //_LCDPORT_TRIS_DATA = 0x00; // OUT
286 //_LCDPORT_LATCH_DATA = 0x00;
288 b = _LCDPORT_TRIS_CONT;
289 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
290 _LCDPORT_TRIS_CONT = b; // Clear Tristate bits, output.
291 b = _LCDPORT_CONT_LATCH;
292 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
293 _LCDPORT_CONT_LATCH = b;
294 _LCDPORT_TRIS_DATA = 0x00; // OUT
295 _LCDPORT_LATCH_DATA = 0x00;
300 void acm1602_putchar(unsigned char addr, unsigned char c)
309 d = _LCDPORT_TRIS_CONT;
310 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
311 _LCDPORT_TRIS_CONT = d;
314 b = _LCDPORT_CONT_LATCH;
315 b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN); // DATA=blank,RW='0'
316 b |= _LCDPORT_CONT_RS; // RS='1"
318 _LCDPORT_CONT_LATCH = b;
319 _ACM1602_TC_WAIT(); // Wait 2.5?us
321 b |= _LCDPORT_CONT_EN; // Do high write.
322 _LCDPORT_CONT_LATCH = b;
323 _ACM1602_TC_WAIT(); // Wait 2.5?us
325 b &= ~_LCDPORT_CONT_EN; // Disable EN
326 _LCDPORT_CONT_LATCH = b;
330 d = _LCDPORT_TRIS_CONT;
331 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
332 _LCDPORT_TRIS_CONT = d;
334 b = _LCDPORT_CONT_LATCH;
335 b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN); // DATA=blank,RW='0'
336 b |= _LCDPORT_CONT_RS; // RS='1"
338 _LCDPORT_CONT_LATCH = b;
339 _ACM1602_TC_WAIT(); // Wait 2.5?us
341 b |= _LCDPORT_CONT_EN;
342 _LCDPORT_CONT_LATCH = b; // Do low write.
343 _ACM1602_TC_WAIT(); // Wait 2.5?us
345 b &= ~_LCDPORT_CONT_EN; // Disable EN
346 _LCDPORT_CONT_LATCH = b;
347 _ACM1602_SHORT_WAIT();
351 d = _LCDPORT_TRIS_DATA;
352 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
353 _LCDPORT_TRIS_DATA = d;
355 b = _LCDPORT_CONT_LATCH;
356 b &= ~_LCDPORT_CONT_RW; // ,RW='0'
357 b |= _LCDPORT_CONT_RS; // RS='1"
358 _LCDPORT_LATCH_DATA = c;
359 _LCDPORT_CONT_LATCH = b;
360 _ACM1602_TC_WAIT(); // Wait 2.5?us
362 b |= _LCDPORT_CONT_EN; // Send character
363 _LCDPORT_CONT_LATCH = b;
364 _ACM1602_TC_WAIT(); // Wait 2.5?us
366 b &= ~_LCDPORT_CONT_EN; // Disable EN
367 _LCDPORT_CONT_LATCH = b;
368 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
372 unsigned char acm1602_getchar(unsigned char addr)
379 d = _LCDPORT_TRIS_CONT;
380 d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
381 _LCDPORT_TRIS_CONT = d;
384 b = _LCDPORT_CONT_LATCH;
385 b &= ~(0xf0 | _LCDPORT_CONT_EN); // DATA=blank
386 b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='1", RW='1'
387 _LCDPORT_CONT_LATCH = b;
388 _ACM1602_TC_WAIT(); // Wait 2.5?us
390 b |= _LCDPORT_CONT_EN;
391 _LCDPORT_CONT_LATCH = b;
392 _ACM1602_TC_WAIT(); // Wait 2.5?us
394 h = _LCDPORT_DATA & 0xf0;
395 _ACM1602_TC_WAIT(); // Wait 2.5?us
397 b &= ~_LCDPORT_CONT_EN; // Disable EN
398 _LCDPORT_CONT_LATCH = b;
403 d = _LCDPORT_TRIS_CONT;
404 d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
405 _LCDPORT_TRIS_CONT = d;
407 b = _LCDPORT_CONT_LATCH;
408 b &= ~(0xf0 | _LCDPORT_CONT_EN); // DATA=blank
409 b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='1", RW='1'
410 _LCDPORT_CONT_LATCH = b;
411 _ACM1602_TC_WAIT(); // Wait 2.5?us
413 b |= _LCDPORT_CONT_EN;
414 _LCDPORT_CONT_LATCH = b;
415 _ACM1602_TC_WAIT(); // Wait 2.5?us
417 l = _LCDPORT_DATA & 0xf0;
418 _ACM1602_TC_WAIT(); // Wait 2.5?us
420 b &= ~_LCDPORT_CONT_EN; // Disable EN
421 _LCDPORT_CONT_LATCH = b;
422 _ACM1602_TC_WAIT(); // Wait 2.5?us
424 d = _LCDPORT_TRIS_CONT;
425 d &= ~_LCDPORT_READMASK; // Set mask for Tristate, direction = write.
426 _LCDPORT_TRIS_CONT = d;
428 _ACM1602_SHORT_WAIT();
435 d = _LCDPORT_TRIS_DATA;
436 d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
437 _LCDPORT_TRIS_DATA = d;
439 b = _LCDPORT_CONT_LATCH;
440 b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RW=1, RS=1
441 b &= ~_LCDPORT_CONT_EN; // Clear Enable
442 _LCDPORT_CONT_LATCH = b;
445 b |= _LCDPORT_CONT_EN; // Send character
446 _LCDPORT_CONT_LATCH = b;
447 _ACM1602_TC_WAIT(); // Wait 2.5?us
449 e = _LCDPORT_DATA; // Read BYTE
452 b &= ~_LCDPORT_CONT_EN; // Disable EN
453 _LCDPORT_CONT_LATCH = b;
455 d = _LCDPORT_TRIS_DATA;
456 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = read.
457 _LCDPORT_TRIS_DATA = d;
459 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
466 void acm1602_cls(unsigned char addr)
468 sendcmd(addr, 0x01, 0xff);
469 _ACM1602_LONG_WAIT(); // Wait 5ms
472 void acm1602_locate(unsigned char addr, char x, char y)
474 unsigned char ramaddr;
475 if((x < 0) || (x > 15)) return;
476 if((y < 0) || (y > 1)) return;
478 ramaddr = 0x80 | (x & 0x0f);
480 ramaddr = 0xc0 | (x & 0x0f);
482 sendcmd(addr, ramaddr, 0xff);
485 void acm1602_home(unsigned char addr)
487 sendcmd(addr, 0x02, 0xff);
488 _ACM1602_LONG_WAIT(); // Wait 5ms
491 void acm1602_printf(unsigned char addr, const char *fmt, ...)
493 char strbuf[32]; // Max 32 bytes.
499 va_start(args, fmt );
500 sprintf(strbuf, args);
502 if((l >= 32) || (l <= 0))return;
503 for(i = 0; i < l; i++) {
504 acm1602_putchar(addr, strbuf[i]);
508 void acm1602_cursordir(unsigned char addr, unsigned char right)
516 sendcmd(addr, cmd, 0xff);
519 void acm1602_init(unsigned char addr, unsigned char cls)
521 acm1602_ioinit(addr);
523 sendonce(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
524 _ACM1602_SHORT_WAIT();
525 sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
526 _ACM1602_SHORT_WAIT();
529 sendonce(addr, 0x38); // 2lines, 8x10dot fonts.
530 _ACM1602_SHORT_WAIT();
531 sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
532 _ACM1602_SHORT_WAIT();
534 sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
535 _ACM1602_SHORT_WAIT();
536 // Send twice on 4Bit Mode.
537 sendcmd(addr, 0x28, 0x00); // 2lines, 8x10dot fonts.
538 _ACM1602_SHORT_WAIT();
539 sendcmd(addr, 0x28, 0x00); // 2lines, 8x10dot fonts.
540 _ACM1602_SHORT_WAIT();
543 sendcmd(addr, 0x0f, 0xff); // Display ON.
544 _ACM1602_SHORT_WAIT();
550 sendcmd(addr, 0b00000110, 0xff); // Cursor increment,not shift.
551 _ACM1602_SHORT_WAIT();