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:
Wed Feb 20 19:37:53 2013 +0000
Revision:
16:c276b75e6585
Parent:
15:b70ebfffb258
Child:
17:652ab113bc2e
Cleaned up and Commented

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 16:c276b75e6585 223 // Clear the screen, Cursor home.
wim 15:b70ebfffb258 224 void TextLCD::cls() {
wim 15:b70ebfffb258 225
wim 15:b70ebfffb258 226 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 227 if(_type==LCD40x4) {
wim 15:b70ebfffb258 228 _ctrl=TextLCD::_LCDCtrl_1; // Select 2nd controller
wim 15:b70ebfffb258 229
wim 15:b70ebfffb258 230 // Second LCD controller Cursor always Off
wim 15:b70ebfffb258 231 _setCursor(TextLCD::CurOff_BlkOff);
wim 15:b70ebfffb258 232
wim 15:b70ebfffb258 233 // Second LCD controller Clearscreen
wim 15:b70ebfffb258 234 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 235
wim 15:b70ebfffb258 236 wait_ms(10); // The CLS command takes 1.64 ms.
wim 15:b70ebfffb258 237 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 238
wim 15:b70ebfffb258 239
wim 15:b70ebfffb258 240 _ctrl=TextLCD::_LCDCtrl_0; // Select primary controller
wim 15:b70ebfffb258 241 }
wim 15:b70ebfffb258 242
wim 15:b70ebfffb258 243 // Primary LCD controller Clearscreen
wim 15:b70ebfffb258 244 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 245
wim 15:b70ebfffb258 246 wait_ms(10); // The CLS command takes 1.64 ms.
wim 15:b70ebfffb258 247 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 248
wim 15:b70ebfffb258 249 // Restore cursormode on primary LCD controller when needed
wim 15:b70ebfffb258 250 if(_type==LCD40x4) {
wim 15:b70ebfffb258 251 _setCursor(_currentCursor);
wim 15:b70ebfffb258 252 }
wim 15:b70ebfffb258 253
wim 15:b70ebfffb258 254 _row=0; // Reset Cursor location
wim 15:b70ebfffb258 255 _column=0;
simon 1:ac48b187213c 256 }
simon 1:ac48b187213c 257
wim 16:c276b75e6585 258 // Move cursor to selected row and column
simon 1:ac48b187213c 259 void TextLCD::locate(int column, int row) {
wim 15:b70ebfffb258 260
wim 15:b70ebfffb258 261 // setAddress() does all the heavy lifting:
wim 15:b70ebfffb258 262 // check column and row sanity,
wim 15:b70ebfffb258 263 // switch controllers for LCD40x4 if needed
wim 15:b70ebfffb258 264 // switch cursor for LCD40x4 if needed
wim 15:b70ebfffb258 265 // set the new memory address to show cursor at correct location
wim 15:b70ebfffb258 266 setAddress(column, row);
wim 15:b70ebfffb258 267
wim 15:b70ebfffb258 268 }
wim 15:b70ebfffb258 269
wim 15:b70ebfffb258 270
wim 16:c276b75e6585 271 // Write a single character (Stream implementation)
wim 15:b70ebfffb258 272 int TextLCD::_putc(int value) {
wim 15:b70ebfffb258 273 int addr;
wim 15:b70ebfffb258 274
wim 15:b70ebfffb258 275 if (value == '\n') {
wim 15:b70ebfffb258 276 //No character to write
wim 15:b70ebfffb258 277
wim 15:b70ebfffb258 278 //Update Cursor
wim 15:b70ebfffb258 279 _column = 0;
wim 15:b70ebfffb258 280 _row++;
wim 15:b70ebfffb258 281 if (_row >= rows()) {
wim 15:b70ebfffb258 282 _row = 0;
wim 15:b70ebfffb258 283 }
wim 15:b70ebfffb258 284 }
wim 15:b70ebfffb258 285 else {
wim 15:b70ebfffb258 286 //Character to write
wim 15:b70ebfffb258 287 _writeData(value);
wim 15:b70ebfffb258 288
wim 15:b70ebfffb258 289 //Update Cursor
wim 15:b70ebfffb258 290 _column++;
wim 15:b70ebfffb258 291 if (_column >= columns()) {
wim 15:b70ebfffb258 292 _column = 0;
wim 15:b70ebfffb258 293 _row++;
wim 15:b70ebfffb258 294 if (_row >= rows()) {
wim 15:b70ebfffb258 295 _row = 0;
wim 15:b70ebfffb258 296 }
wim 15:b70ebfffb258 297 }
wim 15:b70ebfffb258 298 } //else
wim 15:b70ebfffb258 299
wim 15:b70ebfffb258 300 //Set next memoryaddress, make sure cursor blinks at next location
wim 15:b70ebfffb258 301 addr = getAddress(_column, _row);
wim 15:b70ebfffb258 302 _writeCommand(0x80 | addr);
wim 15:b70ebfffb258 303
wim 15:b70ebfffb258 304 return value;
wim 15:b70ebfffb258 305 }
wim 15:b70ebfffb258 306
wim 15:b70ebfffb258 307
wim 16:c276b75e6585 308 // get a single character (Stream implementation)
simon 1:ac48b187213c 309 int TextLCD::_getc() {
simon 1:ac48b187213c 310 return -1;
simon 1:ac48b187213c 311 }
simon 1:ac48b187213c 312
wim 16:c276b75e6585 313 // Set E pin (or E2 pin)
wim 16:c276b75e6585 314 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 13:24506ba22480 315 void TextLCD::_setEnable(bool value) {
wim 13:24506ba22480 316
wim 13:24506ba22480 317 switch(_busType) {
wim 13:24506ba22480 318 case _PinBus :
wim 15:b70ebfffb258 319 if(_ctrl==TextLCD::_LCDCtrl_0) {
wim 15:b70ebfffb258 320 if (value)
wim 15:b70ebfffb258 321 _e = 1; // Set E bit
wim 15:b70ebfffb258 322 else
wim 15:b70ebfffb258 323 _e = 0; // Reset E bit
wim 15:b70ebfffb258 324 }
wim 15:b70ebfffb258 325 else {
wim 15:b70ebfffb258 326 if (value)
wim 15:b70ebfffb258 327 _e2 = 1; // Set E2 bit
wim 15:b70ebfffb258 328 else
wim 15:b70ebfffb258 329 _e2 = 0; // Reset E2 bit
wim 15:b70ebfffb258 330 }
wim 15:b70ebfffb258 331
wim 13:24506ba22480 332 break;
wim 13:24506ba22480 333
wim 13:24506ba22480 334 case _I2CBus :
wim 15:b70ebfffb258 335
wim 15:b70ebfffb258 336 if(_ctrl==TextLCD::_LCDCtrl_0) {
wim 15:b70ebfffb258 337 if (value)
wim 15:b70ebfffb258 338 _lcd_bus |= D_LCD_E; // Set E bit
wim 15:b70ebfffb258 339 else
wim 15:b70ebfffb258 340 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 15:b70ebfffb258 341 }
wim 15:b70ebfffb258 342 else {
wim 15:b70ebfffb258 343 if (value)
wim 15:b70ebfffb258 344 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 15:b70ebfffb258 345 else
wim 15:b70ebfffb258 346 _lcd_bus &= ~D_LCD_E2; // Reset E2bit
wim 15:b70ebfffb258 347 }
wim 15:b70ebfffb258 348
wim 15:b70ebfffb258 349 // write the new data to the I2C portexpander
wim 14:0c32b66b14b8 350 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 15:b70ebfffb258 351
wim 13:24506ba22480 352 break;
wim 13:24506ba22480 353
wim 13:24506ba22480 354 case _SPIBus :
wim 15:b70ebfffb258 355 if(_ctrl==TextLCD::_LCDCtrl_0) {
wim 15:b70ebfffb258 356 if (value)
wim 15:b70ebfffb258 357 _lcd_bus |= D_LCD_E; // Set E bit
wim 15:b70ebfffb258 358 else
wim 15:b70ebfffb258 359 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 15:b70ebfffb258 360 }
wim 15:b70ebfffb258 361 else {
wim 15:b70ebfffb258 362 if (value)
wim 15:b70ebfffb258 363 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 15:b70ebfffb258 364 else
wim 15:b70ebfffb258 365 _lcd_bus &= ~D_LCD_E2; // Reset E2 bit
wim 15:b70ebfffb258 366 }
wim 15:b70ebfffb258 367
wim 15:b70ebfffb258 368 // write the new data to the SPI portexpander
wim 14:0c32b66b14b8 369 _setCS(false);
wim 14:0c32b66b14b8 370 _spi->write(_lcd_bus);
wim 14:0c32b66b14b8 371 _setCS(true);
wim 14:0c32b66b14b8 372
wim 13:24506ba22480 373 break;
wim 13:24506ba22480 374 }
wim 13:24506ba22480 375 }
wim 13:24506ba22480 376
wim 16:c276b75e6585 377 // Set RS pin
wim 16:c276b75e6585 378 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 13:24506ba22480 379 void TextLCD::_setRS(bool value) {
wim 13:24506ba22480 380
wim 13:24506ba22480 381 switch(_busType) {
wim 13:24506ba22480 382 case _PinBus :
wim 13:24506ba22480 383 if (value)
wim 13:24506ba22480 384 _rs = 1; // Set RS bit
wim 13:24506ba22480 385 else
wim 13:24506ba22480 386 _rs = 0; // Reset RS bit
wim 13:24506ba22480 387
wim 13:24506ba22480 388 break;
wim 13:24506ba22480 389
wim 13:24506ba22480 390 case _I2CBus :
wim 14:0c32b66b14b8 391 if (value)
wim 14:0c32b66b14b8 392 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 14:0c32b66b14b8 393 else
wim 14:0c32b66b14b8 394 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 13:24506ba22480 395
wim 15:b70ebfffb258 396 // write the new data to the I2C portexpander
wim 14:0c32b66b14b8 397 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 13:24506ba22480 398
wim 13:24506ba22480 399 break;
wim 13:24506ba22480 400
wim 13:24506ba22480 401 case _SPIBus :
wim 14:0c32b66b14b8 402 if (value)
wim 14:0c32b66b14b8 403 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 14:0c32b66b14b8 404 else
wim 14:0c32b66b14b8 405 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 14:0c32b66b14b8 406
wim 15:b70ebfffb258 407 // write the new data to the SPI portexpander
wim 14:0c32b66b14b8 408 _setCS(false);
wim 14:0c32b66b14b8 409 _spi->write(_lcd_bus);
wim 14:0c32b66b14b8 410 _setCS(true);
wim 14:0c32b66b14b8 411
wim 13:24506ba22480 412 break;
wim 13:24506ba22480 413 }
wim 13:24506ba22480 414
wim 13:24506ba22480 415 }
wim 13:24506ba22480 416
wim 16:c276b75e6585 417 // Place the 4bit data on the databus
wim 16:c276b75e6585 418 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 13:24506ba22480 419 void TextLCD::_setData(int value) {
wim 13:24506ba22480 420 int data;
wim 13:24506ba22480 421
wim 13:24506ba22480 422 switch(_busType) {
wim 13:24506ba22480 423 case _PinBus :
wim 13:24506ba22480 424 _d = value & 0x0F; // Write Databits
wim 13:24506ba22480 425
wim 13:24506ba22480 426 break;
wim 13:24506ba22480 427
wim 13:24506ba22480 428 case _I2CBus :
wim 13:24506ba22480 429 data = value & 0x0F;
wim 13:24506ba22480 430 if (data & 0x01)
wim 13:24506ba22480 431 _lcd_bus |= D_LCD_D4; // Set Databit
wim 13:24506ba22480 432 else
wim 13:24506ba22480 433 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 13:24506ba22480 434
wim 13:24506ba22480 435 if (data & 0x02)
wim 13:24506ba22480 436 _lcd_bus |= D_LCD_D5; // Set Databit
wim 13:24506ba22480 437 else
wim 13:24506ba22480 438 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 13:24506ba22480 439
wim 13:24506ba22480 440 if (data & 0x04)
wim 13:24506ba22480 441 _lcd_bus |= D_LCD_D6; // Set Databit
wim 13:24506ba22480 442 else
wim 13:24506ba22480 443 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 13:24506ba22480 444
wim 13:24506ba22480 445 if (data & 0x08)
wim 13:24506ba22480 446 _lcd_bus |= D_LCD_D7; // Set Databit
wim 13:24506ba22480 447 else
wim 13:24506ba22480 448 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 13:24506ba22480 449
wim 15:b70ebfffb258 450 // write the new data to the I2C portexpander
wim 13:24506ba22480 451 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 13:24506ba22480 452
wim 13:24506ba22480 453 break;
wim 13:24506ba22480 454
wim 13:24506ba22480 455 case _SPIBus :
wim 14:0c32b66b14b8 456
wim 14:0c32b66b14b8 457 data = value & 0x0F;
wim 14:0c32b66b14b8 458 if (data & 0x01)
wim 14:0c32b66b14b8 459 _lcd_bus |= D_LCD_D4; // Set Databit
wim 14:0c32b66b14b8 460 else
wim 14:0c32b66b14b8 461 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 14:0c32b66b14b8 462
wim 14:0c32b66b14b8 463 if (data & 0x02)
wim 14:0c32b66b14b8 464 _lcd_bus |= D_LCD_D5; // Set Databit
wim 14:0c32b66b14b8 465 else
wim 14:0c32b66b14b8 466 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 14:0c32b66b14b8 467
wim 14:0c32b66b14b8 468 if (data & 0x04)
wim 14:0c32b66b14b8 469 _lcd_bus |= D_LCD_D6; // Set Databit
wim 14:0c32b66b14b8 470 else
wim 14:0c32b66b14b8 471 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 14:0c32b66b14b8 472
wim 14:0c32b66b14b8 473 if (data & 0x08)
wim 14:0c32b66b14b8 474 _lcd_bus |= D_LCD_D7; // Set Databit
wim 14:0c32b66b14b8 475 else
wim 14:0c32b66b14b8 476 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 14:0c32b66b14b8 477
wim 15:b70ebfffb258 478 // write the new data to the SPI portexpander
wim 14:0c32b66b14b8 479 _setCS(false);
wim 14:0c32b66b14b8 480 _spi->write(_lcd_bus);
wim 14:0c32b66b14b8 481 _setCS(true);
wim 14:0c32b66b14b8 482
wim 14:0c32b66b14b8 483 break;
wim 13:24506ba22480 484 }
wim 13:24506ba22480 485
wim 13:24506ba22480 486 }
wim 13:24506ba22480 487
wim 13:24506ba22480 488
wim 16:c276b75e6585 489 // Set CS line.
wim 16:c276b75e6585 490 // Only used for SPI bus
wim 14:0c32b66b14b8 491 void TextLCD::_setCS(bool value) {
wim 14:0c32b66b14b8 492
wim 15:b70ebfffb258 493 if (value) {
wim 14:0c32b66b14b8 494 _cs = 1; // Set CS pin
wim 15:b70ebfffb258 495 }
wim 14:0c32b66b14b8 496 else
wim 14:0c32b66b14b8 497 _cs = 0; // Reset CS pin
wim 15:b70ebfffb258 498
wim 14:0c32b66b14b8 499 }
wim 14:0c32b66b14b8 500
wim 14:0c32b66b14b8 501
wim 16:c276b75e6585 502 // Write a byte using the 4-bit interface
wim 16:c276b75e6585 503 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 13:24506ba22480 504 void TextLCD::_writeByte(int value) {
wim 15:b70ebfffb258 505
wim 15:b70ebfffb258 506 // Enable is Low
wim 15:b70ebfffb258 507 _setEnable(true);
wim 16:c276b75e6585 508 _setData(value >> 4); // High nibble
wim 15:b70ebfffb258 509 wait_us(1); // Data setup time
wim 15:b70ebfffb258 510 _setEnable(false);
wim 15:b70ebfffb258 511 wait_us(1); // Data hold time
wim 15:b70ebfffb258 512
wim 13:24506ba22480 513 _setEnable(true);
wim 16:c276b75e6585 514 _setData(value >> 0); // Low nibble
wim 15:b70ebfffb258 515 wait_us(1); // Data setup time
wim 13:24506ba22480 516 _setEnable(false);
wim 15:b70ebfffb258 517 wait_us(1); // Datahold time
wim 15:b70ebfffb258 518
wim 15:b70ebfffb258 519 // Enable is Low
wim 15:b70ebfffb258 520
simon 1:ac48b187213c 521 }
simon 1:ac48b187213c 522
wim 13:24506ba22480 523 void TextLCD::_writeCommand(int command) {
wim 15:b70ebfffb258 524
wim 13:24506ba22480 525 _setRS(false);
wim 16:c276b75e6585 526 wait_us(1); // Data setup time for RS
wim 15:b70ebfffb258 527
wim 15:b70ebfffb258 528 _writeByte(command);
wim 15:b70ebfffb258 529 wait_us(40); // most instructions take 40us
simon 1:ac48b187213c 530 }
simon 1:ac48b187213c 531
wim 13:24506ba22480 532 void TextLCD::_writeData(int data) {
wim 15:b70ebfffb258 533
wim 13:24506ba22480 534 _setRS(true);
wim 16:c276b75e6585 535 wait_us(1); // Data setup time for RS
wim 15:b70ebfffb258 536
wim 13:24506ba22480 537 _writeByte(data);
wim 15:b70ebfffb258 538 wait_us(40); // data writes take 40us
simon 1:ac48b187213c 539 }
simon 1:ac48b187213c 540
wim 8:03116f75b66e 541
wim 8:03116f75b66e 542 #if (0)
wim 16:c276b75e6585 543 // This is the original _address() method.
wim 8:03116f75b66e 544 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
wim 8:03116f75b66e 545 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 546 //
wim 13:24506ba22480 547 int TextLCD::_address(int column, int row) {
simon 1:ac48b187213c 548 switch (_type) {
simon 1:ac48b187213c 549 case LCD20x4:
simon 1:ac48b187213c 550 switch (row) {
simon 1:ac48b187213c 551 case 0:
simon 1:ac48b187213c 552 return 0x80 + column;
simon 1:ac48b187213c 553 case 1:
simon 1:ac48b187213c 554 return 0xc0 + column;
simon 1:ac48b187213c 555 case 2:
simon 1:ac48b187213c 556 return 0x94 + column;
simon 1:ac48b187213c 557 case 3:
simon 1:ac48b187213c 558 return 0xd4 + column;
simon 1:ac48b187213c 559 }
simon 1:ac48b187213c 560 case LCD16x2B:
simon 4:bf5b706f8d32 561 return 0x80 + (row * 40) + column;
simon 1:ac48b187213c 562 case LCD16x2:
simon 1:ac48b187213c 563 case LCD20x2:
simon 1:ac48b187213c 564 default:
simon 4:bf5b706f8d32 565 return 0x80 + (row * 0x40) + column;
simon 1:ac48b187213c 566 }
simon 1:ac48b187213c 567 }
wim 8:03116f75b66e 568 #endif
wim 8:03116f75b66e 569
wim 8:03116f75b66e 570
wim 16:c276b75e6585 571 // This replaces the original _address() method.
wim 8:03116f75b66e 572 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 13:24506ba22480 573 int TextLCD::_address(int column, int row) {
wim 8:03116f75b66e 574 return 0x80 | getAddress(column, row);
wim 8:03116f75b66e 575 }
wim 8:03116f75b66e 576
wim 8:03116f75b66e 577 // This is new method to return the memory address based on row, column and displaytype.
wim 8:03116f75b66e 578 //
wim 8:03116f75b66e 579 int TextLCD::getAddress(int column, int row) {
wim 8:03116f75b66e 580
wim 8:03116f75b66e 581 switch (_type) {
wim 8:03116f75b66e 582 case LCD8x1:
wim 8:03116f75b66e 583 return 0x00 + column;
wim 8:03116f75b66e 584
wim 13:24506ba22480 585 case LCD16x1:
wim 13:24506ba22480 586 // LCD16x1 is a special layout of LCD8x2
wim 13:24506ba22480 587 if (column<8)
wim 13:24506ba22480 588 return 0x00 + column;
wim 13:24506ba22480 589 else
wim 13:24506ba22480 590 return 0x40 + (column - 8);
wim 13:24506ba22480 591
wim 15:b70ebfffb258 592 case LCD12x4:
wim 15:b70ebfffb258 593 switch (row) {
wim 15:b70ebfffb258 594 case 0:
wim 15:b70ebfffb258 595 return 0x00 + column;
wim 15:b70ebfffb258 596 case 1:
wim 15:b70ebfffb258 597 return 0x40 + column;
wim 15:b70ebfffb258 598 case 2:
wim 15:b70ebfffb258 599 return 0x0C + column;
wim 15:b70ebfffb258 600 case 3:
wim 15:b70ebfffb258 601 return 0x4C + column;
wim 15:b70ebfffb258 602 }
wim 15:b70ebfffb258 603
wim 8:03116f75b66e 604 case LCD16x4:
wim 8:03116f75b66e 605 switch (row) {
wim 8:03116f75b66e 606 case 0:
wim 8:03116f75b66e 607 return 0x00 + column;
wim 8:03116f75b66e 608 case 1:
wim 8:03116f75b66e 609 return 0x40 + column;
wim 8:03116f75b66e 610 case 2:
wim 8:03116f75b66e 611 return 0x10 + column;
wim 8:03116f75b66e 612 case 3:
wim 8:03116f75b66e 613 return 0x50 + column;
wim 8:03116f75b66e 614 }
wim 8:03116f75b66e 615
wim 8:03116f75b66e 616 case LCD20x4:
wim 8:03116f75b66e 617 switch (row) {
wim 8:03116f75b66e 618 case 0:
wim 8:03116f75b66e 619 return 0x00 + column;
wim 8:03116f75b66e 620 case 1:
wim 8:03116f75b66e 621 return 0x40 + column;
wim 8:03116f75b66e 622 case 2:
wim 8:03116f75b66e 623 return 0x14 + column;
wim 8:03116f75b66e 624 case 3:
wim 8:03116f75b66e 625 return 0x54 + column;
wim 8:03116f75b66e 626 }
wim 8:03116f75b66e 627
wim 10:dd9b3a696acd 628 // Special mode for KS0078
wim 10:dd9b3a696acd 629 case LCD24x4:
wim 10:dd9b3a696acd 630 switch (row) {
wim 10:dd9b3a696acd 631 case 0:
wim 10:dd9b3a696acd 632 return 0x00 + column;
wim 10:dd9b3a696acd 633 case 1:
wim 10:dd9b3a696acd 634 return 0x20 + column;
wim 10:dd9b3a696acd 635 case 2:
wim 10:dd9b3a696acd 636 return 0x40 + column;
wim 10:dd9b3a696acd 637 case 3:
wim 10:dd9b3a696acd 638 return 0x60 + column;
wim 10:dd9b3a696acd 639 }
wim 10:dd9b3a696acd 640
wim 8:03116f75b66e 641 // Not sure about this one, seems wrong.
wim 8:03116f75b66e 642 case LCD16x2B:
wim 8:03116f75b66e 643 return 0x00 + (row * 40) + column;
wim 8:03116f75b66e 644
wim 8:03116f75b66e 645 case LCD8x2:
wim 15:b70ebfffb258 646 case LCD12x2:
wim 8:03116f75b66e 647 case LCD16x2:
wim 8:03116f75b66e 648 case LCD20x2:
wim 8:03116f75b66e 649 case LCD24x2:
wim 9:0893d986e717 650 case LCD40x2:
wim 8:03116f75b66e 651 return 0x00 + (row * 0x40) + column;
wim 15:b70ebfffb258 652
wim 15:b70ebfffb258 653 case LCD40x4:
wim 15:b70ebfffb258 654 // LCD40x4 is a special case since it has 2 controllers
wim 15:b70ebfffb258 655 // Each controller is configured as 40x2
wim 15:b70ebfffb258 656 if (row<2) {
wim 15:b70ebfffb258 657 // Test to see if we need to switch between controllers
wim 15:b70ebfffb258 658 if (_ctrl != _LCDCtrl_0) {
wim 15:b70ebfffb258 659 // Second LCD controller Cursor Off
wim 15:b70ebfffb258 660 _setCursor(TextLCD::CurOff_BlkOff);
wim 15:b70ebfffb258 661
wim 15:b70ebfffb258 662 // Select primary controller
wim 15:b70ebfffb258 663 _ctrl = _LCDCtrl_0;
wim 15:b70ebfffb258 664
wim 15:b70ebfffb258 665 // Restore cursormode on primary LCD controller
wim 15:b70ebfffb258 666 _setCursor(_currentCursor);
wim 15:b70ebfffb258 667 }
wim 15:b70ebfffb258 668
wim 15:b70ebfffb258 669 return 0x00 + (row * 0x40) + column;
wim 15:b70ebfffb258 670 }
wim 15:b70ebfffb258 671 else {
wim 15:b70ebfffb258 672
wim 15:b70ebfffb258 673 // Test to see if we need to switch between controllers
wim 15:b70ebfffb258 674 if (_ctrl != _LCDCtrl_1) {
wim 15:b70ebfffb258 675 // Primary LCD controller Cursor Off
wim 15:b70ebfffb258 676 _setCursor(TextLCD::CurOff_BlkOff);
wim 15:b70ebfffb258 677
wim 15:b70ebfffb258 678 // Select secondary controller
wim 15:b70ebfffb258 679 _ctrl = _LCDCtrl_1;
wim 15:b70ebfffb258 680
wim 15:b70ebfffb258 681 // Restore cursormode on secondary LCD controller
wim 15:b70ebfffb258 682 _setCursor(_currentCursor);
wim 15:b70ebfffb258 683 }
wim 15:b70ebfffb258 684
wim 15:b70ebfffb258 685 return 0x00 + ((row-2) * 0x40) + column;
wim 15:b70ebfffb258 686 }
wim 8:03116f75b66e 687
wim 8:03116f75b66e 688 // Should never get here.
wim 8:03116f75b66e 689 default:
wim 8:03116f75b66e 690 return 0x00;
wim 8:03116f75b66e 691 }
wim 8:03116f75b66e 692 }
wim 8:03116f75b66e 693
wim 8:03116f75b66e 694
wim 15:b70ebfffb258 695 // Set row, column and update memoryaddress.
wim 8:03116f75b66e 696 //
wim 8:03116f75b66e 697 void TextLCD::setAddress(int column, int row) {
wim 15:b70ebfffb258 698
wim 15:b70ebfffb258 699 // Sanity Check column
wim 15:b70ebfffb258 700 if (column < 0) {
wim 15:b70ebfffb258 701 _column = 0;
wim 15:b70ebfffb258 702 }
wim 15:b70ebfffb258 703 else if (column >= columns()) {
wim 15:b70ebfffb258 704 _column = columns() - 1;
wim 15:b70ebfffb258 705 } else _column = column;
wim 8:03116f75b66e 706
wim 15:b70ebfffb258 707 // Sanity Check row
wim 15:b70ebfffb258 708 if (row < 0) {
wim 15:b70ebfffb258 709 _row = 0;
wim 15:b70ebfffb258 710 }
wim 15:b70ebfffb258 711 else if (row >= rows()) {
wim 15:b70ebfffb258 712 _row = rows() - 1;
wim 15:b70ebfffb258 713 } else _row = row;
wim 15:b70ebfffb258 714
wim 15:b70ebfffb258 715
wim 15:b70ebfffb258 716 // Compute the memory address
wim 15:b70ebfffb258 717 // For LCD40x4: switch controllers if needed
wim 15:b70ebfffb258 718 // switch cursor if needed
wim 15:b70ebfffb258 719 int addr = getAddress(_column, _row);
wim 8:03116f75b66e 720
wim 13:24506ba22480 721 _writeCommand(0x80 | addr);
wim 8:03116f75b66e 722 }
simon 1:ac48b187213c 723
simon 1:ac48b187213c 724 int TextLCD::columns() {
simon 1:ac48b187213c 725 switch (_type) {
wim 8:03116f75b66e 726 case LCD8x1:
wim 8:03116f75b66e 727 case LCD8x2:
wim 8:03116f75b66e 728 return 8;
wim 15:b70ebfffb258 729
wim 15:b70ebfffb258 730 case LCD12x2:
wim 15:b70ebfffb258 731 case LCD12x4:
wim 15:b70ebfffb258 732 return 12;
wim 8:03116f75b66e 733
wim 13:24506ba22480 734 case LCD16x1:
simon 1:ac48b187213c 735 case LCD16x2:
simon 1:ac48b187213c 736 case LCD16x2B:
wim 8:03116f75b66e 737 case LCD16x4:
wim 8:03116f75b66e 738 return 16;
wim 8:03116f75b66e 739
wim 8:03116f75b66e 740 case LCD20x2:
wim 8:03116f75b66e 741 case LCD20x4:
wim 8:03116f75b66e 742 return 20;
wim 8:03116f75b66e 743
wim 8:03116f75b66e 744 case LCD24x2:
wim 10:dd9b3a696acd 745 case LCD24x4:
wim 8:03116f75b66e 746 return 24;
wim 9:0893d986e717 747
wim 9:0893d986e717 748 case LCD40x2:
wim 15:b70ebfffb258 749 case LCD40x4:
wim 9:0893d986e717 750 return 40;
wim 8:03116f75b66e 751
wim 8:03116f75b66e 752 // Should never get here.
simon 1:ac48b187213c 753 default:
wim 8:03116f75b66e 754 return 0;
simon 1:ac48b187213c 755 }
simon 1:ac48b187213c 756 }
simon 1:ac48b187213c 757
simon 1:ac48b187213c 758 int TextLCD::rows() {
simon 1:ac48b187213c 759 switch (_type) {
wim 8:03116f75b66e 760 case LCD8x1:
wim 13:24506ba22480 761 case LCD16x1:
wim 8:03116f75b66e 762 return 1;
wim 8:03116f75b66e 763
wim 15:b70ebfffb258 764 case LCD8x2:
wim 15:b70ebfffb258 765 case LCD12x2:
simon 1:ac48b187213c 766 case LCD16x2:
simon 1:ac48b187213c 767 case LCD16x2B:
simon 1:ac48b187213c 768 case LCD20x2:
wim 8:03116f75b66e 769 case LCD24x2:
wim 9:0893d986e717 770 case LCD40x2:
wim 8:03116f75b66e 771 return 2;
wim 8:03116f75b66e 772
wim 15:b70ebfffb258 773 case LCD12x4:
wim 8:03116f75b66e 774 case LCD16x4:
wim 8:03116f75b66e 775 case LCD20x4:
wim 10:dd9b3a696acd 776 case LCD24x4:
wim 15:b70ebfffb258 777 case LCD40x4:
wim 8:03116f75b66e 778 return 4;
wim 12:6bf9d9957d31 779
wim 12:6bf9d9957d31 780 // Should never get here.
simon 1:ac48b187213c 781 default:
wim 8:03116f75b66e 782 return 0;
simon 1:ac48b187213c 783 }
simon 1:ac48b187213c 784 }
wim 10:dd9b3a696acd 785
wim 10:dd9b3a696acd 786
wim 13:24506ba22480 787 void TextLCD::setCursor(TextLCD::LCDCursor show) {
wim 15:b70ebfffb258 788
wim 15:b70ebfffb258 789 // Save new cursor mode, needed when 2 controllers are in use
wim 15:b70ebfffb258 790 _currentCursor = show;
wim 10:dd9b3a696acd 791
wim 15:b70ebfffb258 792 // Configure current LCD controller
wim 15:b70ebfffb258 793 _setCursor(_currentCursor);
wim 15:b70ebfffb258 794
wim 15:b70ebfffb258 795 }
wim 15:b70ebfffb258 796
wim 15:b70ebfffb258 797 void TextLCD::_setCursor(TextLCD::LCDCursor show) {
wim 15:b70ebfffb258 798
wim 15:b70ebfffb258 799 // Configure current LCD controller
wim 10:dd9b3a696acd 800 switch (show) {
wim 13:24506ba22480 801 case CurOff_BlkOff : _writeCommand(0x0C); // Cursor off and Blink Off
wim 11:9ec02df863a1 802 break;
wim 11:9ec02df863a1 803
wim 15:b70ebfffb258 804 case CurOn_BlkOff : _writeCommand(0x0E); // Cursor on and Blink Off
wim 11:9ec02df863a1 805 break;
wim 11:9ec02df863a1 806
wim 13:24506ba22480 807 case CurOff_BlkOn : _writeCommand(0x0D); // Cursor off and Blink On
wim 11:9ec02df863a1 808 break;
wim 11:9ec02df863a1 809
wim 15:b70ebfffb258 810 case CurOn_BlkOn : _writeCommand(0x0F); // Cursor on and Blink char
wim 11:9ec02df863a1 811 break;
wim 11:9ec02df863a1 812
wim 12:6bf9d9957d31 813 // Should never get here.
wim 10:dd9b3a696acd 814 default :
wim 11:9ec02df863a1 815 break;
wim 16:c276b75e6585 816
wim 10:dd9b3a696acd 817 }
wim 10:dd9b3a696acd 818 }
wim 10:dd9b3a696acd 819
wim 10:dd9b3a696acd 820
wim 11:9ec02df863a1 821 void TextLCD::setUDC(unsigned char c, char *udc_data) {
wim 15:b70ebfffb258 822
wim 15:b70ebfffb258 823 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 824 if(_type==LCD40x4) {
wim 15:b70ebfffb258 825 _LCDCtrl current_ctrl = _ctrl; // Temp save current controller
wim 15:b70ebfffb258 826
wim 15:b70ebfffb258 827 // Select primary controller
wim 15:b70ebfffb258 828 _ctrl=TextLCD::_LCDCtrl_0;
wim 15:b70ebfffb258 829
wim 15:b70ebfffb258 830 // Configure primary LCD controller
wim 15:b70ebfffb258 831 _setUDC(c, udc_data);
wim 15:b70ebfffb258 832
wim 15:b70ebfffb258 833 // Select 2nd controller
wim 15:b70ebfffb258 834 _ctrl=TextLCD::_LCDCtrl_1;
wim 15:b70ebfffb258 835
wim 15:b70ebfffb258 836 // Configure secondary LCD controller
wim 15:b70ebfffb258 837 _setUDC(c, udc_data);
wim 11:9ec02df863a1 838
wim 15:b70ebfffb258 839 // Restore current controller
wim 15:b70ebfffb258 840 _ctrl=current_ctrl;
wim 15:b70ebfffb258 841 }
wim 15:b70ebfffb258 842 else {
wim 15:b70ebfffb258 843 // Configure primary LCD controller
wim 15:b70ebfffb258 844 _setUDC(c, udc_data);
wim 15:b70ebfffb258 845 }
wim 15:b70ebfffb258 846
wim 15:b70ebfffb258 847 }
wim 15:b70ebfffb258 848
wim 15:b70ebfffb258 849 void TextLCD::_setUDC(unsigned char c, char *udc_data) {
wim 15:b70ebfffb258 850
wim 15:b70ebfffb258 851 // Select CG RAM for current LCD controller
wim 15:b70ebfffb258 852 _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address,
wim 15:b70ebfffb258 853 //8 sequential locations needed per UDC
wim 15:b70ebfffb258 854 // Store UDC pattern
wim 11:9ec02df863a1 855 for (int i=0; i<8; i++) {
wim 13:24506ba22480 856 _writeData(*udc_data++);
wim 11:9ec02df863a1 857 }
wim 15:b70ebfffb258 858
wim 15:b70ebfffb258 859 //Select DD RAM again for current LCD controller
wim 15:b70ebfffb258 860 int addr = getAddress(_column, _row);
wim 15:b70ebfffb258 861 _writeCommand(0x80 | addr);
wim 15:b70ebfffb258 862
wim 11:9ec02df863a1 863 }