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:
Fri Jun 13 19:02:26 2014 +0000
Revision:
27:22d5086f6ba6
Parent:
26:bd897a001012
Child:
28:30fa94f7341c
First test of native SPI

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
wim 18:bd65dc10f27f 6 * 2013, v04: WH, Added support for Display On/Off, improved 4bit bootprocess
wim 18:bd65dc10f27f 7 * 2013, v05: WH, Added support for 8x2B, added some UDCs
wim 19:c747b9e2e7b8 8 * 2013, v06: WH, Added support for devices that use internal DC/DC converters
wim 20:e0da005a777f 9 * 2013, v07: WH, Added support for backlight and include portdefinitions for LCD2004 Module from DFROBOT
wim 22:35742ec80c24 10 * 2014, v08: WH, Refactored in Base and Derived Classes to deal with mbed lib change regarding 'NC' defined pins
wim 25:6162b31128c9 11 * 2014, v09: WH/EO, Added Class for Native SPI controllers such as ST7032
wim 26:bd897a001012 12 * 2014, v10: WH, Added Class for Native I2C controllers such as ST7032i, Added support for MCP23008 I2C portexpander, Added support for Adafruit module
simon 1:ac48b187213c 13 *
simon 1:ac48b187213c 14 * Permission is hereby granted, free of charge, to any person obtaining a copy
simon 1:ac48b187213c 15 * of this software and associated documentation files (the "Software"), to deal
simon 1:ac48b187213c 16 * in the Software without restriction, including without limitation the rights
simon 1:ac48b187213c 17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
simon 1:ac48b187213c 18 * copies of the Software, and to permit persons to whom the Software is
simon 1:ac48b187213c 19 * furnished to do so, subject to the following conditions:
simon 1:ac48b187213c 20 *
simon 1:ac48b187213c 21 * The above copyright notice and this permission notice shall be included in
simon 1:ac48b187213c 22 * all copies or substantial portions of the Software.
simon 1:ac48b187213c 23 *
simon 1:ac48b187213c 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
simon 1:ac48b187213c 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
simon 1:ac48b187213c 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
simon 1:ac48b187213c 27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
simon 1:ac48b187213c 28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 1:ac48b187213c 29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
simon 1:ac48b187213c 30 * THE SOFTWARE.
simon 1:ac48b187213c 31 */
simon 1:ac48b187213c 32
simon 1:ac48b187213c 33 #include "TextLCD.h"
simon 1:ac48b187213c 34 #include "mbed.h"
simon 1:ac48b187213c 35
wim 21:9eb628d9e164 36 /** Create a TextLCD_Base interface
wim 15:b70ebfffb258 37 *
wim 21:9eb628d9e164 38 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 39 * @param ctrl LCD controller (default = HD44780)
wim 15:b70ebfffb258 40 */
wim 21:9eb628d9e164 41 TextLCD_Base::TextLCD_Base(LCDType type, LCDCtrl ctrl) : _type(type), _ctrl(ctrl) {
wim 14:0c32b66b14b8 42 }
wim 14:0c32b66b14b8 43
wim 14:0c32b66b14b8 44
wim 21:9eb628d9e164 45 /** Init the LCD Controller(s)
wim 21:9eb628d9e164 46 * Clear display
wim 21:9eb628d9e164 47 */
wim 21:9eb628d9e164 48 void TextLCD_Base::_init() {
wim 15:b70ebfffb258 49
wim 15:b70ebfffb258 50 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 51 if(_type==LCD40x4) {
wim 27:22d5086f6ba6 52 _ctrl_idx=_LCDCtrl_1; // Select 2nd controller
wim 15:b70ebfffb258 53
wim 27:22d5086f6ba6 54 _initCtrl(); // Init 2nd controller
wim 15:b70ebfffb258 55
wim 15:b70ebfffb258 56 // Secondary LCD controller Clearscreen
wim 27:22d5086f6ba6 57 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 58 wait_ms(10); // The CLS command takes 1.64 ms.
wim 27:22d5086f6ba6 59 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 60 }
wim 15:b70ebfffb258 61
wim 15:b70ebfffb258 62 // Select and configure primary LCD controller
wim 27:22d5086f6ba6 63 _ctrl_idx=_LCDCtrl_0; // Select primary controller
wim 13:24506ba22480 64
wim 19:c747b9e2e7b8 65 _initCtrl(); // Init primary controller
wim 15:b70ebfffb258 66
wim 15:b70ebfffb258 67 // Primary LCD controller Clearscreen
wim 27:22d5086f6ba6 68 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 69 wait_ms(10); // The CLS command takes 1.64 ms.
wim 27:22d5086f6ba6 70 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 71 }
wim 15:b70ebfffb258 72
wim 21:9eb628d9e164 73 /** Init the LCD controller
wim 21:9eb628d9e164 74 * 4-bit mode, number of lines, fonttype, no cursor etc
wim 21:9eb628d9e164 75 *
wim 21:9eb628d9e164 76 */
wim 21:9eb628d9e164 77 void TextLCD_Base::_initCtrl() {
wim 15:b70ebfffb258 78
wim 26:bd897a001012 79 this->_setRS(false); // command mode
wim 13:24506ba22480 80
wim 26:bd897a001012 81 wait_ms(20); // Wait 20ms to ensure powered up
simon 1:ac48b187213c 82
wim 17:652ab113bc2e 83 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
wim 17:652ab113bc2e 84 for (int i=0; i<3; i++) {
wim 17:652ab113bc2e 85 _writeNibble(0x3);
wim 20:e0da005a777f 86 wait_ms(15); // This command takes 1.64ms, so wait for it
wim 17:652ab113bc2e 87 }
wim 17:652ab113bc2e 88 _writeNibble(0x2); // 4-bit mode
wim 17:652ab113bc2e 89 wait_us(40); // most instructions take 40us
wim 18:bd65dc10f27f 90
wim 18:bd65dc10f27f 91 // Display is now in 4-bit mode
wim 27:22d5086f6ba6 92 // Note: 4 bit mode is ignored for native SPI and I2C devices
wim 25:6162b31128c9 93
wim 19:c747b9e2e7b8 94 // Device specific initialisations for DC/DC converter to generate VLCD or VLED
wim 19:c747b9e2e7b8 95 switch (_ctrl) {
wim 20:e0da005a777f 96 case ST7036:
wim 19:c747b9e2e7b8 97 // ST7036 controller: Initialise Voltage booster for VLCD. VDD=5V
wim 19:c747b9e2e7b8 98 // Note: supports 1,2 or 3 lines
wim 27:22d5086f6ba6 99 _writeByte( 0x29 ); // 4-bit Databus, 2 Lines, Select Instruction Set = 1
wim 20:e0da005a777f 100 wait_ms(30); // > 26,3ms
wim 19:c747b9e2e7b8 101 _writeByte( 0x14 ); // Bias: 1/5, 2-Lines LCD
wim 20:e0da005a777f 102 wait_ms(30); // > 26,3ms
wim 19:c747b9e2e7b8 103 _writeByte( 0x55 ); // Icon off, Booster on, Set Contrast C5, C4
wim 20:e0da005a777f 104 wait_ms(30); // > 26,3ms
wim 27:22d5086f6ba6 105 _writeByte( 0x6D ); // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
wim 19:c747b9e2e7b8 106 wait_ms(200); // > 200ms!
wim 19:c747b9e2e7b8 107 _writeByte( 0x78 ); // Set Contrast C3, C2, C1, C0
wim 20:e0da005a777f 108 wait_ms(30); // > 26,3ms
wim 27:22d5086f6ba6 109 _writeByte( 0x28 ); // Return to Instruction Set = 0
wim 25:6162b31128c9 110 wait_ms(50);
wim 19:c747b9e2e7b8 111 break;
wim 25:6162b31128c9 112
wim 26:bd897a001012 113 case ST7032_3V3:
wim 26:bd897a001012 114 // ST7032 controller: Initialise Voltage booster for VLCD. VDD=3V3
wim 27:22d5086f6ba6 115
wim 27:22d5086f6ba6 116 // _writeByte( 0x39 ); //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Select Instruction Set = 1
wim 27:22d5086f6ba6 117 _writeByte( 0x29 ); //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Select Instruction Set = 1
wim 27:22d5086f6ba6 118 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 27:22d5086f6ba6 119 wait_us(30);
wim 27:22d5086f6ba6 120 _writeByte( 0x1C ); //Internal OSC frequency adjustment 183HZ, bias will be 1/4
Sissors 24:fb3399713710 121 wait_us(30);
wim 26:bd897a001012 122 _writeByte( 0x73 ); //Contrast control low byte
Sissors 24:fb3399713710 123 wait_us(30);
wim 26:bd897a001012 124 _writeByte( 0x57 ); //booster circuit is turned on. /ICON display off. /Contrast control high byte
Sissors 24:fb3399713710 125 wait_us(30);
wim 27:22d5086f6ba6 126 _writeByte( 0x6C ); //Follower control
Sissors 24:fb3399713710 127 wait_us(50);
wim 27:22d5086f6ba6 128 // _writeByte( 0x0C ); //DISPLAY ON, not needed
wim 27:22d5086f6ba6 129 // _writeByte( 0x38 ); //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Return to Instruction Set = 0
wim 27:22d5086f6ba6 130 _writeByte( 0x28 ); //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Return to Instruction Set = 0
wim 27:22d5086f6ba6 131 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 26:bd897a001012 132 wait_us(30);
wim 26:bd897a001012 133 break;
wim 26:bd897a001012 134
wim 26:bd897a001012 135 //Check and fix booster disable
wim 26:bd897a001012 136 case ST7032_5V:
wim 26:bd897a001012 137 // ST7032 controller: Disable Voltage booster for VLCD. VDD=5V
wim 27:22d5086f6ba6 138 // _writeByte( 0x39 ); //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Instruction Set = 1
wim 27:22d5086f6ba6 139 _writeByte( 0x29 ); //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Select Instruction Set = 1
wim 27:22d5086f6ba6 140 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 27:22d5086f6ba6 141 wait_us(30);
wim 27:22d5086f6ba6 142 _writeByte( 0x1C ); //Internal OSC frequency adjustment 183HZ, bias will be 1/4
wim 26:bd897a001012 143 wait_us(30);
wim 26:bd897a001012 144 _writeByte( 0x73 ); //Contrast control low byte
wim 26:bd897a001012 145 wait_us(30);
wim 26:bd897a001012 146 _writeByte( 0x57 ); //booster circuit is turned on. /ICON display off. /Contrast control high byte
wim 26:bd897a001012 147 wait_us(30);
wim 27:22d5086f6ba6 148 _writeByte( 0x6C ); //Follower control
wim 26:bd897a001012 149 wait_us(50);
wim 27:22d5086f6ba6 150 // _writeByte( 0x0C ); //DISPLAY ON --> remove, done later?
wim 27:22d5086f6ba6 151 // _writeByte( 0x38 ); //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Instruction Set = 0
wim 27:22d5086f6ba6 152 _writeByte( 0x28 ); //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Return to Instruction Set = 0
wim 27:22d5086f6ba6 153 //Note: 4 bit mode is ignored for native SPI and I2C devices
Sissors 24:fb3399713710 154 wait_us(30);
Sissors 24:fb3399713710 155 break;
wim 25:6162b31128c9 156
wim 19:c747b9e2e7b8 157 case WS0010:
wim 19:c747b9e2e7b8 158 // WS0010 OLED controller: Initialise DC/DC Voltage converter for LEDs
wim 19:c747b9e2e7b8 159 // Note: supports 1 or 2 lines (and 16x100 graphics)
wim 19:c747b9e2e7b8 160 // supports 4 fonts (English/Japanese (default), Western European-I, English/Russian, Western European-II)
wim 19:c747b9e2e7b8 161 // Cursor/Disp shift set 0001 SC RL 0 0
wim 19:c747b9e2e7b8 162 //
wim 19:c747b9e2e7b8 163 // Mode en Power set 0001 GC PWR 1 1
wim 19:c747b9e2e7b8 164 // GC = 0 (Graph Mode=1, Char Mode=0)
wim 19:c747b9e2e7b8 165 // PWR = (DC/DC On/Off)
wim 19:c747b9e2e7b8 166
wim 25:6162b31128c9 167 //_writeCommand(0x13); // DC/DC off
wim 19:c747b9e2e7b8 168 _writeCommand(0x17); // DC/DC on
wim 25:6162b31128c9 169
wim 19:c747b9e2e7b8 170 wait_ms(10);
wim 19:c747b9e2e7b8 171 break;
wim 19:c747b9e2e7b8 172
wim 19:c747b9e2e7b8 173 default:
wim 19:c747b9e2e7b8 174 // Devices that do not use DC/DC Voltage converters but external VLCD
wim 19:c747b9e2e7b8 175 break;
wim 19:c747b9e2e7b8 176 }
wim 14:0c32b66b14b8 177
wim 18:bd65dc10f27f 178 // Initialise Display configuration
wim 10:dd9b3a696acd 179 switch (_type) {
wim 10:dd9b3a696acd 180 case LCD8x1:
wim 18:bd65dc10f27f 181 case LCD8x2B:
wim 18:bd65dc10f27f 182 //8x1 is a regular 1 line display
wim 18:bd65dc10f27f 183 //8x2B is a special case of 16x1
wim 15:b70ebfffb258 184 _writeCommand(0x20); // Function set 001 DL N F - -
wim 15:b70ebfffb258 185 // DL=0 (4 bits bus)
wim 13:24506ba22480 186 // N=0 (1 line)
wim 13:24506ba22480 187 // F=0 (5x7 dots font)
wim 10:dd9b3a696acd 188 break;
wim 10:dd9b3a696acd 189
wim 10:dd9b3a696acd 190 case LCD24x4:
wim 10:dd9b3a696acd 191 // Special mode for KS0078
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 (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
wim 15:b70ebfffb258 199 _writeCommand(0x2E); // Function set 001 DL N RE DH REV
wim 15:b70ebfffb258 200 // DL=0 (4 bits bus)
wim 13:24506ba22480 201 // N=1 (Dont care for KS0078)
wim 13:24506ba22480 202 // RE=1 (Ena Extended Regs, special mode for KS0078)
wim 13:24506ba22480 203 // DH=1 (Disp shift, special mode for KS0078)
wim 13:24506ba22480 204 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 205
wim 13:24506ba22480 206 _writeCommand(0x09); // Ext Function set 0000 1 FW BW NW
wim 13:24506ba22480 207 // FW=0 (5-dot font, special mode for KS0078)
wim 13:24506ba22480 208 // BW=0 (Cur BW invert disable, special mode for KS0078)
wim 13:24506ba22480 209 // NW=1 (4 Line, special mode for KS0078)
wim 10:dd9b3a696acd 210
wim 15:b70ebfffb258 211 _writeCommand(0x2A); // Function set 001 DL N RE DH REV
wim 15:b70ebfffb258 212 // DL=0 (4 bits bus)
wim 13:24506ba22480 213 // N=1 (Dont care for KS0078)
wim 13:24506ba22480 214 // RE=0 (Dis. Extended Regs, special mode for KS0078)
wim 13:24506ba22480 215 // DH=1 (Disp shift, special mode for KS0078)
wim 13:24506ba22480 216 // REV=0 (Reverse, special mode for KS0078)
wim 10:dd9b3a696acd 217 break;
wim 10:dd9b3a696acd 218
wim 15:b70ebfffb258 219 // All other LCD types are initialised as 2 Line displays (including LCD40x4)
wim 10:dd9b3a696acd 220 default:
wim 15:b70ebfffb258 221 _writeCommand(0x28); // Function set 001 DL N F - -
wim 27:22d5086f6ba6 222 // DL=0 (4 bits bus)
wim 27:22d5086f6ba6 223 // Note: 4 bit mode is ignored for native SPI and I2C devices
wim 13:24506ba22480 224 // N=1 (2 lines)
wim 15:b70ebfffb258 225 // F=0 (5x7 dots font, only option for 2 line display)
wim 13:24506ba22480 226 // - (Don't care)
wim 10:dd9b3a696acd 227
wim 10:dd9b3a696acd 228 break;
wim 10:dd9b3a696acd 229 }
wim 10:dd9b3a696acd 230
wim 13:24506ba22480 231 _writeCommand(0x06); // Entry Mode 0000 01 CD S
wim 13:24506ba22480 232 // Cursor Direction and Display Shift
wim 13:24506ba22480 233 // CD=1 (Cur incr)
wim 13:24506ba22480 234 // S=0 (No display shift)
wim 10:dd9b3a696acd 235
wim 13:24506ba22480 236 // _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
wim 17:652ab113bc2e 237 // // Display On, Cursor Off, Blink Off
wim 21:9eb628d9e164 238 setCursor(CurOff_BlkOff);
wim 21:9eb628d9e164 239 setMode(DispOn);
simon 1:ac48b187213c 240 }
simon 1:ac48b187213c 241
wim 8:03116f75b66e 242
wim 21:9eb628d9e164 243 /** Clear the screen, Cursor home.
wim 21:9eb628d9e164 244 */
wim 21:9eb628d9e164 245 void TextLCD_Base::cls() {
wim 15:b70ebfffb258 246
wim 15:b70ebfffb258 247 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 248 if(_type==LCD40x4) {
wim 21:9eb628d9e164 249 _ctrl_idx=_LCDCtrl_1; // Select 2nd controller
wim 15:b70ebfffb258 250
wim 15:b70ebfffb258 251 // Second LCD controller Cursor always Off
wim 21:9eb628d9e164 252 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 253
wim 15:b70ebfffb258 254 // Second LCD controller Clearscreen
wim 27:22d5086f6ba6 255 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 256 wait_ms(10); // The CLS command takes 1.64 ms.
wim 15:b70ebfffb258 257 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 258
wim 15:b70ebfffb258 259
wim 21:9eb628d9e164 260 _ctrl_idx=_LCDCtrl_0; // Select primary controller
wim 15:b70ebfffb258 261 }
wim 15:b70ebfffb258 262
wim 15:b70ebfffb258 263 // Primary LCD controller Clearscreen
wim 27:22d5086f6ba6 264 _writeCommand(0x01); // cls, and set cursor to 0
wim 15:b70ebfffb258 265 wait_ms(10); // The CLS command takes 1.64 ms.
wim 15:b70ebfffb258 266 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 267
wim 15:b70ebfffb258 268 // Restore cursormode on primary LCD controller when needed
wim 15:b70ebfffb258 269 if(_type==LCD40x4) {
wim 17:652ab113bc2e 270 _setCursorAndDisplayMode(_currentMode,_currentCursor);
wim 15:b70ebfffb258 271 }
wim 15:b70ebfffb258 272
wim 15:b70ebfffb258 273 _row=0; // Reset Cursor location
wim 15:b70ebfffb258 274 _column=0;
simon 1:ac48b187213c 275 }
simon 1:ac48b187213c 276
wim 21:9eb628d9e164 277 /** Move cursor to selected row and column
wim 21:9eb628d9e164 278 */
wim 21:9eb628d9e164 279 void TextLCD_Base::locate(int column, int row) {
wim 15:b70ebfffb258 280
wim 15:b70ebfffb258 281 // setAddress() does all the heavy lifting:
wim 15:b70ebfffb258 282 // check column and row sanity,
wim 15:b70ebfffb258 283 // switch controllers for LCD40x4 if needed
wim 15:b70ebfffb258 284 // switch cursor for LCD40x4 if needed
wim 15:b70ebfffb258 285 // set the new memory address to show cursor at correct location
wim 15:b70ebfffb258 286 setAddress(column, row);
wim 15:b70ebfffb258 287
wim 15:b70ebfffb258 288 }
wim 15:b70ebfffb258 289
wim 15:b70ebfffb258 290
wim 21:9eb628d9e164 291 /** Write a single character (Stream implementation)
wim 21:9eb628d9e164 292 */
wim 21:9eb628d9e164 293 int TextLCD_Base::_putc(int value) {
wim 15:b70ebfffb258 294 int addr;
wim 15:b70ebfffb258 295
wim 15:b70ebfffb258 296 if (value == '\n') {
wim 15:b70ebfffb258 297 //No character to write
wim 15:b70ebfffb258 298
wim 15:b70ebfffb258 299 //Update Cursor
wim 15:b70ebfffb258 300 _column = 0;
wim 15:b70ebfffb258 301 _row++;
wim 15:b70ebfffb258 302 if (_row >= rows()) {
wim 15:b70ebfffb258 303 _row = 0;
wim 15:b70ebfffb258 304 }
wim 15:b70ebfffb258 305 }
wim 15:b70ebfffb258 306 else {
wim 15:b70ebfffb258 307 //Character to write
wim 15:b70ebfffb258 308 _writeData(value);
wim 15:b70ebfffb258 309
wim 15:b70ebfffb258 310 //Update Cursor
wim 15:b70ebfffb258 311 _column++;
wim 15:b70ebfffb258 312 if (_column >= columns()) {
wim 15:b70ebfffb258 313 _column = 0;
wim 15:b70ebfffb258 314 _row++;
wim 15:b70ebfffb258 315 if (_row >= rows()) {
wim 15:b70ebfffb258 316 _row = 0;
wim 15:b70ebfffb258 317 }
wim 15:b70ebfffb258 318 }
wim 15:b70ebfffb258 319 } //else
wim 15:b70ebfffb258 320
wim 15:b70ebfffb258 321 //Set next memoryaddress, make sure cursor blinks at next location
wim 15:b70ebfffb258 322 addr = getAddress(_column, _row);
wim 15:b70ebfffb258 323 _writeCommand(0x80 | addr);
wim 15:b70ebfffb258 324
wim 15:b70ebfffb258 325 return value;
wim 15:b70ebfffb258 326 }
wim 15:b70ebfffb258 327
wim 15:b70ebfffb258 328
wim 16:c276b75e6585 329 // get a single character (Stream implementation)
wim 21:9eb628d9e164 330 int TextLCD_Base::_getc() {
simon 1:ac48b187213c 331 return -1;
simon 1:ac48b187213c 332 }
simon 1:ac48b187213c 333
wim 14:0c32b66b14b8 334
wim 17:652ab113bc2e 335 // Write a nibble using the 4-bit interface
wim 21:9eb628d9e164 336 void TextLCD_Base::_writeNibble(int value) {
wim 17:652ab113bc2e 337
wim 17:652ab113bc2e 338 // Enable is Low
wim 21:9eb628d9e164 339 this->_setEnable(true);
wim 21:9eb628d9e164 340 this->_setData(value & 0x0F); // Low nibble
wim 17:652ab113bc2e 341 wait_us(1); // Data setup time
wim 21:9eb628d9e164 342 this->_setEnable(false);
wim 17:652ab113bc2e 343 wait_us(1); // Datahold time
wim 17:652ab113bc2e 344
wim 17:652ab113bc2e 345 // Enable is Low
wim 17:652ab113bc2e 346
wim 17:652ab113bc2e 347 }
wim 17:652ab113bc2e 348
wim 17:652ab113bc2e 349
wim 16:c276b75e6585 350 // Write a byte using the 4-bit interface
wim 21:9eb628d9e164 351 void TextLCD_Base::_writeByte(int value) {
wim 15:b70ebfffb258 352
wim 15:b70ebfffb258 353 // Enable is Low
wim 21:9eb628d9e164 354 this->_setEnable(true);
wim 21:9eb628d9e164 355 this->_setData(value >> 4); // High nibble
wim 15:b70ebfffb258 356 wait_us(1); // Data setup time
wim 21:9eb628d9e164 357 this->_setEnable(false);
wim 15:b70ebfffb258 358 wait_us(1); // Data hold time
wim 15:b70ebfffb258 359
wim 21:9eb628d9e164 360 this->_setEnable(true);
wim 21:9eb628d9e164 361 this->_setData(value >> 0); // Low nibble
wim 15:b70ebfffb258 362 wait_us(1); // Data setup time
wim 21:9eb628d9e164 363 this->_setEnable(false);
wim 15:b70ebfffb258 364 wait_us(1); // Datahold time
wim 15:b70ebfffb258 365
wim 15:b70ebfffb258 366 // Enable is Low
wim 15:b70ebfffb258 367
simon 1:ac48b187213c 368 }
simon 1:ac48b187213c 369
wim 21:9eb628d9e164 370 // Write a command byte to the LCD controller
wim 21:9eb628d9e164 371 void TextLCD_Base::_writeCommand(int command) {
wim 15:b70ebfffb258 372
wim 21:9eb628d9e164 373 this->_setRS(false);
wim 16:c276b75e6585 374 wait_us(1); // Data setup time for RS
wim 15:b70ebfffb258 375
wim 21:9eb628d9e164 376 this->_writeByte(command);
wim 15:b70ebfffb258 377 wait_us(40); // most instructions take 40us
simon 1:ac48b187213c 378 }
simon 1:ac48b187213c 379
wim 21:9eb628d9e164 380 // Write a data byte to the LCD controller
wim 21:9eb628d9e164 381 void TextLCD_Base::_writeData(int data) {
wim 15:b70ebfffb258 382
wim 21:9eb628d9e164 383 this->_setRS(true);
wim 16:c276b75e6585 384 wait_us(1); // Data setup time for RS
wim 15:b70ebfffb258 385
wim 21:9eb628d9e164 386 this->_writeByte(data);
wim 15:b70ebfffb258 387 wait_us(40); // data writes take 40us
simon 1:ac48b187213c 388 }
simon 1:ac48b187213c 389
wim 8:03116f75b66e 390
wim 8:03116f75b66e 391 #if (0)
wim 16:c276b75e6585 392 // This is the original _address() method.
wim 8:03116f75b66e 393 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
wim 8:03116f75b66e 394 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 395 //
wim 21:9eb628d9e164 396 int TextLCD_Base::_address(int column, int row) {
simon 1:ac48b187213c 397 switch (_type) {
simon 1:ac48b187213c 398 case LCD20x4:
simon 1:ac48b187213c 399 switch (row) {
simon 1:ac48b187213c 400 case 0:
simon 1:ac48b187213c 401 return 0x80 + column;
simon 1:ac48b187213c 402 case 1:
simon 1:ac48b187213c 403 return 0xc0 + column;
simon 1:ac48b187213c 404 case 2:
simon 1:ac48b187213c 405 return 0x94 + column;
simon 1:ac48b187213c 406 case 3:
simon 1:ac48b187213c 407 return 0xd4 + column;
simon 1:ac48b187213c 408 }
simon 1:ac48b187213c 409 case LCD16x2B:
simon 4:bf5b706f8d32 410 return 0x80 + (row * 40) + column;
simon 1:ac48b187213c 411 case LCD16x2:
simon 1:ac48b187213c 412 case LCD20x2:
simon 1:ac48b187213c 413 default:
simon 4:bf5b706f8d32 414 return 0x80 + (row * 0x40) + column;
simon 1:ac48b187213c 415 }
simon 1:ac48b187213c 416 }
wim 8:03116f75b66e 417 #endif
wim 8:03116f75b66e 418
wim 8:03116f75b66e 419
wim 16:c276b75e6585 420 // This replaces the original _address() method.
wim 8:03116f75b66e 421 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 21:9eb628d9e164 422 int TextLCD_Base::_address(int column, int row) {
wim 8:03116f75b66e 423 return 0x80 | getAddress(column, row);
wim 8:03116f75b66e 424 }
wim 8:03116f75b66e 425
wim 8:03116f75b66e 426 // This is new method to return the memory address based on row, column and displaytype.
wim 8:03116f75b66e 427 //
wim 21:9eb628d9e164 428 int TextLCD_Base::getAddress(int column, int row) {
wim 8:03116f75b66e 429
wim 8:03116f75b66e 430 switch (_type) {
wim 8:03116f75b66e 431 case LCD8x1:
wim 8:03116f75b66e 432 return 0x00 + column;
wim 18:bd65dc10f27f 433
wim 18:bd65dc10f27f 434 case LCD8x2B:
wim 18:bd65dc10f27f 435 // LCD8x2B is a special layout of LCD16x1
wim 18:bd65dc10f27f 436 if (row==0)
wim 18:bd65dc10f27f 437 return 0x00 + column;
wim 18:bd65dc10f27f 438 else
wim 18:bd65dc10f27f 439 return 0x08 + column;
wim 18:bd65dc10f27f 440
wim 18:bd65dc10f27f 441
wim 13:24506ba22480 442 case LCD16x1:
wim 13:24506ba22480 443 // LCD16x1 is a special layout of LCD8x2
wim 13:24506ba22480 444 if (column<8)
wim 13:24506ba22480 445 return 0x00 + column;
wim 13:24506ba22480 446 else
wim 13:24506ba22480 447 return 0x40 + (column - 8);
wim 13:24506ba22480 448
wim 15:b70ebfffb258 449 case LCD12x4:
wim 15:b70ebfffb258 450 switch (row) {
wim 15:b70ebfffb258 451 case 0:
wim 15:b70ebfffb258 452 return 0x00 + column;
wim 15:b70ebfffb258 453 case 1:
wim 15:b70ebfffb258 454 return 0x40 + column;
wim 15:b70ebfffb258 455 case 2:
wim 15:b70ebfffb258 456 return 0x0C + column;
wim 15:b70ebfffb258 457 case 3:
wim 15:b70ebfffb258 458 return 0x4C + column;
wim 15:b70ebfffb258 459 }
wim 15:b70ebfffb258 460
wim 8:03116f75b66e 461 case LCD16x4:
wim 8:03116f75b66e 462 switch (row) {
wim 8:03116f75b66e 463 case 0:
wim 8:03116f75b66e 464 return 0x00 + column;
wim 8:03116f75b66e 465 case 1:
wim 8:03116f75b66e 466 return 0x40 + column;
wim 8:03116f75b66e 467 case 2:
wim 8:03116f75b66e 468 return 0x10 + column;
wim 8:03116f75b66e 469 case 3:
wim 8:03116f75b66e 470 return 0x50 + column;
wim 8:03116f75b66e 471 }
wim 8:03116f75b66e 472
wim 8:03116f75b66e 473 case LCD20x4:
wim 8:03116f75b66e 474 switch (row) {
wim 8:03116f75b66e 475 case 0:
wim 8:03116f75b66e 476 return 0x00 + column;
wim 8:03116f75b66e 477 case 1:
wim 8:03116f75b66e 478 return 0x40 + column;
wim 8:03116f75b66e 479 case 2:
wim 8:03116f75b66e 480 return 0x14 + column;
wim 8:03116f75b66e 481 case 3:
wim 8:03116f75b66e 482 return 0x54 + column;
wim 8:03116f75b66e 483 }
wim 8:03116f75b66e 484
wim 10:dd9b3a696acd 485 // Special mode for KS0078
wim 10:dd9b3a696acd 486 case LCD24x4:
wim 10:dd9b3a696acd 487 switch (row) {
wim 10:dd9b3a696acd 488 case 0:
wim 10:dd9b3a696acd 489 return 0x00 + column;
wim 10:dd9b3a696acd 490 case 1:
wim 10:dd9b3a696acd 491 return 0x20 + column;
wim 10:dd9b3a696acd 492 case 2:
wim 10:dd9b3a696acd 493 return 0x40 + column;
wim 10:dd9b3a696acd 494 case 3:
wim 10:dd9b3a696acd 495 return 0x60 + column;
wim 10:dd9b3a696acd 496 }
wim 10:dd9b3a696acd 497
wim 8:03116f75b66e 498 // Not sure about this one, seems wrong.
wim 8:03116f75b66e 499 case LCD16x2B:
wim 8:03116f75b66e 500 return 0x00 + (row * 40) + column;
wim 8:03116f75b66e 501
wim 18:bd65dc10f27f 502 case LCD8x2:
wim 15:b70ebfffb258 503 case LCD12x2:
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 15:b70ebfffb258 509
wim 15:b70ebfffb258 510 case LCD40x4:
wim 15:b70ebfffb258 511 // LCD40x4 is a special case since it has 2 controllers
wim 15:b70ebfffb258 512 // Each controller is configured as 40x2
wim 15:b70ebfffb258 513 if (row<2) {
wim 15:b70ebfffb258 514 // Test to see if we need to switch between controllers
wim 19:c747b9e2e7b8 515 if (_ctrl_idx != _LCDCtrl_0) {
wim 17:652ab113bc2e 516
wim 15:b70ebfffb258 517 // Second LCD controller Cursor Off
wim 21:9eb628d9e164 518 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 519
wim 15:b70ebfffb258 520 // Select primary controller
wim 19:c747b9e2e7b8 521 _ctrl_idx = _LCDCtrl_0;
wim 15:b70ebfffb258 522
wim 15:b70ebfffb258 523 // Restore cursormode on primary LCD controller
wim 17:652ab113bc2e 524 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 525 }
wim 15:b70ebfffb258 526
wim 15:b70ebfffb258 527 return 0x00 + (row * 0x40) + column;
wim 15:b70ebfffb258 528 }
wim 15:b70ebfffb258 529 else {
wim 15:b70ebfffb258 530
wim 15:b70ebfffb258 531 // Test to see if we need to switch between controllers
wim 19:c747b9e2e7b8 532 if (_ctrl_idx != _LCDCtrl_1) {
wim 15:b70ebfffb258 533 // Primary LCD controller Cursor Off
wim 21:9eb628d9e164 534 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 535
wim 15:b70ebfffb258 536 // Select secondary controller
wim 19:c747b9e2e7b8 537 _ctrl_idx = _LCDCtrl_1;
wim 15:b70ebfffb258 538
wim 15:b70ebfffb258 539 // Restore cursormode on secondary LCD controller
wim 17:652ab113bc2e 540 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 541 }
wim 15:b70ebfffb258 542
wim 15:b70ebfffb258 543 return 0x00 + ((row-2) * 0x40) + column;
wim 15:b70ebfffb258 544 }
wim 8:03116f75b66e 545
wim 8:03116f75b66e 546 // Should never get here.
wim 8:03116f75b66e 547 default:
wim 8:03116f75b66e 548 return 0x00;
wim 8:03116f75b66e 549 }
wim 8:03116f75b66e 550 }
wim 8:03116f75b66e 551
wim 8:03116f75b66e 552
wim 15:b70ebfffb258 553 // Set row, column and update memoryaddress.
wim 8:03116f75b66e 554 //
wim 21:9eb628d9e164 555 void TextLCD_Base::setAddress(int column, int row) {
wim 15:b70ebfffb258 556
wim 15:b70ebfffb258 557 // Sanity Check column
wim 15:b70ebfffb258 558 if (column < 0) {
wim 15:b70ebfffb258 559 _column = 0;
wim 15:b70ebfffb258 560 }
wim 15:b70ebfffb258 561 else if (column >= columns()) {
wim 15:b70ebfffb258 562 _column = columns() - 1;
wim 15:b70ebfffb258 563 } else _column = column;
wim 8:03116f75b66e 564
wim 15:b70ebfffb258 565 // Sanity Check row
wim 15:b70ebfffb258 566 if (row < 0) {
wim 15:b70ebfffb258 567 _row = 0;
wim 15:b70ebfffb258 568 }
wim 15:b70ebfffb258 569 else if (row >= rows()) {
wim 15:b70ebfffb258 570 _row = rows() - 1;
wim 15:b70ebfffb258 571 } else _row = row;
wim 15:b70ebfffb258 572
wim 15:b70ebfffb258 573
wim 15:b70ebfffb258 574 // Compute the memory address
wim 15:b70ebfffb258 575 // For LCD40x4: switch controllers if needed
wim 15:b70ebfffb258 576 // switch cursor if needed
wim 15:b70ebfffb258 577 int addr = getAddress(_column, _row);
wim 8:03116f75b66e 578
wim 13:24506ba22480 579 _writeCommand(0x80 | addr);
wim 8:03116f75b66e 580 }
simon 1:ac48b187213c 581
wim 21:9eb628d9e164 582 int TextLCD_Base::columns() {
simon 1:ac48b187213c 583 switch (_type) {
wim 8:03116f75b66e 584 case LCD8x1:
wim 8:03116f75b66e 585 case LCD8x2:
wim 18:bd65dc10f27f 586 case LCD8x2B:
wim 8:03116f75b66e 587 return 8;
wim 15:b70ebfffb258 588
wim 15:b70ebfffb258 589 case LCD12x2:
wim 15:b70ebfffb258 590 case LCD12x4:
wim 15:b70ebfffb258 591 return 12;
wim 8:03116f75b66e 592
wim 13:24506ba22480 593 case LCD16x1:
simon 1:ac48b187213c 594 case LCD16x2:
simon 1:ac48b187213c 595 case LCD16x2B:
wim 8:03116f75b66e 596 case LCD16x4:
wim 8:03116f75b66e 597 return 16;
wim 8:03116f75b66e 598
wim 8:03116f75b66e 599 case LCD20x2:
wim 8:03116f75b66e 600 case LCD20x4:
wim 8:03116f75b66e 601 return 20;
wim 8:03116f75b66e 602
wim 8:03116f75b66e 603 case LCD24x2:
wim 10:dd9b3a696acd 604 case LCD24x4:
wim 8:03116f75b66e 605 return 24;
wim 9:0893d986e717 606
wim 9:0893d986e717 607 case LCD40x2:
wim 15:b70ebfffb258 608 case LCD40x4:
wim 9:0893d986e717 609 return 40;
wim 8:03116f75b66e 610
wim 8:03116f75b66e 611 // Should never get here.
simon 1:ac48b187213c 612 default:
wim 8:03116f75b66e 613 return 0;
simon 1:ac48b187213c 614 }
simon 1:ac48b187213c 615 }
simon 1:ac48b187213c 616
wim 21:9eb628d9e164 617 int TextLCD_Base::rows() {
simon 1:ac48b187213c 618 switch (_type) {
wim 8:03116f75b66e 619 case LCD8x1:
wim 13:24506ba22480 620 case LCD16x1:
wim 8:03116f75b66e 621 return 1;
wim 8:03116f75b66e 622
wim 15:b70ebfffb258 623 case LCD8x2:
wim 18:bd65dc10f27f 624 case LCD8x2B:
wim 15:b70ebfffb258 625 case LCD12x2:
simon 1:ac48b187213c 626 case LCD16x2:
simon 1:ac48b187213c 627 case LCD16x2B:
simon 1:ac48b187213c 628 case LCD20x2:
wim 8:03116f75b66e 629 case LCD24x2:
wim 9:0893d986e717 630 case LCD40x2:
wim 8:03116f75b66e 631 return 2;
wim 8:03116f75b66e 632
wim 15:b70ebfffb258 633 case LCD12x4:
wim 8:03116f75b66e 634 case LCD16x4:
wim 8:03116f75b66e 635 case LCD20x4:
wim 10:dd9b3a696acd 636 case LCD24x4:
wim 15:b70ebfffb258 637 case LCD40x4:
wim 8:03116f75b66e 638 return 4;
wim 12:6bf9d9957d31 639
wim 12:6bf9d9957d31 640 // Should never get here.
simon 1:ac48b187213c 641 default:
wim 8:03116f75b66e 642 return 0;
simon 1:ac48b187213c 643 }
simon 1:ac48b187213c 644 }
wim 10:dd9b3a696acd 645
wim 10:dd9b3a696acd 646
wim 17:652ab113bc2e 647 // Set the Cursor Mode (Cursor Off & Blink Off, Cursor On & Blink Off, Cursor Off & Blink On, Cursor On & Blink On
wim 21:9eb628d9e164 648 void TextLCD_Base::setCursor(LCDCursor cursorMode) {
wim 15:b70ebfffb258 649
wim 17:652ab113bc2e 650 // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on
wim 17:652ab113bc2e 651 _currentCursor = cursorMode;
wim 10:dd9b3a696acd 652
wim 17:652ab113bc2e 653 // Configure only current LCD controller
wim 17:652ab113bc2e 654 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 655
wim 15:b70ebfffb258 656 }
wim 15:b70ebfffb258 657
wim 17:652ab113bc2e 658 // Set the Displaymode (On/Off)
wim 21:9eb628d9e164 659 void TextLCD_Base::setMode(LCDMode displayMode) {
wim 17:652ab113bc2e 660
wim 17:652ab113bc2e 661 // Save new displayMode, needed when 2 controllers are in use or when cursor is changed
wim 17:652ab113bc2e 662 _currentMode = displayMode;
wim 15:b70ebfffb258 663
wim 17:652ab113bc2e 664 // Select and configure second LCD controller when needed
wim 17:652ab113bc2e 665 if(_type==LCD40x4) {
wim 21:9eb628d9e164 666 if (_ctrl_idx==_LCDCtrl_0) {
wim 17:652ab113bc2e 667 // Configure primary LCD controller
wim 17:652ab113bc2e 668 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 11:9ec02df863a1 669
wim 17:652ab113bc2e 670 // Select 2nd controller
wim 21:9eb628d9e164 671 _ctrl_idx=_LCDCtrl_1;
wim 17:652ab113bc2e 672
wim 17:652ab113bc2e 673 // Configure secondary LCD controller
wim 21:9eb628d9e164 674 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 11:9ec02df863a1 675
wim 17:652ab113bc2e 676 // Restore current controller
wim 21:9eb628d9e164 677 _ctrl_idx=_LCDCtrl_0;
wim 17:652ab113bc2e 678 }
wim 17:652ab113bc2e 679 else {
wim 17:652ab113bc2e 680 // Select primary controller
wim 21:9eb628d9e164 681 _ctrl_idx=_LCDCtrl_0;
wim 17:652ab113bc2e 682
wim 17:652ab113bc2e 683 // Configure primary LCD controller
wim 21:9eb628d9e164 684 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 17:652ab113bc2e 685
wim 17:652ab113bc2e 686 // Restore current controller
wim 21:9eb628d9e164 687 _ctrl_idx=_LCDCtrl_1;
wim 11:9ec02df863a1 688
wim 17:652ab113bc2e 689 // Configure secondary LCD controller
wim 17:652ab113bc2e 690 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 11:9ec02df863a1 691
wim 10:dd9b3a696acd 692 }
wim 17:652ab113bc2e 693 }
wim 17:652ab113bc2e 694 else {
wim 17:652ab113bc2e 695 // Configure primary LCD controller
wim 17:652ab113bc2e 696 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 17:652ab113bc2e 697 }
wim 17:652ab113bc2e 698
wim 17:652ab113bc2e 699 }
wim 17:652ab113bc2e 700
wim 17:652ab113bc2e 701
wim 17:652ab113bc2e 702 // Set the Displaymode (On/Off) and Cursortype for current controller
wim 21:9eb628d9e164 703 void TextLCD_Base::_setCursorAndDisplayMode(LCDMode displayMode, LCDCursor cursorType) {
wim 17:652ab113bc2e 704
wim 17:652ab113bc2e 705 // Configure current LCD controller
wim 17:652ab113bc2e 706 _writeCommand(0x08 | displayMode | cursorType);
wim 10:dd9b3a696acd 707 }
wim 10:dd9b3a696acd 708
wim 20:e0da005a777f 709 // Set the Backlight mode (Off/On)
wim 21:9eb628d9e164 710 void TextLCD_Base::setBacklight(LCDBacklight backlightMode) {
wim 20:e0da005a777f 711
wim 20:e0da005a777f 712 if (backlightMode == LightOn) {
wim 21:9eb628d9e164 713 this->_setBL(true);
wim 20:e0da005a777f 714 }
wim 20:e0da005a777f 715 else {
wim 21:9eb628d9e164 716 this->_setBL(false);
wim 20:e0da005a777f 717 }
wim 20:e0da005a777f 718 }
wim 20:e0da005a777f 719
wim 10:dd9b3a696acd 720
wim 21:9eb628d9e164 721 void TextLCD_Base::setUDC(unsigned char c, char *udc_data) {
wim 15:b70ebfffb258 722
wim 15:b70ebfffb258 723 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 724 if(_type==LCD40x4) {
wim 19:c747b9e2e7b8 725 _LCDCtrl_Idx current_ctrl_idx = _ctrl_idx; // Temp save current controller
wim 15:b70ebfffb258 726
wim 15:b70ebfffb258 727 // Select primary controller
wim 21:9eb628d9e164 728 _ctrl_idx=_LCDCtrl_0;
wim 15:b70ebfffb258 729
wim 15:b70ebfffb258 730 // Configure primary LCD controller
wim 15:b70ebfffb258 731 _setUDC(c, udc_data);
wim 15:b70ebfffb258 732
wim 15:b70ebfffb258 733 // Select 2nd controller
wim 21:9eb628d9e164 734 _ctrl_idx=_LCDCtrl_1;
wim 15:b70ebfffb258 735
wim 15:b70ebfffb258 736 // Configure secondary LCD controller
wim 15:b70ebfffb258 737 _setUDC(c, udc_data);
wim 11:9ec02df863a1 738
wim 15:b70ebfffb258 739 // Restore current controller
wim 19:c747b9e2e7b8 740 _ctrl_idx=current_ctrl_idx;
wim 15:b70ebfffb258 741 }
wim 15:b70ebfffb258 742 else {
wim 15:b70ebfffb258 743 // Configure primary LCD controller
wim 15:b70ebfffb258 744 _setUDC(c, udc_data);
wim 15:b70ebfffb258 745 }
wim 15:b70ebfffb258 746
wim 15:b70ebfffb258 747 }
wim 15:b70ebfffb258 748
wim 21:9eb628d9e164 749 void TextLCD_Base::_setUDC(unsigned char c, char *udc_data) {
wim 15:b70ebfffb258 750
wim 15:b70ebfffb258 751 // Select CG RAM for current LCD controller
wim 15:b70ebfffb258 752 _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address,
wim 15:b70ebfffb258 753 //8 sequential locations needed per UDC
wim 15:b70ebfffb258 754 // Store UDC pattern
wim 11:9ec02df863a1 755 for (int i=0; i<8; i++) {
wim 13:24506ba22480 756 _writeData(*udc_data++);
wim 11:9ec02df863a1 757 }
wim 15:b70ebfffb258 758
wim 15:b70ebfffb258 759 //Select DD RAM again for current LCD controller
wim 15:b70ebfffb258 760 int addr = getAddress(_column, _row);
wim 15:b70ebfffb258 761 _writeCommand(0x80 | addr);
wim 15:b70ebfffb258 762
wim 11:9ec02df863a1 763 }
wim 21:9eb628d9e164 764
wim 23:d47f226efb24 765 //--------- End TextLCD_Base -----------
wim 21:9eb628d9e164 766
wim 22:35742ec80c24 767
wim 21:9eb628d9e164 768
wim 23:d47f226efb24 769 //--------- Start TextLCD Bus -----------
wim 21:9eb628d9e164 770
wim 21:9eb628d9e164 771 /* Create a TextLCD interface for using regular mbed pins
wim 21:9eb628d9e164 772 *
wim 21:9eb628d9e164 773 * @param rs Instruction/data control line
wim 21:9eb628d9e164 774 * @param e Enable line (clock)
wim 21:9eb628d9e164 775 * @param d4-d7 Data lines for using as a 4-bit interface
wim 21:9eb628d9e164 776 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 777 * @param bl Backlight control line (optional, default = NC)
wim 21:9eb628d9e164 778 * @param e2 Enable2 line (clock for second controller, LCD40x4 only)
wim 21:9eb628d9e164 779 * @param ctrl LCD controller (default = HD44780)
wim 21:9eb628d9e164 780 */
wim 21:9eb628d9e164 781 TextLCD::TextLCD(PinName rs, PinName e,
wim 21:9eb628d9e164 782 PinName d4, PinName d5, PinName d6, PinName d7,
wim 21:9eb628d9e164 783 LCDType type, PinName bl, PinName e2, LCDCtrl ctrl) :
wim 21:9eb628d9e164 784 TextLCD_Base(type, ctrl),
wim 22:35742ec80c24 785 _rs(rs), _e(e), _d(d4, d5, d6, d7) {
wim 22:35742ec80c24 786
wim 22:35742ec80c24 787 // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
wim 22:35742ec80c24 788 if (bl != NC) {
wim 22:35742ec80c24 789 _bl = new DigitalOut(bl); //Construct new pin
wim 22:35742ec80c24 790 _bl->write(0); //Deactivate
wim 22:35742ec80c24 791 }
wim 22:35742ec80c24 792 else {
wim 22:35742ec80c24 793 // No Hardware Backlight pin
wim 22:35742ec80c24 794 _bl = NULL; //Construct dummy pin
wim 22:35742ec80c24 795 }
wim 22:35742ec80c24 796
wim 22:35742ec80c24 797 // The hardware Enable2 pin is only needed for LCD40x4. Test and make sure whether it exists or not to prevent illegal access.
wim 22:35742ec80c24 798 if (e2 != NC) {
wim 22:35742ec80c24 799 _e2 = new DigitalOut(e2); //Construct new pin
wim 22:35742ec80c24 800 _e2->write(0); //Deactivate
wim 22:35742ec80c24 801 }
wim 22:35742ec80c24 802 else {
wim 22:35742ec80c24 803 // No Hardware Enable pin
wim 22:35742ec80c24 804 _e2 = NULL; //Construct dummy pin
wim 22:35742ec80c24 805 }
wim 21:9eb628d9e164 806
wim 21:9eb628d9e164 807 _init();
wim 21:9eb628d9e164 808
wim 21:9eb628d9e164 809 }
wim 21:9eb628d9e164 810
wim 22:35742ec80c24 811 /** Set E pin (or E2 pin)
wim 22:35742ec80c24 812 * Used for mbed pins, I2C bus expander or SPI shiftregister
wim 22:35742ec80c24 813 * Default PinName value for E2 is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
wim 22:35742ec80c24 814 * @param value true or false
wim 22:35742ec80c24 815 * @return none
wim 22:35742ec80c24 816 */
wim 21:9eb628d9e164 817 void TextLCD::_setEnable(bool value) {
wim 21:9eb628d9e164 818
wim 22:35742ec80c24 819 if(_ctrl_idx==_LCDCtrl_0) {
wim 22:35742ec80c24 820 if (value) {
wim 22:35742ec80c24 821 _e = 1; // Set E bit
wim 22:35742ec80c24 822 }
wim 22:35742ec80c24 823 else {
wim 22:35742ec80c24 824 _e = 0; // Reset E bit
wim 22:35742ec80c24 825 }
wim 22:35742ec80c24 826 }
wim 22:35742ec80c24 827 else {
wim 22:35742ec80c24 828 if (value) {
wim 22:35742ec80c24 829 if (_e2 != NULL) {_e2->write(1);} //Set E2 bit
wim 22:35742ec80c24 830 }
wim 22:35742ec80c24 831 else {
wim 22:35742ec80c24 832 if (_e2 != NULL) {_e2->write(0);} //Reset E2 bit
wim 22:35742ec80c24 833 }
wim 22:35742ec80c24 834 }
wim 21:9eb628d9e164 835
wim 21:9eb628d9e164 836 }
wim 21:9eb628d9e164 837
wim 21:9eb628d9e164 838 // Set RS pin
wim 21:9eb628d9e164 839 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 840 void TextLCD::_setRS(bool value) {
wim 21:9eb628d9e164 841
wim 22:35742ec80c24 842 if (value) {
wim 21:9eb628d9e164 843 _rs = 1; // Set RS bit
wim 22:35742ec80c24 844 }
wim 22:35742ec80c24 845 else {
wim 21:9eb628d9e164 846 _rs = 0; // Reset RS bit
wim 22:35742ec80c24 847 }
wim 21:9eb628d9e164 848
wim 21:9eb628d9e164 849 }
wim 21:9eb628d9e164 850
wim 22:35742ec80c24 851 /** Set BL pin
wim 22:35742ec80c24 852 * Used for mbed pins, I2C bus expander or SPI shiftregister
wim 22:35742ec80c24 853 * Default PinName value is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
wim 22:35742ec80c24 854 * @param value true or false
wim 22:35742ec80c24 855 * @return none
wim 22:35742ec80c24 856 */
wim 21:9eb628d9e164 857 void TextLCD::_setBL(bool value) {
wim 21:9eb628d9e164 858
wim 22:35742ec80c24 859 if (value) {
wim 22:35742ec80c24 860 if (_bl != NULL) {_bl->write(1);} //Set BL bit
wim 22:35742ec80c24 861 }
wim 22:35742ec80c24 862 else {
wim 22:35742ec80c24 863 if (_bl != NULL) {_bl->write(0);} //Reset BL bit
wim 22:35742ec80c24 864 }
wim 21:9eb628d9e164 865
wim 21:9eb628d9e164 866 }
wim 21:9eb628d9e164 867
wim 21:9eb628d9e164 868 // Place the 4bit data on the databus
wim 21:9eb628d9e164 869 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 21:9eb628d9e164 870 void TextLCD::_setData(int value) {
wim 21:9eb628d9e164 871 _d = value & 0x0F; // Write Databits
wim 21:9eb628d9e164 872 }
wim 21:9eb628d9e164 873
wim 22:35742ec80c24 874 /** Destruct a TextLCD interface for using regular mbed pins
wim 22:35742ec80c24 875 *
wim 22:35742ec80c24 876 * @param none
wim 22:35742ec80c24 877 * @return none
wim 22:35742ec80c24 878 */
wim 22:35742ec80c24 879 TextLCD::~TextLCD() {
wim 22:35742ec80c24 880 if (_bl != NULL) {delete _bl;} // BL pin
wim 22:35742ec80c24 881 if (_e2 != NULL) {delete _e2;} // E2 pin
wim 22:35742ec80c24 882 }
wim 21:9eb628d9e164 883
wim 22:35742ec80c24 884
wim 23:d47f226efb24 885 //----------- End TextLCD ---------------
wim 21:9eb628d9e164 886
wim 21:9eb628d9e164 887
wim 23:d47f226efb24 888 //--------- Start TextLCD_I2C -----------
wim 22:35742ec80c24 889
wim 26:bd897a001012 890 /** Create a TextLCD interface using an I2C PC8574 (or PCF8574A) or MCP23008 portexpander
wim 22:35742ec80c24 891 *
wim 22:35742ec80c24 892 * @param i2c I2C Bus
wim 26:bd897a001012 893 * @param deviceAddress I2C slave address (PCF8574, PCF8574A or MCP23008, default = 0x40)
wim 22:35742ec80c24 894 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 22:35742ec80c24 895 * @param ctrl LCD controller (default = HD44780)
wim 22:35742ec80c24 896 */
wim 21:9eb628d9e164 897 TextLCD_I2C::TextLCD_I2C(I2C *i2c, char deviceAddress, LCDType type, LCDCtrl ctrl) :
wim 21:9eb628d9e164 898 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 899 _i2c(i2c){
wim 21:9eb628d9e164 900
wim 22:35742ec80c24 901 _slaveAddress = deviceAddress & 0xFE;
wim 21:9eb628d9e164 902
wim 26:bd897a001012 903
wim 26:bd897a001012 904 #if (MCP23008==1)
wim 26:bd897a001012 905 // MCP23008 portexpander Init
wim 27:22d5086f6ba6 906 _write_register(IODIR, 0x00); // All outputs
wim 27:22d5086f6ba6 907 _write_register(IPOL, 0x00); // No reverse polarity
wim 27:22d5086f6ba6 908 _write_register(GPINTEN, 0x00); // No interrupt
wim 27:22d5086f6ba6 909 _write_register(DEFVAL, 0x00); // Default value to compare against for interrupts
wim 27:22d5086f6ba6 910 _write_register(INTCON, 0x00); // No interrupt on changes
wim 27:22d5086f6ba6 911 _write_register(IOCON, 0x00); // Interrupt polarity
wim 27:22d5086f6ba6 912 _write_register(GPPU, 0x00); // No Pullup
wim 27:22d5086f6ba6 913 _write_register(INTF, 0x00); //
wim 27:22d5086f6ba6 914 _write_register(INTCAP, 0x00); //
wim 27:22d5086f6ba6 915 _write_register(GPIO, 0x00); // Output/Input pins
wim 27:22d5086f6ba6 916 _write_register(OLAT, 0x00); // Output Latch
wim 26:bd897a001012 917
wim 21:9eb628d9e164 918 // Init the portexpander bus
wim 21:9eb628d9e164 919 _lcd_bus = D_LCD_BUS_DEF;
wim 21:9eb628d9e164 920
wim 21:9eb628d9e164 921 // write the new data to the portexpander
wim 26:bd897a001012 922 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 923 #else
wim 26:bd897a001012 924 // PCF8574 of PCF8574A portexpander
wim 26:bd897a001012 925
wim 26:bd897a001012 926 // Init the portexpander bus
wim 26:bd897a001012 927 _lcd_bus = D_LCD_BUS_DEF;
wim 26:bd897a001012 928
wim 26:bd897a001012 929 // write the new data to the portexpander
wim 21:9eb628d9e164 930 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 931 #endif
wim 21:9eb628d9e164 932
wim 21:9eb628d9e164 933 _init();
wim 21:9eb628d9e164 934
wim 21:9eb628d9e164 935 }
wim 21:9eb628d9e164 936
wim 21:9eb628d9e164 937 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 938 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 939 void TextLCD_I2C::_setEnable(bool value) {
wim 21:9eb628d9e164 940
wim 22:35742ec80c24 941 if(_ctrl_idx==_LCDCtrl_0) {
wim 26:bd897a001012 942 if (value) {
wim 22:35742ec80c24 943 _lcd_bus |= D_LCD_E; // Set E bit
wim 26:bd897a001012 944 }
wim 26:bd897a001012 945 else {
wim 22:35742ec80c24 946 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 26:bd897a001012 947 }
wim 22:35742ec80c24 948 }
wim 22:35742ec80c24 949 else {
wim 26:bd897a001012 950 if (value) {
wim 22:35742ec80c24 951 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 26:bd897a001012 952 }
wim 26:bd897a001012 953 else {
wim 22:35742ec80c24 954 _lcd_bus &= ~D_LCD_E2; // Reset E2bit
wim 26:bd897a001012 955 }
wim 26:bd897a001012 956 }
wim 26:bd897a001012 957
wim 26:bd897a001012 958
wim 26:bd897a001012 959 #if (MCP23008==1)
wim 26:bd897a001012 960 // MCP23008 portexpander
wim 26:bd897a001012 961
wim 26:bd897a001012 962 // write the new data to the portexpander
wim 26:bd897a001012 963 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 964 #else
wim 26:bd897a001012 965 // PCF8574 of PCF8574A portexpander
wim 21:9eb628d9e164 966
wim 22:35742ec80c24 967 // write the new data to the I2C portexpander
wim 22:35742ec80c24 968 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 969 #endif
wim 21:9eb628d9e164 970 }
wim 21:9eb628d9e164 971
wim 21:9eb628d9e164 972 // Set RS pin
wim 21:9eb628d9e164 973 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 974 void TextLCD_I2C::_setRS(bool value) {
wim 21:9eb628d9e164 975
wim 26:bd897a001012 976 if (value) {
wim 22:35742ec80c24 977 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 26:bd897a001012 978 }
wim 26:bd897a001012 979 else {
wim 22:35742ec80c24 980 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 26:bd897a001012 981 }
wim 26:bd897a001012 982
wim 26:bd897a001012 983
wim 26:bd897a001012 984 #if (MCP23008==1)
wim 26:bd897a001012 985 // MCP23008 portexpander
wim 26:bd897a001012 986
wim 26:bd897a001012 987 // write the new data to the portexpander
wim 26:bd897a001012 988 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 989 #else
wim 26:bd897a001012 990 // PCF8574 of PCF8574A portexpander
wim 21:9eb628d9e164 991
wim 22:35742ec80c24 992 // write the new data to the I2C portexpander
wim 22:35742ec80c24 993 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 994 #endif
wim 21:9eb628d9e164 995
wim 21:9eb628d9e164 996 }
wim 21:9eb628d9e164 997
wim 21:9eb628d9e164 998 // Set BL pin
wim 21:9eb628d9e164 999 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1000 void TextLCD_I2C::_setBL(bool value) {
wim 21:9eb628d9e164 1001
wim 26:bd897a001012 1002 if (value) {
wim 21:9eb628d9e164 1003 _lcd_bus |= D_LCD_BL; // Set BL bit
wim 26:bd897a001012 1004 }
wim 26:bd897a001012 1005 else {
wim 21:9eb628d9e164 1006 _lcd_bus &= ~D_LCD_BL; // Reset BL bit
wim 26:bd897a001012 1007 }
wim 26:bd897a001012 1008
wim 26:bd897a001012 1009 #if (MCP23008==1)
wim 26:bd897a001012 1010 // MCP23008 portexpander
wim 26:bd897a001012 1011
wim 26:bd897a001012 1012 // write the new data to the portexpander
wim 26:bd897a001012 1013 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 1014 #else
wim 26:bd897a001012 1015 // PCF8574 of PCF8574A portexpander
wim 21:9eb628d9e164 1016
wim 21:9eb628d9e164 1017 // write the new data to the I2C portexpander
wim 21:9eb628d9e164 1018 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 1019 #endif
wim 21:9eb628d9e164 1020
wim 21:9eb628d9e164 1021 }
wim 21:9eb628d9e164 1022
wim 21:9eb628d9e164 1023
wim 21:9eb628d9e164 1024
wim 21:9eb628d9e164 1025 // Place the 4bit data on the databus
wim 21:9eb628d9e164 1026 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 21:9eb628d9e164 1027 void TextLCD_I2C::_setData(int value) {
wim 21:9eb628d9e164 1028 int data;
wim 22:35742ec80c24 1029
wim 22:35742ec80c24 1030 // Set bit by bit to support any mapping of expander portpins to LCD pins
wim 21:9eb628d9e164 1031
wim 22:35742ec80c24 1032 data = value & 0x0F;
wim 26:bd897a001012 1033 if (data & 0x01){
wim 22:35742ec80c24 1034 _lcd_bus |= D_LCD_D4; // Set Databit
wim 26:bd897a001012 1035 }
wim 26:bd897a001012 1036 else {
wim 26:bd897a001012 1037 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 26:bd897a001012 1038 }
wim 21:9eb628d9e164 1039
wim 26:bd897a001012 1040 if (data & 0x02){
wim 22:35742ec80c24 1041 _lcd_bus |= D_LCD_D5; // Set Databit
wim 26:bd897a001012 1042 }
wim 26:bd897a001012 1043 else {
wim 26:bd897a001012 1044 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 26:bd897a001012 1045 }
wim 21:9eb628d9e164 1046
wim 26:bd897a001012 1047 if (data & 0x04) {
wim 22:35742ec80c24 1048 _lcd_bus |= D_LCD_D6; // Set Databit
wim 26:bd897a001012 1049 }
wim 26:bd897a001012 1050 else {
wim 26:bd897a001012 1051 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 26:bd897a001012 1052 }
wim 21:9eb628d9e164 1053
wim 26:bd897a001012 1054 if (data & 0x08) {
wim 22:35742ec80c24 1055 _lcd_bus |= D_LCD_D7; // Set Databit
wim 26:bd897a001012 1056 }
wim 26:bd897a001012 1057 else {
wim 26:bd897a001012 1058 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 26:bd897a001012 1059 }
wim 21:9eb628d9e164 1060
wim 26:bd897a001012 1061 #if (MCP23008==1)
wim 26:bd897a001012 1062 // MCP23008 portexpander
wim 26:bd897a001012 1063
wim 26:bd897a001012 1064 // write the new data to the portexpander
wim 26:bd897a001012 1065 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 1066 #else
wim 26:bd897a001012 1067 // PCF8574 of PCF8574A portexpander
wim 26:bd897a001012 1068
wim 22:35742ec80c24 1069 // write the new data to the I2C portexpander
wim 26:bd897a001012 1070 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 1071 #endif
wim 22:35742ec80c24 1072
wim 22:35742ec80c24 1073 }
wim 21:9eb628d9e164 1074
wim 26:bd897a001012 1075 // Write data to MCP23008 I2C portexpander
wim 26:bd897a001012 1076 void TextLCD_I2C::_write_register (int reg, int value) {
wim 26:bd897a001012 1077 char data[] = {reg, value};
wim 26:bd897a001012 1078
wim 26:bd897a001012 1079 _i2c->write(_slaveAddress, data, 2);
wim 26:bd897a001012 1080
wim 26:bd897a001012 1081 }
wim 26:bd897a001012 1082
wim 23:d47f226efb24 1083 //---------- End TextLCD_I2C ------------
wim 21:9eb628d9e164 1084
wim 21:9eb628d9e164 1085
wim 21:9eb628d9e164 1086
wim 23:d47f226efb24 1087 //--------- Start TextLCD_SPI -----------
wim 21:9eb628d9e164 1088
wim 22:35742ec80c24 1089 /** Create a TextLCD interface using an SPI 74595 portexpander
wim 22:35742ec80c24 1090 *
wim 22:35742ec80c24 1091 * @param spi SPI Bus
wim 22:35742ec80c24 1092 * @param cs chip select pin (active low)
wim 22:35742ec80c24 1093 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 22:35742ec80c24 1094 * @param ctrl LCD controller (default = HD44780)
wim 22:35742ec80c24 1095 */
wim 21:9eb628d9e164 1096 TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) :
wim 21:9eb628d9e164 1097 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 1098 _spi(spi),
wim 21:9eb628d9e164 1099 _cs(cs) {
wim 21:9eb628d9e164 1100
wim 21:9eb628d9e164 1101 // Setup the spi for 8 bit data, low steady state clock,
wim 21:9eb628d9e164 1102 // rising edge capture, with a 500KHz or 1MHz clock rate
wim 21:9eb628d9e164 1103 _spi->format(8,0);
wim 21:9eb628d9e164 1104 _spi->frequency(500000);
wim 21:9eb628d9e164 1105 //_spi.frequency(1000000);
wim 21:9eb628d9e164 1106
wim 21:9eb628d9e164 1107
wim 21:9eb628d9e164 1108 // Init the portexpander bus
wim 21:9eb628d9e164 1109 _lcd_bus = D_LCD_BUS_DEF;
wim 21:9eb628d9e164 1110
wim 21:9eb628d9e164 1111 // write the new data to the portexpander
wim 21:9eb628d9e164 1112 _setCS(false);
wim 21:9eb628d9e164 1113 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1114 _setCS(true);
wim 21:9eb628d9e164 1115
wim 21:9eb628d9e164 1116 _init();
wim 21:9eb628d9e164 1117
wim 21:9eb628d9e164 1118 }
wim 21:9eb628d9e164 1119
wim 21:9eb628d9e164 1120 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 1121 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1122 void TextLCD_SPI::_setEnable(bool value) {
wim 21:9eb628d9e164 1123
wim 22:35742ec80c24 1124 if(_ctrl_idx==_LCDCtrl_0) {
wim 26:bd897a001012 1125 if (value) {
wim 22:35742ec80c24 1126 _lcd_bus |= D_LCD_E; // Set E bit
wim 26:bd897a001012 1127 }
wim 26:bd897a001012 1128 else {
wim 22:35742ec80c24 1129 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 26:bd897a001012 1130 }
wim 22:35742ec80c24 1131 }
wim 22:35742ec80c24 1132 else {
wim 26:bd897a001012 1133 if (value) {
wim 22:35742ec80c24 1134 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 26:bd897a001012 1135 }
wim 26:bd897a001012 1136 else {
wim 22:35742ec80c24 1137 _lcd_bus &= ~D_LCD_E2; // Reset E2 bit
wim 26:bd897a001012 1138 }
wim 22:35742ec80c24 1139 }
wim 21:9eb628d9e164 1140
wim 22:35742ec80c24 1141 // write the new data to the SPI portexpander
wim 22:35742ec80c24 1142 _setCS(false);
wim 22:35742ec80c24 1143 _spi->write(_lcd_bus);
wim 22:35742ec80c24 1144 _setCS(true);
wim 21:9eb628d9e164 1145
wim 21:9eb628d9e164 1146 }
wim 21:9eb628d9e164 1147
wim 21:9eb628d9e164 1148 // Set RS pin
wim 21:9eb628d9e164 1149 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1150 void TextLCD_SPI::_setRS(bool value) {
wim 21:9eb628d9e164 1151
wim 22:35742ec80c24 1152 if (value) {
wim 21:9eb628d9e164 1153 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 22:35742ec80c24 1154 }
wim 22:35742ec80c24 1155 else {
wim 21:9eb628d9e164 1156 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 22:35742ec80c24 1157 }
wim 21:9eb628d9e164 1158
wim 21:9eb628d9e164 1159 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 1160 _setCS(false);
wim 21:9eb628d9e164 1161 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1162 _setCS(true);
wim 21:9eb628d9e164 1163
wim 21:9eb628d9e164 1164 }
wim 21:9eb628d9e164 1165
wim 21:9eb628d9e164 1166 // Set BL pin
wim 21:9eb628d9e164 1167 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1168 void TextLCD_SPI::_setBL(bool value) {
wim 21:9eb628d9e164 1169
wim 22:35742ec80c24 1170 if (value) {
wim 21:9eb628d9e164 1171 _lcd_bus |= D_LCD_BL; // Set BL bit
wim 22:35742ec80c24 1172 }
wim 22:35742ec80c24 1173 else {
wim 21:9eb628d9e164 1174 _lcd_bus &= ~D_LCD_BL; // Reset BL bit
wim 22:35742ec80c24 1175 }
wim 21:9eb628d9e164 1176
wim 21:9eb628d9e164 1177 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 1178 _setCS(false);
wim 21:9eb628d9e164 1179 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1180 _setCS(true);
wim 21:9eb628d9e164 1181
wim 21:9eb628d9e164 1182 }
wim 21:9eb628d9e164 1183
wim 21:9eb628d9e164 1184
wim 21:9eb628d9e164 1185
wim 21:9eb628d9e164 1186 // Place the 4bit data on the databus
wim 21:9eb628d9e164 1187 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1188 void TextLCD_SPI::_setData(int value) {
wim 21:9eb628d9e164 1189 int data;
wim 21:9eb628d9e164 1190
wim 22:35742ec80c24 1191 // Set bit by bit to support any mapping of expander portpins to LCD pins
wim 22:35742ec80c24 1192
wim 22:35742ec80c24 1193 data = value & 0x0F;
wim 26:bd897a001012 1194 if (data & 0x01) {
wim 22:35742ec80c24 1195 _lcd_bus |= D_LCD_D4; // Set Databit
wim 26:bd897a001012 1196 }
wim 26:bd897a001012 1197 else {
wim 22:35742ec80c24 1198 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 26:bd897a001012 1199 }
wim 26:bd897a001012 1200
wim 26:bd897a001012 1201 if (data & 0x02) {
wim 22:35742ec80c24 1202 _lcd_bus |= D_LCD_D5; // Set Databit
wim 26:bd897a001012 1203 }
wim 26:bd897a001012 1204 else {
wim 22:35742ec80c24 1205 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 26:bd897a001012 1206 }
wim 26:bd897a001012 1207
wim 26:bd897a001012 1208 if (data & 0x04) {
wim 22:35742ec80c24 1209 _lcd_bus |= D_LCD_D6; // Set Databit
wim 26:bd897a001012 1210 }
wim 26:bd897a001012 1211 else {
wim 22:35742ec80c24 1212 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 26:bd897a001012 1213 }
wim 26:bd897a001012 1214
wim 26:bd897a001012 1215 if (data & 0x08) {
wim 22:35742ec80c24 1216 _lcd_bus |= D_LCD_D7; // Set Databit
wim 26:bd897a001012 1217 }
wim 26:bd897a001012 1218 else {
wim 26:bd897a001012 1219 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 26:bd897a001012 1220 }
wim 21:9eb628d9e164 1221
wim 22:35742ec80c24 1222 // write the new data to the SPI portexpander
wim 22:35742ec80c24 1223 _setCS(false);
wim 22:35742ec80c24 1224 _spi->write(_lcd_bus);
wim 22:35742ec80c24 1225 _setCS(true);
wim 21:9eb628d9e164 1226
wim 21:9eb628d9e164 1227 }
wim 21:9eb628d9e164 1228
wim 21:9eb628d9e164 1229
wim 21:9eb628d9e164 1230 // Set CS line.
wim 21:9eb628d9e164 1231 // Only used for SPI bus
wim 21:9eb628d9e164 1232 void TextLCD_SPI::_setCS(bool value) {
wim 21:9eb628d9e164 1233
wim 21:9eb628d9e164 1234 if (value) {
wim 21:9eb628d9e164 1235 _cs = 1; // Set CS pin
wim 21:9eb628d9e164 1236 }
wim 22:35742ec80c24 1237 else {
wim 21:9eb628d9e164 1238 _cs = 0; // Reset CS pin
wim 22:35742ec80c24 1239 }
wim 21:9eb628d9e164 1240 }
wim 21:9eb628d9e164 1241
wim 23:d47f226efb24 1242 //---------- End TextLCD_SPI ------------
wim 22:35742ec80c24 1243
wim 22:35742ec80c24 1244
wim 25:6162b31128c9 1245 //--------- Start TextLCD_SPI_N ---------
Sissors 24:fb3399713710 1246
wim 25:6162b31128c9 1247 /** Create a TextLCD interface using a controller with a native SPI interface
Sissors 24:fb3399713710 1248 *
Sissors 24:fb3399713710 1249 * @param spi SPI Bus
Sissors 24:fb3399713710 1250 * @param cs chip select pin (active low)
wim 25:6162b31128c9 1251 * @param rs Instruction/data control line
Sissors 24:fb3399713710 1252 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 25:6162b31128c9 1253 * @param bl Backlight control line (optional, default = NC)
wim 26:bd897a001012 1254 * @param ctrl LCD controller (default = ST7032_3V3)
wim 25:6162b31128c9 1255 */
wim 25:6162b31128c9 1256 TextLCD_SPI_N::TextLCD_SPI_N(SPI *spi, PinName cs, PinName rs, LCDType type, PinName bl, LCDCtrl ctrl) :
wim 25:6162b31128c9 1257 TextLCD_Base(type, ctrl),
wim 25:6162b31128c9 1258 _spi(spi),
wim 25:6162b31128c9 1259 _cs(cs),
wim 25:6162b31128c9 1260 _rs(rs) {
Sissors 24:fb3399713710 1261
Sissors 24:fb3399713710 1262 // Setup the spi for 8 bit data, low steady state clock,
Sissors 24:fb3399713710 1263 // rising edge capture, with a 500KHz or 1MHz clock rate
Sissors 24:fb3399713710 1264 _spi->format(8,0);
Sissors 24:fb3399713710 1265 _spi->frequency(1000000);
Sissors 24:fb3399713710 1266
Sissors 24:fb3399713710 1267 // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
Sissors 24:fb3399713710 1268 if (bl != NC) {
Sissors 24:fb3399713710 1269 _bl = new DigitalOut(bl); //Construct new pin
Sissors 24:fb3399713710 1270 _bl->write(0); //Deactivate
Sissors 24:fb3399713710 1271 }
Sissors 24:fb3399713710 1272 else {
Sissors 24:fb3399713710 1273 // No Hardware Backlight pin
Sissors 24:fb3399713710 1274 _bl = NULL; //Construct dummy pin
Sissors 24:fb3399713710 1275 }
Sissors 24:fb3399713710 1276
Sissors 24:fb3399713710 1277 _init();
Sissors 24:fb3399713710 1278 }
Sissors 24:fb3399713710 1279
wim 25:6162b31128c9 1280 TextLCD_SPI_N::~TextLCD_SPI_N() {
Sissors 24:fb3399713710 1281 if (_bl != NULL) {delete _bl;} // BL pin
Sissors 24:fb3399713710 1282 }
Sissors 24:fb3399713710 1283
Sissors 24:fb3399713710 1284 // Not used in this mode
wim 25:6162b31128c9 1285 void TextLCD_SPI_N::_setEnable(bool value) {
Sissors 24:fb3399713710 1286 }
Sissors 24:fb3399713710 1287
Sissors 24:fb3399713710 1288 // Set RS pin
Sissors 24:fb3399713710 1289 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 25:6162b31128c9 1290 void TextLCD_SPI_N::_setRS(bool value) {
Sissors 24:fb3399713710 1291 _rs = value;
Sissors 24:fb3399713710 1292 }
Sissors 24:fb3399713710 1293
Sissors 24:fb3399713710 1294 // Set BL pin
wim 25:6162b31128c9 1295 void TextLCD_SPI_N::_setBL(bool value) {
wim 26:bd897a001012 1296 if (_bl) {
Sissors 24:fb3399713710 1297 _bl->write(value);
wim 26:bd897a001012 1298 }
Sissors 24:fb3399713710 1299 }
Sissors 24:fb3399713710 1300
Sissors 24:fb3399713710 1301 // Write a byte using SPI
wim 25:6162b31128c9 1302 void TextLCD_SPI_N::_writeByte(int value) {
Sissors 24:fb3399713710 1303 _cs = 0;
Sissors 24:fb3399713710 1304 wait_us(1);
Sissors 24:fb3399713710 1305 _spi->write(value);
Sissors 24:fb3399713710 1306 wait_us(1);
Sissors 24:fb3399713710 1307 _cs = 1;
Sissors 24:fb3399713710 1308 }
Sissors 24:fb3399713710 1309
Sissors 24:fb3399713710 1310 // Not used in this mode
wim 25:6162b31128c9 1311 void TextLCD_SPI_N::_setData(int value) {
Sissors 24:fb3399713710 1312 }
Sissors 24:fb3399713710 1313
Sissors 24:fb3399713710 1314
wim 25:6162b31128c9 1315 //-------- End TextLCD_SPI_N ------------
wim 21:9eb628d9e164 1316
wim 21:9eb628d9e164 1317
wim 21:9eb628d9e164 1318
wim 21:9eb628d9e164 1319
wim 21:9eb628d9e164 1320