LiquidCrystal_SR1W.cpp
Go to the documentation of this file.

    00001 // ---------------------------------------------------------------------------
    00002 // Created/Adapted by Stephen Erisman 2013-07-06
    00003 // Copyright 2013 - Under creative commons license 3.0:
    00004 //        Attribution-ShareAlike CC BY-SA
    00005 //
    00006 // This software is furnished "as is", without technical support, and with no
    00007 // warranty, express or implied, as to its usefulness for any purpose.
    00008 //
    00009 // Thread Safe: No
    00010 // Extendable: Yes
    00011 //
    00012 // @file LiquidCrystal_SR1W.cpp
    00013 // Connects a hd44780 LCD using 1 pin from the Arduino, via an 8-bit Latching
    00014 // ShiftRegister (SR1W from now on).
    00015 //
    00016 // @brief
    00017 // This is an optimized implementation of the 1-wire shift concept developed by
    00018 // Roman Black (http://www.romanblack.com/shift1.htm) that also makes use of
    00019 // (and merges) the diode-resistor AND "gate" concept (http://www.rentron.com/Myke1.htm)
    00020 // as well as introducing some new and original ideas (particularly how HW_CLEAR works).
    00021 //
    00022 //
    00023 // See the corresponding SR1W header file for full details.
    00024 //
    00025 // History
    00026 // 2013.07.31 serisman - fixed potential interrupt bug and made more performance optimizations
    00027 // 2013.07.10 serisman - more performance optimizations and modified the HW_CLEAR circuit a bit
    00028 // 2013.07.09 serisman - added an even faster version that performs the clear in hardware
    00029 // 2013.07.08 serisman - changed code to shift data MSB first to match SR2W
    00030 // 2013.07.07 serisman - major speed optimization
    00031 // 2013.07.06 serisman - created/modified from SR2W and FastIO sources to create SR1W
    00032 // @author  S. Erisman - arduino@serisman.com
    00033 // ---------------------------------------------------------------------------
    00034
    00035 #include "LiquidCrystal_SR1W.h"
    00036
    00037 // CONSTRUCTORS
    00038 // ---------------------------------------------------------------------------
    00039 // Assuming 1 line 8 pixel high font
    00040 LiquidCrystal_SR1W::LiquidCrystal_SR1W (uint8_t srdata, t_sr1w_circuitType circuitType, t_backlighPol blpol)
    00041 {
    00042         init ( srdata, circuitType, blpol, 1, 0 );
    00043 }
    00044
    00045 // PRIVATE METHODS
    00046 // ---------------------------------------------------------------------------
    00047
    00048 //
    00049 // init
    00050 void LiquidCrystal_SR1W::init(uint8_t srdata, t_sr1w_circuitType circuitType, t_backlighPol blpol, uint8_t lines, uint8_t font)
    00051 {
    00052         _srRegister = fio_pinToOutputRegister(srdata);
    00053         _srMask = fio_pinToBit(srdata);
    00054
    00055         _circuitType = circuitType;
    00056
    00057         _blPolarity = blpol;
    00058
    00059         _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
    00060
    00061    clearSR();
    00062
    00063         backlight(); // set default backlight state to on
    00064 }
    00065
    00066 //
    00067 // clearSR
    00068 uint8_t LiquidCrystal_SR1W::clearSR()
    00069 {
    00070         uint8_t numDelays = 0;
    00071
    00072         // Store these as local variables for extra performance (and smaller compiled sketch size)
    00073         fio_register srRegister = _srRegister;
    00074         fio_bit srMask = _srMask;
    00075
    00076         // Set the Serial PIN to a LOW state
    00077         SR1W_ATOMIC_WRITE_LOW(srRegister, srMask);
    00078
    00079         // We need to delay to make sure the Data and Latch/EN capacitors are fully discharged
    00080         // This also triggers the EN pin because of the falling edge.
    00081         SR1W_DELAY();
    00082
    00083         ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    00084         {
    00085                 // Pre-calculate these values for extra performance and to make sure the clock pulse is as quick as possible
    00086                 fio_bit reg_val = *srRegister;
    00087                 fio_bit bit_low = reg_val & ~srMask;
    00088                 fio_bit bit_high = reg_val | srMask;
    00089
    00090                 // Clear the shift register (without triggering the Latch/EN pins)
    00091                 // We only need to shift 7 bits here because the subsequent HIGH transistion will also shift a '0' in.
    00092                 for (int8_t i = 6; i>=0; i--)
    00093                 {
    00094                         // Shift in a '0' (NOTE: This clock pulse needs to execute as quickly as possible)
    00095                         *srRegister = bit_high;
    00096                         *srRegister = bit_low;
    00097                 }
    00098
    00099                 // Set the Serial PIN to a HIGH state so the next nibble/byte can be loaded
    00100                 // This also shifts the 8th '0' bit in.
    00101                 *srRegister = bit_high;
    00102         }
    00103
    00104         // Give the Data capacitor a chance to fully charge
    00105         SR1W_DELAY();
    00106
    00107         return numDelays;
    00108 }
    00109
    00110 //
    00111 // loadSR
    00112 uint8_t LiquidCrystal_SR1W::loadSR(uint8_t val)
    00113 {
    00114         uint8_t numDelays = 0;
    00115
    00116         // Store these as local variables for extra performance (and smaller compiled sketch size)
    00117         fio_register srRegister = _srRegister;
    00118         fio_bit srMask = _srMask;
    00119
    00120         // NOTE: This assumes the Serial PIN is already HIGH and the Data capacitor is fully charged
    00121         uint8_t previousBit = 1;
    00122
    00123         // Send the data to the shift register (MSB first)
    00124         for (int8_t i = 7; i>=0; i--)
    00125         {
    00126                 if (val & 0x80)
    00127                 {
    00128                         if (previousBit == 0)
    00129                         {
    00130                                 // We need to make sure the Data capacitor has fully recharged
    00131                                 SR1W_DELAY();
    00132                         }
    00133
    00134                         previousBit = 1;
    00135
    00136                         ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    00137                         {
    00138                                 // Pre-calculate these values to make sure the clock pulse is as quick as possible
    00139                                 fio_bit reg_val = *srRegister;
    00140                                 fio_bit bit_low = reg_val & ~srMask;
    00141                                 fio_bit bit_high = reg_val | srMask;
    00142
    00143                                 // Shift in a '1' (NOTE: This clock pulse needs to execute as quickly as possible)
    00144                                 *srRegister = bit_low;
    00145                                 *srRegister = bit_high;
    00146                         }
    00147                 }
    00148                 else
    00149                 {
    00150                         // Shift in a '0'
    00151                         SR1W_ATOMIC_WRITE_LOW(srRegister, srMask);
    00152
    00153                         // We need to make sure the Data capacitor has fully discharged
    00154                         SR1W_DELAY();
    00155
    00156                         previousBit = 0;
    00157
    00158                         SR1W_ATOMIC_WRITE_HIGH(srRegister, srMask);
    00159                 }
    00160                 val <<= 1;
    00161         }
    00162
    00163         // NOTE: Serial PIN is currently HIGH
    00164
    00165         // For SW_CLEAR, we need to delay to make sure the Latch/EN capacitor is fully charged.
    00166         //   This triggers the Latch pin because of the rising edge.
    00167         // For HW_CLEAR, we need to delay to give the hardware time to perform the clear.
    00168         //   This also gives the Data capacitor a chance to fully charge
    00169         SR1W_DELAY();
    00170
    00171    if (_circuitType == SW_CLEAR)
    00172         {
    00173                 // Clear the shift register to get ready for the next nibble/byte
    00174                 // This also discharges the Latch/EN capacitor which finally triggers the EN pin because of the falling edge.
    00175                 numDelays += clearSR();
    00176    }
    00177         else
    00178         {
    00179                 // For some reason HW_CLEAR isn't totally stable unless we delay a little bit more.
    00180                 // TODO... figure this out...
    00181                 SR1W_DELAY();
    00182         }
    00183
    00184         return numDelays;
    00185 }
    00186
    00187 // PUBLIC METHODS
    00188 // ---------------------------------------------------------------------------
    00189
    00190
    00191 /************ low level data pushing commands **********/
    00192 //
    00193 // send
    00194 void LiquidCrystal_SR1W::send(uint8_t value, uint8_t mode)
    00195 {
    00196         uint8_t numDelays = 0;
    00197
    00198         uint8_t data;
    00199
    00200         if ( mode != FOUR_BITS )
    00201         {
    00202                 // upper nibble
    00203                 data = ( mode == DATA ) ? SR1W_RS_MASK : 0;
    00204                 data |= SR1W_EN_MASK | SR1W_UNUSED_MASK;
    00205                 data |= _blMask;
    00206
    00207                 if (value & _BV(4))     data |= SR1W_D4_MASK;
    00208                 if (value & _BV(5)) data |= SR1W_D5_MASK;
    00209                 if (value & _BV(6)) data |= SR1W_D6_MASK;
    00210                 if (value & _BV(7)) data |= SR1W_D7_MASK;
    00211
    00212                 numDelays += loadSR(data);
    00213         }
    00214
    00215         // lower nibble
    00216         data = ( mode == DATA ) ? SR1W_RS_MASK : 0;
    00217         data |= SR1W_EN_MASK | SR1W_UNUSED_MASK;
    00218         data |= _blMask;
    00219
    00220         if (value & _BV(0))     data |= SR1W_D4_MASK;
    00221         if (value & _BV(1)) data |= SR1W_D5_MASK;
    00222         if (value & _BV(2)) data |= SR1W_D6_MASK;
    00223         if (value & _BV(3)) data |= SR1W_D7_MASK;
    00224
    00225         numDelays += loadSR(data);
    00226
    00227         // Make sure we wait at least 40 uS between bytes.
    00228         unsigned int totalDelay = numDelays * SR1W_DELAY_US;
    00229         if (totalDelay < 40)
    00230                 delayMicroseconds(40 - totalDelay);
    00231 }
    00232
    00233 //
    00234 // setBacklight
    00235 void LiquidCrystal_SR1W::setBacklight ( uint8_t value )
    00236 {
    00237         // Check for polarity to configure mask accordingly
    00238         // ----------------------------------------------------------
    00239         if  ( ((_blPolarity == POSITIVE) && (value > 0)) ||
    00240         ((_blPolarity == NEGATIVE ) && ( value == 0 )) )
    00241         {
    00242                 _blMask = SR1W_BL_MASK;
    00243         }
    00244         else
    00245         {
    00246                 _blMask = 0;
    00247         }
    00248
    00249         // Send a dummy (non-existant) command to allow the backlight PIN to be latched.
    00250         // The seems to be safe because the LCD appears to treat this as a NOP.
    00251         send(0, COMMAND);
    00252 }

All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines