Fork for Seoul Hackathon

Dependents:   TextLCD_FC113 Kviz

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TextLCD.cpp Source File

TextLCD.cpp

00001 /* mbed TextLCD Library, for LCDs based on HD44780 controllers
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  *               2014, v08: WH, Refactored in Base and Derived Classes to deal with mbed lib change regarding 'NC' defined pins 
00011  *               2014, v09: WH/EO, Added Class for Native SPI controllers such as ST7032 
00012  *               2014, v10: WH, Added Class for Native I2C controllers such as ST7032i, Added support for MCP23008 I2C portexpander, Added support for Adafruit module  
00013  *               2014, v11: WH, Added support for native I2C controllers such as PCF21XX, Improved the _initCtrl() method to deal with differences between all supported controllers  
00014  *               2014, v12: WH, Added support for native I2C controller PCF2119 and native I2C/SPI controllers SSD1803, ST7036, added setContrast method (by JH1PJL) for supported devices (eg ST7032i) 
00015  *               2014, v13: WH, Added support for controllers US2066/SSD1311 (OLED), added setUDCBlink() method for supported devices (eg SSD1803), fixed issue in setPower() 
00016  *               2014, v14: WH, Added support for PT6314 (VFD), added setOrient() method for supported devices (eg SSD1803, US2066), added Double Height lines for supported devices, 
00017  *                              added 16 UDCs for supported devices (eg PCF2103), moved UDC defines to TextLCD_UDC file, added TextLCD_Config.h for feature and footprint settings.
00018  *               2014, v15: WH, Added AC780 support, added I2C expander modules, fixed setBacklight() for inverted logic modules. Fixed bug in LCD_SPI_N define 
00019  *               2014, v16: WH, Added ST7070 and KS0073 support, added setIcon(), clrIcon() and setInvert() method for supported devices 
00020  *               2015, v17: WH, Clean up low-level _writeCommand() and _writeData(), Added support for alternative fonttables (eg PCF21XX), Added ST7066_ACM controller for ACM1602 module 
00021  *               2015, v18: WH, Performance improvement I2C portexpander
00022  *               2015, v19: WH, Fixed Adafruit I2C/SPI portexpander pinmappings, fixed SYDZ Backlight 
00023  *               2015, v20: WH, Fixed occasional Init fail caused by insufficient wait time after ReturnHome command (0x02), Added defines to reduce memory footprint (eg LCD_ICON),
00024  *                              Fixed and Added more fonttable support for PCF2119R_3V3, Added HD66712 controller.
00025  *               2015, v21: WH, Added LCD32x2 defines and code, Fixed KS0073 DL=1 init for SPI, Added defines to reduce memory footprint (LCD_TWO_CTRL, LCD_CONTRAST, LCD_UTF8_FONT)
00026  *                              Added SPLC792A controller, Added UTF8_2_LCD decode for Cyrilic font (By Andriy Ribalko). Added setFont()
00027  *
00028  * Permission is hereby granted, free of charge, to any person obtaining a copy
00029  * of this software and associated documentation files (the "Software"), to deal
00030  * in the Software without restriction, including without limitation the rights
00031  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00032  * copies of the Software, and to permit persons to whom the Software is
00033  * furnished to do so, subject to the following conditions:
00034  *
00035  * The above copyright notice and this permission notice shall be included in
00036  * all copies or substantial portions of the Software.
00037  *
00038  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00039  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00040  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00041  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00042  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00043  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00044  * THE SOFTWARE.
00045  */
00046 #include "mbed.h"
00047 #include "TextLCD.h"
00048 #include "TextLCD_UDC.inc"
00049 #include "TextLCD_UTF8.inc"
00050    
00051 /** Create a TextLCD_Base interface
00052   *
00053   * @param type  Sets the panel size/addressing mode (default = LCD16x2)
00054   * @param ctrl  LCD controller (default = HD44780)           
00055   */
00056 TextLCD_Base::TextLCD_Base(LCDType type, LCDCtrl ctrl) : _type(type), _ctrl(ctrl) {
00057     
00058   // Extract LCDType data  
00059 
00060   // Columns encoded in b15..b8
00061   _nr_cols = (_type & LCD_T_COL_MSK) >> LCD_T_COL_SHFT;   
00062   
00063   // Rows encoded in b23..b16  
00064   _nr_rows = (_type & LCD_T_ROW_MSK) >> LCD_T_ROW_SHFT;   
00065 
00066   // Addressing mode encoded in b27..b24  
00067   _addr_mode = _type & LCD_T_ADR_MSK;
00068   
00069   // Font table, encoded in LCDCtrl  
00070   _font = _ctrl & LCD_C_FNT_MSK;
00071 }
00072 
00073 /**  Init the LCD Controller(s)
00074   *  Clear display 
00075   *  @param _LCDDatalength dl sets the datalength of data/commands
00076   *  @return none 
00077   */
00078 void TextLCD_Base::_init(_LCDDatalength dl) {
00079 
00080   wait_ms(100);                  // Wait 100ms to ensure powered up
00081   
00082 #if (LCD_TWO_CTRL == 1)
00083   // Select and configure second LCD controller when needed
00084   if(_type==LCD40x4) {
00085     _ctrl_idx=_LCDCtrl_1;        // Select 2nd controller   
00086     _initCtrl(dl);               // Init 2nd controller   
00087   }
00088 #endif
00089     
00090   // Select and configure primary LCD controller
00091   _ctrl_idx=_LCDCtrl_0;          // Select primary controller  
00092   _initCtrl(dl);                 // Init primary controller
00093 
00094   // Clear whole display and Reset Cursor location
00095   // Note: This will make sure that some 3-line displays that skip topline of a 4-line configuration 
00096   //       are cleared and init cursor correctly.
00097   cls();   
00098 } 
00099 
00100 /**  Init the LCD controller
00101   *   Set number of lines, fonttype, no cursor etc
00102   *   The controller is accessed in 4-bit parallel mode either directly via mbed pins or through I2C or SPI expander.
00103   *   Some controllers also support native I2C or SPI interfaces. 
00104   *
00105   *  @param _LCDDatalength dl sets the 4 or 8 bit datalength of data/commands. Required for some native serial modes that dont work when DL=0.
00106   *  @return none  
00107   *
00108   *  Note: some configurations are commented out because they have not yet been tested due to lack of hardware
00109   */
00110 void TextLCD_Base::_initCtrl(_LCDDatalength dl) {
00111   int _bias_lines=0; // Set Bias and lines (Instr Set 1), temporary variable.
00112   int _lines=0;      // Set lines (Ext Instr Set), temporary variable.
00113 
00114     this->_setRS(false); // command mode
00115 
00116     if (dl == _LCD_DL_4) {
00117       // The Controller could be in 8 bit mode (power-on reset) or in 4 bit mode (warm reboot) at this point.
00118       // Follow this procedure to make sure the Controller enters the correct state. The hardware interface
00119       // between the uP and the LCD can only write the 4 most significant bits (Most Significant Nibble, MSN).
00120       // In 4 bit mode the LCD expects the MSN first, followed by the LSN.
00121       //
00122       //    Current state:               8 bit mode                |      4 bit mode, MSN is next        | 4 bit mode, LSN is next          
00123                            //-------------------------------------------------------------------------------------------------                          
00124       _writeNibble(0x3);   //  set 8 bit mode (MSN) and dummy LSN, |   set 8 bit mode (MSN),             |    set dummy LSN, 
00125                            //  remains in 8 bit mode               |    remains in 4 bit mode            |  remains in 4 bit mode
00126       wait_ms(15);         //                           
00127      
00128       _writeNibble(0x3);   //  set 8 bit mode (MSN) and dummy LSN, |      set dummy LSN,                 |    set 8bit mode (MSN), 
00129                            //  remains in 8 bit mode               |   change to 8 bit mode              |  remains in 4 bit mode
00130       wait_ms(15);         // 
00131     
00132       _writeNibble(0x3);   //  set 8 bit mode (MSN) and dummy LSN, | set 8 bit mode (MSN) and dummy LSN, |    set dummy LSN, 
00133                            //  remains in 8 bit mode               |   remains in 8 bit mode             |  change to 8 bit mode
00134       wait_ms(15);         // 
00135 
00136       // Controller is now in 8 bit mode
00137 
00138       _writeNibble(0x2);   // Change to 4-bit mode (MSN), the LSN is undefined dummy
00139       wait_us(40);         // most instructions take 40us
00140 
00141       // Controller is now in 4-bit mode
00142       // Note: 4/8 bit mode is ignored for most native SPI and I2C devices. They dont use the parallel bus.
00143       //       However, _writeNibble() method is void anyway for native SPI and I2C devices.
00144     }
00145     else {
00146       // Reset in 8 bit mode, final Function set will follow 
00147       _writeCommand(0x30); // Function set 0 0 1 DL=1 N F x x       
00148       wait_ms(1);          // most instructions take 40us      
00149     }      
00150    
00151     // Device specific initialisations: DC/DC converter to generate VLCD or VLED, number of lines etc
00152     switch (_ctrl) {
00153 
00154       case KS0073:
00155           // Initialise Display configuration
00156           switch (_type) {
00157 //            case LCD6x1:
00158             case LCD8x1:         //8x1 is a regular 1 line display
00159 //            case LCD8x2B:        //8x1 is a 16x1 line display            
00160             case LCD12x1:                                
00161             case LCD16x1:                                            
00162             case LCD20x1:
00163             case LCD24x1:
00164 //            case LCD32x1:        // EXT pin is High, extension driver needed
00165 //            case LCD40x1:        // EXT pin is High, extension driver needed 
00166 //            case LCD52x1:        // EXT pin is High, extension driver needed 
00167               _function = dl | 0x02; // Set function, 0 0 1 DL, N, RE(0), DH, REV                                                                 
00168                                      // Note: 4 bit mode is NOT ignored for native SPI !                       
00169                                      //   DL=1 (8 bits bus), DL=0  (4 bits bus)             
00170                                      //    N=0 (1-line mode), N=1 (2-line mode), dont care for 4 line mode                                     
00171                                      //   RE=0 (Dis. Extended Regs, special mode for KS0073)
00172                                      //   DH=1 (Disp shift enable, special mode for KS0073)                                
00173                                      //   REV=0 (Reverse normal, special mode for KS0073)
00174                                                  
00175               _function_1 = dl | 0x04; // Set function, 0 0 1 DL, N, RE(1), BE, LP  (Ext Regs)
00176                                      // Note: 4 bit mode is NOT ignored for native SPI !                       
00177                                      //   DL=1 (8 bits bus), DL=0  (4 bits bus)                          
00178                                      //    N=0 (1-line mode), N=1 (2-line mode), dont care for 4 line mode                                     
00179                                      //   RE=1 (Ena Extended Regs, special mode for KS0073)
00180                                      //   BE=0 (Blink Enable, CG/SEG RAM, special mode for KS0073)                                
00181                                      //   LP=0 (LP=1 Low power mode, LP=0 Normal)
00182 
00183               _function_x = 0x00;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00184                                     //    NW=0 (1,2 line), NW=1 (4 Line, special mode for KS0073)                                
00185               break;                                
00186 
00187 //            case LCD12x3D:         // Special mode for KS0073, KS0078 and PCF21XX            
00188 //            case LCD12x3D1:        // Special mode for KS0073, KS0078 and PCF21XX            
00189             case LCD12x4D:         // Special mode for KS0073, KS0078 and PCF21XX            
00190 //            case LCD16x3D:         // Special mode for KS0073, KS0078             
00191 //            case LCD16x3D1:        // Special mode for KS0073, KS0078             
00192 //            case LCD16x4D:         // Special mode for KS0073, KS0078            
00193             case LCD20x4D:         // Special mode for KS0073, KS0078            
00194               _function = dl | 0x02; // Set function, 0 0 1 DL, N, RE(0), DH, REV                                                                 
00195                                      // Note: 4 bit mode is NOT ignored for native SPI !                       
00196                                      //   DL=1  (8 bits bus), DL=0 (4 bits bus)             
00197                                      //    N=0 (1-line mode), N=1 (2-line mode), dont care for 4 line mode                                      
00198                                      //   RE=0  (Dis. Extended Regs, special mode for KS0073)
00199                                      //   DH=1  (Disp shift enable, special mode for KS0073)                                
00200                                      //   REV=0 (Reverse normal, special mode for KS0073)
00201                                     
00202               _function_1 = dl | 0x04; // Set function, 0 0 1 DL, N, RE(1), BE, LP  (Ext Regs)
00203                                      // Note: 4 bit mode is NOT ignored for native SPI !                       
00204                                      //   DL=1 (8 bits bus), DL=0 (4 bits bus)                          
00205                                      //    N=0 (1-line mode), N=1 (2-line mode), dont care for 4 line mode              
00206                                      //   RE=1 (Ena Extended Regs, special mode for KS0073)
00207                                      //   BE=0 (Blink Enable, CG/SEG RAM, special mode for KS0073)                                
00208                                      //   LP=0 (LP=1 Low power mode, LP=0 Normal)                                    
00209 
00210               _function_x = 0x01;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00211                                     //    NW=0 (1,2 line), NW=1 (4 Line, special mode for KS0073)                                
00212               break;                                
00213 
00214 //            case LCD6x2:
00215             case LCD8x2:
00216             case LCD16x2:
00217 //            case LCD16x1C:            
00218             case LCD20x2:
00219             case LCD24x2:
00220             case LCD32x2:            
00221               // All other LCD types are initialised as 2 Line displays
00222               _function = dl | 0x0A; // Set function, 0 0 1 DL, N, RE(0), DH, REV                                                                 
00223                                      // Note: 4 bit mode is NOT ignored for native SPI !                       
00224                                      //   DL=1  (8 bits bus), DL=0  (4 bits bus)             
00225                                      //    N=1  (2-line mode), N=0 (1-line mode)
00226                                      //   RE=0  (Dis. Extended Regs, special mode for KS0073)
00227                                      //   DH=1  (Disp shift enable, special mode for KS0073)                                
00228                                      //   REV=0 (Reverse normal, special mode for KS0073)
00229                                     
00230               _function_1 = dl | 0x0C; // Set function, 0 0 1 DL, N, RE(1), BE, LP  (Ext Regs)
00231                                      // Note: 4 bit mode is NOT ignored for native SPI !                       
00232                                      //   DL=1  (8 bits bus), DL=0  (4 bits bus)                          
00233                                      //    N=1  (2 line mode), N=0 (1-line mode)
00234                                      //   RE=1  (Ena Extended Regs, special mode for KS0073)
00235                                      //   BE=0  (Blink Enable, CG/SEG RAM, special mode for KS0073)                   
00236                                      //   LP=0  (LP=1 Low power mode, LP=0 Normal)                                                                                     
00237 
00238               _function_x = 0x00;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00239                                     //   NW=0  (1,2 line), NW=1 (4 Line, special mode for KS0073)                                
00240               break;
00241 
00242             default:
00243               error("Error: LCD Controller type does not support this Display type\n\r"); 
00244               break;                            
00245           } // switch type
00246 
00247           // init special features
00248           _writeCommand(0x20 | _function_1);// Function set 001 DL N RE(1) BE LP (Ext Regs)
00249                                            //   DL=0 (4 bits bus), DL=1 (8 bits mode)            
00250                                            //    N=0 (1 line mode), N=1 (2 line mode)
00251                                            //   RE=1 (Ena Extended Regs, special mode for KS0073)
00252                                            //   BE=0 (Blink Enable/Disable, CG/SEG RAM, special mode for KS0073)                                
00253                                            //   LP=0  (LP=1 Low power mode, LP=0 Normal)                                                                                                                                
00254 
00255           _writeCommand(0x08 | _function_x); // Ext Function set 0000 1 FW BW NW (Ext Regs)
00256                                            //   FW=0  (5-dot font, special mode for KS0073)
00257                                            //   BW=0  (Cur BW invert disable, special mode for KS0073)
00258                                            //   NW=0  (1,2 Line), NW=1 (4 line, special mode for KS0073)                                
00259 
00260           _writeCommand(0x10);             // Scroll/Shift set 0001 DS/HS4 DS/HS3 DS/HS2 DS/HS1 (Ext Regs)
00261                                            //   Dotscroll/Display shift enable (Special mode for KS0073)
00262 
00263           _writeCommand(0x80);             // Scroll Quantity set 1 0 SQ5 SQ4 SQ3 SQ2 SQ1 SQ0 (Ext Regs)
00264                                            //   Scroll quantity (Special mode for KS0073)
00265 
00266           _writeCommand(0x20 | _function); // Function set 001 DL N RE(0) DH REV (Std Regs)
00267                                            //   DL=0  (4 bits bus), DL=1 (8 bits mode)             
00268                                            //    N=0  (1 line mode), N=1 (2 line mode)
00269                                            //   RE=0  (Dis. Extended Regs, special mode for KS0073)
00270                                            //   DH=1  (Disp shift enable/disable, special mode for KS0073)                                
00271                                            //   REV=0 (Reverse/Normal, special mode for KS0073)
00272           break; // case KS0073 Controller
00273 
00274 
00275       case KS0078:
00276           // Initialise Display configuration
00277           switch (_type) {
00278             case LCD8x1:         //8x1 is a regular 1 line display
00279             case LCD8x2B:        //8x2B is a special case of 16x1
00280 //            case LCD12x1:                                
00281             case LCD16x1:                                            
00282 //            case LCD20x1:
00283             case LCD24x1:
00284               _function = dl | 0x02;    // Function set 001 DL N RE(0) DH REV (Std Regs)
00285                                     //   DL=0  (4 bits bus)             
00286                                     //    N=0  (1 line mode), N=1 (2 line mode)
00287                                     //   RE=0  (Dis. Extended Regs, special mode for KS0078)
00288                                     //   DH=1  (Disp shift enable, special mode for KS0078)                                
00289                                     //   REV=0 (Reverse normal, special mode for KS0078)
00290                                     
00291               _function_1 = dl | 0x04;   // Function set 001 DL N RE(1) BE 0 (Ext Regs)
00292                                     //   DL=0  (4 bits bus)             
00293                                     //    N=0  (1 line mode), N=1 (2 line mode)
00294                                     //   RE=1  (Ena Extended Regs, special mode for KS0078)
00295                                     //   BE=0  (Blink Enable, CG/SEG RAM, special mode for KS0078)                                
00296                                     //      0 
00297 
00298               _function_x = 0x00;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00299                                     //    NW=0  (1,2 line), NW=1 (4 Line, special mode for KS0078)                                
00300               break;                                
00301 
00302 //            case LCD12x3D:         // Special mode for KS0073, KS0078 and PCF21XX            
00303 //            case LCD12x3D1:        // Special mode for KS0073, KS0078 and PCF21XX            
00304 //            case LCD12x4D:         // Special mode for KS0073, KS0078 and PCF21XX            
00305 //            case LCD16x3D:         // Special mode for KS0073, KS0078             
00306 //            case LCD16x4D:         // Special mode for KS0073, KS0078            
00307 //            case LCD20x4D:         // Special mode for KS0073, KS0078            
00308 //            case LCD24x3D:         // Special mode for KS0078
00309 //            case LCD24x3D1:        // Special mode for KS0078
00310             case LCD24x4D:         // Special mode for KS0078
00311               _function  = dl | 0x02;    // Function set 001 DL N RE(0) DH REV (Std Regs)
00312                                     //   DL=0  (4 bits bus)             
00313                                     //    N=0  (dont care for 4 line mode)              
00314                                     //   RE=0  (Dis. Extended Regs, special mode for KS0078)
00315                                     //   DH=1  (Disp shift enable, special mode for KS0078)                                
00316                                     //   REV=0 (Reverse normal, special mode for KS0078)
00317                                     
00318               _function_1 = dl | 0x04;   // Function set 001 DL N RE(1) BE 0 (Ext Regs)
00319                                     //   DL=0  (4 bits bus)             
00320                                     //    N=0  (1 line mode), N=1 (2 line mode)
00321                                     //   RE=1  (Ena Extended Regs, special mode for KS0078)
00322                                     //   BE=0  (Blink Enable, CG/SEG RAM, special mode for KS0078)                                
00323                                     //      0 
00324 
00325               _function_x = 0x01;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00326                                     //    NW=0  (1,2 line), NW=1 (4 Line, special mode for KS0078)                                
00327               break;                                
00328 
00329 //            case LCD6x2:
00330             case LCD8x2:
00331             case LCD16x2:
00332 //            case LCD16x1C:            
00333             case LCD20x2:
00334             case LCD24x2:
00335             case LCD32x2:           
00336             case LCD40x2:                       
00337               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)            
00338               _function  = dl | 0x0A;    // Function set 001 DL N RE(0) DH REV (Std Regs)
00339                                     //   DL=0  (4 bits bus)             
00340                                     //    N=1  (1 line mode), N=1 (2 line mode)
00341                                     //   RE=0  (Dis. Extended Regs, special mode for KS0078)
00342                                     //   DH=1  (Disp shift enable, special mode for KS0078)                                
00343                                     //   REV=0 (Reverse normal, special mode for KS0078)
00344                                     
00345               _function_1 = dl | 0x0C;   // Function set 001 DL N RE(1) BE 0 (Ext Regs)
00346                                     //   DL=0  (4 bits bus)             
00347                                     //    N=1  (1 line mode), N=1 (2 line mode)
00348                                     //   RE=1  (Ena Extended Regs, special mode for KS0078)
00349                                     //   BE=0  (Blink Enable, CG/SEG RAM, special mode for KS0078)                                
00350                                     //      0 
00351 
00352               _function_x = 0x00;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00353                                     //   NW=0  (1,2 line), NW=1 (4 Line, special mode for KS0078)                                
00354               break;
00355 
00356             default:
00357               error("Error: LCD Controller type does not support this Display type\n\r"); 
00358               break;                
00359           } // switch type
00360 
00361           // init special features
00362           _writeCommand(0x20 | _function_1);// Function set 001 DL N RE(1) BE 0 (Ext Regs)
00363                                            //   DL=0 (4 bits bus), DL=1 (8 bits mode)            
00364                                            //    N=0 (1 line mode), N=1 (2 line mode)
00365                                            //   RE=1 (Ena Extended Regs, special mode for KS0078)
00366                                            //   BE=0 (Blink Enable/Disable, CG/SEG RAM, special mode for KS0078)                                
00367                                            //      0 
00368 
00369           _writeCommand(0x08 | _function_x); // Ext Function set 0000 1 FW BW NW (Ext Regs)
00370                                            //   FW=0  (5-dot font, special mode for KS0078)
00371                                            //   BW=0  (Cur BW invert disable, special mode for KS0078)
00372                                            //   NW=0  (1,2 Line), NW=1 (4 line, special mode for KS0078)                                
00373 
00374           _writeCommand(0x10);             // Scroll/Shift set 0001 DS/HS4 DS/HS3 DS/HS2 DS/HS1 (Ext Regs)
00375                                            //   Dotscroll/Display shift enable (Special mode for KS0078)
00376 
00377           _writeCommand(0x80);             // Scroll Quantity set 1 0 SQ5 SQ4 SQ3 SQ2 SQ1 SQ0 (Ext Regs)
00378                                            //   Scroll quantity (Special mode for KS0078)
00379 
00380           _writeCommand(0x20 | _function); // Function set 001 DL N RE(0) DH REV (Std Regs)
00381                                            //   DL=0  (4 bits bus), DL=1 (8 bits mode)             
00382                                            //    N=0  (1 line mode), N=1 (2 line mode)
00383                                            //   RE=0  (Dis. Extended Regs, special mode for KS0078)
00384                                            //   DH=1  (Disp shift enable/disable, special mode for KS0078)                                
00385                                            //   REV=0 (Reverse/Normal, special mode for KS0078)
00386           break; // case KS0078 Controller
00387               
00388       case ST7032_3V3:
00389           // ST7032 controller: Initialise Voltage booster for VLCD. VDD=3V3
00390           // Note: very similar to SPLC792A
00391       case ST7032_5V:
00392           // ST7032 controller: Disable Voltage booster for VLCD. VDD=5V
00393       
00394           // Initialise Display configuration
00395           switch (_type) {
00396             case LCD8x1:         //8x1 is a regular 1 line display
00397             case LCD8x2B:        //8x2B is a special case of 16x1
00398 //            case LCD12x1:                                
00399             case LCD16x1:                                            
00400 //            case LCD20x1:                    
00401             case LCD24x1:
00402               _function = 0x00;       // FUNCTION SET 0 0 1 DL=0 (4 bit), N=0 (1-line display mode), F=0 (5*7dot), 0, IS
00403                                       // Note: 4 bit mode is ignored for native SPI and I2C devices
00404                                       // Saved to allow switch between Instruction sets at later time
00405               break;  
00406 
00407             case LCD12x3D:            // Special mode for KS0078 and PCF21XX
00408             case LCD12x3D1:           // Special mode for KS0078 and PCF21XX
00409             case LCD12x4D:            // Special mode for KS0078 and PCF21XX
00410             case LCD16x3G:            // Special mode for ST7036                        
00411             case LCD24x4D:            // Special mode for KS0078
00412               error("Error: LCD Controller type does not support this Display type\n\r"); 
00413               break;  
00414 
00415             default:
00416               // All other LCD types are initialised as 2 Line displays        
00417               _function = 0x08;       // FUNCTION SET 0 0 1 DL=0 (4 bit), N=1 (2-line display mode), F=0 (5*7dot), 0, IS              
00418                                       // Note: 4 bit mode is ignored for native SPI and I2C devices
00419                                       // Saved to allow switch between Instruction sets at later time
00420               break;                                                                        
00421           } // switch type    
00422                                      
00423           // init special features 
00424           _writeCommand(0x20 | _function | 0x01);           // Set function,  0 0 1 DL N F 0 IS=1 Select Instr Set = 1              
00425 
00426           _writeCommand(0x1C);                              // Internal OSC frequency adjustment Framefreq=183HZ, Bias will be 1/4 (Instr Set=1)
00427                                                             // Note: Bias and Osc register not available on SPLC792A 
00428 
00429           _contrast = LCD_ST7032_CONTRAST;              
00430           _writeCommand(0x70 | (_contrast & 0x0F));         // Set Contrast Low bits, 0 1 1 1 C3 C2 C1 C0 (IS=1)
00431 
00432 
00433           if (_ctrl == ST7032_3V3) {
00434 //            _icon_power = 0x04;                             // Icon display off (Bit3=0), Booster circuit is turned on (Bit2=1) (IS=1)
00435             _icon_power = 0x0C;                             // Icon display on (Bit3=1), Booster circuit is turned on (Bit2=1)  (IS=1)
00436                                                             // Note: Booster circuit always on for SPLC792A, Bit2 is dont care
00437                                                             // Saved to allow contrast change at later time
00438           }
00439           else { 
00440 //            _icon_power = 0x00;                             // Icon display off, Booster circuit is turned off  (IS=1)
00441             _icon_power = 0x08;                             // Icon display on, Booster circuit is turned off  (IS=1)            
00442                                                             // Saved to allow contrast change at later time
00443           }
00444           _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03));  // Set Icon, Booster and Contrast High bits, 0 1 0 1 Ion Bon C5 C4 (IS=1)
00445           wait_ms(10);            // Wait 10ms to ensure powered up
00446           
00447           _writeCommand(0x68 | (LCD_ST7032_RAB & 0x07));      // Voltage follower, 0 1 1 0 FOn=1, Ampl ratio Rab2=1, Rab1=0, Rab0=0  (IS=1)
00448           wait_ms(10);            // Wait 10ms to ensure powered up
00449           
00450           _writeCommand(0x20 | _function);                  // Select Instruction Set = 0
00451 
00452           break; // case ST7032_3V3 Controller
00453                  // case ST7032_5V Controller
00454 
00455       case ST7036_3V3:
00456           // ST7036 controller: Initialise Voltage booster for VLCD. VDD=3V3
00457           // Note: supports 1,2 (LCD_T_A) or 3 lines (LCD_T_G)
00458       case ST7036_5V:
00459           // ST7036 controller: Disable Voltage booster for VLCD. VDD=5V
00460           // Note: supports 1,2 (LCD_T_A) or 3 lines (LCD_T_G)
00461                     
00462           // Initialise Display configuration
00463           switch (_type) {
00464             case LCD8x1:         //8x1 is a regular 1 line display
00465             case LCD8x2B:        //8x2D is a special case of 16x1
00466 //            case LCD12x1:                                
00467             case LCD16x1:   
00468             case LCD24x1:                                                                         
00469               _function = 0x00;     // Set function, 0 0 1 DL=0 (4-bit Databus), N=0 (1 Line), DH=0 (5x7font), IS2, IS1 (Select Instruction Set)
00470                                     // Note: 4 bit mode is ignored for native SPI and I2C devices
00471                                     // Saved to allow switch between Instruction sets at later time
00472               
00473               _bias_lines = 0x04;   // Bias: 1/5, 1 or 2-Lines LCD 
00474               break;  
00475 
00476 //            case LCD12x3G:          // Special mode for ST7036
00477             case LCD16x3G:          // Special mode for ST7036
00478               _function = 0x08;     // Set function, 0 0 1 DL=0 (4-bit Databus), N=1 (2 Line), DH=0 (5x7font), IS2,IS1 (Select Instruction Set)              
00479                                     // Note: 4 bit mode is ignored for native SPI and I2C devices
00480                                     // Saved to allow switch between Instruction sets at later time
00481               
00482               _bias_lines = 0x05;   // Bias: 1/5, 3-Lines LCD           
00483               break;  
00484 
00485 //            case LCD12x3D1:           // Special mode for KS0078 and PCF21XX
00486 //            case LCD16x3D1:           // Special mode for SSD1803
00487             case LCD12x4D:            // Special mode for PCF2116
00488             case LCD24x4D:            // Special mode for KS0078
00489               error("Error: LCD Controller type does not support this Display type\n\r"); 
00490               break;  
00491 
00492             default:
00493               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)       
00494               _function = 0x08;     // Set function, 0 0 1 DL=0 (4-bit Databus), N=1 (2 Line), DH=0 (5x7font), IS2,IS1 (Select Instruction Set)
00495                                     // Note: 4 bit mode is ignored for native SPI and I2C devices
00496                                     // Saved to allow switch between Instruction sets at later time
00497               
00498               _bias_lines = 0x04;   // Bias: 1/5, 1 or 2-Lines LCD 
00499               break;                
00500           } // switch type
00501 
00502 
00503           // init special features 
00504           _writeCommand(0x20 | _function | 0x01);   // Set function, IS2,IS1 = 01 (Select Instr Set = 1)
00505           _writeCommand(0x10 | _bias_lines);        // Set Bias and 1,2 or 3 lines (Instr Set 1)
00506 
00507           _contrast = LCD_ST7036_CONTRAST;
00508           _writeCommand(0x70 | (_contrast & 0x0F)); // Set Contrast, 0 1 1 1 C3 C2 C1 C0 (Instr Set 1)
00509                            
00510           if (_ctrl == ST7036_3V3) {
00511             _icon_power = 0x0C;                       // Set Icon, Booster, Contrast High bits, 0 1 0 1 Ion=1 Bon=1 C5 C4 (Instr Set 1)            
00512 //            _icon_power = 0x04;                       // Set Icon, Booster, Contrast High bits, 0 1 0 1 Ion=0 Bon=1 C5 C4 (Instr Set 1)
00513                                                       // Saved to allow contrast change at later time
00514           } 
00515           else {
00516             _icon_power = 0x08;                       // Set Icon, Booster, Contrast High bits, 0 1 0 1 Ion=1 Bon=0 C5 C4 (Instr Set 1)             
00517 //            _icon_power = 0x00;                       // Set Icon, Booster, Contrast High bits, 0 1 0 1 Ion=0 Bon=0 C5 C4 (Instr Set 1)                         
00518           }
00519           
00520           _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03));   // Set Contrast C5, C4 (Instr Set 1)
00521           wait_ms(10);            // Wait 10ms to ensure powered up
00522 
00523           _writeCommand(0x68 | (LCD_ST7036_RAB & 0x07));  // Voltagefollower On = 1, Ampl ratio Rab2, Rab1, Rab0 = 1 0 1 (Instr Set 1)
00524           wait_ms(10);            // Wait 10ms to ensure powered up
00525 
00526           _writeCommand(0x20 | _function);          // Set function, IS2,IS1 = 00 (Select Instruction Set = 0)
00527          
00528           break; // case ST7036_3V3 Controller
00529                  // case ST7036_5V Controller
00530 
00531       case ST7070:                   
00532           // Initialise Display configuration
00533           switch (_type) {
00534             case LCD8x1:         //8x1 is a regular 1 line display
00535             case LCD8x2B:        //8x2D is a special case of 16x1
00536 //            case LCD12x1:                                
00537             case LCD16x1:   
00538             case LCD24x1:                                                                         
00539               _function = dl | 0x00;      // Set function, 0 0 1 DL=0 (4-bit Databus), N=0 (1 Line), EXT=0, x, x 
00540                                           // Note: 4 bit mode is NOT ignored for native SPI !
00541                                           // Saved to allow switch between Instruction sets at later time
00542               break;  
00543 
00544 //            case LCD12x3D1:           // Special mode for KS0078 and PCF21XX
00545 //            case LCD16x3D1:           // Special mode for SSD1803
00546             case LCD12x4D:            // Special mode for PCF2116
00547             case LCD24x4D:            // Special mode for KS0078
00548 //            case LCD12x3G:          // Special mode for ST7036
00549             case LCD16x3G:          // Special mode for ST7036           
00550               error("Error: LCD Controller type does not support this Display type\n\r"); 
00551               break;  
00552 
00553             default:
00554               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)       
00555               _function = dl | 0x08;   // Set function, 0 0 1 DL, N=1 (2 Line), EXT=0, x, x                                                                 
00556                                        // Note: 4 bit mode is NOT ignored for native SPI !
00557                                        // Saved to allow switch between Instruction sets at later time
00558               break;                
00559           } // switch type
00560 
00561 //          _writeCommand(0x00);                      // NOP, make sure to sync SPI
00562           
00563           // init special features                                                    
00564           _writeCommand(0x20 | _function | 0x04);   // Set function, 0 0 1 DL N EXT=1 x x (Select Instr Set = 1)
00565 
00566           _writeCommand(0x04 | 0x00);               // Set Bias resistors  0 0 0 0 0 1 Rb1,Rb0= 0 0 (Extern Res) (Instr Set 1)
00567 
00568           _writeCommand(0x40 | 0x00);               // COM/SEG directions 0 1 0 0 C1, C2, S1, S2  (Instr Set 1)
00569                                                     // C1=1: Com1-8 -> Com8-1;   C2=1: Com9-16 -> Com16-9
00570                                                     // S1=1: Seg1-40 -> Seg40-1; S2=1: Seg41-80 -> Seg80-41                                                    
00571           
00572           _writeCommand(0x20 | _function);          // Set function, EXT=0 (Select Instr Set = 0)
00573          
00574           break; // case ST7070 Controller
00575          
00576       case SSD1803_3V3:
00577           // SSD1803 controller: Initialise Voltage booster for VLCD. VDD=3V3
00578           // Note: supports 1,2, 3 or 4 lines
00579 //      case SSD1803_5V:
00580           // SSD1803 controller: No Voltage booster for VLCD. VDD=5V
00581                     
00582           // Initialise Display configuration
00583           switch (_type) {
00584             case LCD8x1:         //8x1 is a regular 1 line display
00585             case LCD8x2B:        //8x2D is a special case of 16x1
00586 //            case LCD12x1:                                
00587             case LCD16x1:   
00588             case LCD24x1:                                                                         
00589               _function = 0x00;     //  Set function 0 0 1 DL N DH RE(0) IS 
00590                                     //  Saved to allow switch between Instruction sets at later time
00591                                     //    DL=0 4-bit Databus,
00592                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00593                                     //     N=0 1 Line / 3 Line
00594                                     //    DH=0 Double Height disable 
00595                                     //    IS=0
00596           
00597               _function_1 = 0x02;   // Set function, 0 0 1 DL N BE RE(1) REV
00598                                     //  Saved to allow switch between Instruction sets at later time
00599                                     //    DL=0 4-bit Databus,
00600                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00601                                     //     N=0 1 Line / 3 Line
00602                                     //    BE=0 Blink Enable off, special feature of SSD1803
00603                                     //   REV=0 Reverse off, special feature of SSD1803            
00604                         
00605               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00606                                     //    NW=0 1-Line LCD (N=0)
00607               break;  
00608 
00609             case LCD12x3D:          // Special mode for KS0078 and PCF21XX                                  
00610 //            case LCD12x3D1:           // Special mode for KS0078 and PCF21XX            
00611             case LCD16x3D:          // Special mode for KS0078
00612 //            case LCD16x3D1:           // Special mode for SSD1803
00613 //            case LCD20x3D:            // Special mode for SSD1803
00614               _function = 0x00;     //  Set function 0 0 1 DL N DH RE(0) IS 
00615                                     //  Saved to allow switch between Instruction sets at later time
00616                                     //    DL=0 4-bit Databus,
00617                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00618                                     //     N=0 1 Line / 3 Line
00619                                     //    DH=0 Double Height disable 
00620                                     //    IS=0
00621           
00622               _function_1 = 0x02;   // Set function, 0 0 1 DL N BE RE(1) REV
00623                                     //  Saved to allow switch between Instruction sets at later time
00624                                     //    DL=0 4-bit Databus,
00625                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00626                                     //     N=0 1 Line / 3 Line
00627                                     //    BE=0 Blink Enable off, special feature of SSD1803
00628                                     //   REV=0 Reverse off, special feature of SSD1803            
00629                         
00630               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00631                                     //    NW=1 3-Line LCD (N=0)
00632               break;  
00633 
00634 //            case LCD10x2D:          // Special mode for SSD1803, 4-line mode but switch to double height font
00635             case LCD10x4D:          // Special mode for SSD1803
00636             case LCD20x4D:          // Special mode for SSD1803
00637               _function = 0x08;     //  Set function 0 0 1 DL N DH RE(0) IS 
00638                                     //  Saved to allow switch between Instruction sets at later time
00639                                     //    DL=0 4-bit Databus,
00640                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00641                                     //     N=1 4 Line
00642                                     //    DH=0 Double Height disable 
00643                                     //    IS=0
00644           
00645               _function_1 = 0x0A;   // Set function, 0 0 1 DL N BE RE(1) REV
00646                                     //  Saved to allow switch between Instruction sets at later time
00647                                     //    DL=0 4-bit Databus,
00648                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00649                                     //     N=1 4 Line
00650                                     //    BE=0 Blink Enable off, special feature of SSD1803
00651                                     //   REV=0 Reverse off, special feature of SSD1803            
00652                         
00653               _lines = 0x01;        // Ext function set 0 0 0 0 1 FW BW NW 
00654                                     //    NW=1 4-Line LCD (N=1)
00655               break;  
00656 
00657             case LCD16x3G:          // Special mode for ST7036            
00658             case LCD24x4D:          // Special mode for KS0078
00659               error("Error: LCD Controller type does not support this Display type\n\r"); 
00660               break;  
00661 
00662             default:
00663               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)       
00664               _function = 0x08;     //  Set function 0 0 1 DL N DH RE(0) IS 
00665                                     //  Saved to allow switch between Instruction sets at later time
00666                                     //    DL=0 4-bit Databus,
00667                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00668                                     //     N=1 2 line / 4 Line
00669                                     //    DH=0 Double Height disable 
00670                                     //    RE=0
00671                                     //    IS=0
00672           
00673               _function_1 = 0x0A;   // Set function, 0 0 1 DL N BE RE(1) REV
00674                                     //  Saved to allow switch between Instruction sets at later time
00675                                     //    DL=0 4-bit Databus,
00676                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00677                                     //     N=1 2 line / 4 Line
00678                                     //    BE=0 Blink Enable off, special feature of SSD1803
00679                                     //    RE=1
00680                                     //   REV=0 Reverse off, special feature of SSD1803            
00681                         
00682               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00683                                     //    NW=0 2-Line LCD (N=1)
00684               break;                
00685           } // switch type
00686 
00687 
00688           // init special features 
00689           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
00690                                                     // Select Extended Instruction Set
00691           
00692           _writeCommand(0x06);                      // Set ext entry mode, 0 0 0 0 0 1 BDC=1 COM1-32, BDS=0 SEG100-1    "Bottom View" (Ext Instr Set)
00693 //          _writeCommand(0x05);                      // Set ext entry mode, 0 0 0 0 0 1 BDC=0 COM32-1, BDS=1 SEG1-100    "Top View" (Ext Instr Set)          
00694           wait_ms(5);                               // Wait to ensure completion or SSD1803 fails to set Top/Bottom after reset..
00695          
00696           _writeCommand(0x08 | _lines);             // Set ext function 0 0 0 0 1 FW BW NW 1,2,3 or 4 lines (Ext Instr Set)
00697 
00698           _writeCommand(0x10);                      // Double Height and Bias, 0 0 0 1 UD2=0, UD1=0, BS1=0 Bias 1/5, DH=0 (Ext Instr Set)
00699 
00700 //          _writeCommand(0x76);                      // Set TC Control, 0 1 1 1 0 1 1 0 (Ext Instr Set)
00701 //          _writeData(0x02);                         // Set TC data,    0 0 0 0 0 TC2,TC1,TC0 = 0 1 0 (Ext Instr Set)
00702 
00703           _writeCommand(0x20 | _function | 0x01);   // Set function, 0 0 1 DL N DH RE(0) IS=1 Select Instruction Set 1
00704                                                     // Select Std Instr set, Select IS=1  
00705 
00706           _contrast = LCD_SSD1_CONTRAST;
00707           _writeCommand(0x70 | (_contrast & 0x0F)); // Set Contrast 0 1 1 1 C3, C2, C1, C0 (Instr Set 1)
00708                            
00709 //          _icon_power = 0x04;                       // Icon off, Booster on (Instr Set 1)
00710           _icon_power = 0x0C;                       // Icon on, Booster on (Instr Set 1)          
00711                                                     // Saved to allow contrast change at later time
00712           _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03));   // Set Power, Icon and Contrast, 0 1 0 1 Ion Bon C5 C4 (Instr Set 1)
00713           wait_ms(10);            // Wait 10ms to ensure powered up
00714 
00715           _writeCommand(0x68 | (LCD_SSD1_RAB & 0x07));  // Set Voltagefollower 0 1 1 0 Don = 1, Ampl ratio Rab2, Rab1, Rab0 = 1 1 0  (Instr Set 1)
00716           wait_ms(10);            // Wait 10ms to ensure powered up
00717 
00718           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
00719                                                     // Select Extended Instruction Set 1
00720           _writeCommand(0x10);                      // Shift/Scroll enable, 0 0 0 1 DS4/HS4 DS3/HS3 DS2/HS2 DS1/HS1  (Ext Instr Set 1)
00721 
00722 
00723           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
00724                                                     // Select Std Instr set, Select IS=0
00725          
00726           break; // case SSD1803 Controller
00727 
00728           
00729       // Note1: The PCF21XX family of controllers has several types that dont have an onboard voltage generator for V-LCD.
00730       //        You must supply this LCD voltage externally and not try to enable VGen. 
00731       // Note2: The early versions of PCF2116 controllers (eg PCF2116C) can not generate sufficiently negative voltage for the LCD at a VDD of 3V3. 
00732       //        You must supply this voltage externally and not enable VGen or you must use a higher VDD (e.g. 5V) and enable VGen.
00733       //        More recent versions of the controller (eg PCF2116K) have an improved VGen that will work with 3V3.
00734       // Note3: See datasheet, PCF2116 and other types provide a V0 pin to control the LCD contrast voltage that is provided by VGen. This pins allows 
00735       //        contrast control similar to that of pin 3 on the standard 14pin LCD module connector.
00736       //        You can disable VGen by connecting Vo to VDD. VLCD will then be used directly as LCD voltage.
00737       // Note4: PCF2113 and PCF2119 are different wrt to VLCD generator! There is no V0 pin. The contrast voltage is software controlled by setting the VA and VB registers.
00738       //        Vgen is automatically switched off when the contrast voltage VA or VB is set to 0x00. Note that certain limits apply to allowed values for VA and VB.                    
00739       // Note5: See datasheet, members of the PCF21XX family support different numbers of rows/columns. Not all can support 3 or 4 rows.
00740       // Note6: See datasheet, the PCF21XX-C and PCF21XX-K use a non-standard character set. This may result is strange looking text when not corrected..
00741 
00742       case PCF2103_3V3:
00743           // PCF2103 controller: No Voltage generator for VLCD, VDD=3V3..5V, VLCD input controls contrast voltage.                 
00744           // Initialise Display configuration
00745           switch (_type) {
00746             case LCD24x1:                    
00747               _function = 0x00;       //FUNCTION SET 0 0 1 DL=0 4-bit, 0, M=0 1-line/24 chars display mode, 0, H=0 
00748                                       //Note: 4 bit mode is ignored for I2C mode
00749               break;  
00750 
00751 //            case LCD12x1D:            //Special mode for PCF21XX, Only top line used
00752             case LCD12x2:
00753               _function = 0x04;       //FUNCTION SET 0 0 1 DL=0 4-bit, 0, M=1 2-line/12 chars display mode, 0, H=0
00754                                       //Note: 4 bit mode is ignored for I2C mode
00755               break;  
00756               
00757             default:
00758               error("Error: LCD Controller type does not support this Display type\n\r"); 
00759               break;  
00760             
00761           } // switch type    
00762 
00763           _writeCommand(0x20 | _function | 0x01);          // Set function, Select Instr Set = 1              
00764           wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00765 
00766 // Note: Display from GA628 shows 12 chars. This is actually the right half of a 24x1 display. The commons have been connected in reverse order.
00767           _writeCommand(0x05);                             // Display Conf Set         0000 0, 1, P=0, Q=1               (Instr. Set 1)
00768                                                         
00769           _writeCommand(0x02);                             // Screen Config            0000 001, L=0  (Instr. Set 1)
00770           _writeCommand(0x08);                             // ICON Conf                0000 1, IM=0 (Char mode), IB=0 (no Icon blink), 0 (Instr. Set 1) 
00771 
00772           _writeCommand(0x20 | _function);                 // Set function, Select Instr Set = 0             
00773           
00774 #if(0)
00775           // Select CG RAM
00776           _writeCommand(0x40); //Set CG-RAM address, 8 sequential locations needed per UDC
00777           // Store UDC/Icon pattern: 
00778           //   3 x 8 rows x 5 bits = 120 bits for Normal pattern (UDC 0..2) and
00779           //   3 x 8 rows x 5 bits = 120 bits for Blink pattern (UDC 4..6) 
00780           for (int i=0; i<(8 * 8); i++) {
00781 //            _writeData(0x1F);  // All On
00782             _writeData(0x00);  // All Off            
00783           }
00784 #endif
00785           break; // case PCF2103_3V3 Controller
00786 
00787       case PCF2113_3V3:
00788           // PCF2113 controller: Initialise Voltage booster for VLCD. VDD=3V3. VA and VB control contrast.
00789           // Initialise Display configuration
00790           switch (_type) {
00791 //            case LCD12x1:                                
00792 //              _function = 0x02;       // FUNCTION SET 0 0 1 DL=0 4 bit, 0, M=0 1-line/12 chars display mode, SL=1, IS=0
00793                                       // Note: 4 bit mode is ignored for I2C mode
00794             case LCD24x1:                    
00795               _function = 0x00;       // FUNCTION SET 0 0 1 DL=0 4 bit, 0, M=0 1-line/24 chars display mode, SL=0, IS=0            
00796                                       // Note: 4 bit mode is ignored for I2C mode
00797               break;  
00798 
00799             case LCD12x2:                    
00800               _function = 0x04;       // FUNCTION SET 0 0 1 DL=0 4 bit, 0, M=1 2-line/12 chars display mode, SL=0, IS=0            
00801               break;  
00802              
00803             default:
00804               error("Error: LCD Controller type does not support this Display type\n\r"); 
00805               break;  
00806                          
00807           } // switch type    
00808 
00809           // Init special features
00810           _writeCommand(0x20 | _function | 0x01);          // Set function, Select Instr Set = 1              
00811 
00812           _writeCommand(0x04);                             // Display Conf Set         0000 0, 1, P=0, Q=0               (Instr. Set 1)
00813           _writeCommand(0x10);                             // Temp Compensation Set    0001 0, 0, TC1=0, TC2=0           (Instr. Set 1)
00814 //          _writeCommand(0x42);                             // HV GEN                   0100 S1=1, S2=0 (2x multiplier)   (Instr. Set 1)
00815           _writeCommand(0x40 | (LCD_PCF2_S12 & 0x03));     // HV Gen                   0100 S1=1, S2=0 (2x multiplier)   (Instr. Set 1)
00816           
00817           _contrast = LCD_PCF2_CONTRAST;              
00818           _writeCommand(0x80 | 0x00 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)  1, V=0, VA=contrast
00819           _writeCommand(0x80 | 0x40 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)  1, V=1, VB=contrast
00820           wait_ms(10);            // Wait 10ms to ensure powered up
00821           
00822           _writeCommand(0x02);                             // Screen Config            0000 001, L=0  (Instr. Set 1)
00823           _writeCommand(0x08);                             // ICON Conf                0000 1, IM=0 (Char mode), IB=0 (no icon blink) DM=0 (no direct mode) (Instr. Set 1) 
00824 
00825           _writeCommand(0x20 | _function);                 // Set function, Select Instr Set = 0             
00826 
00827           break; // case PCF2113_3V3 Controller
00828 
00829 
00830 //      case PCF2113_5V:
00831           // PCF2113 controller: No Voltage generator for VLCD. VDD=5V. Contrast voltage controlled by VA or VB.
00832 //@TODO                            
00833 
00834 
00835       case PCF2116_3V3:
00836           // PCF2116 controller: Voltage generator for VLCD. VDD=5V. V0 controls contrast voltage.                 
00837           // Initialise Display configuration
00838           switch (_type) {
00839 //            case LCD12x1:
00840 //            case LCD12x2:                                                                            
00841             case LCD24x1:                    
00842               _writeCommand(0x22);    //FUNCTION SET 0 0 1 DL=0 4-bit, N=0/M=0 1-line/24 chars display mode, G=1 Vgen on, 0 
00843                                       //Note: 4 bit mode is ignored for I2C mode
00844               wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00845               break;  
00846 
00847             case LCD12x3D:            // Special mode for KS0078 and PCF21XX                            
00848             case LCD12x3D1:           // Special mode for PCF21XX                     
00849             case LCD12x4D:            // Special mode for PCF21XX:
00850               _writeCommand(0x2E);    //FUNCTION SET 0 0 1 DL=0 4-bit, N=1/M=1 4-line/12 chars display mode, G=1 VGen on, 0                               
00851                                       //Note: 4 bit mode is ignored for I2C mode              
00852               wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00853               break;  
00854 
00855             case LCD24x2:
00856               _writeCommand(0x2A);    //FUNCTION SET 0 0 1 DL=0 4-bit, N=1/M=0 2-line/24 chars display mode, G=1 VGen on, 0
00857                                       //Note: 4 bit mode is ignored for I2C mode
00858               wait_ms(10);            // Wait 10ms to ensure powered up   
00859               break;  
00860               
00861             default:
00862               error("Error: LCD Controller type does not support this Display type\n\r"); 
00863               break;  
00864             
00865           } // switch type    
00866 
00867           break; // case PCF2116_3V3 Controller
00868 
00869 
00870 //Experimental for cellphone 3-line display, SA=0x74, No Ack supported, Character set C or K, DL = 8 bit, N=0,M=1 (reserved mode !!), external VLCD -2V5
00871 //@TODO                            
00872       case PCF2116_5V:
00873           // PCF2116 controller: No Voltage generator for VLCD. VDD=5V. V0 controls contrast voltage.                           
00874           // Initialise Display configuration
00875           switch (_type) {
00876 //            case LCD12x1:
00877 //            case LCD12x2:                                                                            
00878 //            case LCD24x1:                    
00879 //              _writeCommand(0x20);    //FUNCTION SET 0 0 1 DL=0 4-bit, N=0/M=0 1-line/24 chars display mode, G=0 no Vgen, 0 
00880                                       //Note: 4 bit mode is ignored for I2C mode
00881 //              wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00882 //              break;  
00883 
00884             case LCD12x3D:            // Special mode for KS0078 and PCF21XX                            
00885             case LCD12x3D1:           // Special mode for PCF21XX                     
00886             case LCD12x4D:            // Special mode for PCF21XX:
00887 //              _writeCommand(0x34);    //FUNCTION SET 8 bit, N=0/M=1 4-line/12 chars display mode      OK
00888 //              _writeCommand(0x24);    //FUNCTION SET 4 bit, N=0/M=1 4-line/12 chars display mode      OK                                            
00889               _writeCommand(0x2C);    //FUNCTION SET 0 0 1 DL=0 4-bit, N=1/M=1 4-line/12 chars display mode, G=0 no Vgen, 0  OK       
00890                                       //Note: 4 bit mode is ignored for I2C mode              
00891               wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00892               break;  
00893 
00894 //            case LCD24x2:
00895 //              _writeCommand(0x28);    //FUNCTION SET 4 bit, N=1/M=0 2-line/24 chars display mode
00896                                       //Note: 4 bit mode is ignored for I2C mode
00897 //              wait_ms(10);            // Wait 10ms to ensure powered up   
00898 //              break;  
00899               
00900             default:
00901               error("Error: LCD Controller type does not support this Display type\n\r"); 
00902               break;  
00903             
00904           } // switch type    
00905 
00906           break; // case PCF2116_5V Controller
00907 
00908       case PCF2119_3V3:
00909       case PCF2119R_3V3:
00910           // PCF2119 controller: Initialise Voltage booster for VLCD. VDD=3V3. VA and VB control contrast.
00911           // Note1: See datasheet, the PCF2119 supports icons and provides separate constrast control for Icons and characters.
00912           // Note2: Vgen is switched off when the contrast voltage VA or VB is set to 0x00.
00913                   
00914 //POR or Hardware Reset should be applied
00915           wait_ms(10);            // Wait 10ms to ensure powered up   
00916 
00917           // Initialise Display configuration
00918           switch (_type) {
00919             case LCD8x1:
00920 //            case LCD12x1:
00921             case LCD16x1:           
00922               _function = 0x02;       // FUNCTION SET 0 0 1 DL=0 4-bit, 0 , M=0 1-line/16 chars display mode, SL=1
00923                                       // Note: 4 bit mode is ignored for I2C mode
00924               break;  
00925             
00926             case LCD24x1:                    
00927 //            case LCD32x1:                                
00928               _function = 0x00;       // FUNCTION SET 0 0 1 DL=0 4-bit, 0 , M=0 1-line/32 chars display mode, SL=0
00929                                       // Note: 4 bit mode is ignored for I2C mode
00930               break;  
00931 
00932             case LCD8x2:
00933 //            case LCD12x2:            
00934             case LCD16x2:
00935               _function = 0x04;       // FUNCTION SET 0 0 1 DL=0 4-bit, 0, M=1 2-line/16 chars display mode, SL=0
00936                                       // Note: 4 bit mode is ignored for I2C mode
00937               break;  
00938              
00939             default:
00940               error("Error: LCD Controller type does not support this Display type\n\r"); 
00941               break;  
00942             
00943           } // switch type    
00944 
00945           // Init special features 
00946           _writeCommand(0x20 | _function | 0x01);           // Set function, Select Instruction Set = 1              
00947 
00948 //          _writeCommand(0x04);    // DISP CONF SET (Instr. Set 1)   0000, 0, 1, P=0, Q=0 (IC at Bottom)
00949 //          _writeCommand(0x05);    // Display Conf Set               0000, 0, 1, P=0, Q=1
00950 //          _writeCommand(0x06);    // Display Conf Set               0000, 0, 1, P=1, Q=0
00951           _writeCommand(0x07);    // Display Conf Set               0000, 0, 1, P=1, Q=1    (IC at Top)
00952 
00953           _writeCommand(0x10);    // TEMP CTRL SET (Instr. Set 1)   0001, 0, 0, TC1=0, TC2=0
00954 //          _writeCommand(0x42);    // HV GEN (Instr. Set 1)          0100, 0, 0, S1=1, S2=0 (2x multiplier)
00955           _writeCommand(0x40 | (LCD_PCF2_S12 & 0x03));      // HV GEN (Instr. Set 1)          0100, 0, 0, S1=1, S2=0 (2x multiplier)
00956 
00957           _contrast = LCD_PCF2_CONTRAST;              
00958           _writeCommand(0x80 | 0x00 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)    V=0, VA=contrast
00959           _writeCommand(0x80 | 0x40 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)    V=1, VB=contrast
00960           wait_ms(10);            // Wait 10ms to ensure powered up
00961           
00962           _writeCommand(0x02);    // SCRN CONF (Instr. Set 1)    L=0
00963           _writeCommand(0x08);    // ICON CONF (Instr. Set 1)    IM=0 (Char mode) IB=0 (no icon blink) DM=0 (no direct mode)
00964 
00965           _writeCommand(0x20 | _function);                  // Select Instruction Set = 0
00966 
00967           break; // case PCF2119_3V3 Controller
00968 
00969 //      case PCF2119_5V:
00970           // PCF2119 controller: No Voltage booster for VLCD. VDD=3V3. VA and VB control contrast.
00971           // Note1: See datasheet, the PCF2119 supports icons and provides separate constrast control for Icons and characters.
00972           // Note2: Vgen is switched off when the contrast voltage VA or VB is set to 0x00.                     
00973 //@TODO                            
00974 
00975       case WS0010:         
00976           // WS0010 OLED controller: Initialise DC/DC Voltage converter for LEDs
00977           // Note1: Identical to RS0010  
00978           // Note2: supports 1 or 2 lines (and 16x100 graphics)
00979           //        supports 4 fonts (English/Japanese (default), Western European-I, English/Russian, Western European-II)
00980                            // Cursor/Disp shift set 0001 SC RL  0 0
00981                            //
00982                            // Mode and Power set    0001 GC PWR 1 1                           
00983                            //  GC  = 0 (Graph Mode=1, Char Mode=0)             
00984                            //  PWR = 1 (DC/DC On/Off)
00985    
00986 //@Todo: This may be needed to enable a warm reboot
00987           //_writeCommand(0x13);   // Char mode, DC/DC off              
00988           //wait_ms(10);           // Wait 10ms to ensure powered down                  
00989           _writeCommand(0x17);   // Char mode, DC/DC on        
00990           wait_ms(10);           // Wait 10ms to ensure powered up        
00991 
00992           // Initialise Display configuration
00993           switch (_type) {                    
00994             case LCD8x1:         //8x1 is a regular 1 line display
00995             case LCD8x2B:        //8x2B is a special case of 16x1
00996 //            case LCD12x1:                                
00997             case LCD16x1:                                            
00998             case LCD24x1:
00999               _writeCommand(0x20); // Function set 001 DL N F FT1 FT0
01000                                    //  DL=0  (4 bits bus)             
01001                                    //   N=0  (1 line)
01002                                    //   F=0  (5x7 dots font)
01003                                    //  FT=00 (00 = Engl/Jap, 01 = WestEur1, 10 = Engl/Russian, 11 = WestEur2
01004               break;  
01005 
01006             case LCD12x3D:            // Special mode for KS0078 and PCF21XX                            
01007             case LCD12x3D1:           // Special mode for PCF21XX                     
01008             case LCD12x4D:            // Special mode for PCF21XX:
01009             case LCD16x3G:            // Special mode for ST7036            
01010             case LCD24x4D:            // Special mode for KS0078
01011               error("Error: LCD Controller type does not support this Display type\n\r"); 
01012               break;  
01013 
01014             default:
01015               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)       
01016               _writeCommand(0x28); // Function set 001 DL N F FT1 FT0
01017                                    //  DL=0  (4 bits bus)
01018                                    //   N=1  (2 lines)
01019                                    //   F=0  (5x7 dots font)
01020                                    //  FT=00 (00 = Engl/Jap, 01 = WestEur1, 10 = Engl/Russian, 11 = WestEur2
01021 
01022               break;
01023            } // switch type
01024            
01025            break; // case WS0010 Controller
01026 
01027 
01028       case US2066_3V3:
01029           // US2066/SSD1311 OLED controller, Initialise for VDD=3V3
01030           // Note: supports 1,2, 3 or 4 lines
01031 //      case USS2066_5V:
01032           // US2066 controller, VDD=5V
01033                     
01034           // Initialise Display configuration
01035           switch (_type) {
01036             case LCD8x1:         //8x1 is a regular 1 line display
01037             case LCD8x2B:        //8x2D is a special case of 16x1
01038 //            case LCD12x1:                                
01039             case LCD16x1:   
01040 //            case LCD20x1:                                                                         
01041               _function = 0x00;     //  Set function 0 0 1 X N DH RE(0) IS 
01042                                     //  Saved to allow switch between Instruction sets at later time
01043                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead
01044                                     //     N=0 1 Line / 3 Line
01045                                     //    DH=0 Double Height disable 
01046                                     //    IS=0
01047           
01048               _function_1 = 0x02;   // Set function, 0 0 1 X N BE RE(1) REV
01049                                     //  Saved to allow switch between Instruction sets at later time
01050                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                    
01051                                     //     N=0 1 Line / 3 Line
01052                                     //    BE=0 Blink Enable off, special feature of SSD1803, US2066
01053                                     //   REV=0 Reverse off, special feature of SSD1803, US2066            
01054                         
01055               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
01056                                     //    NW=0 1-Line LCD (N=0)
01057               break;  
01058 
01059             case LCD16x1C:
01060             case LCD8x2:
01061             case LCD16x2:
01062             case LCD20x2:            
01063               _function = 0x08;     //  Set function 0 0 1 X N DH RE(0) IS 
01064                                     //  Saved to allow switch between Instruction sets at later time
01065                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                                                        
01066                                     //     N=1 2 line / 4 Line
01067                                     //    DH=0 Double Height disable 
01068                                     //    IS=0
01069           
01070               _function_1 = 0x0A;   // Set function, 0 0 1 X N BE RE(1) REV
01071                                     //  Saved to allow switch between Instruction sets at later time
01072                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                                                        
01073                                     //     N=1 2 line / 4 Line
01074                                     //    BE=0 Blink Enable off, special feature of SSD1803, US2066
01075                                     //   REV=0 Reverse off, special feature of SSD1803, US2066            
01076                         
01077               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
01078                                     //    NW=0 2-Line LCD (N=1)
01079               break;                
01080 
01081             case LCD12x3D:          // Special mode for KS0078 and PCF21XX 
01082 //            case LCD12x3D1:           // Special mode for KS0078 and PCF21XX            
01083             case LCD16x3D:          // Special mode for KS0078, SSD1803 and US2066
01084 //            case LCD16x3D1:           // Special mode for SSD1803, US2066
01085 //            case LCD20x3D:            // Special mode for SSD1803, US2066
01086               _function = 0x00;     //  Set function 0 0 1 X N DH RE(0) IS 
01087                                     //  Saved to allow switch between Instruction sets at later time
01088                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                    
01089                                     //     N=0 1 Line / 3 Line
01090                                     //    DH=0 Double Height disable 
01091                                     //    IS=0
01092           
01093               _function_1 = 0x02;   // Set function, 0 0 1 X N BE RE(1) REV
01094                                     //  Saved to allow switch between Instruction sets at later time
01095                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                    
01096                                     //     N=0 1 Line / 3 Line
01097                                     //    BE=0 Blink Enable off, special feature of SSD1803, US2066
01098                                     //   REV=0 Reverse off, special feature of SSD1803, US2066            
01099                         
01100               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
01101                                     //    NW=1 3-Line LCD (N=0)
01102               break;  
01103 
01104             case LCD20x4D:          // Special mode for SSD1803, US2066
01105               _function = 0x08;     //  Set function 0 0 1 X N DH RE(0) IS 
01106                                     //  Saved to allow switch between Instruction sets at later time
01107                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead
01108                                     //     N=1 2 line / 4 Line
01109                                     //    DH=0 Double Height disable 
01110                                     //    IS=0
01111           
01112               _function_1 = 0x0A;   // Set function, 0 0 1 DL N BE RE(1) REV
01113                                     //  Saved to allow switch between Instruction sets at later time
01114                                     //    DL=0 bit is ignored for US2066. Uses hardwired pins instead                                    
01115                                     //     N=1 2 line / 4 Line
01116                                     //    BE=0 Blink Enable off, special feature of SSD1803, US2066
01117                                     //   REV=0 Reverse off, special feature of SSD1803, US2066            
01118                         
01119               _lines = 0x01;        // Ext function set 0 0 0 0 1 FW BW NW 
01120                                     //    NW=1 4-Line LCD (N=1)
01121               break;  
01122 
01123 //            case LCD24x1:                                                                         
01124 //            case LCD16x3G:          // Special mode for ST7036            
01125 //            case LCD24x4D:          // Special mode for KS0078
01126             default:            
01127               error("Error: LCD Controller type does not support this Display type\n\r"); 
01128               break;  
01129 
01130           } // switch type
01131 
01132           _writeCommand(0x00);                      // NOP, make sure to sync SPI
01133 
01134           // init special features 
01135           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
01136                                                     // Select Extended Instruction Set
01137 
01138           _writeCommand(0x71);                      // Function Select A: 0 1 1 1 0 0 0 1 (Ext Instr Set)
01139           _writeData(0x00);                         // Disable Internal VDD
01140 
01141           _writeCommand(0x79);                      // Function Select OLED:  0 1 1 1 1 0 0 1 (Ext Instr Set)
01142 
01143           _writeCommand(0xD5);                      // Display Clock Divide Ratio: 1 1 0 1 0 1 0 1 (Ext Instr Set, OLED Instr Set)
01144           _writeCommand(0x70);                      // Display Clock Divide Ratio value: 0 1 1 1 0 0 0 0 (Ext Instr Set, OLED Instr Set)
01145                     
01146           _writeCommand(0x78);                      // Function Disable OLED: 0 1 1 1 1 0 0 0 (Ext Instr Set)
01147           
01148 //          _writeCommand(0x06);                      // Set ext entry mode, 0 0 0 0 0 1 BDC=1 COM1-32, BDS=0 SEG100-1    "Bottom View" (Ext Instr Set)
01149           _writeCommand(0x05);                      // Set ext entry mode, 0 0 0 0 0 1 BDC=0 COM32-1, BDS=1 SEG1-100    "Top View" (Ext Instr Set)          
01150          
01151           _writeCommand(0x08 | _lines);             // Set ext function 0 0 0 0 1 FW BW NW 1,2,3 or 4 lines (Ext Instr Set)
01152 
01153 //          _writeCommand(0x1C);                      // Double Height, 0 0 0 1 UD2=1, UD1=1, X, DH'=0 (Ext Instr Set)
01154 //                                                    // Default
01155 
01156           _writeCommand(0x72);                      // Function Select B: 0 1 1 1 0 0 1 0 (Ext Instr Set)
01157           _writeData(0x01);                         // Select ROM A (CGRAM 8, CGROM 248)
01158 
01159           _writeCommand(0x79);                      // Function Select OLED:  0 1 1 1 1 0 0 1 (Ext Instr Set)
01160 
01161           _writeCommand(0xDA);                      // Set Segm Pins Config:  1 1 0 1 1 0 1 0 (Ext Instr Set, OLED)
01162           _writeCommand(0x10);                      // Set Segm Pins Config value: Altern Odd/Even, Disable Remap (Ext Instr Set, OLED)
01163 
01164           _writeCommand(0xDC);                      // Function Select C: 1 1 0 1 1 1 0 0 (Ext Instr Set, OLED)
01165 //          _writeCommand(0x00);                      // Set internal VSL, GPIO pin HiZ (always read low)
01166           _writeCommand(0x80);                      // Set external VSL, GPIO pin HiZ (always read low)
01167 
01168           _contrast = LCD_US20_CONTRAST;
01169           _writeCommand(0x81);                      // Set Contrast Control: 1 0 0 0 0 0 0 1 (Ext Instr Set, OLED)
01170           _writeCommand((_contrast << 2) | 0x03);   // Set Contrast Value: 8 bits, use 6 bits for compatibility 
01171 
01172           _writeCommand(0xD9);                      // Set Phase Length: 1 1 0 1 1 0 0 1 (Ext Instr Set, OLED)
01173           _writeCommand(0xF1);                      // Set Phase Length Value: 
01174 
01175           _writeCommand(0xDB);                      // Set VCOMH Deselect Lvl: 1 1 0 1 1 0 1 1 (Ext Instr Set, OLED)
01176           _writeCommand(0x30);                      // Set VCOMH Deselect Value: 0.83 x VCC
01177 
01178           wait_ms(10);            // Wait 10ms to ensure powered up
01179 
01180 //Test Fade/Blinking. Hard Blink on/off, No fade in/out ??
01181 //          _writeCommand(0x23);                      // Set (Ext Instr Set, OLED)
01182 //          _writeCommand(0x3F);                      // Set interval 128 frames
01183 //End Test Blinking
01184 
01185           _writeCommand(0x78);                      // Function Disable OLED: 0 1 1 1 1 0 0 0 (Ext Instr Set)
01186           
01187           _writeCommand(0x20 | _function | 0x01);   // Set function, 0 0 1 X N DH RE(0) IS=1 Select Instruction Set 1
01188                                                     // Select Std Instr set, Select IS=1  
01189 
01190           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
01191                                                     // Select Ext Instr Set, IS=1
01192           _writeCommand(0x10);                      // Shift/Scroll enable, 0 0 0 1 DS4/HS4 DS3/HS3 DS2/HS2 DS1/HS1  (Ext Instr Set, IS=1)
01193 
01194           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
01195                                                     // Select Std Instr set, Select IS=0        
01196           break; // case US2066/SSD1311 Controller
01197 
01198       //not yet tested on hardware
01199       case PT6314 :
01200           // Initialise Display configuration
01201           switch (_type) {
01202             case LCD8x1:         //8x1 is a regular 1 line display
01203             case LCD8x2B:        //8x2B is a special case of 16x1
01204 //            case LCD12x1:                                
01205             case LCD16x1:                                            
01206             case LCD20x1:                                                        
01207             case LCD24x1:
01208               _function = 0x00;    // Function set 001 DL N X BR1 BR0
01209                                    //  DL=0 (4 bits bus)
01210                                    //  Note: 4 bit mode is ignored for native SPI and I2C devices                                                                                 
01211                                    //  N=0 (1 line)
01212                                    //  X
01213                                    //  BR1=0 (2 significant bits for brightness
01214                                    //  BR0=0 
01215                                    //           0x0 = 100%
01216                                    //           0x1 =  75%
01217                                    //           0x2 =  50%
01218                                    //           0x3 =  25%                
01219 
01220               break;                                
01221                                                   
01222             // All other valid LCD types are initialised as 2 Line displays
01223             case LCD8x2:  
01224             case LCD16x2:  
01225             case LCD20x2:
01226             case LCD24x2:
01227               _function = 0x08;    // Function set 001 DL N X BR1 BR2
01228                                    //  DL=0 (4 bits bus)
01229                                    //  Note: 4 bit mode is ignored for native SPI and I2C devices                                 
01230                                    //  N=1 (2 lines)
01231                                    //  X
01232                                    //  BR1=0 (2 significant bits for brightness
01233                                    //  BR0=0 
01234               break;
01235               
01236             default:            
01237               error("Error: LCD Controller type does not support this Display type\n\r"); 
01238               break;               
01239           } // switch type
01240            
01241           _contrast = LCD_PT63_CONTRAST;
01242           _writeCommand(0x20 | _function | ((~_contrast) >> 4));        // Invert and shift to use 2 MSBs     
01243           break; // case PT6314 Controller (VFD)
01244 
01245 
01246       case HD66712:
01247           // Initialise Display configuration
01248           switch (_type) {
01249             case LCD8x1:         //8x1 is a regular 1 line display
01250             case LCD12x1:                                
01251             case LCD16x1:                                            
01252             case LCD20x1:
01253             case LCD24x1:
01254 //            case LCD32x1:        // EXT pin is High, extension driver needed
01255               _function  = 0x02;    // Function set 001 DL N RE(0) - - (Std Regs)
01256                                     //   DL=0  (4 bits bus)             
01257                                     //    N=0  (1-line mode, N=1 2-line mode)
01258                                     //   RE=0  (Dis. Extended Regs, special mode for HD66712)
01259                                     //   
01260                                     
01261               _function_1 = 0x04;   // Function set 001 DL N RE(1) BE LP (Ext Regs)
01262                                     //   DL=0  (4 bits bus)             
01263                                     //    N=0  (1-line mode, N=1 2-line mode)
01264                                     //   RE=1  (Ena Extended Regs; special mode for HD66712)
01265                                     //   BE=0  (Blink Enable, CG/SEG RAM; special mode for HD66712)                                
01266                                     //   LP=0  (LP=1 Low power mode, LP=0 Normal; special mode for HD66712)
01267 
01268               _function_x = 0x00;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
01269                                     //    NW=0  (1,2 line), NW=1 (4 Line, special mode for HD66712)                                
01270               break;                                
01271 
01272 //            case LCD12x3D:         // Special mode for KS0073, KS0078, PCF21XX and HD66712
01273 //            case LCD12x3D1:        // Special mode for KS0073, KS0078, PCF21XX and HD66712
01274             case LCD12x4D:         // Special mode for KS0073, KS0078, PCF21XX and HD66712
01275 //            case LCD16x3D:         // Special mode for KS0073, KS0078 and HD66712
01276 //            case LCD16x4D:         // Special mode for KS0073, KS0078 and HD66712            
01277             case LCD20x4D:         // Special mode for KS0073, KS0078 and HD66712            
01278               _function  = 0x02;    // Function set 001 DL N RE(0) - - (Std Regs)
01279                                     //   DL=0  (4 bits bus)             
01280                                     //    N=0  (1-line mode, N=1 2-line mode)
01281                                     //   RE=0  (Dis. Extended Regs, special mode for HD66712)
01282                                     //   
01283                                     
01284               _function_1 = 0x04;   // Function set 001 DL N RE(1) BE LP (Ext Regs)
01285                                     //   DL=0  (4 bits bus)             
01286                                     //    N=0  (1-line mode, N=1 2-line mode)
01287                                     //   RE=1  (Ena Extended Regs; special mode for HD66712)
01288                                     //   BE=0  (Blink Enable, CG/SEG RAM; special mode for HD66712)                                
01289                                     //   LP=0  (LP=1 Low power mode, LP=0 Normal; special mode for HD66712)
01290 
01291               _function_x = 0x01;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
01292                                     //    NW=0  (1,2 line), NW=1 (4 Line, special mode for HD66712)                                
01293               break;                                
01294 
01295             case LCD16x3G:            // Special mode for ST7036                        
01296 //            case LCD24x3D:         // Special mode for KS0078
01297 //            case LCD24x3D1:        // Special mode for KS0078
01298             case LCD24x4D:         // Special mode for KS0078
01299               error("Error: LCD Controller type does not support this Display type\n\r"); 
01300               break;  
01301 
01302             default:
01303               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)            
01304               _function  = 0x0A;    // Function set 001 DL N RE(0) - - (Std Regs)
01305                                     //   DL=0  (4 bits bus)             
01306                                     //    N=1  (2-line mode), N=0 (1-line mode)
01307                                     //   RE=0  (Dis. Extended Regs, special mode for HD66712)
01308                                     
01309               _function_1 = 0x0C;   // Function set 001 DL N RE(1) BE LP (Ext Regs)
01310                                     //   DL=0  (4 bits bus)             
01311                                     //    N=1  (2 line mode), N=0 (1-line mode)
01312                                     //   RE=1  (Ena Extended Regs, special mode for HD66712)
01313                                     //   BE=0  (Blink Enable, CG/SEG RAM, special mode for HD66712)
01314                                     //   LP=0  (LP=1 Low power mode, LP=0 Normal)
01315 
01316               _function_x = 0x00;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
01317                                     //   NW=0  (1,2 line), NW=1 (4 Line, special mode for HD66712)
01318               break;
01319           } // switch type
01320 
01321           // init special features
01322           _writeCommand(0x20 | _function_1);// Function set 001 DL N RE(1) BE LP (Ext Regs)
01323                                            //   DL=0 (4 bits bus), DL=1 (8 bits mode)            
01324                                            //    N=0 (1 line mode), N=1 (2 line mode)
01325                                            //   RE=1 (Ena Extended Regs, special mode for HD66712)
01326                                            //   BE=0 (Blink Enable/Disable, CG/SEG RAM, special mode for HD66712)                                
01327                                            //   LP=0  (LP=1 Low power mode, LP=0 Normal)                                                                                                                                
01328 
01329           _writeCommand(0x08 | _function_x); // Ext Function set 0000 1 FW BW NW (Ext Regs)
01330                                            //   FW=0  (5-dot font, special mode for HD66712)
01331                                            //   BW=0  (Cur BW invert disable, special mode for HD66712)
01332                                            //   NW=0  (1,2 Line), NW=1 (4 line, special mode for HD66712)                                
01333 
01334           _writeCommand(0x10);             // Scroll/Shift set 0001 HS4 HS3 HS2 HS1 (Ext Regs)
01335                                            //   Dotscroll/Display shift enable (Special mode for HD66712)
01336 
01337           _writeCommand(0x80);             // Scroll Quantity set 1 0 HDS5 HDS4 HDS3 HDS2 HDS1 HDS0 (Ext Regs)
01338                                            //   Scroll quantity (Special mode for HD66712)
01339 
01340           _writeCommand(0x20 | _function); // Function set 001 DL N RE(0) DH REV (Std Regs)
01341                                            //   DL=0  (4 bits bus), DL=1 (8 bits mode)             
01342                                            //    N=0  (1 line mode), N=1 (2 line mode)
01343                                            //   RE=0  (Dis. Extended Regs, special mode for HD66712)
01344                                            //   DH=1  (Disp shift enable/disable, special mode for HD66712)
01345                                            //   REV=0 (Reverse/Normal, special mode for HD66712)
01346           break; // case HD66712 Controller
01347 
01348       case SPLC792A_3V3:      
01349           // SPLC792A controller: Initialise Voltage booster for VLCD. VDD=3V3
01350           // Note very similar to ST7032
01351       
01352           // Initialise Display configuration
01353           switch (_type) {
01354             case LCD8x1:         //8x1 is a regular 1 line display
01355             case LCD8x2B:        //8x2B is a special case of 16x1
01356 //            case LCD12x1:                                
01357             case LCD16x1:                                            
01358 //            case LCD20x1:                    
01359             case LCD24x1:
01360               _function = 0x00;       // FUNCTION SET 0 0 1 DL=0 (4 bit), N=0 (1-line display mode), F=0 (5*7dot), 0, IS
01361                                       // Note: 4 bit mode is ignored for native SPI and I2C devices
01362                                       // Saved to allow switch between Instruction sets at later time
01363               break;  
01364 
01365             case LCD12x3D:            // Special mode for KS0078 and PCF21XX
01366             case LCD12x3D1:           // Special mode for KS0078 and PCF21XX
01367             case LCD12x4D:            // Special mode for KS0078 and PCF21XX
01368             case LCD16x3G:            // Special mode for ST7036                        
01369             case LCD24x4D:            // Special mode for KS0078
01370               error("Error: LCD Controller type does not support this Display type\n\r"); 
01371               break;  
01372 
01373             default:
01374               // All other LCD types are initialised as 2 Line displays        
01375               _function = 0x08;       // FUNCTION SET 0 0 1 DL=0 (4 bit), N=1 (2-line display mode), F=0 (5*7dot), 0, IS              
01376                                       // Note: 4 bit mode is ignored for native SPI and I2C devices
01377                                       // Saved to allow switch between Instruction sets at later time
01378               break;                                                                        
01379           } // switch type    
01380                                      
01381           // init special features 
01382           _writeCommand(0x20 | _function | 0x01);           // Set function,  0 0 1 DL N F 0 IS=1 Select Instr Set = 1              
01383 
01384 //SPLC792A Does not support Bias and Internal Osc register
01385 //          _writeCommand(0x1C);                              // Internal OSC frequency adjustment Framefreq=183HZ, Bias will be 1/4 (Instr Set=1)
01386 
01387           _contrast = LCD_SPLC792A_CONTRAST;              
01388           _writeCommand(0x70 | (_contrast & 0x0F));         // Set Contrast Low bits, 0 1 1 1 C3 C2 C1 C0 (IS=1)
01389 
01390 
01391 //          _icon_power = 0x04;                               // Icon display off (Bit3=0), Booster circuit is turned on (Bit2=1) (IS=1)
01392           _icon_power = 0x0C;                               // Icon display on (Bit3=1), Booster circuit is turned on (Bit2=1)  (IS=1)
01393                                                             // Note: Booster circuit always on for SPLC792A, Bit2 is dont care
01394                                                             // Saved to allow contrast change at later time
01395 
01396           _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03));  // Set Icon, Booster and Contrast High bits, 0 1 0 1 Ion Bon C5 C4 (IS=1)
01397           wait_ms(10);            // Wait 10ms to ensure powered up
01398           
01399           _writeCommand(0x68 | (LCD_SPLC792A_RAB & 0x07));  // Voltage follower, 0 1 1 0 FOn=1, Ampl ratio Rab2=1, Rab1=0, Rab0=0  (IS=1)
01400                                                             // Note: Follower circuit always on for SPLC792A, Bit3 is dont care          
01401           wait_ms(10);            // Wait 10ms to ensure powered up
01402           
01403           _writeCommand(0x20 | _function);                  // Select Instruction Set = 0
01404 
01405           break; // case SPLC792A_3V3 Controller
01406           
01407         case ST7066_ACM:                                                // ST7066 4/8 bit, I2C on ACM1602 using a PIC        
01408         default:
01409           // Devices fully compatible to HD44780 that do not use any DC/DC Voltage converters but external VLCD, no icons etc
01410 
01411           // Initialise Display configuration
01412           switch (_type) {
01413             case LCD8x1:         //8x1 is a regular 1 line display
01414             case LCD8x2B:        //8x2B is a special case of 16x1
01415 //            case LCD12x1:                                
01416             case LCD16x1:                                            
01417 //            case LCD20x1:                                                        
01418             case LCD24x1:
01419 //            case LCD40x1:            
01420               _function = 0x00;    // Function set 001 DL N F - -
01421                                    //  DL=0 (4 bits bus)             
01422                                    //   N=0 (1 line)
01423                                    //   F=0 (5x7 dots font)
01424               break;                                
01425                                                   
01426             case LCD12x3D:            // Special mode for KS0078 and PCF21XX                            
01427             case LCD12x3D1:           // Special mode for KS0078 and PCF21XX                     
01428             case LCD12x4D:            // Special mode for KS0078 and PCF21XX:
01429             case LCD16x3D:            // Special mode for KS0078
01430 //            case LCD16x3D1:           // Special mode for KS0078
01431 //            case LCD24x3D:            // Special mode for KS0078
01432 //            case LCD24x3D1:           // Special mode for KS0078            
01433             case LCD24x4D:            // Special mode for KS0078
01434               error("Error: LCD Controller type does not support this Display type\n\r"); 
01435               break;  
01436 
01437             // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)
01438             default:
01439               _function = 0x08;    // Function set 001 DL N F - -
01440                                    //  DL=0 (4 bits bus)
01441                                    //  Note: 4 bit mode is ignored for native SPI and I2C devices                                 
01442                                    //   N=1 (2 lines)
01443                                    //   F=0 (5x7 dots font, only option for 2 line display)
01444                                    //    -  (Don't care)
01445               break;
01446           } // switch type
01447 
01448           _writeCommand(0x20 | _function);                         
01449           break; // case default Controller
01450           
01451     } // switch Controller specific initialisations    
01452 
01453     // Controller general initialisations                                          
01454 //    _writeCommand(0x01); // Clear Display and set cursor to 0
01455 //    wait_ms(10);         // The CLS command takes 1.64 ms.
01456 //                         // Since we are not using the Busy flag, Lets be safe and take 10 ms  
01457 
01458     _writeCommand(0x02); // Cursor Home, DDRAM Address to Origin
01459     wait_ms(10);         // The Return Home command takes 1.64 ms.
01460                          // Since we are not using the Busy flag, Lets be safe and take 10 ms      
01461 
01462     _writeCommand(0x06); // Entry Mode 0000 0 1 I/D S 
01463                          //   Cursor Direction and Display Shift
01464                          //   I/D=1 (Cur incr)
01465                          //     S=0 (No display shift)                        
01466 
01467     _writeCommand(0x14); // Cursor or Display shift 0001 S/C R/L x x 
01468                          //   S/C=0 Cursor moves
01469                          //   R/L=1 Right
01470                          // 
01471 
01472 //    _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
01473 //                         //   Display On, Cursor Off, Blink Off   
01474 
01475 //    setCursor(CurOff_BlkOff);     
01476     setCursor(CurOn_BlkOff);        
01477     setMode(DispOn);     
01478 }
01479 
01480 
01481 /** Clear the screen, Cursor home. 
01482   * Note: The whole display is initialised to charcode 0x20, which may not be a 'space' on some controllers with a
01483   *       different fontset such as the PCF2116C or PCF2119R. In this case you should fill the display with 'spaces'.
01484   */
01485 void TextLCD_Base::cls() {
01486 
01487 #if (LCD_TWO_CTRL == 1)
01488   // Select and configure second LCD controller when needed
01489   if(_type==LCD40x4) {
01490     _ctrl_idx=_LCDCtrl_1; // Select 2nd controller
01491 
01492     // Second LCD controller Cursor always Off
01493     _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
01494 
01495     // Second LCD controller Clearscreen
01496     _writeCommand(0x01);  // cls, and set cursor to 0    
01497     wait_ms(20);          // The CLS command takes 1.64 ms.
01498                           // Since we are not using the Busy flag, Lets be safe and take 10 ms
01499   
01500     _ctrl_idx=_LCDCtrl_0; // Select primary controller
01501   }
01502 
01503   
01504   // Primary LCD controller Clearscreen
01505   _writeCommand(0x01);    // cls, and set cursor to 0
01506   wait_ms(20);            // The CLS command takes 1.64 ms.
01507                           // Since we are not using the Busy flag, Lets be safe and take 10 ms
01508 
01509   // Restore cursormode on primary LCD controller when needed
01510   if(_type==LCD40x4) {
01511     _setCursorAndDisplayMode(_currentMode,_currentCursor);     
01512   }
01513 
01514 #else
01515   // Support only one LCD controller
01516   _writeCommand(0x01);    // cls, and set cursor to 0
01517   wait_ms(20);            // The CLS command takes 1.64 ms.
01518                           // Since we are not using the Busy flag, Lets be safe and take 10 ms
01519 #endif
01520                    
01521   setAddress(0, 0);  // Reset Cursor location
01522                      // Note: This is needed because some displays (eg PCF21XX) don't use line 0 in the '3 Line' mode.   
01523 }
01524 
01525 /** Locate cursor to a screen column and row
01526   *
01527   * @param column  The horizontal position from the left, indexed from 0
01528   * @param row     The vertical position from the top, indexed from 0
01529   */ 
01530 void TextLCD_Base::locate(int column, int row) {
01531     
01532    // setAddress() does all the heavy lifting:
01533    //   check column and row sanity, 
01534    //   switch controllers for LCD40x4 if needed
01535    //   switch cursor for LCD40x4 if needed
01536    //   set the new memory address to show cursor at correct location
01537    setAddress(column, row);      
01538 }
01539    
01540 
01541 /** Write a single character (Stream implementation)
01542   */
01543 int TextLCD_Base::_putc(int value) {
01544   int addr;
01545     
01546     if (value == '\n') {
01547       //No character to write
01548       
01549       //Update Cursor      
01550       _column = 0;
01551       _row++;
01552       if (_row >= rows()) {
01553         _row = 0;
01554       }      
01555     }
01556     else {
01557       //Character to write
01558 
01559 #if (LCD_DEF_FONT == 1)   //Default HD44780 font
01560       _writeData(value);
01561 #elif (LCD_C_FONT == 1) || (LCD_R_FONT == 1) //PCF21xxC or PCF21xxR font
01562       _writeData(ASCII_2_LCD(value));
01563 #elif (LCD_UTF8_FONT == 1) // UTF8 2 byte font (eg Cyrillic)
01564 //      value = UTF_2_LCD(value, utf_seq_rec_first_cyr, utf_seq_recode_cyr, &utf_rnd_recode_cyr[0][0]);      
01565       value = UTF_2_LCD(value);            
01566       if (value >= 0) {
01567         _writeData(value);
01568         
01569         // Only increment cursor when there is something to write
01570         //   Continue below to closing bracket...
01571 #else
01572       _writeData('?'); //Oops, no font defined
01573 #endif
01574 
01575       //Update Cursor
01576       _column++;
01577       if (_column >= columns()) {
01578         _column = 0;
01579         _row++;
01580         if (_row >= rows()) {
01581           _row = 0;
01582         }
01583       }
01584       
01585 #if (LCD_DEF_FONT == 1)   //Default HD44780 font
01586 
01587 #elif (LCD_C_FONT == 1) || (LCD_R_FONT == 1) //PCF21xxC or PCF21xxR font
01588 
01589 #elif (LCD_UTF8_FONT == 1) //UTF8 2 byte font (eg Cyrillic) 
01590         //   Continue code above to close bracket...  
01591       } // if (value >= 0) {..
01592 #else             
01593 
01594 #endif
01595 
01596     } //else
01597 
01598     //Set next memoryaddress, make sure cursor blinks at next location
01599     addr = getAddress(_column, _row);
01600     _writeCommand(0x80 | addr);
01601             
01602     return value;
01603 }
01604 
01605 
01606 // get a single character (Stream implementation)
01607 int TextLCD_Base::_getc() {
01608     return -1;
01609 }
01610 
01611 
01612 #if ((LCD_C_FONT == 1) || (LCD_R_FONT == 1)) //PCF21xxC or PCF21xxR font
01613 /** Convert ASCII character code to the LCD fonttable code
01614   *
01615   * @param c The character to write to the display
01616   * @return The character code for the specific fonttable of the controller
01617   */
01618 int TextLCD_Base::ASCII_2_LCD (int c) {
01619     
01620 //LCD_C_F0 is default for HD44780 and compatible series
01621 //    if (_font == LCD_C_F0) return c;
01622 
01623 //LCD_C_FC for PCF21XXC series    
01624 //LCD_C_FR for PCF21XXR series    
01625 //Used code from Suga koubou library for PCF2119K and PCF2119R
01626     if (((c >= ' ') && (c <= '?')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))) {
01627         c |= 0x80;
01628     } else if (c >= 0xF0 && c <= 0xFF) {
01629         c &= 0x0F;
01630     }
01631     return c;
01632 }
01633 #endif
01634 
01635 #if(LCD_UTF8_FONT == 1)
01636 
01637 /** Convert UTF8 2-byte character code to the LCD fonttable code
01638   * @param c The character to write to the display
01639   * @return character code for the specific fonttable of the controller or -1 if UTF8 code is not yet complete or incorrect
01640   *
01641   * Orig by Andriy, Modified by WH
01642   * 
01643   * Note: The UTF8 decoding table for a specific controller is defined and selected in file TextLCD_UTF8.inc
01644   * The table is accessed in this UTF_2_LCD() method through
01645   *   #define UTF_FIRST, UTF_LAST, UTF_SEQ_REC_FIRST, UTF_SEQ_REC_LAST and 
01646   *   #define UTF_SEQ_RECODE and UTF_RND_RECODE
01647   */
01648 int TextLCD_Base::UTF_2_LCD (int c) {    
01649     int utf_code;
01650     int utf_low_byte;            // Low byte UTF8
01651     static int utf_hi_byte = 0;  // High byte UTF8
01652  
01653     if (c < 0x80) { // Regular ASCII code, no need to convert
01654       return c;
01655     }  
01656     else { // UTF8 handling, See wikipedia.org/wiki/UTF-8 and www.utf8-chartable.de
01657 //      printf("0x%X ", c);    
01658 
01659       if (c >= 0xC0) {           // First UTF8 byte should be formatted as 110b bbaa, Do sanity check
01660         utf_hi_byte = c & 0x1F;  // Mask out significant bits (0x1F) and save high byte
01661         return -1;               // Nothing to display as yet, wait for second UTF8 byte
01662       } 
01663  
01664       if (c <= 0xBF) {           // Second UTF8 byte should be formatted as 10aa aaaa, Do sanity check
01665         utf_low_byte = c & 0x3F; // Mask out significant bits (0x3F)
01666         
01667         // Compose UTF character code from UTF8 bytes. The UTF codes will be between U+0080 and U+07FF
01668         utf_code = (utf_hi_byte << 6) | utf_low_byte; // 00000bbb aaaaaaaa  
01669 //        printf("0x%4X ", utf_code);    
01670       
01671         // Sanity check on UTF codes
01672         // For example Cyrillic characters are UTF encoded between 0x0400 and 0x04FF        
01673         if ((utf_code < UTF_FIRST) || (utf_code > UTF_LAST)) {          
01674           return -1; // Invalid UTF8 code
01675         };
01676         
01677         //Map some specific UTF codes on a character in LCD fonttable using a special correcting lookup table
01678         for (char i=0; UTF_RND_RECODE[i][0]; i++) { // Step through table until endvalue 0 is found or until a match is found
01679           if (utf_code == UTF_RND_RECODE[i][0]) { // UTF8 code match is found
01680             c = UTF_RND_RECODE[1][1];
01681             return c; // found match in correcting random table
01682           }
01683         }
01684                  
01685         //Sanity check on table idx range 
01686         if ((utf_code < UTF_SEQ_REC_FIRST) || (utf_code > UTF_SEQ_REC_LAST)) {          
01687           return -1; // Invalid UTF8 code
01688         };
01689         
01690         //Map all other UTF codes on a character in LCD fonttable using a sequential lookup table
01691         c = UTF_SEQ_RECODE[utf_code - UTF_SEQ_REC_FIRST];       
01692         return c; // entry in sequential table        
01693       }
01694       else {
01695         return -1; // Invalid UTF8 code for second byte          
01696       }  
01697     } // End UTF8 handling
01698 }
01699 
01700 #endif
01701  
01702 
01703 #if(LCD_PRINTF != 1)
01704 /** Write a character to the LCD
01705   *
01706   * @param c The character to write to the display
01707   */
01708 int TextLCD_Base::putc(int c){
01709   return _putc(c);
01710 }  
01711 
01712 
01713 /** Write a raw string to the LCD
01714   *
01715   * @param string text, may be followed by variables to emulate formatting the string.
01716   *                     However, printf formatting is NOT supported and variables will be ignored! 
01717   */
01718 int TextLCD_Base::printf(const char* text, ...) {
01719   
01720   while (*text !=0) {
01721     _putc(*text);
01722     text++;
01723   }
01724   return 0;
01725 }
01726 #endif    
01727 
01728 
01729 // Write a nibble using the 4-bit interface
01730 void TextLCD_Base::_writeNibble(int value) {
01731 
01732 // Enable is Low
01733     this->_setEnable(true);        
01734     this->_setData(value);        // Low nibble of value on D4..D7
01735     wait_us(1); // Data setup time        
01736     this->_setEnable(false);    
01737     wait_us(1); // Datahold time
01738 // Enable is Low
01739 }
01740 
01741 // Write a byte using the 4-bit interface
01742 void TextLCD_Base::_writeByte(int value) {
01743 
01744 // Enable is Low
01745     this->_setEnable(true);          
01746     this->_setData(value >> 4);   // High nibble
01747     wait_us(1); // Data setup time    
01748     this->_setEnable(false);   
01749     wait_us(1); // Data hold time
01750     
01751     this->_setEnable(true);        
01752     this->_setData(value);        // Low nibble
01753     wait_us(1); // Data setup time        
01754     this->_setEnable(false);    
01755     wait_us(1); // Datahold time
01756 
01757 // Enable is Low
01758 }
01759 
01760 // Write a command byte to the LCD controller
01761 void TextLCD_Base::_writeCommand(int command) {
01762 
01763     this->_setRS(false);        
01764     wait_us(1);  // Data setup time for RS       
01765     
01766     this->_writeByte(command);   
01767     wait_us(40); // most instructions take 40us            
01768 }
01769 
01770 // Write a data byte to the LCD controller
01771 void TextLCD_Base::_writeData(int data) {
01772 
01773     this->_setRS(true);            
01774     wait_us(1);  // Data setup time for RS 
01775         
01776     this->_writeByte(data);
01777     wait_us(40); // data writes take 40us                
01778 }
01779 
01780 
01781 // This replaces the original _address() method.
01782 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
01783 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
01784 int TextLCD_Base::_address(int column, int row) {
01785   return 0x80 | getAddress(column, row);
01786 }
01787 
01788 
01789 // This is new method to return the memory address based on row, column and displaytype.
01790 //
01791 /** Return the memoryaddress of screen column and row location
01792    *
01793    * @param column  The horizontal position from the left, indexed from 0
01794    * @param row     The vertical position from the top, indexed from 0
01795    * @return        The memoryaddress of screen column and row location
01796    *
01797    */
01798 int TextLCD_Base::getAddress(int column, int row) {
01799 
01800     switch (_addr_mode) {
01801 
01802         case LCD_T_A:
01803           //Default addressing mode for 1, 2 and 4 rows (except 40x4)
01804           //The two available rows are split and stacked on top of eachother. Addressing for 3rd and 4th line continues where lines 1 and 2 were split.          
01805           //Displays top rows when less than four are used.          
01806           switch (row) {
01807             case 0:
01808               return 0x00 + column;
01809             case 1:
01810               return 0x40 + column;
01811             case 2:
01812               return 0x00 + _nr_cols + column;
01813             case 3:
01814               return 0x40 + _nr_cols + column;
01815             // Should never get here.
01816 //            default:            
01817 //              return 0x00;                    
01818             }
01819           
01820         case LCD_T_B:
01821           // LCD8x2B is a special layout of LCD16x1
01822           if (row==0) 
01823             return 0x00 + column;                        
01824           else   
01825 //            return _nr_cols + column;                                    
01826             return 0x08 + column;                        
01827 
01828         case LCD_T_C:
01829           // LCD16x1C is a special layout of LCD8x2
01830           // LCD32x1C is a special layout of LCD16x2                    
01831           // LCD40x1C is a special layout of LCD20x2          
01832 #if(0)
01833           if (column < 8) 
01834             return 0x00 + column;                        
01835           else   
01836             return 0x40 + (column - 8);                        
01837 #else
01838           if (column < (_nr_cols >> 1)) 
01839             return 0x00 + column;                        
01840           else   
01841             return 0x40 + (column - (_nr_cols >> 1));                        
01842 #endif
01843 
01844         case LCD_T_D:
01845           //Alternate addressing mode for 3 and 4 row displays (except 40x4). Used by PCF21XX, KS0073, KS0078, SSD1803
01846           //The 4 available rows start at a hardcoded address.                    
01847           //Displays top rows when less than four are used.
01848           switch (row) {
01849             case 0:
01850               return 0x00 + column;
01851             case 1:
01852               return 0x20 + column;
01853             case 2:
01854               return 0x40 + column;
01855             case 3:
01856               return 0x60 + column;
01857             // Should never get here.
01858 //            default:            
01859 //              return 0x00;                    
01860             }
01861 
01862         case LCD_T_D1:
01863           //Alternate addressing mode for 3 row displays. Used by PCF21XX, KS0073, KS0078, SSD1803
01864           //The 4 available rows start at a hardcoded address.                              
01865           //Skips top row of 4 row display and starts display at row 1
01866           switch (row) {
01867             case 0:
01868               return 0x20 + column;
01869             case 1:
01870               return 0x40 + column;
01871             case 2:
01872               return 0x60 + column;
01873             // Should never get here.
01874 //            default:            
01875 //              return 0x00;                    
01876             }
01877         
01878         case LCD_T_E:                
01879           // LCD40x4 is a special case since it has 2 controllers.
01880           // Each controller is configured as 40x2 (Type A)
01881           if (row<2) { 
01882             // Test to see if we need to switch between controllers  
01883             if (_ctrl_idx != _LCDCtrl_0) {
01884 
01885               // Second LCD controller Cursor Off
01886               _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);    
01887 
01888               // Select primary controller
01889               _ctrl_idx = _LCDCtrl_0;
01890 
01891               // Restore cursormode on primary LCD controller
01892               _setCursorAndDisplayMode(_currentMode, _currentCursor);    
01893             }           
01894             
01895             return 0x00 + (row * 0x40) + column;          
01896           }
01897           else {
01898 
01899             // Test to see if we need to switch between controllers  
01900             if (_ctrl_idx != _LCDCtrl_1) {
01901               // Primary LCD controller Cursor Off
01902               _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);    
01903 
01904               // Select secondary controller
01905               _ctrl_idx = _LCDCtrl_1;
01906 
01907               // Restore cursormode on secondary LCD controller
01908               _setCursorAndDisplayMode(_currentMode, _currentCursor);    
01909             }           
01910                                    
01911             return 0x00 + ((row-2) * 0x40) + column;          
01912           } 
01913             
01914         case LCD_T_F:
01915           //Alternate addressing mode for 3 row displays.
01916           //The first half of 3rd row continues from 1st row, the second half continues from 2nd row.                              
01917           switch (row) {
01918             case 0:
01919               return 0x00 + column;
01920             case 1:
01921               return 0x40 + column;
01922             case 2:
01923               if (column < (_nr_cols >> 1)) // check first or second half of line
01924                 return (0x00 + _nr_cols + column);                        
01925               else   
01926                 return (0x40 + _nr_cols + (column - (_nr_cols >> 1)));                        
01927             // Should never get here.
01928 //            default:            
01929 //              return 0x00;                    
01930           }
01931 
01932         case LCD_T_G:
01933           //Alternate addressing mode for 3 row displays. Used by ST7036
01934           switch (row) {
01935             case 0:
01936               return 0x00 + column;
01937             case 1:
01938               return 0x10 + column;
01939             case 2:
01940               return 0x20 + column;
01941             // Should never get here.
01942 //            default:            
01943 //              return 0x00;                    
01944             }
01945 
01946         // Should never get here.
01947         default:            
01948             return 0x00;        
01949 
01950     } // switch _addr_mode
01951 }
01952 
01953 
01954 /** Set the memoryaddress of screen column and row location
01955   *
01956   * @param column  The horizontal position from the left, indexed from 0
01957   * @param row     The vertical position from the top, indexed from 0
01958   */
01959 void TextLCD_Base::setAddress(int column, int row) {
01960    
01961 // Sanity Check column
01962     if (column < 0) {
01963       _column = 0;
01964     }
01965     else if (column >= _nr_cols) {
01966       _column = _nr_cols - 1;
01967     } else _column = column;
01968     
01969 // Sanity Check row
01970     if (row < 0) {
01971       _row = 0;
01972     }
01973     else if (row >= _nr_rows) {
01974       _row = _nr_rows - 1;
01975     } else _row = row;
01976     
01977     
01978 // Compute the memory address
01979 // For LCD40x4:  switch controllers if needed
01980 //               switch cursor if needed
01981     int addr = getAddress(_column, _row);
01982     
01983     _writeCommand(0x80 | addr);
01984 }
01985 
01986 
01987 /** Return the number of columns
01988   *
01989   * @return  The number of columns
01990   *
01991   * Note: some configurations are commented out because they have not yet been tested due to lack of hardware     
01992   */   
01993 int TextLCD_Base::columns() {
01994     
01995   // Columns encoded in b7..b0
01996   //return (_type & 0xFF);          
01997   return _nr_cols;           
01998 }
01999 
02000 /** Return the number of rows
02001   *
02002   * @return  The number of rows
02003   *
02004   * Note: some configurations are commented out because they have not yet been tested due to lack of hardware     
02005   */
02006 int TextLCD_Base::rows() {
02007 
02008   // Rows encoded in b15..b8  
02009   //return ((_type >> 8) & 0xFF); 
02010   return _nr_rows;          
02011 }
02012 
02013 /** Set the Cursormode
02014   *
02015   * @param cursorMode  The Cursor mode (CurOff_BlkOff, CurOn_BlkOff, CurOff_BlkOn, CurOn_BlkOn)
02016   */
02017 void TextLCD_Base::setCursor(LCDCursor cursorMode) { 
02018 
02019   // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on
02020   _currentCursor = cursorMode;
02021     
02022   // Configure only current LCD controller
02023   _setCursorAndDisplayMode(_currentMode, _currentCursor);    
02024 }
02025 
02026 /** Set the Displaymode
02027   *
02028   * @param displayMode The Display mode (DispOff, DispOn)
02029   */
02030 void TextLCD_Base::setMode(LCDMode displayMode) { 
02031 
02032   // Save new displayMode, needed when 2 controllers are in use or when cursor is changed
02033   _currentMode = displayMode;
02034 
02035 #if (LCD_TWO_CTRL == 1)    
02036   // Select and configure second LCD controller when needed
02037   if(_type==LCD40x4) {
02038     if (_ctrl_idx==_LCDCtrl_0) {      
02039       // Configure primary LCD controller
02040       _setCursorAndDisplayMode(_currentMode, _currentCursor);
02041 
02042       // Select 2nd controller
02043       _ctrl_idx=_LCDCtrl_1;
02044   
02045       // Configure secondary LCD controller    
02046       _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
02047 
02048       // Restore current controller
02049       _ctrl_idx=_LCDCtrl_0;       
02050     }
02051     else {
02052       // Select primary controller
02053       _ctrl_idx=_LCDCtrl_0;
02054     
02055       // Configure primary LCD controller
02056       _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
02057        
02058       // Restore current controller
02059       _ctrl_idx=_LCDCtrl_1;
02060 
02061       // Configure secondary LCD controller    
02062       _setCursorAndDisplayMode(_currentMode, _currentCursor);
02063     }
02064   }
02065   else {
02066     // Configure primary LCD controller
02067     _setCursorAndDisplayMode(_currentMode, _currentCursor);
02068   }       
02069 #else
02070   // Support only one LCD controller
02071   _setCursorAndDisplayMode(_currentMode, _currentCursor);
02072 
02073 #endif  
02074 }
02075 
02076 /** Low level method to restore the cursortype and display mode for current controller
02077   */     
02078 void TextLCD_Base::_setCursorAndDisplayMode(LCDMode displayMode, LCDCursor cursorType) {    
02079 
02080   // Configure current LCD controller   
02081   switch (_ctrl) {
02082     case ST7070: 
02083       //ST7070 does not support Cursorblink. The P bit selects the font instead !   
02084       _writeCommand(0x08 | displayMode | (cursorType & 0x02));    
02085       break;
02086     default:      
02087       _writeCommand(0x08 | displayMode | cursorType);
02088       break;
02089   } //switch      
02090 }
02091 
02092 /** Set the Backlight mode
02093   *
02094   *  @param backlightMode The Backlight mode (LightOff, LightOn)
02095   */
02096 void TextLCD_Base::setBacklight(LCDBacklight backlightMode) {
02097 
02098 #if (BACKLIGHT_INV==0)      
02099     // Positive Backlight control pin logic
02100     if (backlightMode == LightOn) {
02101       this->_setBL(true);     
02102     }
02103     else {
02104       this->_setBL(false);    
02105     }
02106 #else
02107     // Inverted Backlight control pin logic
02108     if (backlightMode == LightOn) {
02109       this->_setBL(false);    
02110     }
02111     else {
02112       this->_setBL(true);           
02113     }
02114 #endif    
02115 } 
02116 
02117 /** Set User Defined Characters
02118   *
02119   * @param unsigned char c   The Index of the UDC (0..7) for HD44780 or clones and (0..15) for some more advanced controllers 
02120   * @param char *udc_data    The bitpatterns for the UDC (8 bytes of 5 significant bits for bitpattern and 3 bits for blinkmode (advanced types))     
02121   */
02122 void TextLCD_Base::setUDC(unsigned char c, char *udc_data) {
02123 
02124 #if (LCD_TWO_CTRL == 1)
02125   // Select and configure second LCD controller when needed
02126   if(_type==LCD40x4) {
02127     _LCDCtrl_Idx current_ctrl_idx = _ctrl_idx; // Temp save current controller
02128    
02129     // Select primary controller     
02130     _ctrl_idx=_LCDCtrl_0;
02131     
02132     // Configure primary LCD controller
02133     _setUDC(c, udc_data);
02134 
02135     // Select 2nd controller
02136     _ctrl_idx=_LCDCtrl_1;
02137   
02138     // Configure secondary LCD controller    
02139     _setUDC(c, udc_data);
02140 
02141     // Restore current controller
02142     _ctrl_idx=current_ctrl_idx;       
02143   }
02144   else {
02145     // Configure primary LCD controller
02146     _setUDC(c, udc_data); 
02147   }   
02148 #else
02149   // Support only one LCD controller
02150   _setUDC(c, udc_data); 
02151 #endif  
02152 }
02153 
02154 /** Low level method to store user defined characters for current controller
02155   *
02156   * @param unsigned char c   The Index of the UDC (0..7) for HD44780 clones and (0..15) for some more advanced controllers 
02157   * @param char *udc_data    The bitpatterns for the UDC (8 bytes of 5 significant bits for bitpattern and 3 bits for blinkmode (advanced types))       
02158   */     
02159 void TextLCD_Base::_setUDC(unsigned char c, char *udc_data) {
02160   
02161   switch (_ctrl) {
02162     case PCF2103_3V3 : // Some UDCs may be used for Icons                  
02163     case PCF2113_3V3 : // Some UDCs may be used for Icons                      
02164     case PCF2116_3V3 :          
02165     case PCF2116_5V  :              
02166     case PCF2119_3V3 : // Some UDCs may be used for Icons
02167     case PCF2119R_3V3: // Some UDCs may be used for Icons                 
02168       c = c & 0x0F; // mask down to valid range
02169       break;
02170 
02171     default:     
02172       c = c & 0x07; // mask down to valid range    
02173       break;  
02174   } //switch _ctrl
02175 
02176   // Select DD RAM for current LCD controller
02177   // This is needed to correctly set Bit 6 of the addresspointer for controllers that support 16 UDCs
02178   _writeCommand(0x80 | ((c << 3) & 0x40)) ;  
02179     
02180   // Select CG RAM for current LCD controller
02181   _writeCommand(0x40 | ((c << 3) & 0x3F)); //Set CG-RAM address, (note that Bit 6 is retained and can not be set by this command !)
02182                                            //8 sequential locations needed per UDC
02183   // Store UDC pattern 
02184   for (int i=0; i<8; i++) {
02185     _writeData(*udc_data++);
02186   }
02187    
02188   //Select DD RAM again for current LCD controller and restore the addresspointer
02189   int addr = getAddress(_column, _row);
02190   _writeCommand(0x80 | addr);  
02191 }
02192 
02193 #if(LCD_BLINK == 1)
02194 /** Set UDC Blink and Icon blink
02195   * setUDCBlink method is supported by some compatible devices (eg SSD1803) 
02196   *
02197   * @param blinkMode The Blink mode (BlinkOff, BlinkOn)
02198   */
02199 void TextLCD_Base::setUDCBlink(LCDBlink blinkMode){
02200   // Blinking UDCs (and icons) are enabled when a specific controlbit (BE) is set.
02201   // The blinking pixels in the UDC and icons can be controlled by setting additional bits in the UDC or icon bitpattern.
02202   // UDCs are defined by an 8 byte bitpattern. The P0..P4 form the character pattern.
02203   //     P7 P6 P5 P4 P3 P2 P1 P0 
02204   // 0   B1 B0  x  0  1  1  1  0
02205   // 1   B1 B0  x  1  0  0  0  1
02206   //        .............
02207   // 7   B1 B0  x  1  0  0  0  1
02208   //
02209   // Bit 6 and Bit 7 in the pattern will control the blinking mode when Blink is enabled through BE. 
02210   //     B1 B0  Mode
02211   //      0  0  No Blinking in this row of the UDC
02212   //      0  1  Enabled pixels in P4 will blink
02213   //      1  x  Enabled pixels in P0..P4 will blink
02214   //
02215   // Note: the PCF2103 and PCF2113 use UDCs to set Icons 
02216   //   3 x 8 rows x 5 bits = 120 bits Icons for Normal pattern (UDC 0..2) and
02217   //   3 x 8 rows x 5 bits = 120 bits Icons for Blink pattern (UDC 4..6) 
02218   // Note: the PCF2119 uses UDCs to set Icons 
02219   //   4 x 8 rows x 5 bits = 160 bits Icons for Normal pattern (UDC 0..3) and
02220   //   4 x 8 rows x 5 bits = 160 bits Icons for Blink pattern (UDC 4..7) 
02221   switch (blinkMode) {
02222     case BlinkOn: 
02223       // Controllers that support UDC/Icon Blink  
02224       switch (_ctrl) {
02225         case KS0073 :
02226         case KS0078 :
02227         case HD66712 :                    
02228           _function_1 |= 0x02; // Enable UDC/Icon Blink        
02229           _writeCommand(0x20 | _function_1);        // Function set 0 0 1 DL N RE(1) BE 0/LP (Ext Regs)
02230 
02231           _writeCommand(0x20 | _function);          // Function set 0 0 1 DL N RE(0) DH REV (Std Regs)
02232           break; // case KS0073, KS0078, HD66712 Controller
02233     
02234         case US2066_3V3 :  
02235         case SSD1803_3V3 :  
02236           _function_1 |= 0x04; // Enable UDC/Icon Blink
02237           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
02238                                                     // Select Ext Instr Set
02239 
02240           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02241                                                     // Select Std Instr set, Select IS=0
02242           break; // case SSD1803, US2066
02243 
02244         case PCF2103_3V3 :  
02245         case PCF2113_3V3 :  
02246         case PCF2119_3V3 :                  
02247         case PCF2119R_3V3 :                          
02248           // Enable Icon Blink
02249           _writeCommand(0x20 | _function | 0x01);   // Set function, Select Instr Set = 1              
02250           _writeCommand(0x08 | 0x02);               // ICON Conf 0000 1, IM=0 (Char mode), IB=1 (Icon blink), 0 (Instr. Set 1) 
02251           _writeCommand(0x20 | _function);          // Set function, Select Instr Set = 0             
02252 
02253           break; 
02254        
02255         default:
02256           //Unsupported feature for other controllers        
02257           break; 
02258       } //switch _ctrl     
02259     
02260       break; // BlinkOn 
02261 
02262     case BlinkOff:
02263       // Controllers that support UDC Blink  
02264       switch (_ctrl) {
02265         case KS0073 :
02266         case KS0078 :
02267         case HD66712:
02268           _function_1 &= ~0x02; // Disable UDC/Icon Blink        
02269           _writeCommand(0x20 | _function_1);        // Function set 0 0 1 DL N RE(1) BE 0/LP (Ext Regs)
02270 
02271           _writeCommand(0x20 | _function);          // Function set 0 0 1 DL N RE(0) DH REV (Std Regs)
02272           break; // case KS0073, KS0078, HD66712 Controller
02273     
02274         case US2066_3V3 :  
02275         case SSD1803_3V3 :  
02276           _function_1 &= ~0x04; // Disable UDC/Icon Blink
02277           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
02278                                                     // Select Ext Instr Set
02279 
02280           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02281                                                     // Select Std Instr set, Select IS=0
02282           break; // case SSD1803, US2066          
02283  
02284         case PCF2103_3V3 :
02285         case PCF2113_3V3 : 
02286         case PCF2119_3V3 :
02287         case PCF2119R_3V3 :        
02288           // Disable Icon Blink
02289           _writeCommand(0x20 | _function | 0x01);   // Set function, Select Instr Set = 1              
02290           _writeCommand(0x08);                      // ICON Conf 0000 1, IM=0 (Char mode), IB=1 (Icon blink), 0 (Instr. Set 1) 
02291           _writeCommand(0x20 | _function);          // Set function, Select Instr Set = 0             
02292 
02293           break; 
02294        
02295         default:
02296           //Unsupported feature for other controllers        
02297           break; 
02298       } //switch _ctrl     
02299     
02300       break; //BlinkOff
02301       
02302     default:
02303       break;      
02304   } // blinkMode
02305   
02306 } // setUDCBlink()
02307 #endif
02308 
02309 #if(LCD_CONTRAST == 1)
02310 /** Set Contrast
02311   * setContrast method is supported by some compatible devices (eg ST7032i) that have onboard LCD voltage generation
02312   * Initial code for ST70XX imported from fork by JH1PJL
02313   *
02314   * @param unsigned char c   contrast data (6 significant bits, valid range 0..63, Value 0 will disable the Vgen)  
02315   * @return none
02316   */
02317 //@TODO Add support for 40x4 dual controller
02318 void TextLCD_Base::setContrast(unsigned char c) {
02319 
02320 // Function set mode stored during Init. Make sure we dont accidentally switch between 1-line and 2-line mode!
02321 // Icon/Booster mode stored during Init. Make sure we dont accidentally change this!
02322  
02323   _contrast = c & 0x3F; // Sanity check
02324   
02325   switch (_ctrl) {   
02326     case PCF2113_3V3 :  
02327     case PCF2119_3V3 :
02328     case PCF2119R_3V3 :    
02329        if (_contrast <  5) _contrast = 0;  // See datasheet. Sanity check for PCF2113/PCF2119
02330        if (_contrast > 55) _contrast = 55;
02331       
02332        _writeCommand(0x20 | _function | 0x01);               // Set function, Select Instruction Set = 1              
02333        _writeCommand(0x80 | 0x00 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)    V=0, VA=contrast
02334        _writeCommand(0x80 | 0x40 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)    V=1, VB=contrast
02335        _writeCommand(0x20 | _function);                      // Select Instruction Set = 0
02336        break;
02337         
02338     case ST7032_3V3 :  
02339     case ST7032_5V :      
02340     case ST7036_3V3 :      
02341 //    case ST7036_5V :          
02342     case SSD1803_3V3 :
02343     case SPLC792A_3V3 :  
02344       _writeCommand(0x20 | _function | 0x01);                        // Select Instruction Set = 1
02345       _writeCommand(0x70 | (_contrast & 0x0F));                      // Contrast Low bits
02346       _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03)); // Contrast High bits 
02347       _writeCommand(0x20 | _function);                               // Select Instruction Set = 0
02348       break;
02349 
02350     case US2066_3V3 :      
02351       _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
02352                                                 // Select Extended Instruction Set
02353 
02354       _writeCommand(0x79);                      // Function Select OLED:  0 1 1 1 1 0 0 1 (Ext Instr Set)
02355          
02356       _writeCommand(0x81);                      // Set Contrast Control: 1 0 0 0 0 0 0 1 (Ext Instr Set, OLED)
02357       _writeCommand((_contrast << 2) | 0x03);   // Set Contrast Value: 8 bits. Use 6 bits for compatibility    
02358       
02359       _writeCommand(0x78);                      // Function Disable OLED: 0 1 1 1 1 0 0 0 (Ext Instr Set)          
02360 
02361       _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02362                                                 // Select Std Instr set, Select IS=0
02363       break;
02364 
02365     //not yet tested on hardware
02366     case PT6314 :
02367       // Only 2 significant bits
02368       //   0x00 = 100%
02369       //   0x01 =  75%
02370       //   0x02 =  50%
02371       //   0x03 =  25%                
02372       _writeCommand(0x20 | _function | ((~_contrast) >> 4));        // Invert and shift to use 2 MSBs     
02373       break;
02374             
02375     default:  
02376       //Unsupported feature for other controllers
02377       break;               
02378   } // end switch     
02379 } // end setContrast()
02380 #endif
02381 
02382 #if(LCD_POWER == 1)
02383 /** Set Power
02384   * setPower method is supported by some compatible devices (eg SSD1803) that have power down modes
02385   *
02386   * @param bool powerOn  Power on/off   
02387   * @return none
02388   */
02389 //@TODO Add support for 40x4 dual controller  
02390 void TextLCD_Base::setPower(bool powerOn) {
02391   
02392   if (powerOn) {
02393     // Switch on  
02394     setMode(DispOn);       
02395 
02396     // Controllers that supports specific Power Down mode
02397     switch (_ctrl) {
02398     
02399 //    case PCF2113_3V3 :  
02400 //    case PCF2119_3V3 : 
02401 //    case PCF2119R_3V3 :     
02402 //    case ST7032_3V3 :  
02403 //@todo
02404 //    enable Booster Bon
02405 
02406       case WS0010:      
02407         _writeCommand(0x17);   // Char mode, DC/DC on        
02408         wait_ms(10);           // Wait 10ms to ensure powered up             
02409         break;
02410 
02411       case KS0073:        
02412       case KS0078:        
02413       case SSD1803_3V3 :      
02414 //      case SSD1803_5V :            
02415         _writeCommand(0x20 | _function_1);                             // Select Ext Instr Set
02416         _writeCommand(0x02);                                           // Power On
02417         _writeCommand(0x20 | _function);                               // Select Std Instr Set
02418         break;
02419                     
02420       default:  
02421         //Unsupported feature for other controllers
02422         break;              
02423     } // end switch  
02424   }  
02425   else {
02426     // Switch off        
02427     setMode(DispOff);       
02428 
02429     // Controllers that support specific Power Down mode
02430     switch (_ctrl) {
02431     
02432 //    case PCF2113_3V3 :  
02433 //    case PCF2119_3V3 : 
02434 //    case PCF2119R_3V3 :     
02435 //    case ST7032_3V3 :  
02436 //@todo
02437 //    disable Booster Bon
02438 
02439       case WS0010:      
02440         _writeCommand(0x13);   // Char mode, DC/DC off              
02441         break;
02442         
02443       case KS0073:
02444       case KS0078:
02445       case SSD1803_3V3 :      
02446 //      case SSD1803_5V :            
02447         _writeCommand(0x20 | _function_1);                             // Select Ext Instr Set
02448         _writeCommand(0x03);                                           // Power Down
02449         _writeCommand(0x20 | _function);                               // Select Std Instr Set
02450         break;
02451 
02452       default:  
02453         //Unsupported feature for other controllers
02454         break;              
02455     } // end switch  
02456   }
02457 } // end setPower()
02458 #endif
02459 
02460 #if(LCD_ORIENT == 1)
02461 /** Set Orient
02462   * setOrient method is supported by some compatible devices (eg SSD1803, US2066) that have top/bottom view modes
02463   *
02464   * @param LCDOrient orient Orientation 
02465   * @return none
02466   */
02467 void TextLCD_Base::setOrient(LCDOrient orient){
02468 
02469   switch (orient) {
02470        
02471     case Top:
02472       switch (_ctrl) {
02473         case PCF2103_3V3:              
02474         case PCF2116_3V3:        
02475         case PCF2116_5V:                
02476           _writeCommand(0x20 | _function | 0x01);          // Set function, Select Instr Set = 1              
02477           _writeCommand(0x05);                             // Display Conf Set         0000 0, 1, P=0, Q=1               (Instr. Set 1)
02478           _writeCommand(0x20 | _function);                 // Set function, Select Instr Set = 0             
02479           break;
02480 
02481         case PCF2119_3V3:   
02482         case PCF2119R_3V3:                         
02483           _writeCommand(0x20 | _function | 0x01);          // Set function, Select Instr Set = 1              
02484           _writeCommand(0x07);                             // Display Conf Set         0000 0, 1, P=1, Q=1               (Instr. Set 1)
02485           _writeCommand(0x20 | _function);                 // Set function, Select Instr Set = 0             
02486           break;
02487                                
02488         case SSD1803_3V3 :      
02489 //      case SSD1803_5V :
02490         case US2066_3V3 :      
02491           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02492                                                     // Select Extended Instruction Set
02493 //          _writeCommand(0x06);                      // Set ext entry mode, 0 0 0 0 0 1 BDC=1 COM1-32, BDS=0 SEG100-1    "Bottom View" (Ext Instr Set)
02494           _writeCommand(0x05);                      // Set ext entry mode, 0 0 0 0 0 1 BDC=0 COM32-1, BDS=1 SEG1-100    "Top View" (Ext Instr Set)          
02495 
02496           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02497                                                     // Select Std Instr set, Select IS=0       
02498           break;
02499 
02500         case ST7070:      
02501           _writeCommand(0x20 | _function | 0x04);   // Set function, 0 0 1 DL, N, EXT=1, x, x (Select Instr Set = 1)
02502 
02503           _writeCommand(0x40 | 0x00);               // COM/SEG directions 0 1 0 0 C1, C2, S1, S2  (Instr Set 1)
02504                                                     // C1=1: Com1-8 -> Com8-1;   C2=1: Com9-16 -> Com16-9
02505                                                     // S1=1: Seg1-40 -> Seg40-1; S2=1: Seg41-80 -> Seg80-41                                                    
02506           wait_ms(5);                               // Wait to ensure completion or ST7070 fails to set Top/Bottom after reset..
02507           
02508           _writeCommand(0x20 | _function);          // Set function, EXT=0 (Select Instr Set = 0)
02509         
02510           break; // case ST7070 Controller
02511           
02512         default:  
02513           //Unsupported feature for other controllers
02514           break;              
02515 
02516       } // end switch _ctrl     
02517       break; // end Top
02518                 
02519     case Bottom:
02520       switch (_ctrl) {
02521         case PCF2103_3V3:              
02522         case PCF2116_3V3:        
02523         case PCF2116_5V:                
02524           _writeCommand(0x20 | _function | 0x01);          // Set function, Select Instr Set = 1              
02525           _writeCommand(0x06);                             // Display Conf Set         0000 0, 1, P=1, Q=0               (Instr. Set 1)
02526           _writeCommand(0x20 | _function);                 // Set function, Select Instr Set = 0             
02527           break;
02528 
02529         case PCF2119_3V3:
02530         case PCF2119R_3V3 :                                 
02531           _writeCommand(0x20 | _function | 0x01);          // Set function, Select Instr Set = 1              
02532           _writeCommand(0x04);                             // Display Conf Set         0000 0, 1, P=0, Q=0               (Instr. Set 1)
02533           _writeCommand(0x20 | _function);                 // Set function, Select Instr Set = 0             
02534           break;
02535         
02536         case SSD1803_3V3 :      
02537 //      case SSD1803_5V :
02538         case US2066_3V3 :      
02539           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02540                                                     // Select Extended Instruction Set
02541           _writeCommand(0x06);                      // Set ext entry mode, 0 0 0 0 0 1 BDC=1 COM1-32, BDS=0 SEG100-1    "Bottom View" (Ext Instr Set)
02542 //          _writeCommand(0x05);                      // Set ext entry mode, 0 0 0 0 0 1 BDC=0 COM32-1, BDS=1 SEG1-100    "Top View" (Ext Instr Set)          
02543 
02544           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02545                                                     // Select Std Instr set, Select IS=0       
02546           break;
02547 
02548         case ST7070:
02549           //Note: this does not result in correct top/bottom view. 
02550           //The left and right half of each row are reversed and the addressing of both rows is also incorrect:
02551           //Top/bottomline when orientation is flipped:
02552           //  0x48...0x4F  0x40...0x47
02553           //  0x08...0x0F  0x00...0x07
02554           _writeCommand(0x20 | _function | 0x04);   // Set function, 0 0 1 DL N EXT=1 x x (Select Instr Set = 1)
02555 
02556           _writeCommand(0x40 | 0x0F);               // COM/SEG directions 0 1 0 0 C1, C2, S1, S2  (Instr Set 1)
02557                                                     // C1=1: Com1-8 -> Com8-1;   C2=1: Com9-16 -> Com16-9
02558                                                     // S1=1: Seg1-40 -> Seg40-1; S2=1: Seg41-80 -> Seg80-41                                                    
02559           wait_ms(5);                               // Wait to ensure completion or ST7070 fails to set Top/Bottom after reset..
02560           
02561           _writeCommand(0x20 | _function);          // Set function, EXT=0 (Select Instr Set = 0)
02562         
02563           break; // case ST7070 Controller
02564           
02565         default:  
02566           //Unsupported feature for other controllers
02567           break;              
02568 
02569       } // end switch _ctrl     
02570     
02571       break; // end Bottom
02572   } // end switch orient
02573 } // end setOrient()
02574 #endif
02575 
02576 #if(LCD_BIGFONT == 1)
02577 /** Set Big Font
02578   * setBigFont method is supported by some compatible devices (eg SSD1803, US2066) 
02579   *
02580   * @param lines  The selected Big Font lines (None, TopLine, CenterLine, BottomLine, TopBottomLine)
02581   *                                            Double height characters can be shown on lines 1+2, 2+3, 3+4 or 1+2 and 3+4
02582   *                                            Valid double height lines depend on the LCDs number of rows.
02583   */
02584 void TextLCD_Base::setBigFont(LCDBigFont lines) {
02585 
02586   switch (lines) {
02587     case None:
02588       switch (_ctrl) {
02589         case SSD1803_3V3 :      
02590         case US2066_3V3 :      
02591           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02592                                                     // Select Extended Instruction Set
02593           _writeCommand(0x1C);                      // Double Height, 0 0 0 1 UD2=1, UD1=1, X, DH'=0 (Ext Instr Set)
02594                                                     // Default
02595           _function = _function & ~0x04;            // Set function, 0 0 1 DL N DH=0 RE(0) IS=0 Select Instruction Set 0
02596           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02597                                                     // Select Std Instr set, Select IS=0        
02598           break; // end US2066      
02599 
02600         default:
02601           break; // end default      
02602       } // end switch _ctrl     
02603       break; // end None      
02604     
02605     case TopLine:
02606       if (_nr_rows < 2) return; //Sanity check  
02607 
02608       switch (_ctrl) {
02609         case SSD1803_3V3 :              
02610         case US2066_3V3 :      
02611           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02612                                                     // Select Extended Instruction Set
02613           _writeCommand(0x1C);                      // Double Height, 0 0 0 1 UD2=1, UD1=1, X, DH'=0 (Ext Instr Set)
02614                                                     // Default
02615           _function = _function | 0x04;             // Set function, 0 0 1 DL N DH=1 RE(0) IS=0 Select Instruction Set 0
02616           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02617                                                     // Select Std Instr set, Select IS=0        
02618           break; // end US2066, SSD1803      
02619 
02620         default:
02621           break; // end default      
02622       } // end switch _ctrl     
02623       break; // end TopLine              
02624 
02625     case CenterLine:
02626       if (_nr_rows != 4) return; //Sanity check  
02627           
02628       switch (_ctrl) {
02629         case SSD1803_3V3 :              
02630         case US2066_3V3 :      
02631           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02632                                                     // Select Extended Instruction Set
02633           _writeCommand(0x14);                      // Double Height, 0 0 0 1 UD2=0, UD1=1, X, DH'=0 (Ext Instr Set)
02634                                                     // Default
02635           _function = _function | 0x04;             // Set function, 0 0 1 DL N DH=1 RE(0) IS=0 Select Instruction Set 0
02636           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02637                                                     // Select Std Instr set, Select IS=0        
02638           break; // end US2066, SSD1803      
02639 
02640         default:
02641           break; // end default      
02642       } // end switch _ctrl        
02643       break; // end CenterLine              
02644 
02645     case BottomLine:
02646       if (_nr_rows < 3) return; //Sanity check  
02647           
02648       switch (_ctrl) {
02649         case SSD1803_3V3 :              
02650         case US2066_3V3 :      
02651           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02652                                                     // Select Extended Instruction Set
02653           if (_nr_rows == 3) {
02654             _writeCommand(0x14);                      // Double Height, 0 0 0 1 UD2=0, UD1=1, X, DH'=0 (Ext Instr Set)
02655           }  
02656           else {
02657             _writeCommand(0x10);                      // Double Height, 0 0 0 1 UD2=0, UD1=0, X, DH'=0 (Ext Instr Set)
02658           }  
02659           _function = _function | 0x04;             // Set function, 0 0 1 DL N DH=1 RE(0) IS=0 Select Instruction Set 0
02660           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02661                                                     // Select Std Instr set, Select IS=0        
02662           break; // end US2066, SSD1803      
02663 
02664         default:
02665           break; // end default      
02666       } // end switch _ctrl           
02667       break; // end BottomLine          
02668       
02669     case TopBottomLine:
02670       if (_nr_rows != 4) return; //Sanity check  
02671       
02672       switch (_ctrl) {
02673         case SSD1803_3V3 :        
02674         case US2066_3V3 :      
02675           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02676                                                     // Select Extended Instruction Set
02677           _writeCommand(0x18);                      // Double Height, 0 0 0 1 UD2=1, UD1=0, X, DH'=0 (Ext Instr Set)
02678                                                     // Default
02679           _function = _function | 0x04;             // Set function, 0 0 1 DL N DH=1 RE(0) IS=0 Select Instruction Set 0
02680           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
02681                                                     // Select Std Instr set, Select IS=0        
02682           break; // end US2066, SSD1803      
02683 
02684         default:
02685           break; // end default      
02686       } // end switch _ctrl           
02687       break; // end TopBottomLine          
02688 
02689   } // end switch lines
02690 
02691 } // end setBigFont()
02692 #endif
02693 
02694 
02695 #if (LCD_FONTSEL == 1)
02696 /** Set Font
02697   * setFont method is supported by some compatible devices (eg SSD1803, US2066, ST7070) 
02698   *
02699   * @param LCDFont font  The selected Font 
02700   * @return none 
02701   *
02702   * Note: most controllers support only one font and the hardware specific
02703   * fonttable is encoded as part of the controller type number (eg PCF21XXC or PCF21XXR).
02704   * Some controllers support multiple tables that can only be selected by logic levels on a few pins.
02705   * Some controllers also support runtime fontable switching through a specific instruction     
02706   */
02707 void TextLCD_Base::setFont(LCDFont font) {
02708     
02709   switch (font) {
02710     case Font_RA:  // UK/EU
02711       switch (_ctrl) {
02712         case SSD1803_3V3 :      
02713         case US2066_3V3 :      
02714           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02715                                                     // Select Extended Instruction Set
02716           _writeCommand(0x72);                      // ROM Select command, 0 1 1 1 0 0 1 0       (Ext Instr Set)
02717           _writeData(0x00);                         // ROM_0 Select data,  0 0 0 0 ROM2 ROM1 0 0 (Ext Instr Set)
02718           
02719           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS      (Std Instr Set)
02720 
02721           _font = font; // Save active font
02722           break; // end SSD1803, US2066      
02723 
02724         case ST7070: 
02725           //ST7070 does not support Cursorblink. The P bit selects the font instead !   
02726           _writeCommand(0x08 | _currentMode | (_currentCursor & 0x02));           
02727 
02728           _font = font; // Save active font          
02729           break; // end ST7070
02730 
02731         default:
02732           break; // end default      
02733       } // end switch _ctrl     
02734       break; // end Font_RA      
02735 
02736     case Font_RB:    // UK/CYR
02737       switch (_ctrl) {
02738         case SSD1803_3V3 :      
02739         case US2066_3V3 :      
02740           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02741                                                     // Select Extended Instruction Set
02742           _writeCommand(0x72);                      // ROM Select command, 0 1 1 1 0 0 1 0       (Ext Instr Set)
02743           _writeData(0x04);                         // ROM_0 Select data,  0 0 0 0 ROM2 ROM1 0 0 (Ext Instr Set)
02744           
02745           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS      (Std Instr Set)
02746 
02747           _font = font; // Save active font
02748           break; // end SSD1803, US2066      
02749 
02750         case ST7070: 
02751           //ST7070 does not support Cursorblink. The P bit selects the font instead !   
02752           _writeCommand(0x08 | _currentMode | (_currentCursor & 0x02) | 0x01);           
02753 
02754           _font = font; // Save active font
02755           break; // end ST7070
02756 
02757         default:
02758           break; // end default      
02759       } // end switch _ctrl     
02760       break; // end Font_RB      
02761 
02762     case Font_0:   //Font_O is pretty similar to ROM_C
02763     case Font_RC:  // UK/JAP  
02764       switch (_ctrl) {
02765         case SSD1803_3V3 :      
02766         case US2066_3V3 :      
02767           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
02768                                                     // Select Extended Instruction Set
02769           _writeCommand(0x72);                      // ROM Select command, 0 1 1 1 0 0 1 0       (Ext Instr Set)
02770           _writeData(0x08);                         // ROM_0 Select data,  0 0 0 0 ROM2 ROM1 0 0 (Ext Instr Set)
02771           
02772           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS      (Std Instr Set)
02773 
02774           _font = font; // Save active font
02775           break; // end SSD1803, US2066  
02776 
02777         default:
02778           break; // end default      
02779       } // end switch _ctrl     
02780       break; // end Font_RC      
02781   } // end switch font
02782   
02783   //SSD1803 seems to screw up cursor position after selecting new font. Restore to make sure...
02784   //Set next memoryaddress, make sure cursor blinks at next location
02785   int addr = getAddress(_column, _row);
02786   _writeCommand(0x80 | addr);
02787          
02788 }
02789 #endif
02790 
02791 
02792 #if(LCD_ICON==1)
02793 /** Set Icons
02794   *
02795   * @param unsigned char idx   The Index of the icon pattern (0..15) for KS0073 and similar controllers
02796   *                            and Index (0..31) for PCF2103 and similar controllers  
02797   * @param unsigned char data  The bitpattern for the icons (6 lsb for KS0073 bitpattern (5 lsb for KS0078) and 2 msb for blinkmode)       
02798   *                            The bitpattern for the PCF2103 icons is 5 lsb (UDC 0..2) and 5 lsb for blinkmode (UDC 4..6)         
02799   */
02800 void TextLCD_Base::setIcon(unsigned char idx, unsigned char data) {
02801   // Blinking icons are enabled when a specific controlbit (BE) is set.
02802   // The blinking pixels in the icons can be controlled by setting additional bits in the icon bitpattern.
02803   // Icons are defined by a byte bitpattern. The P0..P5 form the Icon pattern for KS0073, and P0..P4 for KS0078
02804   //     P7 P6 P5 P4 P3 P2 P1 P0 
02805   // 0   B1 B0  0  0  1  1  1  0
02806   // 1   B1 B0  1  1  0  0  0  1
02807   //        .............
02808   // 15  B1 B0  1  1  0  0  0  1
02809   //
02810   // Bit 6 and Bit 7 in the pattern will control the blinking mode when Blink is enabled through BE. 
02811   //     B1 B0  Mode
02812   //      0  0  No Blinking for this icon row
02813   //      0  1  Enabled pixels in P5 will blink
02814   //      1  x  Enabled pixels in P0..P5 will blink
02815   //
02816   // Note: the PCF2103 and PCF2113 use UDCs to set Icons 
02817   //   3 x 8 rows x 5 bits = 120 bits Icons for Normal pattern (UDC 0..2) and
02818   //   3 x 8 rows x 5 bits = 120 bits Icons for Blink pattern (UDC 4..6) 
02819   // Note: the PCF2119 uses UDCs to set Icons 
02820   //   4 x 8 rows x 5 bits = 160 bits Icons for Normal pattern (UDC 0..3) and
02821   //   4 x 8 rows x 5 bits = 160 bits Icons for Blink pattern (UDC 4..7) 
02822   
02823   switch (_ctrl) {
02824     case KS0073:
02825     case KS0078:    
02826        _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N RE(1) BE LP 
02827                                                  // Select Extended Instruction Set
02828        _writeCommand(0x40 | (idx & 0x0F));       // Set Icon Address, mask Address to valid range (Ext Instr Set)
02829 
02830        _writeData(data);                         // Set Icon pattern (Ext Instr Set)
02831 
02832        _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N RE(0) DH REV Select Instruction Set 0
02833                                                  // Select Std Instr set, Select IS=0        
02834        break; // end KS0073, KS0078
02835 
02836     case ST7032_3V3:
02837     case ST7032_5V:
02838     case SPLC792A_3V3:
02839        _writeCommand(0x20 | _function | 0x01);   // Set function,  0 0 1 DL N F 0 IS=1 Select Instr Set = 1              
02840        _writeCommand(0x40 | (idx & 0x0F));       // Set Icon Address, mask Address to valid range (Instr Set 1)
02841 
02842        _writeData(data & 0x1F);                  // Set Icon pattern, no blink support (Instr Set 1) 
02843 
02844        _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N RE(0) DH REV Select Instruction Set 0
02845                                                  // Select Std Instr set, Select IS=0        
02846        break; // end ST7032
02847 
02848     case ST7036_3V3:
02849     case ST7036_5V:
02850        _writeCommand(0x20 | _function | 0x01);   // Set function, 0 0 1 DL N DH IS2,IS1 = 01 (Select Instr Set = 1)    
02851        _writeCommand(0x40 | (idx & 0x0F));       // Set Icon Address, mask Address to valid range (Instr Set 1)
02852 
02853        _writeData(data & 0x1F);                  // Set Icon pattern, no blink support (Instr Set 1) 
02854 
02855        _writeCommand(0x20 | _function);          // Set function, IS2,IS1 = 00 (Select Instr Set = 0)    
02856                                                  // Select Std Instr set, Select IS=0        
02857        break; // end ST7036
02858 
02859     case SSD1803_3V3:                  
02860 //    case SSD1803_5V:                      
02861        _writeCommand(0x20 | _function | 0x01);   // Set function, 0 0 1 DL N DH RE(0) IS 
02862                                                  // Select Instruction Set 1
02863        _writeCommand(0x40 | (idx & 0x0F));       // Set Icon Address, mask Address to valid range (Instr Set = 1)
02864        _writeData(data);                         // Set Icon pattern (Instr Set = 1)
02865 
02866        _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS
02867                                                  // Select IS=0        
02868        break; // end SSD1803      
02869 
02870     case PCF2103_3V3:
02871     case PCF2113_3V3:    
02872     case PCF2119_3V3:
02873     case PCF2119R_3V3:                
02874        // Store UDC/Icon pattern for PCF2103 and PCF2113: 
02875        //   3 x 8 rows x 5 bits = 120 bits for Normal pattern (UDC 0..2) and
02876        //   3 x 8 rows x 5 bits = 120 bits for Blink pattern (UDC 4..6) 
02877        // Store UDC/Icon pattern for PCF2119: 
02878        //   4 x 8 rows x 5 bits = 160 bits for Normal pattern (UDC 0..3) and
02879        //   4 x 8 rows x 5 bits = 160 bits for Blink pattern (UDC 4..7)        
02880        _writeCommand(0x40 | (idx & 0x3F));       //Set CG-RAM address, 8 sequential locations needed per UDC
02881        _writeData(data);                         // Set Icon pattern (Instr Set = 1)
02882        break; // case PCF2103_3V3 Controller
02883                  
02884     default:
02885        break; // end default      
02886   } // end switch _ctrl           
02887   
02888   //Select DD RAM again for current LCD controller and restore the addresspointer
02889   int addr = getAddress(_column, _row);
02890   _writeCommand(0x80 | addr);  
02891          
02892 } // end setIcon()
02893 
02894 /** Clear Icons
02895   *
02896   * @param  none
02897   * @return none
02898   */
02899   //@TODO Add support for 40x4 dual controller    
02900 void TextLCD_Base::clrIcon() {
02901   // Icons are defined by a byte bitpattern. The P0..P5 form the Icon pattern for KS0073, and P0..P4 for KS0078
02902   //     P7 P6 P5 P4 P3 P2 P1 P0 
02903   // 0   B1 B0  0  0  0  0  0  0
02904   // 1   B1 B0  0  0  0  0  0  0
02905   //        .............
02906   // 15  B1 B0  0  0  0  0  0  0
02907   //
02908   // Bit 6 and Bit 7 in the pattern will control the blinking mode when Blink is enabled through BE. 
02909   //     B1 B0  Mode
02910   //      0  0  No Blinking for this icon row
02911   //      0  1  Enabled pixels in P5 will blink
02912   //      1  x  Enabled pixels in P0..P5 will blink
02913   //
02914   // Note: the PCF2103 and PCF2113 use UDCs to set Icons 
02915   //   3 x 8 rows x 5 bits = 120 bits Icons for Normal pattern (UDC 0..2) and
02916   //   3 x 8 rows x 5 bits = 120 bits Icons for Blink pattern (UDC 4..6)  
02917   // Note: the PCF2119 uses UDCs to set Icons 
02918   //   4 x 8 rows x 5 bits = 160 bits Icons for Normal pattern (UDC 0..3) and
02919   //   4 x 8 rows x 5 bits = 160 bits Icons for Blink pattern (UDC 4..7)  
02920   int idx;
02921   
02922   switch (_ctrl) {
02923     case KS0073:              
02924     case KS0078:                  
02925        _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N RE(1) BE LP 
02926                                                  // Select Extended Instruction Set
02927        for (idx=0; idx<16; idx++) { 
02928          _writeCommand(0x40 | idx);              // Set Icon Address, mask Address to valid range (Ext Instr Set)
02929          _writeData(0x00);                       // Clear Icon pattern (Ext Instr Set)
02930        }  
02931        _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N RE(0) DH REV Select Std Instruction Set
02932                                                  // Select Std Instr set        
02933        break; // end KS0073, KS0078      
02934 
02935     case ST7032_3V3:
02936     case ST7032_5V:
02937     case SPLC792A_3V3:
02938        _writeCommand(0x20 | _function | 0x01);   // Set function,  0 0 1 DL N F 0 IS=1 Select Instr Set = 1              
02939 
02940        for (idx=0; idx<16; idx++) { 
02941          _writeCommand(0x40 | idx);              // Set Icon Address, mask Address to valid range (Instr Set 1)
02942          _writeData(0x00);                       // Clear Icon pattern (Instr Set 1)
02943        }  
02944 
02945        _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N RE(0) DH REV Select Instruction Set 0
02946                                                  // Select Std Instr set, Select IS=0        
02947        break; // end ST7032
02948 
02949     case ST7036_3V3:
02950     case ST7036_5V:
02951        _writeCommand(0x20 | _function | 0x01);   // Set function, 0 0 1 DL N DH IS2,IS1 = 01 (Select Instr Set = 1)    
02952 
02953        for (idx=0; idx<16; idx++) { 
02954          _writeCommand(0x40 | idx);              // Set Icon Address, mask Address to valid range (Instr Set 1)
02955          _writeData(0x00);                       // Clear Icon pattern (Instr Set 1)
02956        }  
02957 
02958        _writeCommand(0x20 | _function);          // Set function, IS2,IS1 = 00 (Select Instr Set = 0)    
02959                                                  // Select Std Instr set, Select IS=0        
02960        break; // end ST7036
02961 
02962     case SSD1803_3V3:                  
02963 //    case SSD1803_5V:                      
02964        _writeCommand(0x20 | _function | 0x01);   // Set function, 0 0 1 DL N DH RE(0) IS 
02965                                                  // Select Instruction Set 1
02966        for (idx=0; idx<16; idx++) { 
02967          _writeCommand(0x40 | idx);              // Set Icon Address, mask Address to valid range (Ext Instr Set)
02968          _writeData(0x00);                       // Clear Icon pattern (Ext Instr Set)
02969        }  
02970        _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS
02971                                                  // Select IS=0        
02972        break; // end SSD1803      
02973 
02974      case PCF2103_3V3:
02975      case PCF2113_3V3:         
02976        // PCF2103 and PCF2113 use part of the UDC RAM to control Icons   
02977        // Select CG RAM
02978 
02979        _writeCommand(0x40 | (0 * 8)); //Set CG-RAM address, 8 sequential locations needed per UDC
02980        // Store UDC/Icon pattern: 
02981        //   3 x 8 rows x 5 bits = 120 bits for Normal pattern (UDC 0..2) and
02982        for (int i=0; i<(3 * 8); i++) {
02983 //       _writeData(0x1F);  // All On
02984          _writeData(0x00);  // All Off            
02985        }
02986 
02987        _writeCommand(0x40 | (4 * 8)); //Set CG-RAM address, 8 sequential locations needed per UDC
02988        //   3 x 8 rows x 5 bits = 120 bits for Blink pattern (UDC 4..6) 
02989        for (int i=0; i<(3 * 8); i++) {
02990 //       _writeData(0x1F);  // All On
02991          _writeData(0x00);  // All Off            
02992        }
02993        break; // case PCF2103_3V3 Controller
02994 
02995      case PCF2119_3V3:  
02996      case PCF2119R_3V3:
02997        // PCF2119 uses part of the UDC RAM to control Icons   
02998        // Select CG RAM
02999 
03000        _writeCommand(0x40 | (0 * 8)); //Set CG-RAM address, 8 sequential locations needed per UDC
03001        // Store UDC/Icon pattern: 
03002        //   4 x 8 rows x 5 bits = 160 bits for Normal pattern (UDC 0..3) and
03003        for (int i=0; i<(4 * 8); i++) {
03004 //       _writeData(0x1F);  // All On
03005          _writeData(0x00);  // All Off            
03006        }
03007 
03008        _writeCommand(0x40 | (4 * 8)); //Set CG-RAM address, 8 sequential locations needed per UDC
03009        //   4 x 8 rows x 5 bits = 160 bits for Blink pattern (UDC 4..7) 
03010        for (int i=0; i<(4 * 8); i++) {
03011 //       _writeData(0x1F);  // All On
03012          _writeData(0x00);  // All Off            
03013        }
03014        break; // case PCF2119_3V3 Controller
03015 
03016     default:
03017        break; // end default      
03018   } // end switch _ctrl           
03019   
03020   //Select DD RAM again for current LCD controller and restore the addresspointer
03021   int addr = getAddress(_column, _row);
03022   _writeCommand(0x80 | addr);
03023 } //end clrIcon()
03024 #endif
03025 
03026 #if(LCD_INVERT == 1)
03027 /** Set Invert
03028   * setInvert method is supported by some compatible devices (eg KS0073) to swap between black and white 
03029   *
03030   * @param bool invertOn  Invert on/off   
03031   * @return none
03032   */
03033 //@TODO Add support for 40x4 dual controller  
03034 void TextLCD_Base::setInvert(bool invertOn) {
03035   
03036   if (invertOn) {
03037     // Controllers that support Invert
03038     switch (_ctrl) {   
03039       case KS0073:        
03040       case KS0078:        
03041         _function = _function | 0x01;                                  // Enable Invert
03042         _writeCommand(0x20 | _function);                               // Activate Invert (Std Instr Set)
03043         break;
03044       case SSD1803_3V3 :      
03045 //      case SSD1803_5V :                 
03046       case US2066_3V3:
03047 //      case USS2066_5V:
03048         _function_1 = _function_1 | 0x01;                              // Enable Invert 
03049                                                                        // Set function, 0 0 1 DL N BE RE(1) REV  (SSD1803)
03050                                                                        // Set function, 0 0 1 X  N BE RE(1) REV  (US2066)    
03051         _writeCommand(0x20 | _function_1);                             // Activate Invert (Ext Instr Set)
03052         _writeCommand(0x20 | _function);                               // Return to Std Instr Set                            
03053         break;
03054       default:  
03055         //Unsupported feature for other controllers
03056         break;              
03057     } // end switch  
03058   }  
03059   else {
03060     // Controllers that support Invert
03061     switch (_ctrl) {    
03062       case KS0073:
03063       case KS0078:
03064         _function = _function & ~0x01;                                 // Disable Invert
03065         _writeCommand(0x20 | _function);                               // Disable Invert (Std Instr Set)
03066         break;
03067       case SSD1803_3V3 :      
03068 //      case SSD1803_5V :                 
03069       case US2066_3V3:
03070 //      case USS2066_5V:
03071         _function_1 = _function_1 & ~0x01;                             // Disable Invert 
03072                                                                        // Set function, 0 0 1 DL N BE RE(1) REV  (SSD1803)
03073                                                                        // Set function, 0 0 1 X  N BE RE(1) REV  (US2066)                                                                                                                                              
03074         _writeCommand(0x20 | _function_1);                             // Activate Invert (Ext Instr Set)
03075         _writeCommand(0x20 | _function);                               // Return to Std Instr Set                            
03076         break;
03077 
03078       default:  
03079         //Unsupported feature for other controllers
03080         break;              
03081     } // end switch  
03082   }
03083 } // end setInvert()
03084 #endif
03085 
03086 //--------- End TextLCD_Base -----------
03087 
03088 
03089 //--------- Start TextLCD Bus -----------
03090 
03091 /* Create a TextLCD interface for using regular mbed pins
03092  *
03093  * @param rs     Instruction/data control line
03094  * @param e      Enable line (clock)
03095  * @param d4-d7  Data lines for using as a 4-bit interface
03096  * @param type   Sets the panel size/addressing mode (default = LCD16x2)
03097  * @param bl     Backlight control line (optional, default = NC)  
03098  * @param e2     Enable2 line (clock for second controller, LCD40x4 only) 
03099  * @param ctrl   LCD controller (default = HD44780)   
03100  */ 
03101 TextLCD::TextLCD(PinName rs, PinName e,
03102                  PinName d4, PinName d5, PinName d6, PinName d7,
03103                  LCDType type, PinName bl, PinName e2, LCDCtrl ctrl) :
03104                  TextLCD_Base(type, ctrl), 
03105                  _rs(rs), _e(e), _d(d4, d5, d6, d7) {
03106 
03107   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
03108   if (bl != NC) {
03109     _bl = new DigitalOut(bl);   //Construct new pin 
03110     _bl->write(0);              //Deactivate    
03111   }
03112   else {
03113     // No Hardware Backlight pin       
03114     _bl = NULL;                 //Construct dummy pin     
03115   }  
03116 
03117   // The hardware Enable2 pin is only needed for LCD40x4. Test and make sure whether it exists or not to prevent illegal access.
03118   if (e2 != NC) {
03119     _e2 = new DigitalOut(e2);   //Construct new pin 
03120     _e2->write(0);              //Deactivate    
03121   }
03122   else {
03123     // No Hardware Enable pin       
03124     _e2 = NULL;                 //Construct dummy pin     
03125   }  
03126   
03127    _init(_LCD_DL_4);   // Set Datalength to 4 bit for mbed bus interfaces
03128 }
03129 
03130 /** Destruct a TextLCD interface for using regular mbed pins
03131   *
03132   * @param  none
03133   * @return none
03134   */ 
03135 TextLCD::~TextLCD() {
03136    if (_bl != NULL) {delete _bl;}  // BL pin
03137    if (_e2 != NULL) {delete _e2;}  // E2 pin
03138 }
03139 
03140 /** Set E pin (or E2 pin)
03141   * Used for mbed pins, I2C bus expander or SPI shiftregister
03142   * Default PinName value for E2 is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
03143   *   @param  value true or false
03144   *   @return none 
03145   */
03146 void TextLCD::_setEnable(bool value) {
03147 
03148   if(_ctrl_idx==_LCDCtrl_0) {
03149     if (value) {
03150       _e  = 1;    // Set E bit 
03151     }  
03152     else { 
03153       _e  = 0;    // Reset E bit  
03154     }  
03155   }    
03156   else { 
03157     if (value) {
03158       if (_e2 != NULL) {_e2->write(1);}  //Set E2 bit
03159     }  
03160     else { 
03161       if (_e2 != NULL) {_e2->write(0);}  //Reset E2 bit     
03162     }  
03163   }    
03164 }    
03165 
03166 // Set RS pin
03167 // Used for mbed pins, I2C bus expander or SPI shiftregister
03168 void TextLCD::_setRS(bool value) {
03169 
03170   if (value) {
03171     _rs  = 1;    // Set RS bit 
03172   }  
03173   else  {
03174     _rs  = 0;    // Reset RS bit 
03175   }  
03176 }    
03177 
03178 /** Set BL pin
03179   * Used for mbed pins, I2C bus expander or SPI shiftregister
03180   * Default PinName value is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
03181   *   @param  value true or false
03182   *   @return none  
03183   */
03184 void TextLCD::_setBL(bool value) {
03185 
03186   if (value) {
03187     if (_bl != NULL) {_bl->write(1);}  //Set BL bit
03188   }  
03189   else { 
03190     if (_bl != NULL) {_bl->write(0);}  //Reset BL bit  
03191   }  
03192 }    
03193 
03194 // Place the 4bit data on the databus
03195 // Used for mbed pins, I2C bus expander or SPI shifregister
03196 void TextLCD::_setData(int value) {
03197   _d = value & 0x0F;   // Write Databits 
03198 }    
03199 
03200 //----------- End TextLCD ---------------
03201 
03202 
03203 //--------- Start TextLCD_I2C -----------
03204 #if(LCD_I2C == 1) /* I2C Expander PCF8574/MCP23008 */
03205 /** Create a TextLCD interface using an I2C PC8574 (or PCF8574A) or MCP23008 portexpander
03206   *
03207   * @param i2c             I2C Bus
03208   * @param deviceAddress   I2C slave address (PCF8574, PCF8574A or MCP23008, default = 0x40)
03209   * @param type            Sets the panel size/addressing mode (default = LCD16x2)
03210   * @param ctrl            LCD controller (default = HD44780)    
03211   */
03212 TextLCD_I2C::TextLCD_I2C(I2C *i2c, char deviceAddress, LCDType type, LCDCtrl ctrl) :
03213                          TextLCD_Base(type, ctrl), 
03214                          _i2c(i2c){
03215                               
03216   _slaveAddress = deviceAddress & 0xFE;
03217 
03218   // Setup the I2C bus
03219   // The max bitrate for PCF8574 is 100kbit, the max bitrate for MCP23008 is 400kbit, 
03220   _i2c->frequency(100000);
03221   
03222 #if (MCP23008==1)
03223   // MCP23008 portexpander Init
03224   _writeRegister(IODIR,   0x00);  // All pins are outputs
03225   _writeRegister(IPOL,    0x00);  // No reverse polarity on inputs
03226   _writeRegister(GPINTEN, 0x00);  // No interrupt on change of input pins
03227   _writeRegister(DEFVAL,  0x00);  // Default value to compare against for interrupts
03228   _writeRegister(INTCON,  0x00);  // No interrupt on changes, compare against previous pin value 
03229   _writeRegister(IOCON,   0x20);  // b1=0 - Interrupt polarity active low  
03230                                   // b2=0 - Interrupt pin active driver output  
03231                                   // b4=0 - Slew rate enable on SDA
03232                                   // b5=0 - Auto-increment on registeraddress                                  
03233                                   // b5=1 - No auto-increment on registeraddress => needed for performance improved I2C expander mode
03234   _writeRegister(GPPU,    0x00);  // No Pullup 
03235 //               INTF             // Interrupt flags read (Read-Only)
03236 //               INTCAP           // Captured inputpins at time of interrupt (Read-Only)   
03237 //  _writeRegister(GPIO,    0x00);  // Output/Input pins   
03238 //  _writeRegister(OLAT,    0x00);  // Output Latch  
03239     
03240   // Init the portexpander bus
03241   _lcd_bus = LCD_BUS_I2C_DEF;
03242   
03243   // write the new data to the portexpander
03244   _writeRegister(GPIO, _lcd_bus);      
03245 #else
03246   // PCF8574 of PCF8574A portexpander
03247 
03248   // Init the portexpander bus
03249   _lcd_bus = LCD_BUS_I2C_DEF;
03250 
03251   // write the new data to the portexpander
03252   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
03253 #endif
03254 
03255   _init(_LCD_DL_4);   // Set Datalength to 4 bit for all serial expander interfaces
03256 }
03257 
03258 // Set E bit (or E2 bit) in the databus shadowvalue
03259 // Used for mbed I2C bus expander
03260 void TextLCD_I2C::_setEnableBit(bool value) {
03261 
03262 #if (LCD_TWO_CTRL == 1)
03263   if(_ctrl_idx==_LCDCtrl_0) {
03264     if (value) {
03265       _lcd_bus |= LCD_BUS_I2C_E;     // Set E bit 
03266     }  
03267     else {                    
03268       _lcd_bus &= ~LCD_BUS_I2C_E;    // Reset E bit                     
03269     }  
03270   }
03271   else {
03272     if (value) {
03273       _lcd_bus |= LCD_BUS_I2C_E2;    // Set E2 bit 
03274     }  
03275     else {
03276       _lcd_bus &= ~LCD_BUS_I2C_E2;   // Reset E2bit                     
03277     }  
03278   }    
03279 #else
03280 // Support only one controller
03281   if (value) {
03282     _lcd_bus |= LCD_BUS_I2C_E;     // Set E bit 
03283   }  
03284   else {                    
03285     _lcd_bus &= ~LCD_BUS_I2C_E;    // Reset E bit                     
03286   }  
03287 
03288 #endif  
03289 }    
03290 
03291 // Set E pin (or E2 pin)
03292 // Used for mbed pins, I2C bus expander or SPI shiftregister
03293 void TextLCD_I2C::_setEnable(bool value) {
03294 
03295   // Place the E or E2 bit data on the databus shadowvalue
03296   _setEnableBit(value);
03297 
03298 #if (MCP23008==1)
03299   // MCP23008 portexpander
03300   
03301   // write the new data to the portexpander
03302   _writeRegister(GPIO, _lcd_bus);      
03303 #else
03304   // PCF8574 of PCF8574A portexpander
03305 
03306   // write the new data to the I2C portexpander
03307   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
03308 #endif
03309 }    
03310 
03311 
03312 // Set RS pin
03313 // Used for mbed pins, I2C bus expander or SPI shiftregister
03314 void TextLCD_I2C::_setRS(bool value) {
03315 
03316   if (value) {
03317     _lcd_bus |= LCD_BUS_I2C_RS;    // Set RS bit 
03318   }  
03319   else {                    
03320     _lcd_bus &= ~LCD_BUS_I2C_RS;   // Reset RS bit                     
03321   }
03322 
03323 #if (MCP23008==1)
03324   // MCP23008 portexpander
03325   
03326   // write the new data to the portexpander
03327   _writeRegister(GPIO, _lcd_bus);      
03328 #else
03329   // PCF8574 of PCF8574A portexpander
03330 
03331   // write the new data to the I2C portexpander
03332   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
03333 #endif                  
03334 }    
03335 
03336 // Set BL pin
03337 // Used for mbed pins, I2C bus expander or SPI shiftregister
03338 void TextLCD_I2C::_setBL(bool value) {
03339 
03340   if (value) {
03341     _lcd_bus |= LCD_BUS_I2C_BL;    // Set BL bit 
03342   }  
03343   else {                    
03344     _lcd_bus &= ~LCD_BUS_I2C_BL;   // Reset BL bit                     
03345   }
03346   
03347 #if (MCP23008==1)
03348   // MCP23008 portexpander
03349   
03350   // write the new data to the portexpander
03351   _writeRegister(GPIO, _lcd_bus);      
03352 #else
03353   // PCF8574 of PCF8574A portexpander
03354 
03355   // write the new data to the I2C portexpander
03356   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
03357 #endif                 
03358 }    
03359 
03360 #if(0)
03361 // New optimized v018
03362 // Test faster _writeByte 0.11s vs 0.27s for a 20x4 fillscreen (PCF8574), same as v018
03363 // Place the 4bit data in the databus shadowvalue
03364 // Used for mbed I2C bus expander
03365 const char _LCD_DATA_BITS[16] = {
03366       0x00,
03367       (                                                   LCD_BUS_I2C_D4),
03368       (                                  LCD_BUS_I2C_D5                 ),
03369       (                                  LCD_BUS_I2C_D5 | LCD_BUS_I2C_D4),
03370       (                 LCD_BUS_I2C_D6                                  ),                  
03371       (                 LCD_BUS_I2C_D6                  | LCD_BUS_I2C_D4),
03372       (                 LCD_BUS_I2C_D6 | LCD_BUS_I2C_D5                 ),
03373       (                 LCD_BUS_I2C_D6 | LCD_BUS_I2C_D5 | LCD_BUS_I2C_D4),
03374       (LCD_BUS_I2C_D7                                                   ),
03375       (LCD_BUS_I2C_D7                                   | LCD_BUS_I2C_D4),
03376       (LCD_BUS_I2C_D7                  | LCD_BUS_I2C_D5                 ),
03377       (LCD_BUS_I2C_D7                  | LCD_BUS_I2C_D5 | LCD_BUS_I2C_D4),                  
03378       (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D6                                  ),
03379       (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D6                  | LCD_BUS_I2C_D4),
03380       (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D6 | LCD_BUS_I2C_D5                 ),
03381       (LCD_BUS_I2C_D7 | LCD_BUS_I2C_D6 | LCD_BUS_I2C_D5 | LCD_BUS_I2C_D4)
03382     };
03383 void TextLCD_I2C::_setDataBits(int value) {
03384 
03385   //Clear all databits
03386   _lcd_bus &= ~LCD_BUS_I2C_MSK;
03387 
03388   // Set bit by bit to support any mapping of expander portpins to LCD pins 
03389   _lcd_bus |= _LCD_DATA_BITS[value & 0x0F];
03390 }    
03391 #endif
03392 
03393 // Test faster _writeByte 0.11s vs 0.27s for a 20x4 fillscreen (PCF8574)
03394 // Place the 4bit data in the databus shadowvalue
03395 // Used for mbed I2C bus expander
03396 void TextLCD_I2C::_setDataBits(int value) {
03397 
03398   //Clear all databits
03399   _lcd_bus &= ~LCD_BUS_I2C_MSK;
03400 
03401   // Set bit by bit to support any mapping of expander portpins to LCD pins 
03402   if (value & 0x01){
03403     _lcd_bus |= LCD_BUS_I2C_D4;   // Set Databit 
03404   }  
03405 
03406   if (value & 0x02){
03407     _lcd_bus |= LCD_BUS_I2C_D5;   // Set Databit 
03408   }  
03409 
03410   if (value & 0x04) {
03411     _lcd_bus |= LCD_BUS_I2C_D6;   // Set Databit 
03412   }  
03413 
03414   if (value & 0x08) {
03415     _lcd_bus |= LCD_BUS_I2C_D7;   // Set Databit 
03416   }  
03417 }    
03418 
03419 
03420 // Place the 4bit data on the databus
03421 // Used for mbed pins, I2C bus expander or SPI shifregister
03422 void TextLCD_I2C::_setData(int value) {
03423 
03424   // Place the 4bit data on the databus shadowvalue
03425   _setDataBits(value); 
03426   
03427   // Place the 4bit data on the databus
03428 #if (MCP23008==1)
03429   // MCP23008 portexpander
03430   
03431   // write the new data to the portexpander
03432   _writeRegister(GPIO, _lcd_bus);      
03433 #else
03434   // PCF8574 of PCF8574A portexpander
03435 
03436   // write the new data to the I2C portexpander
03437   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
03438 #endif                 
03439 }    
03440 
03441 // Write data to MCP23008 I2C portexpander
03442 // Used for mbed I2C bus expander
03443 void TextLCD_I2C::_writeRegister (int reg, int value) {
03444   char data[] = {reg, value};
03445     
03446   _i2c->write(_slaveAddress, data, 2); 
03447 }
03448 
03449 //New optimized
03450 //Test faster _writeByte 0.11s vs 0.27s for a 20x4 fillscreen (PCF8574)
03451 //Test faster _writeByte 0.14s vs 0.34s for a 20x4 fillscreen (MCP23008)
03452 
03453 // Write a byte using I2C
03454 void TextLCD_I2C::_writeByte(int value) {
03455   char data[6];
03456   
03457 #if (MCP23008==1)
03458   // MCP23008 portexpander
03459 
03460   data[0] = GPIO;                 // set registeraddres
03461                                   // Note: auto-increment is disabled so all data will go to GPIO register
03462   
03463   _setEnableBit(true);            // set E 
03464   _setDataBits(value >> 4);       // set data high  
03465   data[1] = _lcd_bus;
03466   
03467   _setEnableBit(false);           // clear E   
03468   data[2] = _lcd_bus;
03469   
03470   _setEnableBit(true);            // set E   
03471   _setDataBits(value);            // set data low    
03472   data[3] = _lcd_bus;
03473   
03474   _setEnableBit(false);           // clear E     
03475   data[4] = _lcd_bus;
03476   
03477   // write the packed data to the I2C portexpander
03478   _i2c->write(_slaveAddress, data, 5);    
03479 #else
03480   // PCF8574 of PCF8574A portexpander
03481   
03482   _setEnableBit(true);            // set E 
03483   _setDataBits(value >> 4);       // set data high  
03484   data[0] = _lcd_bus;
03485   
03486   _setEnableBit(false);           // clear E   
03487   data[1] = _lcd_bus;
03488   
03489   _setEnableBit(true);            // set E   
03490   _setDataBits(value);            // set data low    
03491   data[2] = _lcd_bus;
03492   
03493   _setEnableBit(false);           // clear E     
03494   data[3] = _lcd_bus;
03495   
03496   // write the packed data to the I2C portexpander
03497   _i2c->write(_slaveAddress, data, 4);    
03498 #endif
03499 }
03500 
03501 #endif /* I2C Expander PCF8574/MCP23008 */
03502 //---------- End TextLCD_I2C ------------
03503 
03504 
03505 //--------- Start TextLCD_SPI -----------
03506 #if(LCD_SPI == 1) /* SPI Expander SN74595          */
03507 
03508  /** Create a TextLCD interface using an SPI 74595 portexpander
03509    *
03510    * @param spi             SPI Bus
03511    * @param cs              chip select pin (active low)
03512    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
03513    * @param ctrl            LCD controller (default = HD44780)      
03514    */
03515 TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) :
03516                          TextLCD_Base(type, ctrl), 
03517                          _spi(spi),        
03518                          _cs(cs) {              
03519   // Init cs
03520   _cs = 1;  
03521 
03522   // Setup the spi for 8 bit data, low steady state clock,
03523   // rising edge capture, with a 500KHz or 1MHz clock rate  
03524   _spi->format(8,0);
03525   _spi->frequency(500000);    
03526   //_spi.frequency(1000000);    
03527 
03528   wait_ms(100);                   // Wait 100ms to ensure LCD powered up
03529   
03530   // Init the portexpander bus
03531   _lcd_bus = LCD_BUS_SPI_DEF;
03532   
03533   // write the new data to the portexpander
03534   _cs = 0;  
03535   _spi->write(_lcd_bus);   
03536   _cs = 1;  
03537 
03538   _init(_LCD_DL_4);   // Set Datalength to 4 bit for all serial expander interfaces
03539 }
03540 
03541 // Set E pin (or E2 pin)
03542 // Used for mbed pins, I2C bus expander or SPI shiftregister
03543 void TextLCD_SPI::_setEnable(bool value) {
03544 
03545   if(_ctrl_idx==_LCDCtrl_0) {
03546     if (value) {
03547       _lcd_bus |= LCD_BUS_SPI_E;     // Set E bit 
03548     }  
03549     else {                    
03550       _lcd_bus &= ~LCD_BUS_SPI_E;    // Reset E bit                     
03551     }  
03552   }
03553   else {
03554     if (value) {
03555       _lcd_bus |= LCD_BUS_SPI_E2;    // Set E2 bit 
03556     }  
03557     else {
03558       _lcd_bus &= ~LCD_BUS_SPI_E2;   // Reset E2 bit                     
03559     }  
03560   }
03561                   
03562   // write the new data to the SPI portexpander
03563   _cs = 0;  
03564   _spi->write(_lcd_bus);   
03565   _cs = 1;    
03566 }    
03567 
03568 // Set RS pin
03569 // Used for mbed pins, I2C bus expander or SPI shiftregister and SPI_N
03570 void TextLCD_SPI::_setRS(bool value) {
03571 
03572   if (value) {
03573     _lcd_bus |= LCD_BUS_SPI_RS;    // Set RS bit 
03574   }  
03575   else {                    
03576     _lcd_bus &= ~LCD_BUS_SPI_RS;   // Reset RS bit                     
03577   }
03578      
03579   // write the new data to the SPI portexpander
03580   _cs = 0;  
03581   _spi->write(_lcd_bus);   
03582   _cs = 1;     
03583 }    
03584 
03585 // Set BL pin
03586 // Used for mbed pins, I2C bus expander or SPI shiftregister
03587 void TextLCD_SPI::_setBL(bool value) {
03588 
03589   if (value) {
03590     _lcd_bus |= LCD_BUS_SPI_BL;    // Set BL bit 
03591   }  
03592   else {
03593     _lcd_bus &= ~LCD_BUS_SPI_BL;   // Reset BL bit                     
03594   }
03595       
03596   // write the new data to the SPI portexpander
03597   _cs = 0;  
03598   _spi->write(_lcd_bus);   
03599   _cs = 1;      
03600 }    
03601 
03602 // Place the 4bit data on the databus
03603 // Used for mbed pins, I2C bus expander or SPI shiftregister
03604 void TextLCD_SPI::_setData(int value) {
03605 
03606   // Set bit by bit to support any mapping of expander portpins to LCD pins
03607   if (value & 0x01) {
03608     _lcd_bus |= LCD_BUS_SPI_D4;   // Set Databit 
03609   }  
03610   else {                    
03611     _lcd_bus &= ~LCD_BUS_SPI_D4;  // Reset Databit                     
03612   }
03613   
03614   if (value & 0x02) {
03615     _lcd_bus |= LCD_BUS_SPI_D5;   // Set Databit 
03616   }  
03617   else {
03618     _lcd_bus &= ~LCD_BUS_SPI_D5;  // Reset Databit                     
03619   }
03620   
03621   if (value & 0x04) {
03622     _lcd_bus |= LCD_BUS_SPI_D6;   // Set Databit 
03623   }  
03624   else {
03625     _lcd_bus &= ~LCD_BUS_SPI_D6;  // Reset Databit                     
03626   }
03627   
03628   if (value & 0x08) {
03629     _lcd_bus |= LCD_BUS_SPI_D7;   // Set Databit 
03630   }  
03631   else {
03632     _lcd_bus &= ~LCD_BUS_SPI_D7;  // Reset Databit
03633   }  
03634                     
03635   // write the new data to the SPI portexpander
03636   _cs = 0;  
03637   _spi->write(_lcd_bus);   
03638   _cs = 1;       
03639 }    
03640 
03641 #endif /* SPI Expander SN74595          */
03642 //---------- End TextLCD_SPI ------------
03643 
03644 
03645 //--------- Start TextLCD_I2C_N ---------
03646 #if(LCD_I2C_N == 1)  /* Native I2C */
03647 
03648  /** Create a TextLCD interface using a controller with native I2C interface
03649    *
03650    * @param i2c             I2C Bus
03651    * @param deviceAddress   I2C slave address (default = 0x7C)  
03652    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
03653    * @param bl              Backlight control line (optional, default = NC)     
03654    * @param ctrl            LCD controller (default = ST7032_3V3)                     
03655    */
03656 TextLCD_I2C_N::TextLCD_I2C_N(I2C *i2c, char deviceAddress, LCDType type, PinName bl, LCDCtrl ctrl) : 
03657                                TextLCD_Base(type, ctrl), 
03658 
03659                                _i2c(i2c){
03660   
03661   _slaveAddress = deviceAddress & 0xFE;
03662   
03663   // Setup the I2C bus
03664   // The max bitrate for ST7032i is 400kbit, lets stick to default here
03665   _i2c->frequency(100000);
03666 
03667        
03668   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
03669   if (bl != NC) {
03670     _bl = new DigitalOut(bl);   //Construct new pin 
03671     _bl->write(0);              //Deactivate    
03672   }
03673   else {
03674     // No Hardware Backlight pin       
03675     _bl = NULL;                 //Construct dummy pin     
03676   }  
03677   
03678   //Sanity check
03679   if (_ctrl & LCD_C_I2C) {
03680     _init(_LCD_DL_8);  // Set Datalength to 8 bit for all native serial interfaces      
03681   }
03682   else {
03683     error("Error: LCD Controller type does not support native I2C interface\n\r");           
03684   }
03685 }
03686 
03687 TextLCD_I2C_N::~TextLCD_I2C_N() {
03688    if (_bl != NULL) {delete _bl;}  // BL pin
03689 }
03690 
03691 // Not used in this mode
03692 void TextLCD_I2C_N::_setEnable(bool value) {
03693 }    
03694 
03695 // Set RS pin
03696 // Used for mbed pins, I2C bus expander or SPI shiftregister and native I2C or SPI
03697 void TextLCD_I2C_N::_setRS(bool value) {
03698 // The controlbyte defines the meaning of the next byte. This next byte can either be data or command.
03699 // Start Slaveaddress+RW  b7 b6 b5 b4 b3 b2 b1 b0   b7...........b0  Stop
03700 //                        Co RS RW  0  0  0  0  0   command or data
03701 //
03702 //   C0=1 indicates that another controlbyte will follow after the next data or command byte 
03703 //   RS=1 means that next byte is data, RS=0 means that next byte is command
03704 //   RW=0 means write to controller. RW=1 means that controller will be read from after the next command. 
03705 //        Many native I2C controllers dont support this option and it is not used by this lib. 
03706 //
03707 
03708   if (value) {
03709     _controlbyte = 0x40; // Next byte is data, No more control bytes will follow
03710   }
03711   else {
03712     _controlbyte = 0x00; // Next byte is command, No more control bytes will follow     
03713   }
03714 }    
03715 
03716 // Set BL pin
03717 void TextLCD_I2C_N::_setBL(bool value) {
03718     if (_bl) {
03719         _bl->write(value);   
03720     }    
03721 }    
03722     
03723 // Not used in this mode
03724 void TextLCD_I2C_N::_setData(int value) {
03725 }    
03726 
03727 // Write a byte using I2C
03728 void TextLCD_I2C_N::_writeByte(int value) {
03729 // The controlbyte defines the meaning of the next byte. This next byte can either be data or command.
03730 // Start Slaveaddress+RW  b7 b6 b5 b4 b3 b2 b1 b0   b7...........b0  Stop
03731 //                        Co RS RW  0  0  0  0  0   command or data
03732 //
03733 //   C0=1 indicates that another controlbyte will follow after the next data or command byte 
03734 //   RS=1 means that next byte is data, RS=0 means that next byte is command
03735 //   RW=0 means write to controller. RW=1 means that controller will be read from after the next command. 
03736 //        Many native I2C controllers dont support this option and it is not used by this lib. 
03737 //
03738   char data[] = {_controlbyte, value};
03739     
03740 #if(LCD_I2C_ACK==1)
03741 //Controllers that support ACK
03742   _i2c->write(_slaveAddress, data, 2); 
03743 #else  
03744 //Controllers that dont support ACK
03745 //Note: This may be issue with some mbed platforms that dont fully/correctly support I2C byte operations.
03746   _i2c->start(); 
03747   _i2c->write(_slaveAddress);   
03748   _i2c->write(data[0]); 
03749   _i2c->write(data[1]);     
03750   _i2c->stop();   
03751 #endif  
03752 }
03753 #endif /* Native I2C */
03754 //-------- End TextLCD_I2C_N ------------
03755 
03756 
03757 //--------- Start TextLCD_SPI_N ---------
03758 #if(LCD_SPI_N == 1) /* Native SPI bus     */
03759  /** Create a TextLCD interface using a controller with a native SPI4 interface
03760    *
03761    * @param spi             SPI Bus
03762    * @param cs              chip select pin (active low)
03763    * @param rs              Instruction/data control line
03764    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
03765    * @param bl              Backlight control line (optional, default = NC)  
03766    * @param ctrl            LCD controller (default = ST7032_3V3) 
03767    */       
03768 TextLCD_SPI_N::TextLCD_SPI_N(SPI *spi, PinName cs, PinName rs, LCDType type, PinName bl, LCDCtrl ctrl) :
03769                              TextLCD_Base(type, ctrl), 
03770                              _spi(spi),        
03771                              _cs(cs),
03772                              _rs(rs) {      
03773         
03774   // Init CS
03775   _cs = 1;
03776 
03777   // Setup the spi for 8 bit data, high steady state clock,
03778   // rising edge capture, with a 500KHz or 1MHz clock rate    
03779 //  _spi->format(8,3);  
03780 //  _spi->frequency(500000); 
03781 //  _spi->frequency(1000000);    
03782   
03783   // Setup the spi for 8 bit data, low steady state clock,
03784   // rising edge capture, with a 500KHz or 1MHz clock rate  
03785   _spi->format(8,0);
03786 //  _spi->frequency(500000); 
03787   _spi->frequency(1000000);    
03788     
03789   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
03790   if (bl != NC) {
03791     _bl = new DigitalOut(bl);   //Construct new pin 
03792     _bl->write(0);              //Deactivate    
03793   }
03794   else {
03795     // No Hardware Backlight pin       
03796     _bl = NULL;                 //Construct dummy pin     
03797   }  
03798 
03799   //Sanity check
03800   if (_ctrl & LCD_C_SPI4) {
03801     _init(_LCD_DL_8);   // Set Datalength to 8 bit for all native serial interfaces
03802                         // ST7070 must set datalength to 8 bits!
03803   }
03804   else {
03805     error("Error: LCD Controller type does not support native SPI4 interface\n\r");           
03806   }
03807 }
03808 
03809 TextLCD_SPI_N::~TextLCD_SPI_N() {
03810    if (_bl != NULL) {delete _bl;}  // BL pin
03811 }
03812 
03813 // Not used in this mode
03814 void TextLCD_SPI_N::_setEnable(bool value) {
03815 }    
03816 
03817 // Set RS pin
03818 // Used for mbed pins, I2C bus expander or SPI shiftregister, SPI_N
03819 void TextLCD_SPI_N::_setRS(bool value) {
03820     _rs = value;
03821 }    
03822 
03823 // Set BL pin
03824 void TextLCD_SPI_N::_setBL(bool value) {
03825     if (_bl) {
03826         _bl->write(value);   
03827     }    
03828 }    
03829 
03830 // Not used in this mode
03831 void TextLCD_SPI_N::_setData(int value) {
03832 }    
03833 
03834 // Write a byte using SPI
03835 void TextLCD_SPI_N::_writeByte(int value) {
03836     _cs = 0;
03837     wait_us(1);
03838     _spi->write(value);
03839     wait_us(1);
03840     _cs = 1;
03841 }
03842 #endif /* Native SPI bus     */  
03843 //-------- End TextLCD_SPI_N ------------
03844 
03845 
03846 //-------- Start TextLCD_SPI_N_3_8 --------
03847 #if(LCD_SPI_N_3_8 == 1) /* Native SPI bus     */
03848 
03849  /** Create a TextLCD interface using a controller with a native SPI3 8 bits interface
03850    * This mode is supported by ST7070. Note that implementation in TexTLCD is not very efficient due to
03851    * structure of the TextLCD library: each databyte is written separately and requires a separate 'count command' set to 1 byte.
03852    *
03853    * @param spi             SPI Bus
03854    * @param cs              chip select pin (active low)
03855    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
03856    * @param bl              Backlight control line (optional, default = NC)  
03857    * @param ctrl            LCD controller (default = ST7070) 
03858    */       
03859 TextLCD_SPI_N_3_8::TextLCD_SPI_N_3_8(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
03860                                      TextLCD_Base(type, ctrl), 
03861                                      _spi(spi),        
03862                                      _cs(cs) {      
03863 
03864   // Init CS
03865   _cs = 1;
03866 
03867   // Setup the spi for 8 bit data, high steady state clock,
03868   // rising edge capture, with a 500KHz or 1MHz clock rate  
03869 //  _spi->format(8,3);  
03870 //  _spi->frequency(500000);    
03871 //  _spi->frequency(1000000);    
03872 
03873   // Setup the spi for 8 bit data, low steady state clock,
03874   // rising edge capture, with a 500KHz or 1MHz clock rate  
03875   _spi->format(8,0);
03876 //  _spi->frequency(500000); 
03877   _spi->frequency(1000000);    
03878   
03879   
03880   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
03881   if (bl != NC) {
03882     _bl = new DigitalOut(bl);   //Construct new pin 
03883     _bl->write(0);              //Deactivate    
03884   }
03885   else {
03886     // No Hardware Backlight pin       
03887     _bl = NULL;                 //Construct dummy pin     
03888   }  
03889 
03890   //Sanity check
03891   if (_ctrl & LCD_C_SPI3_8) { 
03892     _init(_LCD_DL_8);  // Set Datalength to 8 bit for all native serial interfaces   
03893   }
03894   else {
03895     error("Error: LCD Controller type does not support native SPI3 8 bits interface\n\r");           
03896   }
03897 }
03898 
03899 TextLCD_SPI_N_3_8::~TextLCD_SPI_N_3_8() {
03900    if (_bl != NULL) {delete _bl;}  // BL pin
03901 }
03902 
03903 // Not used in this mode
03904 void TextLCD_SPI_N_3_8::_setEnable(bool value) {
03905 }    
03906 
03907 // Used for mbed pins, I2C bus expander or SPI shiftregister, SPI_N
03908 //   RS=1 means that next byte is data, RS=0 means that next byte is command
03909 void TextLCD_SPI_N_3_8::_setRS(bool value) {
03910   
03911   if (value) {
03912     _controlbyte = 0x01; // Next byte is data, No more control bytes will follow
03913   }
03914   else {
03915     _controlbyte = 0x00; // Next byte is command, No more control bytes will follow     
03916   }
03917 }      
03918   
03919 // Set BL pin
03920 void TextLCD_SPI_N_3_8::_setBL(bool value) {
03921     if (_bl) {
03922         _bl->write(value);   
03923     }    
03924 }    
03925 
03926 // Not used in this mode
03927 void TextLCD_SPI_N_3_8::_setData(int value) {
03928 }    
03929 
03930 // Write a byte using SPI3 8 bits mode (ST7070)
03931 void TextLCD_SPI_N_3_8::_writeByte(int value) {
03932     
03933   if (_controlbyte == 0x00) { // Byte is command 
03934     _cs = 0;
03935     wait_us(1);
03936     _spi->write(value);
03937     wait_us(1);
03938     _cs = 1;
03939   }  
03940   else {                      // Byte is data 
03941     // Select Extended Instr Set
03942     _cs = 0;
03943     wait_us(1);
03944     _spi->write(0x20 | _function | 0x04);   // Set function, 0 0 1 DL N EXT=1 x x (Select Instr Set = 1));
03945     wait_us(1);
03946     _cs = 1;     
03947 
03948     wait_us(40);                            // Wait until command has finished...    
03949         
03950     // Set Count to 1 databyte
03951     _cs = 0;
03952     wait_us(1);    
03953     _spi->write(0x80);                      // Set display data length, 1 L6 L5 L4 L3 L2 L1 L0 (Instr Set = 1)
03954     wait_us(1);
03955     _cs = 1;
03956 
03957     wait_us(40);    
03958                 
03959     // Write 1 databyte     
03960     _cs = 0;
03961     wait_us(1);    
03962     _spi->write(value);                     // Write data (Instr Set = 1)
03963     wait_us(1);
03964     _cs = 1;         
03965 
03966     wait_us(40);    
03967         
03968     // Select Standard Instr Set    
03969     _cs = 0;
03970     wait_us(1);    
03971     _spi->write(0x20 | _function);          // Set function, 0 0 1 DL N EXT=0 x x (Select Instr Set = 0));
03972     wait_us(1);
03973     _cs = 1;     
03974   }  
03975 }
03976 #endif /* Native SPI bus     */  
03977 //------- End TextLCD_SPI_N_3_8 -----------
03978 
03979 
03980 //-------- Start TextLCD_SPI_N_3_9 --------
03981 #if(LCD_SPI_N_3_9 == 1) /* Native SPI bus     */
03982 //Code checked out on logic analyser. Not yet tested on hardware..
03983 
03984  /** Create a TextLCD interface using a controller with a native SPI3 9 bits interface
03985    *
03986    * @param spi             SPI Bus
03987    * @param cs              chip select pin (active low)
03988    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
03989    * @param bl              Backlight control line (optional, default = NC)  
03990    * @param ctrl            LCD controller (default = AIP31068) 
03991    */       
03992 TextLCD_SPI_N_3_9::TextLCD_SPI_N_3_9(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
03993                                      TextLCD_Base(type, ctrl), 
03994                                      _spi(spi),        
03995                                      _cs(cs) {      
03996 
03997   // Init CS
03998   _cs = 1;
03999 
04000   // Setup the spi for 9 bit data, high steady state clock,
04001   // rising edge capture, with a 500KHz or 1MHz clock rate  
04002   _spi->format(9,3);  
04003   _spi->frequency(1000000);    
04004   
04005   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
04006   if (bl != NC) {
04007     _bl = new DigitalOut(bl);   //Construct new pin 
04008     _bl->write(0);              //Deactivate    
04009   }
04010   else {
04011     // No Hardware Backlight pin       
04012     _bl = NULL;                 //Construct dummy pin     
04013   }  
04014 
04015   //Sanity check
04016   if (_ctrl & LCD_C_SPI3_9) { 
04017     _init(_LCD_DL_8);  // Set Datalength to 8 bit for all native serial interfaces   
04018   }
04019   else {
04020     error("Error: LCD Controller type does not support native SPI3 9 bits interface\n\r");           
04021   }
04022 }
04023 
04024 TextLCD_SPI_N_3_9::~TextLCD_SPI_N_3_9() {
04025    if (_bl != NULL) {delete _bl;}  // BL pin
04026 }
04027 
04028 // Not used in this mode
04029 void TextLCD_SPI_N_3_9::_setEnable(bool value) {
04030 }    
04031 
04032 // Set RS pin
04033 // Used for mbed pins, I2C bus expander or SPI shiftregister
04034 void TextLCD_SPI_N_3_9::_setRS(bool value) {
04035 // The controlbits define the meaning of the next byte. This next byte can either be data or command.
04036 //   b8  b7...........b0 
04037 //   RS  command or data
04038 //
04039 //   RS=1 means that next byte is data, RS=0 means that next byte is command
04040 //
04041 
04042   if (value) {
04043     _controlbyte = 0x01; // Next byte is data
04044   }
04045   else {
04046     _controlbyte = 0x00; // Next byte is command
04047   }  
04048 }    
04049 
04050 // Set BL pin
04051 void TextLCD_SPI_N_3_9::_setBL(bool value) {
04052     if (_bl) {
04053         _bl->write(value);   
04054     }    
04055 }    
04056 
04057 // Not used in this mode
04058 void TextLCD_SPI_N_3_9::_setData(int value) {
04059 }    
04060 
04061 // Write a byte using SPI3 9 bits mode
04062 void TextLCD_SPI_N_3_9::_writeByte(int value) {
04063     _cs = 0;
04064     wait_us(1);
04065     _spi->write( (_controlbyte << 8) | (value & 0xFF));
04066     wait_us(1);
04067     _cs = 1;
04068 }
04069 #endif /* Native SPI bus     */  
04070 //------- End TextLCD_SPI_N_3_9 -----------
04071 
04072 
04073 //------- Start TextLCD_SPI_N_3_10 --------
04074 #if(LCD_SPI_N_3_10 == 1) /* Native SPI bus     */
04075 
04076  /** Create a TextLCD interface using a controller with a native SPI3 10 bits interface
04077    *
04078    * @param spi             SPI Bus
04079    * @param cs              chip select pin (active low)
04080    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
04081    * @param bl              Backlight control line (optional, default = NC)  
04082    * @param ctrl            LCD controller (default = AIP31068) 
04083    */       
04084 TextLCD_SPI_N_3_10::TextLCD_SPI_N_3_10(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
04085                                        TextLCD_Base(type, ctrl), 
04086                                        _spi(spi),        
04087                                        _cs(cs) {      
04088         
04089   // Init CS
04090   _cs = 1;
04091 
04092   // Setup the spi for 10 bit data, low steady state clock,
04093   // rising edge capture, with a 500KHz or 1MHz clock rate  
04094   _spi->format(10,0);
04095   _spi->frequency(1000000);    
04096   
04097   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
04098   if (bl != NC) {
04099     _bl = new DigitalOut(bl);   //Construct new pin 
04100     _bl->write(0);              //Deactivate    
04101   }
04102   else {
04103     // No Hardware Backlight pin       
04104     _bl = NULL;                 //Construct dummy pin     
04105   }  
04106 
04107   //Sanity check
04108   if (_ctrl & LCD_C_SPI3_10) {
04109      _init(_LCD_DL_8);  // Set Datalength to 8 bit for all native serial interfaces            
04110   }
04111   else {
04112     error("Error: LCD Controller type does not support native SPI3 10 bits interface\n\r");           
04113   }
04114 }
04115 
04116 TextLCD_SPI_N_3_10::~TextLCD_SPI_N_3_10() {
04117    if (_bl != NULL) {delete _bl;}  // BL pin
04118 }
04119 
04120 // Not used in this mode
04121 void TextLCD_SPI_N_3_10::_setEnable(bool value) {
04122 }    
04123 
04124 // Set RS pin
04125 // Used for mbed pins, I2C bus expander or SPI shiftregister
04126 void TextLCD_SPI_N_3_10::_setRS(bool value) {
04127 // The controlbits define the meaning of the next byte. This next byte can either be data or command.
04128 //   b9 b8  b7...........b0 
04129 //   RS RW  command or data
04130 //
04131 //   RS=1 means that next byte is data, RS=0 means that next byte is command
04132 //   RW=0 means that next byte is writen, RW=1 means that next byte is read (not used in this lib)
04133 //
04134 
04135   if (value) {
04136     _controlbyte = 0x02; // Next byte is data
04137   }
04138   else {
04139     _controlbyte = 0x00; // Next byte is command
04140   }  
04141 }    
04142 
04143 // Set BL pin
04144 void TextLCD_SPI_N_3_10::_setBL(bool value) {
04145     if (_bl) {
04146         _bl->write(value);   
04147     }    
04148 }    
04149 
04150 // Not used in this mode
04151 void TextLCD_SPI_N_3_10::_setData(int value) {
04152 }    
04153 
04154 // Write a byte using SPI3 10 bits mode
04155 void TextLCD_SPI_N_3_10::_writeByte(int value) {
04156     _cs = 0;
04157     wait_us(1);
04158     _spi->write( (_controlbyte << 8) | (value & 0xFF));
04159     wait_us(1);
04160     _cs = 1;
04161 }
04162 #endif /* Native SPI bus     */  
04163 //------- End TextLCD_SPI_N_3_10 ----------
04164 
04165 
04166 //------- Start TextLCD_SPI_N_3_16 --------
04167 #if(LCD_SPI_N_3_16 == 1) /* Native SPI bus     */
04168 
04169  /** Create a TextLCD interface using a controller with a native SPI3 16 bits interface
04170    *
04171    * @param spi             SPI Bus
04172    * @param cs              chip select pin (active low)
04173    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
04174    * @param bl              Backlight control line (optional, default = NC)  
04175    * @param ctrl            LCD controller (default = PT6314) 
04176    */       
04177 TextLCD_SPI_N_3_16::TextLCD_SPI_N_3_16(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
04178                                        TextLCD_Base(type, ctrl), 
04179                                        _spi(spi),        
04180                                        _cs(cs) {      
04181         
04182   // Init CS
04183   _cs = 1;
04184 
04185   // Setup the spi for 8 bit data, low steady state clock,
04186   // rising edge capture, with a 500KHz or 1MHz clock rate  
04187   _spi->format(8,0);
04188   _spi->frequency(1000000);    
04189   
04190   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
04191   if (bl != NC) {
04192     _bl = new DigitalOut(bl);   //Construct new pin 
04193     _bl->write(0);              //Deactivate    
04194   }
04195   else {
04196     // No Hardware Backlight pin       
04197     _bl = NULL;                 //Construct dummy pin     
04198   }  
04199 
04200   //Sanity check
04201   if (_ctrl & LCD_C_SPI3_16) {
04202      _init(_LCD_DL_8);  // Set Datalength to 8 bit for all native serial interfaces            
04203   }
04204   else {
04205     error("Error: LCD Controller type does not support native SPI3 16 bits interface\n\r");           
04206   }
04207 }
04208 
04209 TextLCD_SPI_N_3_16::~TextLCD_SPI_N_3_16() {
04210    if (_bl != NULL) {delete _bl;}  // BL pin
04211 }
04212 
04213 // Not used in this mode
04214 void TextLCD_SPI_N_3_16::_setEnable(bool value) {
04215 }    
04216 
04217 // Set RS pin
04218 // Used for mbed pins, I2C bus expander or SPI shiftregister
04219 void TextLCD_SPI_N_3_16::_setRS(bool value) {
04220 // The 16bit mode is split in 2 bytes. The first byte is for synchronisation and controlbits. The controlbits define the meaning of the next byte.
04221 // The 8 actual bits represent either a data or a command byte.
04222 //   b15 b14 b13 b12 b11 b10  b9  b8 - b7 b6 b5 b4 b3 b2 b1 b0 
04223 //     1   1   1   1   1  RW  RS   0   d7 d6 d5 d4 d3 d2 d1 d0
04224 //
04225 //   RS=1 means that next byte is data, RS=0 means that next byte is command
04226 //   RW=0 means that next byte is writen, RW=1 means that next byte is read (not used in this lib)
04227 //
04228 
04229   if (value) {
04230     _controlbyte = 0xFA; // Next byte is data
04231   }
04232   else {
04233     _controlbyte = 0xF8; // Next byte is command
04234   }  
04235 }    
04236 
04237 // Set BL pin
04238 void TextLCD_SPI_N_3_16::_setBL(bool value) {
04239     if (_bl) {
04240         _bl->write(value);   
04241     }    
04242 }    
04243 
04244 // Not used in this mode
04245 void TextLCD_SPI_N_3_16::_setData(int value) {
04246 }    
04247    
04248 // Write a byte using SPI3 16 bits mode
04249 void TextLCD_SPI_N_3_16::_writeByte(int value) {
04250     _cs = 0;
04251     wait_us(1);
04252 
04253     _spi->write(_controlbyte);
04254 
04255     _spi->write(value);     
04256 
04257     wait_us(1);
04258     _cs = 1;
04259 }
04260 #endif /* Native SPI bus     */  
04261 //------- End TextLCD_SPI_N_3_16 ----------
04262 
04263 
04264 //------- Start TextLCD_SPI_N_3_24 --------
04265 #if(LCD_SPI_N_3_24 == 1) /* Native SPI bus     */
04266 
04267  /** Create a TextLCD interface using a controller with a native SPI3 24 bits interface
04268    *
04269    * @param spi             SPI Bus
04270    * @param cs              chip select pin (active low)
04271    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
04272    * @param bl              Backlight control line (optional, default = NC)  
04273    * @param ctrl            LCD controller (default = SSD1803) 
04274    */       
04275 TextLCD_SPI_N_3_24::TextLCD_SPI_N_3_24(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
04276                                        TextLCD_Base(type, ctrl), 
04277                                        _spi(spi),        
04278                                        _cs(cs) {      
04279         
04280   // Init CS
04281   _cs = 1;
04282 
04283   // Setup the spi for 8 bit data, high steady state clock,
04284   // rising edge capture, with a 500KHz or 1MHz clock rate  
04285   _spi->format(8,3);
04286   _spi->frequency(1000000);    
04287   
04288   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
04289   if (bl != NC) {
04290     _bl = new DigitalOut(bl);   //Construct new pin 
04291     _bl->write(0);              //Deactivate    
04292   }
04293   else {
04294     // No Hardware Backlight pin       
04295     _bl = NULL;                 //Construct dummy pin     
04296   }  
04297 
04298   //Sanity check
04299   if (_ctrl & LCD_C_SPI3_24) {
04300     _init(_LCD_DL_8);  // Set Datalength to 8 bit for all native serial interfaces      
04301   }
04302   else {
04303     error("Error: LCD Controller type does not support native SPI3 24 bits interface\n\r");           
04304   }
04305 }
04306 
04307 TextLCD_SPI_N_3_24::~TextLCD_SPI_N_3_24() {
04308    if (_bl != NULL) {delete _bl;}  // BL pin
04309 }
04310 
04311 // Not used in this mode
04312 void TextLCD_SPI_N_3_24::_setEnable(bool value) {
04313 }    
04314 
04315 // Set RS pin
04316 // Used for mbed pins, I2C bus expander or SPI shiftregister
04317 void TextLCD_SPI_N_3_24::_setRS(bool value) {
04318 // The 24bit mode is split in 3 bytes. The first byte is for synchronisation and controlbits. The controlbits define the meaning of the next two bytes.
04319 // Each byte encodes 4 actual bits. The 8 actual bits represent either a data or a command byte.
04320 //   b23 b22 b21 b20 b19 b18 b17 b16 -  b15 b14 b13 b12 b11 b10 b9 b8 - b7 b6 b5 b4 b3 b2 b1 b0 
04321 //     1   1   1   1   1  RW  RS   0     d0  d1  d2  d3   0   0  0  0   d4 d5 d6 d7  0  0  0  0
04322 //
04323 //   RS=1 means that next byte is data, RS=0 means that next byte is command
04324 //   RW=0 means that next byte is writen, RW=1 means that next byte is read (not used in this lib)
04325 //
04326 // Note: SPI3_24 expects LSB first. This is inconsistent with regular SPI convention (and hardware) that sends MSB first.
04327 
04328   if (value) {
04329     _controlbyte = 0xFA; // Next byte is data
04330   }
04331   else {
04332     _controlbyte = 0xF8; // Next byte is command
04333   }   
04334 }    
04335 
04336 // Set BL pin
04337 void TextLCD_SPI_N_3_24::_setBL(bool value) {
04338     if (_bl) {
04339         _bl->write(value);   
04340     }    
04341 }    
04342 
04343 // Not used in this mode
04344 void TextLCD_SPI_N_3_24::_setData(int value) {
04345 }    
04346 
04347 //Mapping table to flip the bits around cause SPI3_24 expects LSB first.
04348 const uint8_t map3_24[16] = {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0};
04349     
04350 // Write a byte using SPI3 24 bits mode
04351 void TextLCD_SPI_N_3_24::_writeByte(int value) {
04352     _cs = 0;
04353     wait_us(1);
04354     _spi->write(_controlbyte);
04355 
04356     //Map and send the LSB nibble
04357     _spi->write( map3_24[value & 0x0F]);     
04358 
04359     //Map and send the MSB nibble
04360     _spi->write( map3_24[(value >> 4) & 0x0F]);     
04361 
04362     wait_us(1);
04363     _cs = 1;
04364 }
04365 #endif /* Native SPI bus     */  
04366 //------- End TextLCD_SPI_N_3_24 ----------