libraries / Visuino_LiquidCrystal / Visuino_LiquidCrystal.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.cpp
  13// This file implements a basic liquid crystal library that comes as standard
  14// in the Arduino SDK.
  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 the parallel port of
  21// the LCD (4 bit and 8 bit).
  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// @author F. Malpartida - fmalpartida@gmail.com
  28// ---------------------------------------------------------------------------
  29#include <stdio.h>
  30#include <string.h>
  31#include <inttypes.h>
  32
  33#if (ARDUINO <  100)
  34#include <WProgram.h>
  35#else
  36#include <Arduino.h>
  37#endif
  38#include "Visuino_LiquidCrystal.h"
  39
  40// CONSTANT  definitions
  41// ---------------------------------------------------------------------------
  42#define LCD_NOBACKLIGHT 0xFF
  43
  44// LCD driver configuration (4bit or 8bit driver control)
  45#define LCD_4BIT                1
  46#define LCD_8BIT                0
  47
  48// STATIC helper functions
  49// ---------------------------------------------------------------------------
  50
  51
  52// CONSTRUCTORS
  53// ---------------------------------------------------------------------------
  54
  55LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable,
  56                             uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
  57                             uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
  58{
  59   init(LCD_8BIT, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7);
  60}
  61
  62LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
  63                             uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
  64                             uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
  65{
  66   init(LCD_8BIT, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7);
  67}
  68
  69LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
  70                             uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
  71{
  72   init(LCD_4BIT, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0);
  73}
  74
  75LiquidCrystal::LiquidCrystal(uint8_t rs,  uint8_t enable,
  76                             uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
  77{
  78   init(LCD_4BIT, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0);
  79}
  80
  81// Contructors with backlight control
  82LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable,
  83                             uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
  84                             uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
  85                             uint8_t backlightPin, t_backlighPol pol)
  86{
  87   init(LCD_8BIT, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7);
  88   setBacklightPin ( backlightPin, pol );
  89}
  90
  91LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
  92                             uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
  93                             uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
  94                             uint8_t backlightPin, t_backlighPol pol)
  95{
  96   init(LCD_8BIT, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7);
  97   setBacklightPin ( backlightPin, pol );
  98}
  99
 100LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
 101                             uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
 102                             uint8_t backlightPin, t_backlighPol pol)
 103{
 104   init(LCD_4BIT, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0);
 105   setBacklightPin ( backlightPin, pol );
 106}
 107
 108LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable,
 109                             uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
 110                             uint8_t backlightPin, t_backlighPol pol)
 111{
 112   init(LCD_4BIT, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0);
 113   setBacklightPin ( backlightPin, pol );
 114}
 115
 116// PUBLIC METHODS
 117// ---------------------------------------------------------------------------
 118
 119/************ low level data pushing commands **********/
 120//
 121// send
 122void LiquidCrystal::send(uint8_t value, uint8_t mode) 
 123{
 124   // Only interested in COMMAND or DATA
 125   digitalWrite( _rs_pin, ( mode == DATA ) );
 126   
 127   // if there is a RW pin indicated, set it low to Write
 128   // ---------------------------------------------------
 129   if (_rw_pin != 255) 
 130   { 
 131      digitalWrite(_rw_pin, LOW);
 132   }
 133   
 134   if ( mode != FOUR_BITS )
 135   {   
 136      if ( (_displayfunction & LCD_8BITMODE ) )
 137      {
 138         writeNbits(value, 8); 
 139      } 
 140      else 
 141      {
 142         writeNbits ( value >> 4, 4 );
 143         writeNbits ( value, 4 );
 144      }
 145   } 
 146   else 
 147   {
 148      writeNbits ( value, 4 );
 149   }
 150   waitUsec ( EXEC_TIME ); // wait for the command to execute by the LCD
 151}
 152
 153//
 154// setBacklightPin
 155void LiquidCrystal::setBacklightPin ( uint8_t pin, t_backlighPol pol )
 156{
 157   pinMode ( pin, OUTPUT );       // Difine the backlight pin as output
 158   _backlightPin = pin;
 159   _polarity = pol;
 160   setBacklight(BACKLIGHT_OFF);   // Set the backlight low by default
 161}
 162
 163//
 164// setBackligh
 165void LiquidCrystal::setBacklight ( uint8_t value )
 166{
 167   // Check if there is a pin assigned to the backlight
 168   // ---------------------------------------------------
 169   if ( _backlightPin != LCD_NOBACKLIGHT )
 170   {
 171      // Check if the pin is associated to a timer, i.e. PWM
 172      // ---------------------------------------------------
 173      if(digitalPinToTimer(_backlightPin) != NOT_ON_TIMER)
 174      {
 175         // Check for control polarity inversion
 176         // ---------------------------------------------------
 177         if ( _polarity == POSITIVE )
 178         {
 179            analogWrite ( _backlightPin, value );
 180         }
 181         else 
 182         {
 183            analogWrite ( _backlightPin, 255 - value );
 184         }
 185      }
 186      // Not a PWM pin, set the backlight pin for POSI or NEG
 187      // polarity
 188      // --------------------------------------------------------
 189      else if (((value > 0) && (_polarity == POSITIVE)) ||
 190               ((value == 0) && (_polarity == NEGATIVE)))
 191      {
 192         digitalWrite( _backlightPin, HIGH);
 193      }
 194      else
 195      {
 196         digitalWrite( _backlightPin, LOW);
 197      }
 198   }
 199}
 200
 201// PRIVATE METHODS
 202// ---------------------------------------------------------------------------
 203
 204
 205// init
 206void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
 207                         uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
 208                         uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
 209{
 210   uint8_t i;
 211   
 212   // Initialize the IO pins
 213   // -----------------------
 214   
 215   _rs_pin = rs;
 216   _rw_pin = rw;
 217   _enable_pin = enable;
 218   
 219   _data_pins[0] = d0;
 220   _data_pins[1] = d1;
 221   _data_pins[2] = d2;
 222   _data_pins[3] = d3; 
 223   _data_pins[4] = d4;
 224   _data_pins[5] = d5;
 225   _data_pins[6] = d6;
 226   _data_pins[7] = d7;
 227   
 228   // Initialize the IO port direction to OUTPUT
 229   // ------------------------------------------
 230   
 231   for ( i = 0; i < 4; i++ )
 232   {
 233      pinMode ( _data_pins[i], OUTPUT );
 234   }
 235   
 236   // Initialize the rest of the ports if it is an 8bit controlled LCD
 237   // ----------------------------------------------------------------
 238   
 239   if ( !fourbitmode )
 240   {
 241      for ( i = 4; i < 8; i++ )
 242      {
 243         pinMode ( _data_pins[i], OUTPUT );
 244      }
 245   }
 246   pinMode(_rs_pin, OUTPUT);
 247   
 248   // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
 249   if (_rw_pin != 255) 
 250   { 
 251      pinMode(_rw_pin, OUTPUT);
 252   }
 253   
 254   pinMode(_enable_pin, OUTPUT);
 255   
 256   // Initialise displaymode functions to defaults: LCD_1LINE and LCD_5x8DOTS
 257   // -------------------------------------------------------------------------
 258   if (fourbitmode)
 259      _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
 260   else 
 261      _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
 262   
 263   // Now we pull both RS and R/W low to begin commands
 264   digitalWrite(_rs_pin, LOW);
 265   digitalWrite(_enable_pin, LOW);
 266   
 267   if (_rw_pin != 255) 
 268   { 
 269      digitalWrite(_rw_pin, LOW);
 270   }
 271   
 272   // Initialise the backlight pin no nothing
 273   _backlightPin = LCD_NOBACKLIGHT;
 274   _polarity = POSITIVE;
 275}
 276
 277//
 278// pulseEnable
 279void LiquidCrystal::pulseEnable(void) 
 280{
 281   // There is no need for the delays, since the digitalWrite operation
 282   // takes longer.
 283   digitalWrite(_enable_pin, HIGH);   
 284   waitUsec(1);          // enable pulse must be > 450ns   
 285   digitalWrite(_enable_pin, LOW);
 286}
 287
 288//
 289// write4bits
 290void LiquidCrystal::writeNbits(uint8_t value, uint8_t numBits) 
 291{
 292   for (uint8_t i = 0; i < numBits; i++) 
 293   {
 294      digitalWrite(_data_pins[i], (value >> i) & 0x01);
 295   }
 296   pulseEnable();
 297}
 298
 299