libraries / Visuino_LiquidCrystal / Visuino_LiquidCrystal_I2C.cppon commit Added link to project report (97a3ba0)
   1// ---------------------------------------------------------------------------
   2// Created by Francisco Malpartida on 20/08/11.
   3// Copyright 2011 - Under creative commons license 3.0:
   4//        Attribution-ShareAlike CC BY-SA
   5//
   6// This software is furnished "as is", without technical support, and with no 
   7// warranty, express or implied, as to its usefulness for any purpose.
   8//
   9// Thread Safe: No
  10// Extendable: Yes
  11//
  12// @file LiquidCrystal_I2C.c
  13// This file implements a basic liquid crystal library that comes as standard
  14// in the Arduino SDK but using an I2C IO extension board.
  15// 
  16// @brief 
  17// This is a basic implementation of the LiquidCrystal library of the
  18// Arduino SDK. The original library has been reworked in such a way that 
  19// this class implements the all methods to command an LCD based
  20// on the Hitachi HD44780 and compatible chipsets using I2C extension
  21// backpacks such as the I2CLCDextraIO with the PCF8574* I2C IO Expander ASIC.
  22//
  23// The functionality provided by this class and its base class is identical
  24// to the original functionality of the Arduino LiquidCrystal library.
  25//
  26//
  27//
  28// @author F. Malpartida - fmalpartida@gmail.com
  29// ---------------------------------------------------------------------------
  30#if (ARDUINO <  100)
  31#include <WProgram.h>
  32#else
  33#include <Arduino.h>
  34#endif
  35#include <inttypes.h>
  36#include "Visuino_I2CIO.h"
  37#include "Visuino_LiquidCrystal_I2C.h"
  38
  39// CONSTANT  definitions
  40// ---------------------------------------------------------------------------
  41
  42// flags for backlight control
  43/*!
  44 @defined 
  45 @abstract   LCD_NOBACKLIGHT
  46 @discussion NO BACKLIGHT MASK
  47 */
  48#define LCD_NOBACKLIGHT 0x00
  49
  50/*!
  51 @defined 
  52 @abstract   LCD_BACKLIGHT
  53 @discussion BACKLIGHT MASK used when backlight is on
  54 */
  55#define LCD_BACKLIGHT   0xFF
  56
  57
  58// Default library configuration parameters used by class constructor with
  59// only the I2C address field.
  60// ---------------------------------------------------------------------------
  61/*!
  62 @defined 
  63 @abstract   Enable bit of the LCD
  64 @discussion Defines the IO of the expander connected to the LCD Enable
  65 */
  66#define EN 6  // Enable bit
  67
  68/*!
  69 @defined 
  70 @abstract   Read/Write bit of the LCD
  71 @discussion Defines the IO of the expander connected to the LCD Rw pin
  72 */
  73#define RW 5  // Read/Write bit
  74
  75/*!
  76 @defined 
  77 @abstract   Register bit of the LCD
  78 @discussion Defines the IO of the expander connected to the LCD Register select pin
  79 */
  80#define RS 4  // Register select bit
  81
  82/*!
  83 @defined 
  84 @abstract   LCD dataline allocation this library only supports 4 bit LCD control
  85 mode.
  86 @discussion D4, D5, D6, D7 LCD data lines pin mapping of the extender module
  87 */
  88#define D4 0
  89#define D5 1
  90#define D6 2
  91#define D7 3
  92
  93
  94// CONSTRUCTORS
  95// ---------------------------------------------------------------------------
  96LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr )
  97{
  98   config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7);
  99}
 100
 101
 102LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t backlighPin, 
 103                                     t_backlighPol pol = POSITIVE)
 104{
 105   config(lcd_Addr, EN, RW, RS, D4, D5, D6, D7);
 106   setBacklightPin(backlighPin, pol);
 107}
 108
 109LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
 110                                     uint8_t Rs)
 111{
 112   config(lcd_Addr, En, Rw, Rs, D4, D5, D6, D7);
 113}
 114
 115LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
 116                                     uint8_t Rs, uint8_t backlighPin, 
 117                                     t_backlighPol pol = POSITIVE)
 118{
 119   config(lcd_Addr, En, Rw, Rs, D4, D5, D6, D7);
 120   setBacklightPin(backlighPin, pol);
 121}
 122
 123LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
 124                                     uint8_t Rs, uint8_t d4, uint8_t d5,
 125                                     uint8_t d6, uint8_t d7 )
 126{
 127   config(lcd_Addr, En, Rw, Rs, d4, d5, d6, d7);
 128}
 129
 130LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
 131                                     uint8_t Rs, uint8_t d4, uint8_t d5,
 132                                     uint8_t d6, uint8_t d7, uint8_t backlighPin, 
 133                                     t_backlighPol pol = POSITIVE )
 134{
 135   config(lcd_Addr, En, Rw, Rs, d4, d5, d6, d7);
 136   setBacklightPin(backlighPin, pol);
 137}
 138
 139// PUBLIC METHODS
 140// ---------------------------------------------------------------------------
 141
 142//
 143// begin
 144void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) 
 145{
 146   
 147   init();     // Initialise the I2C expander interface
 148   LCD::begin ( cols, lines, dotsize );   
 149}
 150
 151
 152// User commands - users can expand this section
 153//----------------------------------------------------------------------------
 154// Turn the (optional) backlight off/on
 155
 156//
 157// setBacklightPin
 158void LiquidCrystal_I2C::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE )
 159{
 160   _backlightPinMask = ( 1 << value );
 161   _polarity = pol;
 162   setBacklight(BACKLIGHT_OFF);
 163}
 164
 165//
 166// setBacklight
 167void LiquidCrystal_I2C::setBacklight( uint8_t value ) 
 168{
 169   // Check if backlight is available
 170   // ----------------------------------------------------
 171   if ( _backlightPinMask != 0x0 )
 172   {
 173      // Check for polarity to configure mask accordingly
 174      // ----------------------------------------------------------
 175      if  (((_polarity == POSITIVE) && (value > 0)) || 
 176           ((_polarity == NEGATIVE ) && ( value == 0 )))
 177      {
 178         _backlightStsMask = _backlightPinMask & LCD_BACKLIGHT;
 179      }
 180      else 
 181      {
 182         _backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT;
 183      }
 184      _i2cio.write( _backlightStsMask );
 185   }
 186}
 187
 188
 189// PRIVATE METHODS
 190// ---------------------------------------------------------------------------
 191
 192//
 193// init
 194int LiquidCrystal_I2C::init()
 195{
 196   int status = 0;
 197   
 198   // initialize the backpack IO expander
 199   // and display functions.
 200   // ------------------------------------------------------------------------
 201   if ( _i2cio.begin ( _Addr ) == 1 )
 202   {
 203      _i2cio.portMode ( OUTPUT );  // Set the entire IO extender to OUTPUT
 204      _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
 205      status = 1;
 206      _i2cio.write(0);  // Set the entire port to LOW
 207   }
 208   return ( status );
 209}
 210
 211//
 212// config
 213void LiquidCrystal_I2C::config (uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs, 
 214                                uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 )
 215{
 216   _Addr = lcd_Addr;
 217   
 218   _backlightPinMask = 0;
 219   _backlightStsMask = LCD_NOBACKLIGHT;
 220   _polarity = POSITIVE;
 221   
 222   _En = ( 1 << En );
 223   _Rw = ( 1 << Rw );
 224   _Rs = ( 1 << Rs );
 225   
 226   // Initialise pin mapping
 227   _data_pins[0] = ( 1 << d4 );
 228   _data_pins[1] = ( 1 << d5 );
 229   _data_pins[2] = ( 1 << d6 );
 230   _data_pins[3] = ( 1 << d7 );   
 231}
 232
 233
 234
 235// low level data pushing commands
 236//----------------------------------------------------------------------------
 237
 238//
 239// send - write either command or data
 240void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) 
 241{
 242   // No need to use the delay routines since the time taken to write takes
 243   // longer that what is needed both for toggling and enable pin an to execute
 244   // the command.
 245   
 246   if ( mode == FOUR_BITS )
 247   {
 248      write4bits( (value & 0x0F), COMMAND );
 249   }
 250   else 
 251   {
 252      write4bits( (value >> 4), mode );
 253      write4bits( (value & 0x0F), mode);
 254   }
 255}
 256
 257//
 258// write4bits
 259void LiquidCrystal_I2C::write4bits ( uint8_t value, uint8_t mode ) 
 260{
 261   uint8_t pinMapValue = 0;
 262   
 263   // Map the value to LCD pin mapping
 264   // --------------------------------
 265   for ( uint8_t i = 0; i < 4; i++ )
 266   {
 267      if ( ( value & 0x1 ) == 1 )
 268      {
 269         pinMapValue |= _data_pins[i];
 270      }
 271      value = ( value >> 1 );
 272   }
 273   
 274   // Is it a command or data
 275   // -----------------------
 276   if ( mode == DATA )
 277   {
 278      mode = _Rs;
 279   }
 280   
 281   pinMapValue |= mode | _backlightStsMask;
 282   pulseEnable ( pinMapValue );
 283}
 284
 285//
 286// pulseEnable
 287void LiquidCrystal_I2C::pulseEnable (uint8_t data)
 288{
 289   _i2cio.write (data | _En);   // En HIGH
 290   _i2cio.write (data & ~_En);  // En LOW
 291}