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:
Sat Jun 14 17:04:25 2014 +0000
Revision:
28:30fa94f7341c
Parent:
27:22d5086f6ba6
Child:
29:a3663151aa65
Updated to support ST7032i with native I2C and SPI interface.

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