| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- // ---------------------------------------------------------------------------
- // 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 fm_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 fm_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 <WProgram.h>
- //#else
- #include <Arduino.h>
- //#endif
- //#include <inttypes.h>
- //#include "fm_I2CIO.h"
- #include "fm_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 fm_LCD
- @discussion Defines the IO of the expander connected to the fm_LCD Enable
- */
- #define EN 6 // Enable bit
- /*!
- @defined
- @abstract Read/Write bit of the fm_LCD
- @discussion Defines the IO of the expander connected to the fm_LCD Rw pin
- */
- #define RW 5 // Read/Write bit
- /*!
- @defined
- @abstract Register bit of the fm_LCD
- @discussion Defines the IO of the expander connected to the fm_LCD Register select pin
- */
- #define RS 4 // Register select bit
- /*!
- @defined
- @abstract fm_LCD dataline allocation this library only supports 4 bit fm_LCD control
- mode.
- @discussion D4, D5, D6, D7 fm_LCD data lines pin mapping of the extender module
- */
- #define D4 0
- #define D5 1
- #define D6 2
- #define D7 3
- // CONSTRUCTORS
- // ---------------------------------------------------------------------------
- fm_LiquidCrystal_I2C::fm_LiquidCrystal_I2C( uint8_t lcd_Addr )
- {
- config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7);
- }
- fm_LiquidCrystal_I2C::fm_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);
- }
- fm_LiquidCrystal_I2C::fm_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);
- }
- fm_LiquidCrystal_I2C::fm_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);
- }
- fm_LiquidCrystal_I2C::fm_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);
- }
- fm_LiquidCrystal_I2C::fm_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 fm_LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize)
- {
- init(); // Initialise the I2C expander interface
- fm_LCD::begin ( cols, lines, dotsize );
- }
- // User commands - users can expand this section
- //----------------------------------------------------------------------------
- // Turn the (optional) backlight off/on
- //
- // setBacklightPin
- void fm_LiquidCrystal_I2C::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE )
- {
- _backlightPinMask = ( 1 << value );
- _polarity = pol;
- setBacklight(BACKLIGHT_OFF);
- }
- //
- // setBacklight
- void fm_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 fm_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 fm_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 fm_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 == LCD_MODE_4BIT)
- {
- write4bits( (value & 0x0F), LCD_SEND_CMD );
- }
- else
- {
- write4bits( (value >> 4), mode );
- write4bits( (value & 0x0F), mode);
- }
- }
- //
- // write4bits
- void fm_LiquidCrystal_I2C::write4bits ( uint8_t value, uint8_t mode )
- {
- uint8_t pinMapValue = 0;
- // Map the value to fm_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 == LCD_SEND_DATA )
- {
- mode = _Rs;
- }
- pinMapValue |= mode | _backlightStsMask;
- pulseEnable ( pinMapValue );
- }
- //
- // pulseEnable
- void fm_LiquidCrystal_I2C::pulseEnable (uint8_t data)
- {
- //Serial.print('d');
- //Serial.print(data);
- //Serial.print(';');
- #if 0
- _i2cio.write (data | _En); // En HIGH
- wait(200);
- _i2cio.write (data & ~_En); // En LOW
- wait(200);
- #else
- _i2cio.write (data | _En); // En HIGH
- _i2cio.write (data & ~_En); // En LOW
- #endif
- }
- void fm_LiquidCrystal_I2C::wait(uint16_t us)
- {
- //Serial.print('w');
- //Serial.print(us);
- //Serial.print(';');
- #if 0
- delayMicroseconds( us );
- #else
- _i2cio.wait(us);
- #endif
- }
|