1

Dependents:   Program_R11

Committer:
wim
Date:
Sat Jun 14 17:04:25 2014 +0000
Revision:
28:30fa94f7341c
Parent:
27:22d5086f6ba6
Child:
29:a3663151aa65
Updated to support ST7032i with native I2C and SPI interface.

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