TextLCD

Dependents:   mbed_2019_rx3

Committer:
wim
Date:
Fri Apr 19 19:36:37 2013 +0000
Revision:
19:c747b9e2e7b8
Parent:
18:bd65dc10f27f
Child:
20:e0da005a777f
Beta version supporting WS0010 and ST7036 DC/DC converters

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