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
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
Diff: TextLCD.cpp
- Revision:
- 38:cbe275b0b647
- Parent:
- 37:ce348c002929
- Child:
- 39:e9c2319de9c5
--- a/TextLCD.cpp Sun Mar 29 13:08:03 2015 +0000 +++ b/TextLCD.cpp Sat Apr 18 11:33:02 2015 +0000 @@ -18,6 +18,8 @@ * 2014, v15: WH, Added AC780 support, added I2C expander modules, fixed setBacklight() for inverted logic modules. Fixed bug in LCD_SPI_N define * 2014, v16: WH, Added ST7070 and KS0073 support, added setIcon(), clrIcon() and setInvert() method for supported devices * 2015, v17: WH, Clean up low-level _writeCommand() and _writeData(), Added support for alternative fonttables (eg PCF21XX), Added ST7066_ACM controller for ACM1602 module + * 2015, v18: WH, Performance improvement I2C portexpander + * 2015, v19: WH, Fixed Adafruit I2C/SPI portexpander pinmappings, fixed SYDZ Backlight * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,6 +71,8 @@ * @return none */ void TextLCD_Base::_init(_LCDDatalength dl) { + + wait_ms(100); // Wait 100ms to ensure powered up // Select and configure second LCD controller when needed if(_type==LCD40x4) { @@ -101,8 +105,6 @@ int _lines=0; // Set lines (Ext Instr Set), temporary variable. this->_setRS(false); // command mode - - wait_ms(20); // Wait 20ms to ensure powered up if (dl == _LCD_DL_4) { // The Controller could be in 8 bit mode (power-on reset) or in 4 bit mode (warm reboot) at this point. @@ -110,18 +112,18 @@ // between the uP and the LCD can only write the 4 most significant bits (Most Significant Nibble, MSN). // In 4 bit mode the LCD expects the MSN first, followed by the LSN. // - // Current state: 8 bit mode | 4 bit mode, MSN is next | 4 bit mode, LSN is next + // Current state: 8 bit mode | 4 bit mode, MSN is next | 4 bit mode, LSN is next //------------------------------------------------------------------------------------------------- - _writeNibble(0x3); // set 8 bit mode (MSN) and dummy LSN, | set 8 bit mode (MSN), | set dummy LSN, - // remains in 8 bit mode | change to 8 bit mode | remains in 4 bit mode + _writeNibble(0x3); // set 8 bit mode (MSN) and dummy LSN, | set 8 bit mode (MSN), | set dummy LSN, + // remains in 8 bit mode | remains in 4 bit mode | remains in 4 bit mode wait_ms(15); // - _writeNibble(0x3); // set 8 bit mode and dummy LSN, | set 8 bit mode and dummy LSN, | set 8bit mode (MSN), - // remains in 8 bit mode | remains in 8 bit mode | remains in 4 bit mode + _writeNibble(0x3); // set 8 bit mode (MSN) and dummy LSN, | set dummy LSN, | set 8bit mode (MSN), + // remains in 8 bit mode | change to 8 bit mode | remains in 4 bit mode wait_ms(15); // - _writeNibble(0x3); // set 8 bit mode and dummy LSN, | set 8 bit mode and dummy LSN, | set dummy LSN, - // remains in 8 bit mode | remains in 8 bit mode | change to 8 bit mode + _writeNibble(0x3); // set 8 bit mode (MSN) and dummy LSN, | set 8 bit mode (MSN) and dummy LSN, | set dummy LSN, + // remains in 8 bit mode | remains in 8 bit mode | change to 8 bit mode wait_ms(15); // // Controller is now in 8 bit mode @@ -132,6 +134,10 @@ // Controller is now in 4-bit mode // Note: 4/8 bit mode is ignored for most native SPI and I2C devices. They dont use the parallel bus. // However, _writeNibble() method is void anyway for native SPI and I2C devices. + } + else { + // Reset in 8 bit mode, final Function set will follow + _writeCommand(0x30); // Function set 0 0 1 DL=1 N F x x } // Device specific initialisations: DC/DC converter to generate VLCD or VLED, number of lines etc @@ -1422,7 +1428,7 @@ // Enable is Low this->_setEnable(true); - this->_setData(value); // Low nibble + this->_setData(value); // Low nibble of value on D4..D7 wait_us(1); // Data setup time this->_setEnable(false); wait_us(1); // Datahold time @@ -2676,8 +2682,8 @@ // No Hardware Enable pin _e2 = NULL; //Construct dummy pin } - - _init(_LCD_DL_4); // Set Datalength to 4 bit for mbed bus interfaces + + _init(_LCD_DL_4); // Set Datalength to 4 bit for mbed bus interfaces } /** Destruct a TextLCD interface for using regular mbed pins @@ -2791,7 +2797,7 @@ // _writeRegister(OLAT, 0x00); // Output Latch // Init the portexpander bus - _lcd_bus = D_LCD_BUS_DEF; + _lcd_bus = LCD_BUS_I2C_DEF; // write the new data to the portexpander _writeRegister(GPIO, _lcd_bus); @@ -2799,7 +2805,7 @@ // PCF8574 of PCF8574A portexpander // Init the portexpander bus - _lcd_bus = D_LCD_BUS_DEF; + _lcd_bus = LCD_BUS_I2C_DEF; // write the new data to the portexpander _i2c->write(_slaveAddress, &_lcd_bus, 1); @@ -2814,18 +2820,18 @@ if(_ctrl_idx==_LCDCtrl_0) { if (value) { - _lcd_bus |= D_LCD_E; // Set E bit + _lcd_bus |= LCD_BUS_I2C_E; // Set E bit } else { - _lcd_bus &= ~D_LCD_E; // Reset E bit + _lcd_bus &= ~LCD_BUS_I2C_E; // Reset E bit } } else { if (value) { - _lcd_bus |= D_LCD_E2; // Set E2 bit + _lcd_bus |= LCD_BUS_I2C_E2; // Set E2 bit } else { - _lcd_bus &= ~D_LCD_E2; // Reset E2bit + _lcd_bus &= ~LCD_BUS_I2C_E2; // Reset E2bit } } } @@ -2856,10 +2862,10 @@ void TextLCD_I2C::_setRS(bool value) { if (value) { - _lcd_bus |= D_LCD_RS; // Set RS bit + _lcd_bus |= LCD_BUS_I2C_RS; // Set RS bit } else { - _lcd_bus &= ~D_LCD_RS; // Reset RS bit + _lcd_bus &= ~LCD_BUS_I2C_RS; // Reset RS bit } #if (MCP23008==1) @@ -2880,10 +2886,10 @@ void TextLCD_I2C::_setBL(bool value) { if (value) { - _lcd_bus |= D_LCD_BL; // Set BL bit + _lcd_bus |= LCD_BUS_I2C_BL; // Set BL bit } else { - _lcd_bus &= ~D_LCD_BL; // Reset BL bit + _lcd_bus &= ~LCD_BUS_I2C_BL; // Reset BL bit } #if (MCP23008==1) @@ -2899,40 +2905,76 @@ #endif } - +#if(0) +// New optimized v018 +// Test faster _writeByte 0.11s vs 0.27s for a 20x4 fillscreen (PCF8574), same as v018 +// Place the 4bit data in the databus shadowvalue +// Used for mbed I2C bus expander +const char _LCD_DATA_BITS[16] = { + 0x00, + ( LCD_BUS_I2C_D4), + ( LCD_BUS_I2C_D5 ), + ( LCD_BUS_I2C_D5 | LCD_BUS_I2C_D4), + ( LCD_BUS_I2C_D6 ), + ( LCD_BUS_I2C_D6 | LCD_BUS_I2C_D4), + ( LCD_BUS_I2C_D6 | LCD_BUS_I2C_D5 ), + ( LCD_BUS_I2C_D6 | LCD_BUS_I2C_D5 | LCD_BUS_I2C_D4), + (LCD_BUS_I2C_D7 ), + (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D4), + (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D5 ), + (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D5 | LCD_BUS_I2C_D4), + (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D6 ), + (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D6 | LCD_BUS_I2C_D4), + (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D6 | LCD_BUS_I2C_D5 ), + (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D6 | LCD_BUS_I2C_D5 | LCD_BUS_I2C_D4) + }; +void TextLCD_I2C::_setDataBits(int value) { + + //Clear all databits + _lcd_bus &= ~LCD_BUS_I2C_MSK; + + // Set bit by bit to support any mapping of expander portpins to LCD pins + _lcd_bus |= _LCD_DATA_BITS[value & 0x0F]; +} + +#else +//orig v017 +// Test faster _writeByte 0.11s vs 0.27s for a 20x4 fillscreen (PCF8574) // Place the 4bit data in the databus shadowvalue // Used for mbed I2C bus expander void TextLCD_I2C::_setDataBits(int value) { // Set bit by bit to support any mapping of expander portpins to LCD pins if (value & 0x01){ - _lcd_bus |= D_LCD_D4; // Set Databit + _lcd_bus |= LCD_BUS_I2C_D4; // Set Databit } else { - _lcd_bus &= ~D_LCD_D4; // Reset Databit + _lcd_bus &= ~LCD_BUS_I2C_D4; // Reset Databit } if (value & 0x02){ - _lcd_bus |= D_LCD_D5; // Set Databit + _lcd_bus |= LCD_BUS_I2C_D5; // Set Databit } else { - _lcd_bus &= ~D_LCD_D5; // Reset Databit + _lcd_bus &= ~LCD_BUS_I2C_D5; // Reset Databit } if (value & 0x04) { - _lcd_bus |= D_LCD_D6; // Set Databit + _lcd_bus |= LCD_BUS_I2C_D6; // Set Databit } else { - _lcd_bus &= ~D_LCD_D6; // Reset Databit + _lcd_bus &= ~LCD_BUS_I2C_D6; // Reset Databit } if (value & 0x08) { - _lcd_bus |= D_LCD_D7; // Set Databit + _lcd_bus |= LCD_BUS_I2C_D7; // Set Databit } else { - _lcd_bus &= ~D_LCD_D7; // Reset Databit + _lcd_bus &= ~LCD_BUS_I2C_D7; // Reset Databit } } +#endif + // Place the 4bit data on the databus // Used for mbed pins, I2C bus expander or SPI shifregister @@ -3032,8 +3074,7 @@ TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) : TextLCD_Base(type, ctrl), _spi(spi), - _cs(cs) { - + _cs(cs) { // Init cs _cs = 1; @@ -3043,8 +3084,10 @@ _spi->frequency(500000); //_spi.frequency(1000000); + wait_ms(100); // Wait 100ms to ensure LCD powered up + // Init the portexpander bus - _lcd_bus = D_LCD_BUS_DEF; + _lcd_bus = LCD_BUS_SPI_DEF; // write the new data to the portexpander _cs = 0; @@ -3060,18 +3103,18 @@ if(_ctrl_idx==_LCDCtrl_0) { if (value) { - _lcd_bus |= D_LCD_E; // Set E bit + _lcd_bus |= LCD_BUS_SPI_E; // Set E bit } else { - _lcd_bus &= ~D_LCD_E; // Reset E bit + _lcd_bus &= ~LCD_BUS_SPI_E; // Reset E bit } } else { if (value) { - _lcd_bus |= D_LCD_E2; // Set E2 bit + _lcd_bus |= LCD_BUS_SPI_E2; // Set E2 bit } else { - _lcd_bus &= ~D_LCD_E2; // Reset E2 bit + _lcd_bus &= ~LCD_BUS_SPI_E2; // Reset E2 bit } } @@ -3086,10 +3129,10 @@ void TextLCD_SPI::_setRS(bool value) { if (value) { - _lcd_bus |= D_LCD_RS; // Set RS bit + _lcd_bus |= LCD_BUS_SPI_RS; // Set RS bit } else { - _lcd_bus &= ~D_LCD_RS; // Reset RS bit + _lcd_bus &= ~LCD_BUS_SPI_RS; // Reset RS bit } // write the new data to the SPI portexpander @@ -3103,10 +3146,10 @@ void TextLCD_SPI::_setBL(bool value) { if (value) { - _lcd_bus |= D_LCD_BL; // Set BL bit + _lcd_bus |= LCD_BUS_SPI_BL; // Set BL bit } else { - _lcd_bus &= ~D_LCD_BL; // Reset BL bit + _lcd_bus &= ~LCD_BUS_SPI_BL; // Reset BL bit } // write the new data to the SPI portexpander @@ -3121,31 +3164,31 @@ // Set bit by bit to support any mapping of expander portpins to LCD pins if (value & 0x01) { - _lcd_bus |= D_LCD_D4; // Set Databit + _lcd_bus |= LCD_BUS_SPI_D4; // Set Databit } else { - _lcd_bus &= ~D_LCD_D4; // Reset Databit + _lcd_bus &= ~LCD_BUS_SPI_D4; // Reset Databit } if (value & 0x02) { - _lcd_bus |= D_LCD_D5; // Set Databit + _lcd_bus |= LCD_BUS_SPI_D5; // Set Databit } else { - _lcd_bus &= ~D_LCD_D5; // Reset Databit + _lcd_bus &= ~LCD_BUS_SPI_D5; // Reset Databit } if (value & 0x04) { - _lcd_bus |= D_LCD_D6; // Set Databit + _lcd_bus |= LCD_BUS_SPI_D6; // Set Databit } else { - _lcd_bus &= ~D_LCD_D6; // Reset Databit + _lcd_bus &= ~LCD_BUS_SPI_D6; // Reset Databit } if (value & 0x08) { - _lcd_bus |= D_LCD_D7; // Set Databit + _lcd_bus |= LCD_BUS_SPI_D7; // Set Databit } else { - _lcd_bus &= ~D_LCD_D7; // Reset Databit + _lcd_bus &= ~LCD_BUS_SPI_D7; // Reset Databit } // write the new data to the SPI portexpander