LCD Library 1.3.0
LCD Library - LCD control class hierarchy library. Drop in replacement for the LiquidCrystal Library.
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