LCD I2C display prints WorkMeter.
authorandre Ebersold <andre.ebersold@free.fr>
Mon, 30 Oct 2023 22:00:48 +0000 (23:00 +0100)
committerandre Ebersold <andre.ebersold@free.fr>
Mon, 30 Oct 2023 22:00:48 +0000 (23:00 +0100)
Application/WorkhourMeter/main.cpp
HAL/Drivers/CMakeLists.txt
HAL/Drivers/LiquidCrystal.cpp [new file with mode: 0644]
HAL/Drivers/LiquidCrystal.h [new file with mode: 0644]

index 126bdfdd38b08575bafe509336a50ada523f6279..f2098842d36697f7b831d686e723b09509ec8e1b 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <Drivers/NetString.h>
 #include <Drivers/DS3231.h>
+#include <Drivers/LiquidCrystal.h>
 #include "Led0.h"
 #include "WorkMeterHandler.h"
 #if 0
@@ -170,6 +171,11 @@ int main(void)
    AvrUart              uart(IUart::BAUD_9600,IUart::PARITY_NONE,IUart::STB_ONE);
    AvrI2C               gI2c;
    DS3231               gRtc(&gI2c);
+   LiquidCrystal        lcd(&gI2c
+                          ,static_cast<Uint8_t>(0x4E)
+                          //,static_cast<Uint8_t>(0x40)
+                          ,static_cast<Uint8_t>(16)
+                          ,static_cast<Uint8_t>(2));
    AvrEeprom            gEeprom;
    NetString            netstring(&uart);
    CommunicationHandler gCom(&netstring,&gParam);
@@ -180,9 +186,9 @@ int main(void)
    uart.init();
    gI2c.init();
    netstring.init();
-
+   lcd.init();
    Timer0 lTimer(sched);
+   lcd.print(reinterpret_cast<Uint8_t *>(const_cast<char *>("WorkMeter")));
    led.on();
     _delay_ms(300);
    led.off();
index 4983705023db12de65c786dc1a692f335b0292f5..b273975ddfb19505ddd9cbcc836bc1410e09cf21 100644 (file)
@@ -7,5 +7,6 @@ add_avr_library(
   Ili9341.cpp
   DS3231.cpp
   XPT2046_Touchscreen.cpp
+  LiquidCrystal.cpp
    )
 
