for

Dependents:   LV_FGSE_Controller_Interface

Committer:
wim
Date:
Fri May 30 15:05:13 2014 +0000
Revision:
26:bd897a001012
Parent:
25:6162b31128c9
Child:
27:22d5086f6ba6
Added support for MCP23008 I2C expander, added pinmapping for Adafruit I2C and SPI backplane.

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