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 void _ACM1602_TC_WAIT(void)
119 static unsigned char lcd_busychk(unsigned char addr)
123 // Set mask for Tristate.
124 b = _LCDPORT_TRIS_DATA;
125 b |= _LCDPORT_READMASK;// Set mask for Tristate, direction = read.
126 _LCDPORT_TRIS_DATA = b;
128 // b = _LCDPORT_CONT_LATCH;
129 _LCDPORT_CONT_RS = 0;
130 _LCDPORT_CONT_RW = 1;
131 // _LCDPORT_CONT_LATCH = b;
132 _ACM1602_TC_WAIT(); // Wait 2.5?us
134 _LCDPORT_CONT_EN = 1; // Send CMD
135 // _LCDPORT_CONT_LATCH = b;
136 _ACM1602_TC_WAIT(); // Wait 2.5?us
139 _ACM1602_TC_WAIT(); // Wait 2.5?us
141 _LCDPORT_CONT_EN = 0; // Disable EN
142 // _LCDPORT_CONT_LATCH = b;
143 _ACM1602_TC_WAIT(); // Wait 2.5?us
145 _LCDPORT_CONT_EN = 1; // Disable EN
146 // _LCDPORT_CONT_LATCH = b;
147 _ACM1602_TC_WAIT(); // Wait 2.5?us
149 _LCDPORT_CONT_EN = 0;; // Disable EN
150 // _LCDPORT_CONT_LATCH = b;
151 _ACM1602_TC_WAIT(); // Wait 2.5?us
153 b = _LCDPORT_TRIS_DATA;
154 b &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
155 _LCDPORT_TRIS_DATA = b;
156 _ACM1602_TC_WAIT(); // Wait 2.5?us
158 if((d & _LCDPORT_BUSYMASK) != 0){
166 void lcd_waitbusy(unsigned char addr, unsigned char flag)
170 if(ff != 0) ff = 0xff;
172 f = lcd_busychk(addr);
173 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
177 static void sendcmd(unsigned char addr, unsigned char cmd,unsigned char busyflag)
183 h = cmd & 0xf0; // Higher bit is used.
184 l = (cmd & 0x0f) << 4; // Higher bit is used.
186 if(busyflag != 0) lcd_waitbusy(addr, 0);
187 d = _LCDPORT_TRIS_CONT;
188 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
189 _LCDPORT_TRIS_CONT = d;
191 _LCDPORT_CONT_RW = 0;
192 _LCDPORT_CONT_EN = 0;
193 _LCDPORT_CONT_RS = 0;
194 _LCDPORT_CONT_LATCH &= 0x0f; // Upper
195 // b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
196 _LCDPORT_CONT_LATCH |= h;
197 // _LCDPORT_CONT_LATCH = b;
198 _ACM1602_TC_WAIT(); // Wait 2.5?us
200 _LCDPORT_CONT_EN = 1;
201 //_LCDPORT_CONT_LATCH = b;
202 _ACM1602_TC_WAIT(); // Wait 2.5?us
204 _LCDPORT_CONT_EN = 0; // Disable EN
205 // _LCDPORT_CONT_LATCH = b;
209 // if(busyflag != 0) lcd_waitbusy(addr, 0);
210 // d = _LCDPORT_TRIS_CONT;
211 // d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
212 // _LCDPORT_TRIS_CONT = d;
214 _LCDPORT_CONT_RW = 0;
215 _LCDPORT_CONT_EN = 0;
216 _LCDPORT_CONT_RS = 0;
217 _LCDPORT_CONT_LATCH &= 0x0f; // Lower
219 _LCDPORT_CONT_LATCH |= l;
220 _ACM1602_TC_WAIT(); // Wait 2.5?us
221 _LCDPORT_CONT_EN = 1;
222 // _LCDPORT_CONT_LATCH = b;
224 _ACM1602_TC_WAIT(); // Wait 2.5?us
225 _LCDPORT_CONT_EN = 0; // Disable EN
226 // _LCDPORT_CONT_LATCH = b;
228 // d = _LCDPORT_TRIS_CONT;
229 // d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
230 // _LCDPORT_TRIS_CONT = d;
235 if(busyflag != 0) lcd_waitbusy(addr, 0);
236 d = _LCDPORT_TRIS_DATA;
237 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
238 _LCDPORT_TRIS_DATA = d;
240 b = _LCDPORT_CONT_LATCH;
241 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
242 _LCDPORT_CONT_LATCH = b;
244 _LCDPORT_LATCH_DATA = cmd;
246 b |= _LCDPORT_CONT_EN; // Send CMD
247 _LCDPORT_CONT_LATCH = b;
248 _ACM1602_TC_WAIT(); // Wait 2.5?us
250 b &= ~_LCDPORT_CONT_EN; // Disable EN
251 _LCDPORT_CONT_LATCH = b;
253 d = _LCDPORT_TRIS_DATA;
254 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
255 _LCDPORT_TRIS_DATA = d;
259 _ACM1602_SHORT_WAIT(); // Wait 50us
262 static void sendonce(unsigned char addr, unsigned char cmd)
268 h = cmd & 0xf0; // Higher bit is used.
270 //d = _LCDPORT_TRIS_CONT;
271 // d = TRIS_D_VAL; // Clear mask for Tristate, direction = write.
272 // _LCDPORT_TRIS_CONT = d;
273 d = _LCDPORT_TRIS_CONT;
274 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
275 _LCDPORT_TRIS_CONT = d;
277 _LCDPORT_CONT_RS = 0;
278 _LCDPORT_CONT_RW = 0;
279 _LCDPORT_CONT_EN = 0; // RS='0',RW='0'
280 _LCDPORT_CONT_LATCH &= 0x0f;
281 _LCDPORT_CONT_LATCH |= h;
282 _ACM1602_TC_WAIT(); // Wait 2.5?us
284 _LCDPORT_CONT_EN = 1; // Send CMD
285 _ACM1602_TC_WAIT(); // Wait 2.5?us
287 _LCDPORT_CONT_EN = 0; // Disable EN
290 // d = _LCDPORT_TRIS_CONT;
291 // d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
292 // _LCDPORT_TRIS_CONT = d;
297 d = _LCDPORT_TRIS_DATA;
298 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
299 _LCDPORT_TRIS_DATA = d;
301 b = _LCDPORT_CONT_LATCH;
302 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
303 _LCDPORT_CONT_LATCH = b;
305 _LCDPORT_LATCH_DATA = cmd;
307 b |= _LCDPORT_CONT_EN; // Send CMD
308 _LCDPORT_CONT_LATCH = b;
309 _ACM1602_TC_WAIT(); // Wait 2.5?us
311 b &= ~_LCDPORT_CONT_EN; // Disable EN
312 _LCDPORT_CONT_LATCH = b;
313 // _ACM1602_TC_WAIT();
315 _ACM1602_SHORT_WAIT(); // Wait 50us
318 static void acm1602_ioinit(unsigned char addr)
323 _ACM1602_LONG_LONG_WAIT();
325 _LCDPORT_TRIS_CONT = TRIS_D_VAL;
327 _LCDPORT_CONT_RS = 0;
328 _LCDPORT_CONT_RW = 0;
329 _LCDPORT_CONT_EN = 0;
330 _LCDPORT_CONT_LATCH &= ~0xf0;
331 // _LCDPORT_CONT_LATCH = b;
332 // _LCDPORT_TRIS_DATA = 0x00; // OUT
333 // _LCDPORT_LATCH_DATA = 0x00;
335 b = _LCDPORT_TRIS_CONT;
336 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
337 _LCDPORT_TRIS_CONT = b; // Clear Tristate bits, output.
338 b = _LCDPORT_CONT_LATCH;
339 b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
340 _LCDPORT_CONT_LATCH = b;
341 _LCDPORT_TRIS_DATA = 0x00; // OUT
342 _LCDPORT_LATCH_DATA = 0x00;
347 void acm1602_putchar(unsigned char addr, unsigned char c)
355 lcd_waitbusy(addr, 0);
356 // d = _LCDPORT_TRIS_CONT;
357 // d &= 0x00; // Clear mask for Tristate, direction = write.
358 d = TRIS_D_VAL; // ALL OUT
359 _LCDPORT_TRIS_CONT = d;
360 _ACM1602_TC_WAIT(); // Wait 2.5?us
363 //b = _LCDPORT_CONT_LATCH;
364 _LCDPORT_CONT_RW = 0;
365 _LCDPORT_CONT_EN = 0; // DATA=blank,RW='0'
366 _LCDPORT_CONT_LATCH &= ~0xf0;
367 _LCDPORT_CONT_RS = 1; // RS='1"
368 // _LCDPORT_CONT_LATCH = b;
369 _ACM1602_TC_WAIT(); // Wait 2.5?us
371 _LCDPORT_CONT_EN = 1; // Do high write.
373 _LCDPORT_CONT_LATCH |= h;
374 _ACM1602_TC_WAIT(); // Wait 2.5?us
376 _LCDPORT_CONT_EN = 0; // Disable EN
377 // _LCDPORT_CONT_LATCH = b;
378 _ACM1602_SHORT_WAIT();
380 // lcd_waitbusy(addr, 0);
381 _LCDPORT_CONT_LATCH &= ~0xf0;
382 _LCDPORT_CONT_RS = 1; // RS='1"
383 _ACM1602_TC_WAIT(); // Wait 2.5?us
385 _LCDPORT_CONT_LATCH |= l; // Do low write.
386 _LCDPORT_CONT_EN = 1;
387 _ACM1602_TC_WAIT(); // Wait 2.5?us
389 _LCDPORT_CONT_EN = 0; // Disable EN
390 _ACM1602_SHORT_WAIT();
394 lcd_waitbusy(addr, 0);
395 d = _LCDPORT_TRIS_DATA;
396 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
397 _LCDPORT_TRIS_DATA = d;
399 b = _LCDPORT_CONT_LATCH;
400 b &= ~_LCDPORT_CONT_RW; // ,RW='0'
401 b |= _LCDPORT_CONT_RS; // RS='1"
402 _LCDPORT_LATCH_DATA = c;
403 _LCDPORT_CONT_LATCH = b;
404 _ACM1602_TC_WAIT(); // Wait 2.5?us
406 b |= _LCDPORT_CONT_EN; // Send character
407 _LCDPORT_CONT_LATCH = b;
408 _ACM1602_TC_WAIT(); // Wait 2.5?us
410 b &= ~_LCDPORT_CONT_EN; // Disable EN
411 _LCDPORT_CONT_LATCH = b;
412 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
418 void acm1602_cls(unsigned char addr)
420 sendcmd(addr, 0x01, 0xff);
421 _ACM1602_LONG_WAIT(); // Wait 5ms
424 void acm1602_setdataramaddress(unsigned char addr, unsigned char pos)
426 unsigned char cmd = (pos & 0x7f) | 0x80;
427 sendcmd(addr, cmd, 0xff);
431 void acm1602_locate_16x2(unsigned char addr, unsigned char x, unsigned char y)
433 unsigned char ramaddr;
436 ramaddr = (y == 0)? x : (x | 0x40);
437 acm1602_setdataramaddress(addr, ramaddr);
443 void acm1602_locate_8x2(unsigned char addr, unsigned char x, unsigned char y)
445 unsigned char ramaddr;
448 ramaddr = (y == 0)? x : x | 0x40;
449 acm1602_setdataramaddress(addr, ramaddr);
452 void acm1602_home(unsigned char addr)
454 sendcmd(addr, 0x02, 0xff);
455 _ACM1602_LONG_WAIT(); // Wait 5ms
459 void acm1602_cursordir(unsigned char addr, unsigned char right)
467 sendcmd(addr, cmd, 0xff);
470 void acm1602_dispcursor(unsigned char addr, unsigned char flag)
473 cmd = 0x0d; // Cursor ON
475 cmd = 0x0c; // Cursor off
477 sendcmd(addr, cmd, 0xff);
480 void acm1602_setcgramaddress(unsigned char addr, unsigned char pos)
482 unsigned char cmd = (pos & 0x3f) | 0x40;
483 sendcmd(addr, cmd, 0xff);
486 void acm1602_init(unsigned char addr, unsigned char cls)
488 acm1602_ioinit(addr);
490 sendcmd(addr,0x01,0x00);
491 sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
492 // sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
495 sendonce(addr, 0x38); // 2lines, 8x10dot fonts.
496 sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
498 _ACM1602_LONG_LONG_WAIT();
499 sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
500 // _ACM1602_SHORT_WAIT();
501 sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
502 // _ACM1602_SHORT_WAIT();
503 sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
504 // _ACM1602_SHORT_WAIT();
505 sendonce(addr, 0x20); // 2lines, 8x10dot fonts.
506 // _ACM1602_SHORT_WAIT();
507 // Send twice on 4Bit Mode.
508 // sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
509 sendcmd(addr, 0x28, 0xff); // 2lines, 8x5dot fonts.
512 // sendcmd(addr, 0x08, 0xff); // Display OFF.
513 sendcmd(addr, 0x0c, 0xff); // Display ON.
514 // sendcmd(addr, 0x06, 0xff); // Cursor increment,not shift.
520 // _ACM1602_LONG_WAIT();
521 sendcmd(addr, 0x06, 0xff);
527 void acm1602_suspend(unsigned char addr)
529 sendcmd(addr, 0x08, 0xff);
530 _ACM1602_LONG_WAIT();
533 void acm1602_resume(unsigned char addr)
535 sendcmd(addr, 0x0c, 0xff);
536 _ACM1602_LONG_WAIT();
544 void st7032_extcmd(unsigned char addr, unsigned char mode,
545 unsigned char cmd, unsigned char busyf)
547 unsigned char m = mode & 0x1c;
549 sendcmd(addr, m, busyf); // Shift to IS1
550 sendcmd(addr, cmd, busyf);
551 m &= 0xfe; // Shift to IS0
552 sendcmd(addr, m, busyf);
555 void st7032_setcontrast(unsigned char addr, unsigned char value,
558 unsigned char val = value & 0x0f;
560 st7032_extcmd(addr, 0x38, val, busyf);