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:
Tue Jun 17 17:41:47 2014 +0000
Revision:
29:a3663151aa65
Parent:
28:30fa94f7341c
Child:
30:033048611c01
Tested with PCF2116

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
wim 29:a3663151aa65 13 * 2014, v11: WH, Added support for native I2C controllers such as PCF21XX, improved the _initCtrl() method to deal with differences between all supported controllers
simon 1:ac48b187213c 14 *
simon 1:ac48b187213c 15 * Permission is hereby granted, free of charge, to any person obtaining a copy
simon 1:ac48b187213c 16 * of this software and associated documentation files (the "Software"), to deal
simon 1:ac48b187213c 17 * in the Software without restriction, including without limitation the rights
simon 1:ac48b187213c 18 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
simon 1:ac48b187213c 19 * copies of the Software, and to permit persons to whom the Software is
simon 1:ac48b187213c 20 * furnished to do so, subject to the following conditions:
simon 1:ac48b187213c 21 *
simon 1:ac48b187213c 22 * The above copyright notice and this permission notice shall be included in
simon 1:ac48b187213c 23 * all copies or substantial portions of the Software.
simon 1:ac48b187213c 24 *
simon 1:ac48b187213c 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
simon 1:ac48b187213c 26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
simon 1:ac48b187213c 27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
simon 1:ac48b187213c 28 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
simon 1:ac48b187213c 29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
simon 1:ac48b187213c 30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
simon 1:ac48b187213c 31 * THE SOFTWARE.
simon 1:ac48b187213c 32 */
simon 1:ac48b187213c 33
simon 1:ac48b187213c 34 #include "TextLCD.h"
simon 1:ac48b187213c 35 #include "mbed.h"
simon 1:ac48b187213c 36
wim 29:a3663151aa65 37
wim 29:a3663151aa65 38 DigitalOut led1(LED1);
wim 29:a3663151aa65 39 DigitalOut led2(LED2);
wim 29:a3663151aa65 40
wim 29:a3663151aa65 41
wim 21:9eb628d9e164 42 /** Create a TextLCD_Base interface
wim 15:b70ebfffb258 43 *
wim 21:9eb628d9e164 44 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 45 * @param ctrl LCD controller (default = HD44780)
wim 15:b70ebfffb258 46 */
wim 21:9eb628d9e164 47 TextLCD_Base::TextLCD_Base(LCDType type, LCDCtrl ctrl) : _type(type), _ctrl(ctrl) {
wim 14:0c32b66b14b8 48 }
wim 14:0c32b66b14b8 49
wim 14:0c32b66b14b8 50
wim 21:9eb628d9e164 51 /** Init the LCD Controller(s)
wim 21:9eb628d9e164 52 * Clear display
wim 21:9eb628d9e164 53 */
wim 21:9eb628d9e164 54 void TextLCD_Base::_init() {
wim 15:b70ebfffb258 55
wim 15:b70ebfffb258 56 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 57 if(_type==LCD40x4) {
wim 27:22d5086f6ba6 58 _ctrl_idx=_LCDCtrl_1; // Select 2nd controller
wim 15:b70ebfffb258 59
wim 27:22d5086f6ba6 60 _initCtrl(); // Init 2nd controller
wim 15:b70ebfffb258 61
wim 15:b70ebfffb258 62 }
wim 15:b70ebfffb258 63
wim 15:b70ebfffb258 64 // Select and configure primary LCD controller
wim 27:22d5086f6ba6 65 _ctrl_idx=_LCDCtrl_0; // Select primary controller
wim 13:24506ba22480 66
wim 19:c747b9e2e7b8 67 _initCtrl(); // Init primary controller
wim 28:30fa94f7341c 68
wim 28:30fa94f7341c 69 // Reset Cursor location
wim 28:30fa94f7341c 70 _row=0;
wim 28:30fa94f7341c 71 _column=0;
wim 15:b70ebfffb258 72 }
wim 15:b70ebfffb258 73
wim 21:9eb628d9e164 74 /** Init the LCD controller
wim 21:9eb628d9e164 75 * 4-bit mode, number of lines, fonttype, no cursor etc
wim 21:9eb628d9e164 76 *
wim 21:9eb628d9e164 77 */
wim 21:9eb628d9e164 78 void TextLCD_Base::_initCtrl() {
wim 15:b70ebfffb258 79
wim 26:bd897a001012 80 this->_setRS(false); // command mode
wim 13:24506ba22480 81
wim 26:bd897a001012 82 wait_ms(20); // Wait 20ms to ensure powered up
simon 1:ac48b187213c 83
wim 17:652ab113bc2e 84 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus)
wim 17:652ab113bc2e 85 for (int i=0; i<3; i++) {
wim 17:652ab113bc2e 86 _writeNibble(0x3);
wim 20:e0da005a777f 87 wait_ms(15); // This command takes 1.64ms, so wait for it
wim 17:652ab113bc2e 88 }
wim 17:652ab113bc2e 89 _writeNibble(0x2); // 4-bit mode
wim 17:652ab113bc2e 90 wait_us(40); // most instructions take 40us
wim 18:bd65dc10f27f 91
wim 18:bd65dc10f27f 92 // Display is now in 4-bit mode
wim 27:22d5086f6ba6 93 // Note: 4 bit mode is ignored for native SPI and I2C devices
wim 25:6162b31128c9 94
wim 29:a3663151aa65 95 // Device specific initialisations: DC/DC converter to generate VLCD or VLED, number of lines etc
wim 19:c747b9e2e7b8 96 switch (_ctrl) {
wim 29:a3663151aa65 97 case KS0078:
wim 29:a3663151aa65 98
wim 29:a3663151aa65 99 // Initialise Display configuration
wim 29:a3663151aa65 100 switch (_type) {
wim 29:a3663151aa65 101 case LCD8x1: //8x1 is a regular 1 line display
wim 29:a3663151aa65 102 case LCD8x2B: //8x2B is a special case of 16x1
wim 29:a3663151aa65 103 // case LCD12x1:
wim 29:a3663151aa65 104 case LCD16x1:
wim 29:a3663151aa65 105 case LCD24x1:
wim 29:a3663151aa65 106 //@TODO check config
wim 29:a3663151aa65 107 _writeCommand(0x20); // Function set 001 DL N F - -
wim 29:a3663151aa65 108 // DL=0 (4 bits bus)
wim 29:a3663151aa65 109 // N=0 (1 line)
wim 29:a3663151aa65 110 // F=0 (5x7 dots font)
wim 29:a3663151aa65 111 break;
wim 29:a3663151aa65 112
wim 29:a3663151aa65 113 case LCD24x4B:
wim 29:a3663151aa65 114 // Special mode for KS0078
wim 29:a3663151aa65 115 _writeCommand(0x2A); // Function set 001 DL N RE DH REV
wim 29:a3663151aa65 116 // DL=0 (4 bits bus)
wim 29:a3663151aa65 117 // N=1 (Dont care for KS0078)
wim 29:a3663151aa65 118 // RE=0 (Dis. Extended Regs, special mode for KS0078)
wim 29:a3663151aa65 119 // DH=1 (Disp shift, special mode for KS0078)
wim 29:a3663151aa65 120 // REV=0 (Reverse, special mode for KS0078)
wim 29:a3663151aa65 121
wim 29:a3663151aa65 122 _writeCommand(0x2E); // Function set 001 DL N RE DH REV
wim 29:a3663151aa65 123 // DL=0 (4 bits bus)
wim 29:a3663151aa65 124 // N=1 (Dont care for KS0078)
wim 29:a3663151aa65 125 // RE=1 (Ena Extended Regs, special mode for KS0078)
wim 29:a3663151aa65 126 // DH=1 (Disp shift, special mode for KS0078)
wim 29:a3663151aa65 127 // REV=0 (Reverse, special mode for KS0078)
wim 29:a3663151aa65 128
wim 29:a3663151aa65 129 _writeCommand(0x09); // Ext Function set 0000 1 FW BW NW
wim 29:a3663151aa65 130 // FW=0 (5-dot font, special mode for KS0078)
wim 29:a3663151aa65 131 // BW=0 (Cur BW invert disable, special mode for KS0078)
wim 29:a3663151aa65 132 // NW=1 (4 Line, special mode for KS0078)
wim 29:a3663151aa65 133
wim 29:a3663151aa65 134 _writeCommand(0x2A); // Function set 001 DL N RE DH REV
wim 29:a3663151aa65 135 // DL=0 (4 bits bus)
wim 29:a3663151aa65 136 // N=1 (Dont care for KS0078)
wim 29:a3663151aa65 137 // RE=0 (Dis. Extended Regs, special mode for KS0078)
wim 29:a3663151aa65 138 // DH=1 (Disp shift, special mode for KS0078)
wim 29:a3663151aa65 139 // REV=0 (Reverse, special mode for KS0078)
wim 29:a3663151aa65 140
wim 29:a3663151aa65 141 // All other LCD types are initialised as 2 Line displays (including LCD40x4)
wim 29:a3663151aa65 142 default:
wim 29:a3663151aa65 143 //@TODO check config
wim 29:a3663151aa65 144 _writeCommand(0x28); // Function set 001 DL N F - -
wim 29:a3663151aa65 145 // DL=0 (4 bits bus)
wim 29:a3663151aa65 146 // Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 147 // N=1 (2 lines)
wim 29:a3663151aa65 148 // F=0 (5x7 dots font, only option for 2 line display)
wim 29:a3663151aa65 149 // - (Don't care)
wim 29:a3663151aa65 150
wim 29:a3663151aa65 151 break;
wim 29:a3663151aa65 152 } // switch type
wim 29:a3663151aa65 153
wim 29:a3663151aa65 154 break; // case KS0078 Controller
wim 29:a3663151aa65 155
wim 26:bd897a001012 156 case ST7032_3V3:
wim 26:bd897a001012 157 // ST7032 controller: Initialise Voltage booster for VLCD. VDD=3V3
wim 27:22d5086f6ba6 158
wim 29:a3663151aa65 159 // Initialise Display configuration
wim 29:a3663151aa65 160 switch (_type) {
wim 29:a3663151aa65 161 case LCD8x1: //8x1 is a regular 1 line display
wim 29:a3663151aa65 162 case LCD8x2B: //8x2B is a special case of 16x1
wim 29:a3663151aa65 163 // case LCD12x1:
wim 29:a3663151aa65 164 case LCD16x1:
wim 29:a3663151aa65 165 case LCD24x1:
wim 28:30fa94f7341c 166
wim 29:a3663151aa65 167 // _writeCommand(0x31); //FUNCTION SET 8 bit,N=0 1-line display mode,5*7dot, Select Instruction Set = 1
wim 29:a3663151aa65 168 _writeCommand(0x21); //FUNCTION SET 4 bit, N=0 1-line display mode, 5*7dot, Select Instruction Set = 1
wim 29:a3663151aa65 169 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 170
wim 29:a3663151aa65 171 _writeCommand(0x1C); //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4
wim 28:30fa94f7341c 172
wim 29:a3663151aa65 173 _writeCommand(0x73); //Contrast control low byte
wim 28:30fa94f7341c 174
wim 29:a3663151aa65 175 _writeCommand(0x57); //booster circuit is turned on. /ICON display off. /Contrast control high byte
wim 29:a3663151aa65 176 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 177
wim 29:a3663151aa65 178 _writeCommand(0x6C); //Follower control
wim 29:a3663151aa65 179 wait_ms(10); // Wait 10ms to ensure powered up
wim 28:30fa94f7341c 180
wim 29:a3663151aa65 181 // _writeCommand(0x30); //FUNCTION SET 8 bit,N=0 1-line display mode,5*7dot, Return to Instruction Set = 0
wim 29:a3663151aa65 182 _writeCommand(0x20); //FUNCTION SET 4 bit, N=0 1-line display mode, 5*7dot, Return to Instruction Set = 0
wim 29:a3663151aa65 183 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 184
wim 29:a3663151aa65 185 break;
wim 29:a3663151aa65 186
wim 29:a3663151aa65 187 default:
wim 29:a3663151aa65 188 // All other LCD types are initialised as 2 Line displays
wim 29:a3663151aa65 189
wim 29:a3663151aa65 190 // _writeCommand(0x39); //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Select Instruction Set = 1
wim 29:a3663151aa65 191 _writeCommand(0x29); //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Select Instruction Set = 1
wim 29:a3663151aa65 192 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 193
wim 29:a3663151aa65 194 _writeCommand(0x1C); //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4
wim 29:a3663151aa65 195
wim 29:a3663151aa65 196 _writeCommand(0x73); //Contrast control low byte
wim 29:a3663151aa65 197
wim 29:a3663151aa65 198 _writeCommand(0x57); //booster circuit is turned on. /ICON display off. /Contrast control high byte
wim 29:a3663151aa65 199 wait_ms(10); // Wait 10ms to ensure powered up
wim 28:30fa94f7341c 200
wim 29:a3663151aa65 201 _writeCommand(0x6C); //Follower control
wim 29:a3663151aa65 202 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 203
wim 29:a3663151aa65 204 // _writeCommand(0x38); //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Return to Instruction Set = 0
wim 29:a3663151aa65 205 _writeCommand(0x28); //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Return to Instruction Set = 0
wim 29:a3663151aa65 206 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 207 } // switch type
wim 29:a3663151aa65 208
wim 29:a3663151aa65 209 break; // case ST7032_3V3 Controller
wim 26:bd897a001012 210
wim 28:30fa94f7341c 211
wim 26:bd897a001012 212 case ST7032_5V:
wim 26:bd897a001012 213 // ST7032 controller: Disable Voltage booster for VLCD. VDD=5V
wim 29:a3663151aa65 214
wim 29:a3663151aa65 215 // Initialise Display configuration
wim 29:a3663151aa65 216 switch (_type) {
wim 29:a3663151aa65 217 case LCD8x1: //8x1 is a regular 1 line display
wim 29:a3663151aa65 218 case LCD8x2B: //8x2B is a special case of 16x1
wim 29:a3663151aa65 219 // case LCD12x1:
wim 29:a3663151aa65 220 case LCD16x1:
wim 29:a3663151aa65 221 case LCD24x1:
wim 29:a3663151aa65 222
wim 29:a3663151aa65 223 // _writeCommand(0x31); //FUNCTION SET 8 bit,N=0 1-line display mode,5*7dot, Select Instruction Set = 1
wim 29:a3663151aa65 224 _writeCommand(0x21); //FUNCTION SET 4 bit, N=0 1-line display mode, 5*7dot, Select Instruction Set = 1
wim 29:a3663151aa65 225 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 226
wim 29:a3663151aa65 227 _writeCommand(0x1C); //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4
wim 29:a3663151aa65 228
wim 29:a3663151aa65 229 _writeCommand(0x73); //Contrast control low byte
wim 28:30fa94f7341c 230
wim 29:a3663151aa65 231 _writeCommand(0x53); //booster circuit is turned off. /ICON display off. /Contrast control high byte
wim 29:a3663151aa65 232 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 233
wim 29:a3663151aa65 234 _writeCommand(0x6C); //Follower control
wim 29:a3663151aa65 235 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 236
wim 29:a3663151aa65 237 // _writeCommand(0x30); //FUNCTION SET 8 bit,N=0 1-line display mode,5*7dot, Return to Instruction Set = 0
wim 29:a3663151aa65 238 _writeCommand(0x20); //FUNCTION SET 4 bit, N=0 1-line display mode, 5*7dot, Return to Instruction Set = 0
wim 29:a3663151aa65 239 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 240
wim 29:a3663151aa65 241 break;
wim 28:30fa94f7341c 242
wim 29:a3663151aa65 243 default:
wim 29:a3663151aa65 244 // All other LCD types are initialised as 2 Line displays
wim 29:a3663151aa65 245
wim 29:a3663151aa65 246 // _writeCommand(0x39); //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Select Instruction Set = 1
wim 29:a3663151aa65 247 _writeCommand(0x29); //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Select Instruction Set = 1
wim 29:a3663151aa65 248 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 249
wim 29:a3663151aa65 250 _writeCommand(0x1C); //Internal OSC frequency adjustment Framefreq=183HZ, bias will be 1/4
wim 29:a3663151aa65 251
wim 29:a3663151aa65 252 _writeCommand(0x73); //Contrast control low byte
wim 29:a3663151aa65 253
wim 29:a3663151aa65 254 _writeCommand(0x53); //booster circuit is turned off. /ICON display off. /Contrast control high byte
wim 29:a3663151aa65 255 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 256
wim 29:a3663151aa65 257 _writeCommand(0x6C); //Follower control
wim 29:a3663151aa65 258 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 259
wim 29:a3663151aa65 260 // _writeCommand(0x38); //FUNCTION SET 8 bit,N=1 2-line display mode,5*7dot, Return to Instruction Set = 0
wim 29:a3663151aa65 261 _writeCommand(0x28); //FUNCTION SET 4 bit, N=1 2-line display mode, 5*7dot, Return to Instruction Set = 0
wim 29:a3663151aa65 262 //Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 263 } // switch type
wim 29:a3663151aa65 264
wim 29:a3663151aa65 265 break; // case ST7032_5V Controller
wim 28:30fa94f7341c 266
wim 29:a3663151aa65 267 case ST7036:
wim 29:a3663151aa65 268 // ST7036 controller: Initialise Voltage booster for VLCD. VDD=5V
wim 29:a3663151aa65 269 // Note: supports 1,2 or 3 lines
wim 28:30fa94f7341c 270
wim 29:a3663151aa65 271 // Initialise Display configuration
wim 29:a3663151aa65 272 switch (_type) {
wim 29:a3663151aa65 273 case LCD8x1: //8x1 is a regular 1 line display
wim 29:a3663151aa65 274 case LCD8x2B: //8x2B is a special case of 16x1
wim 29:a3663151aa65 275 // case LCD12x1:
wim 29:a3663151aa65 276 case LCD16x1:
wim 29:a3663151aa65 277 case LCD24x1:
wim 29:a3663151aa65 278 _writeCommand(0x21); // 4-bit Databus, N=0 1 Line, DH=0 5x7font, IS2,IS1 = 01 Select Instruction Set = 1
wim 29:a3663151aa65 279 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 280 _writeCommand(0x14); // Bias: 1/5, 1 or 2-Lines LCD
wim 29:a3663151aa65 281 // _writeCommand(0x15); // Bias: 1/5, 3-Lines LCD
wim 29:a3663151aa65 282 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 283 _writeCommand(0x55); // Icon off, Booster on, Set Contrast C5, C4
wim 29:a3663151aa65 284 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 285 _writeCommand(0x6D); // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
wim 29:a3663151aa65 286 wait_ms(200); // > 200ms!
wim 29:a3663151aa65 287 _writeCommand(0x78); // Set Contrast C3, C2, C1, C0
wim 29:a3663151aa65 288 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 289 _writeCommand(0x20); // Return to Instruction Set = 0
wim 29:a3663151aa65 290 wait_ms(50);
wim 29:a3663151aa65 291 break;
wim 29:a3663151aa65 292 #if(0)
wim 29:a3663151aa65 293 // case LCD12x3:
wim 29:a3663151aa65 294 case LCD16x3:
wim 29:a3663151aa65 295 _writeCommand(0x29); // 4-bit Databus, N=1 2 Line, DH=0 5x7font, IS2,IS1 = 01 Select Instruction Set = 1
wim 29:a3663151aa65 296 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 297 // _writeCommand(0x14); // Bias: 1/5, 1 or 2-Lines LCD
wim 29:a3663151aa65 298 _writeCommand(0x15); // Bias: 1/5, 3-Lines LCD
wim 29:a3663151aa65 299 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 300 _writeCommand(0x55); // Icon off, Booster on, Set Contrast C5, C4
wim 29:a3663151aa65 301 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 302 _writeCommand(0x6D); // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
wim 29:a3663151aa65 303 wait_ms(200); // > 200ms!
wim 29:a3663151aa65 304 _writeCommand(0x78); // Set Contrast C3, C2, C1, C0
wim 29:a3663151aa65 305 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 306 _writeCommand(0x28); // Return to Instruction Set = 0
wim 29:a3663151aa65 307 wait_ms(50);
wim 29:a3663151aa65 308 break;
wim 29:a3663151aa65 309 #endif
wim 29:a3663151aa65 310 default:
wim 29:a3663151aa65 311 // All other LCD types are initialised as 2 Line displays
wim 29:a3663151aa65 312 _writeCommand(0x29); // 4-bit Databus, N=1 2 Line, DH=0 5x7font, IS2,IS1 = 01 Select Instruction Set = 1
wim 29:a3663151aa65 313 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 314 _writeCommand(0x14); // Bias: 1/5, 2-Lines LCD
wim 29:a3663151aa65 315 // _writeCommand(0x15); // Bias: 1/5, 3-Lines LCD
wim 29:a3663151aa65 316 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 317 _writeCommand(0x55); // Icon off, Booster on, Set Contrast C5, C4
wim 29:a3663151aa65 318 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 319 _writeCommand(0x6D); // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0
wim 29:a3663151aa65 320 wait_ms(200); // > 200ms!
wim 29:a3663151aa65 321 _writeCommand(0x78); // Set Contrast C3, C2, C1, C0
wim 29:a3663151aa65 322 wait_ms(30); // > 26,3ms
wim 29:a3663151aa65 323 _writeCommand(0x28); // Return to Instruction Set = 0
wim 29:a3663151aa65 324 wait_ms(50);
wim 29:a3663151aa65 325 } // switch type
wim 29:a3663151aa65 326
wim 29:a3663151aa65 327 break; // case ST7036 Controller
wim 29:a3663151aa65 328
wim 29:a3663151aa65 329 case PCF21XX_3V3:
wim 29:a3663151aa65 330 // PCF21XX controller: Initialise Voltage booster for VLCD. VDD=3V3
wim 28:30fa94f7341c 331
wim 29:a3663151aa65 332 // Initialise Display configuration
wim 29:a3663151aa65 333 switch (_type) {
wim 29:a3663151aa65 334 case LCD8x1: //8x1 is a regular 1 line display
wim 29:a3663151aa65 335 case LCD8x2B: //8x2B is a special case of 16x1
wim 29:a3663151aa65 336 // case LCD12x1:
wim 29:a3663151aa65 337 case LCD16x1:
wim 29:a3663151aa65 338 case LCD24x1:
wim 29:a3663151aa65 339 _writeCommand(0x22); //FUNCTION SET 4 bit, N=0/M=0 1-line/24 chars display mode, G=1 Booster on
wim 29:a3663151aa65 340 //Note: 4 bit mode is ignored for I2C mode
wim 29:a3663151aa65 341 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 342 break;
wim 29:a3663151aa65 343
wim 29:a3663151aa65 344 case LCD12x3B:
wim 29:a3663151aa65 345 case LCD12x4B:
wim 29:a3663151aa65 346 _writeCommand(0x2E); //FUNCTION SET 4 bit, N=1/M=1 4-line/12 chars display mode, G=1 Booster on
wim 29:a3663151aa65 347 //Note: 4 bit mode is ignored for I2C mode
wim 29:a3663151aa65 348 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 349 break;
wim 29:a3663151aa65 350
wim 29:a3663151aa65 351 default:
wim 29:a3663151aa65 352 // All other LCD types are initialised as 2 Line displays
wim 29:a3663151aa65 353 _writeCommand(0x2A); //FUNCTION SET 4 bit, N=1/M=0 2-line/24 chars display mode, G=1 Booster on
wim 29:a3663151aa65 354 //Note: 4 bit mode is ignored for I2C mode
wim 29:a3663151aa65 355
wim 29:a3663151aa65 356 wait_ms(10); // Wait 10ms to ensure powered up
wim 29:a3663151aa65 357
wim 29:a3663151aa65 358
wim 29:a3663151aa65 359 led1=!led1;
wim 29:a3663151aa65 360 } // switch type
wim 29:a3663151aa65 361
wim 29:a3663151aa65 362
wim 29:a3663151aa65 363 break; // case PCF21XX_3V3 Controller
wim 29:a3663151aa65 364
wim 29:a3663151aa65 365
wim 29:a3663151aa65 366 // case PCF21XX_5V:
wim 29:a3663151aa65 367 // PCF21XX controller: No Voltage booster for VLCD. VDD=5V
wim 29:a3663151aa65 368
wim 29:a3663151aa65 369
wim 19:c747b9e2e7b8 370 case WS0010:
wim 19:c747b9e2e7b8 371 // WS0010 OLED controller: Initialise DC/DC Voltage converter for LEDs
wim 19:c747b9e2e7b8 372 // Note: supports 1 or 2 lines (and 16x100 graphics)
wim 19:c747b9e2e7b8 373 // supports 4 fonts (English/Japanese (default), Western European-I, English/Russian, Western European-II)
wim 19:c747b9e2e7b8 374 // Cursor/Disp shift set 0001 SC RL 0 0
wim 19:c747b9e2e7b8 375 //
wim 19:c747b9e2e7b8 376 // Mode en Power set 0001 GC PWR 1 1
wim 19:c747b9e2e7b8 377 // GC = 0 (Graph Mode=1, Char Mode=0)
wim 19:c747b9e2e7b8 378 // PWR = (DC/DC On/Off)
wim 19:c747b9e2e7b8 379
wim 25:6162b31128c9 380 //_writeCommand(0x13); // DC/DC off
wim 28:30fa94f7341c 381 _writeCommand(0x17); // DC/DC on
wim 28:30fa94f7341c 382 wait_ms(10); // Wait 10ms to ensure powered up
wim 25:6162b31128c9 383
wim 29:a3663151aa65 384
wim 29:a3663151aa65 385 // Initialise Display configuration
wim 29:a3663151aa65 386 switch (_type) {
wim 29:a3663151aa65 387 case LCD8x1: //8x1 is a regular 1 line display
wim 29:a3663151aa65 388 case LCD8x2B: //8x2B is a special case of 16x1
wim 29:a3663151aa65 389 // case LCD12x1:
wim 29:a3663151aa65 390 case LCD16x1:
wim 29:a3663151aa65 391 // case LCD24x1:
wim 29:a3663151aa65 392 _writeCommand(0x20); // Function set 001 DL N F - -
wim 29:a3663151aa65 393 // DL=0 (4 bits bus)
wim 29:a3663151aa65 394 // N=0 (1 line)
wim 29:a3663151aa65 395 // F=0 (5x7 dots font)
wim 29:a3663151aa65 396 break;
wim 29:a3663151aa65 397
wim 29:a3663151aa65 398 default:
wim 29:a3663151aa65 399 // All other LCD types are initialised as 2 Line displays (including LCD40x4)
wim 29:a3663151aa65 400 _writeCommand(0x28); // Function set 001 DL N F - -
wim 29:a3663151aa65 401 // DL=0 (4 bits bus)
wim 29:a3663151aa65 402 // N=1 (2 lines)
wim 29:a3663151aa65 403 // F=0 (5x7 dots font, only option for 2 line display)
wim 29:a3663151aa65 404 // - (Don't care)
wim 29:a3663151aa65 405
wim 29:a3663151aa65 406 break;
wim 29:a3663151aa65 407 } // switch type
wim 29:a3663151aa65 408
wim 29:a3663151aa65 409 break; // case WS0100 Controller
wim 29:a3663151aa65 410
wim 19:c747b9e2e7b8 411 default:
wim 29:a3663151aa65 412 // Devices fully compatible to HD44780 that do not use any DC/DC Voltage converters but external VLCD
wim 10:dd9b3a696acd 413
wim 29:a3663151aa65 414 // Initialise Display configuration
wim 29:a3663151aa65 415 switch (_type) {
wim 29:a3663151aa65 416 case LCD8x1: //8x1 is a regular 1 line display
wim 29:a3663151aa65 417 case LCD8x2B: //8x2B is a special case of 16x1
wim 29:a3663151aa65 418 // case LCD12x1:
wim 29:a3663151aa65 419 case LCD16x1:
wim 29:a3663151aa65 420 case LCD24x1:
wim 29:a3663151aa65 421 _writeCommand(0x20); // Function set 001 DL N F - -
wim 29:a3663151aa65 422 // DL=0 (4 bits bus)
wim 29:a3663151aa65 423 // N=0 (1 line)
wim 29:a3663151aa65 424 // F=0 (5x7 dots font)
wim 29:a3663151aa65 425 break;
wim 29:a3663151aa65 426
wim 29:a3663151aa65 427 // All other LCD types are initialised as 2 Line displays (including LCD40x4)
wim 29:a3663151aa65 428 default:
wim 29:a3663151aa65 429 _writeCommand(0x28); // Function set 001 DL N F - -
wim 29:a3663151aa65 430 // DL=0 (4 bits bus)
wim 29:a3663151aa65 431 // Note: 4 bit mode is ignored for native SPI and I2C devices
wim 29:a3663151aa65 432 // N=1 (2 lines)
wim 29:a3663151aa65 433 // F=0 (5x7 dots font, only option for 2 line display)
wim 29:a3663151aa65 434 // - (Don't care)
wim 29:a3663151aa65 435
wim 29:a3663151aa65 436 break;
wim 29:a3663151aa65 437 } // switch type
wim 10:dd9b3a696acd 438
wim 29:a3663151aa65 439 break; // case default Controller
wim 29:a3663151aa65 440
wim 29:a3663151aa65 441 } // switch Controller specific initialisations
wim 29:a3663151aa65 442
wim 10:dd9b3a696acd 443
wim 29:a3663151aa65 444 // Controller general initialisations
wim 29:a3663151aa65 445
wim 28:30fa94f7341c 446 _writeCommand(0x01); // cls, and set cursor to 0
wim 28:30fa94f7341c 447 wait_ms(10); // The CLS command takes 1.64 ms.
wim 28:30fa94f7341c 448 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 28:30fa94f7341c 449
wim 28:30fa94f7341c 450 _writeCommand(0x02); // Return Home
wim 28:30fa94f7341c 451 // Cursor Home, DDRAM Address to Origin
wim 28:30fa94f7341c 452
wim 28:30fa94f7341c 453 _writeCommand(0x06); // Entry Mode 0000 0 1 I/D S
wim 13:24506ba22480 454 // Cursor Direction and Display Shift
wim 28:30fa94f7341c 455 // I/D=1 (Cur incr)
wim 28:30fa94f7341c 456 // S=0 (No display shift)
wim 10:dd9b3a696acd 457
wim 29:a3663151aa65 458 _writeCommand(0x14); // Cursor or Display shift 0001 S/C R/L x x
wim 29:a3663151aa65 459 // S/C=0 Cursor moves
wim 29:a3663151aa65 460 // R/L=1 Right
wim 29:a3663151aa65 461 //
wim 29:a3663151aa65 462
wim 29:a3663151aa65 463
wim 13:24506ba22480 464 // _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
wim 17:652ab113bc2e 465 // // Display On, Cursor Off, Blink Off
wim 21:9eb628d9e164 466 setCursor(CurOff_BlkOff);
wim 21:9eb628d9e164 467 setMode(DispOn);
wim 29:a3663151aa65 468 led2=!led2;
simon 1:ac48b187213c 469 }
simon 1:ac48b187213c 470
wim 8:03116f75b66e 471
wim 21:9eb628d9e164 472 /** Clear the screen, Cursor home.
wim 21:9eb628d9e164 473 */
wim 21:9eb628d9e164 474 void TextLCD_Base::cls() {
wim 15:b70ebfffb258 475
wim 15:b70ebfffb258 476 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 477 if(_type==LCD40x4) {
wim 21:9eb628d9e164 478 _ctrl_idx=_LCDCtrl_1; // Select 2nd controller
wim 15:b70ebfffb258 479
wim 15:b70ebfffb258 480 // Second LCD controller Cursor always Off
wim 21:9eb628d9e164 481 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 482
wim 15:b70ebfffb258 483 // Second LCD controller Clearscreen
wim 27:22d5086f6ba6 484 _writeCommand(0x01); // cls, and set cursor to 0
wim 29:a3663151aa65 485 wait_ms(10); // The CLS command takes 1.64 ms.
wim 29:a3663151aa65 486 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 487
wim 21:9eb628d9e164 488 _ctrl_idx=_LCDCtrl_0; // Select primary controller
wim 15:b70ebfffb258 489 }
wim 15:b70ebfffb258 490
wim 15:b70ebfffb258 491 // Primary LCD controller Clearscreen
wim 27:22d5086f6ba6 492 _writeCommand(0x01); // cls, and set cursor to 0
wim 29:a3663151aa65 493 wait_ms(10); // The CLS command takes 1.64 ms.
wim 29:a3663151aa65 494 // Since we are not using the Busy flag, Lets be safe and take 10 ms
wim 15:b70ebfffb258 495
wim 15:b70ebfffb258 496 // Restore cursormode on primary LCD controller when needed
wim 15:b70ebfffb258 497 if(_type==LCD40x4) {
wim 17:652ab113bc2e 498 _setCursorAndDisplayMode(_currentMode,_currentCursor);
wim 15:b70ebfffb258 499 }
wim 15:b70ebfffb258 500
wim 29:a3663151aa65 501 setAddress(0, 0); // Reset Cursor location
wim 29:a3663151aa65 502 // Note: this is needed because some rare displays (eg PCF21XX) don't use line 0 in the '3 Line' mode.
simon 1:ac48b187213c 503 }
simon 1:ac48b187213c 504
wim 29:a3663151aa65 505 /** Locate cursor to a screen column and row
wim 29:a3663151aa65 506 *
wim 29:a3663151aa65 507 * @param column The horizontal position from the left, indexed from 0
wim 29:a3663151aa65 508 * @param row The vertical position from the top, indexed from 0
wim 29:a3663151aa65 509 */
wim 21:9eb628d9e164 510 void TextLCD_Base::locate(int column, int row) {
wim 15:b70ebfffb258 511
wim 15:b70ebfffb258 512 // setAddress() does all the heavy lifting:
wim 15:b70ebfffb258 513 // check column and row sanity,
wim 15:b70ebfffb258 514 // switch controllers for LCD40x4 if needed
wim 15:b70ebfffb258 515 // switch cursor for LCD40x4 if needed
wim 15:b70ebfffb258 516 // set the new memory address to show cursor at correct location
wim 15:b70ebfffb258 517 setAddress(column, row);
wim 15:b70ebfffb258 518
wim 15:b70ebfffb258 519 }
wim 15:b70ebfffb258 520
wim 15:b70ebfffb258 521
wim 21:9eb628d9e164 522 /** Write a single character (Stream implementation)
wim 21:9eb628d9e164 523 */
wim 21:9eb628d9e164 524 int TextLCD_Base::_putc(int value) {
wim 15:b70ebfffb258 525 int addr;
wim 15:b70ebfffb258 526
wim 15:b70ebfffb258 527 if (value == '\n') {
wim 15:b70ebfffb258 528 //No character to write
wim 15:b70ebfffb258 529
wim 15:b70ebfffb258 530 //Update Cursor
wim 15:b70ebfffb258 531 _column = 0;
wim 15:b70ebfffb258 532 _row++;
wim 15:b70ebfffb258 533 if (_row >= rows()) {
wim 15:b70ebfffb258 534 _row = 0;
wim 15:b70ebfffb258 535 }
wim 15:b70ebfffb258 536 }
wim 15:b70ebfffb258 537 else {
wim 15:b70ebfffb258 538 //Character to write
wim 15:b70ebfffb258 539 _writeData(value);
wim 15:b70ebfffb258 540
wim 15:b70ebfffb258 541 //Update Cursor
wim 15:b70ebfffb258 542 _column++;
wim 15:b70ebfffb258 543 if (_column >= columns()) {
wim 15:b70ebfffb258 544 _column = 0;
wim 15:b70ebfffb258 545 _row++;
wim 15:b70ebfffb258 546 if (_row >= rows()) {
wim 15:b70ebfffb258 547 _row = 0;
wim 15:b70ebfffb258 548 }
wim 15:b70ebfffb258 549 }
wim 15:b70ebfffb258 550 } //else
wim 15:b70ebfffb258 551
wim 15:b70ebfffb258 552 //Set next memoryaddress, make sure cursor blinks at next location
wim 15:b70ebfffb258 553 addr = getAddress(_column, _row);
wim 15:b70ebfffb258 554 _writeCommand(0x80 | addr);
wim 15:b70ebfffb258 555
wim 15:b70ebfffb258 556 return value;
wim 15:b70ebfffb258 557 }
wim 15:b70ebfffb258 558
wim 15:b70ebfffb258 559
wim 16:c276b75e6585 560 // get a single character (Stream implementation)
wim 21:9eb628d9e164 561 int TextLCD_Base::_getc() {
simon 1:ac48b187213c 562 return -1;
simon 1:ac48b187213c 563 }
simon 1:ac48b187213c 564
wim 14:0c32b66b14b8 565
wim 17:652ab113bc2e 566 // Write a nibble using the 4-bit interface
wim 21:9eb628d9e164 567 void TextLCD_Base::_writeNibble(int value) {
wim 17:652ab113bc2e 568
wim 17:652ab113bc2e 569 // Enable is Low
wim 21:9eb628d9e164 570 this->_setEnable(true);
wim 21:9eb628d9e164 571 this->_setData(value & 0x0F); // Low nibble
wim 17:652ab113bc2e 572 wait_us(1); // Data setup time
wim 21:9eb628d9e164 573 this->_setEnable(false);
wim 17:652ab113bc2e 574 wait_us(1); // Datahold time
wim 17:652ab113bc2e 575
wim 17:652ab113bc2e 576 // Enable is Low
wim 17:652ab113bc2e 577
wim 17:652ab113bc2e 578 }
wim 17:652ab113bc2e 579
wim 17:652ab113bc2e 580
wim 16:c276b75e6585 581 // Write a byte using the 4-bit interface
wim 21:9eb628d9e164 582 void TextLCD_Base::_writeByte(int value) {
wim 15:b70ebfffb258 583
wim 15:b70ebfffb258 584 // Enable is Low
wim 21:9eb628d9e164 585 this->_setEnable(true);
wim 21:9eb628d9e164 586 this->_setData(value >> 4); // High nibble
wim 15:b70ebfffb258 587 wait_us(1); // Data setup time
wim 21:9eb628d9e164 588 this->_setEnable(false);
wim 15:b70ebfffb258 589 wait_us(1); // Data hold time
wim 15:b70ebfffb258 590
wim 21:9eb628d9e164 591 this->_setEnable(true);
wim 21:9eb628d9e164 592 this->_setData(value >> 0); // Low nibble
wim 15:b70ebfffb258 593 wait_us(1); // Data setup time
wim 21:9eb628d9e164 594 this->_setEnable(false);
wim 15:b70ebfffb258 595 wait_us(1); // Datahold time
wim 15:b70ebfffb258 596
wim 15:b70ebfffb258 597 // Enable is Low
wim 15:b70ebfffb258 598
simon 1:ac48b187213c 599 }
simon 1:ac48b187213c 600
wim 21:9eb628d9e164 601 // Write a command byte to the LCD controller
wim 21:9eb628d9e164 602 void TextLCD_Base::_writeCommand(int command) {
wim 15:b70ebfffb258 603
wim 21:9eb628d9e164 604 this->_setRS(false);
wim 16:c276b75e6585 605 wait_us(1); // Data setup time for RS
wim 15:b70ebfffb258 606
wim 21:9eb628d9e164 607 this->_writeByte(command);
wim 15:b70ebfffb258 608 wait_us(40); // most instructions take 40us
simon 1:ac48b187213c 609 }
simon 1:ac48b187213c 610
wim 21:9eb628d9e164 611 // Write a data byte to the LCD controller
wim 21:9eb628d9e164 612 void TextLCD_Base::_writeData(int data) {
wim 15:b70ebfffb258 613
wim 21:9eb628d9e164 614 this->_setRS(true);
wim 16:c276b75e6585 615 wait_us(1); // Data setup time for RS
wim 15:b70ebfffb258 616
wim 21:9eb628d9e164 617 this->_writeByte(data);
wim 15:b70ebfffb258 618 wait_us(40); // data writes take 40us
simon 1:ac48b187213c 619 }
simon 1:ac48b187213c 620
wim 8:03116f75b66e 621
wim 8:03116f75b66e 622 #if (0)
wim 16:c276b75e6585 623 // This is the original _address() method.
wim 8:03116f75b66e 624 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
wim 8:03116f75b66e 625 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 8:03116f75b66e 626 //
wim 21:9eb628d9e164 627 int TextLCD_Base::_address(int column, int row) {
simon 1:ac48b187213c 628 switch (_type) {
simon 1:ac48b187213c 629 case LCD20x4:
simon 1:ac48b187213c 630 switch (row) {
simon 1:ac48b187213c 631 case 0:
simon 1:ac48b187213c 632 return 0x80 + column;
simon 1:ac48b187213c 633 case 1:
simon 1:ac48b187213c 634 return 0xc0 + column;
simon 1:ac48b187213c 635 case 2:
simon 1:ac48b187213c 636 return 0x94 + column;
simon 1:ac48b187213c 637 case 3:
simon 1:ac48b187213c 638 return 0xd4 + column;
simon 1:ac48b187213c 639 }
simon 1:ac48b187213c 640 case LCD16x2B:
simon 4:bf5b706f8d32 641 return 0x80 + (row * 40) + column;
simon 1:ac48b187213c 642 case LCD16x2:
simon 1:ac48b187213c 643 case LCD20x2:
simon 1:ac48b187213c 644 default:
simon 4:bf5b706f8d32 645 return 0x80 + (row * 0x40) + column;
simon 1:ac48b187213c 646 }
simon 1:ac48b187213c 647 }
wim 8:03116f75b66e 648 #endif
wim 8:03116f75b66e 649
wim 8:03116f75b66e 650
wim 16:c276b75e6585 651 // This replaces the original _address() method.
wim 8:03116f75b66e 652 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
wim 21:9eb628d9e164 653 int TextLCD_Base::_address(int column, int row) {
wim 8:03116f75b66e 654 return 0x80 | getAddress(column, row);
wim 8:03116f75b66e 655 }
wim 8:03116f75b66e 656
wim 8:03116f75b66e 657 // This is new method to return the memory address based on row, column and displaytype.
wim 8:03116f75b66e 658 //
wim 29:a3663151aa65 659 /** Return the memoryaddress of screen column and row location
wim 29:a3663151aa65 660 *
wim 29:a3663151aa65 661 * @param column The horizontal position from the left, indexed from 0
wim 29:a3663151aa65 662 * @param row The vertical position from the top, indexed from 0
wim 29:a3663151aa65 663 * @param return The memoryaddress of screen column and row location
wim 29:a3663151aa65 664 */
wim 21:9eb628d9e164 665 int TextLCD_Base::getAddress(int column, int row) {
wim 8:03116f75b66e 666
wim 8:03116f75b66e 667 switch (_type) {
wim 8:03116f75b66e 668 case LCD8x1:
wim 29:a3663151aa65 669 case LCD24x1:
wim 8:03116f75b66e 670 return 0x00 + column;
wim 18:bd65dc10f27f 671
wim 29:a3663151aa65 672 case LCD16x1:
wim 29:a3663151aa65 673 // LCD16x1 is a special layout of LCD8x2
wim 29:a3663151aa65 674 if (column<8)
wim 29:a3663151aa65 675 return 0x00 + column;
wim 29:a3663151aa65 676 else
wim 29:a3663151aa65 677 return 0x40 + (column - 8);
wim 29:a3663151aa65 678
wim 18:bd65dc10f27f 679 case LCD8x2B:
wim 18:bd65dc10f27f 680 // LCD8x2B is a special layout of LCD16x1
wim 18:bd65dc10f27f 681 if (row==0)
wim 18:bd65dc10f27f 682 return 0x00 + column;
wim 18:bd65dc10f27f 683 else
wim 18:bd65dc10f27f 684 return 0x08 + column;
wim 18:bd65dc10f27f 685
wim 29:a3663151aa65 686 case LCD8x2:
wim 29:a3663151aa65 687 case LCD12x2:
wim 29:a3663151aa65 688 case LCD16x2:
wim 29:a3663151aa65 689 case LCD20x2:
wim 29:a3663151aa65 690 case LCD24x2:
wim 29:a3663151aa65 691 case LCD40x2:
wim 29:a3663151aa65 692 return 0x00 + (row * 0x40) + column;
wim 13:24506ba22480 693
wim 29:a3663151aa65 694 // Not sure about this one, seems wrong.
wim 29:a3663151aa65 695 // Left in for compatibility with original library
wim 29:a3663151aa65 696 case LCD16x2B:
wim 29:a3663151aa65 697 return 0x00 + (row * 40) + column;
wim 29:a3663151aa65 698
wim 29:a3663151aa65 699
wim 28:30fa94f7341c 700 // Special mode for ST7036
wim 28:30fa94f7341c 701 // case LCD16x3:
wim 28:30fa94f7341c 702
wim 29:a3663151aa65 703 // Special mode for PCF2116
wim 29:a3663151aa65 704 case LCD12x3B:
wim 29:a3663151aa65 705 switch (row) {
wim 29:a3663151aa65 706 case 0:
wim 29:a3663151aa65 707 return 0x20 + column;
wim 29:a3663151aa65 708 case 1:
wim 29:a3663151aa65 709 return 0x40 + column;
wim 29:a3663151aa65 710 case 2:
wim 29:a3663151aa65 711 return 0x60 + column;
wim 29:a3663151aa65 712 }
wim 29:a3663151aa65 713
wim 29:a3663151aa65 714 case LCD12x4:
wim 28:30fa94f7341c 715 switch (row) {
wim 28:30fa94f7341c 716 case 0:
wim 28:30fa94f7341c 717 return 0x00 + column;
wim 28:30fa94f7341c 718 case 1:
wim 29:a3663151aa65 719 return 0x40 + column;
wim 28:30fa94f7341c 720 case 2:
wim 29:a3663151aa65 721 return 0x0C + column;
wim 29:a3663151aa65 722 case 3:
wim 29:a3663151aa65 723 return 0x4C + column;
wim 28:30fa94f7341c 724 }
wim 28:30fa94f7341c 725
wim 28:30fa94f7341c 726 // Special mode for PCF2116 (and KS0078)
wim 28:30fa94f7341c 727 case LCD12x4B:
wim 28:30fa94f7341c 728 switch (row) {
wim 28:30fa94f7341c 729 case 0:
wim 28:30fa94f7341c 730 return 0x00 + column;
wim 28:30fa94f7341c 731 case 1:
wim 28:30fa94f7341c 732 return 0x20 + column;
wim 28:30fa94f7341c 733 case 2:
wim 28:30fa94f7341c 734 return 0x40 + column;
wim 28:30fa94f7341c 735 case 3:
wim 28:30fa94f7341c 736 return 0x60 + column;
wim 28:30fa94f7341c 737 }
wim 28:30fa94f7341c 738
wim 8:03116f75b66e 739 case LCD16x4:
wim 8:03116f75b66e 740 switch (row) {
wim 8:03116f75b66e 741 case 0:
wim 8:03116f75b66e 742 return 0x00 + column;
wim 8:03116f75b66e 743 case 1:
wim 8:03116f75b66e 744 return 0x40 + column;
wim 8:03116f75b66e 745 case 2:
wim 8:03116f75b66e 746 return 0x10 + column;
wim 8:03116f75b66e 747 case 3:
wim 8:03116f75b66e 748 return 0x50 + column;
wim 8:03116f75b66e 749 }
wim 8:03116f75b66e 750
wim 8:03116f75b66e 751 case LCD20x4:
wim 8:03116f75b66e 752 switch (row) {
wim 8:03116f75b66e 753 case 0:
wim 8:03116f75b66e 754 return 0x00 + column;
wim 8:03116f75b66e 755 case 1:
wim 8:03116f75b66e 756 return 0x40 + column;
wim 8:03116f75b66e 757 case 2:
wim 8:03116f75b66e 758 return 0x14 + column;
wim 8:03116f75b66e 759 case 3:
wim 8:03116f75b66e 760 return 0x54 + column;
wim 8:03116f75b66e 761 }
wim 8:03116f75b66e 762
wim 10:dd9b3a696acd 763 // Special mode for KS0078
wim 29:a3663151aa65 764 case LCD24x4B:
wim 10:dd9b3a696acd 765 switch (row) {
wim 10:dd9b3a696acd 766 case 0:
wim 10:dd9b3a696acd 767 return 0x00 + column;
wim 10:dd9b3a696acd 768 case 1:
wim 10:dd9b3a696acd 769 return 0x20 + column;
wim 10:dd9b3a696acd 770 case 2:
wim 10:dd9b3a696acd 771 return 0x40 + column;
wim 10:dd9b3a696acd 772 case 3:
wim 10:dd9b3a696acd 773 return 0x60 + column;
wim 10:dd9b3a696acd 774 }
wim 10:dd9b3a696acd 775
wim 15:b70ebfffb258 776 case LCD40x4:
wim 15:b70ebfffb258 777 // LCD40x4 is a special case since it has 2 controllers
wim 15:b70ebfffb258 778 // Each controller is configured as 40x2
wim 15:b70ebfffb258 779 if (row<2) {
wim 15:b70ebfffb258 780 // Test to see if we need to switch between controllers
wim 19:c747b9e2e7b8 781 if (_ctrl_idx != _LCDCtrl_0) {
wim 17:652ab113bc2e 782
wim 15:b70ebfffb258 783 // Second LCD controller Cursor Off
wim 21:9eb628d9e164 784 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 785
wim 15:b70ebfffb258 786 // Select primary controller
wim 19:c747b9e2e7b8 787 _ctrl_idx = _LCDCtrl_0;
wim 15:b70ebfffb258 788
wim 15:b70ebfffb258 789 // Restore cursormode on primary LCD controller
wim 17:652ab113bc2e 790 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 791 }
wim 15:b70ebfffb258 792
wim 15:b70ebfffb258 793 return 0x00 + (row * 0x40) + column;
wim 15:b70ebfffb258 794 }
wim 15:b70ebfffb258 795 else {
wim 15:b70ebfffb258 796
wim 15:b70ebfffb258 797 // Test to see if we need to switch between controllers
wim 19:c747b9e2e7b8 798 if (_ctrl_idx != _LCDCtrl_1) {
wim 15:b70ebfffb258 799 // Primary LCD controller Cursor Off
wim 21:9eb628d9e164 800 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 15:b70ebfffb258 801
wim 15:b70ebfffb258 802 // Select secondary controller
wim 19:c747b9e2e7b8 803 _ctrl_idx = _LCDCtrl_1;
wim 15:b70ebfffb258 804
wim 15:b70ebfffb258 805 // Restore cursormode on secondary LCD controller
wim 17:652ab113bc2e 806 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 807 }
wim 15:b70ebfffb258 808
wim 15:b70ebfffb258 809 return 0x00 + ((row-2) * 0x40) + column;
wim 15:b70ebfffb258 810 }
wim 8:03116f75b66e 811
wim 8:03116f75b66e 812 // Should never get here.
wim 8:03116f75b66e 813 default:
wim 8:03116f75b66e 814 return 0x00;
wim 8:03116f75b66e 815 }
wim 8:03116f75b66e 816 }
wim 8:03116f75b66e 817
wim 8:03116f75b66e 818
wim 29:a3663151aa65 819 /** Set the memoryaddress of screen column and row location
wim 29:a3663151aa65 820 *
wim 29:a3663151aa65 821 * @param column The horizontal position from the left, indexed from 0
wim 29:a3663151aa65 822 * @param row The vertical position from the top, indexed from 0
wim 29:a3663151aa65 823 */
wim 21:9eb628d9e164 824 void TextLCD_Base::setAddress(int column, int row) {
wim 15:b70ebfffb258 825
wim 15:b70ebfffb258 826 // Sanity Check column
wim 15:b70ebfffb258 827 if (column < 0) {
wim 15:b70ebfffb258 828 _column = 0;
wim 15:b70ebfffb258 829 }
wim 15:b70ebfffb258 830 else if (column >= columns()) {
wim 15:b70ebfffb258 831 _column = columns() - 1;
wim 15:b70ebfffb258 832 } else _column = column;
wim 8:03116f75b66e 833
wim 15:b70ebfffb258 834 // Sanity Check row
wim 15:b70ebfffb258 835 if (row < 0) {
wim 15:b70ebfffb258 836 _row = 0;
wim 15:b70ebfffb258 837 }
wim 15:b70ebfffb258 838 else if (row >= rows()) {
wim 15:b70ebfffb258 839 _row = rows() - 1;
wim 15:b70ebfffb258 840 } else _row = row;
wim 15:b70ebfffb258 841
wim 15:b70ebfffb258 842
wim 15:b70ebfffb258 843 // Compute the memory address
wim 15:b70ebfffb258 844 // For LCD40x4: switch controllers if needed
wim 15:b70ebfffb258 845 // switch cursor if needed
wim 15:b70ebfffb258 846 int addr = getAddress(_column, _row);
wim 8:03116f75b66e 847
wim 13:24506ba22480 848 _writeCommand(0x80 | addr);
wim 8:03116f75b66e 849 }
simon 1:ac48b187213c 850
wim 29:a3663151aa65 851
wim 29:a3663151aa65 852 /** Return the number of columns
wim 29:a3663151aa65 853 *
wim 29:a3663151aa65 854 * @param return The number of columns
wim 29:a3663151aa65 855 */
wim 21:9eb628d9e164 856 int TextLCD_Base::columns() {
simon 1:ac48b187213c 857 switch (_type) {
wim 8:03116f75b66e 858 case LCD8x1:
wim 8:03116f75b66e 859 case LCD8x2:
wim 18:bd65dc10f27f 860 case LCD8x2B:
wim 8:03116f75b66e 861 return 8;
wim 15:b70ebfffb258 862
wim 15:b70ebfffb258 863 case LCD12x2:
wim 29:a3663151aa65 864 case LCD12x3B:
wim 15:b70ebfffb258 865 case LCD12x4:
wim 29:a3663151aa65 866 case LCD12x4B:
wim 15:b70ebfffb258 867 return 12;
wim 8:03116f75b66e 868
wim 13:24506ba22480 869 case LCD16x1:
simon 1:ac48b187213c 870 case LCD16x2:
simon 1:ac48b187213c 871 case LCD16x2B:
wim 28:30fa94f7341c 872 // case LCD16x3:
wim 8:03116f75b66e 873 case LCD16x4:
wim 8:03116f75b66e 874 return 16;
wim 8:03116f75b66e 875
wim 8:03116f75b66e 876 case LCD20x2:
wim 8:03116f75b66e 877 case LCD20x4:
wim 8:03116f75b66e 878 return 20;
wim 8:03116f75b66e 879
wim 29:a3663151aa65 880 case LCD24x1:
wim 8:03116f75b66e 881 case LCD24x2:
wim 29:a3663151aa65 882 case LCD24x4B:
wim 8:03116f75b66e 883 return 24;
wim 9:0893d986e717 884
wim 9:0893d986e717 885 case LCD40x2:
wim 15:b70ebfffb258 886 case LCD40x4:
wim 9:0893d986e717 887 return 40;
wim 8:03116f75b66e 888
wim 8:03116f75b66e 889 // Should never get here.
simon 1:ac48b187213c 890 default:
wim 8:03116f75b66e 891 return 0;
simon 1:ac48b187213c 892 }
simon 1:ac48b187213c 893 }
simon 1:ac48b187213c 894
wim 29:a3663151aa65 895 /** Return the number of rows
wim 29:a3663151aa65 896 *
wim 29:a3663151aa65 897 * @param return The number of rows
wim 29:a3663151aa65 898 */
wim 21:9eb628d9e164 899 int TextLCD_Base::rows() {
simon 1:ac48b187213c 900 switch (_type) {
wim 8:03116f75b66e 901 case LCD8x1:
wim 13:24506ba22480 902 case LCD16x1:
wim 29:a3663151aa65 903 case LCD24x1:
wim 8:03116f75b66e 904 return 1;
wim 8:03116f75b66e 905
wim 15:b70ebfffb258 906 case LCD8x2:
wim 18:bd65dc10f27f 907 case LCD8x2B:
wim 15:b70ebfffb258 908 case LCD12x2:
simon 1:ac48b187213c 909 case LCD16x2:
simon 1:ac48b187213c 910 case LCD16x2B:
simon 1:ac48b187213c 911 case LCD20x2:
wim 8:03116f75b66e 912 case LCD24x2:
wim 9:0893d986e717 913 case LCD40x2:
wim 8:03116f75b66e 914 return 2;
wim 28:30fa94f7341c 915
wim 29:a3663151aa65 916 case LCD12x3B:
wim 28:30fa94f7341c 917 // case LCD16x3:
wim 29:a3663151aa65 918 return 3;
wim 8:03116f75b66e 919
wim 15:b70ebfffb258 920 case LCD12x4:
wim 29:a3663151aa65 921 case LCD12x4B:
wim 8:03116f75b66e 922 case LCD16x4:
wim 8:03116f75b66e 923 case LCD20x4:
wim 29:a3663151aa65 924 case LCD24x4B:
wim 15:b70ebfffb258 925 case LCD40x4:
wim 8:03116f75b66e 926 return 4;
wim 12:6bf9d9957d31 927
wim 12:6bf9d9957d31 928 // Should never get here.
simon 1:ac48b187213c 929 default:
wim 8:03116f75b66e 930 return 0;
simon 1:ac48b187213c 931 }
simon 1:ac48b187213c 932 }
wim 10:dd9b3a696acd 933
wim 29:a3663151aa65 934 /** Set the Cursormode
wim 29:a3663151aa65 935 *
wim 29:a3663151aa65 936 * @param cursorMode The Cursor mode (CurOff_BlkOff, CurOn_BlkOff, CurOff_BlkOn, CurOn_BlkOn)
wim 29:a3663151aa65 937 */
wim 21:9eb628d9e164 938 void TextLCD_Base::setCursor(LCDCursor cursorMode) {
wim 15:b70ebfffb258 939
wim 17:652ab113bc2e 940 // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on
wim 17:652ab113bc2e 941 _currentCursor = cursorMode;
wim 10:dd9b3a696acd 942
wim 17:652ab113bc2e 943 // Configure only current LCD controller
wim 17:652ab113bc2e 944 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 15:b70ebfffb258 945
wim 15:b70ebfffb258 946 }
wim 15:b70ebfffb258 947
wim 29:a3663151aa65 948 /** Set the Displaymode
wim 29:a3663151aa65 949 *
wim 29:a3663151aa65 950 * @param displayMode The Display mode (DispOff, DispOn)
wim 29:a3663151aa65 951 */
wim 21:9eb628d9e164 952 void TextLCD_Base::setMode(LCDMode displayMode) {
wim 17:652ab113bc2e 953
wim 17:652ab113bc2e 954 // Save new displayMode, needed when 2 controllers are in use or when cursor is changed
wim 17:652ab113bc2e 955 _currentMode = displayMode;
wim 15:b70ebfffb258 956
wim 17:652ab113bc2e 957 // Select and configure second LCD controller when needed
wim 17:652ab113bc2e 958 if(_type==LCD40x4) {
wim 21:9eb628d9e164 959 if (_ctrl_idx==_LCDCtrl_0) {
wim 17:652ab113bc2e 960 // Configure primary LCD controller
wim 17:652ab113bc2e 961 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 11:9ec02df863a1 962
wim 17:652ab113bc2e 963 // Select 2nd controller
wim 21:9eb628d9e164 964 _ctrl_idx=_LCDCtrl_1;
wim 17:652ab113bc2e 965
wim 17:652ab113bc2e 966 // Configure secondary LCD controller
wim 21:9eb628d9e164 967 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 11:9ec02df863a1 968
wim 17:652ab113bc2e 969 // Restore current controller
wim 21:9eb628d9e164 970 _ctrl_idx=_LCDCtrl_0;
wim 17:652ab113bc2e 971 }
wim 17:652ab113bc2e 972 else {
wim 17:652ab113bc2e 973 // Select primary controller
wim 21:9eb628d9e164 974 _ctrl_idx=_LCDCtrl_0;
wim 17:652ab113bc2e 975
wim 17:652ab113bc2e 976 // Configure primary LCD controller
wim 21:9eb628d9e164 977 _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
wim 17:652ab113bc2e 978
wim 17:652ab113bc2e 979 // Restore current controller
wim 21:9eb628d9e164 980 _ctrl_idx=_LCDCtrl_1;
wim 11:9ec02df863a1 981
wim 17:652ab113bc2e 982 // Configure secondary LCD controller
wim 17:652ab113bc2e 983 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 11:9ec02df863a1 984
wim 10:dd9b3a696acd 985 }
wim 17:652ab113bc2e 986 }
wim 17:652ab113bc2e 987 else {
wim 17:652ab113bc2e 988 // Configure primary LCD controller
wim 17:652ab113bc2e 989 _setCursorAndDisplayMode(_currentMode, _currentCursor);
wim 17:652ab113bc2e 990 }
wim 17:652ab113bc2e 991
wim 17:652ab113bc2e 992 }
wim 17:652ab113bc2e 993
wim 17:652ab113bc2e 994
wim 29:a3663151aa65 995 /** Low level method to restore the cursortype and display mode for current controller
wim 29:a3663151aa65 996 */
wim 21:9eb628d9e164 997 void TextLCD_Base::_setCursorAndDisplayMode(LCDMode displayMode, LCDCursor cursorType) {
wim 17:652ab113bc2e 998
wim 17:652ab113bc2e 999 // Configure current LCD controller
wim 17:652ab113bc2e 1000 _writeCommand(0x08 | displayMode | cursorType);
wim 10:dd9b3a696acd 1001 }
wim 10:dd9b3a696acd 1002
wim 29:a3663151aa65 1003
wim 29:a3663151aa65 1004 /** Set the Backlight mode
wim 29:a3663151aa65 1005 *
wim 29:a3663151aa65 1006 * @param backlightMode The Backlight mode (LightOff, LightOn)
wim 29:a3663151aa65 1007 */
wim 21:9eb628d9e164 1008 void TextLCD_Base::setBacklight(LCDBacklight backlightMode) {
wim 20:e0da005a777f 1009
wim 20:e0da005a777f 1010 if (backlightMode == LightOn) {
wim 21:9eb628d9e164 1011 this->_setBL(true);
wim 20:e0da005a777f 1012 }
wim 20:e0da005a777f 1013 else {
wim 21:9eb628d9e164 1014 this->_setBL(false);
wim 20:e0da005a777f 1015 }
wim 20:e0da005a777f 1016 }
wim 20:e0da005a777f 1017
wim 29:a3663151aa65 1018 /** Set User Defined Characters
wim 29:a3663151aa65 1019 *
wim 29:a3663151aa65 1020 * @param unsigned char c The Index of the UDC (0..7)
wim 29:a3663151aa65 1021 * @param char *udc_data The bitpatterns for the UDC (8 bytes of 5 significant bits)
wim 29:a3663151aa65 1022 */
wim 21:9eb628d9e164 1023 void TextLCD_Base::setUDC(unsigned char c, char *udc_data) {
wim 15:b70ebfffb258 1024
wim 15:b70ebfffb258 1025 // Select and configure second LCD controller when needed
wim 15:b70ebfffb258 1026 if(_type==LCD40x4) {
wim 19:c747b9e2e7b8 1027 _LCDCtrl_Idx current_ctrl_idx = _ctrl_idx; // Temp save current controller
wim 15:b70ebfffb258 1028
wim 15:b70ebfffb258 1029 // Select primary controller
wim 21:9eb628d9e164 1030 _ctrl_idx=_LCDCtrl_0;
wim 15:b70ebfffb258 1031
wim 15:b70ebfffb258 1032 // Configure primary LCD controller
wim 15:b70ebfffb258 1033 _setUDC(c, udc_data);
wim 15:b70ebfffb258 1034
wim 15:b70ebfffb258 1035 // Select 2nd controller
wim 21:9eb628d9e164 1036 _ctrl_idx=_LCDCtrl_1;
wim 15:b70ebfffb258 1037
wim 15:b70ebfffb258 1038 // Configure secondary LCD controller
wim 15:b70ebfffb258 1039 _setUDC(c, udc_data);
wim 11:9ec02df863a1 1040
wim 15:b70ebfffb258 1041 // Restore current controller
wim 19:c747b9e2e7b8 1042 _ctrl_idx=current_ctrl_idx;
wim 15:b70ebfffb258 1043 }
wim 15:b70ebfffb258 1044 else {
wim 15:b70ebfffb258 1045 // Configure primary LCD controller
wim 15:b70ebfffb258 1046 _setUDC(c, udc_data);
wim 15:b70ebfffb258 1047 }
wim 15:b70ebfffb258 1048
wim 15:b70ebfffb258 1049 }
wim 15:b70ebfffb258 1050
wim 29:a3663151aa65 1051 /** Low level method to store user defined characters for current controller
wim 29:a3663151aa65 1052 */
wim 21:9eb628d9e164 1053 void TextLCD_Base::_setUDC(unsigned char c, char *udc_data) {
wim 15:b70ebfffb258 1054
wim 15:b70ebfffb258 1055 // Select CG RAM for current LCD controller
wim 15:b70ebfffb258 1056 _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address,
wim 15:b70ebfffb258 1057 //8 sequential locations needed per UDC
wim 15:b70ebfffb258 1058 // Store UDC pattern
wim 11:9ec02df863a1 1059 for (int i=0; i<8; i++) {
wim 13:24506ba22480 1060 _writeData(*udc_data++);
wim 11:9ec02df863a1 1061 }
wim 15:b70ebfffb258 1062
wim 15:b70ebfffb258 1063 //Select DD RAM again for current LCD controller
wim 15:b70ebfffb258 1064 int addr = getAddress(_column, _row);
wim 15:b70ebfffb258 1065 _writeCommand(0x80 | addr);
wim 15:b70ebfffb258 1066
wim 11:9ec02df863a1 1067 }
wim 21:9eb628d9e164 1068
wim 23:d47f226efb24 1069 //--------- End TextLCD_Base -----------
wim 21:9eb628d9e164 1070
wim 22:35742ec80c24 1071
wim 21:9eb628d9e164 1072
wim 23:d47f226efb24 1073 //--------- Start TextLCD Bus -----------
wim 21:9eb628d9e164 1074
wim 21:9eb628d9e164 1075 /* Create a TextLCD interface for using regular mbed pins
wim 21:9eb628d9e164 1076 *
wim 21:9eb628d9e164 1077 * @param rs Instruction/data control line
wim 21:9eb628d9e164 1078 * @param e Enable line (clock)
wim 21:9eb628d9e164 1079 * @param d4-d7 Data lines for using as a 4-bit interface
wim 21:9eb628d9e164 1080 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 21:9eb628d9e164 1081 * @param bl Backlight control line (optional, default = NC)
wim 21:9eb628d9e164 1082 * @param e2 Enable2 line (clock for second controller, LCD40x4 only)
wim 21:9eb628d9e164 1083 * @param ctrl LCD controller (default = HD44780)
wim 21:9eb628d9e164 1084 */
wim 21:9eb628d9e164 1085 TextLCD::TextLCD(PinName rs, PinName e,
wim 21:9eb628d9e164 1086 PinName d4, PinName d5, PinName d6, PinName d7,
wim 21:9eb628d9e164 1087 LCDType type, PinName bl, PinName e2, LCDCtrl ctrl) :
wim 21:9eb628d9e164 1088 TextLCD_Base(type, ctrl),
wim 22:35742ec80c24 1089 _rs(rs), _e(e), _d(d4, d5, d6, d7) {
wim 22:35742ec80c24 1090
wim 22:35742ec80c24 1091 // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
wim 22:35742ec80c24 1092 if (bl != NC) {
wim 22:35742ec80c24 1093 _bl = new DigitalOut(bl); //Construct new pin
wim 22:35742ec80c24 1094 _bl->write(0); //Deactivate
wim 22:35742ec80c24 1095 }
wim 22:35742ec80c24 1096 else {
wim 22:35742ec80c24 1097 // No Hardware Backlight pin
wim 22:35742ec80c24 1098 _bl = NULL; //Construct dummy pin
wim 22:35742ec80c24 1099 }
wim 22:35742ec80c24 1100
wim 22:35742ec80c24 1101 // 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 1102 if (e2 != NC) {
wim 22:35742ec80c24 1103 _e2 = new DigitalOut(e2); //Construct new pin
wim 22:35742ec80c24 1104 _e2->write(0); //Deactivate
wim 22:35742ec80c24 1105 }
wim 22:35742ec80c24 1106 else {
wim 22:35742ec80c24 1107 // No Hardware Enable pin
wim 22:35742ec80c24 1108 _e2 = NULL; //Construct dummy pin
wim 22:35742ec80c24 1109 }
wim 21:9eb628d9e164 1110
wim 21:9eb628d9e164 1111 _init();
wim 21:9eb628d9e164 1112
wim 21:9eb628d9e164 1113 }
wim 21:9eb628d9e164 1114
wim 29:a3663151aa65 1115
wim 29:a3663151aa65 1116 /** Destruct a TextLCD interface for using regular mbed pins
wim 29:a3663151aa65 1117 *
wim 29:a3663151aa65 1118 * @param none
wim 29:a3663151aa65 1119 * @return none
wim 29:a3663151aa65 1120 */
wim 29:a3663151aa65 1121 TextLCD::~TextLCD() {
wim 29:a3663151aa65 1122 if (_bl != NULL) {delete _bl;} // BL pin
wim 29:a3663151aa65 1123 if (_e2 != NULL) {delete _e2;} // E2 pin
wim 29:a3663151aa65 1124 }
wim 29:a3663151aa65 1125
wim 29:a3663151aa65 1126
wim 22:35742ec80c24 1127 /** Set E pin (or E2 pin)
wim 22:35742ec80c24 1128 * Used for mbed pins, I2C bus expander or SPI shiftregister
wim 22:35742ec80c24 1129 * Default PinName value for E2 is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
wim 22:35742ec80c24 1130 * @param value true or false
wim 22:35742ec80c24 1131 * @return none
wim 22:35742ec80c24 1132 */
wim 21:9eb628d9e164 1133 void TextLCD::_setEnable(bool value) {
wim 21:9eb628d9e164 1134
wim 22:35742ec80c24 1135 if(_ctrl_idx==_LCDCtrl_0) {
wim 22:35742ec80c24 1136 if (value) {
wim 22:35742ec80c24 1137 _e = 1; // Set E bit
wim 22:35742ec80c24 1138 }
wim 22:35742ec80c24 1139 else {
wim 22:35742ec80c24 1140 _e = 0; // Reset E bit
wim 22:35742ec80c24 1141 }
wim 22:35742ec80c24 1142 }
wim 22:35742ec80c24 1143 else {
wim 22:35742ec80c24 1144 if (value) {
wim 22:35742ec80c24 1145 if (_e2 != NULL) {_e2->write(1);} //Set E2 bit
wim 22:35742ec80c24 1146 }
wim 22:35742ec80c24 1147 else {
wim 22:35742ec80c24 1148 if (_e2 != NULL) {_e2->write(0);} //Reset E2 bit
wim 22:35742ec80c24 1149 }
wim 22:35742ec80c24 1150 }
wim 21:9eb628d9e164 1151
wim 21:9eb628d9e164 1152 }
wim 21:9eb628d9e164 1153
wim 21:9eb628d9e164 1154 // Set RS pin
wim 21:9eb628d9e164 1155 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1156 void TextLCD::_setRS(bool value) {
wim 21:9eb628d9e164 1157
wim 22:35742ec80c24 1158 if (value) {
wim 21:9eb628d9e164 1159 _rs = 1; // Set RS bit
wim 22:35742ec80c24 1160 }
wim 22:35742ec80c24 1161 else {
wim 21:9eb628d9e164 1162 _rs = 0; // Reset RS bit
wim 22:35742ec80c24 1163 }
wim 21:9eb628d9e164 1164
wim 21:9eb628d9e164 1165 }
wim 21:9eb628d9e164 1166
wim 22:35742ec80c24 1167 /** Set BL pin
wim 22:35742ec80c24 1168 * Used for mbed pins, I2C bus expander or SPI shiftregister
wim 22:35742ec80c24 1169 * Default PinName value is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
wim 22:35742ec80c24 1170 * @param value true or false
wim 22:35742ec80c24 1171 * @return none
wim 22:35742ec80c24 1172 */
wim 21:9eb628d9e164 1173 void TextLCD::_setBL(bool value) {
wim 21:9eb628d9e164 1174
wim 22:35742ec80c24 1175 if (value) {
wim 22:35742ec80c24 1176 if (_bl != NULL) {_bl->write(1);} //Set BL bit
wim 22:35742ec80c24 1177 }
wim 22:35742ec80c24 1178 else {
wim 22:35742ec80c24 1179 if (_bl != NULL) {_bl->write(0);} //Reset BL bit
wim 22:35742ec80c24 1180 }
wim 21:9eb628d9e164 1181
wim 21:9eb628d9e164 1182 }
wim 21:9eb628d9e164 1183
wim 21:9eb628d9e164 1184 // Place the 4bit data on the databus
wim 21:9eb628d9e164 1185 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 21:9eb628d9e164 1186 void TextLCD::_setData(int value) {
wim 21:9eb628d9e164 1187 _d = value & 0x0F; // Write Databits
wim 21:9eb628d9e164 1188 }
wim 21:9eb628d9e164 1189
wim 22:35742ec80c24 1190
wim 23:d47f226efb24 1191 //----------- End TextLCD ---------------
wim 21:9eb628d9e164 1192
wim 21:9eb628d9e164 1193
wim 23:d47f226efb24 1194 //--------- Start TextLCD_I2C -----------
wim 22:35742ec80c24 1195
wim 26:bd897a001012 1196 /** Create a TextLCD interface using an I2C PC8574 (or PCF8574A) or MCP23008 portexpander
wim 22:35742ec80c24 1197 *
wim 22:35742ec80c24 1198 * @param i2c I2C Bus
wim 26:bd897a001012 1199 * @param deviceAddress I2C slave address (PCF8574, PCF8574A or MCP23008, default = 0x40)
wim 22:35742ec80c24 1200 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 22:35742ec80c24 1201 * @param ctrl LCD controller (default = HD44780)
wim 22:35742ec80c24 1202 */
wim 21:9eb628d9e164 1203 TextLCD_I2C::TextLCD_I2C(I2C *i2c, char deviceAddress, LCDType type, LCDCtrl ctrl) :
wim 21:9eb628d9e164 1204 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 1205 _i2c(i2c){
wim 21:9eb628d9e164 1206
wim 22:35742ec80c24 1207 _slaveAddress = deviceAddress & 0xFE;
wim 28:30fa94f7341c 1208
wim 28:30fa94f7341c 1209
wim 28:30fa94f7341c 1210 // Setup the I2C bus
wim 28:30fa94f7341c 1211 // The max bitrate for PCF8574 is 100kbit, the max bitrate for MCP23008 is 400kbit,
wim 28:30fa94f7341c 1212 // _i2c->frequency(100000);
wim 21:9eb628d9e164 1213
wim 26:bd897a001012 1214
wim 26:bd897a001012 1215 #if (MCP23008==1)
wim 26:bd897a001012 1216 // MCP23008 portexpander Init
wim 27:22d5086f6ba6 1217 _write_register(IODIR, 0x00); // All outputs
wim 27:22d5086f6ba6 1218 _write_register(IPOL, 0x00); // No reverse polarity
wim 27:22d5086f6ba6 1219 _write_register(GPINTEN, 0x00); // No interrupt
wim 27:22d5086f6ba6 1220 _write_register(DEFVAL, 0x00); // Default value to compare against for interrupts
wim 27:22d5086f6ba6 1221 _write_register(INTCON, 0x00); // No interrupt on changes
wim 27:22d5086f6ba6 1222 _write_register(IOCON, 0x00); // Interrupt polarity
wim 27:22d5086f6ba6 1223 _write_register(GPPU, 0x00); // No Pullup
wim 27:22d5086f6ba6 1224 _write_register(INTF, 0x00); //
wim 27:22d5086f6ba6 1225 _write_register(INTCAP, 0x00); //
wim 27:22d5086f6ba6 1226 _write_register(GPIO, 0x00); // Output/Input pins
wim 27:22d5086f6ba6 1227 _write_register(OLAT, 0x00); // Output Latch
wim 26:bd897a001012 1228
wim 21:9eb628d9e164 1229 // Init the portexpander bus
wim 21:9eb628d9e164 1230 _lcd_bus = D_LCD_BUS_DEF;
wim 21:9eb628d9e164 1231
wim 21:9eb628d9e164 1232 // write the new data to the portexpander
wim 26:bd897a001012 1233 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 1234 #else
wim 26:bd897a001012 1235 // PCF8574 of PCF8574A portexpander
wim 26:bd897a001012 1236
wim 26:bd897a001012 1237 // Init the portexpander bus
wim 26:bd897a001012 1238 _lcd_bus = D_LCD_BUS_DEF;
wim 26:bd897a001012 1239
wim 26:bd897a001012 1240 // write the new data to the portexpander
wim 21:9eb628d9e164 1241 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 1242 #endif
wim 21:9eb628d9e164 1243
wim 21:9eb628d9e164 1244 _init();
wim 21:9eb628d9e164 1245
wim 21:9eb628d9e164 1246 }
wim 21:9eb628d9e164 1247
wim 21:9eb628d9e164 1248 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 1249 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1250 void TextLCD_I2C::_setEnable(bool value) {
wim 21:9eb628d9e164 1251
wim 22:35742ec80c24 1252 if(_ctrl_idx==_LCDCtrl_0) {
wim 26:bd897a001012 1253 if (value) {
wim 22:35742ec80c24 1254 _lcd_bus |= D_LCD_E; // Set E bit
wim 26:bd897a001012 1255 }
wim 26:bd897a001012 1256 else {
wim 22:35742ec80c24 1257 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 26:bd897a001012 1258 }
wim 22:35742ec80c24 1259 }
wim 22:35742ec80c24 1260 else {
wim 26:bd897a001012 1261 if (value) {
wim 22:35742ec80c24 1262 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 26:bd897a001012 1263 }
wim 26:bd897a001012 1264 else {
wim 22:35742ec80c24 1265 _lcd_bus &= ~D_LCD_E2; // Reset E2bit
wim 26:bd897a001012 1266 }
wim 26:bd897a001012 1267 }
wim 26:bd897a001012 1268
wim 26:bd897a001012 1269
wim 26:bd897a001012 1270 #if (MCP23008==1)
wim 26:bd897a001012 1271 // MCP23008 portexpander
wim 26:bd897a001012 1272
wim 26:bd897a001012 1273 // write the new data to the portexpander
wim 26:bd897a001012 1274 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 1275 #else
wim 26:bd897a001012 1276 // PCF8574 of PCF8574A portexpander
wim 21:9eb628d9e164 1277
wim 22:35742ec80c24 1278 // write the new data to the I2C portexpander
wim 22:35742ec80c24 1279 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 1280 #endif
wim 21:9eb628d9e164 1281 }
wim 21:9eb628d9e164 1282
wim 21:9eb628d9e164 1283 // Set RS pin
wim 21:9eb628d9e164 1284 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1285 void TextLCD_I2C::_setRS(bool value) {
wim 21:9eb628d9e164 1286
wim 26:bd897a001012 1287 if (value) {
wim 22:35742ec80c24 1288 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 26:bd897a001012 1289 }
wim 26:bd897a001012 1290 else {
wim 22:35742ec80c24 1291 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 26:bd897a001012 1292 }
wim 26:bd897a001012 1293
wim 26:bd897a001012 1294
wim 26:bd897a001012 1295 #if (MCP23008==1)
wim 26:bd897a001012 1296 // MCP23008 portexpander
wim 26:bd897a001012 1297
wim 26:bd897a001012 1298 // write the new data to the portexpander
wim 26:bd897a001012 1299 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 1300 #else
wim 26:bd897a001012 1301 // PCF8574 of PCF8574A portexpander
wim 21:9eb628d9e164 1302
wim 22:35742ec80c24 1303 // write the new data to the I2C portexpander
wim 22:35742ec80c24 1304 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 1305 #endif
wim 21:9eb628d9e164 1306
wim 21:9eb628d9e164 1307 }
wim 21:9eb628d9e164 1308
wim 21:9eb628d9e164 1309 // Set BL pin
wim 21:9eb628d9e164 1310 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1311 void TextLCD_I2C::_setBL(bool value) {
wim 21:9eb628d9e164 1312
wim 26:bd897a001012 1313 if (value) {
wim 21:9eb628d9e164 1314 _lcd_bus |= D_LCD_BL; // Set BL bit
wim 26:bd897a001012 1315 }
wim 26:bd897a001012 1316 else {
wim 21:9eb628d9e164 1317 _lcd_bus &= ~D_LCD_BL; // Reset BL bit
wim 26:bd897a001012 1318 }
wim 26:bd897a001012 1319
wim 26:bd897a001012 1320 #if (MCP23008==1)
wim 26:bd897a001012 1321 // MCP23008 portexpander
wim 26:bd897a001012 1322
wim 26:bd897a001012 1323 // write the new data to the portexpander
wim 26:bd897a001012 1324 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 1325 #else
wim 26:bd897a001012 1326 // PCF8574 of PCF8574A portexpander
wim 21:9eb628d9e164 1327
wim 21:9eb628d9e164 1328 // write the new data to the I2C portexpander
wim 21:9eb628d9e164 1329 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 1330 #endif
wim 21:9eb628d9e164 1331
wim 21:9eb628d9e164 1332 }
wim 21:9eb628d9e164 1333
wim 21:9eb628d9e164 1334
wim 21:9eb628d9e164 1335
wim 21:9eb628d9e164 1336 // Place the 4bit data on the databus
wim 21:9eb628d9e164 1337 // Used for mbed pins, I2C bus expander or SPI shifregister
wim 21:9eb628d9e164 1338 void TextLCD_I2C::_setData(int value) {
wim 21:9eb628d9e164 1339 int data;
wim 22:35742ec80c24 1340
wim 22:35742ec80c24 1341 // Set bit by bit to support any mapping of expander portpins to LCD pins
wim 21:9eb628d9e164 1342
wim 22:35742ec80c24 1343 data = value & 0x0F;
wim 26:bd897a001012 1344 if (data & 0x01){
wim 22:35742ec80c24 1345 _lcd_bus |= D_LCD_D4; // Set Databit
wim 26:bd897a001012 1346 }
wim 26:bd897a001012 1347 else {
wim 26:bd897a001012 1348 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 26:bd897a001012 1349 }
wim 21:9eb628d9e164 1350
wim 26:bd897a001012 1351 if (data & 0x02){
wim 22:35742ec80c24 1352 _lcd_bus |= D_LCD_D5; // Set Databit
wim 26:bd897a001012 1353 }
wim 26:bd897a001012 1354 else {
wim 26:bd897a001012 1355 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 26:bd897a001012 1356 }
wim 21:9eb628d9e164 1357
wim 26:bd897a001012 1358 if (data & 0x04) {
wim 22:35742ec80c24 1359 _lcd_bus |= D_LCD_D6; // Set Databit
wim 26:bd897a001012 1360 }
wim 26:bd897a001012 1361 else {
wim 26:bd897a001012 1362 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 26:bd897a001012 1363 }
wim 21:9eb628d9e164 1364
wim 26:bd897a001012 1365 if (data & 0x08) {
wim 22:35742ec80c24 1366 _lcd_bus |= D_LCD_D7; // Set Databit
wim 26:bd897a001012 1367 }
wim 26:bd897a001012 1368 else {
wim 26:bd897a001012 1369 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 26:bd897a001012 1370 }
wim 21:9eb628d9e164 1371
wim 26:bd897a001012 1372 #if (MCP23008==1)
wim 26:bd897a001012 1373 // MCP23008 portexpander
wim 26:bd897a001012 1374
wim 26:bd897a001012 1375 // write the new data to the portexpander
wim 26:bd897a001012 1376 _write_register(GPIO, _lcd_bus);
wim 26:bd897a001012 1377 #else
wim 26:bd897a001012 1378 // PCF8574 of PCF8574A portexpander
wim 26:bd897a001012 1379
wim 22:35742ec80c24 1380 // write the new data to the I2C portexpander
wim 26:bd897a001012 1381 _i2c->write(_slaveAddress, &_lcd_bus, 1);
wim 26:bd897a001012 1382 #endif
wim 22:35742ec80c24 1383
wim 22:35742ec80c24 1384 }
wim 21:9eb628d9e164 1385
wim 26:bd897a001012 1386 // Write data to MCP23008 I2C portexpander
wim 26:bd897a001012 1387 void TextLCD_I2C::_write_register (int reg, int value) {
wim 26:bd897a001012 1388 char data[] = {reg, value};
wim 26:bd897a001012 1389
wim 26:bd897a001012 1390 _i2c->write(_slaveAddress, data, 2);
wim 26:bd897a001012 1391
wim 26:bd897a001012 1392 }
wim 26:bd897a001012 1393
wim 23:d47f226efb24 1394 //---------- End TextLCD_I2C ------------
wim 21:9eb628d9e164 1395
wim 21:9eb628d9e164 1396
wim 28:30fa94f7341c 1397 //--------- Start TextLCD_I2C_N ---------
wim 28:30fa94f7341c 1398
wim 28:30fa94f7341c 1399 /** Create a TextLCD interface using a controller with native I2C interface
wim 28:30fa94f7341c 1400 *
wim 28:30fa94f7341c 1401 * @param i2c I2C Bus
wim 28:30fa94f7341c 1402 * @param deviceAddress I2C slave address (default = 0x7C)
wim 28:30fa94f7341c 1403 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 28:30fa94f7341c 1404 * @param bl Backlight control line (optional, default = NC)
wim 28:30fa94f7341c 1405 * @param ctrl LCD controller (default = ST7032_3V3)
wim 28:30fa94f7341c 1406 */
wim 28:30fa94f7341c 1407 TextLCD_I2C_N::TextLCD_I2C_N(I2C *i2c, char deviceAddress, LCDType type, PinName bl, LCDCtrl ctrl) :
wim 28:30fa94f7341c 1408 TextLCD_Base(type, ctrl),
wim 28:30fa94f7341c 1409 _i2c(i2c){
wim 28:30fa94f7341c 1410
wim 28:30fa94f7341c 1411 _slaveAddress = deviceAddress & 0xFE;
wim 28:30fa94f7341c 1412
wim 28:30fa94f7341c 1413 // Setup the I2C bus
wim 29:a3663151aa65 1414 // The max bitrate for ST7032i is 400kbit, lets stick to default here
wim 29:a3663151aa65 1415 _i2c->frequency(100000);
wim 29:a3663151aa65 1416 // _i2c->frequency(50000);
wim 28:30fa94f7341c 1417
wim 28:30fa94f7341c 1418
wim 28:30fa94f7341c 1419 // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
wim 28:30fa94f7341c 1420 if (bl != NC) {
wim 28:30fa94f7341c 1421 _bl = new DigitalOut(bl); //Construct new pin
wim 28:30fa94f7341c 1422 _bl->write(0); //Deactivate
wim 28:30fa94f7341c 1423 }
wim 28:30fa94f7341c 1424 else {
wim 28:30fa94f7341c 1425 // No Hardware Backlight pin
wim 28:30fa94f7341c 1426 _bl = NULL; //Construct dummy pin
wim 28:30fa94f7341c 1427 }
wim 28:30fa94f7341c 1428
wim 28:30fa94f7341c 1429 _init();
wim 28:30fa94f7341c 1430 }
wim 28:30fa94f7341c 1431
wim 28:30fa94f7341c 1432 TextLCD_I2C_N::~TextLCD_I2C_N() {
wim 28:30fa94f7341c 1433 if (_bl != NULL) {delete _bl;} // BL pin
wim 28:30fa94f7341c 1434 }
wim 28:30fa94f7341c 1435
wim 28:30fa94f7341c 1436 // Not used in this mode
wim 28:30fa94f7341c 1437 void TextLCD_I2C_N::_setEnable(bool value) {
wim 28:30fa94f7341c 1438 }
wim 28:30fa94f7341c 1439
wim 28:30fa94f7341c 1440 // Set RS pin
wim 28:30fa94f7341c 1441 // Used for mbed pins, I2C bus expander or SPI shiftregister and native I2C or SPI
wim 28:30fa94f7341c 1442 void TextLCD_I2C_N::_setRS(bool value) {
wim 28:30fa94f7341c 1443
wim 28:30fa94f7341c 1444 if (value) {
wim 28:30fa94f7341c 1445 _controlbyte = 0x40; // Next byte is data, No more control bytes will follow
wim 28:30fa94f7341c 1446 }
wim 28:30fa94f7341c 1447 else {
wim 28:30fa94f7341c 1448 _controlbyte = 0x00; // Next byte is command, No more control bytes will follow
wim 28:30fa94f7341c 1449 }
wim 28:30fa94f7341c 1450 }
wim 28:30fa94f7341c 1451
wim 28:30fa94f7341c 1452 // Set BL pin
wim 28:30fa94f7341c 1453 void TextLCD_I2C_N::_setBL(bool value) {
wim 28:30fa94f7341c 1454 if (_bl) {
wim 28:30fa94f7341c 1455 _bl->write(value);
wim 28:30fa94f7341c 1456 }
wim 28:30fa94f7341c 1457 }
wim 28:30fa94f7341c 1458
wim 29:a3663151aa65 1459
wim 29:a3663151aa65 1460 // Not used in this mode
wim 29:a3663151aa65 1461 void TextLCD_I2C_N::_setData(int value) {
wim 29:a3663151aa65 1462 }
wim 29:a3663151aa65 1463
wim 29:a3663151aa65 1464
wim 28:30fa94f7341c 1465 // Write a byte using I2C
wim 28:30fa94f7341c 1466 void TextLCD_I2C_N::_writeByte(int value) {
wim 28:30fa94f7341c 1467
wim 28:30fa94f7341c 1468 char data[] = {_controlbyte, value};
wim 28:30fa94f7341c 1469
wim 28:30fa94f7341c 1470 _i2c->write(_slaveAddress, data, 2);
wim 28:30fa94f7341c 1471
wim 28:30fa94f7341c 1472 }
wim 28:30fa94f7341c 1473
wim 28:30fa94f7341c 1474
wim 28:30fa94f7341c 1475 //-------- End TextLCD_I2C_N ------------
wim 28:30fa94f7341c 1476
wim 28:30fa94f7341c 1477
wim 28:30fa94f7341c 1478
wim 21:9eb628d9e164 1479
wim 23:d47f226efb24 1480 //--------- Start TextLCD_SPI -----------
wim 21:9eb628d9e164 1481
wim 22:35742ec80c24 1482 /** Create a TextLCD interface using an SPI 74595 portexpander
wim 22:35742ec80c24 1483 *
wim 22:35742ec80c24 1484 * @param spi SPI Bus
wim 22:35742ec80c24 1485 * @param cs chip select pin (active low)
wim 22:35742ec80c24 1486 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 22:35742ec80c24 1487 * @param ctrl LCD controller (default = HD44780)
wim 22:35742ec80c24 1488 */
wim 21:9eb628d9e164 1489 TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) :
wim 21:9eb628d9e164 1490 TextLCD_Base(type, ctrl),
wim 21:9eb628d9e164 1491 _spi(spi),
wim 21:9eb628d9e164 1492 _cs(cs) {
wim 21:9eb628d9e164 1493
wim 21:9eb628d9e164 1494 // Setup the spi for 8 bit data, low steady state clock,
wim 21:9eb628d9e164 1495 // rising edge capture, with a 500KHz or 1MHz clock rate
wim 21:9eb628d9e164 1496 _spi->format(8,0);
wim 21:9eb628d9e164 1497 _spi->frequency(500000);
wim 21:9eb628d9e164 1498 //_spi.frequency(1000000);
wim 21:9eb628d9e164 1499
wim 21:9eb628d9e164 1500
wim 21:9eb628d9e164 1501 // Init the portexpander bus
wim 21:9eb628d9e164 1502 _lcd_bus = D_LCD_BUS_DEF;
wim 21:9eb628d9e164 1503
wim 21:9eb628d9e164 1504 // write the new data to the portexpander
wim 21:9eb628d9e164 1505 _setCS(false);
wim 21:9eb628d9e164 1506 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1507 _setCS(true);
wim 21:9eb628d9e164 1508
wim 21:9eb628d9e164 1509 _init();
wim 21:9eb628d9e164 1510
wim 21:9eb628d9e164 1511 }
wim 21:9eb628d9e164 1512
wim 21:9eb628d9e164 1513 // Set E pin (or E2 pin)
wim 21:9eb628d9e164 1514 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1515 void TextLCD_SPI::_setEnable(bool value) {
wim 21:9eb628d9e164 1516
wim 22:35742ec80c24 1517 if(_ctrl_idx==_LCDCtrl_0) {
wim 26:bd897a001012 1518 if (value) {
wim 22:35742ec80c24 1519 _lcd_bus |= D_LCD_E; // Set E bit
wim 26:bd897a001012 1520 }
wim 26:bd897a001012 1521 else {
wim 22:35742ec80c24 1522 _lcd_bus &= ~D_LCD_E; // Reset E bit
wim 26:bd897a001012 1523 }
wim 22:35742ec80c24 1524 }
wim 22:35742ec80c24 1525 else {
wim 26:bd897a001012 1526 if (value) {
wim 22:35742ec80c24 1527 _lcd_bus |= D_LCD_E2; // Set E2 bit
wim 26:bd897a001012 1528 }
wim 26:bd897a001012 1529 else {
wim 22:35742ec80c24 1530 _lcd_bus &= ~D_LCD_E2; // Reset E2 bit
wim 26:bd897a001012 1531 }
wim 22:35742ec80c24 1532 }
wim 21:9eb628d9e164 1533
wim 22:35742ec80c24 1534 // write the new data to the SPI portexpander
wim 22:35742ec80c24 1535 _setCS(false);
wim 22:35742ec80c24 1536 _spi->write(_lcd_bus);
wim 22:35742ec80c24 1537 _setCS(true);
wim 21:9eb628d9e164 1538
wim 21:9eb628d9e164 1539 }
wim 21:9eb628d9e164 1540
wim 21:9eb628d9e164 1541 // Set RS pin
wim 21:9eb628d9e164 1542 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1543 void TextLCD_SPI::_setRS(bool value) {
wim 21:9eb628d9e164 1544
wim 22:35742ec80c24 1545 if (value) {
wim 21:9eb628d9e164 1546 _lcd_bus |= D_LCD_RS; // Set RS bit
wim 22:35742ec80c24 1547 }
wim 22:35742ec80c24 1548 else {
wim 21:9eb628d9e164 1549 _lcd_bus &= ~D_LCD_RS; // Reset RS bit
wim 22:35742ec80c24 1550 }
wim 21:9eb628d9e164 1551
wim 21:9eb628d9e164 1552 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 1553 _setCS(false);
wim 21:9eb628d9e164 1554 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1555 _setCS(true);
wim 21:9eb628d9e164 1556
wim 21:9eb628d9e164 1557 }
wim 21:9eb628d9e164 1558
wim 21:9eb628d9e164 1559 // Set BL pin
wim 21:9eb628d9e164 1560 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1561 void TextLCD_SPI::_setBL(bool value) {
wim 21:9eb628d9e164 1562
wim 22:35742ec80c24 1563 if (value) {
wim 21:9eb628d9e164 1564 _lcd_bus |= D_LCD_BL; // Set BL bit
wim 22:35742ec80c24 1565 }
wim 22:35742ec80c24 1566 else {
wim 21:9eb628d9e164 1567 _lcd_bus &= ~D_LCD_BL; // Reset BL bit
wim 22:35742ec80c24 1568 }
wim 21:9eb628d9e164 1569
wim 21:9eb628d9e164 1570 // write the new data to the SPI portexpander
wim 21:9eb628d9e164 1571 _setCS(false);
wim 21:9eb628d9e164 1572 _spi->write(_lcd_bus);
wim 21:9eb628d9e164 1573 _setCS(true);
wim 21:9eb628d9e164 1574
wim 21:9eb628d9e164 1575 }
wim 21:9eb628d9e164 1576
wim 21:9eb628d9e164 1577
wim 21:9eb628d9e164 1578 // Place the 4bit data on the databus
wim 21:9eb628d9e164 1579 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 21:9eb628d9e164 1580 void TextLCD_SPI::_setData(int value) {
wim 21:9eb628d9e164 1581 int data;
wim 21:9eb628d9e164 1582
wim 22:35742ec80c24 1583 // Set bit by bit to support any mapping of expander portpins to LCD pins
wim 22:35742ec80c24 1584
wim 22:35742ec80c24 1585 data = value & 0x0F;
wim 26:bd897a001012 1586 if (data & 0x01) {
wim 22:35742ec80c24 1587 _lcd_bus |= D_LCD_D4; // Set Databit
wim 26:bd897a001012 1588 }
wim 26:bd897a001012 1589 else {
wim 22:35742ec80c24 1590 _lcd_bus &= ~D_LCD_D4; // Reset Databit
wim 26:bd897a001012 1591 }
wim 26:bd897a001012 1592
wim 26:bd897a001012 1593 if (data & 0x02) {
wim 22:35742ec80c24 1594 _lcd_bus |= D_LCD_D5; // Set Databit
wim 26:bd897a001012 1595 }
wim 26:bd897a001012 1596 else {
wim 22:35742ec80c24 1597 _lcd_bus &= ~D_LCD_D5; // Reset Databit
wim 26:bd897a001012 1598 }
wim 26:bd897a001012 1599
wim 26:bd897a001012 1600 if (data & 0x04) {
wim 22:35742ec80c24 1601 _lcd_bus |= D_LCD_D6; // Set Databit
wim 26:bd897a001012 1602 }
wim 26:bd897a001012 1603 else {
wim 22:35742ec80c24 1604 _lcd_bus &= ~D_LCD_D6; // Reset Databit
wim 26:bd897a001012 1605 }
wim 26:bd897a001012 1606
wim 26:bd897a001012 1607 if (data & 0x08) {
wim 22:35742ec80c24 1608 _lcd_bus |= D_LCD_D7; // Set Databit
wim 26:bd897a001012 1609 }
wim 26:bd897a001012 1610 else {
wim 26:bd897a001012 1611 _lcd_bus &= ~D_LCD_D7; // Reset Databit
wim 26:bd897a001012 1612 }
wim 21:9eb628d9e164 1613
wim 22:35742ec80c24 1614 // write the new data to the SPI portexpander
wim 22:35742ec80c24 1615 _setCS(false);
wim 22:35742ec80c24 1616 _spi->write(_lcd_bus);
wim 22:35742ec80c24 1617 _setCS(true);
wim 21:9eb628d9e164 1618
wim 21:9eb628d9e164 1619 }
wim 21:9eb628d9e164 1620
wim 21:9eb628d9e164 1621
wim 21:9eb628d9e164 1622 // Set CS line.
wim 21:9eb628d9e164 1623 // Only used for SPI bus
wim 21:9eb628d9e164 1624 void TextLCD_SPI::_setCS(bool value) {
wim 21:9eb628d9e164 1625
wim 21:9eb628d9e164 1626 if (value) {
wim 21:9eb628d9e164 1627 _cs = 1; // Set CS pin
wim 21:9eb628d9e164 1628 }
wim 22:35742ec80c24 1629 else {
wim 21:9eb628d9e164 1630 _cs = 0; // Reset CS pin
wim 22:35742ec80c24 1631 }
wim 21:9eb628d9e164 1632 }
wim 21:9eb628d9e164 1633
wim 23:d47f226efb24 1634 //---------- End TextLCD_SPI ------------
wim 22:35742ec80c24 1635
wim 22:35742ec80c24 1636
wim 25:6162b31128c9 1637 //--------- Start TextLCD_SPI_N ---------
Sissors 24:fb3399713710 1638
wim 25:6162b31128c9 1639 /** Create a TextLCD interface using a controller with a native SPI interface
Sissors 24:fb3399713710 1640 *
Sissors 24:fb3399713710 1641 * @param spi SPI Bus
Sissors 24:fb3399713710 1642 * @param cs chip select pin (active low)
wim 25:6162b31128c9 1643 * @param rs Instruction/data control line
Sissors 24:fb3399713710 1644 * @param type Sets the panel size/addressing mode (default = LCD16x2)
wim 25:6162b31128c9 1645 * @param bl Backlight control line (optional, default = NC)
wim 26:bd897a001012 1646 * @param ctrl LCD controller (default = ST7032_3V3)
wim 25:6162b31128c9 1647 */
wim 25:6162b31128c9 1648 TextLCD_SPI_N::TextLCD_SPI_N(SPI *spi, PinName cs, PinName rs, LCDType type, PinName bl, LCDCtrl ctrl) :
wim 25:6162b31128c9 1649 TextLCD_Base(type, ctrl),
wim 25:6162b31128c9 1650 _spi(spi),
wim 25:6162b31128c9 1651 _cs(cs),
wim 25:6162b31128c9 1652 _rs(rs) {
Sissors 24:fb3399713710 1653
Sissors 24:fb3399713710 1654 // Setup the spi for 8 bit data, low steady state clock,
Sissors 24:fb3399713710 1655 // rising edge capture, with a 500KHz or 1MHz clock rate
Sissors 24:fb3399713710 1656 _spi->format(8,0);
Sissors 24:fb3399713710 1657 _spi->frequency(1000000);
Sissors 24:fb3399713710 1658
Sissors 24:fb3399713710 1659 // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
Sissors 24:fb3399713710 1660 if (bl != NC) {
Sissors 24:fb3399713710 1661 _bl = new DigitalOut(bl); //Construct new pin
Sissors 24:fb3399713710 1662 _bl->write(0); //Deactivate
Sissors 24:fb3399713710 1663 }
Sissors 24:fb3399713710 1664 else {
Sissors 24:fb3399713710 1665 // No Hardware Backlight pin
Sissors 24:fb3399713710 1666 _bl = NULL; //Construct dummy pin
Sissors 24:fb3399713710 1667 }
Sissors 24:fb3399713710 1668
Sissors 24:fb3399713710 1669 _init();
Sissors 24:fb3399713710 1670 }
Sissors 24:fb3399713710 1671
wim 25:6162b31128c9 1672 TextLCD_SPI_N::~TextLCD_SPI_N() {
Sissors 24:fb3399713710 1673 if (_bl != NULL) {delete _bl;} // BL pin
Sissors 24:fb3399713710 1674 }
Sissors 24:fb3399713710 1675
Sissors 24:fb3399713710 1676 // Not used in this mode
wim 25:6162b31128c9 1677 void TextLCD_SPI_N::_setEnable(bool value) {
Sissors 24:fb3399713710 1678 }
Sissors 24:fb3399713710 1679
Sissors 24:fb3399713710 1680 // Set RS pin
Sissors 24:fb3399713710 1681 // Used for mbed pins, I2C bus expander or SPI shiftregister
wim 25:6162b31128c9 1682 void TextLCD_SPI_N::_setRS(bool value) {
Sissors 24:fb3399713710 1683 _rs = value;
Sissors 24:fb3399713710 1684 }
Sissors 24:fb3399713710 1685
Sissors 24:fb3399713710 1686 // Set BL pin
wim 25:6162b31128c9 1687 void TextLCD_SPI_N::_setBL(bool value) {
wim 26:bd897a001012 1688 if (_bl) {
Sissors 24:fb3399713710 1689 _bl->write(value);
wim 26:bd897a001012 1690 }
Sissors 24:fb3399713710 1691 }
Sissors 24:fb3399713710 1692
wim 29:a3663151aa65 1693 // Not used in this mode
wim 29:a3663151aa65 1694 void TextLCD_SPI_N::_setData(int value) {
wim 29:a3663151aa65 1695 }
wim 29:a3663151aa65 1696
wim 29:a3663151aa65 1697
Sissors 24:fb3399713710 1698 // Write a byte using SPI
wim 25:6162b31128c9 1699 void TextLCD_SPI_N::_writeByte(int value) {
Sissors 24:fb3399713710 1700 _cs = 0;
Sissors 24:fb3399713710 1701 wait_us(1);
Sissors 24:fb3399713710 1702 _spi->write(value);
Sissors 24:fb3399713710 1703 wait_us(1);
Sissors 24:fb3399713710 1704 _cs = 1;
Sissors 24:fb3399713710 1705 }
Sissors 24:fb3399713710 1706
Sissors 24:fb3399713710 1707
Sissors 24:fb3399713710 1708
wim 25:6162b31128c9 1709 //-------- End TextLCD_SPI_N ------------
wim 21:9eb628d9e164 1710
wim 21:9eb628d9e164 1711
wim 21:9eb628d9e164 1712
wim 21:9eb628d9e164 1713
wim 21:9eb628d9e164 1714