diff --git a/HAL/Drivers/LiquidCrystal.cpp b/HAL/Drivers/LiquidCrystal.cpp
new file mode 100644 (file)
index 0000000..20b9c36
--- /dev/null
@@ -0,0 +1,109 @@
+#include <util/delay.h>
+#include "Utils/StdTypes.h"
+
+#include "Abstract/II2C.h"
+#include "Drivers/LiquidCrystal.h"
+
+
+LiquidCrystal::LiquidCrystal(II2C *argII2C,Uint8_t lcd_Addr, Uint8_t argCols,Uint8_t argRows)
+: itsII2C(argII2C),m_LCDaddr(lcd_Addr)
+       , m_Cols(argCols),m_Rows(argRows)
+       , m_BackLight(LCD_NOBACKLIGHT)
+       , m_DispFunction(LCD_2LINE)
+       , m_DispMode(LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT)
+       , m_DispCtrl(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF)
+{
+}
+
+void LiquidCrystal::print(const Uint8_t *arg)
+{
+    Uint8_t *_c = const_cast<Uint8_t *>(arg);
+    while(*_c != '\0')
+    {
+        write(*_c);
+       _c++;
+    }
+}
+/* Should be called before scheduler starts */ 
+void LiquidCrystal::init()
+{
+    _delay_ms(10);
+
+    expanderWrite(m_BackLight);
+
+    _delay_ms(10);
+    // We start in 8 bits mode, try to set 4 bit mode
+    for (Uint8_t i = 0 ; i < 2 ; ++i)
+    { 
+        write4bits(0x03<<4);
+        _delay_us(4500);
+    }
+    write4bits(0x03<<4);
+    _delay_us(150);
+    // Finally, set to 4 bits interface !
+    write4bits(0x02<<4);
+
+    command(LCD_FUNCTIONSET | m_DispFunction);
+
+    m_DispCtrl |= LCD_DISPLAYON;
+    command(LCD_DISPLAYCONTROL | m_DispCtrl);
+
+    clear();
+
+    home();
+}
+void LiquidCrystal::clear()
+{
+    command(LCD_CLEARDISPLAY);
+    _delay_ms(2);
+}
+
+void LiquidCrystal::home()
+{
+    command(LCD_RETURNHOME);
+    _delay_ms(2);
+}
+
+void LiquidCrystal::setCursor(Uint8_t col,Uint8_t row)
+{
+    Uint8_t row_offsets[] = {0x00,0x40,0x14,0x54};
+    if ( row > m_Rows)
+    {
+         row = m_Rows -1;
+    }
+    command(LCD_SETDDRAMADDR |( col + row_offsets[row]));
+}
+
+
+/* Lowest level */
+void LiquidCrystal::send(Uint8_t argValue, Uint8_t argMode)
+{
+    write4bits( (argValue & 0xf0) | argMode) ;
+    write4bits( ( (argValue<<4) & 0xf0) | argMode) ;
+}
+
+void LiquidCrystal::write4bits(Uint8_t argData)
+{
+    expanderWrite(argData);
+    pulseEnable(argData);
+}
+
+
+
+void LiquidCrystal::expanderWrite(Uint8_t argData)
+{
+    Uint8_t cmd[1] = { static_cast<Uint8_t >(argData | m_BackLight)} ;
+    itsII2C->write(m_LCDaddr,cmd,1);
+}
+
+
+void LiquidCrystal::pulseEnable(Uint8_t argData)
+{
+    expanderWrite(argData | En); // En High
+    // Delay 1us
+    _delay_us(1);
+    expanderWrite(argData & ~En); // En low
+    // Delay 40us
+    _delay_us(40);
+
+}
diff --git a/HAL/Drivers/LiquidCrystal.h b/HAL/Drivers/LiquidCrystal.h
new file mode 100644 (file)
index 0000000..2ffae21
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef __LIQUIDCRYSTAL_H__\r
+#define __LIQUIDCRYSTAL_H__\r
+\r
+// commands\r
+#define LCD_CLEARDISPLAY 0x01\r
+#define LCD_RETURNHOME 0x02\r
+#define LCD_ENTRYMODESET 0x04\r
+#define LCD_DISPLAYCONTROL 0x08\r
+#define LCD_CURSORSHIFT 0x10\r
+#define LCD_FUNCTIONSET 0x20\r
+#define LCD_SETCGRAMADDR 0x40\r
+#define LCD_SETDDRAMADDR 0x80\r
+\r
+// flags for display entry mode\r
+#define LCD_ENTRYRIGHT 0x00\r
+#define LCD_ENTRYLEFT 0x02\r
+#define LCD_ENTRYSHIFTINCREMENT 0x01\r
+#define LCD_ENTRYSHIFTDECREMENT 0x00\r
+\r
+// flags for display on/off control\r
+#define LCD_DISPLAYON 0x04\r
+#define LCD_DISPLAYOFF 0x00\r
+#define LCD_CURSORON 0x02\r
+#define LCD_CURSOROFF 0x00\r
+#define LCD_BLINKON 0x01\r
+#define LCD_BLINKOFF 0x00\r
+\r
+// flags for display/cursor shift\r
+#define LCD_DISPLAYMOVE 0x08\r
+#define LCD_CURSORMOVE 0x00\r
+#define LCD_MOVERIGHT 0x04\r
+#define LCD_MOVELEFT 0x00\r
+\r
+// flags for function set\r
+#define LCD_8BITMODE 0x10\r
+#define LCD_4BITMODE 0x00\r
+#define LCD_2LINE 0x08\r
+#define LCD_1LINE 0x00\r
+#define LCD_5x10DOTS 0x04\r
+#define LCD_5x8DOTS 0x00\r
+\r\r
+// flags for backlight control\r
+#define LCD_BACKLIGHT 0x08\r
+#define LCD_NOBACKLIGHT 0x00\r
+\r\r
+#define En 0b00000100  // Enable bit\r
+#define Rw 0b00000010  // Read/Write bit\r
+#define Rs 0b00000001  // Register select bit\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+class LiquidCrystal\r
+{\r
+    public:\r
+       LiquidCrystal(II2C *argII2C,Uint8_t lcd_Addr, Uint8_t argCols,Uint8_t argRows);\r
+\r
+       void print(const Uint8_t *arg);\r
+        /* Should be called before scheduler starts */ \r
+       void init();\r
+       \r
+       void clear();\r
+       \r
+       void home();\r
+\r
+       void setCursor(Uint8_t col,Uint8_t row);\r
+\r
+       inline void write(Uint8_t _char) { send(_char,Rs); };\r
+    private:\r
+       inline void command(Uint8_t argValue) { send (argValue,0) ; } ;\r
+\r
+       void send(Uint8_t argValue , Uint8_t argMode);\r
+       \r
+       void write4bits(Uint8_t arg);\r
+\r
+       /* PCF Interface */\r
+       void expanderWrite(Uint8_t argData);\r
+\r
+       void pulseEnable(Uint8_t argData);\r
+\r
+\r
+    private:\r
+       II2C   *itsII2C;\r
+       Uint8_t m_LCDaddr;\r
+       Uint8_t m_Cols;\r
+       Uint8_t m_Rows;\r
+       Uint8_t m_BackLight;\r
+       Uint8_t m_DispFunction;\r
+       Uint8_t m_DispMode;\r
+       Uint8_t m_DispCtrl;\r
+};\r
+\r
+#endif\r