closes #13 - rename private variable for LCD bit-mask pin.

closes #15 - comments added to header files and method descriptions.
closes #16 - added critical sections to fastIOs and associated usage on the LiquidCrystal_SR class.
ref #14 - partially closed pending review.
This commit is contained in:
FMC
2012-03-04 13:24:46 +01:00
parent 6b73f540e6
commit 9f4e1553a5
9 changed files with 227 additions and 161 deletions
+82 -66
View File
@@ -27,7 +27,7 @@
// (https://github.com/chipKIT32/chipKIT32-MAX/blob/master/hardware/pic32/
// cores/pic32/wiring_digital.c)
// ---------------------------------------------------------------------------
#include <util/atomic.h> // for critical section management
#include "FastIO.h"
fio_register fio_pinToOutputRegister(uint8_t pin, uint8_t initial_state)
@@ -73,14 +73,17 @@ void fio_digitalWrite(fio_register pinRegister, uint8_t pinBit, uint8_t value)
#ifdef FIO_FALLBACK
digitalWrite(pinBit, value);
#else
if(value == LOW)
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
fio_digitalWrite_LOW(pinRegister,pinBit);
}
else
{
fio_digitalWrite_HIGH(pinRegister,pinBit);
}
if(value == LOW)
{
fio_digitalWrite_LOW(pinRegister,pinBit);
}
else
{
fio_digitalWrite_HIGH(pinRegister,pinBit);
}
}
#endif
}
@@ -97,42 +100,47 @@ int fio_digitalRead(fio_register pinRegister, uint8_t pinBit)
#endif
}
void fio_shiftOut ( fio_register dataRegister, fio_bit dataBit, fio_register clockRegister,
fio_bit clockBit, uint8_t value, uint8_t bitOrder)
void fio_shiftOut ( fio_register dataRegister, fio_bit dataBit,
fio_register clockRegister, fio_bit clockBit,
uint8_t value, uint8_t bitOrder)
{
// # disable interrupts
// uint8_t oldSREG = SREG;
// cli();
int8_t i;
for(i = 0; i < 8; i++)
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
if (bitOrder == LSBFIRST)
for(i = 0; i < 8; i++)
{
fio_digitalWrite(dataRegister, dataBit, !!(value & (1 << i)));
}
else
{
fio_digitalWrite(dataRegister, dataBit, !!(value & (1 << (7 - i))));
}
fio_digitalWrite_HIGH (clockRegister, clockBit);
// Switching is a little bit faster
fio_digitalWrite_SWITCH (clockRegister,clockBit);
}
// # enable interrupts
// SREG = oldSREG;
if (bitOrder == LSBFIRST)
{
fio_digitalWrite(dataRegister, dataBit, !!(value & (1 << i)));
}
else
{
fio_digitalWrite(dataRegister, dataBit, !!(value & (1 << (7 - i))));
}
fio_digitalWrite_HIGH (clockRegister, clockBit);
// Switching is a little bit faster
fio_digitalWrite_SWITCH (clockRegister,clockBit);
}
} // end critical section
}
void fio_shiftOut(fio_register dataRegister, uint8_t dataBit, fio_register clockRegister, uint8_t clockBit)
void fio_shiftOut(fio_register dataRegister, uint8_t dataBit,
fio_register clockRegister, uint8_t clockBit)
{
// shift out 0x0 (B00000000) fast, byte order is irrelevant
fio_digitalWrite_LOW (dataRegister, dataBit);
for(uint8_t i = 0; i<8; ++i)
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
fio_digitalWrite_HIGH (clockRegister, clockBit);
fio_digitalWrite_SWITCH (clockRegister, clockBit);
}
// shift out 0x0 (B00000000) fast, byte order is irrelevant
fio_digitalWrite_LOW (dataRegister, dataBit);
for(uint8_t i = 0; i<8; ++i)
{
fio_digitalWrite_HIGH (clockRegister, clockBit);
fio_digitalWrite_SWITCH (clockRegister, clockBit);
}
}
}
void fio_shiftOut1_init(uint8_t pin)
{
@@ -146,10 +154,12 @@ void fio_shiftOut1_init(fio_register shift1Register, fio_bit shift1Bit)
fio_digitalWrite(shift1Register,shift1Bit,HIGH);
delayMicroseconds(300);
}
void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value, boolean noLatch)
void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value,
boolean noLatch)
{
/*
* this function are based on Shif1 protocol developed by Roman Black (http://www.romanblack.com/shift1.htm)
* this function are based on Shif1 protocol developed by Roman Black
* (http://www.romanblack.com/shift1.htm)
*
* test sketches:
* http://pastebin.com/raw.php?i=2hnC9v2Z
@@ -161,34 +171,37 @@ void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value
* arduino-one-wire-shift-register-prototype)
* 7HC595N
*/
// disable interrupts since timing is going to be critical
uint8_t oldSREG;
oldSREG = SREG;
cli();
// iterate but ignore last bit (is it correct now?)
for(int8_t i = 7; i>=0; --i)
{
// assume that pin is HIGH (smokin' pot all day... :) - requires initialization
if(LOW==!!(value & (1 << i)))
// assume that pin is HIGH (smokin' pot all day... :) - requires
// initialization
if(value & _BV(i))
{
// LOW = 0 Bit
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
// hold pin LOW for 15us
delayMicroseconds(15);
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH);
// hold pin HIGH for 30us
delayMicroseconds(30);
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
// HIGH = 1 Bit
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
//hold pin LOW for 1us - done! :)
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH);
//hold pin HIGH for 15us
} // end critical section
delayMicroseconds(15);
}
else
{
// HIGH = 1 Bit
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
//hold pin LOW for 1us - done! :)
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH);
//hold pin HIGH for 15us
delayMicroseconds(15);
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
// LOW = 0 Bit
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
// hold pin LOW for 15us
delayMicroseconds(15);
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH);
} // end critical section
// hold pin HIGH for 30us
delayMicroseconds(30);
}
if(!noLatch && i==1)
{
@@ -198,19 +211,22 @@ void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value
if(!noLatch)
{
// send last bit (=LOW) and Latch command
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
// Hold pin low for 200us
delayMicroseconds(199);
fio_digitalWrite_HIGH(shift1Register,shift1Bit);
// Hold pin high for 300us and leave it that way - using explicit HIGH here, just in case.
delayMicroseconds(299);
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
// send last bit (=LOW) and Latch command
fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
} // end critical section
delayMicroseconds(199); // Hold pin low for 200us
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
fio_digitalWrite_HIGH(shift1Register,shift1Bit);
} // end critical section
delayMicroseconds(299); // Hold pin high for 300us and leave it that
// way - using explicit HIGH here, just in case.
}
// enable interrupts
SREG = oldSREG;
}
void fio_shiftOut1(uint8_t pin, uint8_t value, boolean noLatch)
{
fio_shiftOut1(fio_pinToOutputRegister(pin, SKIP),fio_pinToBit(pin),value, noLatch);
+4 -1
View File
@@ -40,6 +40,7 @@
#include <inttypes.h>
#include <util/delay.h>
/*!
@defined
@abstract Enables IO digitalRead/digitalWrite fall back for non-AVR
@@ -47,6 +48,8 @@
*/
#ifndef __AVR__
#define FIO_FALLBACK
#define ATOMIC_BLOCK
#define ATOMIC_RESTORESTATE
#endif
// PUBLIC CONSTANTS DEFINITIONS
@@ -64,7 +67,7 @@ typedef uint8_t fio_bit;
#ifndef FIO_FALLBACK
typedef volatile uint8_t * fio_register;
typedef volatile uint8_t *fio_register;
#else
// remove volatile to give optimizer a chance
typedef uint8_t fio_register;
+11 -1
View File
@@ -93,7 +93,7 @@ void LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize)
// before sending commands. Arduino can turn on way before 4.5V so we'll wait
// 50
// ---------------------------------------------------------------------------
delayMicroseconds(100000);
delay (100); // 100ms delay
//put the LCD into 4 bit or 8 bit mode
// -------------------------------------
@@ -293,6 +293,16 @@ void LCD::createChar(uint8_t location, uint8_t charmap[])
}
}
void LCD::backlight ( void )
{
setBacklight(255);
}
void LCD::noBacklight ( void )
{
setBacklight(0);
}
// General LCD commands - generic methods used by the rest of the commands
// ---------------------------------------------------------------------------
void LCD::command(uint8_t value)
+42 -17
View File
@@ -26,6 +26,9 @@
// it has been extended to drive 4 and 8 bit mode control, LCDs and I2C extension
// backpacks such as the I2CLCDextraIO using the PCF8574* I2C IO Expander ASIC.
//
// The functionality provided by this class and its base class is identical
// to the original functionality of the Arduino LiquidCrystal library.
//
// @version API 1.1.0
//
//
@@ -156,9 +159,9 @@ public:
initializes the LCD, therefore, it MUST be called prior to using any other
method from this class.
This method is pure abstract, it is dependent on each derived class from
this base class to implement the internals of how the LCD is initialized
and configured.
This method is abstract, a base implementation is available common to all LCD
drivers. Should it not be compatible with some other LCD driver, a derived
implementation should be done on the driver specif class.
@param cols[in] the number of columns that the display has
@param rows[in] the number of rows that the display has
@@ -379,19 +382,6 @@ public:
//
// virtual class methods
// --------------------------------------------------------------------------
/*!
@function
@abstract Switch-on/off the LCD backlight.
@discussion Switch-on/off the LCD backlight.
The setBacklightPin has to be called before setting the backlight for
this method to work. @see setBacklightPin. This method is device dependent
and can be programmed on each subclass. An empty function call is provided
that does nothing.
@param mode: backlight mode (HIGH|LOW)
*/
virtual void setBacklight ( uint8_t mode ) { };
/*!
@function
@abstract Sets the pin to control the backlight.
@@ -401,7 +391,42 @@ public:
@param mode: backlight mode (HIGH|LOW)
*/
virtual void setBacklightPin ( uint8_t pin ) { };
virtual void setBacklightPin ( uint8_t value ) { };
/*!
@function
@abstract Sets the pin to control the backlight.
@discussion Sets the pin in the device to control the backlight. The behaviour
of this method is very dependent on the device. Some controllers support
dimming some don't. Please read the actual header file for each individual
device. The setBacklightPin method has to be called before setting the backlight.
@see setBacklightPin.
NOTE: The prefered methods to control the backlight are "backlight" and
"noBacklight".
@param 0..255 - the value is very dependent on the LCD, however, 0
will be interpreted as off.
*/
virtual void setBacklight ( uint8_t value ) { };
/*!
@function
@abstract Switch-on the LCD backlight.
@discussion Switch-on the LCD backlight.
The setBacklightPin has to be called before setting the backlight for
this method to work. @see setBacklightPin.
*/
void backlight ( void );
/*!
@function
@abstract Switch-off the LCD backlight.
@discussion Switch-off the LCD backlight.
The setBacklightPin has to be called before setting the backlight for
this method to work. @see setBacklightPin.
*/
void noBacklight ( void );
/*!
@function
+10 -10
View File
@@ -104,16 +104,6 @@ void LiquidCrystal::send(uint8_t value, uint8_t mode)
waitUsec ( EXEC_TIME ); // wait for the command to execute by the LCD
}
//
// setBackligh
void LiquidCrystal::setBacklight ( uint8_t mode )
{
if ( _backlightPin != LCD_NOBACKLIGHT )
{
digitalWrite ( _backlightPin, mode );
}
}
//
// setBacklightPin
void LiquidCrystal::setBacklightPin ( uint8_t pin )
@@ -122,6 +112,16 @@ void LiquidCrystal::setBacklightPin ( uint8_t pin )
_backlightPin = pin;
}
//
// setBackligh
void LiquidCrystal::setBacklight ( uint8_t value )
{
if ( _backlightPin != LCD_NOBACKLIGHT )
{
analogWrite ( _backlightPin, value );
}
}
// PRIVATE METHODS
// ---------------------------------------------------------------------------
+18 -15
View File
@@ -20,8 +20,6 @@
// on the Hitachi HD44780 and compatible chipsets using the parallel port of
// the LCD (4 bit and 8 bit).
//
// The functionality provided by this class and its base class is identical
// to the original functionality of the Arduino LiquidCrystal library.
//
//
// @author F. Malpartida - fmalpartida@gmail.com
@@ -84,26 +82,31 @@ public:
*/
virtual void send(uint8_t value, uint8_t mode);
/*!
@function
@abstract Switch-on/off the LCD backlight.
@discussion Switch-on/off the LCD backlight.
The setBacklightPin has to be called before setting the backlight for
this method to work. @see setBacklightPin.
@param mode: backlight mode (HIGH|LOW)
*/
void setBacklight ( uint8_t mode );
/*!
@function
@abstract Sets the pin to control the backlight.
@discussion Sets the pin in the device to control the backlight.
@param mode: backlight mode (HIGH|LOW)
@param pin: pin assigned to the backlight
*/
void setBacklightPin ( uint8_t pin );
/*!
@function
@abstract Switch-on/off the LCD backlight.
@discussion Switch-on/off the LCD backlight.
The setBacklightPin has to be called before setting the backlight for
this method to work. @see setBacklightPin. For dimming control of the
backlight, the configuration pin must be a PWM output pin. Dim control
is achieved by passing a value from 1 to 255 as a parameter. If the
pin configured when calling the setBacklightPin does not support PWM,
then: (0..127) backlight off, (128..255) backlight on.
@param value: backlight value. 0: off, 1..255: dim control of the
backlight. For negative logic 255: off, 254..0: dim control.
For non PWM pins: 0..127 - backligh off, 128..255 - backlight on.
*/
void setBacklight ( uint8_t value );
private:
+25 -24
View File
@@ -50,8 +50,8 @@ LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr )
{
_Addr = lcd_Addr;
_backlightPin = 0x0;
_backlightMask = LCD_NOBACKLIGHT;
_backlightPinMask = 0x0;
_backlightStsMask = LCD_NOBACKLIGHT;
_En = EN;
_Rw = RW;
@@ -69,8 +69,8 @@ LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
{
_Addr = lcd_Addr;
_backlightPin = 0;
_backlightMask = LCD_NOBACKLIGHT;
_backlightPinMask = 0;
_backlightStsMask = LCD_NOBACKLIGHT;
_En = ( 1 << En );
_Rw = ( 1 << Rw );
@@ -89,8 +89,8 @@ LiquidCrystal_I2C::LiquidCrystal_I2C( uint8_t lcd_Addr, uint8_t En, uint8_t Rw,
{
_Addr = lcd_Addr;
_backlightPin = 0;
_backlightMask = LCD_NOBACKLIGHT;
_backlightPinMask = 0;
_backlightStsMask = LCD_NOBACKLIGHT;
_En = ( 1 << En );
_Rw = ( 1 << Rw );
@@ -118,31 +118,32 @@ void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize)
// User commands - users can expand this section
//----------------------------------------------------------------------------
// Turn the (optional) backlight off/on
//
// setBacklight
void LiquidCrystal_I2C::setBacklight( uint8_t mode )
{
if ( mode == HIGH )
{
_backlightMask = _backlightPin & LCD_BACKLIGHT;
}
else
{
_backlightMask = _backlightPin & LCD_NOBACKLIGHT;
}
_i2cio.write( _backlightMask );
}
//
// setBacklightPin
void LiquidCrystal_I2C::setBacklightPin ( uint8_t pin )
{
_backlightPin = ( 1 << pin );
_backlightPinMask = ( 1 << pin );
}
//
// setBacklight
void LiquidCrystal_I2C::setBacklight( uint8_t value )
{
if ( value > 0 )
{
_backlightStsMask = _backlightPinMask & LCD_BACKLIGHT;
}
else
{
_backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT;
}
_i2cio.write( _backlightStsMask );
}
// PRIVATE METHODS
// ---------------------------------------------------------------------------
@@ -203,7 +204,7 @@ void LiquidCrystal_I2C::write4bits ( uint8_t value, uint8_t mode )
mode = _Rs;
}
pinMapValue |= mode | _backlightMask;
pinMapValue |= mode | _backlightStsMask;
_i2cio.write ( pinMapValue );
pulseEnable ( pinMapValue );
}
+12 -12
View File
@@ -140,6 +140,16 @@ public:
*/
virtual void send(uint8_t value, uint8_t mode);
/*!
@function
@abstract Sets the pin to control the backlight.
@discussion Sets the pin in the device to control the backlight. This device
doesn't support dimming backlight capability.
@param 0: backlight off, 1..255: backlight on.
*/
void setBacklightPin ( uint8_t value );
/*!
@function
@abstract Switch-on/off the LCD backlight.
@@ -151,16 +161,6 @@ public:
*/
void setBacklight ( uint8_t mode );
/*!
@function
@abstract Sets the pin to control the backlight.
@discussion Sets the pin in the device to control the backlight.
@param mode: backlight mode (HIGH|LOW)
*/
void setBacklightPin ( uint8_t pin );
private:
/*!
@@ -190,8 +190,8 @@ private:
uint8_t _Addr; // I2C Address of the IO expander
uint8_t _backlightPin; // Backlight IO pin
uint8_t _backlightMask; // Backlight status mask
uint8_t _backlightPinMask; // Backlight IO pin mask
uint8_t _backlightStsMask; // Backlight status mask
I2CIO _i2cio; // I2CIO PCF8574* expansion module driver I2CLCDextraIO
uint8_t _En; // LCD expander word for enable pin
uint8_t _Rw; // LCD expander word for R/W pin
+23 -15
View File
@@ -75,6 +75,7 @@
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <util/atomic.h> // for critical section management
#if (ARDUINO < 100)
#include <WProgram.h>
@@ -89,8 +90,8 @@
// CONSTRUCTORS
// ---------------------------------------------------------------------------
// Assuming 1 line 8 pixel high font
LiquidCrystal_SR::LiquidCrystal_SR ( uint8_t srdata, uint8_t srclock,
uint8_t enable )
LiquidCrystal_SR::LiquidCrystal_SR (uint8_t srdata, uint8_t srclock,
uint8_t enable )
{
init ( srdata, srclock, enable, 1, 0 );
}
@@ -101,16 +102,17 @@ LiquidCrystal_SR::LiquidCrystal_SR ( uint8_t srdata, uint8_t srclock,
//
// init
void LiquidCrystal_SR::init(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, uint8_t font)
void LiquidCrystal_SR::init(uint8_t srdata, uint8_t srclock, uint8_t enable,
uint8_t lines, uint8_t font)
{
// Initialise private variables
_two_wire = 0;
_srDataRegister = fio_pinToOutputRegister(srdata);
_srDataBit = fio_pinToBit(srdata);
_srClockRegister = fio_pinToOutputRegister(srclock);
_srClockBit = fio_pinToBit(srclock);
if (enable == TWO_WIRE)
{
_two_wire = 1;
@@ -122,13 +124,14 @@ void LiquidCrystal_SR::init(uint8_t srdata, uint8_t srclock, uint8_t enable, uin
_srEnableRegister = fio_pinToOutputRegister(enable);
_srEnableBit = fio_pinToBit(enable);
}
// Configure control pins as outputs
// ------------------------------------------------------------------------
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x10DOTS;
}
//
// shiftIt
void LiquidCrystal_SR::shiftIt(uint8_t val)
{
@@ -138,7 +141,7 @@ void LiquidCrystal_SR::shiftIt(uint8_t val)
fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit);
}
fio_shiftOut(_srDataRegister, _srDataBit, _srClockRegister, _srClockBit, val, MSBFIRST);
// LCD ENABLE PULSE
//
// While this library is written with a shift register without an output
@@ -146,9 +149,12 @@ void LiquidCrystal_SR::shiftIt(uint8_t val)
// latch. The shiftregister latch pin (STR, RCL or similar) is then
// connected to the LCD enable pin. The LCD is (very likely) slower
// to read the Enable pulse, and then reads the new contents of the SR.
fio_digitalWrite_HIGH(_srEnableRegister, _srEnableBit);
waitUsec (1); // enable pulse must be >450ns
fio_digitalWrite_SWITCHTO(_srEnableRegister, _srEnableBit, LOW);
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
fio_digitalWrite_HIGH(_srEnableRegister, _srEnableBit);
waitUsec (1); // enable pulse must be >450ns
fio_digitalWrite_SWITCHTO(_srEnableRegister, _srEnableBit, LOW);
} // end critical section
waitUsec ( 37 ); // commands need > 37us to settle
}
@@ -157,7 +163,7 @@ void LiquidCrystal_SR::shiftIt(uint8_t val)
/************ low level data pushing commands **********/
//
// send
void LiquidCrystal_SR::send(uint8_t value, uint8_t mode)
{
@@ -168,11 +174,13 @@ void LiquidCrystal_SR::send(uint8_t value, uint8_t mode)
shiftIt(mode | SR_EN_BIT | ((value << 3) & 0x78)); // lower nibble
}
//
// setBacklightPin
void LiquidCrystal_SR::setBacklightPin ( uint8_t pin )
{ }
//
// setBacklight
void LiquidCrystal_SR::setBacklight ( uint8_t mode )
{ }
void LiquidCrystal_SR::setBacklightPin ( uint8_t pin )
{ }