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

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

Fork of TextLCD by Simon Ford

Example

Hello World! for the TextLCD

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

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

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

}

Handbook page

More info is here

Committer:
wim
Date:
Sat May 10 21:34:51 2014 +0000
Revision:
25:6162b31128c9
Parent:
24:fb3399713710
Child:
26:bd897a001012
Added support for controllers with native SPI interface.

Who changed what in which revision?

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