sd

Fork of TextLCD by Wim Huiskamp

Committer:
wim
Date:
Fri Jun 13 19:02:26 2014 +0000
Revision:
27:22d5086f6ba6
Parent:
26:bd897a001012
Child:
28:30fa94f7341c
First test of native SPI

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