Files
New-LiquidCrystal/LiquidCrystal_I2C.cpp
T
FMC 1211ad8e4c Closes #20 - remove wait 1us during interrupt masking in loadSR. Not needed.
Closes #19 - Added support for on/off commands
Closes #18 - Set backlight initial state during initialization to off.
Closes #17 - New SR3W class.
Added documentation for new class
Move some methods for the public interface of the LCD class to private, since they should never be called by the user.
2012-03-16 21:29:45 +01:00

291 lines
7.9 KiB
C++
Executable File

// ---------------------------------------------------------------------------
// 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 <WProgram.h>
#else
#include <Arduino.h>
#endif
#include <inttypes.h>
#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
}