1

Dependents:   Program_R11

Committer:
wim
Date:
Wed Apr 02 17:49:55 2014 +0000
Revision:
22:35742ec80c24
Parent:
21:9eb628d9e164
Child:
23:d47f226efb24
Refactored TextLCD bus version to fix issue with pins default defined as NC.; Note: I2C and SPI versions now need to be declared as TextLCD_I2C() or TextLCD_SPI() in user code.

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 14:0c32b66b14b8 3 * 2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs
wim 14:0c32b66b14b8 4 * 2013, v02: WH, Added I2C and SPI bus interfaces
wim 15:b70ebfffb258 5 * 2013, v03: WH, Added support for LCD40x4 which uses 2 controllers
wim 18:bd65dc10f27f 6 * 2013, v04: WH, Added support for Display On/Off, improved 4bit bootprocess
wim 18:bd65dc10f27f 7 * 2013, v05: WH, Added support for 8x2B, added some UDCs
wim 19:c747b9e2e7b8 8 * 2013, v06: WH, Added support for devices that use internal DC/DC converters
wim 20:e0da005a777f 9 * 2013, v07: WH, Added support for backlight and include portdefinitions for LCD2004 Module from DFROBOT
wim 22:35742ec80c24 10 * 2014, v08: WH, Refactored in Base and Derived Classes to deal with mbed lib change regarding 'NC' defined pins
simon 1:ac48b187213c 11 *
simon 1:ac48b187213c 12 * Permission is hereby granted, free of charge, to any person obtaining a copy
simon 1:ac48b187213c 13 * of this software and associated documentation files (the "Software"), to deal
simon 1:ac48b187213c 14 * in the Software without restriction, including without limitation the rights
simon 1:ac48b187213c 15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
simon 1:ac48b187213c 16 * copies of the Software, and to permit persons to whom the Software is
simon 1:ac48b187213c 17 * furnished to do so, subject to the following conditions:
simon 1:ac48b187213c 18 *
simon 1:ac48b187213c 19 * The above copyright notice and this permission notice shall be included in
simon 1:ac48b187213c 20 * all copies or substantial portions of the Software.
simon 1:ac48b187213c 21 *
simon 1:ac48b187213c 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
simon 1:ac48b187213c 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
simon 1:ac48b187213c 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
simon 1:ac48b187213c 25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
simon 1:ac48b187213c 26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 1:ac48b187213c 27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
simon 1:ac48b187213c 28 * THE SOFTWARE.
simon 1:ac48b187213c 29 */
simon 1:ac48b187213c 30
simon 1:ac48b187213c 31 #include "TextLCD.h"
simon 1:ac48b187213c 32 #include "mbed.h"
simon 1:ac48b187213c 33
wim 21:9eb628d9e164 34 /** Create a TextLCD_Base interface
wim 15:b70ebfffb258 35 *
wim 21:9eb628d9e164 36 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 37 * @param ctrl LCD controller (default = HD44780)
wim 15:b70ebfffb258 38 */
wim 21:9eb628d9e164 39 TextLCD_Base::TextLCD_Base(LCDType type, LCDCtrl ctrl) : _type(type), _ctrl(ctrl) {
wim 14:0c32b66b14b8 40 }
wim 14:0c32b66b14b8 41
wim 14:0c32b66b14b8 42
wim 21:9eb628d9e164 43 /** Init the LCD Controller(s)
wim 21:9eb628d9e164 44 * Clear display
wim 21:9eb628d9e164 45 */
wim 21:9eb628d9e164 46 void TextLCD_Base::_init() {
wim 15:b70ebfffb258 47
wim 15:b70ebfffb258 48 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 49 if(_type==LCD40x4) {
wim 21:9eb628d9e164 50 _ctrl_idx=_LCDCtrl_1; // Select 2nd controller
wim 15:b70ebfffb258 51
wim 19:c747b9e2e7b8 52 _initCtrl(); // Init 2nd controller
wim 15:b70ebfffb258 53
wim 15:b70ebfffb258 54 // Secondary LCD controller Clearscreen
wim 15:b70ebfffb258 55 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 56 wait_ms(10); // The CLS command takes 1.64 ms.
wim 15:b70ebfffb258 57 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 58
wim 15:b70ebfffb258 59 }
wim 15:b70ebfffb258 60
wim 15:b70ebfffb258 61 // Select and configure primary LCD controller
wim 21:9eb628d9e164 62 _ctrl_idx=_LCDCtrl_0; // Select primary controller
wim 13:24506ba22480 63
wim 19:c747b9e2e7b8 64 _initCtrl(); // Init primary controller
wim 15:b70ebfffb258 65
wim 15:b70ebfffb258 66 // Primary LCD controller Clearscreen
wim 15:b70ebfffb258 67 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 68
wim 15:b70ebfffb258 69 wait_ms(10); // The CLS command takes 1.64 ms.
wim 15:b70ebfffb258 70 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 71
wim 15:b70ebfffb258 72 }
wim 15:b70ebfffb258 73
wim 21:9eb628d9e164 74 /** Init the LCD controller
wim 21:9eb628d9e164 75 * 4-bit mode, number of lines, fonttype, no cursor etc
wim 21:9eb628d9e164 76 *
wim 21:9eb628d9e164 77 */
wim 21:9eb628d9e164 78 void TextLCD_Base::_initCtrl() {
wim 15:b70ebfffb258 79
wim 21:9eb628d9e164 80 this->_setRS(false); // command mode
wim 13:24506ba22480 81
wim 15:b70ebfffb258 82 wait_ms(20); // Wait 20ms to ensure powered up
simon 1:ac48b187213c 83
wim 17:652ab113bc2e 84 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
wim 17:652ab113bc2e 85 for (int i=0; i<3; i++) {
wim 17:652ab113bc2e 86 _writeNibble(0x3);
wim 20:e0da005a777f 87 wait_ms(15); // This command takes 1.64ms, so wait for it
wim 17:652ab113bc2e 88 }
wim 17:652ab113bc2e 89 _writeNibble(0x2); // 4-bit mode
wim 17:652ab113bc2e 90 wait_us(40); // most instructions take 40us
wim 18:bd65dc10f27f 91
wim 18:bd65dc10f27f 92 // Display is now in 4-bit mode
wim 18:bd65dc10f27f 93
wim 19:c747b9e2e7b8 94
wim 19:c747b9e2e7b8 95 // Device specific initialisations for DC/DC converter to generate VLCD or VLED
wim 19:c747b9e2e7b8 96 switch (_ctrl) {
wim 20:e0da005a777f 97 case ST7036:
wim 19:c747b9e2e7b8 98 // ST7036 controller: Initialise Voltage booster for VLCD. VDD=5V
wim 19:c747b9e2e7b8 99 // Note: supports 1,2 or 3 lines
wim 19:c747b9e2e7b8 100 _writeByte( 0x29 ); // 4-bit Databus, 2 Lines, Select Instruction table 1
wim 20:e0da005a777f 101 wait_ms(30); // > 26,3ms
wim 19:c747b9e2e7b8 102 _writeByte( 0x14 ); // Bias: 1/5, 2-Lines LCD
wim 20:e0da005a777f 103 wait_ms(30); // > 26,3ms
wim 19:c747b9e2e7b8 104 _writeByte( 0x55 ); // Icon off, Booster on, Set Contrast C5, C4
wim 20:e0da005a777f 105 wait_ms(30); // > 26,3ms
wim 19:c747b9e2e7b8 106 _writeByte( 0x6d ); // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
wim 19:c747b9e2e7b8 107 wait_ms(200); // > 200ms!
wim 19:c747b9e2e7b8 108 _writeByte( 0x78 ); // Set Contrast C3, C2, C1, C0
wim 20:e0da005a777f 109 wait_ms(30); // > 26,3ms
wim 19:c747b9e2e7b8 110 _writeByte( 0x28 ); // Return to Instruction table 0
wim 19:c747b9e2e7b8 111 wait_ms(50);
wim 19:c747b9e2e7b8 112
wim 19:c747b9e2e7b8 113 break;
wim 19:c747b9e2e7b8 114
wim 19:c747b9e2e7b8 115 case WS0010:
wim 19:c747b9e2e7b8 116 // WS0010 OLED controller: Initialise DC/DC Voltage converter for LEDs
wim 19:c747b9e2e7b8 117 // Note: supports 1 or 2 lines (and 16x100 graphics)
wim 19:c747b9e2e7b8 118 // supports 4 fonts (English/Japanese (default), Western European-I, English/Russian, Western European-II)
wim 19:c747b9e2e7b8 119
wim 19:c747b9e2e7b8 120 // Cursor/Disp shift set 0001 SC RL 0 0
wim 19:c747b9e2e7b8 121 //
wim 19:c747b9e2e7b8 122 // Mode en Power set 0001 GC PWR 1 1
wim 19:c747b9e2e7b8 123 // GC = 0 (Graph Mode=1, Char Mode=0)
wim 19:c747b9e2e7b8 124 // PWR = (DC/DC On/Off)
wim 19:c747b9e2e7b8 125
wim 19:c747b9e2e7b8 126 //_writeCommand(0x13); // DC/DC off
wim 19:c747b9e2e7b8 127
wim 19:c747b9e2e7b8 128 _writeCommand(0x17); // DC/DC on
wim 19:c747b9e2e7b8 129 wait_ms(10);
wim 19:c747b9e2e7b8 130
wim 19:c747b9e2e7b8 131 break;
wim 19:c747b9e2e7b8 132
wim 19:c747b9e2e7b8 133 default:
wim 19:c747b9e2e7b8 134 // Devices that do not use DC/DC Voltage converters but external VLCD
wim 19:c747b9e2e7b8 135 break;
wim 19:c747b9e2e7b8 136 }
wim 14:0c32b66b14b8 137
wim 18:bd65dc10f27f 138 // Initialise Display configuration
wim 10:dd9b3a696acd 139 switch (_type) {
wim 10:dd9b3a696acd 140 case LCD8x1:
wim 18:bd65dc10f27f 141 case LCD8x2B:
wim 18:bd65dc10f27f 142 //8x1 is a regular 1 line display
wim 18:bd65dc10f27f 143 //8x2B is a special case of 16x1
wim 15:b70ebfffb258 144 _writeCommand(0x20); // Function set 001 DL N F - -
wim 15:b70ebfffb258 145 // DL=0 (4 bits bus)
wim 13:24506ba22480 146 // N=0 (1 line)
wim 13:24506ba22480 147 // F=0 (5x7 dots font)
wim 10:dd9b3a696acd 148 break;
wim 10:dd9b3a696acd 149
wim 10:dd9b3a696acd 150 case LCD24x4:
wim 10:dd9b3a696acd 151 // Special mode for KS0078
wim 15:b70ebfffb258 152 _writeCommand(0x2A); // Function set 001 DL N RE DH REV
wim 15:b70ebfffb258 153 // DL=0 (4 bits bus)
wim 13:24506ba22480 154 // N=1 (Dont care for KS0078)
wim 13:24506ba22480 155 // RE=0 (Extended Regs, special mode for KS0078)
wim 13:24506ba22480 156 // DH=1 (Disp shift, special mode for KS0078)
wim 13:24506ba22480 157 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 158
wim 15:b70ebfffb258 159 _writeCommand(0x2E); // Function set 001 DL N RE DH REV
wim 15:b70ebfffb258 160 // DL=0 (4 bits bus)
wim 13:24506ba22480 161 // N=1 (Dont care for KS0078)
wim 13:24506ba22480 162 // RE=1 (Ena Extended Regs, special mode for KS0078)
wim 13:24506ba22480 163 // DH=1 (Disp shift, special mode for KS0078)
wim 13:24506ba22480 164 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 165
wim 13:24506ba22480 166 _writeCommand(0x09); // Ext Function set 0000 1 FW BW NW
wim 13:24506ba22480 167 // FW=0 (5-dot font, special mode for KS0078)
wim 13:24506ba22480 168 // BW=0 (Cur BW invert disable, special mode for KS0078)
wim 13:24506ba22480 169 // NW=1 (4 Line, special mode for KS0078)
wim 10:dd9b3a696acd 170
wim 15:b70ebfffb258 171 _writeCommand(0x2A); // Function set 001 DL N RE DH REV
wim 15:b70ebfffb258 172 // DL=0 (4 bits bus)
wim 13:24506ba22480 173 // N=1 (Dont care for KS0078)
wim 13:24506ba22480 174 // RE=0 (Dis. Extended Regs, special mode for KS0078)
wim 13:24506ba22480 175 // DH=1 (Disp shift, special mode for KS0078)
wim 13:24506ba22480 176 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 177 break;
wim 10:dd9b3a696acd 178
wim 15:b70ebfffb258 179 // All other LCD types are initialised as 2 Line displays (including LCD40x4)
wim 10:dd9b3a696acd 180 default:
wim 15:b70ebfffb258 181 _writeCommand(0x28); // Function set 001 DL N F - -
wim 15:b70ebfffb258 182 // DL=0 (4 bits bus)
wim 13:24506ba22480 183 // N=1 (2 lines)
wim 15:b70ebfffb258 184 // F=0 (5x7 dots font, only option for 2 line display)
wim 13:24506ba22480 185 // - (Don't care)
wim 10:dd9b3a696acd 186
wim 10:dd9b3a696acd 187 break;
wim 10:dd9b3a696acd 188 }
wim 10:dd9b3a696acd 189
wim 13:24506ba22480 190 _writeCommand(0x06); // Entry Mode 0000 01 CD S
wim 13:24506ba22480 191 // Cursor Direction and Display Shift
wim 13:24506ba22480 192 // CD=1 (Cur incr)
wim 13:24506ba22480 193 // S=0 (No display shift)
wim 10:dd9b3a696acd 194
wim 13:24506ba22480 195 // _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
wim 17:652ab113bc2e 196 // // Display On, Cursor Off, Blink Off
wim 21:9eb628d9e164 197 setCursor(CurOff_BlkOff);
wim 21:9eb628d9e164 198 setMode(DispOn);
simon 1:ac48b187213c 199 }
simon 1:ac48b187213c 200
wim 8:03116f75b66e 201
wim 21:9eb628d9e164 202 /** Clear the screen, Cursor home.
wim 21:9eb628d9e164 203 */
wim 21:9eb628d9e164 204 void TextLCD_Base::cls() {
wim 15:b70ebfffb258 205
wim 15:b70ebfffb258 206 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 207 if(_type==LCD40x4) {
wim 21:9eb628d9e164 208 _ctrl_idx=_LCDCtrl_1; // Select 2nd controller
wim 15:b70ebfffb258 209
wim 15:b70ebfffb258 210 // Second LCD controller Cursor always Off
wim 21:9eb628d9e164 211 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 212
wim 15:b70ebfffb258 213 // Second LCD controller Clearscreen
wim 15:b70ebfffb258 214 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 215
wim 15:b70ebfffb258 216 wait_ms(10); // The CLS command takes 1.64 ms.
wim 15:b70ebfffb258 217 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 218
wim 15:b70ebfffb258 219
wim 21:9eb628d9e164 220 _ctrl_idx=_LCDCtrl_0; // Select primary controller
wim 15:b70ebfffb258 221 }
wim 15:b70ebfffb258 222
wim 15:b70ebfffb258 223 // Primary LCD controller Clearscreen
wim 15:b70ebfffb258 224 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 225
wim 15:b70ebfffb258 226 wait_ms(10); // The CLS command takes 1.64 ms.
wim 15:b70ebfffb258 227 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 228
wim 15:b70ebfffb258 229 // Restore cursormode on primary LCD controller when needed
wim 15:b70ebfffb258 230 if(_type==LCD40x4) {
wim 17:652ab113bc2e 231 _setCursorAndDisplayMode(_currentMode,_currentCursor);
wim 15:b70ebfffb258 232 }
wim 15:b70ebfffb258 233
wim 15:b70ebfffb258 234 _row=0; // Reset Cursor location
wim 15:b70ebfffb258 235 _column=0;
simon 1:ac48b187213c 236 }
simon 1:ac48b187213c 237
wim 21:9eb628d9e164 238 /** Move cursor to selected row and column
wim 21:9eb628d9e164 239 */
wim 21:9eb628d9e164 240 void TextLCD_Base::locate(int column, int row) {
wim 15:b70ebfffb258 241
wim 15:b70ebfffb258 242 // setAddress() does all the heavy lifting:
wim 15:b70ebfffb258 243 // check column and row sanity,
wim 15:b70ebfffb258 244 // switch controllers for LCD40x4 if needed
wim 15:b70ebfffb258 245 // switch cursor for LCD40x4 if needed
wim 15:b70ebfffb258 246 // set the new memory address to show cursor at correct location
wim 15:b70ebfffb258 247 setAddress(column, row);
wim 15:b70ebfffb258 248
wim 15:b70ebfffb258 249 }
wim 15:b70ebfffb258 250
wim 15:b70ebfffb258 251
wim 21:9eb628d9e164 252 /** Write a single character (Stream implementation)
wim 21:9eb628d9e164 253 */
wim 21:9eb628d9e164 254 int TextLCD_Base::_putc(int value) {
wim 15:b70ebfffb258 255 int addr;
wim 15:b70ebfffb258 256
wim 15:b70ebfffb258 257 if (value == '\n') {
wim 15:b70ebfffb258 258 //No character to write
wim 15:b70ebfffb258 259
wim 15:b70ebfffb258 260 //Update Cursor
wim 15:b70ebfffb258 261 _column = 0;
wim 15:b70ebfffb258 262 _row++;
wim 15:b70ebfffb258 263 if (_row >= rows()) {
wim 15:b70ebfffb258 264 _row = 0;
wim 15:b70ebfffb258 265 }
wim 15:b70ebfffb258 266 }
wim 15:b70ebfffb258 267 else {
wim 15:b70ebfffb258 268 //Character to write
wim 15:b70ebfffb258 269 _writeData(value);
wim 15:b70ebfffb258 270
wim 15:b70ebfffb258 271 //Update Cursor
wim 15:b70ebfffb258 272 _column++;
wim 15:b70ebfffb258 273 if (_column >= columns()) {
wim 15:b70ebfffb258 274 _column = 0;
wim 15:b70ebfffb258 275 _row++;
wim 15:b70ebfffb258 276 if (_row >= rows()) {
wim 15:b70ebfffb258 277 _row = 0;
wim 15:b70ebfffb258 278 }
wim 15:b70ebfffb258 279 }
wim 15:b70ebfffb258 280 } //else
wim 15:b70ebfffb258 281
wim 15:b70ebfffb258 282 //Set next memoryaddress, make sure cursor blinks at next location
wim 15:b70ebfffb258 283 addr = getAddress(_column, _row);
wim 15:b70ebfffb258 284 _writeCommand(0x80 | addr);
wim 15:b70ebfffb258 285
wim 15:b70ebfffb258 286 return value;
wim 15:b70ebfffb258 287 }
wim 15:b70ebfffb258 288
wim 15:b70ebfffb258 289
wim 16:c276b75e6585 290 // get a single character (Stream implementation)
wim 21:9eb628d9e164 291 int TextLCD_Base::_getc() {
simon 1:ac48b187213c 292 return -1;
simon 1:ac48b187213c 293 }
simon 1:ac48b187213c 294
wim 14:0c32b66b14b8 295
wim 17:652ab113bc2e 296 // Write a nibble using the 4-bit interface
wim 21:9eb628d9e164 297 void TextLCD_Base::_writeNibble(int value) {
wim 17:652ab113bc2e 298
wim 17:652ab113bc2e 299 // Enable is Low
wim 21:9eb628d9e164 300 this->_setEnable(true);
wim 21:9eb628d9e164 301 this->_setData(value & 0x0F); // Low nibble
wim 17:652ab113bc2e 302 wait_us(1); // Data setup time
wim 21:9eb628d9e164 303 this->_setEnable(false);
wim 17:652ab113bc2e 304 wait_us(1); // Datahold time
wim 17:652ab113bc2e 305
wim 17:652ab113bc2e 306 // Enable is Low
wim 17:652ab113bc2e 307
wim 17:652ab113bc2e 308 }
wim 17:652ab113bc2e 309
wim 17:652ab113bc2e 310
wim 16:c276b75e6585 311 // Write a byte using the 4-bit interface
wim 21:9eb628d9e164 312 void TextLCD_Base::_writeByte(int value) {
wim 15:b70ebfffb258 313
wim 15:b70ebfffb258 314 // Enable is Low
wim 21:9eb628d9e164 315 this->_setEnable(true);
wim 21:9eb628d9e164 316 this->_setData(value >> 4); // High nibble
wim 15:b70ebfffb258 317 wait_us(1); // Data setup time
wim 21:9eb628d9e164 318 this->_setEnable(false);
wim 15:b70ebfffb258 319 wait_us(1); // Data hold time
wim 15:b70ebfffb258 320
wim 21:9eb628d9e164 321 this->_setEnable(true);
wim 21:9eb628d9e164 322 this->_setData(value >> 0); // Low nibble
wim 15:b70ebfffb258 323 wait_us(1); // Data setup time
wim 21:9eb628d9e164 324 this->_setEnable(false);
wim 15:b70ebfffb258 325 wait_us(1); // Datahold time
wim 15:b70ebfffb258 326
wim 15:b70ebfffb258 327 // Enable is Low
wim 15:b70ebfffb258 328
simon 1:ac48b187213c 329 }
simon 1:ac48b187213c 330
wim 21:9eb628d9e164 331 // Write a command byte to the LCD controller
wim 21:9eb628d9e164 332 void TextLCD_Base::_writeCommand(int command) {
wim 15:b70ebfffb258 333
wim 21:9eb628d9e164 334 this->_setRS(false);
wim 16:c276b75e6585 335 wait_us(1); // Data setup time for RS
wim 15:b70ebfffb258 336
wim 21:9eb628d9e164 337 this->_writeByte(command);
wim 15:b70ebfffb258 338 wait_us(40); // most instructions take 40us
simon 1:ac48b187213c 339 }
simon 1:ac48b187213c 340
wim 21:9eb628d9e164 341 // Write a data byte to the LCD controller
wim 21:9eb628d9e164 342 void TextLCD_Base::_writeData(int data) {
wim 15:b70ebfffb258 343
wim 21:9eb628d9e164 344 this->_setRS(true);
wim 16:c276b75e6585 345 wait_us(1); // Data setup time for RS
wim 15:b70ebfffb258 346
wim 21:9eb628d9e164 347 this->_writeByte(data);
wim 15:b70ebfffb258 348 wait_us(40); // data writes take 40us
simon 1:ac48b187213c 349 }
simon 1:ac48b187213c 350
wim 8:03116f75b66e 351
wim 8:03116f75b66e 352 #if (0)
wim 16:c276b75e6585 353 // This is the original _address() method.
wim 8:03116f75b66e 354 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
wim 8:03116f75b66e 355 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 356 //
wim 21:9eb628d9e164 357 int TextLCD_Base::_address(int column, int row) {
simon 1:ac48b187213c 358 switch (_type) {
simon 1:ac48b187213c 359 case LCD20x4:
simon 1:ac48b187213c 360 switch (row) {
simon 1:ac48b187213c 361 case 0:
simon 1:ac48b187213c 362 return 0x80 + column;
simon 1:ac48b187213c 363 case 1:
simon 1:ac48b187213c 364 return 0xc0 + column;
simon 1:ac48b187213c 365 case 2:
simon 1:ac48b187213c 366 return 0x94 + column;
simon 1:ac48b187213c 367 case 3:
simon 1:ac48b187213c 368 return 0xd4 + column;
simon 1:ac48b187213c 369 }
simon 1:ac48b187213c 370 case LCD16x2B:
simon 4:bf5b706f8d32 371 return 0x80 + (row * 40) + column;
simon 1:ac48b187213c 372 case LCD16x2:
simon 1:ac48b187213c 373 case LCD20x2:
simon 1:ac48b187213c 374 default:
simon 4:bf5b706f8d32 375 return 0x80 + (row * 0x40) + column;
simon 1:ac48b187213c 376 }
simon 1:ac48b187213c 377 }
wim 8:03116f75b66e 378 #endif
wim 8:03116f75b66e 379
wim 8:03116f75b66e 380
wim 16:c276b75e6585 381 // This replaces the original _address() method.
wim 8:03116f75b66e 382 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 21:9eb628d9e164 383 int TextLCD_Base::_address(int column, int row) {
wim 8:03116f75b66e 384 return 0x80 | getAddress(column, row);
wim 8:03116f75b66e 385 }
wim 8:03116f75b66e 386
wim 8:03116f75b66e 387 // This is new method to return the memory address based on row, column and displaytype.
wim 8:03116f75b66e 388 //
wim 21:9eb628d9e164 389 int TextLCD_Base::getAddress(int column, int row) {
wim 8:03116f75b66e 390
wim 8:03116f75b66e 391 switch (_type) {
wim 8:03116f75b66e 392 case LCD8x1:
wim 8:03116f75b66e 393 return 0x00 + column;
wim 18:bd65dc10f27f 394
wim 18:bd65dc10f27f 395 case LCD8x2B:
wim 18:bd65dc10f27f 396 // LCD8x2B is a special layout of LCD16x1
wim 18:bd65dc10f27f 397 if (row==0)
wim 18:bd65dc10f27f 398 return 0x00 + column;
wim 18:bd65dc10f27f 399 else
wim 18:bd65dc10f27f 400 return 0x08 + column;
wim 18:bd65dc10f27f 401
wim 18:bd65dc10f27f 402
wim 13:24506ba22480 403 case LCD16x1:
wim 13:24506ba22480 404 // LCD16x1 is a special layout of LCD8x2
wim 13:24506ba22480 405 if (column<8)
wim 13:24506ba22480 406 return 0x00 + column;
wim 13:24506ba22480 407 else
wim 13:24506ba22480 408 return 0x40 + (column - 8);
wim 13:24506ba22480 409
wim 15:b70ebfffb258 410 case LCD12x4:
wim 15:b70ebfffb258 411 switch (row) {
wim 15:b70ebfffb258 412 case 0:
wim 15:b70ebfffb258 413 return 0x00 + column;
wim 15:b70ebfffb258 414 case 1:
wim 15:b70ebfffb258 415 return 0x40 + column;
wim 15:b70ebfffb258 416 case 2:
wim 15:b70ebfffb258 417 return 0x0C + column;
wim 15:b70ebfffb258 418 case 3:
wim 15:b70ebfffb258 419 return 0x4C + column;
wim 15:b70ebfffb258 420 }
wim 15:b70ebfffb258 421
wim 8:03116f75b66e 422 case LCD16x4:
wim 8:03116f75b66e 423 switch (row) {
wim 8:03116f75b66e 424 case 0:
wim 8:03116f75b66e 425 return 0x00 + column;
wim 8:03116f75b66e 426 case 1:
wim 8:03116f75b66e 427 return 0x40 + column;
wim 8:03116f75b66e 428 case 2:
wim 8:03116f75b66e 429 return 0x10 + column;
wim 8:03116f75b66e 430 case 3:
wim 8:03116f75b66e 431 return 0x50 + column;
wim 8:03116f75b66e 432 }
wim 8:03116f75b66e 433
wim 8:03116f75b66e 434 case LCD20x4:
wim 8:03116f75b66e 435 switch (row) {
wim 8:03116f75b66e 436 case 0:
wim 8:03116f75b66e 437 return 0x00 + column;
wim 8:03116f75b66e 438 case 1:
wim 8:03116f75b66e 439 return 0x40 + column;
wim 8:03116f75b66e 440 case 2:
wim 8:03116f75b66e 441 return 0x14 + column;
wim 8:03116f75b66e 442 case 3:
wim 8:03116f75b66e 443 return 0x54 + column;
wim 8:03116f75b66e 444 }
wim 8:03116f75b66e 445
wim 10:dd9b3a696acd 446 // Special mode for KS0078
wim 10:dd9b3a696acd 447 case LCD24x4:
wim 10:dd9b3a696acd 448 switch (row) {
wim 10:dd9b3a696acd 449 case 0:
wim 10:dd9b3a696acd 450 return 0x00 + column;
wim 10:dd9b3a696acd 451 case 1:
wim 10:dd9b3a696acd 452 return 0x20 + column;
wim 10:dd9b3a696acd 453 case 2:
wim 10:dd9b3a696acd 454 return 0x40 + column;
wim 10:dd9b3a696acd 455 case 3:
wim 10:dd9b3a696acd 456 return 0x60 + column;
wim 10:dd9b3a696acd 457 }
wim 10:dd9b3a696acd 458
wim 8:03116f75b66e 459 // Not sure about this one, seems wrong.
wim 8:03116f75b66e 460 case LCD16x2B:
wim 8:03116f75b66e 461 return 0x00 + (row * 40) + column;
wim 8:03116f75b66e 462
wim 18:bd65dc10f27f 463 case LCD8x2:
wim 15:b70ebfffb258 464 case LCD12x2:
wim 8:03116f75b66e 465 case LCD16x2:
wim 8:03116f75b66e 466 case LCD20x2:
wim 8:03116f75b66e 467 case LCD24x2:
wim 9:0893d986e717 468 case LCD40x2:
wim 8:03116f75b66e 469 return 0x00 + (row * 0x40) + column;
wim 15:b70ebfffb258 470
wim 15:b70ebfffb258 471 case LCD40x4:
wim 15:b70ebfffb258 472 // LCD40x4 is a special case since it has 2 controllers
wim 15:b70ebfffb258 473 // Each controller is configured as 40x2
wim 15:b70ebfffb258 474 if (row<2) {
wim 15:b70ebfffb258 475 // Test to see if we need to switch between controllers
wim 19:c747b9e2e7b8 476 if (_ctrl_idx != _LCDCtrl_0) {
wim 17:652ab113bc2e 477
wim 15:b70ebfffb258 478 // Second LCD controller Cursor Off
wim 21:9eb628d9e164 479 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 480
wim 15:b70ebfffb258 481 // Select primary controller
wim 19:c747b9e2e7b8 482 _ctrl_idx = _LCDCtrl_0;
wim 15:b70ebfffb258 483
wim 15:b70ebfffb258 484 // Restore cursormode on primary LCD controller
wim 17:652ab113bc2e 485 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 486 }
wim 15:b70ebfffb258 487
wim 15:b70ebfffb258 488 return 0x00 + (row * 0x40) + column;
wim 15:b70ebfffb258 489 }
wim 15:b70ebfffb258 490 else {
wim 15:b70ebfffb258 491
wim 15:b70ebfffb258 492 // Test to see if we need to switch between controllers
wim 19:c747b9e2e7b8 493 if (_ctrl_idx != _LCDCtrl_1) {
wim 15:b70ebfffb258 494 // Primary LCD controller Cursor Off
wim 21:9eb628d9e164 495 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 496
wim 15:b70ebfffb258 497 // Select secondary controller
wim 19:c747b9e2e7b8 498 _ctrl_idx = _LCDCtrl_1;
wim 15:b70ebfffb258 499
wim 15:b70ebfffb258 500 // Restore cursormode on secondary LCD controller
wim 17:652ab113bc2e 501 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 502 }
wim 15:b70ebfffb258 503
wim 15:b70ebfffb258 504 return 0x00 + ((row-2) * 0x40) + column;
wim 15:b70ebfffb258 505 }
wim 8:03116f75b66e 506
wim 8:03116f75b66e 507 // Should never get here.
wim 8:03116f75b66e 508 default:
wim 8:03116f75b66e 509 return 0x00;
wim 8:03116f75b66e 510 }
wim 8:03116f75b66e 511 }
wim 8:03116f75b66e 512
wim 8:03116f75b66e 513
wim 15:b70ebfffb258 514 // Set row, column and update memoryaddress.
wim 8:03116f75b66e 515 //
wim 21:9eb628d9e164 516 void TextLCD_Base::setAddress(int column, int row) {
wim 15:b70ebfffb258 517
wim 15:b70ebfffb258 518 // Sanity Check column
wim 15:b70ebfffb258 519 if (column < 0) {
wim 15:b70ebfffb258 520 _column = 0;
wim 15:b70ebfffb258 521 }
wim 15:b70ebfffb258 522 else if (column >= columns()) {
wim 15:b70ebfffb258 523 _column = columns() - 1;
wim 15:b70ebfffb258 524 } else _column = column;
wim 8:03116f75b66e 525
wim 15:b70ebfffb258 526 // Sanity Check row
wim 15:b70ebfffb258 527 if (row < 0) {
wim 15:b70ebfffb258 528 _row = 0;
wim 15:b70ebfffb258 529 }
wim 15:b70ebfffb258 530 else if (row >= rows()) {
wim 15:b70ebfffb258 531 _row = rows() - 1;
wim 15:b70ebfffb258 532 } else _row = row;
wim 15:b70ebfffb258 533
wim 15:b70ebfffb258 534
wim 15:b70ebfffb258 535 // Compute the memory address
wim 15:b70ebfffb258 536 // For LCD40x4: switch controllers if needed
wim 15:b70ebfffb258 537 // switch cursor if needed
wim 15:b70ebfffb258 538 int addr = getAddress(_column, _row);
wim 8:03116f75b66e 539
wim 13:24506ba22480 540 _writeCommand(0x80 | addr);
wim 8:03116f75b66e 541 }
simon 1:ac48b187213c 542
wim 21:9eb628d9e164 543 int TextLCD_Base::columns() {
simon 1:ac48b187213c 544 switch (_type) {
wim 8:03116f75b66e 545 case LCD8x1:
wim 8:03116f75b66e 546 case LCD8x2:
wim 18:bd65dc10f27f 547 case LCD8x2B:
wim 8:03116f75b66e 548 return 8;
wim 15:b70ebfffb258 549
wim 15:b70ebfffb258 550 case LCD12x2:
wim 15:b70ebfffb258 551 case LCD12x4:
wim 15:b70ebfffb258 552 return 12;
wim 8:03116f75b66e 553
wim 13:24506ba22480 554 case LCD16x1:
simon 1:ac48b187213c 555 case LCD16x2:
simon 1:ac48b187213c 556 case LCD16x2B:
wim 8:03116f75b66e 557 case LCD16x4:
wim 8:03116f75b66e 558 return 16;
wim 8:03116f75b66e 559
wim 8:03116f75b66e 560 case LCD20x2:
wim 8:03116f75b66e 561 case LCD20x4:
wim 8:03116f75b66e 562 return 20;
wim 8:03116f75b66e 563
wim 8:03116f75b66e 564 case LCD24x2:
wim 10:dd9b3a696acd 565 case LCD24x4:
wim 8:03116f75b66e 566 return 24;
wim 9:0893d986e717 567
wim 9:0893d986e717 568 case LCD40x2:
wim 15:b70ebfffb258 569 case LCD40x4:
wim 9:0893d986e717 570 return 40;
wim 8:03116f75b66e 571
wim 8:03116f75b66e 572 // Should never get here.
simon 1:ac48b187213c 573 default:
wim 8:03116f75b66e 574 return 0;
simon 1:ac48b187213c 575 }
simon 1:ac48b187213c 576 }
simon 1:ac48b187213c 577
wim 21:9eb628d9e164 578 int TextLCD_Base::rows() {
simon 1:ac48b187213c 579 switch (_type) {
wim 8:03116f75b66e 580 case LCD8x1:
wim 13:24506ba22480 581 case LCD16x1:
wim 8:03116f75b66e 582 return 1;
wim 8:03116f75b66e 583
wim 15:b70ebfffb258 584 case LCD8x2:
wim 18:bd65dc10f27f 585 case LCD8x2B:
wim 15:b70ebfffb258 586 case LCD12x2:
simon 1:ac48b187213c 587 case LCD16x2:
simon 1:ac48b187213c 588 case LCD16x2B:
simon 1:ac48b187213c 589 case LCD20x2:
wim 8:03116f75b66e 590 case LCD24x2:
wim 9:0893d986e717 591 case LCD40x2:
wim 8:03116f75b66e 592 return 2;
wim 8:03116f75b66e 593
wim 15:b70ebfffb258 594 case LCD12x4:
wim 8:03116f75b66e 595 case LCD16x4:
wim 8:03116f75b66e 596 case LCD20x4:
wim 10:dd9b3a696acd 597 case LCD24x4:
wim 15:b70ebfffb258 598 case LCD40x4:
wim 8:03116f75b66e 599 return 4;
wim 12:6bf9d9957d31 600
wim 12:6bf9d9957d31 601 // Should never get here.
simon 1:ac48b187213c 602 default:
wim 8:03116f75b66e 603 return 0;
simon 1:ac48b187213c 604 }
simon 1:ac48b187213c 605 }
wim 10:dd9b3a696acd 606
wim 10:dd9b3a696acd 607
wim 17:652ab113bc2e 608 // Set the Cursor Mode (Cursor Off & Blink Off, Cursor On & Blink Off, Cursor Off & Blink On, Cursor On & Blink On
wim 21:9eb628d9e164 609 void TextLCD_Base::setCursor(LCDCursor cursorMode) {
wim 15:b70ebfffb258 610
wim 17:652ab113bc2e 611 // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on
wim 17:652ab113bc2e 612 _currentCursor = cursorMode;
wim 10:dd9b3a696acd 613
wim 17:652ab113bc2e 614 // Configure only current LCD controller
wim 17:652ab113bc2e 615 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 616
wim 15:b70ebfffb258 617 }
wim 15:b70ebfffb258 618
wim 17:652ab113bc2e 619 // Set the Displaymode (On/Off)
wim 21:9eb628d9e164 620 void TextLCD_Base::setMode(LCDMode displayMode) {
wim 17:652ab113bc2e 621
wim 17:652ab113bc2e 622 // Save new displayMode, needed when 2 controllers are in use or when cursor is changed
wim 17:652ab113bc2e 623 _currentMode = displayMode;
wim 15:b70ebfffb258 624
wim 17:652ab113bc2e 625 // Select and configure second LCD controller when needed
wim 17:652ab113bc2e 626 if(_type==LCD40x4) {
wim 21:9eb628d9e164 627 if (_ctrl_idx==_LCDCtrl_0) {
wim 17:652ab113bc2e 628 // Configure primary LCD controller
wim 17:652ab113bc2e 629 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 11:9ec02df863a1 630
wim 17:652ab113bc2e 631 // Select 2nd controller
wim 21:9eb628d9e164 632 _ctrl_idx=_LCDCtrl_1;
wim 17:652ab113bc2e 633
wim 17:652ab113bc2e 634 // Configure secondary LCD controller
wim 21:9eb628d9e164 635 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 11:9ec02df863a1 636
wim 17:652ab113bc2e 637 // Restore current controller
wim 21:9eb628d9e164 638 _ctrl_idx=_LCDCtrl_0;
wim 17:652ab113bc2e 639 }
wim 17:652ab113bc2e 640 else {
wim 17:652ab113bc2e 641 // Select primary controller
wim 21:9eb628d9e164 642 _ctrl_idx=_LCDCtrl_0;
wim 17:652ab113bc2e 643
wim 17:652ab113bc2e 644 // Configure primary LCD controller
wim 21:9eb628d9e164 645 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 17:652ab113bc2e 646
wim 17:652ab113bc2e 647 // Restore current controller
wim 21:9eb628d9e164 648 _ctrl_idx=_LCDCtrl_1;
wim 11:9ec02df863a1 649
wim 17:652ab113bc2e 650 // Configure secondary LCD controller
wim 17:652ab113bc2e 651 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 11:9ec02df863a1 652
wim 10:dd9b3a696acd 653 }
wim 17:652ab113bc2e 654 }
wim 17:652ab113bc2e 655 else {
wim 17:652ab113bc2e 656 // Configure primary LCD controller
wim 17:652ab113bc2e 657 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 17:652ab113bc2e 658 }
wim 17:652ab113bc2e 659
wim 17:652ab113bc2e 660 }
wim 17:652ab113bc2e 661
wim 17:652ab113bc2e 662
wim 17:652ab113bc2e 663 // Set the Displaymode (On/Off) and Cursortype for current controller
wim 21:9eb628d9e164 664 void TextLCD_Base::_setCursorAndDisplayMode(LCDMode displayMode, LCDCursor cursorType) {
wim 17:652ab113bc2e 665
wim 17:652ab113bc2e 666 // Configure current LCD controller
wim 17:652ab113bc2e 667 _writeCommand(0x08 | displayMode | cursorType);
wim 10:dd9b3a696acd 668 }
wim 10:dd9b3a696acd 669
wim 20:e0da005a777f 670 // Set the Backlight mode (Off/On)
wim 21:9eb628d9e164 671 void TextLCD_Base::setBacklight(LCDBacklight backlightMode) {
wim 20:e0da005a777f 672
wim 20:e0da005a777f 673 if (backlightMode == LightOn) {
wim 21:9eb628d9e164 674 this->_setBL(true);
wim 20:e0da005a777f 675 }
wim 20:e0da005a777f 676 else {
wim 21:9eb628d9e164 677 this->_setBL(false);
wim 20:e0da005a777f 678 }
wim 20:e0da005a777f 679 }
wim 20:e0da005a777f 680
wim 10:dd9b3a696acd 681
wim 21:9eb628d9e164 682 void TextLCD_Base::setUDC(unsigned char c, char *udc_data) {
wim 15:b70ebfffb258 683
wim 15:b70ebfffb258 684 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 685 if(_type==LCD40x4) {
wim 19:c747b9e2e7b8 686 _LCDCtrl_Idx current_ctrl_idx = _ctrl_idx; // Temp save current controller
wim 15:b70ebfffb258 687
wim 15:b70ebfffb258 688 // Select primary controller
wim 21:9eb628d9e164 689 _ctrl_idx=_LCDCtrl_0;
wim 15:b70ebfffb258 690
wim 15:b70ebfffb258 691 // Configure primary LCD controller
wim 15:b70ebfffb258 692 _setUDC(c, udc_data);
wim 15:b70ebfffb258 693
wim 15:b70ebfffb258 694 // Select 2nd controller
wim 21:9eb628d9e164 695 _ctrl_idx=_LCDCtrl_1;
wim 15:b70ebfffb258 696
wim 15:b70ebfffb258 697 // Configure secondary LCD controller
wim 15:b70ebfffb258 698 _setUDC(c, udc_data);
wim 11:9ec02df863a1 699
wim 15:b70ebfffb258 700 // Restore current controller
wim 19:c747b9e2e7b8 701 _ctrl_idx=current_ctrl_idx;
wim 15:b70ebfffb258 702 }
wim 15:b70ebfffb258 703 else {
wim 15:b70ebfffb258 704 // Configure primary LCD controller
wim 15:b70ebfffb258 705 _setUDC(c, udc_data);
wim 15:b70ebfffb258 706 }
wim 15:b70ebfffb258 707
wim 15:b70ebfffb258 708 }
wim 15:b70ebfffb258 709
wim 21:9eb628d9e164 710 void TextLCD_Base::_setUDC(unsigned char c, char *udc_data) {
wim 15:b70ebfffb258 711
wim 15:b70ebfffb258 712 // Select CG RAM for current LCD controller
wim 15:b70ebfffb258 713 _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address,
wim 15:b70ebfffb258 714 //8 sequential locations needed per UDC
wim 15:b70ebfffb258 715 // Store UDC pattern
wim 11:9ec02df863a1 716 for (int i=0; i<8; i++) {
wim 13:24506ba22480 717 _writeData(*udc_data++);
wim 11:9ec02df863a1 718 }
wim 15:b70ebfffb258 719
wim 15:b70ebfffb258 720 //Select DD RAM again for current LCD controller
wim 15:b70ebfffb258 721 int addr = getAddress(_column, _row);
wim 15:b70ebfffb258 722 _writeCommand(0x80 | addr);
wim 15:b70ebfffb258 723
wim 11:9ec02df863a1 724 }
wim 21:9eb628d9e164 725
wim 22:35742ec80c24 726 ///--------- End TextLCD_Base -----------
wim 21:9eb628d9e164 727
wim 22:35742ec80c24 728
wim 21:9eb628d9e164 729
wim 22:35742ec80c24 730 ///--------- Start TextLCD Bus -----------
wim 21:9eb628d9e164 731
wim 21:9eb628d9e164 732 /* Create a TextLCD interface for using regular mbed pins
wim 21:9eb628d9e164 733 *
wim 21:9eb628d9e164 734 * @param rs Instruction/data control line
wim 21:9eb628d9e164 735 * @param e Enable line (clock)
wim 21:9eb628d9e164 736 * @param d4-d7 Data lines for using as a 4-bit interface
wim 21:9eb628d9e164 737 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 738 * @param bl Backlight control line (optional, default = NC)
wim 21:9eb628d9e164 739 * @param e2 Enable2 line (clock for second controller, LCD40x4 only)
wim 21:9eb628d9e164 740 * @param ctrl LCD controller (default = HD44780)
wim 21:9eb628d9e164 741 */
wim 21:9eb628d9e164 742 TextLCD::TextLCD(PinName rs, PinName e,
wim 21:9eb628d9e164 743 PinName d4, PinName d5, PinName d6, PinName d7,
wim 21:9eb628d9e164 744 LCDType type, PinName bl, PinName e2, LCDCtrl ctrl) :
wim 21:9eb628d9e164 745 TextLCD_Base(type, ctrl),
wim 22:35742ec80c24 746 _rs(rs), _e(e), _d(d4, d5, d6, d7) {
wim 22:35742ec80c24 747
wim 22:35742ec80c24 748 // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
wim 22:35742ec80c24 749 if (bl != NC) {
wim 22:35742ec80c24 750 _bl = new DigitalOut(bl); //Construct new pin
wim 22:35742ec80c24 751 _bl->write(0); //Deactivate
wim 22:35742ec80c24 752 }
wim 22:35742ec80c24 753 else {
wim 22:35742ec80c24 754 // No Hardware Backlight pin
wim 22:35742ec80c24 755 _bl = NULL; //Construct dummy pin
wim 22:35742ec80c24 756 }
wim 22:35742ec80c24 757
wim 22:35742ec80c24 758 // The hardware Enable2 pin is only needed for LCD40x4. Test and make sure whether it exists or not to prevent illegal access.
wim 22:35742ec80c24 759 if (e2 != NC) {
wim 22:35742ec80c24 760 _e2 = new DigitalOut(e2); //Construct new pin
wim 22:35742ec80c24 761 _e2->write(0); //Deactivate
wim 22:35742ec80c24 762 }
wim 22:35742ec80c24 763 else {
wim 22:35742ec80c24 764 // No Hardware Enable pin
wim 22:35742ec80c24 765 _e2 = NULL; //Construct dummy pin
wim 22:35742ec80c24 766 }
wim 21:9eb628d9e164 767
wim 21:9eb628d9e164 768 _init();
wim 21:9eb628d9e164 769
wim 21:9eb628d9e164 770 }
wim 21:9eb628d9e164 771
wim 22:35742ec80c24 772 /** Set E pin (or E2 pin)
wim 22:35742ec80c24 773 * Used for mbed pins, I2C bus expander or SPI shiftregister
wim 22:35742ec80c24 774 * Default PinName value for E2 is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
wim 22:35742ec80c24 775 * @param value true or false
wim 22:35742ec80c24 776 * @return none
wim 22:35742ec80c24 777 */
wim 21:9eb628d9e164 778 void TextLCD::_setEnable(bool value) {
wim 21:9eb628d9e164 779
wim 22:35742ec80c24 780 if(_ctrl_idx==_LCDCtrl_0) {
wim 22:35742ec80c24 781 if (value) {
wim 22:35742ec80c24 782 _e = 1; // Set E bit
wim 22:35742ec80c24 783 }
wim 22:35742ec80c24 784 else {
wim 22:35742ec80c24 785 _e = 0; // Reset E bit
wim 22:35742ec80c24 786 }
wim 22:35742ec80c24 787 }
wim 22:35742ec80c24 788 else {
wim 22:35742ec80c24 789 if (value) {
wim 22:35742ec80c24 790 if (_e2 != NULL) {_e2->write(1);} //Set E2 bit
wim 22:35742ec80c24 791 }
wim 22:35742ec80c24 792 else {
wim 22:35742ec80c24 793 if (_e2 != NULL) {_e2->write(0);} //Reset E2 bit
wim 22:35742ec80c24 794 }
wim 22:35742ec80c24 795 }
wim 21:9eb628d9e164 796
wim 21:9eb628d9e164 797 }
wim 21:9eb628d9e164 798
wim 21:9eb628d9e164 799 // Set RS pin
wim 21:9eb628d9e164 800 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 801 void TextLCD::_setRS(bool value) {
wim 21:9eb628d9e164 802
wim 22:35742ec80c24 803 if (value) {
wim 21:9eb628d9e164 804 _rs = 1; // Set RS bit
wim 22:35742ec80c24 805 }
wim 22:35742ec80c24 806 else {
wim 21:9eb628d9e164 807 _rs = 0; // Reset RS bit
wim 22:35742ec80c24 808 }
wim 21:9eb628d9e164 809
wim 21:9eb628d9e164 810 }
wim 21:9eb628d9e164 811
wim 22:35742ec80c24 812 /** Set BL pin
wim 22:35742ec80c24 813 * Used for mbed pins, I2C bus expander or SPI shiftregister
wim 22:35742ec80c24 814 * Default PinName value is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
wim 22:35742ec80c24 815 * @param value true or false
wim 22:35742ec80c24 816 * @return none
wim 22:35742ec80c24 817 */
wim 21:9eb628d9e164 818 void TextLCD::_setBL(bool value) {
wim 21:9eb628d9e164 819
wim 22:35742ec80c24 820 if (value) {
wim 22:35742ec80c24 821 if (_bl != NULL) {_bl->write(1);} //Set BL bit
wim 22:35742ec80c24 822 }
wim 22:35742ec80c24 823 else {
wim 22:35742ec80c24 824 if (_bl != NULL) {_bl->write(0);} //Reset BL bit
wim 22:35742ec80c24 825 }
wim 21:9eb628d9e164 826
wim 21:9eb628d9e164 827 }
wim 21:9eb628d9e164 828
wim 21:9eb628d9e164 829 // Place the 4bit data on the databus
wim 21:9eb628d9e164 830 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 21:9eb628d9e164 831 void TextLCD::_setData(int value) {
wim 21:9eb628d9e164 832 _d = value & 0x0F; // Write Databits
wim 21:9eb628d9e164 833 }
wim 21:9eb628d9e164 834
wim 22:35742ec80c24 835 /** Destruct a TextLCD interface for using regular mbed pins
wim 22:35742ec80c24 836 *
wim 22:35742ec80c24 837 * @param none
wim 22:35742ec80c24 838 * @return none
wim 22:35742ec80c24 839 */
wim 22:35742ec80c24 840 TextLCD::~TextLCD() {
wim 22:35742ec80c24 841 if (_bl != NULL) {delete _bl;} // BL pin
wim 22:35742ec80c24 842 if (_e2 != NULL) {delete _e2;} // E2 pin
wim 22:35742ec80c24 843 }
wim 21:9eb628d9e164 844
wim 22:35742ec80c24 845
wim 22:35742ec80c24 846 ///----------- End TextLCD ---------------
wim 21:9eb628d9e164 847
wim 21:9eb628d9e164 848
wim 22:35742ec80c24 849 ///--------- Start TextLCD_I2C -----------
wim 22:35742ec80c24 850
wim 22:35742ec80c24 851 /** Create a TextLCD interface using an I2C PC8574 or PCF8574A portexpander
wim 22:35742ec80c24 852 *
wim 22:35742ec80c24 853 * @param i2c I2C Bus
wim 22:35742ec80c24 854 * @param deviceAddress I2C slave address (PCF8574 or PCF8574A, default = 0x40)
wim 22:35742ec80c24 855 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 22:35742ec80c24 856 * @param ctrl LCD controller (default = HD44780)
wim 22:35742ec80c24 857 */
wim 21:9eb628d9e164 858 TextLCD_I2C::TextLCD_I2C(I2C *i2c, char deviceAddress, LCDType type, LCDCtrl ctrl) :
wim 21:9eb628d9e164 859 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 860 _i2c(i2c){
wim 21:9eb628d9e164 861
wim 22:35742ec80c24 862 _slaveAddress = deviceAddress & 0xFE;
wim 21:9eb628d9e164 863
wim 21:9eb628d9e164 864 // Init the portexpander bus
wim 21:9eb628d9e164 865 _lcd_bus = D_LCD_BUS_DEF;
wim 21:9eb628d9e164 866
wim 21:9eb628d9e164 867 // write the new data to the portexpander
wim 21:9eb628d9e164 868 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 869
wim 21:9eb628d9e164 870 _init();
wim 21:9eb628d9e164 871
wim 21:9eb628d9e164 872 }
wim 21:9eb628d9e164 873
wim 21:9eb628d9e164 874 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 875 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 876 void TextLCD_I2C::_setEnable(bool value) {
wim 21:9eb628d9e164 877
wim 22:35742ec80c24 878 if(_ctrl_idx==_LCDCtrl_0) {
wim 22:35742ec80c24 879 if (value)
wim 22:35742ec80c24 880 _lcd_bus |= D_LCD_E; // Set E bit
wim 22:35742ec80c24 881 else
wim 22:35742ec80c24 882 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 22:35742ec80c24 883 }
wim 22:35742ec80c24 884 else {
wim 22:35742ec80c24 885 if (value)
wim 22:35742ec80c24 886 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 22:35742ec80c24 887 else
wim 22:35742ec80c24 888 _lcd_bus &= ~D_LCD_E2; // Reset E2bit
wim 22:35742ec80c24 889 }
wim 21:9eb628d9e164 890
wim 22:35742ec80c24 891 // write the new data to the I2C portexpander
wim 22:35742ec80c24 892 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 893
wim 21:9eb628d9e164 894 }
wim 21:9eb628d9e164 895
wim 21:9eb628d9e164 896 // Set RS pin
wim 21:9eb628d9e164 897 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 898 void TextLCD_I2C::_setRS(bool value) {
wim 21:9eb628d9e164 899
wim 22:35742ec80c24 900 if (value)
wim 22:35742ec80c24 901 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 22:35742ec80c24 902 else
wim 22:35742ec80c24 903 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 21:9eb628d9e164 904
wim 22:35742ec80c24 905 // write the new data to the I2C portexpander
wim 22:35742ec80c24 906 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 907
wim 21:9eb628d9e164 908 }
wim 21:9eb628d9e164 909
wim 21:9eb628d9e164 910 // Set BL pin
wim 21:9eb628d9e164 911 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 912 void TextLCD_I2C::_setBL(bool value) {
wim 21:9eb628d9e164 913
wim 21:9eb628d9e164 914 if (value)
wim 21:9eb628d9e164 915 _lcd_bus |= D_LCD_BL; // Set BL bit
wim 21:9eb628d9e164 916 else
wim 21:9eb628d9e164 917 _lcd_bus &= ~D_LCD_BL; // Reset BL bit
wim 21:9eb628d9e164 918
wim 21:9eb628d9e164 919 // write the new data to the I2C portexpander
wim 21:9eb628d9e164 920 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 921
wim 21:9eb628d9e164 922 }
wim 21:9eb628d9e164 923
wim 21:9eb628d9e164 924
wim 21:9eb628d9e164 925
wim 21:9eb628d9e164 926 // Place the 4bit data on the databus
wim 21:9eb628d9e164 927 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 21:9eb628d9e164 928 void TextLCD_I2C::_setData(int value) {
wim 21:9eb628d9e164 929 int data;
wim 22:35742ec80c24 930
wim 22:35742ec80c24 931 // Set bit by bit to support any mapping of expander portpins to LCD pins
wim 21:9eb628d9e164 932
wim 22:35742ec80c24 933 data = value & 0x0F;
wim 22:35742ec80c24 934 if (data & 0x01)
wim 22:35742ec80c24 935 _lcd_bus |= D_LCD_D4; // Set Databit
wim 22:35742ec80c24 936 else
wim 22:35742ec80c24 937 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 21:9eb628d9e164 938
wim 22:35742ec80c24 939 if (data & 0x02)
wim 22:35742ec80c24 940 _lcd_bus |= D_LCD_D5; // Set Databit
wim 22:35742ec80c24 941 else
wim 22:35742ec80c24 942 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 21:9eb628d9e164 943
wim 22:35742ec80c24 944 if (data & 0x04)
wim 22:35742ec80c24 945 _lcd_bus |= D_LCD_D6; // Set Databit
wim 22:35742ec80c24 946 else
wim 22:35742ec80c24 947 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 21:9eb628d9e164 948
wim 22:35742ec80c24 949 if (data & 0x08)
wim 22:35742ec80c24 950 _lcd_bus |= D_LCD_D7; // Set Databit
wim 22:35742ec80c24 951 else
wim 22:35742ec80c24 952 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 21:9eb628d9e164 953
wim 22:35742ec80c24 954 // write the new data to the I2C portexpander
wim 22:35742ec80c24 955 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 22:35742ec80c24 956
wim 22:35742ec80c24 957 }
wim 21:9eb628d9e164 958
wim 22:35742ec80c24 959 ///---------- End TextLCD_I2C ------------
wim 21:9eb628d9e164 960
wim 21:9eb628d9e164 961
wim 21:9eb628d9e164 962
wim 22:35742ec80c24 963 ///--------- Start TextLCD_SPI -----------
wim 21:9eb628d9e164 964
wim 22:35742ec80c24 965 /** Create a TextLCD interface using an SPI 74595 portexpander
wim 22:35742ec80c24 966 *
wim 22:35742ec80c24 967 * @param spi SPI Bus
wim 22:35742ec80c24 968 * @param cs chip select pin (active low)
wim 22:35742ec80c24 969 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 22:35742ec80c24 970 * @param ctrl LCD controller (default = HD44780)
wim 22:35742ec80c24 971 */
wim 21:9eb628d9e164 972 TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) :
wim 21:9eb628d9e164 973 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 974 _spi(spi),
wim 21:9eb628d9e164 975 _cs(cs) {
wim 21:9eb628d9e164 976
wim 21:9eb628d9e164 977 // Setup the spi for 8 bit data, low steady state clock,
wim 21:9eb628d9e164 978 // rising edge capture, with a 500KHz or 1MHz clock rate
wim 21:9eb628d9e164 979 _spi->format(8,0);
wim 21:9eb628d9e164 980 _spi->frequency(500000);
wim 21:9eb628d9e164 981 //_spi.frequency(1000000);
wim 21:9eb628d9e164 982
wim 21:9eb628d9e164 983
wim 21:9eb628d9e164 984 // Init the portexpander bus
wim 21:9eb628d9e164 985 _lcd_bus = D_LCD_BUS_DEF;
wim 21:9eb628d9e164 986
wim 21:9eb628d9e164 987 // write the new data to the portexpander
wim 21:9eb628d9e164 988 _setCS(false);
wim 21:9eb628d9e164 989 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 990 _setCS(true);
wim 21:9eb628d9e164 991
wim 21:9eb628d9e164 992 _init();
wim 21:9eb628d9e164 993
wim 21:9eb628d9e164 994 }
wim 21:9eb628d9e164 995
wim 21:9eb628d9e164 996 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 997 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 998 void TextLCD_SPI::_setEnable(bool value) {
wim 21:9eb628d9e164 999
wim 22:35742ec80c24 1000 if(_ctrl_idx==_LCDCtrl_0) {
wim 22:35742ec80c24 1001 if (value)
wim 22:35742ec80c24 1002 _lcd_bus |= D_LCD_E; // Set E bit
wim 22:35742ec80c24 1003 else
wim 22:35742ec80c24 1004 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 22:35742ec80c24 1005 }
wim 22:35742ec80c24 1006 else {
wim 22:35742ec80c24 1007 if (value)
wim 22:35742ec80c24 1008 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 22:35742ec80c24 1009 else
wim 22:35742ec80c24 1010 _lcd_bus &= ~D_LCD_E2; // Reset E2 bit
wim 22:35742ec80c24 1011 }
wim 21:9eb628d9e164 1012
wim 22:35742ec80c24 1013 // write the new data to the SPI portexpander
wim 22:35742ec80c24 1014 _setCS(false);
wim 22:35742ec80c24 1015 _spi->write(_lcd_bus);
wim 22:35742ec80c24 1016 _setCS(true);
wim 21:9eb628d9e164 1017
wim 21:9eb628d9e164 1018 }
wim 21:9eb628d9e164 1019
wim 21:9eb628d9e164 1020 // Set RS pin
wim 21:9eb628d9e164 1021 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1022 void TextLCD_SPI::_setRS(bool value) {
wim 21:9eb628d9e164 1023
wim 22:35742ec80c24 1024 if (value) {
wim 21:9eb628d9e164 1025 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 22:35742ec80c24 1026 }
wim 22:35742ec80c24 1027 else {
wim 21:9eb628d9e164 1028 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 22:35742ec80c24 1029 }
wim 21:9eb628d9e164 1030
wim 21:9eb628d9e164 1031 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 1032 _setCS(false);
wim 21:9eb628d9e164 1033 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1034 _setCS(true);
wim 21:9eb628d9e164 1035
wim 21:9eb628d9e164 1036 }
wim 21:9eb628d9e164 1037
wim 21:9eb628d9e164 1038 // Set BL pin
wim 21:9eb628d9e164 1039 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1040 void TextLCD_SPI::_setBL(bool value) {
wim 21:9eb628d9e164 1041
wim 22:35742ec80c24 1042 if (value) {
wim 21:9eb628d9e164 1043 _lcd_bus |= D_LCD_BL; // Set BL bit
wim 22:35742ec80c24 1044 }
wim 22:35742ec80c24 1045 else {
wim 21:9eb628d9e164 1046 _lcd_bus &= ~D_LCD_BL; // Reset BL bit
wim 22:35742ec80c24 1047 }
wim 21:9eb628d9e164 1048
wim 21:9eb628d9e164 1049 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 1050 _setCS(false);
wim 21:9eb628d9e164 1051 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1052 _setCS(true);
wim 21:9eb628d9e164 1053
wim 21:9eb628d9e164 1054 }
wim 21:9eb628d9e164 1055
wim 21:9eb628d9e164 1056
wim 21:9eb628d9e164 1057
wim 21:9eb628d9e164 1058 // Place the 4bit data on the databus
wim 21:9eb628d9e164 1059 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1060 void TextLCD_SPI::_setData(int value) {
wim 21:9eb628d9e164 1061 int data;
wim 21:9eb628d9e164 1062
wim 22:35742ec80c24 1063 // Set bit by bit to support any mapping of expander portpins to LCD pins
wim 22:35742ec80c24 1064
wim 22:35742ec80c24 1065 data = value & 0x0F;
wim 22:35742ec80c24 1066 if (data & 0x01)
wim 22:35742ec80c24 1067 _lcd_bus |= D_LCD_D4; // Set Databit
wim 22:35742ec80c24 1068 else
wim 22:35742ec80c24 1069 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 22:35742ec80c24 1070
wim 22:35742ec80c24 1071 if (data & 0x02)
wim 22:35742ec80c24 1072 _lcd_bus |= D_LCD_D5; // Set Databit
wim 22:35742ec80c24 1073 else
wim 22:35742ec80c24 1074 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 21:9eb628d9e164 1075
wim 22:35742ec80c24 1076 if (data & 0x04)
wim 22:35742ec80c24 1077 _lcd_bus |= D_LCD_D6; // Set Databit
wim 22:35742ec80c24 1078 else
wim 22:35742ec80c24 1079 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 21:9eb628d9e164 1080
wim 22:35742ec80c24 1081 if (data & 0x08)
wim 22:35742ec80c24 1082 _lcd_bus |= D_LCD_D7; // Set Databit
wim 22:35742ec80c24 1083 else
wim 22:35742ec80c24 1084 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 21:9eb628d9e164 1085
wim 22:35742ec80c24 1086 // write the new data to the SPI portexpander
wim 22:35742ec80c24 1087 _setCS(false);
wim 22:35742ec80c24 1088 _spi->write(_lcd_bus);
wim 22:35742ec80c24 1089 _setCS(true);
wim 21:9eb628d9e164 1090
wim 21:9eb628d9e164 1091 }
wim 21:9eb628d9e164 1092
wim 21:9eb628d9e164 1093
wim 21:9eb628d9e164 1094 // Set CS line.
wim 21:9eb628d9e164 1095 // Only used for SPI bus
wim 21:9eb628d9e164 1096 void TextLCD_SPI::_setCS(bool value) {
wim 21:9eb628d9e164 1097
wim 21:9eb628d9e164 1098 if (value) {
wim 21:9eb628d9e164 1099 _cs = 1; // Set CS pin
wim 21:9eb628d9e164 1100 }
wim 22:35742ec80c24 1101 else {
wim 21:9eb628d9e164 1102 _cs = 0; // Reset CS pin
wim 22:35742ec80c24 1103 }
wim 21:9eb628d9e164 1104 }
wim 21:9eb628d9e164 1105
wim 21:9eb628d9e164 1106
wim 22:35742ec80c24 1107 ///---------- End TextLCD_SPI ------------
wim 22:35742ec80c24 1108
wim 22:35742ec80c24 1109
wim 21:9eb628d9e164 1110
wim 21:9eb628d9e164 1111
wim 21:9eb628d9e164 1112
wim 21:9eb628d9e164 1113
wim 21:9eb628d9e164 1114