-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathhd44780.h
438 lines (380 loc) · 18.5 KB
/
hd44780.h
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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
// vi:ts=4
// -------------------------------------------------------------------------
// hd44780.h - hd44780 base class
// Copyright (c) 2014-2020 Bill Perry
// (Derivative work of arduino.cc IDE LiquidCrystal library)
// Note:
// Original Copyrights for LiquidCrystal are a mess as originally none were
// specified, but in Nov 2015 these have appeared so they are included:
//
// Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
// Copyright (c) 2010 Arduino LLC. All right reserved.
//
// See licenseInfo.txt for a history of the copyrights of LiquidCrystal
// --------------------------------------------------------------------------
//
// This file is part of the hd44780 library
//
// hd44780 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation version 3 of the License.
//
// hd44780 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with hd44780. If not, see <http://www.gnu.org/licenses/>.
//
// See the license.txt file for further licensing & copyright details.
// -----------------------------------------------------------------------
//
// hd44780 is an extensible LCD library for hd44780 based LCD displays.
// The library consists of a hd44780 base class combined with one or more
// i/o subclasses to perform the i/o communication between the host and the
// hd44780 display interface.
//
// The API functionality provided by the hd44780 base class, when combined
// with an hd44780 library i/o subclass, is compatible with the API
// functionality of the Arduino LiquidCrystal library as well as compatibilty
// with most of the LCD API 1.0 Specification (nearly obsolete).
//
// The hd44780 API also provides some addtional extensions and all the API
// functions provided by hd44780 are common across all i/o subclasses.
//
// -----------------------------------------------------------------------
// History
//
// 2020-11-14 bperrybap - created internal command4bit() for begin() function
// 2019.08.11 bperrybap - support for 1 and 2 lines in setRowOffsets()
// 2018.03.23 bperrybap - bumped default instruction time from 37us to 38us
// 2017.12.23 bperrybap - added LCD API 1.0 init() function
// 2017.12.23 bperrybap - allow write() to use 0 as a value without cast
// 2017.05.11 bperrybap - added auto linewrap functionality
// 2016.12.26 bperrybap - new BUSY error status, new constructors
// 2016.09.08 bperrybap - changed param order of iowrite() to match ioread()
// 2016.08.06 bperrybap - changed iosend() to iowrite()
// 2016.08.06 bperrybap - added status() and read()
// 2016.07.27 bperrybap - added return status to command() and iosend()
// 2016.07.20 bperrybap - merged hd44780 base class and i/o classes into a
// single library.
//
// 2016.06.08 bperrybap - removed pre 1.0 support
// 2016.06.03 bperrybap - added smart execution delays
// 2016.05.14 bperrybap - added LCD 1.0 API functions
// 2016.05.05 bperrybap - added support for 8 bit mode
// 2014.02.15 bperrybap - initial creation
//
// @author Bill Perry - [email protected]
//
// ------------------------------------------------------------------------
#ifndef hd44780_h
#define hd44780_h
#if (ARDUINO < 100) && !defined(MPIDE)
#error hd44780 library requires Arduino 1.0 or later
#endif
#include <Arduino.h>
#include <inttypes.h>
#include <Print.h>
#define HD44780_VERSION 10302
#define HD44780_VERSIONSTR "1.3.2"
class hd44780 : public Print
{
public:
hd44780();
hd44780(uint8_t cols, uint8_t rows);
hd44780(uint8_t cols, uint8_t rows, uint32_t chExecTime, uint32_t insExecTime);
// default execute times in us for clear/home and instructions/data
// The hd44780 spec uses 1520 and 37 in table 6 page 24
// note: the spec does not specify the time for Clear display
// 38us is used vs 37 as 37 had issues on VERY fast processors that could
// send data to the LCD that fast.
// these can be overridden using setExecTimes(chUs, insUs)
static const int HD44780_CHEXECTIME = 2000; // time in us for clear&home
static const int HD44780_INSEXECTIME = 38;
// API return values
// 0 means successful, less than zero means unsuccessful
static const int RV_ENOERR=0; // no error. Do not change!
static const int RV_EIO=-1; // i/o operation failed (generic/default error)
static const int RV_EINVAL=-2; // invalid argument/parameter
static const int RV_ENOTSUP=-3; // not supported
static const int RV_ENXIO=-4; // no such device or address
static const int RV_EMSGSIZE=-5; // Message/data too long
static const int RV_EBUSY=-6; // device is unexpectedly BUSY
// commands
static const uint8_t HD44780_CLEARDISPLAY = 0x01;
static const uint8_t HD44780_RETURNHOME = 0x02;
static const uint8_t HD44780_ENTRYMODESET = 0x04;
static const uint8_t HD44780_DISPLAYCONTROL = 0x08;
static const uint8_t HD44780_CURDISPSHIFT = 0x10;
static const uint8_t HD44780_FUNCTIONSET = 0x20;
static const uint8_t HD44780_SETCGRAMADDR = 0x40;
static const uint8_t HD44780_SETDDRAMADDR = 0x80;
// flags for entry mode set;
static const uint8_t HD44780_ENTRYLEFT2RIGHT = 0x02;
static const uint8_t HD44780_ENTRYAUTOSHIFT = 0x01;
// flags for display on/off control;
static const uint8_t HD44780_DISPLAYON = 0x04;
// static const uint8_t HD44780_DISPLAYOFF = 0x00;
static const uint8_t HD44780_CURSORON = 0x02;
static const uint8_t HD44780_CURSOROFF = 0x00;
static const uint8_t HD44780_BLINKON = 0x01;
static const uint8_t HD44780_BLINKOFF = 0x00;
// flags for cursor/display shift;
static const uint8_t HD44780_DISPLAYMOVE = 0x08;
static const uint8_t HD44780_CURSORMOVE = 0x00;
static const uint8_t HD44780_MOVERIGHT = 0x04;
static const uint8_t HD44780_MOVELEFT = 0x00;
// flags for function set;
static const uint8_t HD44780_8BITMODE = 0x10;
static const uint8_t HD44780_4BITMODE = 0x00;
static const uint8_t HD44780_2LINE = 0x08;
static const uint8_t HD44780_1LINE = 0x00;
static const uint8_t HD44780_5x10DOTS = 0x04;
static const uint8_t HD44780_5x8DOTS = 0x00;
// Print class println() function is not supported
// catch it and print an error
size_t __attribute__ ((error("println() is not supported"))) println(const __FlashStringHelper *);
size_t __attribute__ ((error("println() is not supported"))) println(const String &s);
size_t __attribute__ ((error("println() is not supported"))) println(const char[]);
size_t __attribute__ ((error("println() is not supported"))) println(char);
size_t __attribute__ ((error("println() is not supported"))) println(unsigned char, int = DEC);
size_t __attribute__ ((error("println() is not supported"))) println(int, int = DEC);
size_t __attribute__ ((error("println() is not supported"))) println(unsigned int, int = DEC);
size_t __attribute__ ((error("println() is not supported"))) println(long, int = DEC);
size_t __attribute__ ((error("println() is not supported"))) println(unsigned long, int = DEC);
size_t __attribute__ ((error("println() is not supported"))) println(double, int = 2);
#ifdef Printable_h
size_t __attribute__ ((error("println() is not supported"))) println(const Printable&);
#endif
size_t __attribute__ ((error("println() is not supported"))) println(void);
// ALL API calls return a status.
// This is a change to existing APIs like
// LiquidCrystal and LCD API 1.0
// but should be compatible with existing code.
//
// Unless otherwise documented,
// A less than zero status means the API call was not successful
// Arduino IDE LiquidCrystal lib functions
// =======================================
// begin()
// returns 0 on success, non zero on initalization failure
int begin(uint8_t cols, uint8_t rows, uint8_t charsize = HD44780_5x8DOTS);
#if 0
// init ()
// This version will NEVER be implemented in this class as it is
// not conformant to LCD API 1.0 and is hardware i/o specific
void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
#endif
int clear();
int home();
int setCursor(uint8_t col, uint8_t row);
size_t write(uint8_t value); // does char & line processing
size_t _write(uint8_t value); // does not do char & line processing
// write() overloads for 0 or null which is an int
// This is only because Print class doesn't do it.
inline size_t write(unsigned int value) { return(write((uint8_t)value)); }
inline size_t write(int value) { return(write((uint8_t)value)); }
inline size_t _write(unsigned int value) { return(_write((uint8_t)value)); }
inline size_t _write(int value) { return(_write((uint8_t)value)); }
using Print::write; // for other Print Class write() functions
int cursor();
int noCursor();
int blink();
int noBlink();
int display(); // turn on LCD pixels
int noDisplay(); // turn off LCD pixels
int scrollDisplayLeft();
int scrollDisplayRight();
int autoscroll(); // auto horizontal scrolling
int noAutoscroll(); // no auto horizontal scrolling
int leftToRight();
int rightToLeft();
int createChar(uint8_t charval, uint8_t charmap[]); // no PROGMEM
int moveCursorLeft();
int moveCursorRight();
// sets memory address for each row, added in IDE 1.6.0
// hd44780 allows calls with 1, 2, 3, or 4 offsets
int setRowOffsets(int row0, int row1=0, int row2=0, int row3=0);
// Mandatory LCD API 1.0 functions
// ================================
int init(); // uses defaults; using begin(cols, rows) is recommended
#if ( __GNUC__ >= 4) && (__GNUC_MINOR__ >= 5)
inline void __attribute__((deprecated("Use setExecTimes() instead"))) setDelay(uint32_t CmdDelay, uint32_t CharDelay)
{setExecTimes(CmdDelay, CharDelay);}
#else
inline void __attribute__((deprecated)) setDelay(uint32_t CmdDelay, uint32_t CharDelay)
{setExecTimes(CmdDelay, CharDelay);}
#endif
// command()
// returns 0 on success, non zero on command failure
int command(uint8_t);
#if 0
// setCursor()
// MAJOR PROBLEM:
// The LiquidCrystal API defines this as setCursor(col, row);
// This is fundamentally incompatible with this defintion.
// there is no way to fix this.
// The LiquidCrytal API is in wide spread use so it wins.
// any LCD API 1.0 code will have to be fixed to deal wth this.
// A quick and dirty way to work around this to define a macro
// to flip the parameters:
// #define setCursor(_row, _col) setCursor(_col, _row)
// and place it just after the #include for the library
void setCursor(uint8_t row, uint8_t col);
#endif
// cursor_on()
// cursor_off()
// blink_on()
// blink_off()
// These functions should be considered obsolete as LiquidCrytal API has
// api functions for these that are in wide spread use.
// note: only very new versions of gcc support setting warning message
// it breaks on on older versions that shipped with older 1.x IDEs
// so test for gcc 4.5 or greater for better deprecated messages
#if ( __GNUC__ >= 4) && (__GNUC_MINOR__ >= 5)
inline int __attribute__((deprecated("Use cursor() instead"))) cursor_on() {return(cursor());}
inline int __attribute__((deprecated("Use noCursor() instead"))) cursor_off() {return(noCursor());}
inline int __attribute__((deprecated("Use blink() instead"))) blink_on() {return(blink());}
inline int __attribute__((deprecated("Use noBlink() instead"))) blink_off() { return(noBlink());}
#else
inline int __attribute__((deprecated)) cursor_on() {return(cursor());}
inline int __attribute__((deprecated)) cursor_off() {return(noCursor());}
inline int __attribute__((deprecated)) blink_on() {return(blink());}
inline int __attribute__((deprecated)) blink_off() { return(noBlink());}
#endif
// optional LCD API 1.0 functions
// ==============================
inline int setBacklight(uint8_t dimvalue) {return(iosetBacklight(dimvalue));}
inline int setContrast(uint8_t contvalue) {return(iosetContrast(contvalue));}
int on(void); // turn on LCD pixels and backlight
int off(void); // turn off LCD pixels and backlight
// status();
// The LCD API 1.0 documenation says it does not work the same
// on all devices.
// On one device it returns some sort of fifo status.
// the documenation isn't clear what it should do on other h/w.
// hd44780 mandates that all API functions work the same for all
// i/o subclasses.
//
// returns:
// success: 8 bit hd44780 status byte read from LCD (busy flag & address)
// failure: negataive value (error or read/status not supported)
int status();
// extended LCD API 1.0 functions
// ==============================
// load_custom_character()
// this function should be considered obsolete as LiquidCrystal API has
// a createChar() function that is in wide spread use
// LCD API documentation for this call says 7 byte array
// but it is really 8 bytes per custom char
// note: only very new versions of gcc support setting warning message
// it breaks on on older versions that shipped with older 1.x IDEs
// so test for gcc 4.5 or greater for better deprecated messages
#if ( __GNUC__ >= 4) && (__GNUC_MINOR__ >= 5)
inline void __attribute__((deprecated("Use createChar() instead")))
load_custom_character(uint8_t Char_Num, uint8_t Rows[]) {createChar(Char_Num, Rows); }
#else
inline void __attribute__((deprecated))
load_custom_character(uint8_t Char_Num, uint8_t Rows[]) {createChar(Char_Num, Rows); }
#endif
#if 0
// This will NEVER be implemented in this class as it is very h/w specific
uint8_t keypad(); // not implemented
#endif
// Additional API functions
// These are hd44780 lib extensions that are
// not part of LCD 1.0 or LiquidCrystal
// note:
// status() exists in LCD 1.0 API but is different
// hd44780 status() function will be consistent across all i/o subclasses
// ===================================================================
int backlight(void); // turn on Backlight (max brightness)
int noBacklight(void); // turn off Backlight
// PROGMEM is wreck on AVR, as there is no way to detect its use.
// for now:
// hd44780 assumes that const stores data in flash and
// on processors that use/need PROGMEM it must be used on the declaration
inline int createChar(uint8_t charval, char charmap[]) // does not assume PROGMEM
{ return(createChar(charval, (uint8_t *) charmap)); }
// on processors that don't use/need PROGMEM it can be left off the declaration
int createChar(uint8_t charval, const uint8_t charmap[]); // assumes PROGMEM
// this function is for compatibilty with other libraries like fm's newliquidCrystal
inline int createChar(uint8_t charval, const char charmap[]) // assumes PROGMEM
{ return(createChar(charval, (const uint8_t *) charmap)); }
int read(void);
// enable automatic line wrapping (only works in left 2 right mode)
int lineWrap(void) { if(_displaymode & HD44780_ENTRYLEFT2RIGHT) {_wraplines=1; return(RV_ENOERR);}else{return(RV_ENOTSUP);}}
// disable automatic line wrapping
int noLineWrap(void){ _wraplines=0; return(RV_ENOERR);}; // turn off automatic line wrapping
// set execution times for commmands to override defaults
inline void setExecTimes(uint32_t chExecTimeUs, uint32_t insExecTimeUs)
{ _chExecTime = chExecTimeUs; _insExecTime = insExecTimeUs;}
// A few undocumented helper functions for the included examples
static int blinkLED(int blinks); // blink a built in LED if possible
static void fatalError(int errcode); // hang in loop blinking error code
protected:
// type of data being sent through ioread()/iowrite()
// IOcmd - read/write an 8 bit status/command to/from display
// IOdata - read/writes 8 bits of data to/from display
// IOcmd4bit - write D4-d7 cmd bits to display using a single EN strobe
// 8 bit host interfaces can treate this same as IOcmd
enum iotype {HD44780_IOcmd, HD44780_IOdata, HD44780_IOcmd4bit};
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _cols;
uint8_t _rows;
// wait for lcd to be ready
inline void waitReady() {_waitReady((_startTime), _execTime);}
inline void waitReady(int32_t offsetUs) {_waitReady((_startTime+offsetUs), _execTime);}
inline void _waitReady(uint32_t _stime, uint32_t _etime)
{while(( ((uint32_t)micros()) - _stime) < _etime){}}
private:
uint8_t _curcol; // current LCD col if doing char & line processing
uint8_t _currow; // current LCD row if doing char & line processing
uint8_t _wraplines; // set to nonzero if wrapping long lines
// i/o subclass functions
virtual int ioinit() {return 0;} // optional - successful if not implemented
virtual int ioread(hd44780::iotype type) {if(type) return(RV_ENOTSUP);else return(RV_ENOTSUP);} // optional, return fail if not implemented
virtual int iowrite(hd44780::iotype type, uint8_t value)=0;// mandatory
virtual int iosetBacklight(uint8_t dimvalue){if(dimvalue) return(RV_ENOTSUP); else return(RV_ENOTSUP);} // optional
virtual int iosetContrast(uint8_t contvalue){if(contvalue) return(RV_ENOTSUP); else return(RV_ENOTSUP);}// optional
uint8_t _rowOffsets[4]; // memory address of start of each row/line
// stuff for tracking execution times
inline void markStart(uint32_t exectime) { _startTime = (uint32_t) micros(); _execTime = exectime;}
uint32_t _chExecTime; // time in Us of execution time for clear/home
uint32_t _insExecTime; // time in Us of execution time for instructions or data
uint32_t _startTime; // 'start' time of last thing sent to LCD (cmd or data)
uint32_t _execTime; // execution time in Us of last thing sent to LCD (cmd or data)
// internal API function to send only upper 4 bits of byte on LCD DB4 to DB7 pins
int command4bit(uint8_t value)
{
int status = iowrite(HD44780_IOcmd4bit, value);
markStart(_insExecTime);
return(status);
}
};
// LED_BUILTIN define fixups for Teensy, ChipKit, ESP8266, ESP32 cores
#if !defined(LED_BUILTIN)
#if defined(CORE_TEENSY)
#define LED_BUILTIN CORE_LED0_PIN
#elif defined(ARDUINO_ARCH_ESP8266)
#define LED_BUILTIN BUILTIN_LED
// this is for cores that incorrectly used BUILTIN_LED instead of LED_BUILTIN
// esp32 core does this, they have LED_BUILTIN but it is a const not a define
// this works around that.
#elif defined(BUILTIN_LED)
#define LED_BUILTIN BUILTIN_LED
// special check for pre 1.0.6 IDEs that didn't define LED_BUILTIN
#elif (ARDUINO < 106 ) && ( defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__))
#define LED_BUILTIN 13 // IDE bundled AVR boards use pin 13 for builtin led
#elif defined(PIN_LED1) // chipkit
#define LED_BUILTIN PIN_LED1
#endif
#endif
// endif for header guard
#endif