Initial commit

Fork of TextLCD by Wim Huiskamp

Committer:
wim
Date:
Mon Feb 04 21:48:24 2013 +0000
Revision:
10:dd9b3a696acd
Parent:
9:0893d986e717
Child:
11:9ec02df863a1
Added support for 24x4 LCDs using KS0078 controller; Added Cursor On/Off

Who changed what in which revision?

UserRevisionLine numberNew contents of line
simon 1:ac48b187213c 1 /* mbed TextLCD Library, for a 4-bit LCD based on HD44780
simon 6:e4cb7ddee0d3 2 * Copyright (c) 2007-2010, sford, http://mbed.org
wim 8:03116f75b66e 3 * 2013, WH, Updated LCD types and fixed lcd address issues
simon 1:ac48b187213c 4 *
simon 1:ac48b187213c 5 * Permission is hereby granted, free of charge, to any person obtaining a copy
simon 1:ac48b187213c 6 * of this software and associated documentation files (the "Software"), to deal
simon 1:ac48b187213c 7 * in the Software without restriction, including without limitation the rights
simon 1:ac48b187213c 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
simon 1:ac48b187213c 9 * copies of the Software, and to permit persons to whom the Software is
simon 1:ac48b187213c 10 * furnished to do so, subject to the following conditions:
simon 1:ac48b187213c 11 *
simon 1:ac48b187213c 12 * The above copyright notice and this permission notice shall be included in
simon 1:ac48b187213c 13 * all copies or substantial portions of the Software.
simon 1:ac48b187213c 14 *
simon 1:ac48b187213c 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
simon 1:ac48b187213c 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
simon 1:ac48b187213c 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
simon 1:ac48b187213c 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
simon 1:ac48b187213c 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 1:ac48b187213c 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
simon 1:ac48b187213c 21 * THE SOFTWARE.
simon 1:ac48b187213c 22 */
simon 1:ac48b187213c 23
simon 1:ac48b187213c 24 #include "TextLCD.h"
simon 1:ac48b187213c 25 #include "mbed.h"
simon 1:ac48b187213c 26
simon 7:44f34c09bd37 27 TextLCD::TextLCD(PinName rs, PinName e, PinName d4, PinName d5,
simon 7:44f34c09bd37 28 PinName d6, PinName d7, LCDType type) : _rs(rs),
simon 7:44f34c09bd37 29 _e(e), _d(d4, d5, d6, d7),
simon 1:ac48b187213c 30 _type(type) {
simon 1:ac48b187213c 31
simon 1:ac48b187213c 32 _e = 1;
simon 1:ac48b187213c 33 _rs = 0; // command mode
simon 1:ac48b187213c 34
simon 1:ac48b187213c 35 wait(0.015); // Wait 15ms to ensure powered up
simon 1:ac48b187213c 36
simon 1:ac48b187213c 37 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
simon 1:ac48b187213c 38 for (int i=0; i<3; i++) {
simon 1:ac48b187213c 39 writeByte(0x3);
simon 1:ac48b187213c 40 wait(0.00164); // this command takes 1.64ms, so wait for it
simon 1:ac48b187213c 41 }
simon 1:ac48b187213c 42 writeByte(0x2); // 4-bit mode
simon 1:ac48b187213c 43 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 44
wim 10:dd9b3a696acd 45 // Display is now in 4-bit mode
wim 10:dd9b3a696acd 46 switch (_type) {
wim 10:dd9b3a696acd 47 case LCD8x1:
wim 10:dd9b3a696acd 48 writeCommand(0x20); // Function set 001 BW N F - -
wim 10:dd9b3a696acd 49 // N=0 (1 line)
wim 10:dd9b3a696acd 50 // F=0 (5x7 dots font)
wim 10:dd9b3a696acd 51 break;
wim 10:dd9b3a696acd 52
wim 10:dd9b3a696acd 53 case LCD24x4:
wim 10:dd9b3a696acd 54 // Special mode for KS0078
wim 10:dd9b3a696acd 55 writeCommand(0x2A); // Function set 001 BW N RE DH REV
wim 10:dd9b3a696acd 56 // N=1 (Dont care for KS0078)
wim 10:dd9b3a696acd 57 // RE=0 (Extended Regs, special mode for KS0078)
wim 10:dd9b3a696acd 58 // DH=1 (Disp shift, special mode for KS0078)
wim 10:dd9b3a696acd 59 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 60
wim 10:dd9b3a696acd 61 writeCommand(0x2E); // Function set 001 BW N RE DH REV
wim 10:dd9b3a696acd 62 // N=1 (Dont care for KS0078)
wim 10:dd9b3a696acd 63 // RE=1 (Ena Extended Regs, special mode for KS0078)
wim 10:dd9b3a696acd 64 // DH=1 (Disp shift, special mode for KS0078)
wim 10:dd9b3a696acd 65 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 66
wim 10:dd9b3a696acd 67 writeCommand(0x09); // Ext Function set 0000 1 FW BW NW
wim 10:dd9b3a696acd 68 // FW=0 (5-dot font, special mode for KS0078)
wim 10:dd9b3a696acd 69 // BW=0 (Cur BW invert disable, special mode for KS0078)
wim 10:dd9b3a696acd 70 // NW=1 (4 Line, special mode for KS0078)
wim 10:dd9b3a696acd 71
wim 10:dd9b3a696acd 72 writeCommand(0x2A); // Function set 001 BW N RE DH REV
wim 10:dd9b3a696acd 73 // N=1 (Dont care for KS0078)
wim 10:dd9b3a696acd 74 // RE=0 (Dis. Extended Regs, special mode for KS0078)
wim 10:dd9b3a696acd 75 // DH=1 (Disp shift, special mode for KS0078)
wim 10:dd9b3a696acd 76 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 77 break;
wim 10:dd9b3a696acd 78
wim 10:dd9b3a696acd 79 default:
wim 10:dd9b3a696acd 80 writeCommand(0x28); // Function set 001 BW N F - -
wim 10:dd9b3a696acd 81 // N=1 (2 lines)
wim 10:dd9b3a696acd 82 // F=0 (5x7 dots font)
wim 10:dd9b3a696acd 83
wim 10:dd9b3a696acd 84 break;
wim 10:dd9b3a696acd 85 }
wim 10:dd9b3a696acd 86
wim 10:dd9b3a696acd 87 writeCommand(0x0C); // Display Ctrl 0000 1 D C B
wim 10:dd9b3a696acd 88 // Display On, Cursor Off, Blink Off
wim 10:dd9b3a696acd 89 _cursor = CurOff;
wim 10:dd9b3a696acd 90
wim 10:dd9b3a696acd 91 writeCommand(0x06); // Entry Mode 0000 01 CD S
wim 10:dd9b3a696acd 92 // Cursor Direction and Display Shift
wim 10:dd9b3a696acd 93 // CD=1 (Cur incr)
wim 10:dd9b3a696acd 94 // S=0 (No display shift)
wim 10:dd9b3a696acd 95
wim 10:dd9b3a696acd 96 cls();
simon 1:ac48b187213c 97 }
simon 1:ac48b187213c 98
wim 8:03116f75b66e 99
simon 1:ac48b187213c 100 void TextLCD::character(int column, int row, int c) {
wim 8:03116f75b66e 101 int addr = getAddress(column, row);
wim 8:03116f75b66e 102
wim 8:03116f75b66e 103 writeCommand(0x80 | addr);
simon 1:ac48b187213c 104 writeData(c);
simon 1:ac48b187213c 105 }
simon 1:ac48b187213c 106
wim 8:03116f75b66e 107
simon 1:ac48b187213c 108 void TextLCD::cls() {
simon 1:ac48b187213c 109 writeCommand(0x01); // cls, and set cursor to 0
simon 1:ac48b187213c 110 wait(0.00164f); // This command takes 1.64 ms
simon 1:ac48b187213c 111 locate(0, 0);
simon 1:ac48b187213c 112 }
simon 1:ac48b187213c 113
simon 1:ac48b187213c 114 void TextLCD::locate(int column, int row) {
simon 1:ac48b187213c 115 _column = column;
simon 1:ac48b187213c 116 _row = row;
simon 1:ac48b187213c 117 }
simon 1:ac48b187213c 118
simon 1:ac48b187213c 119 int TextLCD::_putc(int value) {
simon 1:ac48b187213c 120 if (value == '\n') {
simon 1:ac48b187213c 121 _column = 0;
simon 1:ac48b187213c 122 _row++;
simon 1:ac48b187213c 123 if (_row >= rows()) {
simon 1:ac48b187213c 124 _row = 0;
simon 1:ac48b187213c 125 }
simon 1:ac48b187213c 126 } else {
simon 1:ac48b187213c 127 character(_column, _row, value);
simon 1:ac48b187213c 128 _column++;
simon 1:ac48b187213c 129 if (_column >= columns()) {
simon 1:ac48b187213c 130 _column = 0;
simon 1:ac48b187213c 131 _row++;
simon 1:ac48b187213c 132 if (_row >= rows()) {
simon 1:ac48b187213c 133 _row = 0;
simon 1:ac48b187213c 134 }
simon 1:ac48b187213c 135 }
simon 1:ac48b187213c 136 }
simon 1:ac48b187213c 137 return value;
simon 1:ac48b187213c 138 }
simon 1:ac48b187213c 139
simon 1:ac48b187213c 140 int TextLCD::_getc() {
simon 1:ac48b187213c 141 return -1;
simon 1:ac48b187213c 142 }
simon 1:ac48b187213c 143
simon 1:ac48b187213c 144 void TextLCD::writeByte(int value) {
simon 1:ac48b187213c 145 _d = value >> 4;
simon 1:ac48b187213c 146 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 147 _e = 0;
simon 1:ac48b187213c 148 wait(0.000040f);
simon 1:ac48b187213c 149 _e = 1;
simon 1:ac48b187213c 150 _d = value >> 0;
simon 1:ac48b187213c 151 wait(0.000040f);
simon 1:ac48b187213c 152 _e = 0;
simon 1:ac48b187213c 153 wait(0.000040f); // most instructions take 40us
simon 1:ac48b187213c 154 _e = 1;
simon 1:ac48b187213c 155 }
simon 1:ac48b187213c 156
simon 1:ac48b187213c 157 void TextLCD::writeCommand(int command) {
simon 1:ac48b187213c 158 _rs = 0;
simon 1:ac48b187213c 159 writeByte(command);
simon 1:ac48b187213c 160 }
simon 1:ac48b187213c 161
simon 1:ac48b187213c 162 void TextLCD::writeData(int data) {
simon 1:ac48b187213c 163 _rs = 1;
simon 1:ac48b187213c 164 writeByte(data);
simon 1:ac48b187213c 165 }
simon 1:ac48b187213c 166
wim 8:03116f75b66e 167
wim 8:03116f75b66e 168 #if (0)
wim 8:03116f75b66e 169 // This is the original method.
wim 8:03116f75b66e 170 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
wim 8:03116f75b66e 171 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 172 //
simon 1:ac48b187213c 173 int TextLCD::address(int column, int row) {
simon 1:ac48b187213c 174 switch (_type) {
simon 1:ac48b187213c 175 case LCD20x4:
simon 1:ac48b187213c 176 switch (row) {
simon 1:ac48b187213c 177 case 0:
simon 1:ac48b187213c 178 return 0x80 + column;
simon 1:ac48b187213c 179 case 1:
simon 1:ac48b187213c 180 return 0xc0 + column;
simon 1:ac48b187213c 181 case 2:
simon 1:ac48b187213c 182 return 0x94 + column;
simon 1:ac48b187213c 183 case 3:
simon 1:ac48b187213c 184 return 0xd4 + column;
simon 1:ac48b187213c 185 }
simon 1:ac48b187213c 186 case LCD16x2B:
simon 4:bf5b706f8d32 187 return 0x80 + (row * 40) + column;
simon 1:ac48b187213c 188 case LCD16x2:
simon 1:ac48b187213c 189 case LCD20x2:
simon 1:ac48b187213c 190 default:
simon 4:bf5b706f8d32 191 return 0x80 + (row * 0x40) + column;
simon 1:ac48b187213c 192 }
simon 1:ac48b187213c 193 }
wim 8:03116f75b66e 194 #endif
wim 8:03116f75b66e 195
wim 8:03116f75b66e 196
wim 8:03116f75b66e 197 // This replaces the original method.
wim 8:03116f75b66e 198 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 199 int TextLCD::address(int column, int row) {
wim 8:03116f75b66e 200 return 0x80 | getAddress(column, row);
wim 8:03116f75b66e 201 }
wim 8:03116f75b66e 202
wim 8:03116f75b66e 203 // This is new method to return the memory address based on row, column and displaytype.
wim 8:03116f75b66e 204 //
wim 8:03116f75b66e 205 int TextLCD::getAddress(int column, int row) {
wim 8:03116f75b66e 206
wim 8:03116f75b66e 207 switch (_type) {
wim 8:03116f75b66e 208 case LCD8x1:
wim 8:03116f75b66e 209 return 0x00 + column;
wim 8:03116f75b66e 210
wim 8:03116f75b66e 211 case LCD16x4:
wim 8:03116f75b66e 212 switch (row) {
wim 8:03116f75b66e 213 case 0:
wim 8:03116f75b66e 214 return 0x00 + column;
wim 8:03116f75b66e 215 case 1:
wim 8:03116f75b66e 216 return 0x40 + column;
wim 8:03116f75b66e 217 case 2:
wim 8:03116f75b66e 218 return 0x10 + column;
wim 8:03116f75b66e 219 case 3:
wim 8:03116f75b66e 220 return 0x50 + column;
wim 8:03116f75b66e 221 }
wim 8:03116f75b66e 222
wim 8:03116f75b66e 223 case LCD20x4:
wim 8:03116f75b66e 224 switch (row) {
wim 8:03116f75b66e 225 case 0:
wim 8:03116f75b66e 226 return 0x00 + column;
wim 8:03116f75b66e 227 case 1:
wim 8:03116f75b66e 228 return 0x40 + column;
wim 8:03116f75b66e 229 case 2:
wim 8:03116f75b66e 230 return 0x14 + column;
wim 8:03116f75b66e 231 case 3:
wim 8:03116f75b66e 232 return 0x54 + column;
wim 8:03116f75b66e 233 }
wim 8:03116f75b66e 234
wim 10:dd9b3a696acd 235 // Special mode for KS0078
wim 10:dd9b3a696acd 236 case LCD24x4:
wim 10:dd9b3a696acd 237 switch (row) {
wim 10:dd9b3a696acd 238 case 0:
wim 10:dd9b3a696acd 239 return 0x00 + column;
wim 10:dd9b3a696acd 240 case 1:
wim 10:dd9b3a696acd 241 return 0x20 + column;
wim 10:dd9b3a696acd 242 case 2:
wim 10:dd9b3a696acd 243 return 0x40 + column;
wim 10:dd9b3a696acd 244 case 3:
wim 10:dd9b3a696acd 245 return 0x60 + column;
wim 10:dd9b3a696acd 246 }
wim 10:dd9b3a696acd 247
wim 8:03116f75b66e 248 // Not sure about this one, seems wrong.
wim 8:03116f75b66e 249 case LCD16x2B:
wim 8:03116f75b66e 250 return 0x00 + (row * 40) + column;
wim 8:03116f75b66e 251
wim 8:03116f75b66e 252 case LCD8x2:
wim 8:03116f75b66e 253 case LCD16x2:
wim 8:03116f75b66e 254 case LCD20x2:
wim 8:03116f75b66e 255 case LCD24x2:
wim 9:0893d986e717 256 case LCD40x2:
wim 8:03116f75b66e 257 return 0x00 + (row * 0x40) + column;
wim 8:03116f75b66e 258
wim 8:03116f75b66e 259 // Should never get here.
wim 8:03116f75b66e 260 default:
wim 8:03116f75b66e 261 return 0x00;
wim 8:03116f75b66e 262 }
wim 8:03116f75b66e 263 }
wim 8:03116f75b66e 264
wim 8:03116f75b66e 265
wim 8:03116f75b66e 266 // Added for consistency. Set row, colum and update memoryaddress.
wim 8:03116f75b66e 267 //
wim 8:03116f75b66e 268 void TextLCD::setAddress(int column, int row) {
wim 8:03116f75b66e 269
wim 8:03116f75b66e 270 locate(column, row);
wim 8:03116f75b66e 271
wim 8:03116f75b66e 272 int addr = getAddress(column, row);
wim 8:03116f75b66e 273
wim 8:03116f75b66e 274 writeCommand(0x80 | addr);
wim 8:03116f75b66e 275 }
simon 1:ac48b187213c 276
simon 1:ac48b187213c 277 int TextLCD::columns() {
simon 1:ac48b187213c 278 switch (_type) {
wim 8:03116f75b66e 279 case LCD8x1:
wim 8:03116f75b66e 280 case LCD8x2:
wim 8:03116f75b66e 281 return 8;
wim 8:03116f75b66e 282
simon 1:ac48b187213c 283 case LCD16x2:
simon 1:ac48b187213c 284 case LCD16x2B:
wim 8:03116f75b66e 285 case LCD16x4:
wim 8:03116f75b66e 286 return 16;
wim 8:03116f75b66e 287
wim 8:03116f75b66e 288 case LCD20x2:
wim 8:03116f75b66e 289 case LCD20x4:
wim 8:03116f75b66e 290 return 20;
wim 8:03116f75b66e 291
wim 8:03116f75b66e 292 case LCD24x2:
wim 10:dd9b3a696acd 293 case LCD24x4:
wim 8:03116f75b66e 294 return 24;
wim 9:0893d986e717 295
wim 9:0893d986e717 296 case LCD40x2:
wim 9:0893d986e717 297 return 40;
wim 8:03116f75b66e 298
wim 8:03116f75b66e 299 // Should never get here.
simon 1:ac48b187213c 300 default:
wim 8:03116f75b66e 301 return 0;
simon 1:ac48b187213c 302 }
simon 1:ac48b187213c 303 }
simon 1:ac48b187213c 304
simon 1:ac48b187213c 305 int TextLCD::rows() {
simon 1:ac48b187213c 306 switch (_type) {
wim 8:03116f75b66e 307 case LCD8x1:
wim 8:03116f75b66e 308 return 1;
wim 8:03116f75b66e 309
wim 8:03116f75b66e 310 case LCD8x2:
simon 1:ac48b187213c 311 case LCD16x2:
simon 1:ac48b187213c 312 case LCD16x2B:
simon 1:ac48b187213c 313 case LCD20x2:
wim 8:03116f75b66e 314 case LCD24x2:
wim 9:0893d986e717 315 case LCD40x2:
wim 8:03116f75b66e 316 return 2;
wim 8:03116f75b66e 317
wim 8:03116f75b66e 318 case LCD16x4:
wim 8:03116f75b66e 319 case LCD20x4:
wim 10:dd9b3a696acd 320 case LCD24x4:
wim 8:03116f75b66e 321 return 4;
wim 8:03116f75b66e 322
simon 1:ac48b187213c 323 default:
wim 8:03116f75b66e 324 return 0;
simon 1:ac48b187213c 325 }
simon 1:ac48b187213c 326 }
wim 10:dd9b3a696acd 327
wim 10:dd9b3a696acd 328
wim 10:dd9b3a696acd 329 TextLCD::LCDCursor TextLCD::cursor(TextLCD::LCDCursor show) {
wim 10:dd9b3a696acd 330 LCDCursor cur = _cursor;
wim 10:dd9b3a696acd 331
wim 10:dd9b3a696acd 332 switch (show) {
wim 10:dd9b3a696acd 333 case CurOn : writeCommand(0x0F); // Cursor on and Blink char
wim 10:dd9b3a696acd 334 wait_us(40);
wim 10:dd9b3a696acd 335 _cursor = show;
wim 10:dd9b3a696acd 336 break;
wim 10:dd9b3a696acd 337 case CurOff : writeCommand(0x0C);
wim 10:dd9b3a696acd 338 wait_us(40);
wim 10:dd9b3a696acd 339 _cursor = show;
wim 10:dd9b3a696acd 340 break;
wim 10:dd9b3a696acd 341 default :
wim 10:dd9b3a696acd 342 break;
wim 10:dd9b3a696acd 343
wim 10:dd9b3a696acd 344 }
wim 10:dd9b3a696acd 345 return cur;
wim 10:dd9b3a696acd 346 }
wim 10:dd9b3a696acd 347
wim 10:dd9b3a696acd 348
wim 10:dd9b3a696acd 349
wim 10:dd9b3a696acd 350