![]() |
LCD Library 1.3.0
LCD Library - LCD control class hierarchy library. Drop in replacement for the LiquidCrystal Library.
|
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 }