-
Notifications
You must be signed in to change notification settings - Fork 0
/
LiquidCrystal_SR3W.cpp
283 lines (244 loc) · 9.01 KB
/
LiquidCrystal_SR3W.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
// ---------------------------------------------------------------------------
// Created by Francisco Malpartida on 7.3.2012.
// Copyright 2011 - Under creative commons license 3.0:
// Attribution-ShareAlike CC BY-SA
//
// This software is furnished "as is", without technical support, and with no
// warranty, express or implied, as to its usefulness for any purpose.
//
// Thread Safe: No
// Extendable: Yes
//
// @file LiquidCrystal_SRG.h
// This file implements a basic liquid crystal library that comes as standard
// in the Arduino SDK but using a generic SHIFT REGISTER extension board.
//
// @brief
// This is a basic implementation of the LiquidCrystal library of the
// Arduino SDK. The original library has been reworked in such a way that
// this class implements the all methods to command an LCD based
// on the Hitachi HD44780 and compatible chipsets using a 3 wire latching
// shift register. While it has been tested with a 74HC595N shift register
// it should also work with other latching shift registers such as the MC14094
// and the HEF4094
//
// This particular driver has been created as generic as possible to enable
// users to configure and connect their LCDs using just 3 digital IOs from the
// AVR or Arduino, and connect the LCD to the outputs of the shiftregister
// in any configuration. The library is configured by passing the IO pins
// that control the strobe, data and clock of the shift register and a map
// of how the shiftregister is connected to the LCD.
//
//
// +--------------------------------------------+
// | MCU |
// | IO1 IO2 IO3 |
// +----+-------------+-------------+-----------+
// | | |
// | | |
// +----+-------------+-------------+-----------+
// | Strobe Data Clock |
// | 8-bit shift/latch register | 74HC595N
// | Qa0 Qb1 Qc2 Qd3 Qe4 Qf5 Qg6 Qh7 |
// +----+----+----+----+----+----+----+----+----+
// | | | | | | |
// |11 |12 |13 |14 |6 |5 |4 (LCD pins)
// +----+----+----+----+----+----+----+----+----+
// | DB4 DB5 DB6 DB7 E Rw RS |
// | LCD Module |
//
// NOTE: Rw is not used by the driver so it can be connected to GND.
//
// The functionality provided by this class and its base class is identical
// to the original functionality of the Arduino LiquidCrystal library.
//
//
// History
// 2012.03.29 bperrybap - fixed constructors not properly using Rs
// Fixed incorrect use of 5x10 for default font
// - now matches original LQ library.
// moved delay to send() so it is per cmd/write vs shiftout()
// NOTE: delay is on hairy edge of working when FAST_MODE is on.
// because of waitUsec().
// There is margin at 16Mhz AVR but might fail on 20Mhz AVRs.
//
// @author F. Malpartida - fmalpartida@gmail.com
// ---------------------------------------------------------------------------
// flags for backlight control
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#if (ARDUINO < 100)
#include <WProgram.h>
#else
#include <Arduino.h>
#endif
#include "LiquidCrystal_SR3W.h"
#include "FastIO.h"
/*!
@defined
@abstract LCD_NOBACKLIGHT
@discussion No BACKLIGHT MASK
*/
#define LCD_NOBACKLIGHT 0x00
/*!
@defined
@abstract LCD_BACKLIGHT
@discussion BACKLIGHT MASK used when backlight is on
*/
#define LCD_BACKLIGHT 0xFF
// Default library configuration parameters used by class constructor with
// only the I2C address field.
// ---------------------------------------------------------------------------
/*!
@defined
@abstract Enable bit of the LCD
@discussion Defines the IO of the expander connected to the LCD's Enable
*/
#define EN 4 // Enable bit
/*!
@defined
@abstract Read/Write bit of the LCD
@discussion Defines the IO of the expander connected to the LCD's Rw pin
*/
#define RW 5 // Read/Write bit
/*!
@defined
@abstract Register bit of the LCD
@discussion Defines the IO of the expander connected to the LCD's Register select pin
*/
#define RS 6 // Register select bit
/*!
@defined
@abstract LCD dataline allocation this library only supports 4 bit LCD control
mode.
@discussion D4, D5, D6, D7 LCD data lines pin mapping of the extender module
*/
#define D4 0
#define D5 1
#define D6 2
#define D7 3
LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe)
{
init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 );
}
LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe,
uint8_t backlighPin, t_backlighPol pol)
{
init( data, clk, strobe, RS, RW, EN, D4, D5, D6, D7 );
setBacklightPin(backlighPin, pol);
}
LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe,
uint8_t En, uint8_t Rw, uint8_t Rs,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 )
{
init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 );
}
LiquidCrystal_SR3W::LiquidCrystal_SR3W(uint8_t data, uint8_t clk, uint8_t strobe,
uint8_t En, uint8_t Rw, uint8_t Rs,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
uint8_t backlighPin, t_backlighPol pol)
{
init( data, clk, strobe, Rs, Rw, En, d4, d5, d6, d7 );
setBacklightPin(backlighPin, pol);
}
void LiquidCrystal_SR3W::send(uint8_t value, uint8_t mode)
{
if ( mode != FOUR_BITS )
{
write4bits( (value >> 4), mode ); // upper nibble
}
write4bits( (value & 0x0F), mode); // lower nibble
#if (F_CPU <= 16000000)
// No need to use the delay routines on AVR since the time taken to write
// on AVR with SR pin mapping even with fio is longer than LCD command execution.
waitUsec(37); //goes away on AVRs
#else
delayMicroseconds ( 37 ); // commands & data writes need > 37us to complete
#endif
}
void LiquidCrystal_SR3W::setBacklightPin ( uint8_t value, t_backlighPol pol = POSITIVE )
{
_backlightPinMask = ( 1 << value );
_backlightStsMask = LCD_NOBACKLIGHT;
_polarity = pol;
setBacklight (BACKLIGHT_OFF); // Set backlight to off as initial setup
}
void LiquidCrystal_SR3W::setBacklight ( uint8_t value )
{
// Check if backlight is available
// ----------------------------------------------------
if ( _backlightPinMask != 0x0 )
{
// Check for polarity to configure mask accordingly
// ----------------------------------------------------------
if (((_polarity == POSITIVE) && (value > 0)) ||
((_polarity == NEGATIVE ) && ( value == 0 )))
{
_backlightStsMask = _backlightPinMask & LCD_BACKLIGHT;
}
else
{
_backlightStsMask = _backlightPinMask & LCD_NOBACKLIGHT;
}
loadSR( _backlightStsMask );
}
}
// PRIVATE METHODS
// -----------------------------------------------------------------------------
int LiquidCrystal_SR3W::init(uint8_t data, uint8_t clk, uint8_t strobe,
uint8_t Rs, uint8_t Rw, uint8_t En,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
{
_data = fio_pinToBit(data);
_clk = fio_pinToBit(clk);
_strobe = fio_pinToBit(strobe);
_data_reg = fio_pinToOutputRegister(data);
_clk_reg = fio_pinToOutputRegister(clk);
_strobe_reg = fio_pinToOutputRegister(strobe);
// LCD pin mapping
_backlightPinMask = 0;
_backlightStsMask = LCD_NOBACKLIGHT;
_polarity = POSITIVE;
_En = ( 1 << En );
_Rw = ( 1 << Rw );
_Rs = ( 1 << Rs );
// Initialise pin mapping
_data_pins[0] = ( 1 << d4 );
_data_pins[1] = ( 1 << d5 );
_data_pins[2] = ( 1 << d6 );
_data_pins[3] = ( 1 << d7 );
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
return (1);
}
void LiquidCrystal_SR3W::write4bits(uint8_t value, uint8_t mode)
{
uint8_t pinMapValue = 0;
// Map the value to LCD pin mapping
// --------------------------------
for ( uint8_t i = 0; i < 4; i++ )
{
if ( ( value & 0x1 ) == 1 )
{
pinMapValue |= _data_pins[i];
}
value = ( value >> 1 );
}
// Is it a command or data
// -----------------------
mode = ( mode == LCD_DATA ) ? _Rs : 0;
pinMapValue |= mode | _backlightStsMask;
loadSR ( pinMapValue | _En ); // Send with enable high
loadSR ( pinMapValue); // Send with enable low
}
void LiquidCrystal_SR3W::loadSR(uint8_t value)
{
// Load the shift register with information
fio_shiftOut(_data_reg, _data, _clk_reg, _clk, value, MSBFIRST);
// Strobe the data into the latch
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
fio_digitalWrite_HIGH(_strobe_reg, _strobe);
fio_digitalWrite_SWITCHTO(_strobe_reg, _strobe, LOW);
}
}