Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: EthernetInterface NTPClient SDFileSystem TextLCD WebSocketClient mbed-rtos mbed Socket lwip-eth lwip-sys lwip FATFileSystem
TextLCD.cpp
00001 /* mbed TextLCD Library, for a 4-bit LCD based on HD44780 00002 * Copyright (c) 2007-2010, sford, http://mbed.org 00003 * 2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs 00004 * 2013, v02: WH, Added I2C and SPI bus interfaces 00005 * 2013, v03: WH, Added support for LCD40x4 which uses 2 controllers 00006 * 2013, v04: WH, Added support for Display On/Off, improved 4bit bootprocess 00007 * 2013, v05: WH, Added support for 8x2B, added some UDCs 00008 * 2013, v06: WH, Added support for devices that use internal DC/DC converters 00009 * 2013, v07: WH, Added support for backlight and include portdefinitions for LCD2004 Module from DFROBOT 00010 * 00011 * Permission is hereby granted, free of charge, to any person obtaining a copy 00012 * of this software and associated documentation files (the "Software"), to deal 00013 * in the Software without restriction, including without limitation the rights 00014 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00015 * copies of the Software, and to permit persons to whom the Software is 00016 * furnished to do so, subject to the following conditions: 00017 * 00018 * The above copyright notice and this permission notice shall be included in 00019 * all copies or substantial portions of the Software. 00020 * 00021 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00022 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00023 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00024 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00025 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00026 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00027 * THE SOFTWARE. 00028 */ 00029 00030 #include "TextLCD.h" 00031 #include "mbed.h" 00032 00033 00034 /* Create a TextLCD interface for using regular mbed pins 00035 * 00036 * @param rs Instruction/data control line 00037 * @param e Enable line (clock) 00038 * @param d4-d7 Data lines for using as a 4-bit interface 00039 * @param type Sets the panel size/addressing mode (default = LCD16x2) 00040 * @param bl Backlight control line (optional, default = NC) 00041 * @param e2 Enable2 line (clock for second controller, LCD40x4 only) 00042 * @param ctrl LCD controller (default = HD44780) 00043 */ 00044 TextLCD::TextLCD(PinName rs, PinName e, 00045 PinName d4, PinName d5, PinName d6, PinName d7, 00046 LCDType type, PinName bl, PinName e2, LCDCtrl ctrl) : _rs(rs), _e(e), _bl(bl), _e2(e2), 00047 _d(d4, d5, d6, d7), 00048 _cs(NC), 00049 _type(type), 00050 _ctrl(ctrl) { 00051 00052 _busType = _PinBus; 00053 00054 _init(); 00055 00056 } 00057 00058 /* Create a TextLCD interface using an I2C PC8574 portexpander 00059 * 00060 * @param i2c I2C Bus 00061 * @param deviceAddress I2C slave address (PCF8574) 00062 * @param type Sets the panel size/addressing mode (default = LCD16x2) 00063 * @param ctrl LCD controller (default = HD44780) 00064 */ 00065 TextLCD::TextLCD(I2C *i2c, char deviceAddress, LCDType type, LCDCtrl ctrl) : 00066 _rs(NC), _e(NC), _bl(NC), _e2(NC), 00067 _d(NC), 00068 _i2c(i2c), 00069 _cs(NC), 00070 _type(type), 00071 _ctrl(ctrl) { 00072 00073 _slaveAddress = deviceAddress; 00074 _busType = _I2CBus; 00075 00076 00077 // Init the portexpander bus 00078 _lcd_bus = D_LCD_BUS_DEF; 00079 00080 // write the new data to the portexpander 00081 _i2c->write(_slaveAddress, &_lcd_bus, 1); 00082 00083 _init(); 00084 00085 } 00086 00087 /* Create a TextLCD interface using an SPI 74595 portexpander 00088 * 00089 * @param spi SPI Bus 00090 * @param cs chip select pin (active low) 00091 * @param type Sets the panel size/addressing mode (default = LCD16x2) 00092 * @param ctrl LCD controller (default = HD44780) 00093 */ 00094 TextLCD::TextLCD(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) : 00095 _rs(NC), _e(NC), _bl(NC), _e2(NC), 00096 _d(NC), 00097 _spi(spi), 00098 _cs(cs), 00099 _type(type), 00100 _ctrl(ctrl) { 00101 00102 _busType = _SPIBus; 00103 00104 // Setup the spi for 8 bit data, low steady state clock, 00105 // rising edge capture, with a 500KHz or 1MHz clock rate 00106 _spi->format(8,0); 00107 _spi->frequency(500000); 00108 //_spi.frequency(1000000); 00109 00110 00111 // Init the portexpander bus 00112 _lcd_bus = D_LCD_BUS_DEF; 00113 00114 // write the new data to the portexpander 00115 _setCS(false); 00116 _spi->write(_lcd_bus); 00117 _setCS(true); 00118 00119 _init(); 00120 00121 } 00122 00123 00124 /* Init the LCD Controller(s) 00125 * Clear display 00126 */ 00127 void TextLCD::_init() { 00128 00129 // Select and configure second LCD controller when needed 00130 if(_type==LCD40x4) { 00131 _ctrl_idx=TextLCD::_LCDCtrl_1; // Select 2nd controller 00132 00133 _initCtrl(); // Init 2nd controller 00134 00135 // Secondary LCD controller Clearscreen 00136 _writeCommand(0x01); // cls, and set cursor to 0 00137 wait_ms(10); // The CLS command takes 1.64 ms. 00138 // Since we are not using the Busy flag, Lets be safe and take 10 ms 00139 00140 } 00141 00142 // Select and configure primary LCD controller 00143 _ctrl_idx=TextLCD::_LCDCtrl_0; // Select primary controller 00144 00145 _initCtrl(); // Init primary controller 00146 00147 // Primary LCD controller Clearscreen 00148 _writeCommand(0x01); // cls, and set cursor to 0 00149 00150 wait_ms(10); // The CLS command takes 1.64 ms. 00151 // Since we are not using the Busy flag, Lets be safe and take 10 ms 00152 00153 } 00154 00155 /* Init the LCD controller 00156 * 4-bit mode, number of lines, fonttype, no cursor etc 00157 * 00158 */ 00159 void TextLCD::_initCtrl() { 00160 00161 _setRS(false); // command mode 00162 00163 wait_ms(20); // Wait 20ms to ensure powered up 00164 00165 // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus) 00166 for (int i=0; i<3; i++) { 00167 _writeNibble(0x3); 00168 wait_ms(15); // This command takes 1.64ms, so wait for it 00169 } 00170 _writeNibble(0x2); // 4-bit mode 00171 wait_us(40); // most instructions take 40us 00172 00173 // Display is now in 4-bit mode 00174 00175 00176 // Device specific initialisations for DC/DC converter to generate VLCD or VLED 00177 switch (_ctrl) { 00178 case ST7036: 00179 // ST7036 controller: Initialise Voltage booster for VLCD. VDD=5V 00180 // Note: supports 1,2 or 3 lines 00181 _writeByte( 0x29 ); // 4-bit Databus, 2 Lines, Select Instruction table 1 00182 wait_ms(30); // > 26,3ms 00183 _writeByte( 0x14 ); // Bias: 1/5, 2-Lines LCD 00184 wait_ms(30); // > 26,3ms 00185 _writeByte( 0x55 ); // Icon off, Booster on, Set Contrast C5, C4 00186 wait_ms(30); // > 26,3ms 00187 _writeByte( 0x6d ); // Voltagefollower On, Ampl ratio Rab2, Rab1, Rab0 00188 wait_ms(200); // > 200ms! 00189 _writeByte( 0x78 ); // Set Contrast C3, C2, C1, C0 00190 wait_ms(30); // > 26,3ms 00191 _writeByte( 0x28 ); // Return to Instruction table 0 00192 wait_ms(50); 00193 00194 break; 00195 00196 case WS0010: 00197 // WS0010 OLED controller: Initialise DC/DC Voltage converter for LEDs 00198 // Note: supports 1 or 2 lines (and 16x100 graphics) 00199 // supports 4 fonts (English/Japanese (default), Western European-I, English/Russian, Western European-II) 00200 00201 // Cursor/Disp shift set 0001 SC RL 0 0 00202 // 00203 // Mode en Power set 0001 GC PWR 1 1 00204 // GC = 0 (Graph Mode=1, Char Mode=0) 00205 // PWR = (DC/DC On/Off) 00206 00207 //_writeCommand(0x13); // DC/DC off 00208 00209 _writeCommand(0x17); // DC/DC on 00210 wait_ms(10); 00211 00212 break; 00213 00214 default: 00215 // Devices that do not use DC/DC Voltage converters but external VLCD 00216 break; 00217 } 00218 00219 // Initialise Display configuration 00220 switch (_type) { 00221 case LCD8x1: 00222 case LCD8x2B: 00223 //8x1 is a regular 1 line display 00224 //8x2B is a special case of 16x1 00225 _writeCommand(0x20); // Function set 001 DL N F - - 00226 // DL=0 (4 bits bus) 00227 // N=0 (1 line) 00228 // F=0 (5x7 dots font) 00229 break; 00230 00231 case LCD24x4: 00232 // Special mode for KS0078 00233 _writeCommand(0x2A); // Function set 001 DL N RE DH REV 00234 // DL=0 (4 bits bus) 00235 // N=1 (Dont care for KS0078) 00236 // RE=0 (Extended Regs, special mode for KS0078) 00237 // DH=1 (Disp shift, special mode for KS0078) 00238 // REV=0 (Reverse, special mode for KS0078) 00239 00240 _writeCommand(0x2E); // Function set 001 DL N RE DH REV 00241 // DL=0 (4 bits bus) 00242 // N=1 (Dont care for KS0078) 00243 // RE=1 (Ena Extended Regs, special mode for KS0078) 00244 // DH=1 (Disp shift, special mode for KS0078) 00245 // REV=0 (Reverse, special mode for KS0078) 00246 00247 _writeCommand(0x09); // Ext Function set 0000 1 FW BW NW 00248 // FW=0 (5-dot font, special mode for KS0078) 00249 // BW=0 (Cur BW invert disable, special mode for KS0078) 00250 // NW=1 (4 Line, special mode for KS0078) 00251 00252 _writeCommand(0x2A); // Function set 001 DL N RE DH REV 00253 // DL=0 (4 bits bus) 00254 // N=1 (Dont care for KS0078) 00255 // RE=0 (Dis. Extended Regs, special mode for KS0078) 00256 // DH=1 (Disp shift, special mode for KS0078) 00257 // REV=0 (Reverse, special mode for KS0078) 00258 break; 00259 00260 // All other LCD types are initialised as 2 Line displays (including LCD40x4) 00261 default: 00262 _writeCommand(0x28); // Function set 001 DL N F - - 00263 // DL=0 (4 bits bus) 00264 // N=1 (2 lines) 00265 // F=0 (5x7 dots font, only option for 2 line display) 00266 // - (Don't care) 00267 00268 break; 00269 } 00270 00271 _writeCommand(0x06); // Entry Mode 0000 01 CD S 00272 // Cursor Direction and Display Shift 00273 // CD=1 (Cur incr) 00274 // S=0 (No display shift) 00275 00276 // _writeCommand(0x0C); // Display Ctrl 0000 1 D C B 00277 // // Display On, Cursor Off, Blink Off 00278 setCursor(TextLCD::CurOff_BlkOff); 00279 setMode(TextLCD::DispOn); 00280 } 00281 00282 00283 // Clear the screen, Cursor home. 00284 void TextLCD::cls() { 00285 00286 // Select and configure second LCD controller when needed 00287 if(_type==LCD40x4) { 00288 _ctrl_idx=TextLCD::_LCDCtrl_1; // Select 2nd controller 00289 00290 // Second LCD controller Cursor always Off 00291 _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff); 00292 00293 // Second LCD controller Clearscreen 00294 _writeCommand(0x01); // cls, and set cursor to 0 00295 00296 wait_ms(10); // The CLS command takes 1.64 ms. 00297 // Since we are not using the Busy flag, Lets be safe and take 10 ms 00298 00299 00300 _ctrl_idx=TextLCD::_LCDCtrl_0; // Select primary controller 00301 } 00302 00303 // Primary LCD controller Clearscreen 00304 _writeCommand(0x01); // cls, and set cursor to 0 00305 00306 wait_ms(10); // The CLS command takes 1.64 ms. 00307 // Since we are not using the Busy flag, Lets be safe and take 10 ms 00308 00309 // Restore cursormode on primary LCD controller when needed 00310 if(_type==LCD40x4) { 00311 _setCursorAndDisplayMode(_currentMode,_currentCursor); 00312 } 00313 00314 _row=0; // Reset Cursor location 00315 _column=0; 00316 } 00317 00318 // Move cursor to selected row and column 00319 void TextLCD::locate(int column, int row) { 00320 00321 // setAddress() does all the heavy lifting: 00322 // check column and row sanity, 00323 // switch controllers for LCD40x4 if needed 00324 // switch cursor for LCD40x4 if needed 00325 // set the new memory address to show cursor at correct location 00326 setAddress(column, row); 00327 00328 } 00329 00330 00331 // Write a single character (Stream implementation) 00332 int TextLCD::_putc(int value) { 00333 int addr; 00334 00335 if (value == '\n') { 00336 //No character to write 00337 00338 //Update Cursor 00339 _column = 0; 00340 _row++; 00341 if (_row >= rows()) { 00342 _row = 0; 00343 } 00344 } 00345 else { 00346 //Character to write 00347 _writeData(value); 00348 00349 //Update Cursor 00350 _column++; 00351 if (_column >= columns()) { 00352 _column = 0; 00353 _row++; 00354 if (_row >= rows()) { 00355 _row = 0; 00356 } 00357 } 00358 } //else 00359 00360 //Set next memoryaddress, make sure cursor blinks at next location 00361 addr = getAddress(_column, _row); 00362 _writeCommand(0x80 | addr); 00363 00364 return value; 00365 } 00366 00367 00368 // get a single character (Stream implementation) 00369 int TextLCD::_getc() { 00370 return -1; 00371 } 00372 00373 // Set E pin (or E2 pin) 00374 // Used for mbed pins, I2C bus expander or SPI shifregister 00375 void TextLCD::_setEnable(bool value) { 00376 00377 switch(_busType) { 00378 case _PinBus : 00379 if(_ctrl_idx==TextLCD::_LCDCtrl_0) { 00380 if (value) 00381 _e = 1; // Set E bit 00382 else 00383 _e = 0; // Reset E bit 00384 } 00385 else { 00386 if (value) 00387 _e2 = 1; // Set E2 bit 00388 else 00389 _e2 = 0; // Reset E2 bit 00390 } 00391 00392 break; 00393 00394 case _I2CBus : 00395 00396 if(_ctrl_idx==TextLCD::_LCDCtrl_0) { 00397 if (value) 00398 _lcd_bus |= D_LCD_E; // Set E bit 00399 else 00400 _lcd_bus &= ~D_LCD_E; // Reset E bit 00401 } 00402 else { 00403 if (value) 00404 _lcd_bus |= D_LCD_E2; // Set E2 bit 00405 else 00406 _lcd_bus &= ~D_LCD_E2; // Reset E2bit 00407 } 00408 00409 // write the new data to the I2C portexpander 00410 _i2c->write(_slaveAddress, &_lcd_bus, 1); 00411 00412 break; 00413 00414 case _SPIBus : 00415 if(_ctrl_idx==TextLCD::_LCDCtrl_0) { 00416 if (value) 00417 _lcd_bus |= D_LCD_E; // Set E bit 00418 else 00419 _lcd_bus &= ~D_LCD_E; // Reset E bit 00420 } 00421 else { 00422 if (value) 00423 _lcd_bus |= D_LCD_E2; // Set E2 bit 00424 else 00425 _lcd_bus &= ~D_LCD_E2; // Reset E2 bit 00426 } 00427 00428 // write the new data to the SPI portexpander 00429 _setCS(false); 00430 _spi->write(_lcd_bus); 00431 _setCS(true); 00432 00433 break; 00434 } 00435 } 00436 00437 // Set RS pin 00438 // Used for mbed pins, I2C bus expander or SPI shifregister 00439 void TextLCD::_setRS(bool value) { 00440 00441 switch(_busType) { 00442 case _PinBus : 00443 if (value) 00444 _rs = 1; // Set RS bit 00445 else 00446 _rs = 0; // Reset RS bit 00447 00448 break; 00449 00450 case _I2CBus : 00451 if (value) 00452 _lcd_bus |= D_LCD_RS; // Set RS bit 00453 else 00454 _lcd_bus &= ~D_LCD_RS; // Reset RS bit 00455 00456 // write the new data to the I2C portexpander 00457 _i2c->write(_slaveAddress, &_lcd_bus, 1); 00458 00459 break; 00460 00461 case _SPIBus : 00462 if (value) 00463 _lcd_bus |= D_LCD_RS; // Set RS bit 00464 else 00465 _lcd_bus &= ~D_LCD_RS; // Reset RS bit 00466 00467 // write the new data to the SPI portexpander 00468 _setCS(false); 00469 _spi->write(_lcd_bus); 00470 _setCS(true); 00471 00472 break; 00473 } 00474 00475 } 00476 00477 // Set BL pin 00478 // Used for mbed pins, I2C bus expander or SPI shifregister 00479 void TextLCD::_setBL(bool value) { 00480 00481 switch(_busType) { 00482 case _PinBus : 00483 if (value) 00484 _bl = 1; // Set BL bit 00485 else 00486 _bl = 0; // Reset BL bit 00487 00488 break; 00489 00490 case _I2CBus : 00491 if (value) 00492 _lcd_bus |= D_LCD_BL; // Set BL bit 00493 else 00494 _lcd_bus &= ~D_LCD_BL; // Reset BL bit 00495 00496 // write the new data to the I2C portexpander 00497 _i2c->write(_slaveAddress, &_lcd_bus, 1); 00498 00499 break; 00500 00501 case _SPIBus : 00502 if (value) 00503 _lcd_bus |= D_LCD_BL; // Set BL bit 00504 else 00505 _lcd_bus &= ~D_LCD_BL; // Reset BL bit 00506 00507 // write the new data to the SPI portexpander 00508 _setCS(false); 00509 _spi->write(_lcd_bus); 00510 _setCS(true); 00511 00512 break; 00513 } 00514 00515 } 00516 00517 00518 00519 // Place the 4bit data on the databus 00520 // Used for mbed pins, I2C bus expander or SPI shifregister 00521 void TextLCD::_setData(int value) { 00522 int data; 00523 00524 switch(_busType) { 00525 case _PinBus : 00526 _d = value & 0x0F; // Write Databits 00527 00528 break; 00529 00530 case _I2CBus : 00531 data = value & 0x0F; 00532 if (data & 0x01) 00533 _lcd_bus |= D_LCD_D4; // Set Databit 00534 else 00535 _lcd_bus &= ~D_LCD_D4; // Reset Databit 00536 00537 if (data & 0x02) 00538 _lcd_bus |= D_LCD_D5; // Set Databit 00539 else 00540 _lcd_bus &= ~D_LCD_D5; // Reset Databit 00541 00542 if (data & 0x04) 00543 _lcd_bus |= D_LCD_D6; // Set Databit 00544 else 00545 _lcd_bus &= ~D_LCD_D6; // Reset Databit 00546 00547 if (data & 0x08) 00548 _lcd_bus |= D_LCD_D7; // Set Databit 00549 else 00550 _lcd_bus &= ~D_LCD_D7; // Reset Databit 00551 00552 // write the new data to the I2C portexpander 00553 _i2c->write(_slaveAddress, &_lcd_bus, 1); 00554 00555 break; 00556 00557 case _SPIBus : 00558 00559 data = value & 0x0F; 00560 if (data & 0x01) 00561 _lcd_bus |= D_LCD_D4; // Set Databit 00562 else 00563 _lcd_bus &= ~D_LCD_D4; // Reset Databit 00564 00565 if (data & 0x02) 00566 _lcd_bus |= D_LCD_D5; // Set Databit 00567 else 00568 _lcd_bus &= ~D_LCD_D5; // Reset Databit 00569 00570 if (data & 0x04) 00571 _lcd_bus |= D_LCD_D6; // Set Databit 00572 else 00573 _lcd_bus &= ~D_LCD_D6; // Reset Databit 00574 00575 if (data & 0x08) 00576 _lcd_bus |= D_LCD_D7; // Set Databit 00577 else 00578 _lcd_bus &= ~D_LCD_D7; // Reset Databit 00579 00580 // write the new data to the SPI portexpander 00581 _setCS(false); 00582 _spi->write(_lcd_bus); 00583 _setCS(true); 00584 00585 break; 00586 } 00587 00588 } 00589 00590 00591 // Set CS line. 00592 // Only used for SPI bus 00593 void TextLCD::_setCS(bool value) { 00594 00595 if (value) { 00596 _cs = 1; // Set CS pin 00597 } 00598 else 00599 _cs = 0; // Reset CS pin 00600 00601 } 00602 00603 00604 // Write a nibble using the 4-bit interface 00605 // Used for mbed pins, I2C bus expander or SPI shifregister 00606 void TextLCD::_writeNibble(int value) { 00607 00608 // Enable is Low 00609 _setEnable(true); 00610 _setData(value & 0x0F); // Low nibble 00611 wait_us(1); // Data setup time 00612 _setEnable(false); 00613 wait_us(1); // Datahold time 00614 00615 // Enable is Low 00616 00617 } 00618 00619 00620 // Write a byte using the 4-bit interface 00621 // Used for mbed pins, I2C bus expander or SPI shifregister 00622 void TextLCD::_writeByte(int value) { 00623 00624 // Enable is Low 00625 _setEnable(true); 00626 _setData(value >> 4); // High nibble 00627 wait_us(1); // Data setup time 00628 _setEnable(false); 00629 wait_us(1); // Data hold time 00630 00631 _setEnable(true); 00632 _setData(value >> 0); // Low nibble 00633 wait_us(1); // Data setup time 00634 _setEnable(false); 00635 wait_us(1); // Datahold time 00636 00637 // Enable is Low 00638 00639 } 00640 00641 void TextLCD::_writeCommand(int command) { 00642 00643 _setRS(false); 00644 wait_us(1); // Data setup time for RS 00645 00646 _writeByte(command); 00647 wait_us(40); // most instructions take 40us 00648 } 00649 00650 void TextLCD::_writeData(int data) { 00651 00652 _setRS(true); 00653 wait_us(1); // Data setup time for RS 00654 00655 _writeByte(data); 00656 wait_us(40); // data writes take 40us 00657 } 00658 00659 00660 #if (0) 00661 // This is the original _address() method. 00662 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80. 00663 // Left it in here for compatibility with older code. New applications should use getAddress() instead. 00664 // 00665 int TextLCD::_address(int column, int row) { 00666 switch (_type) { 00667 case LCD20x4: 00668 switch (row) { 00669 case 0: 00670 return 0x80 + column; 00671 case 1: 00672 return 0xc0 + column; 00673 case 2: 00674 return 0x94 + column; 00675 case 3: 00676 return 0xd4 + column; 00677 } 00678 case LCD16x2B: 00679 return 0x80 + (row * 40) + column; 00680 case LCD16x2: 00681 case LCD20x2: 00682 default: 00683 return 0x80 + (row * 0x40) + column; 00684 } 00685 } 00686 #endif 00687 00688 00689 // This replaces the original _address() method. 00690 // Left it in here for compatibility with older code. New applications should use getAddress() instead. 00691 int TextLCD::_address(int column, int row) { 00692 return 0x80 | getAddress(column, row); 00693 } 00694 00695 // This is new method to return the memory address based on row, column and displaytype. 00696 // 00697 int TextLCD::getAddress(int column, int row) { 00698 00699 switch (_type) { 00700 case LCD8x1: 00701 return 0x00 + column; 00702 00703 case LCD8x2B: 00704 // LCD8x2B is a special layout of LCD16x1 00705 if (row==0) 00706 return 0x00 + column; 00707 else 00708 return 0x08 + column; 00709 00710 00711 case LCD16x1: 00712 // LCD16x1 is a special layout of LCD8x2 00713 if (column<8) 00714 return 0x00 + column; 00715 else 00716 return 0x40 + (column - 8); 00717 00718 case LCD12x4: 00719 switch (row) { 00720 case 0: 00721 return 0x00 + column; 00722 case 1: 00723 return 0x40 + column; 00724 case 2: 00725 return 0x0C + column; 00726 case 3: 00727 return 0x4C + column; 00728 } 00729 00730 case LCD16x4: 00731 switch (row) { 00732 case 0: 00733 return 0x00 + column; 00734 case 1: 00735 return 0x40 + column; 00736 case 2: 00737 return 0x10 + column; 00738 case 3: 00739 return 0x50 + column; 00740 } 00741 00742 case LCD20x4: 00743 switch (row) { 00744 case 0: 00745 return 0x00 + column; 00746 case 1: 00747 return 0x40 + column; 00748 case 2: 00749 return 0x14 + column; 00750 case 3: 00751 return 0x54 + column; 00752 } 00753 00754 // Special mode for KS0078 00755 case LCD24x4: 00756 switch (row) { 00757 case 0: 00758 return 0x00 + column; 00759 case 1: 00760 return 0x20 + column; 00761 case 2: 00762 return 0x40 + column; 00763 case 3: 00764 return 0x60 + column; 00765 } 00766 00767 // Not sure about this one, seems wrong. 00768 case LCD16x2B: 00769 return 0x00 + (row * 40) + column; 00770 00771 case LCD8x2: 00772 case LCD12x2: 00773 case LCD16x2: 00774 case LCD20x2: 00775 case LCD24x2: 00776 case LCD40x2: 00777 return 0x00 + (row * 0x40) + column; 00778 00779 case LCD40x4: 00780 // LCD40x4 is a special case since it has 2 controllers 00781 // Each controller is configured as 40x2 00782 if (row<2) { 00783 // Test to see if we need to switch between controllers 00784 if (_ctrl_idx != _LCDCtrl_0) { 00785 00786 // Second LCD controller Cursor Off 00787 _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff); 00788 00789 // Select primary controller 00790 _ctrl_idx = _LCDCtrl_0; 00791 00792 // Restore cursormode on primary LCD controller 00793 _setCursorAndDisplayMode(_currentMode, _currentCursor); 00794 } 00795 00796 return 0x00 + (row * 0x40) + column; 00797 } 00798 else { 00799 00800 // Test to see if we need to switch between controllers 00801 if (_ctrl_idx != _LCDCtrl_1) { 00802 // Primary LCD controller Cursor Off 00803 _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff); 00804 00805 // Select secondary controller 00806 _ctrl_idx = _LCDCtrl_1; 00807 00808 // Restore cursormode on secondary LCD controller 00809 _setCursorAndDisplayMode(_currentMode, _currentCursor); 00810 } 00811 00812 return 0x00 + ((row-2) * 0x40) + column; 00813 } 00814 00815 // Should never get here. 00816 default: 00817 return 0x00; 00818 } 00819 } 00820 00821 00822 // Set row, column and update memoryaddress. 00823 // 00824 void TextLCD::setAddress(int column, int row) { 00825 00826 // Sanity Check column 00827 if (column < 0) { 00828 _column = 0; 00829 } 00830 else if (column >= columns()) { 00831 _column = columns() - 1; 00832 } else _column = column; 00833 00834 // Sanity Check row 00835 if (row < 0) { 00836 _row = 0; 00837 } 00838 else if (row >= rows()) { 00839 _row = rows() - 1; 00840 } else _row = row; 00841 00842 00843 // Compute the memory address 00844 // For LCD40x4: switch controllers if needed 00845 // switch cursor if needed 00846 int addr = getAddress(_column, _row); 00847 00848 _writeCommand(0x80 | addr); 00849 } 00850 00851 int TextLCD::columns() { 00852 switch (_type) { 00853 case LCD8x1: 00854 case LCD8x2: 00855 case LCD8x2B: 00856 return 8; 00857 00858 case LCD12x2: 00859 case LCD12x4: 00860 return 12; 00861 00862 case LCD16x1: 00863 case LCD16x2: 00864 case LCD16x2B: 00865 case LCD16x4: 00866 return 16; 00867 00868 case LCD20x2: 00869 case LCD20x4: 00870 return 20; 00871 00872 case LCD24x2: 00873 case LCD24x4: 00874 return 24; 00875 00876 case LCD40x2: 00877 case LCD40x4: 00878 return 40; 00879 00880 // Should never get here. 00881 default: 00882 return 0; 00883 } 00884 } 00885 00886 int TextLCD::rows() { 00887 switch (_type) { 00888 case LCD8x1: 00889 case LCD16x1: 00890 return 1; 00891 00892 case LCD8x2: 00893 case LCD8x2B: 00894 case LCD12x2: 00895 case LCD16x2: 00896 case LCD16x2B: 00897 case LCD20x2: 00898 case LCD24x2: 00899 case LCD40x2: 00900 return 2; 00901 00902 case LCD12x4: 00903 case LCD16x4: 00904 case LCD20x4: 00905 case LCD24x4: 00906 case LCD40x4: 00907 return 4; 00908 00909 // Should never get here. 00910 default: 00911 return 0; 00912 } 00913 } 00914 00915 00916 // Set the Cursor Mode (Cursor Off & Blink Off, Cursor On & Blink Off, Cursor Off & Blink On, Cursor On & Blink On 00917 void TextLCD::setCursor(TextLCD::LCDCursor cursorMode) { 00918 00919 // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on 00920 _currentCursor = cursorMode; 00921 00922 // Configure only current LCD controller 00923 _setCursorAndDisplayMode(_currentMode, _currentCursor); 00924 00925 } 00926 00927 // Set the Displaymode (On/Off) 00928 void TextLCD::setMode(TextLCD::LCDMode displayMode) { 00929 00930 // Save new displayMode, needed when 2 controllers are in use or when cursor is changed 00931 _currentMode = displayMode; 00932 00933 // Select and configure second LCD controller when needed 00934 if(_type==LCD40x4) { 00935 if (_ctrl_idx==TextLCD::_LCDCtrl_0) { 00936 // Configure primary LCD controller 00937 _setCursorAndDisplayMode(_currentMode, _currentCursor); 00938 00939 // Select 2nd controller 00940 _ctrl_idx=TextLCD::_LCDCtrl_1; 00941 00942 // Configure secondary LCD controller 00943 _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff); 00944 00945 // Restore current controller 00946 _ctrl_idx=TextLCD::_LCDCtrl_0; 00947 } 00948 else { 00949 // Select primary controller 00950 _ctrl_idx=TextLCD::_LCDCtrl_0; 00951 00952 // Configure primary LCD controller 00953 _setCursorAndDisplayMode(_currentMode, TextLCD::CurOff_BlkOff); 00954 00955 // Restore current controller 00956 _ctrl_idx=TextLCD::_LCDCtrl_1; 00957 00958 // Configure secondary LCD controller 00959 _setCursorAndDisplayMode(_currentMode, _currentCursor); 00960 00961 } 00962 } 00963 else { 00964 // Configure primary LCD controller 00965 _setCursorAndDisplayMode(_currentMode, _currentCursor); 00966 } 00967 00968 } 00969 00970 00971 // Set the Displaymode (On/Off) and Cursortype for current controller 00972 void TextLCD::_setCursorAndDisplayMode(TextLCD::LCDMode displayMode, TextLCD::LCDCursor cursorType) { 00973 00974 // Configure current LCD controller 00975 _writeCommand(0x08 | displayMode | cursorType); 00976 } 00977 00978 // Set the Backlight mode (Off/On) 00979 void TextLCD::setBacklight(TextLCD::LCDBacklight backlightMode) { 00980 00981 if (backlightMode == LightOn) { 00982 _setBL(true); 00983 } 00984 else { 00985 _setBL(false); 00986 } 00987 } 00988 00989 00990 void TextLCD::setUDC(unsigned char c, char *udc_data) { 00991 00992 // Select and configure second LCD controller when needed 00993 if(_type==LCD40x4) { 00994 _LCDCtrl_Idx current_ctrl_idx = _ctrl_idx; // Temp save current controller 00995 00996 // Select primary controller 00997 _ctrl_idx=TextLCD::_LCDCtrl_0; 00998 00999 // Configure primary LCD controller 01000 _setUDC(c, udc_data); 01001 01002 // Select 2nd controller 01003 _ctrl_idx=TextLCD::_LCDCtrl_1; 01004 01005 // Configure secondary LCD controller 01006 _setUDC(c, udc_data); 01007 01008 // Restore current controller 01009 _ctrl_idx=current_ctrl_idx; 01010 } 01011 else { 01012 // Configure primary LCD controller 01013 _setUDC(c, udc_data); 01014 } 01015 01016 } 01017 01018 void TextLCD::_setUDC(unsigned char c, char *udc_data) { 01019 01020 // Select CG RAM for current LCD controller 01021 _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address, 01022 //8 sequential locations needed per UDC 01023 // Store UDC pattern 01024 for (int i=0; i<8; i++) { 01025 _writeData(*udc_data++); 01026 } 01027 01028 //Select DD RAM again for current LCD controller 01029 int addr = getAddress(_column, _row); 01030 _writeCommand(0x80 | addr); 01031 01032 }
Generated on Tue Jul 12 2022 14:07:59 by
1.7.2