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:
Sissors
Date:
Sat May 10 13:50:25 2014 +0000
Revision:
24:fb3399713710
Parent:
23:d47f226efb24
Child:
25:6162b31128c9
Added ST7032 support + SPI mode

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