From: andre Ebersold Date: Mon, 30 Oct 2023 22:00:48 +0000 (+0100) Subject: LCD I2C display prints WorkMeter. X-Git-Url: https://git.ebersold.fr/?a=commitdiff_plain;h=caf5d672ca62691611fe7b32144dbe63dcb313c1;p=atmel%2Favr.git LCD I2C display prints WorkMeter. --- diff --git a/Application/WorkhourMeter/main.cpp b/Application/WorkhourMeter/main.cpp index 126bdfd..f209884 100644 --- a/Application/WorkhourMeter/main.cpp +++ b/Application/WorkhourMeter/main.cpp @@ -30,6 +30,7 @@ #include #include +#include #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(0x4E) + //,static_cast(0x40) + ,static_cast(16) + ,static_cast(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(const_cast("WorkMeter"))); led.on(); _delay_ms(300); led.off(); diff --git a/HAL/Drivers/CMakeLists.txt b/HAL/Drivers/CMakeLists.txt index 4983705..b273975 100644 --- a/HAL/Drivers/CMakeLists.txt +++ b/HAL/Drivers/CMakeLists.txt @@ -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 index 0000000..20b9c36 --- /dev/null +++ b/HAL/Drivers/LiquidCrystal.cpp @@ -0,0 +1,109 @@ +#include +#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(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(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 index 0000000..2ffae21 --- /dev/null +++ b/HAL/Drivers/LiquidCrystal.h @@ -0,0 +1,94 @@ +#ifndef __LIQUIDCRYSTAL_H__ +#define __LIQUIDCRYSTAL_H__ + +// commands +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off control +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 + +// flags for backlight control +#define LCD_BACKLIGHT 0x08 +#define LCD_NOBACKLIGHT 0x00 + +#define En 0b00000100 // Enable bit +#define Rw 0b00000010 // Read/Write bit +#define Rs 0b00000001 // Register select bit + + +/** + * + */ +class LiquidCrystal +{ + public: + LiquidCrystal(II2C *argII2C,Uint8_t lcd_Addr, Uint8_t argCols,Uint8_t argRows); + + void print(const Uint8_t *arg); + /* Should be called before scheduler starts */ + void init(); + + void clear(); + + void home(); + + void setCursor(Uint8_t col,Uint8_t row); + + inline void write(Uint8_t _char) { send(_char,Rs); }; + private: + inline void command(Uint8_t argValue) { send (argValue,0) ; } ; + + void send(Uint8_t argValue , Uint8_t argMode); + + void write4bits(Uint8_t arg); + + /* PCF Interface */ + void expanderWrite(Uint8_t argData); + + void pulseEnable(Uint8_t argData); + + + private: + II2C *itsII2C; + Uint8_t m_LCDaddr; + Uint8_t m_Cols; + Uint8_t m_Rows; + Uint8_t m_BackLight; + Uint8_t m_DispFunction; + Uint8_t m_DispMode; + Uint8_t m_DispCtrl; +}; + +#endif