Updated for more display types. Fixed memoryaddress confusion in address() method. Added new getAddress() method. Added support for UDCs, Backlight control and other features such as control through I2C and SPI port expanders and controllers with native I2C and SPI interfaces. Refactored to fix issue with pins that are default declared as NC.

Dependents:   GPSDevice TestTextLCD SD to Flash Data Transfer DrumMachine ... more

Fork of TextLCD by Simon Ford

Example

Hello World! for the TextLCD

#include "mbed.h"
#include "TextLCD.h"
 
// Host PC Communication channels
Serial pc(USBTX, USBRX); // tx, rx
 
// I2C Communication
I2C i2c_lcd(p28,p27); // SDA, SCL
 
// SPI Communication
SPI spi_lcd(p5, NC, p7); // MOSI, MISO, SCLK

//TextLCD lcd(p15, p16, p17, p18, p19, p20);                // RS, E, D4-D7, LCDType=LCD16x2, BL=NC, E2=NC, LCDTCtrl=HD44780
//TextLCD_SPI lcd(&spi_lcd, p8, TextLCD::LCD40x4);   // SPI bus, 74595 expander, CS pin, LCD Type  
TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD20x4);  // I2C bus, PCF8574 Slaveaddress, LCD Type
//TextLCD_I2C lcd(&i2c_lcd, 0x42, TextLCD::LCD16x2, TextLCD::WS0010); // I2C bus, PCF8574 Slaveaddress, LCD Type, Device Type
//TextLCD_SPI_N lcd(&spi_lcd, p8, p9);               // SPI bus, CS pin, RS pin, LCDType=LCD16x2, BL=NC, LCDTCtrl=ST7032_3V3   
//TextLCD_I2C_N lcd(&i2c_lcd, ST7032_SA, TextLCD::LCD16x2, NC, TextLCD::ST7032_3V3); // I2C bus, Slaveaddress, LCD Type, BL=NC, LCDTCtrl=ST7032_3V3  

int main() {
    pc.printf("LCD Test. Columns=%d, Rows=%d\n\r", lcd.columns(), lcd.rows());
    
    for (int row=0; row<lcd.rows(); row++) {
      int col=0;
      
      pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));      
//      lcd.putc('-');
      lcd.putc('0' + row);      
      
      for (col=1; col<lcd.columns()-1; col++) {    
        lcd.putc('*');
      }
 
      pc.printf("MemAddr(Col=%d, Row=%d)=0x%02X\n\r", col, row, lcd.getAddress(col, row));      
      lcd.putc('+');
        
    }    
    
// Show cursor as blinking character
    lcd.setCursor(TextLCD::CurOff_BlkOn);
 
// Set and show user defined characters. A maximum of 8 UDCs are supported by the HD44780.
// They are defined by a 5x7 bitpattern. 
    lcd.setUDC(0, (char *) udc_0);  // Show |>
    lcd.putc(0);    
    lcd.setUDC(1, (char *) udc_1);  // Show <|
    lcd.putc(1);    

}

Handbook page

More info is here

Committer:
wim
Date:
Fri May 30 15:05:13 2014 +0000
Revision:
26:bd897a001012
Parent:
25:6162b31128c9
Child:
27:22d5086f6ba6
Added support for MCP23008 I2C expander, added pinmapping for Adafruit I2C and SPI backplane.

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