// --------------------------------------------------------------------------- // Created by Francisco Malpartida on 20/08/11. // Copyright 2011 - Under creative commons license 3.0: // Attribution-ShareAlike CC BY-SA // // This software is furnished "as is", without technical support, and with no // warranty, express or implied, as to its usefulness for any purpose. // // Thread Safe: No // Extendable: Yes // // @file LiquidCrystal_I2C.c // This file implements a basic liquid crystal library that comes as standard // in the Arduino SDK but using an I2C IO extension board. // // @brief // This is a basic implementation of the LiquidCrystal library of the // Arduino SDK. The original library has been reworked in such a way that // this class implements the all methods to command an LCD based // on the Hitachi HD44780 and compatible chipsets using I2C extension // backpacks such as the I2CLCDextraIO with the PCF8574* I2C IO Expander ASIC. // // The functionality provided by this class and its base class is identical // to the original functionality of the Arduino LiquidCrystal library. // // // // @author F. Malpartida - fmalpartida@gmail.com // --------------------------------------------------------------------------- #if (ARDUINO < 100) #include #else #include #endif #include #include "I2CIO.h" #include "LiquidCrystal_I2C.h" // CONSTANT definitions // --------------------------------------------------------------------------- // flags for backlight control /*! @defined @abstract LCD_NOBACKLIGHT @discussion NO BACKLIGHT MASK */ #define LCD_NOBACKLIGHT 0x00 /*! @defined @abstract LCD_BACKLIGHT @discussion BACKLIGHT MASK used when backlight is on */ #define LCD_BACKLIGHT 0xFF // Default library configuration parameters used by class constructor with // only the I2C address field. // --------------------------------------------------------------------------- /*! @defined @abstract Enable bit of the LCD @discussion Defines the IO of the expander connected to the LCD Enable */ #define EN 6 // Enable bit /*! @defined @abstract Read/Write bit of the LCD @discussion Defines the IO of the expander connected to the LCD Rw pin */ #define RW 5 // Read/Write bit /*! @defined @abstract Register bit of the LCD @discussion Defines the IO of the expander connected to the LCD Register select pin */ #define RS 4 // Register select bit /*! @defined @abstract LCD dataline allocation this library only supports 4 bit LCD control mode. @discussion D4, D5, D6, D7 LCD data lines pin mapping of the extender module */ #define D4 0 #define D5 1 #define D6 2 #define D7 3 // CONSTRUCTORS // --------------------------------------------------------------------------- LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr ) { config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7); } LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t backlighPin, t_backlighPol pol = POSITIVE) { config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7); setBacklightPin(backlighPin, pol); } LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs) { config(lcd_Addr, En, Rw, Rs, D4, D5, D6, D7); } LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, uint8_t backlighPin, t_backlighPol pol = POSITIVE) { config(lcd_Addr, En, Rw, Rs, D4, D5, D6, D7); setBacklightPin(backlighPin, pol); } LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 ) { config(lcd_Addr, En, Rw, Rs, d4, d5, d6, d7); } LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, uint8_t backlighPin, t_backlighPol pol = POSITIVE ) { config(lcd_Addr, En, Rw, Rs, d4, d5, d6, d7); setBacklightPin(backlighPin, pol); } // PUBLIC METHODS // --------------------------------------------------------------------------- // // begin void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { init(); // Initialise the I2C expander interface LCD::begin ( cols, lines, dotsize ); } // User commands - users can expand this section //---------------------------------------------------------------------------- // Turn the (optional) backlight off/on // // setBacklightPin void LiquidCrystal_I2C::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE ) { _backlightPinMask = ( 1 << value ); _polarity = pol; setBacklight(BACKLIGHT_OFF); } // // setBacklight void LiquidCrystal_I2C::setBacklight( uint8_t value ) { // Check if backlight is available // ---------------------------------------------------- if ( _backlightPinMask != 0x0 ) { // Check for polarity to configure mask accordingly // ---------------------------------------------------------- if (((_polarity == POSITIVE) && (value > 0)) || ((_polarity == NEGATIVE ) && ( value == 0 ))) { _backlightStsMask = _backlightPinMask & LCD_BACKLIGHT; } else { _backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT; } _i2cio.write( _backlightStsMask ); } } // PRIVATE METHODS // --------------------------------------------------------------------------- // // init int LiquidCrystal_I2C::init() { int status = 0; // initialize the backpack IO expander // and display functions. // ------------------------------------------------------------------------ if ( _i2cio.begin ( _Addr ) == 1 ) { _i2cio.portMode ( OUTPUT ); // Set the entire IO extender to OUTPUT _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; status = 1; _i2cio.write(0); // Set the entire port to LOW } return ( status ); } // // config void LiquidCrystal_I2C::config (uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 ) { _Addr = lcd_Addr; _backlightPinMask = 0; _backlightStsMask = LCD_NOBACKLIGHT; _polarity = POSITIVE; _En = ( 1 << En ); _Rw = ( 1 << Rw ); _Rs = ( 1 << Rs ); // Initialise pin mapping _data_pins[0] = ( 1 << d4 ); _data_pins[1] = ( 1 << d5 ); _data_pins[2] = ( 1 << d6 ); _data_pins[3] = ( 1 << d7 ); } // low level data pushing commands //---------------------------------------------------------------------------- // // send - write either command or data void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) { // No need to use the delay routines since the time taken to write takes // longer that what is needed both for toggling and enable pin an to execute // the command. if ( mode == FOUR_BITS ) { write4bits( (value & 0x0F), COMMAND ); } else { write4bits( (value >> 4), mode ); write4bits( (value & 0x0F), mode); } } // // write4bits void LiquidCrystal_I2C::write4bits ( uint8_t value, uint8_t mode ) { uint8_t pinMapValue = 0; // Map the value to LCD pin mapping // -------------------------------- for ( uint8_t i = 0; i < 4; i++ ) { if ( ( value & 0x1 ) == 1 ) { pinMapValue |= _data_pins[i]; } value = ( value >> 1 ); } // Is it a command or data // ----------------------- if ( mode == DATA ) { mode = _Rs; } pinMapValue |= mode | _backlightStsMask; pulseEnable ( pinMapValue ); } // // pulseEnable void LiquidCrystal_I2C::pulseEnable (uint8_t data) { _i2cio.write (data | _En); // En HIGH _i2cio.write (data & ~_En); // En LOW }