kub-kar-timer/lib/NewLiquidCrystal/LiquidCrystal_SR3W.cpp

284 lines
9.0 KiB
C++

// ---------------------------------------------------------------------------
// Created by Francisco Malpartida on 7.3.2012.
// 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_SRG.h
// This file implements a basic liquid crystal library that comes as standard
// in the Arduino SDK but using a generic SHIFT REGISTER 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 a 3 wire latching
// shift register. While it has been tested with a 74HC595N shift register
// it should also work with other latching shift registers such as the MC14094
// and the HEF4094
//
// This particular driver has been created as generic as possible to enable
// users to configure and connect their LCDs using just 3 digital IOs from the
// AVR or Arduino, and connect the LCD to the outputs of the shiftregister
// in any configuration. The library is configured by passing the IO pins
// that control the strobe, data and clock of the shift register and a map
// of how the shiftregister is connected to the LCD.
//
//
// +--------------------------------------------+
// | MCU |
// | IO1 IO2 IO3 |
// +----+-------------+-------------+-----------+
// | | |
// | | |
// +----+-------------+-------------+-----------+
// | Strobe Data Clock |
// | 8-bit shift/latch register | 74HC595N
// | Qa0 Qb1 Qc2 Qd3 Qe4 Qf5 Qg6 Qh7 |
// +----+----+----+----+----+----+----+----+----+
// | | | | | | |
// |11 |12 |13 |14 |6 |5 |4 (LCD pins)
// +----+----+----+----+----+----+----+----+----+
// | DB4 DB5 DB6 DB7 E Rw RS |
// | LCD Module |
//
// NOTE: Rw is not used by the driver so it can be connected to GND.
//
// The functionality provided by this class and its base class is identical
// to the original functionality of the Arduino LiquidCrystal library.
//
//
// History
// 2012.03.29 bperrybap - fixed constructors not properly using Rs
// Fixed incorrect use of 5x10 for default font
// - now matches original LQ library.
// moved delay to send() so it is per cmd/write vs shiftout()
// NOTE: delay is on hairy edge of working when FAST_MODE is on.
// because of waitUsec().
// There is margin at 16Mhz AVR but might fail on 20Mhz AVRs.
//
// @author F. Malpartida - fmalpartida@gmail.com
// ---------------------------------------------------------------------------
// flags for backlight control
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#if (ARDUINO < 100)
#include <WProgram.h>
#else
#include <Arduino.h>
#endif
#include "LiquidCrystal_SR3W.h"
#include "FastIO.h"
/*!
@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's Enable
*/
#define EN 4 // Enable bit
/*!
@defined
@abstract Read/Write bit of the LCD
@discussion Defines the IO of the expander connected to the LCD's 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's Register select pin
*/
#define RS 6 // 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
LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe)
{
init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 );
}
LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe,
uint8_t backlighPin, t_backlighPol pol)
{
init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 );
setBacklightPin(backlighPin, pol);
}
LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe,
uint8_t En, uint8_t Rw, uint8_t Rs,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 )
{
init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 );
}
LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe,
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)
{
init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 );
setBacklightPin(backlighPin, pol);
}
void LiquidCrystal_SR3W::send(uint8_t value, uint8_t mode)
{
if ( mode != FOUR_BITS )
{
write4bits( (value >> 4), mode ); // upper nibble
}
write4bits( (value & 0x0F), mode); // lower nibble
#if (F_CPU <= 16000000)
// No need to use the delay routines on AVR since the time taken to write
// on AVR with SR pin mapping even with fio is longer than LCD command execution.
waitUsec(37); //goes away on AVRs
#else
delayMicroseconds ( 37 ); // commands & data writes need > 37us to complete
#endif
}
void LiquidCrystal_SR3W::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE )
{
_backlightPinMask = ( 1 << value );
_backlightStsMask = LCD_NOBACKLIGHT;
_polarity = pol;
setBacklight (BACKLIGHT_OFF); // Set backlight to off as initial setup
}
void LiquidCrystal_SR3W::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;
}
loadSR( _backlightStsMask );
}
}
// PRIVATE METHODS
// -----------------------------------------------------------------------------
int LiquidCrystal_SR3W::init(uint8_t data, uint8_t clk, uint8_t strobe,
uint8_t Rs, uint8_t Rw, uint8_t En,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
_data = fio_pinToBit(data);
_clk = fio_pinToBit(clk);
_strobe = fio_pinToBit(strobe);
_data_reg = fio_pinToOutputRegister(data);
_clk_reg = fio_pinToOutputRegister(clk);
_strobe_reg = fio_pinToOutputRegister(strobe);
// LCD pin mapping
_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 );
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
return (1);
}
void LiquidCrystal_SR3W::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
// -----------------------
mode = ( mode == DATA ) ? _Rs : 0;
pinMapValue |= mode | _backlightStsMask;
loadSR ( pinMapValue | _En ); // Send with enable high
loadSR ( pinMapValue); // Send with enable low
}
void LiquidCrystal_SR3W::loadSR(uint8_t value)
{
// Load the shift register with information
fio_shiftOut(_data_reg, _data, _clk_reg, _clk, value, MSBFIRST);
// Strobe the data into the latch
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
fio_digitalWrite_HIGH(_strobe_reg, _strobe);
fio_digitalWrite_SWITCHTO(_strobe_reg, _strobe, LOW);
}
}