Updated for more display types. Fixed memoryaddress confusion in address() method. Added new getAddress() method. Added support for UDCs, Backlight control and other features such as control through I2C and SPI port expanders and controllers with native I2C and SPI interfaces. Refactored to fix issue with pins that are default declared as NC.

Dependents:   GPSDevice TestTextLCD SD to Flash Data Transfer DrumMachine ... more

Fork of TextLCD by Simon Ford

Example

Hello World! for the TextLCD

#include "mbed.h"
#include "TextLCD.h"
 
// Host PC Communication channels
Serial pc(USBTX, USBRX); // tx, rx
 
// I2C Communication
I2C i2c_lcd(p28,p27); // SDA, SCL
 
// SPI Communication
SPI spi_lcd(p5, NC, p7); // MOSI, MISO, SCLK

//TextLCD lcd(p15, p16, p17, p18, p19, p20);                // RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=HD44780
//TextLCD_SPI lcd(&spi_lcd, p8, TextLCD::LCD40x4);   // SPI bus, 74595 expander, CS pin, LCD Type  
TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD20x4);  // I2C bus, PCF8574 Slaveaddress, LCD Type
//TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD16x2, TextLCD::WS0010); // I2C bus, PCF8574 Slaveaddress, LCD Type, Device Type
//TextLCD_SPI_N lcd(&spi_lcd, p8, p9);               // SPI bus, CS pin, RS pin, LCDType=LCD16x2, BL=NC, LCDTCtrl=ST7032_3V3   
//TextLCD_I2C_N lcd(&i2c_lcd, ST7032_SA, TextLCD::LCD16x2, NC, TextLCD::ST7032_3V3); // I2C bus, Slaveaddress, LCD Type, BL=NC, LCDTCtrl=ST7032_3V3  

int main() {
    pc.printf("LCD Test. Columns=%d, Rows=%d\n\r", lcd.columns(), lcd.rows());
    
    for (int row=0; row<lcd.rows(); row++) {
      int col=0;
      
      pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));      
//      lcd.putc('-');
      lcd.putc('0' + row);      
      
      for (col=1; col<lcd.columns()-1; col++) {    
        lcd.putc('*');
      }
 
      pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));      
      lcd.putc('+');
        
    }    
    
// Show cursor as blinking character
    lcd.setCursor(TextLCD::CurOff_BlkOn);
 
// Set and show user defined characters. A maximum of 8 UDCs are supported by the HD44780.
// They are defined by a 5x7 bitpattern. 
    lcd.setUDC(0, (char *) udc_0);  // Show |>
    lcd.putc(0);    
    lcd.setUDC(1, (char *) udc_1);  // Show <|
    lcd.putc(1);    

}

Handbook page

More info is here

Committer:
wim
Date:
Tue Feb 19 22:09:09 2013 +0000
Revision:
15:b70ebfffb258
Parent:
14:0c32b66b14b8
Child:
16:c276b75e6585
Working testversion for 40x4.; Fixed cursor problems.; Fixed UDC problems, always return to DD RAM.

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