OSDN Git Service

[Disp][LCD] Update I/O definition.
[openi2cradio/OpenI2CRadio.git] / lcd_acm1602.c
index 7eac6ca..fbf212d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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();
@@ -41,6 +66,11 @@ static void sendcmd(unsigned char addr, unsigned char cmd)
     _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();
@@ -58,58 +88,384 @@ void acm1602_putchar(unsigned char addr, unsigned char c)
     _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
 }
 
@@ -123,12 +479,12 @@ void acm1602_locate(unsigned char addr, char x, char y)
     } 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
 }
 
@@ -155,25 +511,42 @@ void acm1602_cursordir(unsigned char addr, unsigned char right)
     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