Initial commit

Fork of TextLCD by Wim Huiskamp

Committer:
wim
Date:
Sat Mar 09 19:39:53 2013 +0000
Revision:
18:bd65dc10f27f
Parent:
17:652ab113bc2e
Child:
19:c747b9e2e7b8
Added some UDCs, Updated documentation.

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