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 _LCDPORT_CONT_RS = 0;
121 _LCDPORT_CONT_RW = 1;
122 // _LCDPORT_CONT_LATCH = b;
123 _ACM1602_TC_WAIT(); // Wait 2.5?us
125 _LCDPORT_CONT_EN = 1; // Send CMD
126 // _LCDPORT_CONT_LATCH = b;
127 _ACM1602_TC_WAIT(); // Wait 2.5?us
130 _ACM1602_TC_WAIT(); // Wait 2.5?us
132 _LCDPORT_CONT_EN = 0; // Disable EN
133 // _LCDPORT_CONT_LATCH = b;
134 _ACM1602_TC_WAIT(); // Wait 2.5?us
136 _LCDPORT_CONT_EN = 1; // Disable EN
137 // _LCDPORT_CONT_LATCH = b;
138 _ACM1602_TC_WAIT(); // Wait 2.5?us
140 _LCDPORT_CONT_EN = 0;; // Disable EN
141 // _LCDPORT_CONT_LATCH = b;
142 _ACM1602_TC_WAIT(); // Wait 2.5?us
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
149 if((d & _LCDPORT_BUSYMASK) != 0){
157 void lcd_waitbusy(unsigned char addr, unsigned char flag)
161 if(ff != 0) ff = 0xff;
163 f = lcd_busychk(addr);
164 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
168 static void sendcmd(unsigned char addr, unsigned char cmd,unsigned char busyflag)
174 h = cmd & 0xf0; // Higher bit is used.
175 l = (cmd & 0x0f) << 4; // Higher bit is used.
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;
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
191 _LCDPORT_CONT_EN = 1;
192 //_LCDPORT_CONT_LATCH = b;
193 _ACM1602_TC_WAIT(); // Wait 2.5?us
195 _LCDPORT_CONT_EN = 0; // Disable EN
196 // _LCDPORT_CONT_LATCH = b;
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;
205 _LCDPORT_CONT_RW = 0;
206 _LCDPORT_CONT_EN = 0;
207 _LCDPORT_CONT_RS = 0;
208 _LCDPORT_CONT_LATCH &= 0x0f; // Lower
210 _LCDPORT_CONT_LATCH |= l;
211 _ACM1602_TC_WAIT(); // Wait 2.5?us
212 _LCDPORT_CONT_EN = 1;
213 // _LCDPORT_CONT_LATCH = b;
215 _ACM1602_TC_WAIT(); // Wait 2.5?us
216 _LCDPORT_CONT_EN = 0; // Disable EN
217 // _LCDPORT_CONT_LATCH = b;
219 // d = _LCDPORT_TRIS_CONT;
220 // d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
221 // _LCDPORT_TRIS_CONT = d;
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;
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;
235 _LCDPORT_LATCH_DATA = cmd;
237 b |= _LCDPORT_CONT_EN; // Send CMD
238 _LCDPORT_CONT_LATCH = b;
239 _ACM1602_TC_WAIT(); // Wait 2.5?us
241 b &= ~_LCDPORT_CONT_EN; // Disable EN
242 _LCDPORT_CONT_LATCH = b;
244 d = _LCDPORT_TRIS_DATA;
245 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
246 _LCDPORT_TRIS_DATA = d;
250 _ACM1602_SHORT_WAIT(); // Wait 50us
253 static void sendonce(unsigned char addr, unsigned char cmd)
259 h = cmd & 0xf0; // Higher bit is used.
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;
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
275 _LCDPORT_CONT_EN = 1; // Send CMD
276 _ACM1602_TC_WAIT(); // Wait 2.5?us
278 _LCDPORT_CONT_EN = 0; // Disable EN
281 // d = _LCDPORT_TRIS_CONT;
282 // d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
283 // _LCDPORT_TRIS_CONT = d;
288 d = _LCDPORT_TRIS_DATA;
289 d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
290 _LCDPORT_TRIS_DATA = d;
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;
296 _LCDPORT_LATCH_DATA = cmd;
298 b |= _LCDPORT_CONT_EN; // Send CMD
299 _LCDPORT_CONT_LATCH = b;
300 _ACM1602_TC_WAIT(); // Wait 2.5?us
302 b &= ~_LCDPORT_CONT_EN; // Disable EN
303 _LCDPORT_CONT_LATCH = b;
304 // _ACM1602_TC_WAIT();
306 _ACM1602_SHORT_WAIT(); // Wait 50us
309 static void acm1602_ioinit(unsigned char addr)
314 _ACM1602_LONG_LONG_WAIT();
316 _LCDPORT_TRIS_CONT = TRIS_D_VAL;
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;
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;
338 void acm1602_putchar(unsigned char addr, unsigned char c)
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
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
362 _LCDPORT_CONT_EN = 1; // Do high write.
364 _LCDPORT_CONT_LATCH |= h;
365 _ACM1602_TC_WAIT(); // Wait 2.5?us
367 _LCDPORT_CONT_EN = 0; // Disable EN
368 // _LCDPORT_CONT_LATCH = b;
369 _ACM1602_SHORT_WAIT();
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
376 _LCDPORT_CONT_LATCH |= l; // Do low write.
377 _LCDPORT_CONT_EN = 1;
378 _ACM1602_TC_WAIT(); // Wait 2.5?us
380 _LCDPORT_CONT_EN = 0; // Disable EN
381 _ACM1602_SHORT_WAIT();
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;
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
397 b |= _LCDPORT_CONT_EN; // Send character
398 _LCDPORT_CONT_LATCH = b;
399 _ACM1602_TC_WAIT(); // Wait 2.5?us
401 b &= ~_LCDPORT_CONT_EN; // Disable EN
402 _LCDPORT_CONT_LATCH = b;
403 _ACM1602_SHORT_WAIT(); // Wait 0.1ms
409 void acm1602_cls(unsigned char addr)
411 sendcmd(addr, 0x01, 0xff);
412 _ACM1602_LONG_LONG_WAIT(); // Wait 5ms
415 void acm1602_setdataramaddress(unsigned char addr, unsigned char pos)
417 unsigned char cmd = (pos & 0x7f) | 0x80;
418 sendcmd(addr, cmd, 0xff);
421 void acm1602_locate_16x2(unsigned char addr, char x, char y)
423 unsigned char ramaddr;
424 ramaddr = (y == 0)? x & 0x0f : (x & 0x0f) | 0x40;
425 acm1602_setdataramaddress(addr, ramaddr);
431 void acm1602_locate_8x2(unsigned char addr, char x, char y)
433 unsigned char ramaddr;
434 if((x < 0) || (x > 8)) return;
435 if((y < 0) || (y > 1)) return;
436 ramaddr = (y == 0)? x & 0x0f : (x & 0x0f) | 0x40;
437 acm1602_setdataramaddress(addr, ramaddr);
440 void acm1602_home(unsigned char addr)
442 sendcmd(addr, 0x02, 0xff);
443 _ACM1602_LONG_LONG_WAIT(); // Wait 5ms
447 void acm1602_cursordir(unsigned char addr, unsigned char right)
455 sendcmd(addr, cmd, 0xff);
458 void acm1602_setcgramaddress(unsigned char addr, unsigned char pos)
460 unsigned char cmd = (pos & 0x3f) | 0x40;
461 sendcmd(addr, cmd, 0xff);
464 void acm1602_init(unsigned char addr, unsigned char cls)
466 acm1602_ioinit(addr);
468 sendcmd(addr,0x01,0x00);
469 sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
470 // sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
473 sendonce(addr, 0x38); // 2lines, 8x10dot fonts.
474 sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
476 _ACM1602_LONG_LONG_WAIT();
477 sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
478 _ACM1602_SHORT_WAIT();
479 sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
480 _ACM1602_SHORT_WAIT();
481 sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
482 _ACM1602_SHORT_WAIT();
483 sendonce(addr, 0x20); // 2lines, 8x10dot fonts.
484 _ACM1602_SHORT_WAIT();
485 // Send twice on 4Bit Mode.
486 // sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
487 sendcmd(addr, 0x28, 0xff); // 2lines, 8x5dot fonts.
490 // sendcmd(addr, 0x08, 0xff); // Display OFF.
491 sendcmd(addr, 0x0c, 0xff); // Display ON.
492 sendcmd(addr, 0x06, 0xff); // Cursor increment,not shift.
498 _ACM1602_LONG_WAIT();
499 // sendcmd(addr, 0x06, 0xff);
505 void acm1602_suspend(unsigned char addr)
507 sendcmd(addr, 0x08, 0xff);
508 _ACM1602_LONG_WAIT();
515 void st7032_extcmd(unsigned char addr, unsigned char mode,
516 unsigned char cmd, unsigned char busyf)
518 unsigned char m = mode & 0x1c;
520 sendcmd(addr, m, busyf); // Shift to IS1
521 sendcmd(addr, cmd, busyf);
522 m &= 0xfe; // Shift to IS0
523 sendcmd(addr, m, busyf);
526 void st7032_setcontrast(unsigned char addr, unsigned char value,
529 unsigned char val = value & 0x0f;
531 st7032_extcmd(addr, 0x38, val, busyf);