Zumo32U4 library
PololuHD44780.cpp
1// Copyright Pololu Corporation. For more information, see http://www.pololu.com/
2
3#include <PololuHD44780.h>
4
5#define LCD_CLEAR 0x01
6#define LCD_SHOW_BLINK 0x0F
7#define LCD_SHOW_SOLID 0x0E
8#define LCD_HIDE 0x0C
9#define LCD_CURSOR_L 0x10
10#define LCD_CURSOR_R 0x14
11#define LCD_SHIFT_L 0x18
12#define LCD_SHIFT_R 0x1C
13
14PololuHD44780Base::PololuHD44780Base()
15{
16 initialized = false;
17}
18
19void PololuHD44780Base::init2()
20{
21 // The startup procedure comes from Figure 24 of the HD44780 datasheet. The
22 // delay times in the later part of this function come from Table 6.
23
24 initPins();
25
26 // We need to wait at least 15 ms after VCC reaches 4.5 V.
27 //
28 // Assumption: The AVR's power-on reset is already configured to wait for
29 // tens of milliseconds, so no delay is needed here.
30
31 sendCommand4Bit(3); // Function set
32 _delay_us(4200); // Needs to be at least 4.1 ms.
33 sendCommand4Bit(3); // Function set
34 _delay_us(150); // Needs to be at least 100 us.
35 sendCommand4Bit(3); // Function set
36
37 sendCommand4Bit(0b0010); // 4-bit interface
38 sendCommand(0b00101000); // 4-bit, 2 line, 5x8 dots font
39
40 setDisplayControl(0b000); // display off, cursor off, blinking off
41 clear();
42 setEntryMode(0b10); // cursor shifts right, no auto-scrolling
43 setDisplayControl(0b100); // display on, cursor off, blinking off
44}
45
46void PololuHD44780Base::sendAndDelay(uint8_t data, bool rsValue, bool only4bit)
47{
48 init();
49
50 send(data, rsValue, only4bit);
51
52 // Every data transfer or command takes at least 37 us to complete, and most
53 // of them only take that long according to the HD44780 datasheet. We delay
54 // for 37 us here so we don't have to do it in lots of other places.
55 //
56 // NOTE: If we add support for configurations where the R/W line is
57 // connected, then this delay and others like it should be disabled, and we
58 // should instead wait for the busy flag before sending the next command.
59 _delay_us(37);
60}
61
62size_t PololuHD44780Base::write(uint8_t data)
63{
64 sendData(data);
65 return 1;
66}
67
68size_t PololuHD44780Base::write(const uint8_t * buffer, size_t length)
69{
70 size_t n = length;
71 while (n--)
72 {
73 sendData(*buffer++);
74 }
75 return length;
76}
77
79{
80 sendCommand(LCD_CLEAR);
81
82 // It's not clear how long this command takes because it doesn't say in
83 // Table 6 of the HD44780 datasheet. A good guess is that it takes 1.52 ms,
84 // since the Return Home command does.
85 _delay_us(2000);
86}
87
88void PololuHD44780Base::gotoXY(uint8_t x, uint8_t y)
89{
90 // Each entry is the RAM address of a line, with its most
91 // significant bit set for convenience.
92 const uint8_t line_mem[] = {0x80, 0xC0, 0x94, 0xD4};
93
94 // Avoid out-of-bounds array access.
95 if (y > 3) { y = 3; }
96
97 sendCommand(line_mem[y] + x);
98
99 // This could take up to 37 us according to Table 6 of the HD44780 datasheet.
100 _delay_us(37);
101}
102
103void PololuHD44780Base::loadCustomCharacter(const uint8_t * picture, uint8_t number)
104{
105 uint8_t address = number * 8;
106
107 for(uint8_t i = 0; i < 8; i++)
108 {
109 // Set CG RAM address.
110 sendCommand(0b01000000 | (address + i));
111
112 // Write character data.
113 sendData(pgm_read_byte(picture + i));
114 }
115}
116
117void PololuHD44780Base::loadCustomCharacterFromRam(const uint8_t * picture, uint8_t number)
118{
119 uint8_t address = number * 8;
120
121 for(uint8_t i = 0; i < 8; i++)
122 {
123 // Set CG RAM address.
124 sendCommand(0b01000000 | (address + i));
125
126 // Write character data.
127 sendData(picture[i]);
128 }
129}
130
131void PololuHD44780Base::setDisplayControl(uint8_t displayControl)
132{
133 sendCommand(0b00001000 | displayControl);
134 this->displayControl = displayControl;
135}
136
138{
139 setDisplayControl((displayControl | 0b010) & ~0b001);
140}
141
143{
144 setDisplayControl((displayControl | 0b001) & ~0b010);
145}
146
148{
149 setDisplayControl(displayControl & ~0b011);
150}
151
153{
154 setDisplayControl(displayControl & ~0b100);
155}
156
158{
159 setDisplayControl(displayControl | 0b100);
160}
161
163{
164 setDisplayControl(displayControl & ~0b010);
165}
166
168{
169 setDisplayControl(displayControl | 0b010);
170}
171
173{
174 setDisplayControl(displayControl & ~0b001);
175}
176
178{
179 setDisplayControl(displayControl | 0b001);
180}
181
183{
184 sendCommand(0b00011000);
185}
186
188{
189 sendCommand(0b00011100);
190}
191
193{
194 sendCommand(0b00000010);
195 _delay_us(1600); // needs to be at least 1.52 ms
196}
197
198void PololuHD44780Base::setEntryMode(uint8_t entryMode)
199{
200 sendCommand(0b00000100 | entryMode);
201 this->entryMode = entryMode;
202}
203
205{
206 setEntryMode(entryMode | 0b10);
207}
208
210{
211 setEntryMode(entryMode & ~0b10);
212}
213
215{
216 setEntryMode(entryMode | 0b01);
217}
218
220{
221 setEntryMode(entryMode & ~0b01);
222}
virtual void send(uint8_t data, bool rsValue, bool only4bits)=0
virtual size_t write(uint8_t c)
void gotoXY(uint8_t x, uint8_t y)
void loadCustomCharacterFromRam(const uint8_t *picture, uint8_t number)
void loadCustomCharacter(const uint8_t *picture, uint8_t number)
virtual void initPins()=0