TextLCD
Revision 15:b70ebfffb258, committed 2013-02-19
- Comitter:
- wim
- Date:
- Tue Feb 19 22:09:09 2013 +0000
- Parent:
- 14:0c32b66b14b8
- Child:
- 16:c276b75e6585
- Commit message:
- Working testversion for 40x4.; Fixed cursor problems.; Fixed UDC problems, always return to DD RAM.
Changed in this revision
TextLCD.cpp | Show annotated file Show diff for this revision Revisions of this file |
TextLCD.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/TextLCD.cpp Sun Feb 10 18:43:51 2013 +0000 +++ b/TextLCD.cpp Tue Feb 19 22:09:09 2013 +0000 @@ -2,6 +2,7 @@ * Copyright (c) 2007-2010, sford, http://mbed.org * 2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs * 2013, v02: WH, Added I2C and SPI bus interfaces + * 2013, v03: WH, Added support for LCD40x4 which uses 2 controllers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,13 +26,21 @@ #include "TextLCD.h" #include "mbed.h" + +/* Create a TextLCD interface for using regular mbed pins + * + * @param rs Instruction/data control line + * @param e Enable line (clock) + * @param d4-d7 Data lines for using as a 4-bit interface + * @param type Sets the panel size/addressing mode (default = LCD16x2) + * @param e2 Enable2 line (clock for second controller, LCD40x4 only) + */ TextLCD::TextLCD(PinName rs, PinName e, PinName d4, PinName d5, PinName d6, PinName d7, - LCDType type): _rs(rs), _e(e), - _d(d4, d5, d6, d7), - _cs(NC), - _type(type) { - + LCDType type, PinName e2) : _rs(rs), _e(e), _e2(e2), + _d(d4, d5, d6, d7), + _cs(NC), + _type(type) { _busType = _PinBus; @@ -39,19 +48,25 @@ } - +/* Create a TextLCD interface using an I2C PC8574 portexpander + * + * @param i2c I2C Bus + * @param deviceAddress I2C slave address (PCF8574) + * @param type Sets the panel size/addressing mode (default = LCD16x2) + */ TextLCD::TextLCD(I2C *i2c, char deviceAddress, LCDType type) : - _rs(NC), _e(NC), _d(NC), - _cs(NC), - _i2c(i2c), + _rs(NC), _e(NC), _e2(NC), + _d(NC), + _i2c(i2c), + _cs(NC), _type(type) { - + _slaveAddress = deviceAddress; _busType = _I2CBus; // Init the portexpander bus - _lcd_bus = 0x80; + _lcd_bus = D_LCD_BUS_DEF; // write the new data to the portexpander _i2c->write(_slaveAddress, &_lcd_bus, 1); @@ -60,11 +75,17 @@ } - + /* Create a TextLCD interface using an SPI 74595 portexpander + * + * @param spi SPI Bus + * @param cs chip select pin (active low) + * @param type Sets the panel size/addressing mode (default = LCD16x2) + */ TextLCD::TextLCD(SPI *spi, PinName cs, LCDType type) : - _rs(NC), _e(NC), _d(NC), - _spi(spi), - _cs(cs), + _rs(NC), _e(NC), _e2(NC), + _d(NC), + _spi(spi), + _cs(cs), _type(type) { _busType = _SPIBus; @@ -77,7 +98,7 @@ // Init the portexpander bus - _lcd_bus = 0x80; + _lcd_bus = D_LCD_BUS_DEF; // write the new data to the portexpander _setCS(false); @@ -89,47 +110,75 @@ } -/* Init the LCD controller - * 4-bit mode, number of lines, no cursor etc +/* Init the LCD Controller(s) * Clear display */ void TextLCD::_init() { -// _e = 1; -// _rs = 0; // command mode + + // Select and configure second LCD controller when needed + if(_type==LCD40x4) { + _ctrl=TextLCD::_LCDCtrl_1; // Select 2nd controller + + _initCtrl(); // Init 2nd controller + + // Secondary LCD controller Clearscreen + _writeCommand(0x01); // cls, and set cursor to 0 + wait_ms(10); // The CLS command takes 1.64 ms. + // Since we are not using the Busy flag, Lets be safe and take 10 ms + + } + + // Select and configure primary LCD controller + _ctrl=TextLCD::_LCDCtrl_0; // Select primary controller - _setEnable(true); + _initCtrl(); // Init primary controller + + // Primary LCD controller Clearscreen + _writeCommand(0x01); // cls, and set cursor to 0 + + wait_ms(10); // The CLS command takes 1.64 ms. + // Since we are not using the Busy flag, Lets be safe and take 10 ms + +} + +/* Init the LCD controller + * 4-bit mode, number of lines, fonttype, no cursor etc + * + */ +void TextLCD::_initCtrl() { + _setRS(false); // command mode -// wait(0.015); // Wait 15ms to ensure powered up - wait_ms(15); // Wait 15ms to ensure powered up + wait_ms(20); // Wait 20ms to ensure powered up // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus) for (int i=0; i<3; i++) { _writeByte(0x3); -// wait(0.00164); // this command takes 1.64ms, so wait for it - wait_ms(10); // this command takes 1.64ms, so wait for it + wait_ms(15); // this command takes 1.64ms, so wait for it } _writeByte(0x2); // 4-bit mode -// wait(0.000040f); // most instructions take 40us wait_us(40); // most instructions take 40us // Display is now in 4-bit mode switch (_type) { case LCD8x1: - _writeCommand(0x20); // Function set 001 BW N F - - + _writeCommand(0x20); // Function set 001 DL N F - - + // DL=0 (4 bits bus) // N=0 (1 line) // F=0 (5x7 dots font) break; case LCD24x4: // Special mode for KS0078 - _writeCommand(0x2A); // Function set 001 BW N RE DH REV + _writeCommand(0x2A); // Function set 001 DL N RE DH REV + // DL=0 (4 bits bus) // N=1 (Dont care for KS0078) // RE=0 (Extended Regs, special mode for KS0078) // DH=1 (Disp shift, special mode for KS0078) // REV=0 (Reverse, special mode for KS0078) - _writeCommand(0x2E); // Function set 001 BW N RE DH REV + _writeCommand(0x2E); // Function set 001 DL N RE DH REV + // DL=0 (4 bits bus) // N=1 (Dont care for KS0078) // RE=1 (Ena Extended Regs, special mode for KS0078) // DH=1 (Disp shift, special mode for KS0078) @@ -140,17 +189,20 @@ // BW=0 (Cur BW invert disable, special mode for KS0078) // NW=1 (4 Line, special mode for KS0078) - _writeCommand(0x2A); // Function set 001 BW N RE DH REV + _writeCommand(0x2A); // Function set 001 DL N RE DH REV + // DL=0 (4 bits bus) // N=1 (Dont care for KS0078) // RE=0 (Dis. Extended Regs, special mode for KS0078) // DH=1 (Disp shift, special mode for KS0078) // REV=0 (Reverse, special mode for KS0078) break; +// All other LCD types are initialised as 2 Line displays (including LCD40x4) default: - _writeCommand(0x28); // Function set 001 BW N F - - + _writeCommand(0x28); // Function set 001 DL N F - - + // DL=0 (4 bits bus) // N=1 (2 lines) - // F=0 (5x7 dots font) + // F=0 (5x7 dots font, only option for 2 line display) // - (Don't care) break; @@ -163,33 +215,117 @@ // _writeCommand(0x0C); // Display Ctrl 0000 1 D C B // // Display On, Cursor Off, Blink Off - setCursor(TextLCD::CurOff_BlkOff); - - cls(); + setCursor(TextLCD::CurOff_BlkOff); + } -void TextLCD::_character(int column, int row, int c) { - int addr = getAddress(column, row); - - _writeCommand(0x80 | addr); - _writeData(c); + +#if(LCD40x4Test) +void TextLCD::cls() { + + // Select and configure second LCD controller when needed + if(_type==LCD40x4) { + _ctrl=TextLCD::_LCDCtrl_1; // Select 2nd controller + + // Second LCD controller Cursor always Off + _setCursor(TextLCD::CurOff_BlkOff); + + // Second LCD controller Clearscreen + _writeCommand(0x01); // cls, and set cursor to 0 + + wait_ms(10); // The CLS command takes 1.64 ms. + // Since we are not using the Busy flag, Lets be safe and take 10 ms + + + _ctrl=TextLCD::_LCDCtrl_0; // Select primary controller + } + + // Primary LCD controller Clearscreen + _writeCommand(0x01); // cls, and set cursor to 0 + + wait_ms(10); // The CLS command takes 1.64 ms. + // Since we are not using the Busy flag, Lets be safe and take 10 ms + + // Restore cursormode on primary LCD controller when needed + if(_type==LCD40x4) { + _setCursor(_currentCursor); + } + + _row=0; // Reset Cursor location + _column=0; } - +#else +//standard void TextLCD::cls() { _writeCommand(0x01); // cls, and set cursor to 0 -// wait(0.00164f); // This command takes 1.64 ms + wait_ms(10); // The CLS command takes 1.64 ms. // Since we are not using the Busy flag, Lets be safe and take 10 ms locate(0, 0); } +#endif void TextLCD::locate(int column, int row) { - _column = column; - _row = row; + + // setAddress() does all the heavy lifting: + // check column and row sanity, + // switch controllers for LCD40x4 if needed + // switch cursor for LCD40x4 if needed + // set the new memory address to show cursor at correct location + setAddress(column, row); + +} + + +//Not needed in new version, is now part of _putc() +void TextLCD::_character(int column, int row, int c) { + int addr = getAddress(column, row); + + _writeCommand(0x80 | addr); + _writeData(c); } + +#if(LCD40x4Test) + +int TextLCD::_putc(int value) { + int addr; + + if (value == '\n') { + //No character to write + + //Update Cursor + _column = 0; + _row++; + if (_row >= rows()) { + _row = 0; + } + } + else { + //Character to write + _writeData(value); + + //Update Cursor + _column++; + if (_column >= columns()) { + _column = 0; + _row++; + if (_row >= rows()) { + _row = 0; + } + } + } //else + + //Set next memoryaddress, make sure cursor blinks at next location + addr = getAddress(_column, _row); + _writeCommand(0x80 | addr); + + return value; +} +#else +//Standard int TextLCD::_putc(int value) { if (value == '\n') { _column = 0; @@ -208,9 +344,16 @@ } } } + return value; } +#endif + + + + + int TextLCD::_getc() { return -1; } @@ -220,31 +363,79 @@ switch(_busType) { case _PinBus : +#if(LCD40x4Test) + if(_ctrl==TextLCD::_LCDCtrl_0) { + if (value) + _e = 1; // Set E bit + else + _e = 0; // Reset E bit + } + else { + if (value) + _e2 = 1; // Set E2 bit + else + _e2 = 0; // Reset E2 bit + } + +#else if (value) _e = 1; // Set E bit else _e = 0; // Reset E bit - +#endif break; case _I2CBus : + +#if(LCD40x4Test) + if(_ctrl==TextLCD::_LCDCtrl_0) { + if (value) + _lcd_bus |= D_LCD_E; // Set E bit + else + _lcd_bus &= ~D_LCD_E; // Reset E bit + } + else { + if (value) + _lcd_bus |= D_LCD_E2; // Set E2 bit + else + _lcd_bus &= ~D_LCD_E2; // Reset E2bit + } + +#else if (value) _lcd_bus |= D_LCD_E; // Set E bit else _lcd_bus &= ~D_LCD_E; // Reset E bit - // write the new data to the portexpander +#endif + // write the new data to the I2C portexpander _i2c->write(_slaveAddress, &_lcd_bus, 1); - + break; case _SPIBus : +#if(LCD40x4Test) + if(_ctrl==TextLCD::_LCDCtrl_0) { + if (value) + _lcd_bus |= D_LCD_E; // Set E bit + else + _lcd_bus &= ~D_LCD_E; // Reset E bit + } + else { + if (value) + _lcd_bus |= D_LCD_E2; // Set E2 bit + else + _lcd_bus &= ~D_LCD_E2; // Reset E2 bit + } + +#else if (value) _lcd_bus |= D_LCD_E; // Set E bit else _lcd_bus &= ~D_LCD_E; // Reset E bit - - // write the new data to the portexpander +#endif + + // write the new data to the SPI portexpander _setCS(false); _spi->write(_lcd_bus); _setCS(true); @@ -270,7 +461,7 @@ else _lcd_bus &= ~D_LCD_RS; // Reset RS bit - // write the new data to the portexpander + // write the new data to the I2C portexpander _i2c->write(_slaveAddress, &_lcd_bus, 1); break; @@ -281,7 +472,7 @@ else _lcd_bus &= ~D_LCD_RS; // Reset RS bit - // write the new data to the portexpander + // write the new data to the SPI portexpander _setCS(false); _spi->write(_lcd_bus); _setCS(true); @@ -322,7 +513,7 @@ else _lcd_bus &= ~D_LCD_D7; // Reset Databit - // write the new data to the portexpander + // write the new data to the I2C portexpander _i2c->write(_slaveAddress, &_lcd_bus, 1); break; @@ -350,7 +541,7 @@ else _lcd_bus &= ~D_LCD_D7; // Reset Databit - // write the new data to the portexpander + // write the new data to the SPI portexpander _setCS(false); _spi->write(_lcd_bus); _setCS(true); @@ -364,48 +555,51 @@ // Set CS line. Only used for SPI bus void TextLCD::_setCS(bool value) { - if (value) + if (value) { _cs = 1; // Set CS pin + } else _cs = 0; // Reset CS pin - + } void TextLCD::_writeByte(int value) { -// _d = value >> 4; - _setData(value >> 4); -// wait(0.000040f); // most instructions take 40us - wait_us(40); // most instructions take 40us -// _e = 0; - _setEnable(false); -// wait(0.000040f); - wait_us(40); // most instructions take 40us -// _e = 1; + +// Enable is Low + _setEnable(true); + _setData(value >> 4); + wait_us(1); // Data setup time + _setEnable(false); + wait_us(1); // Data hold time + _setEnable(true); -// _d = value >> 0; _setData(value >> 0); -// wait(0.000040f); - wait_us(40); // most instructions take 40us -// _e = 0; + wait_us(1); // Data setup time _setEnable(false); -// wait(0.000040f); // most instructions take 40us - wait_us(40); // most instructions take 40us -// _e = 1; - _setEnable(true); + wait_us(1); // Datahold time + +// Enable is Low + } void TextLCD::_writeCommand(int command) { -// _rs = 0; + _setRS(false); - _writeByte(command); + wait_us(1); // Data setup time + + _writeByte(command); + wait_us(40); // most instructions take 40us } void TextLCD::_writeData(int data) { -// _rs = 1; + _setRS(true); + wait_us(1); // Data setup time + _writeByte(data); + wait_us(40); // data writes take 40us } @@ -459,6 +653,18 @@ else return 0x40 + (column - 8); + case LCD12x4: + switch (row) { + case 0: + return 0x00 + column; + case 1: + return 0x40 + column; + case 2: + return 0x0C + column; + case 3: + return 0x4C + column; + } + case LCD16x4: switch (row) { case 0: @@ -501,11 +707,50 @@ return 0x00 + (row * 40) + column; case LCD8x2: + case LCD12x2: case LCD16x2: case LCD20x2: case LCD24x2: case LCD40x2: return 0x00 + (row * 0x40) + column; + +#if(LCD40x4Test) + case LCD40x4: + // LCD40x4 is a special case since it has 2 controllers + // Each controller is configured as 40x2 + if (row<2) { + // Test to see if we need to switch between controllers + if (_ctrl != _LCDCtrl_0) { + // Second LCD controller Cursor Off + _setCursor(TextLCD::CurOff_BlkOff); + + // Select primary controller + _ctrl = _LCDCtrl_0; + + // Restore cursormode on primary LCD controller + _setCursor(_currentCursor); + } + + return 0x00 + (row * 0x40) + column; + } + else { + + // Test to see if we need to switch between controllers + if (_ctrl != _LCDCtrl_1) { + // Primary LCD controller Cursor Off + _setCursor(TextLCD::CurOff_BlkOff); + + // Select secondary controller + _ctrl = _LCDCtrl_1; + + // Restore cursormode on secondary LCD controller + _setCursor(_currentCursor); + } + + return 0x00 + ((row-2) * 0x40) + column; + } + +#endif // Should never get here. default: @@ -514,13 +759,31 @@ } -// Added for consistency. Set row, column and update memoryaddress. +// Set row, column and update memoryaddress. // void TextLCD::setAddress(int column, int row) { - - locate(column, row); + +// Sanity Check column + if (column < 0) { + _column = 0; + } + else if (column >= columns()) { + _column = columns() - 1; + } else _column = column; - int addr = getAddress(column, row); +// Sanity Check row + if (row < 0) { + _row = 0; + } + else if (row >= rows()) { + _row = rows() - 1; + } else _row = row; + + +// Compute the memory address +// For LCD40x4: switch controllers if needed +// switch cursor if needed + int addr = getAddress(_column, _row); _writeCommand(0x80 | addr); } @@ -530,6 +793,10 @@ case LCD8x1: case LCD8x2: return 8; + + case LCD12x2: + case LCD12x4: + return 12; case LCD16x1: case LCD16x2: @@ -546,6 +813,10 @@ return 24; case LCD40x2: + +#if(LCD40x4Test) + case LCD40x4: +#endif return 40; // Should never get here. @@ -560,7 +831,8 @@ case LCD16x1: return 1; - case LCD8x2: + case LCD8x2: + case LCD12x2: case LCD16x2: case LCD16x2B: case LCD20x2: @@ -568,9 +840,13 @@ case LCD40x2: return 2; + case LCD12x4: case LCD16x4: case LCD20x4: case LCD24x4: +#if(LCD40x4Test) + case LCD40x4: +#endif return 4; // Should never get here. @@ -580,27 +856,33 @@ } + +#if(LCD40x4Test) + void TextLCD::setCursor(TextLCD::LCDCursor show) { + + // Save new cursor mode, needed when 2 controllers are in use + _currentCursor = show; + // Configure current LCD controller + _setCursor(_currentCursor); + +} + +void TextLCD::_setCursor(TextLCD::LCDCursor show) { + + // Configure current LCD controller switch (show) { case CurOff_BlkOff : _writeCommand(0x0C); // Cursor off and Blink Off - wait_us(40); - _cursor = show; break; - case CurOn_BlkOff : _writeCommand(0x0E); // Cursor on and Blink Off - wait_us(40); - _cursor = show; + case CurOn_BlkOff : _writeCommand(0x0E); // Cursor on and Blink Off break; case CurOff_BlkOn : _writeCommand(0x0D); // Cursor off and Blink On - wait_us(40); - _cursor = show; break; - case CurOn_BlkOn : _writeCommand(0x0F); // Cursor on and Blink char - wait_us(40); - _cursor = show; + case CurOn_BlkOn : _writeCommand(0x0F); // Cursor on and Blink char break; // Should never get here. @@ -611,13 +893,96 @@ } +#else +//standard +void TextLCD::setCursor(TextLCD::LCDCursor show) { + + switch (show) { + case CurOff_BlkOff : _writeCommand(0x0C); // Cursor off and Blink Off + break; + case CurOn_BlkOff : _writeCommand(0x0E); // Cursor on and Blink Off + break; + + case CurOff_BlkOn : _writeCommand(0x0D); // Cursor off and Blink On + break; + + case CurOn_BlkOn : _writeCommand(0x0F); // Cursor on and Blink char + break; + +// Should never get here. + default : + break; + + } + +} + +#endif + + + + +#if(LCD40x4Test) void TextLCD::setUDC(unsigned char c, char *udc_data) { - _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address + + // Select and configure second LCD controller when needed + if(_type==LCD40x4) { + _LCDCtrl current_ctrl = _ctrl; // Temp save current controller + + // Select primary controller + _ctrl=TextLCD::_LCDCtrl_0; + + // Configure primary LCD controller + _setUDC(c, udc_data); + + // Select 2nd controller + _ctrl=TextLCD::_LCDCtrl_1; + + // Configure secondary LCD controller + _setUDC(c, udc_data); + // Restore current controller + _ctrl=current_ctrl; + } + else { + // Configure primary LCD controller + _setUDC(c, udc_data); + } + +} + +void TextLCD::_setUDC(unsigned char c, char *udc_data) { + + // Select CG RAM for current LCD controller + _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address, + //8 sequential locations needed per UDC + // Store UDC pattern for (int i=0; i<8; i++) { _writeData(*udc_data++); } + + //Select DD RAM again for current LCD controller + int addr = getAddress(_column, _row); + _writeCommand(0x80 | addr); + } +#else +//standard +void TextLCD::setUDC(unsigned char c, char *udc_data) { + // Select CG RAM for current LCD controller + _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address + //8 sequential locations needed per UDC + // Store UDC pattern + for (int i=0; i<8; i++) { + _writeData(*udc_data++); + } + + //Select DD RAM again for current LCD controller + addr = getAddress(_column, _row); + _writeCommand(0x80 | addr); + +} +#endif
--- a/TextLCD.h Sun Feb 10 18:43:51 2013 +0000 +++ b/TextLCD.h Tue Feb 19 22:09:09 2013 +0000 @@ -1,7 +1,8 @@ /* mbed TextLCD Library, for a 4-bit LCD based on HD44780 * Copyright (c) 2007-2010, sford, http://mbed.org * 2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs - * 2013, v02: WH, Added I2C and SPI bus interfaces + * 2013, v02: WH, Added I2C and SPI bus interfaces + * 2013, v03: WH, Added support for LCD40x4 which uses 2 controllers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,15 +28,20 @@ #include "mbed.h" + +//Test Only +//#define LCD40x4Test 0 +#define LCD40x4Test 1 + /** A TextLCD interface for driving 4-bit HD44780-based LCDs * - * Currently supports 8x1, 8x2, 16x2, 16x4, 20x2, 20x4, 24x2, 24x4 and 40x2 panels + * Currently supports 8x1, 8x2, 12x4, 16x1, 16x2, 16x4, 20x2, 20x4, 24x2, 24x4 and 40x2 panels * * @code * #include "mbed.h" * #include "TextLCD.h" * - * TextLCD lcd(p15, p16, p17, p18, p19, p20); // RS, E, D4-D7 + * TextLCD lcd(p15, p16, p17, p18, p19, p20); // RS, E, D4-D7, LCDType=LCD16x2 * * int main() { * lcd.printf("Hello World!\n"); @@ -47,19 +53,20 @@ //Pin Defines for I2C PCF8574 and SPI 74595 Bus //LCD and serial portexpanders should be wired accordingly //Note: LCD RW pin must be connected to GND -// E2 may be used for future expansion to LCD40x4 +// E2 is used for LCD40x4 (second controller) // BL may be used for future expansion to control backlight // -#define D_LCD_PIN_D4 0x00 -#define D_LCD_PIN_D5 0x01 -#define D_LCD_PIN_D6 0x02 -#define D_LCD_PIN_D7 0x03 -#define D_LCD_PIN_RS 0x04 -#define D_LCD_PIN_E 0x05 -#define D_LCD_PIN_E2 0x06 -#define D_LCD_PIN_BL 0x07 +#define D_LCD_PIN_D4 0 +#define D_LCD_PIN_D5 1 +#define D_LCD_PIN_D6 2 +#define D_LCD_PIN_D7 3 +#define D_LCD_PIN_RS 4 +#define D_LCD_PIN_E 5 +#define D_LCD_PIN_E2 6 +#define D_LCD_PIN_BL 7 #define D_LCD_BUS_MSK 0x0F +#define D_LCD_BUS_DEF 0x00 //Bitpattern Defines for I2C PCF8574 and SPI 74595 Bus // @@ -112,7 +119,7 @@ /** A TextLCD interface for driving 4-bit HD44780-based LCDs * - * Currently supports 8x1, 8x2, 16x1, 16x2, 16x4, 20x2, 20x4, 24x2, 24x4 and 40x2 panels + * Currently supports 8x1, 8x2, 12x4, 16x1, 16x2, 16x4, 20x2, 20x4, 24x2, 24x4, 40x2 and 40x4 panels * */ class TextLCD : public Stream { @@ -122,6 +129,8 @@ enum LCDType { LCD8x1, /**< 8x1 LCD panel */ LCD8x2, /**< 8x2 LCD panel */ + LCD12x2, /**< 12x2 LCD panel */ + LCD12x4, /**< 12x4 LCD panel */ LCD16x1, /**< 16x1 LCD panel (actually 8x2) */ LCD16x2, /**< 16x2 LCD panel (default) */ LCD16x2B, /**< 16x2 LCD panel alternate addressing */ @@ -130,7 +139,8 @@ LCD20x4, /**< 20x4 LCD panel */ LCD24x2, /**< 24x2 LCD panel */ LCD24x4, /**< 24x4 LCD panel, special mode KS0078 */ - LCD40x2 /**< 40x2 LCD panel */ + LCD40x2, /**< 40x2 LCD panel */ + LCD40x4 /**< 40x4 LCD panel, Two controller version */ }; /** LCD Cursor control */ @@ -142,14 +152,15 @@ }; - /** Create a TextLCD interface for using regural mbed pins + /** Create a TextLCD interface for using regular mbed pins * * @param rs Instruction/data control line * @param e Enable line (clock) * @param d4-d7 Data lines for using as a 4-bit interface * @param type Sets the panel size/addressing mode (default = LCD16x2) + * @param e2 Enable2 line (clock for second controller, LCD40x4 only) */ - TextLCD(PinName rs, PinName e, PinName d4, PinName d5, PinName d6, PinName d7, LCDType type = LCD16x2); + TextLCD(PinName rs, PinName e, PinName d4, PinName d5, PinName d6, PinName d7, LCDType type = LCD16x2, PinName e2 = NC); /** Create a TextLCD interface using an I2C PC8574 portexpander * @@ -243,17 +254,32 @@ enum _LCDBus { _PinBus, /*< Regular mbed pins */ _I2CBus, /*< I2C PCF8574 Portexpander */ - _SPIBus /*< SPI 74595 */ + _SPIBus /*< SPI 74595 Shiftregister */ }; + /* LCD controller select, mainly used for LCD40x4 */ + enum _LCDCtrl { + _LCDCtrl_0, /*< Primary */ + _LCDCtrl_1, /*< Secondary */ + }; + // Stream implementation functions virtual int _putc(int value); virtual int _getc(); +//Low level methods for LCD controller void _init(); + void _initCtrl(); int _address(int column, int row); void _character(int column, int row, int c); + void _setCursor(TextLCD::LCDCursor show); + void _setUDC(unsigned char c, char *udc_data); +//Low level write operations to LCD controller + void _writeByte(int value); + void _writeCommand(int command); + void _writeData(int data); + //Low level writes to LCD Bus (serial or parallel) void _setEnable(bool value); void _setRS(bool value); @@ -263,13 +289,9 @@ //Low level writes to LCD serial bus only void _writeBus(); -//Low level writes to LCD - void _writeByte(int value); - void _writeCommand(int command); - void _writeData(int data); // Regular mbed pins bus - DigitalOut _rs, _e; + DigitalOut _rs, _e, _e2; BusOut _d; // I2C bus @@ -283,16 +305,19 @@ //Bus Interface type _LCDBus _busType; -// Internal bus mirror value for serial only +// Internal bus mirror value for serial bus only char _lcd_bus; //Display type LCDType _type; +//Controller select, mainly used for LCD40x4 + _LCDCtrl _ctrl; + // Cursor int _column; int _row; - LCDCursor _cursor; + LCDCursor _currentCursor; }; #endif