New LiquidCrystal library  1.5.0
Generic LCD control library
/Users/fmalpartida/Documents/development/mercurial repos/SW/NewLiquidCrystal_lib/LiquidCrystal_SR1W.h
1 // ---------------------------------------------------------------------------
2 // Created/Adapted by Stephen Erisman 2013-07-06
3 // Copyright (C) - 2018
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License v3.0
16 // along with this program.
17 // If not, see <https://www.gnu.org/licenses/gpl-3.0.en.html>.
18 //
19 // ---------------------------------------------------------------------------
20 //
21 // @file LiquidCrystal_SR1W.h
22 // Connects a hd44780 LCD using 1 pin from the Arduino, via an 8-bit Latching
23 // ShiftRegister (SR1W from now on).
24 //
25 // @brief
26 // This is the 1 wire shift register interface class for the LCD library
27 //
28 // The functionality provided by this class and its base class is a superset of
29 // the original functionality of the Arduino LiquidCrystal library and can
30 // be used as such.
31 // See the LCD class for a full description of the API functions available.
32 //
33 // It works with a 8-bit latched, no-tristate, unidirectional SIPO (Serial-In-Parallel-Out)
34 // shift register, and an hd44780 LCD in 4-bit mode.
35 // The 74HC595 shift register has been tested.
36 //
37 //
38 // 1 Pin required from the Arduino:
39 // - Serial PIN:
40 // The Serial PIN is wired directly to the shift register's Clock PIN and its
41 // unaltered signal directly triggers the Clock on every LOW to HIGH transition.
42 //
43 // Additionally, the Serial PIN is wired through a resistor capacitor (RC) filter to
44 // the shift register's Data PIN. During a quick transition of the Serial PIN the
45 // RC filter will maintain the Data PIN's previous value because the capacitor isn't
46 // given enough time to charge (or discharge) to the alternate state. If the transition
47 // is held for enough time, however, the RC capacitor will charge (or discharge) and the
48 // value seen by the Data PIN will have changed state.
49 //
50 // There are two circuit versions that behave differently for Latch, Enable, and Clear:
51 //
52 // HW_CLEAR version:
53 // In this version the shift register's Latch and LCD's Enable PINs are wired directly to
54 // the shift register's Q'H output. The shift register's /Clear PIN is then wired up
55 // through two logic "gates": first QH and Q'H are AND'd together with a diode-resistor
56 // "gate" the output of which is NAND'd with VCC using a resistor-NPN-resistor "gate".
57 // So, /CLR = ((QH AND Q'H) NAND VCC). We also put a capacitor on the NPN base to GND
58 // to delay the signal a bit and allow the Latch and EN signals some extra time to trigger.
59 //
60 // This all fits together as follows:
61 // 1. We shift in a '1'.
62 // 2. Ws shift in the other 7 bits.
63 // 3. At this point the first '1' has been shifted into Q'H causing it to go HIGH.
64 // 4. When Q'H is HIGH it causes Latch and EN to also go HIGH.
65 // 5. When Latch transitions to HIGH it changes the shift register outputs to the bits
66 // that were shifted in.
67 // 6. This causes QH to go HIGH (if it wasn't already).
68 // 7. Now that QH AND Q'H are both HIGH they causes the base capacitor to start charging.
69 // 8. When the capacitor has charged enough the transistor brings /CLR LOW.
70 // 8. This will cause /CLR to trigger and the shift register will be cleared
71 // (NOTE: This doesn't change the latched outputs)
72 // 9. The clearing of the shift register causes Q'H to go LOW.
73 // 9. When Q'H is LOW it causes Latch and EN to also go LOW.
74 // 10. When EN transitions to LOW the LCD reads in the bits on the shift register pins
75 // and does it's thing.
76 // 11. Now that Q'H is LOW the base capacitor starts discharging.
77 // 12. When the capacitor has discharged enough the transistor will stop sinking /CLR.
78 // 13. This will cause /CLR to be pulled back up to HIGH by the VCC pullup resistor
79 // (it will stay that way until our next nibble/byte has been shifted in)
80 // 14. We are now ready for our next nibble/byte.
81 //
82 //
83 // SW_CLEAR version:
84 // In this version the Serial PIN is wired to the shift register's Latch and LCD's Enable
85 // PINs through another RC filter. These PINs are also wired through a diode (AND "gate")
86 // tied to the shift register's Q'H output. This combination means that the Latch and
87 // Enable PINs will be held LOW as long as EITHER the Q'H or RC output is LOW.
88 //
89 // This all fits together as follows:
90 // 1. We shift in a '1'.
91 // 2. We shift in the other 7 bits. (NOTE: We leave Serial PIN HIGH at the end of this)
92 // 3. At this point the first '1' has been shifted into Q'H causing it to go HIGH.
93 // (NOTE: Up until this time Q'H has been LOW so the attached diode has been keeping
94 // the Latch/EN pins LOW.)
95 // 4. Now that Q'H is HIGH it causes the attached diode to stop discharging the Latch/EN
96 // capacitor. We delay here for a while to make sure it is fully charged.
97 // 5. When the capacitor has charged enough Latch/EN will be HIGH
98 // 5. When Latch transitions to HIGH it changes the shift register outputs to what was
99 // shifted in.
100 // 6. We now bring the Serial PIN LOW and wait for the Latch/EN capacitor to discharge.
101 // 7. When the capacitor has discharged enough Latch/EN will be LOW
102 // 8. When EN transitions to LOW the LCD reads in the bits on the shift register pins
103 // and does it's thing.
104 // 9. We now shift in '0' 8 times (as quickly as possible).
105 // 10. If we keep the LOW to HIGH to LOW pulses short enough while shifting in the '0's
106 // the Latch/EN capacitor won't have time to charge to a point where it will re-trigger
107 // the Latch/EN pins.
108 // 11. Now Q'H will be LOW and the shift register has been cleared (NOTE: This doesn't
109 // change the latched outputs.)
110 // 12. We now bring the Serial PIN HIGH again and wait for the Data capacitor to recharge.
111 // 13. When the Data capacitor has fully charged we are ready for our next nibble/byte.
112 //
113 //
114 // These designs incorporate (and merge) ideas originally found here (1-wire concept):
115 // http://www.romanblack.com/shift1.htm
116 // and here (diode-resistor AND "gate" EN control):
117 // http://www.rentron.com/Myke1.htm
118 // as well as introducing some new and original ideas (particularly how HW_CLEAR works).
119 //
120 // Because of its use of the diode AND "gate", the SW_CLEAR design allows for faster sending
121 // of data to the LCD compared to Roman's original design. With the proposed 5uS delay (see
122 // notes below), a byte can be sent to the LCD in as little as 30 uS (plus overhead) when
123 // sending all 1's. This increases to as much as 190 uS (plus overhead) when sending all 0's.
124 // This is in comparison to Roman's estimate of around 3-4 mS to send a byte. So this
125 // implementation is 15-133 times faster for the cost of a single (1N4148 or similar) diode.
126 //
127 // The HW_CLEAR version is even faster as it can completely eliminate the clearSR() call as
128 // well as the delays that are needed to latch the data in the SW_CLEAR version.
129 //
130 //
131 // Default Shift Register Bits - Shifted MSB first:
132 // Bit #0 (QA) - not used
133 // Bit #1 (QB) - connects to LCD data input D7
134 // Bit #2 (QC) - connects to LCD data input D6
135 // Bit #3 (QD) - connects to LCD data input D5
136 // Bit #4 (QE) - connects to LCD data input D4
137 // Bit #5 (QF) - optional backlight control
138 // Bit #6 (QG) - connects to RS (Register Select) on the LCD
139 // Bit #7 (QH) - used for /CLR on the HW_CLEAR version (cannot be changed)
140 // (Q'H) - used for Latch/EN (via the diode AND "gate") (cannot be changed)
141 //
142 // NOTE: Any of these can be changed around as needed EXCEPT Bit #7 (QH and Q'H).
143 //
144 //
145 // Circuit Types (for the 74HC595)
146 // -------------------------------
147 // The 74HC595 is a latching shift register. See the explanations above for how these circuits
148 // work.
149 //
150 //
151 // HW_CLEAR version: (Faster but higher part count)
152 // ------------------------------------------------
153 //
154 // 74HC595 (VCC)
155 // +----u----+ | 2.2nF
156 // (LCD D7)------------1-|QB VCC|-16--+ +----||----(GND)
157 // (LCD D6)------------2-|QC QA|-15 |
158 // (LCD D5)------------3-|QD SER|-14-------+--[ Resistor ]--+
159 // (LCD D4)------------4-|QE /OE|-13--(GND) 1.5k |
160 // (BL Circuit)--------5-|QF RCK|-12-----+ |
161 // | | \ |
162 // (LCD RS)------------6-|QG SCK|-11-------)----------------+--(Serial PIN)
163 // | | |
164 // +-------7-|QH /CLR|-10-------)--+--[ Resistor ]--(VCC)
165 // | | | / | 1k
166 // | +--8-|GND Q'H|--9-----+ |
167 // | | +---------+ | | (GND)--(LCD RW)
168 // | | 0.1uF | \
169 // | (GND)-----||----(VCC) +------)--------------(LCD EN)
170 // | | /
171 // |----|<|----+--[ Resistor ]--| |
172 // diode | 1k C
173 // | |
174 // +-------------+---B-|> (NPN)
175 // | |
176 // (2.2nF) = E
177 // | |
178 // (GND) (GND)
179 //
180 //
181 // SW_CLEAR version: (Lower part count but slower)
182 // -----------------------------------------------
183 //
184 // 74HC595 (VCC)
185 // +----u----+ | 2.2nF
186 // (LCD D7)------------1-|QB VCC|-16--+ +----||----(GND)
187 // (LCD D6)------------2-|QC QA|-15 |
188 // (LCD D5)------------3-|QD SER|-14---------+--[ Resistor ]--+
189 // (LCD D4)------------4-|QE /OE|-13--(GND) 1.5k |
190 // (BL Circuit)--------5-|QF RCK|-12---------+ |
191 // | | \ |
192 // (LCD RS)------------6-|QG SCK|-11-----------)--------------+--(Serial PIN)
193 // 7-|QH /CLR|-10--(VCC) / |
194 // +--8-|GND Q'H|--9---|<|---+--[ Resistor ]--+
195 // | +---------+ diode | 1.5k
196 // | |
197 // | 0.1uF |
198 // (GND)-----||----(VCC) +----||----(GND)
199 // | 2.2nF
200 // (LCD EN)-------------------------------------+
201 // (LCD RW)--(GND)
202 //
203 //
204 // In either case the LCD RW pin is hardwired to GND meaning we will only be able to write
205 // to the LCD.
206 // Therefore, the Busy Flag (BF, data bit D7) is not able to be read and we have to make use
207 // of the minimum delay time constraints. This isn't really a problem because it usually
208 // takes us longer to shift and latch the data than the minimum delay anyway. For now, we
209 // simply keep track of our delays and add more delay at the end to get to at least 37 uS.
210 //
211 //
212 // Backlight Control Circuit
213 // -------------------------
214 // Since we are using the latching nature of the shift resiter we don't need the extra
215 // backlight circuitry that SR2W uses. Keeping it around, however, would still work because
216 // the circuit just slows down the transitions to the mosfet a bit.
217 //
218 // Here are two more optimized versions that can be used.
219 //
220 //
221 // NPN Transistor version: (Cheaper but more power draw and higher part count)
222 // ---------------------------------------------------------------------------
223 //
224 // (value depends on LCD, 100ohm is usually safe)
225 // (LCD BL anode)---[ resistor ]---(VCC)
226 //
227 // (LCD BL cathode)---------------+
228 // |
229 // C
230 // |
231 // (BL input)--[ Resistor ]---B-|> (NPN)
232 // 1k |
233 // E
234 // |
235 // (GND)
236 //
237 // NOTE: The Bate resistor is needed because the NPN is current fed. For lower
238 // power draw, try a 10k resistor.
239 //
240 //
241 // N-CH Mosfet version: (More costly but less power draw and lower part count)
242 // ---------------------------------------------------------------------------
243 //
244 // (value depends on LCD, 100ohm is usually safe)
245 // (LCD BL anode)---[ resistor ]---(VCC)
246 //
247 // (LCD BL cathode)---------------+
248 // |
249 // D
250 // |
251 // (BL input)----------------G-|-< (2N7000 FET)
252 // |
253 // S
254 // |
255 // (GND)
256 //
257 // NOTE: Gate resistor not needed because the mosfet is voltage fed and only really
258 // pulls current while switching.
259 //
260 // In either case, when the BL input is HIGH the LCD backlight will turn on.
261 //
262 //
263 // History
264 // 2013.07.31 serisman - fixed potential interrupt bug and made more performance optimizations
265 // 2013.07.10 serisman - more performance optimizations and modified the HW_CLEAR circuit a bit
266 // 2013.07.09 serisman - added an even faster version that performs the clear in hardware
267 // 2013.07.08 serisman - changed code to shift data MSB first to match SR2W
268 // 2013.07.07 serisman - major speed optimization
269 // 2013.07.06 serisman - created/modified from SR2W source to create SR1W
270 // @author S. Erisman - arduino@serisman.com
271 // --------------------------------------------------------------------------------
272 
273 #ifndef _LIQUIDCRYSTAL_SR1W_
274 #define _LIQUIDCRYSTAL_SR1W_
275 
276 #if defined (__AVR__)
277 
278 #include <inttypes.h>
279 #include "LCD.h"
280 #include "FastIO.h"
281 
282 // 1-wire SR timing constants
283 // ---------------------------------------------------------------------------
284 
285 // NOTE:
286 // The 1.5k resistor (1.2k - 1.8k with a 20% tolerance)
287 // takes between 2.376uS and 4.36uS to fully charge or discharge
288 // the 2.2n capacitor (1.98n - 2.42n with a 10% tolerance).
289 // We round this up to a 5uS delay to provide an additional safety margin.
290 
291 #define SR1W_DELAY_US 5
292 #define SR1W_DELAY() { delayMicroseconds(SR1W_DELAY_US); numDelays++; }
293 
294 // 1-wire SR output bit constants
295 // ---------------------------------------------------------------------------
296 
297 #define SR1W_UNUSED_MASK 0x01 // Set unused bit(s) to '1' as they are slightly faster to clock in.
298 #define SR1W_D7_MASK 0x02
299 #define SR1W_D6_MASK 0x04
300 #define SR1W_D5_MASK 0x08
301 #define SR1W_D4_MASK 0x10
302 #define SR1W_BL_MASK 0x20
303 #define SR1W_RS_MASK 0x40
304 #define SR1W_EN_MASK 0x80 // This cannot be changed. It has to be the first thing shifted in.
305 
306 #define SR1W_ATOMIC_WRITE_LOW(reg, mask) ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { *reg &= ~mask; }
307 #define SR1W_ATOMIC_WRITE_HIGH(reg, mask) ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { *reg |= mask; }
308 
309 
310 typedef enum { SW_CLEAR, HW_CLEAR } t_sr1w_circuitType;
311 
312 class LiquidCrystal_SR1W : public LCD
313 {
314 public:
326  LiquidCrystal_SR1W (uint8_t srdata, t_sr1w_circuitType circuitType,
327  t_backlightPol blpol = POSITIVE);
328 
341  virtual void send(uint8_t value, uint8_t mode);
342 
343 
353  void setBacklight ( uint8_t mode );
354 
355 private:
356 
362  void init ( uint8_t srdata, t_sr1w_circuitType circuitType, t_backlightPol blpol,
363  uint8_t lines, uint8_t font );
364 
370  uint8_t clearSR ();
371 
376  uint8_t loadSR (uint8_t val);
377 
378  fio_register _srRegister; // Serial PIN
379  fio_bit _srMask;
380 
381  t_sr1w_circuitType _circuitType;
382 
383  uint8_t _blPolarity;
384  uint8_t _blMask;
385 };
386 
387 #else
388 #error "ONLY SUPPORTED ON AVR PROCESSORS"
389 #endif // defined (__AVR__)
390 
391 #endif
Definition: LCD.h:199
virtual void setBacklight(uint8_t value)
Definition: LCD.h:517