for

Dependents:   LV_FGSE_Controller_Interface

Committer:
wim
Date:
Mon May 13 19:29:13 2013 +0000
Revision:
20:e0da005a777f
Parent:
19:c747b9e2e7b8
Child:
21:9eb628d9e164
Added support for Backlight control; Added portdefinitions for I2C/TWI LCD2004 Module from DFROBOT

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