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{ 135init( 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, 139uint8_t backlighPin, t_backlighPol pol) 140{ 141init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 ); 142setBacklightPin(backlighPin, pol); 143} 144 145LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data,uint8_t clk,uint8_t strobe, 146uint8_t En,uint8_t Rw,uint8_t Rs, 147uint8_t d4,uint8_t d5,uint8_t d6,uint8_t d7 ) 148{ 149init( 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, 153uint8_t En,uint8_t Rw,uint8_t Rs, 154uint8_t d4,uint8_t d5,uint8_t d6,uint8_t d7, 155uint8_t backlighPin, t_backlighPol pol) 156{ 157init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 ); 158setBacklightPin(backlighPin, pol); 159} 160 161 162voidLiquidCrystal_SR3W::send(uint8_t value,uint8_t mode) 163{ 164 165if( mode != FOUR_BITS ) 166{ 167write4bits( (value >>4), mode );// upper nibble 168} 169write4bits( (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. 175waitUsec(37);//goes away on AVRs 176#else 177delayMicroseconds(37);// commands & data writes need > 37us to complete 178#endif 179 180} 181 182 183voidLiquidCrystal_SR3W::setBacklightPin(uint8_t value, t_backlighPol pol = POSITIVE ) 184{ 185 _backlightPinMask = (1<< value ); 186 _backlightStsMask = LCD_NOBACKLIGHT; 187 _polarity = pol; 188setBacklight(BACKLIGHT_OFF);// Set backlight to off as initial setup 189} 190 191voidLiquidCrystal_SR3W::setBacklight(uint8_t value ) 192{ 193// Check if backlight is available 194// ---------------------------------------------------- 195if( _backlightPinMask !=0x0) 196{ 197// Check for polarity to configure mask accordingly 198// ---------------------------------------------------------- 199if(((_polarity == POSITIVE) && (value >0)) || 200((_polarity == NEGATIVE ) && ( value ==0))) 201{ 202 _backlightStsMask = _backlightPinMask & LCD_BACKLIGHT; 203} 204else 205{ 206 _backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT; 207} 208loadSR( _backlightStsMask ); 209} 210} 211 212 213// PRIVATE METHODS 214// ----------------------------------------------------------------------------- 215 216intLiquidCrystal_SR3W::init(uint8_t data,uint8_t clk,uint8_t strobe, 217uint8_t Rs,uint8_t Rw,uint8_t En, 218uint8_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 244return(1); 245} 246 247voidLiquidCrystal_SR3W::write4bits(uint8_t value,uint8_t mode) 248{ 249uint8_t pinMapValue =0; 250 251// Map the value to LCD pin mapping 252// -------------------------------- 253for(uint8_t i =0; i <4; i++ ) 254{ 255if( ( 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; 267loadSR( pinMapValue | _En );// Send with enable high 268loadSR( pinMapValue);// Send with enable low 269} 270 271 272voidLiquidCrystal_SR3W::loadSR(uint8_t value) 273{ 274// Load the shift register with information 275fio_shiftOut(_data_reg, _data, _clk_reg, _clk, value, MSBFIRST); 276 277// Strobe the data into the latch 278ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 279{ 280fio_digitalWrite_HIGH(_strobe_reg, _strobe); 281fio_digitalWrite_SWITCHTO(_strobe_reg, _strobe, LOW); 282} 283}