for

Dependents:   LV_FGSE_Controller_Interface

Committer:
wim
Date:
Sat Mar 02 16:51:01 2013 +0000
Revision:
17:652ab113bc2e
Parent:
16:c276b75e6585
Child:
18:bd65dc10f27f
Added support for Display On/Off. Improved 4bit bootprocess.

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