summaryrefslogtreecommitdiff
path: root/docs/feature_hd44780.md
blob: dcbd656bbee4c695a5d2c393ec1100f7bd4bbfbb (plain)
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
# HD44780 LCD Driver :id=hd44780-lcd-driver

## Supported Hardware :id=supported-hardware

LCD modules using [HD44780U](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) IC or equivalent, communicating in 4-bit mode.

|Module|Size          |Notes                            |
|------|--------------|---------------------------------|
|1602A |16x2, 5x8 dots|                                 |
|2004A |20x4, 5x8 dots|Untested, not currently supported|

To run these modules at 3.3V, an additional MAX660 voltage converter IC must be soldered on, along with two 10µF capacitors. See [this page](https://www.codrey.com/electronic-circuits/hack-your-16x2-lcd/) for more details.

## Usage :id=usage

Add the following to your `rules.mk`:

```make
HD44780_ENABLE = yes
```

## Basic Configuration :id=basic-configuration

Add the following to your `config.h`:

|Define                 |Default       |Description                                                                                          |
|-----------------------|--------------|-----------------------------------------------------------------------------------------------------|
|`HD44780_DATA_PINS`    |*Not defined* |(Required) An array of four GPIO pins connected to the display's D4-D7 pins, eg. `{ B1, B3, B2, B6 }`|
|`HD44780_RS_PIN`       |*Not defined* |(Required) The GPIO connected to the display's RS pin                                                |
|`HD44780_RW_PIN`       |*Not defined* |(Required) The GPIO connected to the display's RW pin                                                |
|`HD44780_E_PIN`        |*Not defined* |(Required) The GPIO connected to the display's E pin                                                 |
|`HD44780_DISPLAY_COLS` |`16`          |The number of visible characters on a single line of the display                                     |
|`HD44780_DISPLAY_LINES`|`2`           |The number of visible lines on the display                                                           |
|`HD44780_WRAP_LINES`   |*Not defined* |If defined, input characters will wrap to the next line                                              |

## Examples :id=examples

### Hello World :id=example-hello-world

Add the following to your `keymap.c`:

```c
void keyboard_post_init_user(void) {
    hd44780_init(true, true); // Show blinking cursor
    hd44780_puts_P(PSTR("Hello, world!\n"));
}
```

### Custom Character Definition :id=example-custom-character

Up to eight custom characters can be defined. This data is stored in the Character Generator RAM (CGRAM), and is not persistent across power cycles.

This example defines the QMK Psi as the first custom character. The first 16 positions in the character set are reserved for the eight custom characters duplicated.

```
Byte |      16 8 4 2 1
   1 | x x x ■ □ ■ □ ■
   2 | x x x ■ □ ■ □ ■
   3 | x x x ■ □ ■ □ ■
   4 | x x x □ ■ ■ ■ □
   5 | x x x □ □ ■ □ □
   6 | x x x □ □ ■ □ □
   7 | x x x □ □ ■ □ □
   8 | x x x □ □ □ □ □
```

```c
const uint8_t PROGMEM psi[8] = { 0x15, 0x15, 0x15, 0x0E, 0x04, 0x04, 0x04, 0x00 };

void keyboard_post_init_user(void) {
    hd44780_init(false, false);
    hd44780_define_char_P(0, psi);
    // Cursor is incremented while defining characters so must be reset
    hd44780_home();
    // 0x08 to avoid null terminator
    hd44780_puts_P(PSTR("\x08 QMK Firmware"));
}
```

## API :id=api

### `void hd44780_init(bool cursor, bool blink)` :id=api-hd44780-init

Initialize the display.

This function should be called only once, before any of the other functions can be called.

#### Arguments :id=api-hd44780-init-arguments

 - `bool cursor`  
   Whether to show the cursor.
 - `bool blink`  
   Whether to blink the cursor, if shown.

---

### `void hd44780_clear(void)` :id=api-hd44780-clear

Clear the display.

This function is called on init.

---

### `void hd44780_home(void)` :id=api-hd44780-home

Move the cursor to the home position.

This function is called on init.

---

### `void hd44780_on(bool cursor, bool blink)` :id=api-hd44780-on

Turn the display on, and/or set the cursor properties.

This function is called on init.

#### Arguments :id=api-hd44780-on-arguments

 - `bool cursor`  
   Whether to show the cursor.
 - `bool blink`  
   Whether to blink the cursor, if shown.

---

### `void hd44780_off(void)` :id=api-hd44780-off

Turn the display off.

---

### `void hd44780_set_cursor(uint8_t col, uint8_t line)` :id=api-hd44780-set-cursor

Move the cursor to the specified position on the display.

#### Arguments :id=api-hd44780-set-cursor-arguments

 - `uint8_t col`  
   The column number to move to, from 0 to 15 on 16x2 displays.
 - `bool line`  
   The line number to move to, either 0 or 1 on 16x2 displays.

---

### `void hd44780_putc(char c)` :id=api-hd44780-putc

Print a character to the display. The newline character `\n` will move the cursor to the start of the next line.

The exact character shown may depend on the ROM code of your particular display - refer to the datasheet for the full character set.

#### Arguments :id=api-hd44780-putc-arguments

 - `char c`  
   The character to print.

---

### `void hd44780_puts(const char *s)` :id=api-hd44780-puts

Print a string of characters to the display.

#### Arguments :id=api-hd44780-puts-arguments

 - `const char *s`  
   The string to print.

---

### `void hd44780_puts_P(const char *s)` :id=api-hd44780-puts-p

Print a string of characters from PROGMEM to the display.

On ARM devices, this function is simply an alias of `hd44780_puts()`.

#### Arguments :id=api-hd44780-puts-p-arguments

 - `const char *s`  
   The PROGMEM string to print (ie. `PSTR("Hello")`).

---

### `void hd44780_define_char(uint8_t index, uint8_t *data)` :id=api-hd44780-define-char

Define a custom character.

#### Arguments :id=api-hd44780-define-char-arguments

 - `uint8_t index`  
   The index of the custom character to define, from 0 to 7.
 - `uint8_t *data`  
   An array of 8 bytes containing the 5-bit row data of the character, where the first byte is the topmost row, and the least significant bit of each byte is the rightmost column.

---

### `void hd44780_define_char_P(uint8_t index, const uint8_t *data)` :id=api-hd44780-define-char-p

Define a custom character from PROGMEM.

On ARM devices, this function is simply an alias of `hd44780_define_char()`.

#### Arguments :id=api-hd44780-define-char-p-arguments

 - `uint8_t index`  
   The index of the custom character to define, from 0 to 7.
 - `const uint8_t *data`  
   A PROGMEM array of 8 bytes containing the 5-bit row data of the character, where the first byte is the topmost row, and the least significant bit of each byte is the rightmost column.

---

### `bool hd44780_busy(void)` :id=api-hd44780-busy

Indicates whether the display is currently processing, and cannot accept instructions.

#### Return Value :id=api-hd44780-busy-arguments

`true` if the display is busy.

---

### `void hd44780_write(uint8_t data, bool isData)` :id=api-hd44780-write

Write a byte to the display.

#### Arguments :id=api-hd44780-write-arguments

 - `uint8_t data`  
   The byte to send to the display.
 - `bool isData`  
   Whether the byte is an instruction or character data.

---

### `uint8_t hd44780_read(bool isData)` :id=api-hd44780-read

Read a byte from the display.

#### Arguments :id=api-hd44780-read-arguments

 - `bool isData`  
   Whether to read the current cursor position, or the character at the cursor.

#### Return Value :id=api-hd44780-read-return

If `isData` is `true`, the returned byte will be the character at the current DDRAM address. Otherwise, it will be the current DDRAM address and the busy flag.

---

### `void hd44780_command(uint8_t command)` :id=api-hd44780-command

Send a command to the display. Refer to the datasheet and `hd44780.h` for the valid commands and defines.

This function waits for the display to clear the busy flag before sending the command.

#### Arguments :id=api-hd44780-command-arguments

 - `uint8_t command`  
   The command to send.

---

### `void hd44780_data(uint8_t data)` :id=api-hd44780-data

Send a byte of data to the display.

This function waits for the display to clear the busy flag before sending the data.

#### Arguments :id=api-hd44780-data-arguments

 - `uint8_t data`  
   The byte of data to send.

---

### `void hd44780_set_cgram_address(uint8_t address)` :id=api-hd44780-set-cgram-address

Set the CGRAM address.

This function is used when defining custom characters.

#### Arguments :id=api-hd44780-set-cgram-address-arguments

 - `uint8_t address`  
   The CGRAM address to move to, from `0x00` to `0x3F`.

---

### `void hd44780_set_ddram_address(uint8_t address)` :id=api-hd44780-set-ddram-address

Set the DDRAM address.

This function is used when printing characters to the display, and setting the cursor.

#### Arguments :id=api-hd44780-set-ddram-address-arguments

 - `uint8_t address`  
   The DDRAM address to move to, from `0x00` to `0x7F`.