/*
* OpenI2CRADIO
- * I2C-LCD ACM1602 Handler
+ * I2C/Parallel LCD ACM1602 Handler, variant of ST7066U.
* Copyright (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
* License: GPL2+LE
*
#include "lcd_acm1602.h"
#ifdef _USE_I2C_1602
-static void sendcmd(unsigned char addr, unsigned char cmd)
+static unsigned char lcd_busychk(void)
+{
+ unsigned char b, d;
+ // Under development.
+ d = 0xff;
+ if((d & _LCDPORT_BUSYMASK) != 0){
+ d = 0xff; // BUSY
+ } else {
+ d = 0;
+ }
+ return d;
+}
+
+static void lcd_waitbusy(unsigned char flag)
+{
+ unsigned char f,ff;
+ ff = flag;
+ if(ff != 0) ff = 0xff;
+ do {
+ f = lcd_busychk();
+ _ACM1602_SHORT_WAIT(); // Wait 0.1ms
+ } while(f != ff);
+}
+
+
+static void sendcmd(unsigned char addr, unsigned char cmd, unsigned char busyflag)
{
i2c_idle();
OPENASMASTER();
_ACM1602_I2C_WAIT(); // 0.2ms
}
+static void sendonce(unsigned char addr, unsigned char cmd)
+{
+ sendcmd(addr, cmd, 0x00);
+}
+
static void acm1602_ioinit(unsigned char addr)
{
_ACM1602_LONG_LONG_WAIT();
_ACM1602_SHORT_WAIT(); // Wait 50us
}
+unsigned char acm1602_getchar(unsigned char addr)
+{
+ // Under development
+ return 0x00;
+}
#else // Parallel
-static void sendcmd(unsigned char addr, unsigned char cmd)
+static unsigned char lcd_busychk(void)
{
- unsigned char b;
- b = _LCDPORT_CONT;
- b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='0',RW='0'
+ unsigned char b, d;
+
+ // Set mask for Tristate.
+ b = _LCDPORT_TRIS_DATA;
+ b |= _LCDPORT_READMASK;// Set mask for Tristate, direction = read.
+ _LCDPORT_TRIS_DATA = b;
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~_LCDPORT_CONT_RS;
+ b |= _LCDPORT_CONT_RW;
+ _LCDPORT_CONT_LATCH = b;
+ b |= _LCDPORT_CONT_EN; // Send CMD
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+ d = _LCDPORT_DATA;
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+
+ b = _LCDPORT_TRIS_DATA;
+ b &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_DATA = b;
+
+ if((d & _LCDPORT_BUSYMASK) != 0){
+ d = 0xff; // BUSY
+ } else {
+ d = 0;
+ }
+ return d;
+}
+
+static void lcd_waitbusy(unsigned char flag)
+{
+ unsigned char f,ff;
+ ff = flag;
+ if(ff != 0) ff = 0xff;
+ do {
+ f = lcd_busychk();
+ _ACM1602_SHORT_WAIT(); // Wait 0.1ms
+ } while(f != ff);
+}
+
+static void sendcmd(unsigned char addr, unsigned char cmd,unsigned char busyflag)
+{
+#ifdef _LCD_IF_4BIT
+ unsigned char b, d;
+ unsigned char h,l;
+
+ h = cmd & 0xf0; // Higher bit is used.
+ l = (cmd & 0x0f) << 4; // Higher bit is used.
+ // Higher NIBBLE
+ if(busyflag != 0) lcd_waitbusy(0);
+ d = _LCDPORT_TRIS_CONT;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_CONT = d;
+
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
+ b |= h;
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+ b |= _LCDPORT_CONT_EN;
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT();
+
+ // Lower NIBBLE
+ if(busyflag != 0) lcd_waitbusy(0);
+ d = _LCDPORT_TRIS_CONT;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_CONT = d;
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN | _LCDPORT_CONT_RS); // DATA=blank,RW='0',RS='0"
+ b |= l;
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+ b |= _LCDPORT_CONT_EN;
_LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+
+ d = _LCDPORT_TRIS_CONT;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_CONT = d;
+
+#else
+ unsigned char b,d;
+
+ if(busyflag != 0) lcd_waitbusy(0);
+ d = _LCDPORT_TRIS_DATA;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_DATA = d;
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
+ _LCDPORT_CONT_LATCH = b;
+
_LCDPORT_LATCH_DATA = cmd;
+
b |= _LCDPORT_CONT_EN; // Send CMD
_LCDPORT_CONT_LATCH = b;
_ACM1602_TC_WAIT(); // Wait 2.5?us
+
b &= ~_LCDPORT_CONT_EN; // Disable EN
_LCDPORT_CONT_LATCH = b;
+
+ d = _LCDPORT_TRIS_DATA;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_DATA = d;
+
+#endif
// End of Command.
+ _ACM1602_SHORT_WAIT(); // Wait 50us
+}
+
+static void sendonce(unsigned char addr, unsigned char cmd)
+{
+#ifdef _LCD_IF_4BIT
+ unsigned char b, d;
+ unsigned char h;
+
+ h = cmd & 0xf0; // Higher bit is used.
+ // Higher NIBBLE
+ d = _LCDPORT_TRIS_CONT;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_CONT = d;
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
+ b |= h;
+ _LCDPORT_CONT_LATCH = b;
+
+ b |= _LCDPORT_CONT_EN; // Send CMD
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT();
+
+ d = _LCDPORT_TRIS_CONT;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_CONT = d;
+
+#else
+ unsigned char b, d;
+
+ d = _LCDPORT_TRIS_DATA;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_DATA = d;
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN); // RS='0',RW='0'
+ _LCDPORT_CONT_LATCH = b;
+
+ _LCDPORT_LATCH_DATA = cmd;
+
+ b |= _LCDPORT_CONT_EN; // Send CMD
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+// _ACM1602_TC_WAIT();
+#endif
+ _ACM1602_SHORT_WAIT(); // Wait 50us
}
static void acm1602_ioinit(unsigned char addr)
{
unsigned char b;
+// lcd_waitbusy(0);
_ACM1602_LONG_LONG_WAIT();
+#ifdef _LCD_IF_4BIT
+ b = _LCDPORT_TRIS_CONT;
+ b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN | 0xf0);
+ _LCDPORT_TRIS_CONT = b; // Clear Tristate bits, output.
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN | 0xf0);
+ _LCDPORT_CONT_LATCH = b;
+
+ //_LCDPORT_TRIS_DATA = 0x00; // OUT
+ //_LCDPORT_LATCH_DATA = 0x00;
+#else
b = _LCDPORT_TRIS_CONT;
b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
_LCDPORT_TRIS_CONT = b; // Clear Tristate bits, output.
- b = _LCDPORT_CONT;
+ b = _LCDPORT_CONT_LATCH;
b &= ~(_LCDPORT_CONT_RS | _LCDPORT_CONT_RW | _LCDPORT_CONT_EN);
_LCDPORT_CONT_LATCH = b;
_LCDPORT_TRIS_DATA = 0x00; // OUT
_LCDPORT_LATCH_DATA = 0x00;
+#endif
}
+
void acm1602_putchar(unsigned char addr, unsigned char c)
{
- unsigned char b;
- b = _LCDPORT_CONT;
- b &= ~_LCDPORT_CONT_RW; // ,RW='0'
+ unsigned char b, d;
+#ifdef _LCD_IF_4BIT
+ unsigned char h, l;
+ h = c & 0xf0;
+ l = (c & 0x0f)<<4;
+
+ lcd_waitbusy(0);
+ d = _LCDPORT_TRIS_CONT;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_CONT = d;
+
+ // Send high nibble
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN); // DATA=blank,RW='0'
b |= _LCDPORT_CONT_RS; // RS='1"
+ b |= h;
_LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b |= _LCDPORT_CONT_EN; // Do high write.
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT();
+
+ lcd_waitbusy(0);
+ d = _LCDPORT_TRIS_CONT;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_CONT = d;
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(_LCDPORT_CONT_RW | 0xf0 | _LCDPORT_CONT_EN); // DATA=blank,RW='0'
+ b |= _LCDPORT_CONT_RS; // RS='1"
+ b |= l;
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b |= _LCDPORT_CONT_EN;
+ _LCDPORT_CONT_LATCH = b; // Do low write.
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_SHORT_WAIT();
+
+#else
+ lcd_waitbusy(0);
+ d = _LCDPORT_TRIS_DATA;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = write.
+ _LCDPORT_TRIS_DATA = d;
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~_LCDPORT_CONT_RW; // ,RW='0'
+ b |= _LCDPORT_CONT_RS; // RS='1"
_LCDPORT_LATCH_DATA = c;
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b |= _LCDPORT_CONT_EN; // Send character
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_SHORT_WAIT(); // Wait 0.1ms
+#endif
+}
+
+unsigned char acm1602_getchar(unsigned char addr)
+{
+ unsigned char b, d;
+#ifdef _LCD_IF_4BIT
+ unsigned char h, l;
+
+ lcd_waitbusy(0);
+ d = _LCDPORT_TRIS_CONT;
+ d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
+ _LCDPORT_TRIS_CONT = d;
+
+ // Recv high nibble
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(0xf0 | _LCDPORT_CONT_EN); // DATA=blank
+ b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='1", RW='1'
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b |= _LCDPORT_CONT_EN;
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ h = _LCDPORT_DATA & 0xf0;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT();
+
+ lcd_waitbusy(0);
+ // Recv Low nibble.
+ d = _LCDPORT_TRIS_CONT;
+ d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
+ _LCDPORT_TRIS_CONT = d;
+
+ b = _LCDPORT_CONT_LATCH;
+ b &= ~(0xf0 | _LCDPORT_CONT_EN); // DATA=blank
+ b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RS='1", RW='1'
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b |= _LCDPORT_CONT_EN;
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ l = _LCDPORT_DATA & 0xf0;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ b &= ~_LCDPORT_CONT_EN; // Disable EN
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ d = _LCDPORT_TRIS_CONT;
+ d &= ~_LCDPORT_READMASK; // Set mask for Tristate, direction = write.
+ _LCDPORT_TRIS_CONT = d;
+
+ _ACM1602_SHORT_WAIT();
+
+ d = h | (l >> 4);
+ return d;
+#else
+ unsigned char e;
+ lcd_waitbusy(0);
+ d = _LCDPORT_TRIS_DATA;
+ d |= _LCDPORT_READMASK; // Set mask for Tristate, direction = read.
+ _LCDPORT_TRIS_DATA = d;
+
+ b = _LCDPORT_CONT_LATCH;
+ b |= (_LCDPORT_CONT_RS | _LCDPORT_CONT_RW); // RW=1, RS=1
+ b &= ~_LCDPORT_CONT_EN; // Clear Enable
+ _LCDPORT_CONT_LATCH = b;
+ _ACM1602_TC_WAIT();
+
b |= _LCDPORT_CONT_EN; // Send character
_LCDPORT_CONT_LATCH = b;
_ACM1602_TC_WAIT(); // Wait 2.5?us
+
+ e = _LCDPORT_DATA; // Read BYTE
+ _ACM1602_TC_WAIT();
+
b &= ~_LCDPORT_CONT_EN; // Disable EN
_LCDPORT_CONT_LATCH = b;
+
+ d = _LCDPORT_TRIS_DATA;
+ d &= ~_LCDPORT_READMASK; // Clear mask for Tristate, direction = read.
+ _LCDPORT_TRIS_DATA = d;
+
_ACM1602_SHORT_WAIT(); // Wait 0.1ms
+ return e;
+#endif
}
#endif
void acm1602_cls(unsigned char addr)
{
- sendcmd(addr, 0x01);
+ sendcmd(addr, 0x01, 0xff);
_ACM1602_LONG_WAIT(); // Wait 5ms
}
} else {
ramaddr = 0xc0 | (x & 0x0f);
}
- sendcmd(addr, ramaddr);
+ sendcmd(addr, ramaddr, 0xff);
}
void acm1602_home(unsigned char addr)
{
- sendcmd(addr, 0x02);
+ sendcmd(addr, 0x02, 0xff);
_ACM1602_LONG_WAIT(); // Wait 5ms
}
if(right == 0) {
cmd = 0x18;
} else {
- cmd=0x1c;
+ cmd = 0x1c;
}
- sendcmd(addr, cmd);
+ sendcmd(addr, cmd, 0xff);
}
void acm1602_init(unsigned char addr, unsigned char cls)
{
acm1602_ioinit(addr);
- sendcmd(addr, 0x38); // 2lines, 8x10dot fonts.
+#ifdef _USE_I2C_1602
+ sendonce(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
+ _ACM1602_SHORT_WAIT();
+ sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
_ACM1602_SHORT_WAIT();
- sendcmd(addr, 0x38); // 2lines, 8x10dot fonts.
+#else
+ #ifndef _LCD_IF_4BIT
+ sendonce(addr, 0x38); // 2lines, 8x10dot fonts.
_ACM1602_SHORT_WAIT();
- sendcmd(addr, 0x0f); // Display ON.
+ sendcmd(addr, 0x38, 0x00); // 2lines, 8x10dot fonts.
+ _ACM1602_SHORT_WAIT();
+ #else
+ sendonce(addr, 0x30); // 2lines, 8x10dot fonts.
+ _ACM1602_SHORT_WAIT();
+ // Send twice on 4Bit Mode.
+ sendcmd(addr, 0x28, 0x00); // 2lines, 8x10dot fonts.
+ _ACM1602_SHORT_WAIT();
+ sendcmd(addr, 0x28, 0x00); // 2lines, 8x10dot fonts.
+ _ACM1602_SHORT_WAIT();
+ #endif
+#endif
+ sendcmd(addr, 0x0f, 0xff); // Display ON.
_ACM1602_SHORT_WAIT();
if(cls == 0){
acm1602_home(addr);
} else {
acm1602_cls(addr);
}
- sendcmd(addr, 0b00000110); // Cursor increment,not shift.
+ sendcmd(addr, 0b00000110, 0xff); // Cursor increment,not shift.
_ACM1602_SHORT_WAIT();
}
\ No newline at end of file