1

Dependents:   Program_R11

Committer:
wim
Date:
Tue Apr 01 21:30:25 2014 +0000
Revision:
21:9eb628d9e164
Parent:
20:e0da005a777f
Child:
22:35742ec80c24
Refactored in Abstract Base class and Derived classes for Bus interface, I2C portexpander interface and SPI shiftregister interface.; This was needed to solve problem with recent mbed lib and DigitalOut pins that are default defined as 'NC'.

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 21:9eb628d9e164 10 * 2014, v08: WH, Refactored in Base in 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 21:9eb628d9e164 726
wim 21:9eb628d9e164 727 ///-------------------------------------------------------------------
wim 21:9eb628d9e164 728
wim 21:9eb628d9e164 729
wim 21:9eb628d9e164 730 /* Create a TextLCD interface for using regular mbed pins
wim 21:9eb628d9e164 731 *
wim 21:9eb628d9e164 732 * @param rs Instruction/data control line
wim 21:9eb628d9e164 733 * @param e Enable line (clock)
wim 21:9eb628d9e164 734 * @param d4-d7 Data lines for using as a 4-bit interface
wim 21:9eb628d9e164 735 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 736 * @param bl Backlight control line (optional, default = NC)
wim 21:9eb628d9e164 737 * @param e2 Enable2 line (clock for second controller, LCD40x4 only)
wim 21:9eb628d9e164 738 * @param ctrl LCD controller (default = HD44780)
wim 21:9eb628d9e164 739 */
wim 21:9eb628d9e164 740 TextLCD::TextLCD(PinName rs, PinName e,
wim 21:9eb628d9e164 741 PinName d4, PinName d5, PinName d6, PinName d7,
wim 21:9eb628d9e164 742 LCDType type, PinName bl, PinName e2, LCDCtrl ctrl) :
wim 21:9eb628d9e164 743 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 744 _rs(rs), _e(e), _bl(bl), _e2(e2),
wim 21:9eb628d9e164 745 _d(d4, d5, d6, d7) {
wim 21:9eb628d9e164 746
wim 21:9eb628d9e164 747 _init();
wim 21:9eb628d9e164 748
wim 21:9eb628d9e164 749 }
wim 21:9eb628d9e164 750
wim 21:9eb628d9e164 751 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 752 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 753 void TextLCD::_setEnable(bool value) {
wim 21:9eb628d9e164 754
wim 21:9eb628d9e164 755 if(_ctrl_idx==_LCDCtrl_0) {
wim 21:9eb628d9e164 756 if (value)
wim 21:9eb628d9e164 757 _e = 1; // Set E bit
wim 21:9eb628d9e164 758 else
wim 21:9eb628d9e164 759 _e = 0; // Reset E bit
wim 21:9eb628d9e164 760 }
wim 21:9eb628d9e164 761 else {
wim 21:9eb628d9e164 762 if (value)
wim 21:9eb628d9e164 763 _e2 = 1; // Set E2 bit
wim 21:9eb628d9e164 764 else
wim 21:9eb628d9e164 765 _e2 = 0; // Reset E2 bit
wim 21:9eb628d9e164 766 }
wim 21:9eb628d9e164 767
wim 21:9eb628d9e164 768 }
wim 21:9eb628d9e164 769
wim 21:9eb628d9e164 770 // Set RS pin
wim 21:9eb628d9e164 771 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 772 void TextLCD::_setRS(bool value) {
wim 21:9eb628d9e164 773
wim 21:9eb628d9e164 774 if (value)
wim 21:9eb628d9e164 775 _rs = 1; // Set RS bit
wim 21:9eb628d9e164 776 else
wim 21:9eb628d9e164 777 _rs = 0; // Reset RS bit
wim 21:9eb628d9e164 778
wim 21:9eb628d9e164 779 }
wim 21:9eb628d9e164 780
wim 21:9eb628d9e164 781 // Set BL pin
wim 21:9eb628d9e164 782 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 783 void TextLCD::_setBL(bool value) {
wim 21:9eb628d9e164 784
wim 21:9eb628d9e164 785 if (value)
wim 21:9eb628d9e164 786 _bl = 1; // Set BL bit
wim 21:9eb628d9e164 787 else
wim 21:9eb628d9e164 788 _bl = 0; // Reset BL bit
wim 21:9eb628d9e164 789
wim 21:9eb628d9e164 790 }
wim 21:9eb628d9e164 791
wim 21:9eb628d9e164 792
wim 21:9eb628d9e164 793
wim 21:9eb628d9e164 794 // Place the 4bit data on the databus
wim 21:9eb628d9e164 795 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 21:9eb628d9e164 796 void TextLCD::_setData(int value) {
wim 21:9eb628d9e164 797 _d = value & 0x0F; // Write Databits
wim 21:9eb628d9e164 798 }
wim 21:9eb628d9e164 799
wim 21:9eb628d9e164 800
wim 21:9eb628d9e164 801
wim 21:9eb628d9e164 802
wim 21:9eb628d9e164 803 ///----------------------------------------------------------------------------------------
wim 21:9eb628d9e164 804
wim 21:9eb628d9e164 805
wim 21:9eb628d9e164 806 /* Create a TextLCD interface using an I2C PC8574 portexpander
wim 21:9eb628d9e164 807 *
wim 21:9eb628d9e164 808 * @param i2c I2C Bus
wim 21:9eb628d9e164 809 * @param deviceAddress I2C slave address (PCF8574)
wim 21:9eb628d9e164 810 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 811 * @param ctrl LCD controller (default = HD44780)
wim 21:9eb628d9e164 812 */
wim 21:9eb628d9e164 813 TextLCD_I2C::TextLCD_I2C(I2C *i2c, char deviceAddress, LCDType type, LCDCtrl ctrl) :
wim 21:9eb628d9e164 814 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 815 _i2c(i2c){
wim 21:9eb628d9e164 816
wim 21:9eb628d9e164 817 _slaveAddress = deviceAddress;
wim 21:9eb628d9e164 818
wim 21:9eb628d9e164 819 // Init the portexpander bus
wim 21:9eb628d9e164 820 _lcd_bus = D_LCD_BUS_DEF;
wim 21:9eb628d9e164 821
wim 21:9eb628d9e164 822 // write the new data to the portexpander
wim 21:9eb628d9e164 823 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 824
wim 21:9eb628d9e164 825 _init();
wim 21:9eb628d9e164 826
wim 21:9eb628d9e164 827 }
wim 21:9eb628d9e164 828
wim 21:9eb628d9e164 829 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 830 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 831 void TextLCD_I2C::_setEnable(bool value) {
wim 21:9eb628d9e164 832
wim 21:9eb628d9e164 833 if(_ctrl_idx==_LCDCtrl_0) {
wim 21:9eb628d9e164 834 if (value)
wim 21:9eb628d9e164 835 _lcd_bus |= D_LCD_E; // Set E bit
wim 21:9eb628d9e164 836 else
wim 21:9eb628d9e164 837 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 21:9eb628d9e164 838 }
wim 21:9eb628d9e164 839 else {
wim 21:9eb628d9e164 840 if (value)
wim 21:9eb628d9e164 841 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 21:9eb628d9e164 842 else
wim 21:9eb628d9e164 843 _lcd_bus &= ~D_LCD_E2; // Reset E2bit
wim 21:9eb628d9e164 844 }
wim 21:9eb628d9e164 845
wim 21:9eb628d9e164 846 // write the new data to the I2C portexpander
wim 21:9eb628d9e164 847 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 848
wim 21:9eb628d9e164 849 }
wim 21:9eb628d9e164 850
wim 21:9eb628d9e164 851 // Set RS pin
wim 21:9eb628d9e164 852 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 853 void TextLCD_I2C::_setRS(bool value) {
wim 21:9eb628d9e164 854
wim 21:9eb628d9e164 855 if (value)
wim 21:9eb628d9e164 856 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 21:9eb628d9e164 857 else
wim 21:9eb628d9e164 858 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 21:9eb628d9e164 859
wim 21:9eb628d9e164 860 // write the new data to the I2C portexpander
wim 21:9eb628d9e164 861 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 862
wim 21:9eb628d9e164 863 }
wim 21:9eb628d9e164 864
wim 21:9eb628d9e164 865 // Set BL pin
wim 21:9eb628d9e164 866 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 867 void TextLCD_I2C::_setBL(bool value) {
wim 21:9eb628d9e164 868
wim 21:9eb628d9e164 869 if (value)
wim 21:9eb628d9e164 870 _lcd_bus |= D_LCD_BL; // Set BL bit
wim 21:9eb628d9e164 871 else
wim 21:9eb628d9e164 872 _lcd_bus &= ~D_LCD_BL; // Reset BL bit
wim 21:9eb628d9e164 873
wim 21:9eb628d9e164 874 // write the new data to the I2C portexpander
wim 21:9eb628d9e164 875 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 876
wim 21:9eb628d9e164 877 }
wim 21:9eb628d9e164 878
wim 21:9eb628d9e164 879
wim 21:9eb628d9e164 880
wim 21:9eb628d9e164 881 // Place the 4bit data on the databus
wim 21:9eb628d9e164 882 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 21:9eb628d9e164 883 void TextLCD_I2C::_setData(int value) {
wim 21:9eb628d9e164 884 int data;
wim 21:9eb628d9e164 885
wim 21:9eb628d9e164 886 data = value & 0x0F;
wim 21:9eb628d9e164 887 if (data & 0x01)
wim 21:9eb628d9e164 888 _lcd_bus |= D_LCD_D4; // Set Databit
wim 21:9eb628d9e164 889 else
wim 21:9eb628d9e164 890 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 21:9eb628d9e164 891
wim 21:9eb628d9e164 892 if (data & 0x02)
wim 21:9eb628d9e164 893 _lcd_bus |= D_LCD_D5; // Set Databit
wim 21:9eb628d9e164 894 else
wim 21:9eb628d9e164 895 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 21:9eb628d9e164 896
wim 21:9eb628d9e164 897 if (data & 0x04)
wim 21:9eb628d9e164 898 _lcd_bus |= D_LCD_D6; // Set Databit
wim 21:9eb628d9e164 899 else
wim 21:9eb628d9e164 900 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 21:9eb628d9e164 901
wim 21:9eb628d9e164 902 if (data & 0x08)
wim 21:9eb628d9e164 903 _lcd_bus |= D_LCD_D7; // Set Databit
wim 21:9eb628d9e164 904 else
wim 21:9eb628d9e164 905 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 21:9eb628d9e164 906
wim 21:9eb628d9e164 907 // write the new data to the I2C portexpander
wim 21:9eb628d9e164 908 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 21:9eb628d9e164 909
wim 21:9eb628d9e164 910
wim 21:9eb628d9e164 911 }
wim 21:9eb628d9e164 912
wim 21:9eb628d9e164 913
wim 21:9eb628d9e164 914
wim 21:9eb628d9e164 915
wim 21:9eb628d9e164 916
wim 21:9eb628d9e164 917 ///------------------------------------------------------------------------------------
wim 21:9eb628d9e164 918
wim 21:9eb628d9e164 919
wim 21:9eb628d9e164 920
wim 21:9eb628d9e164 921
wim 21:9eb628d9e164 922
wim 21:9eb628d9e164 923
wim 21:9eb628d9e164 924 // TextLCD_SPI Implementation
wim 21:9eb628d9e164 925
wim 21:9eb628d9e164 926
wim 21:9eb628d9e164 927 /* Create a TextLCD interface using an SPI 74595 portexpander
wim 21:9eb628d9e164 928 *
wim 21:9eb628d9e164 929 * @param spi SPI Bus
wim 21:9eb628d9e164 930 * @param cs chip select pin (active low)
wim 21:9eb628d9e164 931 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 932 * @param ctrl LCD controller (default = HD44780)
wim 21:9eb628d9e164 933 */
wim 21:9eb628d9e164 934 TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) :
wim 21:9eb628d9e164 935 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 936 _spi(spi),
wim 21:9eb628d9e164 937 _cs(cs) {
wim 21:9eb628d9e164 938
wim 21:9eb628d9e164 939 // Setup the spi for 8 bit data, low steady state clock,
wim 21:9eb628d9e164 940 // rising edge capture, with a 500KHz or 1MHz clock rate
wim 21:9eb628d9e164 941 _spi->format(8,0);
wim 21:9eb628d9e164 942 _spi->frequency(500000);
wim 21:9eb628d9e164 943 //_spi.frequency(1000000);
wim 21:9eb628d9e164 944
wim 21:9eb628d9e164 945
wim 21:9eb628d9e164 946 // Init the portexpander bus
wim 21:9eb628d9e164 947 _lcd_bus = D_LCD_BUS_DEF;
wim 21:9eb628d9e164 948
wim 21:9eb628d9e164 949 // write the new data to the portexpander
wim 21:9eb628d9e164 950 _setCS(false);
wim 21:9eb628d9e164 951 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 952 _setCS(true);
wim 21:9eb628d9e164 953
wim 21:9eb628d9e164 954 _init();
wim 21:9eb628d9e164 955
wim 21:9eb628d9e164 956 }
wim 21:9eb628d9e164 957
wim 21:9eb628d9e164 958 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 959 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 960 void TextLCD_SPI::_setEnable(bool value) {
wim 21:9eb628d9e164 961
wim 21:9eb628d9e164 962 if(_ctrl_idx==_LCDCtrl_0) {
wim 21:9eb628d9e164 963 if (value)
wim 21:9eb628d9e164 964 _lcd_bus |= D_LCD_E; // Set E bit
wim 21:9eb628d9e164 965 else
wim 21:9eb628d9e164 966 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 21:9eb628d9e164 967 }
wim 21:9eb628d9e164 968 else {
wim 21:9eb628d9e164 969 if (value)
wim 21:9eb628d9e164 970 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 21:9eb628d9e164 971 else
wim 21:9eb628d9e164 972 _lcd_bus &= ~D_LCD_E2; // Reset E2 bit
wim 21:9eb628d9e164 973 }
wim 21:9eb628d9e164 974
wim 21:9eb628d9e164 975 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 976 _setCS(false);
wim 21:9eb628d9e164 977 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 978 _setCS(true);
wim 21:9eb628d9e164 979
wim 21:9eb628d9e164 980 }
wim 21:9eb628d9e164 981
wim 21:9eb628d9e164 982 // Set RS pin
wim 21:9eb628d9e164 983 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 984 void TextLCD_SPI::_setRS(bool value) {
wim 21:9eb628d9e164 985
wim 21:9eb628d9e164 986 if (value)
wim 21:9eb628d9e164 987 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 21:9eb628d9e164 988 else
wim 21:9eb628d9e164 989 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 21:9eb628d9e164 990
wim 21:9eb628d9e164 991 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 992 _setCS(false);
wim 21:9eb628d9e164 993 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 994 _setCS(true);
wim 21:9eb628d9e164 995
wim 21:9eb628d9e164 996 }
wim 21:9eb628d9e164 997
wim 21:9eb628d9e164 998 // Set BL pin
wim 21:9eb628d9e164 999 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1000 void TextLCD_SPI::_setBL(bool value) {
wim 21:9eb628d9e164 1001
wim 21:9eb628d9e164 1002 if (value)
wim 21:9eb628d9e164 1003 _lcd_bus |= D_LCD_BL; // Set BL bit
wim 21:9eb628d9e164 1004 else
wim 21:9eb628d9e164 1005 _lcd_bus &= ~D_LCD_BL; // Reset BL bit
wim 21:9eb628d9e164 1006
wim 21:9eb628d9e164 1007 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 1008 _setCS(false);
wim 21:9eb628d9e164 1009 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1010 _setCS(true);
wim 21:9eb628d9e164 1011
wim 21:9eb628d9e164 1012 }
wim 21:9eb628d9e164 1013
wim 21:9eb628d9e164 1014
wim 21:9eb628d9e164 1015
wim 21:9eb628d9e164 1016 // Place the 4bit data on the databus
wim 21:9eb628d9e164 1017 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1018 void TextLCD_SPI::_setData(int value) {
wim 21:9eb628d9e164 1019 int data;
wim 21:9eb628d9e164 1020
wim 21:9eb628d9e164 1021 data = value & 0x0F;
wim 21:9eb628d9e164 1022 if (data & 0x01)
wim 21:9eb628d9e164 1023 _lcd_bus |= D_LCD_D4; // Set Databit
wim 21:9eb628d9e164 1024 else
wim 21:9eb628d9e164 1025 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 21:9eb628d9e164 1026
wim 21:9eb628d9e164 1027 if (data & 0x02)
wim 21:9eb628d9e164 1028 _lcd_bus |= D_LCD_D5; // Set Databit
wim 21:9eb628d9e164 1029 else
wim 21:9eb628d9e164 1030 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 21:9eb628d9e164 1031
wim 21:9eb628d9e164 1032 if (data & 0x04)
wim 21:9eb628d9e164 1033 _lcd_bus |= D_LCD_D6; // Set Databit
wim 21:9eb628d9e164 1034 else
wim 21:9eb628d9e164 1035 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 21:9eb628d9e164 1036
wim 21:9eb628d9e164 1037 if (data & 0x08)
wim 21:9eb628d9e164 1038 _lcd_bus |= D_LCD_D7; // Set Databit
wim 21:9eb628d9e164 1039 else
wim 21:9eb628d9e164 1040 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 21:9eb628d9e164 1041
wim 21:9eb628d9e164 1042 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 1043 _setCS(false);
wim 21:9eb628d9e164 1044 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1045 _setCS(true);
wim 21:9eb628d9e164 1046
wim 21:9eb628d9e164 1047 }
wim 21:9eb628d9e164 1048
wim 21:9eb628d9e164 1049
wim 21:9eb628d9e164 1050 // Set CS line.
wim 21:9eb628d9e164 1051 // Only used for SPI bus
wim 21:9eb628d9e164 1052 void TextLCD_SPI::_setCS(bool value) {
wim 21:9eb628d9e164 1053
wim 21:9eb628d9e164 1054 if (value) {
wim 21:9eb628d9e164 1055 _cs = 1; // Set CS pin
wim 21:9eb628d9e164 1056 }
wim 21:9eb628d9e164 1057 else
wim 21:9eb628d9e164 1058 _cs = 0; // Reset CS pin
wim 21:9eb628d9e164 1059
wim 21:9eb628d9e164 1060 }
wim 21:9eb628d9e164 1061
wim 21:9eb628d9e164 1062
wim 21:9eb628d9e164 1063
wim 21:9eb628d9e164 1064
wim 21:9eb628d9e164 1065
wim 21:9eb628d9e164 1066
wim 21:9eb628d9e164 1067
wim 21:9eb628d9e164 1068
wim 21:9eb628d9e164 1069
wim 21:9eb628d9e164 1070
wim 21:9eb628d9e164 1071