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:
Sun Feb 10 18:43:51 2013 +0000
Revision:
14:0c32b66b14b8
Parent:
13:24506ba22480
Child:
15:b70ebfffb258
Added support for I2C and SPI bus interfaces

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
simon 1:ac48b187213c 5 *
simon 1:ac48b187213c 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
simon 1:ac48b187213c 7 * of this software and associated documentation files (the "Software"), to deal
simon 1:ac48b187213c 8 * in the Software without restriction, including without limitation the rights
simon 1:ac48b187213c 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
simon 1:ac48b187213c 10 * copies of the Software, and to permit persons to whom the Software is
simon 1:ac48b187213c 11 * furnished to do so, subject to the following conditions:
simon 1:ac48b187213c 12 *
simon 1:ac48b187213c 13 * The above copyright notice and this permission notice shall be included in
simon 1:ac48b187213c 14 * all copies or substantial portions of the Software.
simon 1:ac48b187213c 15 *
simon 1:ac48b187213c 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
simon 1:ac48b187213c 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
simon 1:ac48b187213c 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
simon 1:ac48b187213c 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
simon 1:ac48b187213c 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 1:ac48b187213c 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
simon 1:ac48b187213c 22 * THE SOFTWARE.
simon 1:ac48b187213c 23 */
simon 1:ac48b187213c 24
simon 1:ac48b187213c 25 #include "TextLCD.h"
simon 1:ac48b187213c 26 #include "mbed.h"
simon 1:ac48b187213c 27
wim 13:24506ba22480 28 TextLCD::TextLCD(PinName rs, PinName e,
wim 13:24506ba22480 29 PinName d4, PinName d5, PinName d6, PinName d7,
wim 13:24506ba22480 30 LCDType type): _rs(rs), _e(e),
wim 13:24506ba22480 31 _d(d4, d5, d6, d7),
wim 14:0c32b66b14b8 32 _cs(NC),
wim 13:24506ba22480 33 _type(type) {
wim 13:24506ba22480 34
wim 13:24506ba22480 35
wim 13:24506ba22480 36 _busType = _PinBus;
wim 13:24506ba22480 37
wim 13:24506ba22480 38 _init();
wim 13:24506ba22480 39
wim 13:24506ba22480 40 }
wim 13:24506ba22480 41
wim 13:24506ba22480 42
wim 13:24506ba22480 43 TextLCD::TextLCD(I2C *i2c, char deviceAddress, LCDType type) :
wim 13:24506ba22480 44 _rs(NC), _e(NC), _d(NC),
wim 14:0c32b66b14b8 45 _cs(NC),
wim 13:24506ba22480 46 _i2c(i2c),
simon 1:ac48b187213c 47 _type(type) {
wim 13:24506ba22480 48
wim 13:24506ba22480 49 _slaveAddress = deviceAddress;
wim 13:24506ba22480 50 _busType = _I2CBus;
simon 1:ac48b187213c 51
wim 13:24506ba22480 52
wim 13:24506ba22480 53 // Init the portexpander bus
wim 13:24506ba22480 54 _lcd_bus = 0x80;
wim 13:24506ba22480 55
wim 13:24506ba22480 56 // write the new data to the portexpander
wim 13:24506ba22480 57 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 13:24506ba22480 58
wim 13:24506ba22480 59 _init();
wim 13:24506ba22480 60
wim 13:24506ba22480 61 }
simon 1:ac48b187213c 62
wim 14:0c32b66b14b8 63
wim 14:0c32b66b14b8 64 TextLCD::TextLCD(SPI *spi, PinName cs, LCDType type) :
wim 14:0c32b66b14b8 65 _rs(NC), _e(NC), _d(NC),
wim 14:0c32b66b14b8 66 _spi(spi),
wim 14:0c32b66b14b8 67 _cs(cs),
wim 14:0c32b66b14b8 68 _type(type) {
wim 14:0c32b66b14b8 69
wim 14:0c32b66b14b8 70 _busType = _SPIBus;
wim 14:0c32b66b14b8 71
wim 14:0c32b66b14b8 72 // Setup the spi for 8 bit data, low steady state clock,
wim 14:0c32b66b14b8 73 // rising edge capture, with a 500KHz or 1MHz clock rate
wim 14:0c32b66b14b8 74 _spi->format(8,0);
wim 14:0c32b66b14b8 75 _spi->frequency(500000);
wim 14:0c32b66b14b8 76 //_spi.frequency(1000000);
wim 14:0c32b66b14b8 77
wim 14:0c32b66b14b8 78
wim 14:0c32b66b14b8 79 // Init the portexpander bus
wim 14:0c32b66b14b8 80 _lcd_bus = 0x80;
wim 14:0c32b66b14b8 81
wim 14:0c32b66b14b8 82 // write the new data to the portexpander
wim 14:0c32b66b14b8 83 _setCS(false);
wim 14:0c32b66b14b8 84 _spi->write(_lcd_bus);
wim 14:0c32b66b14b8 85 _setCS(true);
wim 14:0c32b66b14b8 86
wim 14:0c32b66b14b8 87 _init();
wim 14:0c32b66b14b8 88
wim 14:0c32b66b14b8 89 }
wim 14:0c32b66b14b8 90
wim 14:0c32b66b14b8 91
wim 14:0c32b66b14b8 92 /* Init the LCD controller
wim 13:24506ba22480 93 * 4-bit mode, number of lines, no cursor etc
wim 13:24506ba22480 94 * Clear display
wim 13:24506ba22480 95 */
wim 13:24506ba22480 96 void TextLCD::_init() {
wim 13:24506ba22480 97 // _e = 1;
wim 13:24506ba22480 98 // _rs = 0; // command mode
wim 13:24506ba22480 99
wim 13:24506ba22480 100 _setEnable(true);
wim 13:24506ba22480 101 _setRS(false); // command mode
wim 13:24506ba22480 102
wim 14:0c32b66b14b8 103 // wait(0.015); // Wait 15ms to ensure powered up
wim 14:0c32b66b14b8 104 wait_ms(15); // Wait 15ms to ensure powered up
simon 1:ac48b187213c 105
simon 1:ac48b187213c 106 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
simon 1:ac48b187213c 107 for (int i=0; i<3; i++) {
wim 13:24506ba22480 108 _writeByte(0x3);
wim 14:0c32b66b14b8 109 // wait(0.00164); // this command takes 1.64ms, so wait for it
wim 14:0c32b66b14b8 110 wait_ms(10); // this command takes 1.64ms, so wait for it
simon 1:ac48b187213c 111 }
wim 13:24506ba22480 112 _writeByte(0x2); // 4-bit mode
wim 14:0c32b66b14b8 113 // wait(0.000040f); // most instructions take 40us
wim 14:0c32b66b14b8 114 wait_us(40); // most instructions take 40us
wim 14:0c32b66b14b8 115
wim 10:dd9b3a696acd 116 // Display is now in 4-bit mode
wim 10:dd9b3a696acd 117 switch (_type) {
wim 10:dd9b3a696acd 118 case LCD8x1:
wim 13:24506ba22480 119 _writeCommand(0x20); // Function set 001 BW N F - -
wim 13:24506ba22480 120 // N=0 (1 line)
wim 13:24506ba22480 121 // F=0 (5x7 dots font)
wim 10:dd9b3a696acd 122 break;
wim 10:dd9b3a696acd 123
wim 10:dd9b3a696acd 124 case LCD24x4:
wim 10:dd9b3a696acd 125 // Special mode for KS0078
wim 13:24506ba22480 126 _writeCommand(0x2A); // Function set 001 BW N RE DH REV
wim 13:24506ba22480 127 // N=1 (Dont care for KS0078)
wim 13:24506ba22480 128 // RE=0 (Extended Regs, special mode for KS0078)
wim 13:24506ba22480 129 // DH=1 (Disp shift, special mode for KS0078)
wim 13:24506ba22480 130 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 131
wim 13:24506ba22480 132 _writeCommand(0x2E); // Function set 001 BW N RE DH REV
wim 13:24506ba22480 133 // N=1 (Dont care for KS0078)
wim 13:24506ba22480 134 // RE=1 (Ena Extended Regs, special mode for KS0078)
wim 13:24506ba22480 135 // DH=1 (Disp shift, special mode for KS0078)
wim 13:24506ba22480 136 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 137
wim 13:24506ba22480 138 _writeCommand(0x09); // Ext Function set 0000 1 FW BW NW
wim 13:24506ba22480 139 // FW=0 (5-dot font, special mode for KS0078)
wim 13:24506ba22480 140 // BW=0 (Cur BW invert disable, special mode for KS0078)
wim 13:24506ba22480 141 // NW=1 (4 Line, special mode for KS0078)
wim 10:dd9b3a696acd 142
wim 13:24506ba22480 143 _writeCommand(0x2A); // Function set 001 BW N RE DH REV
wim 13:24506ba22480 144 // N=1 (Dont care for KS0078)
wim 13:24506ba22480 145 // RE=0 (Dis. Extended Regs, special mode for KS0078)
wim 13:24506ba22480 146 // DH=1 (Disp shift, special mode for KS0078)
wim 13:24506ba22480 147 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 148 break;
wim 10:dd9b3a696acd 149
wim 10:dd9b3a696acd 150 default:
wim 13:24506ba22480 151 _writeCommand(0x28); // Function set 001 BW N F - -
wim 13:24506ba22480 152 // N=1 (2 lines)
wim 13:24506ba22480 153 // F=0 (5x7 dots font)
wim 13:24506ba22480 154 // - (Don't care)
wim 10:dd9b3a696acd 155
wim 10:dd9b3a696acd 156 break;
wim 10:dd9b3a696acd 157 }
wim 10:dd9b3a696acd 158
wim 13:24506ba22480 159 _writeCommand(0x06); // Entry Mode 0000 01 CD S
wim 13:24506ba22480 160 // Cursor Direction and Display Shift
wim 13:24506ba22480 161 // CD=1 (Cur incr)
wim 13:24506ba22480 162 // S=0 (No display shift)
wim 10:dd9b3a696acd 163
wim 13:24506ba22480 164 // _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
wim 13:24506ba22480 165 // // Display On, Cursor Off, Blink Off
wim 13:24506ba22480 166 setCursor(TextLCD::CurOff_BlkOff);
wim 11:9ec02df863a1 167
wim 10:dd9b3a696acd 168 cls();
simon 1:ac48b187213c 169 }
simon 1:ac48b187213c 170
wim 8:03116f75b66e 171
wim 13:24506ba22480 172 void TextLCD::_character(int column, int row, int c) {
wim 8:03116f75b66e 173 int addr = getAddress(column, row);
wim 8:03116f75b66e 174
wim 13:24506ba22480 175 _writeCommand(0x80 | addr);
wim 13:24506ba22480 176 _writeData(c);
simon 1:ac48b187213c 177 }
simon 1:ac48b187213c 178
wim 8:03116f75b66e 179
simon 1:ac48b187213c 180 void TextLCD::cls() {
wim 13:24506ba22480 181 _writeCommand(0x01); // cls, and set cursor to 0
wim 14:0c32b66b14b8 182 // wait(0.00164f); // This command takes 1.64 ms
wim 14:0c32b66b14b8 183 wait_ms(10); // The CLS command takes 1.64 ms.
wim 14:0c32b66b14b8 184 // Since we are not using the Busy flag, Lets be safe and take 10 ms
simon 1:ac48b187213c 185 locate(0, 0);
simon 1:ac48b187213c 186 }
simon 1:ac48b187213c 187
simon 1:ac48b187213c 188 void TextLCD::locate(int column, int row) {
simon 1:ac48b187213c 189 _column = column;
simon 1:ac48b187213c 190 _row = row;
simon 1:ac48b187213c 191 }
simon 1:ac48b187213c 192
simon 1:ac48b187213c 193 int TextLCD::_putc(int value) {
simon 1:ac48b187213c 194 if (value == '\n') {
simon 1:ac48b187213c 195 _column = 0;
simon 1:ac48b187213c 196 _row++;
simon 1:ac48b187213c 197 if (_row >= rows()) {
simon 1:ac48b187213c 198 _row = 0;
simon 1:ac48b187213c 199 }
simon 1:ac48b187213c 200 } else {
wim 13:24506ba22480 201 _character(_column, _row, value);
simon 1:ac48b187213c 202 _column++;
simon 1:ac48b187213c 203 if (_column >= columns()) {
simon 1:ac48b187213c 204 _column = 0;
simon 1:ac48b187213c 205 _row++;
simon 1:ac48b187213c 206 if (_row >= rows()) {
simon 1:ac48b187213c 207 _row = 0;
simon 1:ac48b187213c 208 }
simon 1:ac48b187213c 209 }
simon 1:ac48b187213c 210 }
simon 1:ac48b187213c 211 return value;
simon 1:ac48b187213c 212 }
simon 1:ac48b187213c 213
simon 1:ac48b187213c 214 int TextLCD::_getc() {
simon 1:ac48b187213c 215 return -1;
simon 1:ac48b187213c 216 }
simon 1:ac48b187213c 217
wim 13:24506ba22480 218
wim 13:24506ba22480 219 void TextLCD::_setEnable(bool value) {
wim 13:24506ba22480 220
wim 13:24506ba22480 221 switch(_busType) {
wim 13:24506ba22480 222 case _PinBus :
wim 13:24506ba22480 223 if (value)
wim 13:24506ba22480 224 _e = 1; // Set E bit
wim 13:24506ba22480 225 else
wim 13:24506ba22480 226 _e = 0; // Reset E bit
wim 13:24506ba22480 227
wim 13:24506ba22480 228 break;
wim 13:24506ba22480 229
wim 13:24506ba22480 230 case _I2CBus :
wim 14:0c32b66b14b8 231 if (value)
wim 14:0c32b66b14b8 232 _lcd_bus |= D_LCD_E; // Set E bit
wim 14:0c32b66b14b8 233 else
wim 14:0c32b66b14b8 234 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 13:24506ba22480 235
wim 14:0c32b66b14b8 236 // write the new data to the portexpander
wim 14:0c32b66b14b8 237 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 13:24506ba22480 238
wim 13:24506ba22480 239 break;
wim 13:24506ba22480 240
wim 13:24506ba22480 241 case _SPIBus :
wim 14:0c32b66b14b8 242 if (value)
wim 14:0c32b66b14b8 243 _lcd_bus |= D_LCD_E; // Set E bit
wim 14:0c32b66b14b8 244 else
wim 14:0c32b66b14b8 245 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 14:0c32b66b14b8 246
wim 14:0c32b66b14b8 247 // write the new data to the portexpander
wim 14:0c32b66b14b8 248 _setCS(false);
wim 14:0c32b66b14b8 249 _spi->write(_lcd_bus);
wim 14:0c32b66b14b8 250 _setCS(true);
wim 14:0c32b66b14b8 251
wim 13:24506ba22480 252 break;
wim 13:24506ba22480 253 }
wim 13:24506ba22480 254 }
wim 13:24506ba22480 255
wim 13:24506ba22480 256 void TextLCD::_setRS(bool value) {
wim 13:24506ba22480 257
wim 13:24506ba22480 258 switch(_busType) {
wim 13:24506ba22480 259 case _PinBus :
wim 13:24506ba22480 260 if (value)
wim 13:24506ba22480 261 _rs = 1; // Set RS bit
wim 13:24506ba22480 262 else
wim 13:24506ba22480 263 _rs = 0; // Reset RS bit
wim 13:24506ba22480 264
wim 13:24506ba22480 265 break;
wim 13:24506ba22480 266
wim 13:24506ba22480 267 case _I2CBus :
wim 14:0c32b66b14b8 268 if (value)
wim 14:0c32b66b14b8 269 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 14:0c32b66b14b8 270 else
wim 14:0c32b66b14b8 271 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 13:24506ba22480 272
wim 14:0c32b66b14b8 273 // write the new data to the portexpander
wim 14:0c32b66b14b8 274 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 13:24506ba22480 275
wim 13:24506ba22480 276 break;
wim 13:24506ba22480 277
wim 13:24506ba22480 278 case _SPIBus :
wim 14:0c32b66b14b8 279 if (value)
wim 14:0c32b66b14b8 280 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 14:0c32b66b14b8 281 else
wim 14:0c32b66b14b8 282 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 14:0c32b66b14b8 283
wim 14:0c32b66b14b8 284 // write the new data to the portexpander
wim 14:0c32b66b14b8 285 _setCS(false);
wim 14:0c32b66b14b8 286 _spi->write(_lcd_bus);
wim 14:0c32b66b14b8 287 _setCS(true);
wim 14:0c32b66b14b8 288
wim 13:24506ba22480 289 break;
wim 13:24506ba22480 290 }
wim 13:24506ba22480 291
wim 13:24506ba22480 292 }
wim 13:24506ba22480 293
wim 13:24506ba22480 294 void TextLCD::_setData(int value) {
wim 13:24506ba22480 295 int data;
wim 13:24506ba22480 296
wim 13:24506ba22480 297 switch(_busType) {
wim 13:24506ba22480 298 case _PinBus :
wim 13:24506ba22480 299 _d = value & 0x0F; // Write Databits
wim 13:24506ba22480 300
wim 13:24506ba22480 301 break;
wim 13:24506ba22480 302
wim 13:24506ba22480 303 case _I2CBus :
wim 13:24506ba22480 304 data = value & 0x0F;
wim 13:24506ba22480 305 if (data & 0x01)
wim 13:24506ba22480 306 _lcd_bus |= D_LCD_D4; // Set Databit
wim 13:24506ba22480 307 else
wim 13:24506ba22480 308 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 13:24506ba22480 309
wim 13:24506ba22480 310 if (data & 0x02)
wim 13:24506ba22480 311 _lcd_bus |= D_LCD_D5; // Set Databit
wim 13:24506ba22480 312 else
wim 13:24506ba22480 313 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 13:24506ba22480 314
wim 13:24506ba22480 315 if (data & 0x04)
wim 13:24506ba22480 316 _lcd_bus |= D_LCD_D6; // Set Databit
wim 13:24506ba22480 317 else
wim 13:24506ba22480 318 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 13:24506ba22480 319
wim 13:24506ba22480 320 if (data & 0x08)
wim 13:24506ba22480 321 _lcd_bus |= D_LCD_D7; // Set Databit
wim 13:24506ba22480 322 else
wim 13:24506ba22480 323 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 13:24506ba22480 324
wim 13:24506ba22480 325 // write the new data to the portexpander
wim 13:24506ba22480 326 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 13:24506ba22480 327
wim 13:24506ba22480 328 break;
wim 13:24506ba22480 329
wim 13:24506ba22480 330 case _SPIBus :
wim 14:0c32b66b14b8 331
wim 14:0c32b66b14b8 332 data = value & 0x0F;
wim 14:0c32b66b14b8 333 if (data & 0x01)
wim 14:0c32b66b14b8 334 _lcd_bus |= D_LCD_D4; // Set Databit
wim 14:0c32b66b14b8 335 else
wim 14:0c32b66b14b8 336 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 14:0c32b66b14b8 337
wim 14:0c32b66b14b8 338 if (data & 0x02)
wim 14:0c32b66b14b8 339 _lcd_bus |= D_LCD_D5; // Set Databit
wim 14:0c32b66b14b8 340 else
wim 14:0c32b66b14b8 341 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 14:0c32b66b14b8 342
wim 14:0c32b66b14b8 343 if (data & 0x04)
wim 14:0c32b66b14b8 344 _lcd_bus |= D_LCD_D6; // Set Databit
wim 14:0c32b66b14b8 345 else
wim 14:0c32b66b14b8 346 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 14:0c32b66b14b8 347
wim 14:0c32b66b14b8 348 if (data & 0x08)
wim 14:0c32b66b14b8 349 _lcd_bus |= D_LCD_D7; // Set Databit
wim 14:0c32b66b14b8 350 else
wim 14:0c32b66b14b8 351 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 14:0c32b66b14b8 352
wim 14:0c32b66b14b8 353 // write the new data to the portexpander
wim 14:0c32b66b14b8 354 _setCS(false);
wim 14:0c32b66b14b8 355 _spi->write(_lcd_bus);
wim 14:0c32b66b14b8 356 _setCS(true);
wim 14:0c32b66b14b8 357
wim 14:0c32b66b14b8 358 break;
wim 13:24506ba22480 359 }
wim 13:24506ba22480 360
wim 13:24506ba22480 361 }
wim 13:24506ba22480 362
wim 13:24506ba22480 363
wim 14:0c32b66b14b8 364 // Set CS line. Only used for SPI bus
wim 14:0c32b66b14b8 365 void TextLCD::_setCS(bool value) {
wim 14:0c32b66b14b8 366
wim 14:0c32b66b14b8 367 if (value)
wim 14:0c32b66b14b8 368 _cs = 1; // Set CS pin
wim 14:0c32b66b14b8 369 else
wim 14:0c32b66b14b8 370 _cs = 0; // Reset CS pin
wim 14:0c32b66b14b8 371
wim 14:0c32b66b14b8 372 }
wim 14:0c32b66b14b8 373
wim 14:0c32b66b14b8 374
wim 13:24506ba22480 375
wim 13:24506ba22480 376 void TextLCD::_writeByte(int value) {
wim 13:24506ba22480 377 // _d = value >> 4;
wim 13:24506ba22480 378 _setData(value >> 4);
wim 14:0c32b66b14b8 379 // wait(0.000040f); // most instructions take 40us
wim 14:0c32b66b14b8 380 wait_us(40); // most instructions take 40us
wim 13:24506ba22480 381 // _e = 0;
wim 13:24506ba22480 382 _setEnable(false);
wim 14:0c32b66b14b8 383 // wait(0.000040f);
wim 14:0c32b66b14b8 384 wait_us(40); // most instructions take 40us
wim 13:24506ba22480 385 // _e = 1;
wim 13:24506ba22480 386 _setEnable(true);
wim 13:24506ba22480 387 // _d = value >> 0;
wim 13:24506ba22480 388 _setData(value >> 0);
wim 14:0c32b66b14b8 389 // wait(0.000040f);
wim 14:0c32b66b14b8 390 wait_us(40); // most instructions take 40us
wim 13:24506ba22480 391 // _e = 0;
wim 13:24506ba22480 392 _setEnable(false);
wim 14:0c32b66b14b8 393 // wait(0.000040f); // most instructions take 40us
wim 14:0c32b66b14b8 394 wait_us(40); // most instructions take 40us
wim 13:24506ba22480 395 // _e = 1;
wim 13:24506ba22480 396 _setEnable(true);
simon 1:ac48b187213c 397 }
simon 1:ac48b187213c 398
wim 13:24506ba22480 399 void TextLCD::_writeCommand(int command) {
wim 13:24506ba22480 400 // _rs = 0;
wim 13:24506ba22480 401 _setRS(false);
wim 13:24506ba22480 402 _writeByte(command);
simon 1:ac48b187213c 403 }
simon 1:ac48b187213c 404
wim 13:24506ba22480 405 void TextLCD::_writeData(int data) {
wim 13:24506ba22480 406 // _rs = 1;
wim 13:24506ba22480 407 _setRS(true);
wim 13:24506ba22480 408 _writeByte(data);
simon 1:ac48b187213c 409 }
simon 1:ac48b187213c 410
wim 8:03116f75b66e 411
wim 8:03116f75b66e 412 #if (0)
wim 8:03116f75b66e 413 // This is the original method.
wim 8:03116f75b66e 414 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
wim 8:03116f75b66e 415 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 416 //
wim 13:24506ba22480 417 int TextLCD::_address(int column, int row) {
simon 1:ac48b187213c 418 switch (_type) {
simon 1:ac48b187213c 419 case LCD20x4:
simon 1:ac48b187213c 420 switch (row) {
simon 1:ac48b187213c 421 case 0:
simon 1:ac48b187213c 422 return 0x80 + column;
simon 1:ac48b187213c 423 case 1:
simon 1:ac48b187213c 424 return 0xc0 + column;
simon 1:ac48b187213c 425 case 2:
simon 1:ac48b187213c 426 return 0x94 + column;
simon 1:ac48b187213c 427 case 3:
simon 1:ac48b187213c 428 return 0xd4 + column;
simon 1:ac48b187213c 429 }
simon 1:ac48b187213c 430 case LCD16x2B:
simon 4:bf5b706f8d32 431 return 0x80 + (row * 40) + column;
simon 1:ac48b187213c 432 case LCD16x2:
simon 1:ac48b187213c 433 case LCD20x2:
simon 1:ac48b187213c 434 default:
simon 4:bf5b706f8d32 435 return 0x80 + (row * 0x40) + column;
simon 1:ac48b187213c 436 }
simon 1:ac48b187213c 437 }
wim 8:03116f75b66e 438 #endif
wim 8:03116f75b66e 439
wim 8:03116f75b66e 440
wim 8:03116f75b66e 441 // This replaces the original method.
wim 8:03116f75b66e 442 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 13:24506ba22480 443 int TextLCD::_address(int column, int row) {
wim 8:03116f75b66e 444 return 0x80 | getAddress(column, row);
wim 8:03116f75b66e 445 }
wim 8:03116f75b66e 446
wim 8:03116f75b66e 447 // This is new method to return the memory address based on row, column and displaytype.
wim 8:03116f75b66e 448 //
wim 8:03116f75b66e 449 int TextLCD::getAddress(int column, int row) {
wim 8:03116f75b66e 450
wim 8:03116f75b66e 451 switch (_type) {
wim 8:03116f75b66e 452 case LCD8x1:
wim 8:03116f75b66e 453 return 0x00 + column;
wim 8:03116f75b66e 454
wim 13:24506ba22480 455 case LCD16x1:
wim 13:24506ba22480 456 // LCD16x1 is a special layout of LCD8x2
wim 13:24506ba22480 457 if (column<8)
wim 13:24506ba22480 458 return 0x00 + column;
wim 13:24506ba22480 459 else
wim 13:24506ba22480 460 return 0x40 + (column - 8);
wim 13:24506ba22480 461
wim 8:03116f75b66e 462 case LCD16x4:
wim 8:03116f75b66e 463 switch (row) {
wim 8:03116f75b66e 464 case 0:
wim 8:03116f75b66e 465 return 0x00 + column;
wim 8:03116f75b66e 466 case 1:
wim 8:03116f75b66e 467 return 0x40 + column;
wim 8:03116f75b66e 468 case 2:
wim 8:03116f75b66e 469 return 0x10 + column;
wim 8:03116f75b66e 470 case 3:
wim 8:03116f75b66e 471 return 0x50 + column;
wim 8:03116f75b66e 472 }
wim 8:03116f75b66e 473
wim 8:03116f75b66e 474 case LCD20x4:
wim 8:03116f75b66e 475 switch (row) {
wim 8:03116f75b66e 476 case 0:
wim 8:03116f75b66e 477 return 0x00 + column;
wim 8:03116f75b66e 478 case 1:
wim 8:03116f75b66e 479 return 0x40 + column;
wim 8:03116f75b66e 480 case 2:
wim 8:03116f75b66e 481 return 0x14 + column;
wim 8:03116f75b66e 482 case 3:
wim 8:03116f75b66e 483 return 0x54 + column;
wim 8:03116f75b66e 484 }
wim 8:03116f75b66e 485
wim 10:dd9b3a696acd 486 // Special mode for KS0078
wim 10:dd9b3a696acd 487 case LCD24x4:
wim 10:dd9b3a696acd 488 switch (row) {
wim 10:dd9b3a696acd 489 case 0:
wim 10:dd9b3a696acd 490 return 0x00 + column;
wim 10:dd9b3a696acd 491 case 1:
wim 10:dd9b3a696acd 492 return 0x20 + column;
wim 10:dd9b3a696acd 493 case 2:
wim 10:dd9b3a696acd 494 return 0x40 + column;
wim 10:dd9b3a696acd 495 case 3:
wim 10:dd9b3a696acd 496 return 0x60 + column;
wim 10:dd9b3a696acd 497 }
wim 10:dd9b3a696acd 498
wim 8:03116f75b66e 499 // Not sure about this one, seems wrong.
wim 8:03116f75b66e 500 case LCD16x2B:
wim 8:03116f75b66e 501 return 0x00 + (row * 40) + column;
wim 8:03116f75b66e 502
wim 8:03116f75b66e 503 case LCD8x2:
wim 8:03116f75b66e 504 case LCD16x2:
wim 8:03116f75b66e 505 case LCD20x2:
wim 8:03116f75b66e 506 case LCD24x2:
wim 9:0893d986e717 507 case LCD40x2:
wim 8:03116f75b66e 508 return 0x00 + (row * 0x40) + column;
wim 8:03116f75b66e 509
wim 8:03116f75b66e 510 // Should never get here.
wim 8:03116f75b66e 511 default:
wim 8:03116f75b66e 512 return 0x00;
wim 8:03116f75b66e 513 }
wim 8:03116f75b66e 514 }
wim 8:03116f75b66e 515
wim 8:03116f75b66e 516
wim 13:24506ba22480 517 // Added for consistency. Set row, column and update memoryaddress.
wim 8:03116f75b66e 518 //
wim 8:03116f75b66e 519 void TextLCD::setAddress(int column, int row) {
wim 8:03116f75b66e 520
wim 8:03116f75b66e 521 locate(column, row);
wim 8:03116f75b66e 522
wim 8:03116f75b66e 523 int addr = getAddress(column, row);
wim 8:03116f75b66e 524
wim 13:24506ba22480 525 _writeCommand(0x80 | addr);
wim 8:03116f75b66e 526 }
simon 1:ac48b187213c 527
simon 1:ac48b187213c 528 int TextLCD::columns() {
simon 1:ac48b187213c 529 switch (_type) {
wim 8:03116f75b66e 530 case LCD8x1:
wim 8:03116f75b66e 531 case LCD8x2:
wim 8:03116f75b66e 532 return 8;
wim 8:03116f75b66e 533
wim 13:24506ba22480 534 case LCD16x1:
simon 1:ac48b187213c 535 case LCD16x2:
simon 1:ac48b187213c 536 case LCD16x2B:
wim 8:03116f75b66e 537 case LCD16x4:
wim 8:03116f75b66e 538 return 16;
wim 8:03116f75b66e 539
wim 8:03116f75b66e 540 case LCD20x2:
wim 8:03116f75b66e 541 case LCD20x4:
wim 8:03116f75b66e 542 return 20;
wim 8:03116f75b66e 543
wim 8:03116f75b66e 544 case LCD24x2:
wim 10:dd9b3a696acd 545 case LCD24x4:
wim 8:03116f75b66e 546 return 24;
wim 9:0893d986e717 547
wim 9:0893d986e717 548 case LCD40x2:
wim 9:0893d986e717 549 return 40;
wim 8:03116f75b66e 550
wim 8:03116f75b66e 551 // Should never get here.
simon 1:ac48b187213c 552 default:
wim 8:03116f75b66e 553 return 0;
simon 1:ac48b187213c 554 }
simon 1:ac48b187213c 555 }
simon 1:ac48b187213c 556
simon 1:ac48b187213c 557 int TextLCD::rows() {
simon 1:ac48b187213c 558 switch (_type) {
wim 8:03116f75b66e 559 case LCD8x1:
wim 13:24506ba22480 560 case LCD16x1:
wim 8:03116f75b66e 561 return 1;
wim 8:03116f75b66e 562
wim 8:03116f75b66e 563 case LCD8x2:
simon 1:ac48b187213c 564 case LCD16x2:
simon 1:ac48b187213c 565 case LCD16x2B:
simon 1:ac48b187213c 566 case LCD20x2:
wim 8:03116f75b66e 567 case LCD24x2:
wim 9:0893d986e717 568 case LCD40x2:
wim 8:03116f75b66e 569 return 2;
wim 8:03116f75b66e 570
wim 8:03116f75b66e 571 case LCD16x4:
wim 8:03116f75b66e 572 case LCD20x4:
wim 10:dd9b3a696acd 573 case LCD24x4:
wim 8:03116f75b66e 574 return 4;
wim 12:6bf9d9957d31 575
wim 12:6bf9d9957d31 576 // Should never get here.
simon 1:ac48b187213c 577 default:
wim 8:03116f75b66e 578 return 0;
simon 1:ac48b187213c 579 }
simon 1:ac48b187213c 580 }
wim 10:dd9b3a696acd 581
wim 10:dd9b3a696acd 582
wim 13:24506ba22480 583 void TextLCD::setCursor(TextLCD::LCDCursor show) {
wim 10:dd9b3a696acd 584
wim 10:dd9b3a696acd 585 switch (show) {
wim 13:24506ba22480 586 case CurOff_BlkOff : _writeCommand(0x0C); // Cursor off and Blink Off
wim 11:9ec02df863a1 587 wait_us(40);
wim 11:9ec02df863a1 588 _cursor = show;
wim 11:9ec02df863a1 589 break;
wim 11:9ec02df863a1 590
wim 13:24506ba22480 591 case CurOn_BlkOff : _writeCommand(0x0E); // Cursor on and Blink Off
wim 11:9ec02df863a1 592 wait_us(40);
wim 11:9ec02df863a1 593 _cursor = show;
wim 11:9ec02df863a1 594 break;
wim 11:9ec02df863a1 595
wim 13:24506ba22480 596 case CurOff_BlkOn : _writeCommand(0x0D); // Cursor off and Blink On
wim 11:9ec02df863a1 597 wait_us(40);
wim 11:9ec02df863a1 598 _cursor = show;
wim 11:9ec02df863a1 599 break;
wim 11:9ec02df863a1 600
wim 13:24506ba22480 601 case CurOn_BlkOn : _writeCommand(0x0F); // Cursor on and Blink char
wim 11:9ec02df863a1 602 wait_us(40);
wim 11:9ec02df863a1 603 _cursor = show;
wim 11:9ec02df863a1 604 break;
wim 11:9ec02df863a1 605
wim 12:6bf9d9957d31 606 // Should never get here.
wim 10:dd9b3a696acd 607 default :
wim 11:9ec02df863a1 608 break;
wim 10:dd9b3a696acd 609
wim 10:dd9b3a696acd 610 }
wim 11:9ec02df863a1 611
wim 10:dd9b3a696acd 612 }
wim 10:dd9b3a696acd 613
wim 10:dd9b3a696acd 614
wim 11:9ec02df863a1 615 void TextLCD::setUDC(unsigned char c, char *udc_data) {
wim 13:24506ba22480 616 _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address
wim 11:9ec02df863a1 617
wim 11:9ec02df863a1 618 for (int i=0; i<8; i++) {
wim 13:24506ba22480 619 _writeData(*udc_data++);
wim 11:9ec02df863a1 620 }
wim 11:9ec02df863a1 621 }
wim 10:dd9b3a696acd 622
wim 10:dd9b3a696acd 623