A basic basic basic driver for 2x16 HD44780 based displays using the four wire interface.

Dependents:   lcdLibraryTest generado_final

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?

UserRevisionLine numberNew 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