A basic basic basic driver for 2x16 HD44780 based displays using the four wire interface.
Dependents: lcdLibraryTest generado_final
lcd.cpp@0:0db835052212, 2013-11-08 (annotated)
- Committer:
- mattegan
- Date:
- Fri Nov 08 07:03:35 2013 +0000
- Revision:
- 0:0db835052212
[ADMIN] initial commit - everything should be working
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mattegan | 0:0db835052212 | 1 | #include "lcd.h" |
mattegan | 0:0db835052212 | 2 | |
mattegan | 0:0db835052212 | 3 | //Public Methods |
mattegan | 0:0db835052212 | 4 | ////////////////////////////////////////////////////////////////////////////////////////// |
mattegan | 0:0db835052212 | 5 | |
mattegan | 0:0db835052212 | 6 | lcd::lcd(PinName _rs, PinName _rw, PinName _e, PinName _db4, PinName _db5, PinName _db6, PinName _db7): |
mattegan | 0:0db835052212 | 7 | registerSelect(_rs), readWrite(_rw), enable(_e), dataBus(_db4, _db5, _db6, _db7) { |
mattegan | 0:0db835052212 | 8 | |
mattegan | 0:0db835052212 | 9 | currentMode = klcdReadMode; |
mattegan | 0:0db835052212 | 10 | setMode(klcdWriteMode); |
mattegan | 0:0db835052212 | 11 | |
mattegan | 0:0db835052212 | 12 | //wait for more than 15ms after Vcc rises to 4.5v |
mattegan | 0:0db835052212 | 13 | wait_ms(20); |
mattegan | 0:0db835052212 | 14 | |
mattegan | 0:0db835052212 | 15 | //function set (interface is 8 bits long) |
mattegan | 0:0db835052212 | 16 | writeNibble(klcdInstructionRegister, 0x3); |
mattegan | 0:0db835052212 | 17 | |
mattegan | 0:0db835052212 | 18 | //wait for more than 4.1ms |
mattegan | 0:0db835052212 | 19 | wait_ms(4.5); |
mattegan | 0:0db835052212 | 20 | |
mattegan | 0:0db835052212 | 21 | //function set(interface is 8 bits long) |
mattegan | 0:0db835052212 | 22 | writeNibble(klcdInstructionRegister, 0x3); |
mattegan | 0:0db835052212 | 23 | |
mattegan | 0:0db835052212 | 24 | //wait for more than 100us |
mattegan | 0:0db835052212 | 25 | wait_us(150); |
mattegan | 0:0db835052212 | 26 | |
mattegan | 0:0db835052212 | 27 | //function set (interface is 8 bits long) |
mattegan | 0:0db835052212 | 28 | writeNibble(klcdInstructionRegister, 0x3); |
mattegan | 0:0db835052212 | 29 | wait_us(90); |
mattegan | 0:0db835052212 | 30 | |
mattegan | 0:0db835052212 | 31 | //function set (interface is 4 bits long) |
mattegan | 0:0db835052212 | 32 | writeNibble(klcdInstructionRegister, 0x2); |
mattegan | 0:0db835052212 | 33 | wait_us(90); |
mattegan | 0:0db835052212 | 34 | |
mattegan | 0:0db835052212 | 35 | //function set (interface is 4 bits long) set display lines and character font |
mattegan | 0:0db835052212 | 36 | // 2 lines, 5x8 character font (1 0 0 0) |
mattegan | 0:0db835052212 | 37 | writeByte(klcdInstructionRegister, 0x28, false); |
mattegan | 0:0db835052212 | 38 | wait_us(90); |
mattegan | 0:0db835052212 | 39 | |
mattegan | 0:0db835052212 | 40 | //display off |
mattegan | 0:0db835052212 | 41 | writeByte(klcdInstructionRegister, 0x08, false); |
mattegan | 0:0db835052212 | 42 | wait_us(90); |
mattegan | 0:0db835052212 | 43 | |
mattegan | 0:0db835052212 | 44 | //display clear |
mattegan | 0:0db835052212 | 45 | writeByte(klcdInstructionRegister, 0x01, false); |
mattegan | 0:0db835052212 | 46 | wait_ms(2.0); |
mattegan | 0:0db835052212 | 47 | |
mattegan | 0:0db835052212 | 48 | //entry mode set |
mattegan | 0:0db835052212 | 49 | writeByte(klcdInstructionRegister, 0x0C, false); |
mattegan | 0:0db835052212 | 50 | wait_us(90); |
mattegan | 0:0db835052212 | 51 | |
mattegan | 0:0db835052212 | 52 | //clear display, and turn on |
mattegan | 0:0db835052212 | 53 | writeByte(klcdInstructionRegister, 0x01); |
mattegan | 0:0db835052212 | 54 | writeByte(klcdInstructionRegister, 0x0C); |
mattegan | 0:0db835052212 | 55 | |
mattegan | 0:0db835052212 | 56 | //turn shifting off |
mattegan | 0:0db835052212 | 57 | writeByte(klcdInstructionRegister, 0x04); |
mattegan | 0:0db835052212 | 58 | |
mattegan | 0:0db835052212 | 59 | row = 0; |
mattegan | 0:0db835052212 | 60 | column = 0; |
mattegan | 0:0db835052212 | 61 | |
mattegan | 0:0db835052212 | 62 | } |
mattegan | 0:0db835052212 | 63 | |
mattegan | 0:0db835052212 | 64 | void lcd::clear() { |
mattegan | 0:0db835052212 | 65 | //clear screen -> 0 0 (0 0 0 0 0 0 0 1) |
mattegan | 0:0db835052212 | 66 | writeByte(klcdInstructionRegister, 0x01); |
mattegan | 0:0db835052212 | 67 | locate(0, 0); |
mattegan | 0:0db835052212 | 68 | } |
mattegan | 0:0db835052212 | 69 | |
mattegan | 0:0db835052212 | 70 | void lcd::locate(int _row, int _column) { |
mattegan | 0:0db835052212 | 71 | row = _row; |
mattegan | 0:0db835052212 | 72 | column = _column; |
mattegan | 0:0db835052212 | 73 | } |
mattegan | 0:0db835052212 | 74 | |
mattegan | 0:0db835052212 | 75 | void lcd::locateCharacter(int _row, int _column, int _char) { |
mattegan | 0:0db835052212 | 76 | //set DDRAM address -> 0 0 (1 a a a a a a a) |
mattegan | 0:0db835052212 | 77 | //write DDRAM -> 1 0 (d d d d d d d d); |
mattegan | 0:0db835052212 | 78 | writeByte(klcdInstructionRegister, 0x80 + (_row * 0x40) + _column); |
mattegan | 0:0db835052212 | 79 | writeByte(klcdDataRegister, _char); |
mattegan | 0:0db835052212 | 80 | } |
mattegan | 0:0db835052212 | 81 | |
mattegan | 0:0db835052212 | 82 | void lcd::defineCharacter(int _char, int _charData[8]) { |
mattegan | 0:0db835052212 | 83 | if(_char < 0 || _char > 7) return; |
mattegan | 0:0db835052212 | 84 | //write CGRAM address 0 0 (0 1 a a a a a a) |
mattegan | 0:0db835052212 | 85 | // first three bits are character (0-7) |
mattegan | 0:0db835052212 | 86 | // second three bits are the row in the character |
mattegan | 0:0db835052212 | 87 | writeByte(klcdInstructionRegister, 0x40 + (_char << 3)); |
mattegan | 0:0db835052212 | 88 | for(int row = 0; row < 8; row++) { |
mattegan | 0:0db835052212 | 89 | //write CGRAM data 1 0 (d d d d d d d d) |
mattegan | 0:0db835052212 | 90 | writeByte(klcdDataRegister, _charData[row]); |
mattegan | 0:0db835052212 | 91 | } |
mattegan | 0:0db835052212 | 92 | } |
mattegan | 0:0db835052212 | 93 | |
mattegan | 0:0db835052212 | 94 | //Protected Methods |
mattegan | 0:0db835052212 | 95 | ////////////////////////////////////////////////////////////////////////////////////////// |
mattegan | 0:0db835052212 | 96 | void lcd::setMode(int _mode) { |
mattegan | 0:0db835052212 | 97 | //since changing the databus mode takes time only do it |
mattegan | 0:0db835052212 | 98 | // if we're not in the mode already, this might be |
mattegan | 0:0db835052212 | 99 | // fuzzy science (read, not actually accurate), but it |
mattegan | 0:0db835052212 | 100 | // can't hurt |
mattegan | 0:0db835052212 | 101 | if(_mode != currentMode) { |
mattegan | 0:0db835052212 | 102 | readWrite = _mode; |
mattegan | 0:0db835052212 | 103 | currentMode = _mode; |
mattegan | 0:0db835052212 | 104 | switch(_mode) { |
mattegan | 0:0db835052212 | 105 | case klcdWriteMode: { |
mattegan | 0:0db835052212 | 106 | dataBus.output(); |
mattegan | 0:0db835052212 | 107 | break; |
mattegan | 0:0db835052212 | 108 | } |
mattegan | 0:0db835052212 | 109 | case klcdReadMode: { |
mattegan | 0:0db835052212 | 110 | dataBus.input(); |
mattegan | 0:0db835052212 | 111 | break; |
mattegan | 0:0db835052212 | 112 | } |
mattegan | 0:0db835052212 | 113 | } |
mattegan | 0:0db835052212 | 114 | } |
mattegan | 0:0db835052212 | 115 | } |
mattegan | 0:0db835052212 | 116 | |
mattegan | 0:0db835052212 | 117 | void lcd::waitUntilNotBusy() { |
mattegan | 0:0db835052212 | 118 | setMode(klcdReadMode); |
mattegan | 0:0db835052212 | 119 | registerSelect = klcdInstructionRegister; |
mattegan | 0:0db835052212 | 120 | wait_us(5); |
mattegan | 0:0db835052212 | 121 | enable = klcdEnableHigh; |
mattegan | 0:0db835052212 | 122 | wait_us(0.5); |
mattegan | 0:0db835052212 | 123 | while(dataBus.read() >> 3) {}; |
mattegan | 0:0db835052212 | 124 | enable = klcdEnableLow; |
mattegan | 0:0db835052212 | 125 | wait_us(0.6); |
mattegan | 0:0db835052212 | 126 | readNibble(klcdInstructionRegister); |
mattegan | 0:0db835052212 | 127 | return; |
mattegan | 0:0db835052212 | 128 | } |
mattegan | 0:0db835052212 | 129 | |
mattegan | 0:0db835052212 | 130 | void lcd::writeByte(int _reg, int _byte, bool _wait) { |
mattegan | 0:0db835052212 | 131 | //write the most significant four bytes first |
mattegan | 0:0db835052212 | 132 | writeNibble(_reg, _byte >> 4); |
mattegan | 0:0db835052212 | 133 | writeNibble(_reg, _byte); |
mattegan | 0:0db835052212 | 134 | if(_wait) { |
mattegan | 0:0db835052212 | 135 | waitUntilNotBusy(); |
mattegan | 0:0db835052212 | 136 | } |
mattegan | 0:0db835052212 | 137 | } |
mattegan | 0:0db835052212 | 138 | |
mattegan | 0:0db835052212 | 139 | //this is useless at the moment, not sure how I want to structure |
mattegan | 0:0db835052212 | 140 | // reading bytes with the four wire interface, as one read is |
mattegan | 0:0db835052212 | 141 | // technically reading the busy flag and internal address counter, |
mattegan | 0:0db835052212 | 142 | // another is actually reading bytes from CGRAM or DDRAM (which isn't |
mattegan | 0:0db835052212 | 143 | // all that useful actually) |
mattegan | 0:0db835052212 | 144 | int lcd::readNibble(int _reg) { |
mattegan | 0:0db835052212 | 145 | setMode(klcdReadMode); |
mattegan | 0:0db835052212 | 146 | registerSelect = _reg; |
mattegan | 0:0db835052212 | 147 | |
mattegan | 0:0db835052212 | 148 | //wait more than 60ns for address set up, then bring enable high |
mattegan | 0:0db835052212 | 149 | wait_us(0.1); |
mattegan | 0:0db835052212 | 150 | enable = klcdEnableHigh; |
mattegan | 0:0db835052212 | 151 | //wait for the enable pulse width to elapse (450ns), by which time the data |
mattegan | 0:0db835052212 | 152 | // should be present on the bus, then bring enable low, and wait |
mattegan | 0:0db835052212 | 153 | // till the end of the enable cycle |
mattegan | 0:0db835052212 | 154 | wait_us(0.5); |
mattegan | 0:0db835052212 | 155 | int nibble = dataBus.read(); |
mattegan | 0:0db835052212 | 156 | enable = klcdEnableLow; |
mattegan | 0:0db835052212 | 157 | wait_us(0.6); |
mattegan | 0:0db835052212 | 158 | return nibble; |
mattegan | 0:0db835052212 | 159 | } |
mattegan | 0:0db835052212 | 160 | |
mattegan | 0:0db835052212 | 161 | //write a four bit nibble onto the bus with correct delays |
mattegan | 0:0db835052212 | 162 | void lcd::writeNibble(int _reg, int _nibble) { |
mattegan | 0:0db835052212 | 163 | setMode(klcdWriteMode); |
mattegan | 0:0db835052212 | 164 | registerSelect = _reg; |
mattegan | 0:0db835052212 | 165 | |
mattegan | 0:0db835052212 | 166 | dataBus = _nibble; |
mattegan | 0:0db835052212 | 167 | //wait for more than 60ns for address set up, then bring enable high |
mattegan | 0:0db835052212 | 168 | wait_us(0.1); |
mattegan | 0:0db835052212 | 169 | enable = klcdEnableHigh; |
mattegan | 0:0db835052212 | 170 | //wait for more than 450ns for enable pulse width, then bring enable low |
mattegan | 0:0db835052212 | 171 | wait_us(0.5); |
mattegan | 0:0db835052212 | 172 | enable = klcdEnableLow; |
mattegan | 0:0db835052212 | 173 | //wait for more than 550ns for the completion of the enable cycle |
mattegan | 0:0db835052212 | 174 | wait_us(0.6); |
mattegan | 0:0db835052212 | 175 | } |
mattegan | 0:0db835052212 | 176 | |
mattegan | 0:0db835052212 | 177 | |
mattegan | 0:0db835052212 | 178 | //Stream Implementation |
mattegan | 0:0db835052212 | 179 | ////////////////////////////////////////////////////////////////////////////////////// |
mattegan | 0:0db835052212 | 180 | int lcd::_putc(int _char) { |
mattegan | 0:0db835052212 | 181 | if(_char == '\n') { |
mattegan | 0:0db835052212 | 182 | column = 0; |
mattegan | 0:0db835052212 | 183 | row = (++row % 2); |
mattegan | 0:0db835052212 | 184 | } else { |
mattegan | 0:0db835052212 | 185 | locateCharacter(row, column, _char); |
mattegan | 0:0db835052212 | 186 | column++; |
mattegan | 0:0db835052212 | 187 | } |
mattegan | 0:0db835052212 | 188 | return _char; |
mattegan | 0:0db835052212 | 189 | } |
mattegan | 0:0db835052212 | 190 | |
mattegan | 0:0db835052212 | 191 | //not respoinding to getc (yet, this would require reading out of the |
mattegan | 0:0db835052212 | 192 | // DDRAM of the display, or caching |
mattegan | 0:0db835052212 | 193 | int lcd::_getc() { |
mattegan | 0:0db835052212 | 194 | return -1; |
mattegan | 0:0db835052212 | 195 | } |
mattegan | 0:0db835052212 | 196 | |
mattegan | 0:0db835052212 | 197 | |
mattegan | 0:0db835052212 | 198 | |
mattegan | 0:0db835052212 | 199 | |
mattegan | 0:0db835052212 | 200 | |
mattegan | 0:0db835052212 | 201 | |
mattegan | 0:0db835052212 | 202 | |
mattegan | 0:0db835052212 | 203 | |
mattegan | 0:0db835052212 | 204 | |
mattegan | 0:0db835052212 | 205 | |
mattegan | 0:0db835052212 | 206 | |
mattegan | 0:0db835052212 | 207 | |
mattegan | 0:0db835052212 | 208 | |
mattegan | 0:0db835052212 | 209 | |
mattegan | 0:0db835052212 | 210 | |
mattegan | 0:0db835052212 | 211 | |
mattegan | 0:0db835052212 | 212 | |
mattegan | 0:0db835052212 | 213 | |
mattegan | 0:0db835052212 | 214 | |
mattegan | 0:0db835052212 | 215 |