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

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

Fork of TextLCD by Simon Ford

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 ----------