libraries / Visuino_LiquidCrystal / Visuino_LiquidCrystal_SR3W.cppon commit Added link to project report (97a3ba0)
   1// ---------------------------------------------------------------------------
   2// Created by Francisco Malpartida on 7.3.2012.
   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_SRG.h
  13// This file implements a basic liquid crystal library that comes as standard
  14// in the Arduino SDK but using a generic SHIFT REGISTER 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 a 3 wire latching
  21// shift register. While it has been tested with a 74HC595N shift register
  22// it should also work with other latching shift registers such as the MC14094
  23// and the HEF4094
  24//
  25// This particular driver has been created as generic as possible to enable
  26// users to configure and connect their LCDs using just 3 digital IOs from the
  27// AVR or Arduino, and connect the LCD to the outputs of the shiftregister
  28// in any configuration. The library is configured by passing the IO pins
  29// that control the strobe, data and clock of the shift register and a map
  30// of how the shiftregister is connected to the LCD.
  31// 
  32//
  33//   +--------------------------------------------+
  34//   |                 MCU                        |
  35//   |   IO1           IO2           IO3          |
  36//   +----+-------------+-------------+-----------+
  37//        |             |             |
  38//        |             |             |
  39//   +----+-------------+-------------+-----------+
  40//   |    Strobe        Data          Clock       |
  41//   |          8-bit shift/latch register        | 74HC595N
  42//   |    Qa0  Qb1  Qc2  Qd3  Qe4  Qf5  Qg6  Qh7  |
  43//   +----+----+----+----+----+----+----+----+----+
  44//        |    |    |    |    |    |    |    
  45//        |11  |12  |13  |14  |6   |5   |4   (LCD pins)
  46//   +----+----+----+----+----+----+----+----+----+
  47//   |    DB4  DB5  DB6  DB7  E    Rw   RS        |
  48//   |                 LCD Module                 |
  49//
  50// NOTE: Rw is not used by the driver so it can be connected to GND.
  51//
  52// The functionality provided by this class and its base class is identical
  53// to the original functionality of the Arduino LiquidCrystal library.
  54//
  55//
  56// History
  57// 2012.03.29 bperrybap - fixed constructors not properly using Rs
  58//                        Fixed incorrect use of 5x10 for default font 
  59//                        - now matches original LQ library.
  60//                        moved delay to send() so it is per cmd/write vs shiftout()
  61//                        NOTE: delay is on hairy edge of working when FAST_MODE is on.
  62//                        because of waitUsec().
  63//                        There is margin at 16Mhz AVR but might fail on 20Mhz AVRs.
  64//                        
  65// @author F. Malpartida - fmalpartida@gmail.com
  66// ---------------------------------------------------------------------------
  67// flags for backlight control
  68#include <stdio.h>
  69#include <string.h>
  70#include <inttypes.h>
  71
  72#if (ARDUINO <  100)
  73#include <WProgram.h>
  74#else
  75#include <Arduino.h>
  76#endif
  77#include "Visuino_LiquidCrystal_SR3W.h"
  78
  79#include "Visuino_FastIO.h"
  80
  81/*!
  82 @defined 
  83 @abstract   LCD_NOBACKLIGHT
  84 @discussion No BACKLIGHT MASK
  85 */
  86#define LCD_NOBACKLIGHT 0x00
  87
  88/*!
  89 @defined 
  90 @abstract   LCD_BACKLIGHT
  91 @discussion BACKLIGHT MASK used when backlight is on
  92 */
  93#define LCD_BACKLIGHT   0xFF
  94
  95
  96// Default library configuration parameters used by class constructor with
  97// only the I2C address field.
  98// ---------------------------------------------------------------------------
  99/*!
 100 @defined 
 101 @abstract   Enable bit of the LCD
 102 @discussion Defines the IO of the expander connected to the LCD's Enable
 103 */
 104#define EN 4  // Enable bit
 105
 106/*!
 107 @defined 
 108 @abstract   Read/Write bit of the LCD
 109 @discussion Defines the IO of the expander connected to the LCD's Rw pin
 110 */
 111#define RW 5  // Read/Write bit
 112
 113/*!
 114 @defined 
 115 @abstract   Register bit of the LCD
 116 @discussion Defines the IO of the expander connected to the LCD's Register select pin
 117 */
 118#define RS 6  // Register select bit
 119
 120/*!
 121 @defined 
 122 @abstract   LCD dataline allocation this library only supports 4 bit LCD control
 123 mode.
 124 @discussion D4, D5, D6, D7 LCD data lines pin mapping of the extender module
 125 */
 126#define D4 0
 127#define D5 1
 128#define D6 2
 129#define D7 3
 130
 131
 132
 133LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe)
 134{
 135   init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 );
 136}
 137
 138LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe,
 139                                       uint8_t backlighPin, t_backlighPol pol)
 140{
 141   init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 );
 142   setBacklightPin(backlighPin, pol);
 143}
 144
 145LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe,
 146                                       uint8_t En, uint8_t Rw, uint8_t Rs, 
 147                                       uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 )
 148{
 149   init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 );
 150}
 151
 152LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe, 
 153                                       uint8_t En, uint8_t Rw, uint8_t Rs, 
 154                                       uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
 155                                       uint8_t backlighPin, t_backlighPol pol)
 156{
 157   init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 );
 158   setBacklightPin(backlighPin, pol);
 159}
 160
 161
 162void LiquidCrystal_SR3W::send(uint8_t value, uint8_t mode)
 163{
 164   
 165   if ( mode != FOUR_BITS )
 166   {
 167      write4bits( (value >> 4), mode ); // upper nibble
 168   }   
 169   write4bits( (value & 0x0F), mode); // lower nibble
 170
 171
 172#if (F_CPU <= 16000000)
 173   // No need to use the delay routines on AVR since the time taken to write
 174   // on AVR with SR pin mapping even with fio is longer than LCD command execution.
 175   waitUsec(37); //goes away on AVRs
 176#else
 177   delayMicroseconds ( 37 );      // commands & data writes need > 37us to complete
 178#endif
 179
 180}
 181
 182
 183void LiquidCrystal_SR3W::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE )
 184{
 185   _backlightPinMask = ( 1 << value );
 186   _backlightStsMask = LCD_NOBACKLIGHT;
 187   _polarity = pol;
 188   setBacklight (BACKLIGHT_OFF);     // Set backlight to off as initial setup
 189}
 190
 191void LiquidCrystal_SR3W::setBacklight ( uint8_t value )
 192{
 193   // Check if backlight is available
 194   // ----------------------------------------------------
 195   if ( _backlightPinMask != 0x0 )
 196   {
 197      // Check for polarity to configure mask accordingly
 198      // ----------------------------------------------------------
 199      if  (((_polarity == POSITIVE) && (value > 0)) || 
 200           ((_polarity == NEGATIVE ) && ( value == 0 )))
 201      {
 202         _backlightStsMask = _backlightPinMask & LCD_BACKLIGHT;
 203      }
 204      else 
 205      {
 206         _backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT;
 207      }
 208      loadSR( _backlightStsMask );
 209   }
 210}
 211
 212
 213// PRIVATE METHODS
 214// -----------------------------------------------------------------------------
 215
 216int LiquidCrystal_SR3W::init(uint8_t data, uint8_t clk, uint8_t strobe, 
 217                             uint8_t Rs, uint8_t Rw, uint8_t En,
 218                             uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
 219{
 220   _data       = fio_pinToBit(data);
 221   _clk        = fio_pinToBit(clk);
 222   _strobe     = fio_pinToBit(strobe);
 223   _data_reg   = fio_pinToOutputRegister(data);
 224   _clk_reg    = fio_pinToOutputRegister(clk);
 225   _strobe_reg = fio_pinToOutputRegister(strobe);
 226   
 227   // LCD pin mapping
 228   _backlightPinMask = 0;
 229   _backlightStsMask = LCD_NOBACKLIGHT;
 230   _polarity = POSITIVE;
 231   
 232   _En = ( 1 << En );
 233   _Rw = ( 1 << Rw );
 234   _Rs = ( 1 << Rs );
 235   
 236   // Initialise pin mapping
 237   _data_pins[0] = ( 1 << d4 );
 238   _data_pins[1] = ( 1 << d5 );
 239   _data_pins[2] = ( 1 << d6 );
 240   _data_pins[3] = ( 1 << d7 );
 241   
 242   _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
 243   
 244   return (1);
 245}
 246
 247void LiquidCrystal_SR3W::write4bits(uint8_t value, uint8_t mode)
 248{
 249   uint8_t pinMapValue = 0;
 250   
 251   // Map the value to LCD pin mapping
 252   // --------------------------------
 253   for ( uint8_t i = 0; i < 4; i++ )
 254   {
 255      if ( ( value & 0x1 ) == 1 )
 256      {
 257         pinMapValue |= _data_pins[i];
 258      }
 259      value = ( value >> 1 );
 260   }
 261   
 262   // Is it a command or data
 263   // -----------------------
 264   mode = ( mode == DATA ) ? _Rs : 0;
 265   
 266   pinMapValue |= mode | _backlightStsMask;
 267   loadSR ( pinMapValue | _En );  // Send with enable high
 268   loadSR ( pinMapValue); // Send with enable low
 269}
 270
 271
 272void LiquidCrystal_SR3W::loadSR(uint8_t value) 
 273{
 274   // Load the shift register with information
 275   fio_shiftOut(_data_reg, _data, _clk_reg, _clk, value, MSBFIRST);
 276   
 277   // Strobe the data into the latch
 278   ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 279   {
 280      fio_digitalWrite_HIGH(_strobe_reg, _strobe);
 281      fio_digitalWrite_SWITCHTO(_strobe_reg, _strobe, LOW);
 282   }
 283}