OSDN Git Service

[SCHEMATIC] Modify SW/MW/LW Preamp, insert galbanic-isolator replace of common-mode...
[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 void _ACM1602_TC_WAIT(void)
111 {
112 #ifdef __SDCC
113    delay10tcy(4);
114 #else
115    __delay_us(5);
116 #endif
117 }
118
119 static unsigned char lcd_busychk(unsigned char addr)
120 {
121     unsigned char b, d;
122
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;
127
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
133
134     _LCDPORT_CONT_EN = 1; // Send CMD
135 //    _LCDPORT_CONT_LATCH = b;
136     _ACM1602_TC_WAIT(); // Wait 2.5?us
137
138     d = _LCDPORT_DATA;
139     _ACM1602_TC_WAIT(); // Wait 2.5?us
140
141     _LCDPORT_CONT_EN = 0; // Disable EN
142 //    _LCDPORT_CONT_LATCH = b;
143     _ACM1602_TC_WAIT(); // Wait 2.5?us
144
145     _LCDPORT_CONT_EN = 1; // Disable EN
146 //    _LCDPORT_CONT_LATCH = b;
147     _ACM1602_TC_WAIT(); // Wait 2.5?us
148
149     _LCDPORT_CONT_EN = 0;; // Disable EN
150 //    _LCDPORT_CONT_LATCH = b;
151     _ACM1602_TC_WAIT(); // Wait 2.5?us
152
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
157
158     if((d & _LCDPORT_BUSYMASK) != 0){
159         d = 0xff; // BUSY
160     } else {
161         d = 0;
162     }
163     return d;
164 }
165
166 void lcd_waitbusy(unsigned char addr, unsigned char flag)
167 {
168     unsigned char f,ff;
169     ff = flag;
170     if(ff != 0) ff = 0xff;
171     do {
172         f = lcd_busychk(addr);
173         _ACM1602_SHORT_WAIT(); // Wait 0.1ms
174     } while(f != ff);
175 }
176
177 static void sendcmd(unsigned char addr, unsigned char cmd,unsigned char busyflag)
178 {
179 #ifdef _LCD_IF_4BIT
180     unsigned char b, d;
181     unsigned char h,l;
182
183     h = cmd & 0xf0; // Higher bit is used.
184     l = (cmd & 0x0f) << 4; // Higher bit is used.
185     // Higher NIBBLE
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;
190
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
199
200     _LCDPORT_CONT_EN = 1;
201     //_LCDPORT_CONT_LATCH = b;
202     _ACM1602_TC_WAIT(); // Wait 2.5?us
203
204     _LCDPORT_CONT_EN = 0; // Disable EN
205 //    _LCDPORT_CONT_LATCH = b;
206     _ACM1602_TC_WAIT();
207
208     // Lower NIBBLE
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;
213
214     _LCDPORT_CONT_RW = 0;
215     _LCDPORT_CONT_EN = 0;
216     _LCDPORT_CONT_RS = 0;
217     _LCDPORT_CONT_LATCH &= 0x0f; // Lower
218
219     _LCDPORT_CONT_LATCH |= l;
220     _ACM1602_TC_WAIT(); // Wait 2.5?us
221     _LCDPORT_CONT_EN = 1;
222 //    _LCDPORT_CONT_LATCH = b;
223
224     _ACM1602_TC_WAIT(); // Wait 2.5?us
225     _LCDPORT_CONT_EN = 0; // Disable EN
226 //    _LCDPORT_CONT_LATCH = b;
227
228 //    d = _LCDPORT_TRIS_CONT;
229  //   d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
230   //  _LCDPORT_TRIS_CONT = d;
231
232 #else
233     unsigned char b,d;
234
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;
239
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;
243
244     _LCDPORT_LATCH_DATA = cmd;
245
246     b |= _LCDPORT_CONT_EN; // Send CMD
247     _LCDPORT_CONT_LATCH = b;
248     _ACM1602_TC_WAIT(); // Wait 2.5?us
249
250     b &= ~_LCDPORT_CONT_EN; // Disable EN
251     _LCDPORT_CONT_LATCH = b;
252
253     d = _LCDPORT_TRIS_DATA;
254     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
255     _LCDPORT_TRIS_DATA = d;
256
257 #endif
258     // End of Command.
259     _ACM1602_SHORT_WAIT(); // Wait 50us
260 }
261
262 static void sendonce(unsigned char addr, unsigned char cmd)
263 {
264 #ifdef _LCD_IF_4BIT
265     unsigned char b, d;
266     unsigned char h;
267
268     h = cmd & 0xf0; // Higher bit is used.
269     // Higher NIBBLE
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;
276
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
283
284     _LCDPORT_CONT_EN = 1; // Send CMD
285     _ACM1602_TC_WAIT(); // Wait 2.5?us
286
287     _LCDPORT_CONT_EN = 0; // Disable EN
288     _ACM1602_TC_WAIT();
289
290 //    d = _LCDPORT_TRIS_CONT;
291 //    d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
292 //    _LCDPORT_TRIS_CONT = d;
293
294 #else
295     unsigned char b, d;
296
297     d = _LCDPORT_TRIS_DATA;
298     d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
299     _LCDPORT_TRIS_DATA = d;
300
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;
304
305     _LCDPORT_LATCH_DATA = cmd;
306
307     b |= _LCDPORT_CONT_EN; // Send CMD
308     _LCDPORT_CONT_LATCH = b;
309     _ACM1602_TC_WAIT(); // Wait 2.5?us
310
311     b &= ~_LCDPORT_CONT_EN; // Disable EN
312     _LCDPORT_CONT_LATCH = b;
313 //    _ACM1602_TC_WAIT();
314 #endif
315     _ACM1602_SHORT_WAIT(); // Wait 50us
316 }
317
318 static void acm1602_ioinit(unsigned char addr)
319 {
320     unsigned char b;
321
322 //    lcd_waitbusy(0);
323     _ACM1602_LONG_LONG_WAIT();
324 #ifdef _LCD_IF_4BIT
325     _LCDPORT_TRIS_CONT = TRIS_D_VAL;
326
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;
334 #else
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;
343 #endif
344 }
345
346
347 void acm1602_putchar(unsigned char addr, unsigned char c)
348 {
349     unsigned char b, d;
350 #ifdef _LCD_IF_4BIT
351     unsigned char h, l;
352     h = c & 0xf0;
353     l = (c & 0x0f)<<4;
354
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
361
362     // Send high nibble
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
370
371     _LCDPORT_CONT_EN = 1; // Do high write.
372 //    b |= h;
373     _LCDPORT_CONT_LATCH |= h;
374     _ACM1602_TC_WAIT(); // Wait 2.5?us
375
376     _LCDPORT_CONT_EN = 0; // Disable EN
377 //    _LCDPORT_CONT_LATCH = b;
378     _ACM1602_SHORT_WAIT();
379
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
384
385     _LCDPORT_CONT_LATCH |= l; // Do low write.
386     _LCDPORT_CONT_EN = 1;
387     _ACM1602_TC_WAIT(); // Wait 2.5?us
388
389     _LCDPORT_CONT_EN = 0; // Disable EN
390     _ACM1602_SHORT_WAIT();
391
392
393 #else
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;
398
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
405
406     b |= _LCDPORT_CONT_EN; // Send character
407     _LCDPORT_CONT_LATCH = b;
408     _ACM1602_TC_WAIT(); // Wait 2.5?us
409
410     b &= ~_LCDPORT_CONT_EN; // Disable EN
411     _LCDPORT_CONT_LATCH = b;
412     _ACM1602_SHORT_WAIT(); // Wait 0.1ms
413 #endif
414 }
415
416 #endif
417
418 void acm1602_cls(unsigned char addr)
419 {
420     sendcmd(addr, 0x01, 0xff);
421     _ACM1602_LONG_WAIT(); // Wait 5ms
422 }
423
424 void acm1602_setdataramaddress(unsigned char addr, unsigned char pos)
425 {
426     unsigned char cmd = (pos & 0x7f) | 0x80;
427     sendcmd(addr, cmd, 0xff);
428 }
429
430
431 void acm1602_locate_16x2(unsigned char addr, unsigned char x, unsigned char y)
432 {
433     unsigned char ramaddr;
434     if(x > 16) return;
435     if(y > 1) return;
436     ramaddr = (y == 0)? x  : (x  | 0x40);
437     acm1602_setdataramaddress(addr, ramaddr);
438 }
439
440 /*
441  * For using
442  */
443 void acm1602_locate_8x2(unsigned char addr, unsigned char x, unsigned char y)
444 {
445     unsigned char ramaddr;
446     if(x > 8) return;
447     if(y > 1) return;
448     ramaddr = (y == 0)? x : x | 0x40;
449     acm1602_setdataramaddress(addr, ramaddr);
450 }
451
452 void acm1602_home(unsigned char addr)
453 {
454     sendcmd(addr, 0x02, 0xff);
455     _ACM1602_LONG_WAIT(); // Wait 5ms
456 }
457
458
459 void acm1602_cursordir(unsigned char addr, unsigned char right)
460 {
461     unsigned char cmd;
462
463     cmd = 0x14;
464     if(right == 0)  {
465         cmd = 0x10;
466     }
467     sendcmd(addr, cmd, 0xff);
468 }
469
470 void acm1602_dispcursor(unsigned char addr, unsigned char flag)
471 {
472     unsigned char cmd;
473     cmd = 0x0d; // Cursor ON
474     if(flag == 0x00) {
475         cmd = 0x0c; // Cursor off
476     }
477     sendcmd(addr, cmd, 0xff);
478 }
479
480 void acm1602_setcgramaddress(unsigned char addr, unsigned char pos)
481 {
482     unsigned char cmd = (pos & 0x3f) | 0x40;
483     sendcmd(addr, cmd, 0xff);
484 }
485
486 void acm1602_init(unsigned char addr, unsigned char cls)
487 {
488     acm1602_ioinit(addr);
489 #ifdef _USE_I2C_1602
490     sendcmd(addr,0x01,0x00);
491     sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
492 //    sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
493 #else
494   #ifndef _LCD_IF_4BIT
495     sendonce(addr, 0x38); // 2lines, 8x10dot fonts.
496     sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
497   #else // 4Bit
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.
510   #endif
511 #endif
512 //    sendcmd(addr, 0x08, 0xff); // Display OFF.
513     sendcmd(addr, 0x0c, 0xff); // Display ON.
514 //    sendcmd(addr, 0x06, 0xff); // Cursor increment,not shift.
515    if(cls == 0){
516         acm1602_home(addr);
517     } else {
518         acm1602_cls(addr);
519     }
520 //    _ACM1602_LONG_WAIT();
521     sendcmd(addr, 0x06, 0xff);
522 }
523
524 /*
525  * Suspend lcd
526  */
527 void acm1602_suspend(unsigned char addr)
528 {
529     sendcmd(addr, 0x08, 0xff);
530     _ACM1602_LONG_WAIT();
531 }
532
533 void acm1602_resume(unsigned char addr)
534 {
535     sendcmd(addr, 0x0c, 0xff);
536     _ACM1602_LONG_WAIT();
537 }
538
539
540 #ifdef _USE_I2C_1602
541 /*
542  * st7032 extensions.
543  */
544 void st7032_extcmd(unsigned char addr, unsigned char mode, 
545         unsigned char cmd, unsigned char busyf)
546 {
547     unsigned char m = mode & 0x1c;
548     m = m | 0x21;
549     sendcmd(addr, m, busyf); // Shift to IS1
550     sendcmd(addr, cmd, busyf);
551     m &= 0xfe; // Shift to IS0
552     sendcmd(addr, m, busyf);
553 }
554
555 void st7032_setcontrast(unsigned char addr, unsigned char value,
556         unsigned char busyf)
557 {
558     unsigned char val = value & 0x0f;
559     val |= 0x70;
560     st7032_extcmd(addr, 0x38, val, busyf);
561 }
562 #endif