Romi32U4 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 
14 PololuHD44780Base::PololuHD44780Base()
15 {
16  initialized = false;
17 }
18 
19 void 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 
46 void 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 
62 size_t PololuHD44780Base::write(uint8_t data)
63 {
64  sendData(data);
65  return 1;
66 }
67 
68 size_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 
88 void 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 
103 void 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 
117 void 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 
131 void 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 
198 void 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 size_t write(uint8_t c)
void gotoXY(uint8_t x, uint8_t y)
virtual void initPins()=0
void loadCustomCharacterFromRam(const uint8_t *picture, uint8_t number)
virtual void send(uint8_t data, bool rsValue, bool only4bits)=0
void loadCustomCharacter(const uint8_t *picture, uint8_t number)