diff --git a/ArduinoImpl.cpp b/ArduinoImpl.cpp new file mode 100644 index 0000000..031a51b --- /dev/null +++ b/ArduinoImpl.cpp @@ -0,0 +1,38 @@ +#include "ArduinoImpl.h" +#include + +ArduinoImpl::ArduinoImpl(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows) +{ + _Addr = lcd_Addr; + _cols = lcd_cols; + _rows = lcd_rows; + _backlightval = LCD_NOBACKLIGHT; +} + +void ArduinoImpl::setBacklightVal(uint8_t val) +{ + _backlightval = val; +} + +void ArduinoImpl::delayMilliseconds(uint32_t val) +{ + ::delay(val); +} + +void ArduinoImpl::delayMicroseconds(uint32_t val) +{ + ::delayMicroseconds(val); +} + +void ArduinoImpl::init_priv() +{ + Serial.print("ArduinoImpl::init_priv\n"); + Wire.begin(); +} + +void ArduinoImpl::expanderWrite(uint8_t _data) +{ + Wire.beginTransmission(_Addr); + printIIC((int)(_data) | _backlightval); + Wire.endTransmission(); +} diff --git a/ArduinoImpl.h b/ArduinoImpl.h new file mode 100644 index 0000000..ab09a50 --- /dev/null +++ b/ArduinoImpl.h @@ -0,0 +1,33 @@ +#ifndef _ARDUINOIMPL_H_ +#define _ARDUINOIMPL_H_ + +#include "LCI2CImpl.h" +#include "LiquidCrystal_I2C.h" + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#define printIIC(args) Wire.write(args) +#else +#include "WProgram.h" +#define printIIC(args) Wire.send(args) +#endif + +#include "Wire.h" + +class ArduinoImpl : public LCI2CImpl { +public: + ArduinoImpl(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows); + virtual ~ArduinoImpl() {}; + virtual void init_priv(); + virtual void setBacklightVal(uint8_t val); + virtual void delayMilliseconds(uint32_t val); + virtual void delayMicroseconds(uint32_t val); + virtual void expanderWrite(uint8_t _data); +private: + uint8_t _Addr; + uint8_t _cols; + uint8_t _rows; + uint8_t _backlightval; +}; + +#endif diff --git a/LCI2CImpl.cpp b/LCI2CImpl.cpp new file mode 100644 index 0000000..e75fdd6 --- /dev/null +++ b/LCI2CImpl.cpp @@ -0,0 +1,9 @@ +#include "LCI2CImpl.h" +#include + +#if 0 +LCI2CImpl::LCI2CImpl(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows) +{ +} +#endif + diff --git a/LCI2CImpl.h b/LCI2CImpl.h new file mode 100644 index 0000000..82a06a0 --- /dev/null +++ b/LCI2CImpl.h @@ -0,0 +1,17 @@ +#ifndef _LCI2CIMPL_H_ +#define _LCI2CIMPL_H_ + +#include +#include + +class LCI2CImpl { +public: + virtual ~LCI2CImpl() {}; + virtual void init_priv() = 0; + virtual void setBacklightVal(uint8_t backlightval) = 0; + virtual void expanderWrite(uint8_t _data) = 0; + virtual void delayMilliseconds(uint32_t delay) = 0; + virtual void delayMicroseconds(uint32_t delay) = 0; +}; + +#endif diff --git a/LiquidCrystal_I2C.cpp b/LiquidCrystal_I2C.cpp index 9dea08c..e9ae7ae 100644 --- a/LiquidCrystal_I2C.cpp +++ b/LiquidCrystal_I2C.cpp @@ -1,332 +1,438 @@ -// Based on the work by DFRobot - -#include "LiquidCrystal_I2C.h" -#include -#if defined(ARDUINO) && ARDUINO >= 100 - -#include "Arduino.h" - -#define printIIC(args) Wire.write(args) -inline size_t LiquidCrystal_I2C::write(uint8_t value) { - send(value, Rs); - return 1; -} - -#else -#include "WProgram.h" - -#define printIIC(args) Wire.send(args) -inline void LiquidCrystal_I2C::write(uint8_t value) { - send(value, Rs); -} - -#endif -#include "Wire.h" - - - -// When the display powers up, it is configured as follows: -// -// 1. Display clear -// 2. Function set: -// DL = 1; 8-bit interface data -// N = 0; 1-line display -// F = 0; 5x8 dot character font -// 3. Display on/off control: -// D = 0; Display off -// C = 0; Cursor off -// B = 0; Blinking off -// 4. Entry mode set: -// I/D = 1; Increment by 1 -// S = 0; No shift -// -// Note, however, that resetting the Arduino doesn't reset the LCD, so we -// can't assume that its in that state when a sketch starts (and the -// LiquidCrystal constructor is called). - -LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows) -{ - _Addr = lcd_Addr; - _cols = lcd_cols; - _rows = lcd_rows; - _backlightval = LCD_NOBACKLIGHT; -} - -void LiquidCrystal_I2C::oled_init(){ - _oled = true; - init_priv(); -} - -void LiquidCrystal_I2C::init(){ - init_priv(); -} - -void LiquidCrystal_I2C::init_priv() -{ - Wire.begin(); - _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; - begin(_cols, _rows); -} - -void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { - if (lines > 1) { - _displayfunction |= LCD_2LINE; - } - _numlines = lines; - - // for some 1 line displays you can select a 10 pixel high font - if ((dotsize != 0) && (lines == 1)) { - _displayfunction |= LCD_5x10DOTS; - } - - // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! - // according to datasheet, we need at least 40ms after power rises above 2.7V - // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 - delay(50); - - // Now we pull both RS and R/W low to begin commands - expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) - delay(1000); - - //put the LCD into 4 bit mode - // this is according to the hitachi HD44780 datasheet - // figure 24, pg 46 - - // we start in 8bit mode, try to set 4 bit mode - write4bits(0x03 << 4); - delayMicroseconds(4500); // wait min 4.1ms - - // second try - write4bits(0x03 << 4); - delayMicroseconds(4500); // wait min 4.1ms - - // third go! - write4bits(0x03 << 4); - delayMicroseconds(150); - - // finally, set to 4-bit interface - write4bits(0x02 << 4); - - - // set # lines, font size, etc. - command(LCD_FUNCTIONSET | _displayfunction); - - // turn the display on with no cursor or blinking default - _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; - display(); - - // clear it off - clear(); - - // Initialize to default text direction (for roman languages) - _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; - - // set the entry mode - command(LCD_ENTRYMODESET | _displaymode); - - home(); - -} - -/********** high level commands, for the user! */ -void LiquidCrystal_I2C::clear(){ - command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! - if (_oled) setCursor(0,0); -} - -void LiquidCrystal_I2C::home(){ - command(LCD_RETURNHOME); // set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! -} - -void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row){ - int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; - if ( row > _numlines ) { - row = _numlines-1; // we count rows starting w/0 - } - command(LCD_SETDDRAMADDR | (col + row_offsets[row])); -} - -// Turn the display on/off (quickly) -void LiquidCrystal_I2C::noDisplay() { - _displaycontrol &= ~LCD_DISPLAYON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} -void LiquidCrystal_I2C::display() { - _displaycontrol |= LCD_DISPLAYON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -// Turns the underline cursor on/off -void LiquidCrystal_I2C::noCursor() { - _displaycontrol &= ~LCD_CURSORON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} -void LiquidCrystal_I2C::cursor() { - _displaycontrol |= LCD_CURSORON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -// Turn on and off the blinking cursor -void LiquidCrystal_I2C::noBlink() { - _displaycontrol &= ~LCD_BLINKON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} -void LiquidCrystal_I2C::blink() { - _displaycontrol |= LCD_BLINKON; - command(LCD_DISPLAYCONTROL | _displaycontrol); -} - -// These commands scroll the display without changing the RAM -void LiquidCrystal_I2C::scrollDisplayLeft(void) { - command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); -} -void LiquidCrystal_I2C::scrollDisplayRight(void) { - command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); -} - -// This is for text that flows Left to Right -void LiquidCrystal_I2C::leftToRight(void) { - _displaymode |= LCD_ENTRYLEFT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This is for text that flows Right to Left -void LiquidCrystal_I2C::rightToLeft(void) { - _displaymode &= ~LCD_ENTRYLEFT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This will 'right justify' text from the cursor -void LiquidCrystal_I2C::autoscroll(void) { - _displaymode |= LCD_ENTRYSHIFTINCREMENT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// This will 'left justify' text from the cursor -void LiquidCrystal_I2C::noAutoscroll(void) { - _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; - command(LCD_ENTRYMODESET | _displaymode); -} - -// Allows us to fill the first 8 CGRAM locations -// with custom characters -void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) { - location &= 0x7; // we only have 8 locations 0-7 - command(LCD_SETCGRAMADDR | (location << 3)); - for (int i=0; i<8; i++) { - write(charmap[i]); - } -} - -//createChar with PROGMEM input -void LiquidCrystal_I2C::createChar(uint8_t location, const char *charmap) { - location &= 0x7; // we only have 8 locations 0-7 - command(LCD_SETCGRAMADDR | (location << 3)); - for (int i=0; i<8; i++) { - write(pgm_read_byte_near(charmap++)); - } -} - -// Turn the (optional) backlight off/on -void LiquidCrystal_I2C::noBacklight(void) { - _backlightval=LCD_NOBACKLIGHT; - expanderWrite(0); -} - -void LiquidCrystal_I2C::backlight(void) { - _backlightval=LCD_BACKLIGHT; - expanderWrite(0); -} - - - -/*********** mid level commands, for sending data/cmds */ - -inline void LiquidCrystal_I2C::command(uint8_t value) { - send(value, 0); -} - - -/************ low level data pushing commands **********/ - -// write either command or data -void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) { - uint8_t highnib=value&0xf0; - uint8_t lownib=(value<<4)&0xf0; - write4bits((highnib)|mode); - write4bits((lownib)|mode); -} - -void LiquidCrystal_I2C::write4bits(uint8_t value) { - expanderWrite(value); - pulseEnable(value); -} - -void LiquidCrystal_I2C::expanderWrite(uint8_t _data){ - Wire.beginTransmission(_Addr); - printIIC((int)(_data) | _backlightval); - Wire.endTransmission(); -} - -void LiquidCrystal_I2C::pulseEnable(uint8_t _data){ - expanderWrite(_data | En); // En high - delayMicroseconds(1); // enable pulse must be >450ns - - expanderWrite(_data & ~En); // En low - delayMicroseconds(50); // commands need > 37us to settle -} - - -// Alias functions - -void LiquidCrystal_I2C::cursor_on(){ - cursor(); -} - -void LiquidCrystal_I2C::cursor_off(){ - noCursor(); -} - -void LiquidCrystal_I2C::blink_on(){ - blink(); -} - -void LiquidCrystal_I2C::blink_off(){ - noBlink(); -} - -void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows){ - createChar(char_num, rows); -} - -void LiquidCrystal_I2C::setBacklight(uint8_t new_val){ - if(new_val){ - backlight(); // turn backlight on - }else{ - noBacklight(); // turn backlight off - } -} - -void LiquidCrystal_I2C::printstr(const char c[]){ - //This function is not identical to the function used for "real" I2C displays - //it's here so the user sketch doesn't have to be changed - print(c); -} - - -// unsupported API functions -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -void LiquidCrystal_I2C::off(){} -void LiquidCrystal_I2C::on(){} -void LiquidCrystal_I2C::setDelay (int cmdDelay,int charDelay) {} -uint8_t LiquidCrystal_I2C::status(){return 0;} -uint8_t LiquidCrystal_I2C::keypad (){return 0;} -uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype){return 0;} -void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end){} -void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end){} -void LiquidCrystal_I2C::setContrast(uint8_t new_val){} -#pragma GCC diagnostic pop - +#include "LiquidCrystal_I2C.h" + +#if defined(ARDUINO) + #include "ArduinoImpl.h" +#else + #include "RPIImpl.h" +#endif + +#include +#include +#include + +// When the display powers up, it is configured as follows: +// +// 1. Display clear +// 2. Function set: +// DL = 1; 8-bit interface data +// N = 0; 1-line display +// F = 0; 5x8 dot character font +// 3. Display on/off control: +// D = 0; Display off +// C = 0; Cursor off +// B = 0; Blinking off +// 4. Entry mode set: +// I/D = 1; Increment by 1 +// S = 0; No shift +// +// Note, however, that resetting the Arduino doesn't reset the LCD, so we +// can't assume that its in that state when a sketch starts (and the +// LiquidCrystal constructor is called). + +LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows) +{ + _Addr = lcd_Addr; + _cols = lcd_cols; + _rows = lcd_rows; + _backlightval = LCD_NOBACKLIGHT; + _adapter = 2; + createDevice(); +} + +LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t lcd_cols, +uint8_t lcd_rows, uint8_t lcd_adapter) +{ + _Addr = lcd_Addr; + _cols = lcd_cols; + _rows = lcd_rows; + _backlightval = LCD_NOBACKLIGHT; + _adapter = lcd_adapter; + createDevice(); +} + +// compile time factory to get proper implementation class + +void LiquidCrystal_I2C::createDevice() +{ +#if defined(ARDUINO) + _pImpl = new ArduinoImpl(_Addr, _cols, _rows); +#else + _pImpl = new RPIImpl(_Addr, _cols, _rows, _adapter); +#endif + _pImpl->setBacklightVal(_backlightval); +} + +void LiquidCrystal_I2C::write(uint8_t value) +{ + send(value, Rs); +} + +void LiquidCrystal_I2C::oled_init() +{ + _oled = true; + init_priv(); +} + +void LiquidCrystal_I2C::init() +{ + init_priv(); +} + +void LiquidCrystal_I2C::init_priv() +{ + _pImpl->init_priv(); // Wire.begin() on arduino; + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + begin(_cols, _rows); +} + +void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) +{ + if (lines > 1) { + _displayfunction |= LCD_2LINE; + } + + _numlines = lines; + + // for some 1 line displays you can select a 10 pixel high font + if ((dotsize != 0) && (lines == 1)) { + _displayfunction |= LCD_5x10DOTS; + } + + // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! + // according to datasheet, we need at least 40ms after power rises above 2.7V + // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 + + _pImpl->delayMilliseconds(50); + + // Now we pull both RS and R/W low to begin commands + + expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) + _pImpl->delayMilliseconds(1000); + + //put the LCD into 4 bit mode + // this is according to the hitachi HD44780 datasheet + // figure 24, pg 46 + + // we start in 8bit mode, try to set 4 bit mode + + write4bits(0x03 << 4); + _pImpl->delayMicroseconds(4500); // wait min 4.1ms + + // second try + write4bits(0x03 << 4); + _pImpl->delayMicroseconds(4500); // wait min 4.1ms + + // third go! + write4bits(0x03 << 4); + _pImpl->delayMicroseconds(150); + + // finally, set to 4-bit interface + write4bits(0x02 << 4); + + // set # lines, font size, etc. + command(LCD_FUNCTIONSET | _displayfunction); + + // turn the display on with no cursor or blinking default + _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; + display(); + + // clear it off + clear(); + + // Initialize to default text direction (for roman languages) + _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; + + // set the entry mode + command(LCD_ENTRYMODESET | _displaymode); + + home(); +} + +/********** high level commands, for the user! */ +void LiquidCrystal_I2C::clear() +{ + command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero + _pImpl->delayMicroseconds(2000); // this command takes a long time! + if (_oled) { + setCursor(0,0); + } +} + +void LiquidCrystal_I2C::delay(int ms) +{ + _pImpl->delayMilliseconds(ms); +} + +void LiquidCrystal_I2C::home() +{ + command(LCD_RETURNHOME); // set cursor position to zero + _pImpl->delayMicroseconds(2000); // this command takes a long time! +} + +void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row) +{ + int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; + if ( row > _numlines ) { + row = _numlines-1; // we count rows starting w/0 + } + command(LCD_SETDDRAMADDR | (col + row_offsets[row])); +} + +// Turn the display on/off (quickly) +void LiquidCrystal_I2C::noDisplay() +{ + _displaycontrol &= ~LCD_DISPLAYON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void LiquidCrystal_I2C::display() +{ + _displaycontrol |= LCD_DISPLAYON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turns the underline cursor on/off +void LiquidCrystal_I2C::noCursor() +{ + _displaycontrol &= ~LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void LiquidCrystal_I2C::cursor() +{ + _displaycontrol |= LCD_CURSORON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// Turn on and off the blinking cursor +void LiquidCrystal_I2C::noBlink() +{ + _displaycontrol &= ~LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +void LiquidCrystal_I2C::blink() +{ + _displaycontrol |= LCD_BLINKON; + command(LCD_DISPLAYCONTROL | _displaycontrol); +} + +// These commands scroll the display without changing the RAM +void LiquidCrystal_I2C::scrollDisplayLeft(void) +{ + command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); +} + +void LiquidCrystal_I2C::scrollDisplayRight(void) +{ + command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); +} + +// This is for text that flows Left to Right +void LiquidCrystal_I2C::leftToRight(void) +{ + _displaymode |= LCD_ENTRYLEFT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This is for text that flows Right to Left +void LiquidCrystal_I2C::rightToLeft(void) +{ + _displaymode &= ~LCD_ENTRYLEFT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'right justify' text from the cursor +void LiquidCrystal_I2C::autoscroll(void) +{ + _displaymode |= LCD_ENTRYSHIFTINCREMENT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// This will 'left justify' text from the cursor +void LiquidCrystal_I2C::noAutoscroll(void) +{ + _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; + command(LCD_ENTRYMODESET | _displaymode); +} + +// Allows us to fill the first 8 CGRAM locations +// with custom characters +void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) +{ + location &= 0x7; // we only have 8 locations 0-7 + command(LCD_SETCGRAMADDR | (location << 3)); + for (int i=0; i<8; i++) { + write(charmap[i]); + } +} + +#if 0 +//createChar with PROGMEM input +void LiquidCrystal_I2C::createChar(uint8_t location, const char *charmap) +{ + Serial.print("createChar 2\n"); + location &= 0x7; // we only have 8 locations 0-7 + command(LCD_SETCGRAMADDR | (location << 3)); + for (int i=0; i<8; i++) { + write(pgm_read_byte_near(charmap++)); + } +} +#endif + +// Turn the (optional) backlight off/on +void LiquidCrystal_I2C::noBacklight(void) +{ + _backlightval=LCD_NOBACKLIGHT; + _pImpl->setBacklightVal(_backlightval); + expanderWrite(0); +} + +void LiquidCrystal_I2C::backlight(void) +{ + _backlightval=LCD_BACKLIGHT; + _pImpl->setBacklightVal(_backlightval); + expanderWrite(0); +} + +/*********** mid level commands, for sending data/cmds */ + +inline void LiquidCrystal_I2C::command(uint8_t value) +{ + send(value, 0); +} + +/************ low level data pushing commands **********/ + +// write either command or data +void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) +{ + uint8_t highnib=value&0xf0; + uint8_t lownib=(value<<4)&0xf0; + write4bits((highnib)|mode); + write4bits((lownib)|mode); +} + +void LiquidCrystal_I2C::write4bits(uint8_t value) +{ + expanderWrite(value); + pulseEnable(value); +} + +void LiquidCrystal_I2C::expanderWrite(uint8_t _data) +{ + _pImpl->expanderWrite(_data); +} + +void LiquidCrystal_I2C::pulseEnable(uint8_t _data){ + expanderWrite(_data | En); // En high + _pImpl->delayMicroseconds(1); // enable pulse must be >450ns + expanderWrite(_data & ~En); // En low + _pImpl->delayMicroseconds(50); // commands need > 37us to settle +} + +// Alias functions + +void LiquidCrystal_I2C::cursor_on() +{ + cursor(); +} + +void LiquidCrystal_I2C::cursor_off() +{ + noCursor(); +} + +void LiquidCrystal_I2C::blink_on() +{ + blink(); +} + +void LiquidCrystal_I2C::blink_off() +{ + noBlink(); +} + +void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows) +{ + createChar(char_num, rows); +} + +void LiquidCrystal_I2C::setBacklight(uint8_t new_val) +{ + if (new_val) { + backlight(); // turn backlight on + } else { + noBacklight(); // turn backlight off + } +} + +void LiquidCrystal_I2C::printstr(const char c[]) +{ + //This function is not identical to the function used for "real" I2C displays + //it's here so the user sketch doesn't have to be changed + print(c); +} + +// replace the Arduino implemented Print with our own + +size_t LiquidCrystal_I2C::print(const char arg1[]) +{ + for (int i = 0; i < strlen(arg1); i++) { + print(arg1[i]); + } + return strlen(arg1); +} + +size_t LiquidCrystal_I2C::print(char arg1) +{ + write(arg1); + return 1; +} + +size_t LiquidCrystal_I2C::print(unsigned char arg1, int base) +{ + return print(((int) arg1) & 0xff, base); +} + +size_t LiquidCrystal_I2C::print(int arg1, int base) +{ + // XXX this works if value is not negative + + return print(((unsigned int) arg1) & 0xff, base); +} + +size_t LiquidCrystal_I2C::print(unsigned int arg1, int base) +{ + char buf[4]; + char format[4]; + + if (base == HEX) { + strcpy(format, "%x"); + } else { + strcpy(format, "%o"); + } + snprintf(buf, sizeof(buf), format, arg1); + for (int i = 0; i < strlen(buf); i++) { + print(buf[i]); + } + return strlen(buf); +} + +size_t LiquidCrystal_I2C::print(long arg1, int base) +{ + // TBD + return 0; +} + +size_t LiquidCrystal_I2C::print(unsigned long arg1, int base) +{ + // TBD + return 0; +} + +size_t LiquidCrystal_I2C::print(double arg1, int base) +{ + // TBD + return 0; +} diff --git a/LiquidCrystal_I2C.h b/LiquidCrystal_I2C.h index f7c7d13..76f44d9 100644 --- a/LiquidCrystal_I2C.h +++ b/LiquidCrystal_I2C.h @@ -1,131 +1,139 @@ -//YWROBOT -#ifndef LiquidCrystal_I2C_h -#define LiquidCrystal_I2C_h - -#include -#include "Print.h" -#include - -// 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 B00000100 // Enable bit -#define Rw B00000010 // Read/Write bit -#define Rs B00000001 // Register select bit - -class LiquidCrystal_I2C : public Print { -public: - LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows); - void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS ); - void clear(); - void home(); - void noDisplay(); - void display(); - void noBlink(); - void blink(); - void noCursor(); - void cursor(); - void scrollDisplayLeft(); - void scrollDisplayRight(); - void printLeft(); - void printRight(); - void leftToRight(); - void rightToLeft(); - void shiftIncrement(); - void shiftDecrement(); - void noBacklight(); - void backlight(); - void autoscroll(); - void noAutoscroll(); - void createChar(uint8_t, uint8_t[]); - void createChar(uint8_t location, const char *charmap); - // Example: const char bell[8] PROGMEM = {B00100,B01110,B01110,B01110,B11111,B00000,B00100,B00000}; - - void setCursor(uint8_t, uint8_t); -#if defined(ARDUINO) && ARDUINO >= 100 - virtual size_t write(uint8_t); -#else - virtual void write(uint8_t); -#endif - void command(uint8_t); - void init(); - void oled_init(); - -////compatibility API function aliases -void blink_on(); // alias for blink() -void blink_off(); // alias for noBlink() -void cursor_on(); // alias for cursor() -void cursor_off(); // alias for noCursor() -void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight() -void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar() -void printstr(const char[]); - -////Unsupported API functions (not implemented in this library) -uint8_t status(); -void setContrast(uint8_t new_val); -uint8_t keypad(); -void setDelay(int,int); -void on(); -void off(); -uint8_t init_bargraph(uint8_t graphtype); -void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end); -void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end); - - -private: - void init_priv(); - void send(uint8_t, uint8_t); - void write4bits(uint8_t); - void expanderWrite(uint8_t); - void pulseEnable(uint8_t); - uint8_t _Addr; - uint8_t _displayfunction; - uint8_t _displaycontrol; - uint8_t _displaymode; - uint8_t _numlines; - bool _oled = false; - uint8_t _cols; - uint8_t _rows; - uint8_t _backlightval; -}; - -#endif +#ifndef LiquidCrystal_I2C_h +#define LiquidCrystal_I2C_h + +#include + +#include "LCI2CImpl.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 + +#if !defined(BIN) +#define BIN 2 +#endif +#if !defined(OCT) +#define OCT 8 +#endif +#if !defined(HEX) +#define HEX 16 +#endif + +// 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 0x04 // Enable bit B00000100 +#define Rw 0x02 // Read/Write bit B00000010 +#define Rs 0x01 // Register select bit B00000001 + +class LiquidCrystal_I2C { +public: + LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows); + LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows, +uint8_t lcd_adapter); + void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); + void clear(); + void home(); + void noDisplay(); + void display(); + void noBlink(); + void blink(); + void noCursor(); + void cursor(); + void scrollDisplayLeft(); + void scrollDisplayRight(); + void printLeft(); + void printRight(); + void leftToRight(); + void rightToLeft(); + void shiftIncrement(); + void shiftDecrement(); + void noBacklight(); + void backlight(); + void autoscroll(); + void noAutoscroll(); + void createChar(uint8_t, uint8_t[]); +#if 0 + void createChar(uint8_t location, const char *charmap); + // Example: const char bell[8] PROGMEM = {B00100,B01110,B01110,B01110,B11111,B00000,B00100,B00000}; +#endif + + void setCursor(uint8_t, uint8_t); + void write(uint8_t); + void command(uint8_t); + void init(); + void oled_init(); + void delay(int ms); + void blink_on(); // alias for blink() + void blink_off(); // alias for noBlink() + void cursor_on(); // alias for cursor() + void cursor_off(); // alias for noCursor() + void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight() + void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar() + void printstr(const char[]); + size_t print(const char arg1[]); + size_t print(char arg1); + size_t print(unsigned char arg1, int arg2); + size_t print(int arg1, int arg2); + size_t print(unsigned int arg1, int arg2); + size_t print(long arg1, int arg2); + size_t print(unsigned long arg1, int arg2); + size_t print(double arg1, int arg2 = 2); + +private: + void createDevice(); + void init_priv(); + void send(uint8_t, uint8_t); + void write4bits(uint8_t); + void expanderWrite(uint8_t); + void pulseEnable(uint8_t); + LCI2CImpl *_pImpl; + uint8_t _Addr; + uint8_t _adapter; + uint8_t _displayfunction; + uint8_t _displaycontrol; + uint8_t _displaymode; + uint8_t _numlines; + bool _oled = false; + uint8_t _cols; + uint8_t _rows; + uint8_t _backlightval; +}; + +#endif diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..fad8263 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,21 @@ +AM_CXXFLAGS = + +ACLOCAL_AMFLAGS = -I m4 + +lib_LTLIBRARIES = liblci2c.la + +liblci2c_la_SOURCES = \ + RPIImpl.cpp \ + LiquidCrystal_I2C.cpp \ + LCI2CImpl.cpp + +liblci2c_la_CXXFLAGS = $(AM_CXXFLAGS) +liblci2c_la_LIBADD = + +#bin_PROGRAMS = tests +# +#tests_SOURCES = tests.cpp +#tests_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON) +#tests_LDADD = -lhiredis -lswsscommon -lpthread $(top_srcdir)/meta/libsaimetadata.la $(top_srcdir)/meta/libsaimeta.la libsairedis.la +# +#TESTS = tests diff --git a/README.md b/README.md index 1a1664c..4e22a2c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,30 @@ # LiquidCrystal_I2C -LiquidCrystal Arduino library for I2C LCD displays +Portable LiquidCrystal C++ library for I2C LCD displays, with implementations +for both Arduino and RPI (RPI should work with any modern Linux device that +supports I2C). -This repo is being transfered to GitLab at https://gitlab.com/tandembyte/liquidcrystal_i2c +Arduino Instructions + +Copy to the libraries dir of the IDE using standard process. Then load +one of the sketches into the IDE in exampiles directory, compile, burn to +device as usual. + +Linux Instructions + +Native RPI (Raspbian) + +``` +$ autoreconf --install +$ ./configure +$ sudo make install +``` + +The build examples: + +``` +$ cd examples/CustomChars +``` + +Follow steps in README.txt (you can execute the README in bash from command +line as well). diff --git a/RPIImpl.cpp b/RPIImpl.cpp new file mode 100644 index 0000000..7f69b9a --- /dev/null +++ b/RPIImpl.cpp @@ -0,0 +1,136 @@ +#if !defined(ARDUINO) + +#include "RPIImpl.h" +#include +#include "LiquidCrystal_I2C.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +RPIImpl::RPIImpl(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows) +{ + _Addr = lcd_Addr; + _cols = lcd_cols; + _rows = lcd_rows; + _backlightval = LCD_NOBACKLIGHT; + + /* default the adapter, almost surely wrong. caller should + inspect /sys/class/i2c-dev/ or run "i2cdetect -l" and + use other constructor, which passes the adapter explicitly */ + + _adapter = 1; + _fd = -1; +} + +RPIImpl::RPIImpl(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows, uint8_t +i2c_adapter) +{ + _Addr = lcd_Addr; + _cols = lcd_cols; + _rows = lcd_rows; + _backlightval = LCD_NOBACKLIGHT; + _adapter = i2c_adapter; + _fd = -1; +} + +RPIImpl::~RPIImpl() +{ + if (_fd != -1) { + ::close(_fd); + _fd = -1; + } +} + +void RPIImpl::delayMilliseconds(uint32_t delay) +{ + // XXX this may need to push down to driver, given in userland, hard + // to make strong promises about delays. + + struct timespec ts; + int res; + + ts.tv_sec = delay / 1000; + ts.tv_nsec = (delay % 1000) * 1000000; + + do { + res = nanosleep(&ts, &ts); + } while (res && errno == EINTR); +} + +void RPIImpl::delayMicroseconds(uint32_t delay) +{ + // XXX this may need to push down to driver, given in userland, hard + // to make strong promises about delays. + + struct timespec ts; + int res; + + ts.tv_sec = delay / 1000000; + ts.tv_nsec = (delay % 1000000) * 1000; + + do { + res = nanosleep(&ts, &ts); + } while (res && errno == EINTR); +} + +void RPIImpl::setBacklightVal(uint8_t val) +{ + _backlightval = val; +} + +void RPIImpl::init_priv() +{ +#if !defined(ARDUINO) + fprintf(stderr, "%s enter\n", __FUNCTION__); +#endif + char filename[20]; + + snprintf(filename, sizeof(filename), "/dev/i2c-%d", _adapter); + _fd = open(filename, O_RDWR); + if (_fd < 0) { +#if !defined(ARDUINO) + fprintf(stderr, "unable to open %s, errno is %d\n", filename, errno); +#endif + } + + if (ioctl(_fd, I2C_SLAVE, _Addr) < 0) { +#if !defined(ARDUINO) + fprintf(stderr, "ioctl failed for fd %d and addr %d, errno is %d\n", +_fd, _Addr, errno); +#endif + } +#if defined(NOT_YET) + Serial.print("ArduinoImpl::init_priv\n"); + Wire.begin(); +#endif +} + +void RPIImpl::expanderWrite(uint8_t data) +{ +#if !defined(ARDUINO) && 0 + fprintf(stderr, "%s enter fd is %d\n", __FUNCTION__, _fd); +#endif + if (_fd >= 0) { + data |= _backlightval; + int ret = write(_fd, (char *) &data, sizeof(data)); + if (ret < 0) { +#if !defined(ARDUINO) + fprintf(stderr, "write failed for fd %d, errno is %d\n", _fd, errno); +#endif + } + } +#if defined(NOT_YET) + Wire.beginTransmission(_Addr); + printIIC((int)(_data) | _backlightval); + Wire.endTransmission(); +#endif +} + +#endif // !ARDUINO diff --git a/RPIImpl.h b/RPIImpl.h new file mode 100644 index 0000000..8874927 --- /dev/null +++ b/RPIImpl.h @@ -0,0 +1,29 @@ +#ifndef _RPIIMPL_H_ +#define _RPIIMPL_H_ + +#if !defined(ARDUINO) +#include "LCI2CImpl.h" + +class RPIImpl : public LCI2CImpl { +public: + RPIImpl(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows); + RPIImpl(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows, uint8_t +i2c_adapter); + virtual ~RPIImpl(); + virtual void init_priv(); + virtual void setBacklightVal(uint8_t val); + virtual void delayMilliseconds(uint32_t val); + virtual void delayMicroseconds(uint32_t val); + virtual void expanderWrite(uint8_t _data); +private: + uint8_t _Addr; + uint8_t _cols; + uint8_t _rows; + uint8_t _backlightval; + uint8_t _adapter; + int _fd; +}; + +#endif // !ARDUINO + +#endif diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..6c63370 --- /dev/null +++ b/configure.ac @@ -0,0 +1,12 @@ +AC_INIT([liblci2c], [1.0], [bug-automake@gnu.org]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AC_PROG_CXX +AM_PROG_AR +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIRS([m4]) +AC_CONFIG_FILES([ + Makefile +]) +LT_INIT +AC_OUTPUT + diff --git a/examples/CustomChars/CustomChars.cpp b/examples/CustomChars/CustomChars.cpp new file mode 100644 index 0000000..b73246a --- /dev/null +++ b/examples/CustomChars/CustomChars.cpp @@ -0,0 +1,145 @@ +//YWROBOT +//Compatible with the Arduino IDE 1.0 +//Library version:1.1 +#include "LiquidCrystal_I2C.h" + +#if !defined(ARDUINO) || (defined(ARDUINO) && ARDUINO >= 100) +#define printByte(args) write(args); +#else +#define printByte(args) print(args,BYTE); +#endif + +uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4}; +uint8_t note[8] = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0}; +uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0}; +uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0}; +uint8_t duck[8] = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0}; +uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0}; +uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0}; +uint8_t retarrow[8] = { 0x1,0x1,0x5,0x9,0x1f,0x8,0x4}; + +#if !defined(ARDUINO) +#include +#endif + +// display all keycodes +void displayKeyCodes(LiquidCrystal_I2C &lcd) { +#if !defined(ARDUINO) + fprintf(stderr, "%s enter\n", __FUNCTION__); +#endif + uint8_t i = 0; + while (1) { + lcd.clear(); + lcd.print("Codes 0x"); lcd.print(i, HEX); + lcd.print("-0x"); lcd.print(i+15, HEX); + lcd.setCursor(0, 1); + for (int j=0; j<16; j++) { + lcd.printByte(i+j); + } + i+=16; + + lcd.delay(4000); + } +} + +void setupInternal(LiquidCrystal_I2C &lcd) +{ +#if !defined(ARDUINO) + fprintf(stderr, "%s enter\n", __FUNCTION__); +#endif + lcd.init(); // initialize the lcd + lcd.backlight(); + + lcd.createChar(0, bell); + lcd.createChar(1, note); + lcd.createChar(2, clock); + lcd.createChar(3, heart); + lcd.createChar(4, duck); + lcd.createChar(5, check); + lcd.createChar(6, cross); + lcd.createChar(7, retarrow); + lcd.home(); + + lcd.print("Hello world..."); + lcd.setCursor(0, 1); + lcd.print(" i "); + lcd.printByte(3); +#if defined(ARDUINO) + lcd.print(" arduinos!"); +#else + lcd.print(" raspberry pis!"); +#endif + lcd.delay(5000); + displayKeyCodes(lcd); +} + +void setup() +{ +#if !defined(ARDUINO) + fprintf(stderr, "%s enter\n", __FUNCTION__); +#endif + LiquidCrystal_I2C lcd(0x27, 20, 4); + setupInternal(lcd); +} + +void loop() +{ +} + +#if !defined(ARDUINO) + +#include +#include +#include +#include + +void usage(char *pgm) +{ + fprintf(stderr, "usage: %s [-a adapter][-d addr][-r rows][-c columns]\n", pgm); + fprintf(stderr, "specify adapter in base 16, e.g., -a 27 for hex 0x27", pgm); + _exit(1); +} + +int main(int argc, char *argv[]) +{ + extern char *optarg; + extern int optind; + int c; + uint8_t adapter = 1; + uint8_t addr = 0x27; + uint8_t columns = 20; + uint8_t rows = 4; + + while ((c = getopt(argc, argv, "d:c:r:a:")) != -1) { + switch (c) { + case 'd': + adapter = (uint8_t) atoi(optarg); + break; + case 'a': + addr = (uint8_t) strtol(optarg, NULL, 16); + break; + case 'c': + columns = (uint8_t) atoi(optarg); + break; + case 'r': + rows = (uint8_t) atoi(optarg); + break; + default : + usage(argv[0]); + } + } + +#if !defined(ARDUINO) + fprintf(stderr, "addr %d columns %d rows %d adapter %d\n", + addr, columns, rows, adapter); +#endif + LiquidCrystal_I2C lcd(addr, columns, rows, adapter); + + setupInternal(lcd); + + while (1) { + loop(); + } +} + +#endif diff --git a/examples/CustomChars/README.txt b/examples/CustomChars/README.txt new file mode 100644 index 0000000..93eb191 --- /dev/null +++ b/examples/CustomChars/README.txt @@ -0,0 +1,9 @@ +#!/bin/bash + +g++ -I ../../ CustomChars.cpp -o customchars -llci2c + +# Inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to determine the +# i2c adapter number for the LCD display. These numbers are ephemeral +# and can change across reboots, so you can't assume anything. +# +# sudo LD_LIBRARY_PATH=/usr/local/lib ./customchars -a 27 -d 1 diff --git a/examples/HelloWorld/HelloWorld.cpp b/examples/HelloWorld/HelloWorld.cpp new file mode 100644 index 0000000..18e260a --- /dev/null +++ b/examples/HelloWorld/HelloWorld.cpp @@ -0,0 +1,81 @@ +//YWROBOT +//Compatible with the Arduino IDE 1.0 +//Library version:1.1 +#include + +void setup(LiquidCrystal_I2C &lcd) +{ + lcd.init(); // initialize the lcd + // Print a message to the LCD. + lcd.backlight(); + lcd.setCursor(3,0); + lcd.print("Hello, world!"); + lcd.setCursor(2,1); + lcd.print("Ywrobot Arduino!"); + lcd.setCursor(0,2); + lcd.print("Arduino LCM IIC 2004"); + lcd.setCursor(2,3); + lcd.print("Power By Ec-yuan!"); +} + +void loop() +{ +} + +#if !defined(ARDUINO) + +#include +#include +#include +#include + +void usage(char *pgm) +{ + fprintf(stderr, "usage: %s [-a adapter][-d addr][-r rows][-c columns]\n", pgm); + fprintf(stderr, "specify adapter in base 16, e.g., -a 27 for hex 0x27", pgm); + _exit(1); +} + +int main(int argc, char *argv[]) +{ + extern char *optarg; + extern int optind; + int c; + uint8_t adapter = 1; + uint8_t addr = 0x27; + uint8_t columns = 20; + uint8_t rows = 4; + + while ((c = getopt(argc, argv, "d:c:r:a:")) != -1) { + switch (c) { + case 'd': + adapter = (uint8_t) atoi(optarg); + break; + case 'a': + addr = (uint8_t) strtol(optarg, NULL, 16); + break; + case 'c': + columns = (uint8_t) atoi(optarg); + break; + case 'r': + rows = (uint8_t) atoi(optarg); + break; + default : + usage(argv[0]); + } + } + +#if !defined(ARDUINO) + fprintf(stderr, "addr %d columns %d rows %d adapter %d\n", + addr, columns, rows, adapter); +#endif + LiquidCrystal_I2C lcd(addr, columns, rows, adapter); + + setup(lcd); + + while (1) { + loop(); + } +} + +#endif diff --git a/examples/HelloWorld/HelloWorld.pde b/examples/HelloWorld/HelloWorld.pde index 234d115..a6b4cba 100644 --- a/examples/HelloWorld/HelloWorld.pde +++ b/examples/HelloWorld/HelloWorld.pde @@ -23,4 +23,4 @@ void setup() void loop() { -} +} diff --git a/examples/HelloWorld/README.txt b/examples/HelloWorld/README.txt new file mode 100644 index 0000000..2c667fc --- /dev/null +++ b/examples/HelloWorld/README.txt @@ -0,0 +1,9 @@ +#!/bin/bash + +g++ -I ../../ HelloWorld.cpp -o helloworld -llci2c + +# Inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to determine the +# i2c adapter number for the LCD display. These numbers are ephemeral +# and can change across reboots, so you can't assume anything. +# +# sudo LD_LIBRARY_PATH=/usr/local/lib ./helloworld -a 27 -d 1 diff --git a/examples/SerialDisplay/SerialDisplay.pde b/examples/SerialDisplay/SerialDisplay.pde index 1fca4e1..fdbbc64 100644 --- a/examples/SerialDisplay/SerialDisplay.pde +++ b/examples/SerialDisplay/SerialDisplay.pde @@ -31,4 +31,4 @@ void loop() lcd.write(Serial.read()); } } -} +} diff --git a/library.json b/library.json index 4710920..89c9115 100644 --- a/library.json +++ b/library.json @@ -5,7 +5,7 @@ "repository": { "type": "git", - "url": "https://github.com/marcoschwartz/LiquidCrystal_I2C.git" + "url": "https://github.com/slogan621/LiquidCrystal_I2C.git" }, "frameworks": "arduino", "platforms":