LCDisplay with IIC (I2C)-bus and IC 8574

Fork of TextLCD by Oscar de Jesus Vasquez

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TextLCD.cpp Source File

TextLCD.cpp

00001 /* mbed TextLCD Library, for a 4-bit LCD based on HD44780
00002  * Copyright (c) 2007-2010, sford, http://mbed.org
00003  *               2013, v01: WH, Added LCD types, fixed LCD address issues, added Cursor and UDCs 
00004  *               2013, v02: WH, Added I2C and SPI bus interfaces  
00005  *               2013, v03: WH, Added support for LCD40x4 which uses 2 controllers 
00006  *               2013, v04: WH, Added support for Display On/Off, improved 4bit bootprocess
00007  *               2013, v05: WH, Added support for 8x2B, added some UDCs   
00008  *               2013, v06: WH, Added support for devices that use internal DC/DC converters 
00009  *               2013, v07: WH, Added support for backlight and include portdefinitions for LCD2004 Module from DFROBOT 
00010  *               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  *@Todo Add AC780S/KS0066i
00017  *
00018  * Permission is hereby granted, free of charge, to any person obtaining a copy
00019  * of this software and associated documentation files (the "Software"), to deal
00020  * in the Software without restriction, including without limitation the rights
00021  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00022  * copies of the Software, and to permit persons to whom the Software is
00023  * furnished to do so, subject to the following conditions:
00024  *
00025  * The above copyright notice and this permission notice shall be included in
00026  * all copies or substantial portions of the Software.
00027  *
00028  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00029  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00030  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00031  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00032  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00033  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00034  * THE SOFTWARE.
00035  */
00036 
00037 #include "TextLCD.h"
00038 #include "mbed.h"
00039 
00040 //For Testing only
00041 //DigitalOut led1(LED1);
00042 //DigitalOut led2(LED2);
00043 //  led2=!led2;    
00044 
00045 
00046 // User Defined Characters (UDCs) are defined by an 8 byte bitpattern. The P0..P5 form the character pattern.
00047 //     P7 P6 P5 P4 P3 P2 P1 P0 
00048 // 0   B1 B0  x  0  1  1  1  0
00049 // 1   B1 B0  x  1  0  0  0  1
00050 // .       .............
00051 // 7   B1 B0  x  1  0  0  0  1
00052 //
00053 // Blinking UDCs are enabled when a specific controlbit (BE) is set.
00054 // The blinking pixels in the UDC can be controlled by setting additional bits in the UDC bitpattern.
00055 // Bit 6 and Bit 7 in the pattern will control the blinking mode when Blink is enabled through BE. 
00056 //     B1 B0  Mode
00057 //      0  0  No Blinking in this row of the UDC
00058 //      0  1  Enabled pixels in P4 will blink
00059 //      1  x  Enabled pixels in P0..P4 will blink
00060 
00061 /** Some sample User Defined Chars 5x7 dots */
00062 //const char udc_ae[] = {0x00, 0x00, 0x1B, 0x05, 0x1F, 0x14, 0x1F, 0x00};  //æ
00063 //const char udc_0e[] = {0x00, 0x00, 0x0E, 0x13, 0x15, 0x19, 0x0E, 0x00};  //ø
00064 //const char udc_ao[] = {0x0E, 0x0A, 0x0E, 0x01, 0x0F, 0x11, 0x0F, 0x00};  //å
00065 //const char udc_AE[] = {0x0F, 0x14, 0x14, 0x1F, 0x14, 0x14, 0x17, 0x00};  //Æ
00066 //const char udc_0E[] = {0x0E, 0x13, 0x15, 0x15, 0x15, 0x19, 0x0E, 0x00};  //Ø
00067 //const char udc_Ao[] = {0x0E, 0x0A, 0x0E, 0x11, 0x1F, 0x11, 0x11, 0x00};  //Å
00068 //const char udc_PO[] = {0x04, 0x0A, 0x0A, 0x1F, 0x1B, 0x1B, 0x1F, 0x00};  //Padlock Open
00069 //const char udc_PC[] = {0x1C, 0x10, 0x08, 0x1F, 0x1B, 0x1B, 0x1F, 0x00};  //Padlock Closed
00070 
00071 //const char udc_alpha[] = {0x00, 0x00, 0x0D, 0x12, 0x12, 0x12, 0x0D, 0x00};  //alpha
00072 //const char udc_ohm[]   = {0x0E, 0x11, 0x11, 0x11, 0x0A, 0x0A, 0x1B, 0x00};  //ohm
00073 //const char udc_sigma[] = {0x1F, 0x08, 0x04, 0x02, 0x04, 0x08, 0x1F, 0x00};  //sigma
00074 //const char udc_pi[]    = {0x1F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00};  //pi
00075 //const char udc_root[]  = {0x07, 0x04, 0x04, 0x04, 0x14, 0x0C, 0x04, 0x00};  //root
00076 
00077 const char udc_0[]  = {0x18, 0x14, 0x12, 0x11, 0x12, 0x14, 0x18, 0x00};  // |>
00078 const char udc_1[]  = {0x03, 0x05, 0x09, 0x11, 0x09, 0x05, 0x03, 0x00};  // <|
00079 const char udc_2[]  = {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00};  // |
00080 const char udc_3[]  = {0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00};  // ||
00081 const char udc_4[]  = {0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00};  // |||
00082 const char udc_5[]  = {0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00};  // =
00083 const char udc_6[]  = {0x15, 0x0a, 0x15, 0x0a, 0x15, 0x0a, 0x15, 0x00};  // checkerboard
00084 const char udc_7[]  = {0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x10, 0x00};  // \
00085 
00086 const char udc_degr[]   = {0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00, 0x00};  // Degree symbol
00087 
00088 const char udc_TM_T[]   = {0x1F, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00};  // Trademark T
00089 const char udc_TM_M[]   = {0x11, 0x1B, 0x15, 0x11, 0x00, 0x00, 0x00, 0x00};  // Trademark M
00090 
00091 //const char udc_Bat_Hi[] = {0x0E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00};  // Battery Full
00092 //const char udc_Bat_Ha[] = {0x0E, 0x11, 0x13, 0x17, 0x1F, 0x1F, 0x1F, 0x00};  // Battery Half
00093 //const char udc_Bat_Lo[] = {0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1F, 0x00};  // Battery Low
00094 //const char udc_Bat_Hi[] = {0x0E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00};  // Battery Full
00095 //const char udc_Bat_Ha[] = {0x0E, 0x11, 0x11, 0x1F, 0x1F, 0x1F, 0x1F, 0x00};  // Battery Half
00096 //const char udc_Bat_Lo[] = {0x0E, 0x11, 0x11, 0x11, 0x11, 0x1F, 0x1F, 0x00};  // Battery Low
00097 const char udc_Bat_Hi[] = {0x8E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x00};  // Battery Full, Blink
00098 const char udc_Bat_Ha[] = {0x8E, 0x91, 0x91, 0x9F, 0x9F, 0x9F, 0x9F, 0x00};  // Battery Half, Blink
00099 const char udc_Bat_Lo[] = {0x8E, 0x91, 0x91, 0x91, 0x91, 0x9F, 0x9F, 0x00};  // Battery Low, Blink
00100 const char udc_AC[]     = {0x0A, 0x0A, 0x1F, 0x11, 0x0E, 0x04, 0x04, 0x00};  // AC Power
00101 
00102 //const char udc_smiley[] = {0x00, 0x0A, 0x00, 0x04, 0x11, 0x0E, 0x00, 0x00};  // Smiley
00103 //const char udc_droopy[] = {0x00, 0x0A, 0x00, 0x04, 0x00, 0x0E, 0x11, 0x00};  // Droopey
00104 //const char udc_note[]   = {0x01, 0x03, 0x05, 0x09, 0x0B, 0x1B, 0x18, 0x00};  // Note
00105 
00106 //const char udc_bar_1[]  = {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00};  // Bar 1
00107 //const char udc_bar_2[]  = {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00};  // Bar 11
00108 //const char udc_bar_3[]  = {0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00};  // Bar 111
00109 //const char udc_bar_4[]  = {0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x00};  // Bar 1111
00110 //const char udc_bar_5[]  = {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00};  // Bar 11111
00111 
00112 //const char udc_ch_1[]  =  {0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00};  // Hor bars 4
00113 //const char udc_ch_2[]  =  {0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f};  // Hor bars 4 (inverted)
00114 //const char udc_ch_3[]  =  {0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15};  // Ver bars 3
00115 //const char udc_ch_4[]  =  {0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a};  // Ver bars 3 (inverted)
00116 //const char udc_ch_yr[] =  {0x08, 0x0f, 0x12, 0x0f, 0x0a, 0x1f, 0x02, 0x02};  // Year   (kana)
00117 //const char udc_ch_mo[] =  {0x0f, 0x09, 0x0f, 0x09, 0x0f, 0x09, 0x09, 0x13};  // Month  (kana)
00118 //const char udc_ch_dy[] =  {0x1f, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11, 0x1F};  // Day    (kana)
00119 //const char udc_ch_mi[] =  {0x0C, 0x0a, 0x11, 0x1f, 0x09, 0x09, 0x09, 0x13};  // minute (kana)
00120 
00121 //const char udc_bell[]     = {0x04,0x0E,0x0E,0x0E,0x1F,0x00,0x04};
00122 //const char udc_note[]     = {0x02,0x03,0x02,0x0E,0x1E,0x0C,0x00};
00123 //const char udc_clock[]    = {0x00,0x0E,0x15,0x17,0x11,0x0E,0x00};
00124 //const char udc_heart[]    = {0x00,0x0a,0x1F,0x1F,0x0E,0x04,0x00};
00125 //const char udc_duck[]     = {0x00,0x0c,0x1D,0x0F,0x0F,0x06,0x00};
00126 //const char udc_check[]    = {0x00,0x01,0x03,0x16,0x1C,0x08,0x00};
00127 //const char udc_cross[]    = {0x00,0x1B,0x0E,0x04,0x0E,0x1B,0x00};
00128 //const char udc_retarrow[] = {0x01,0x01,0x05,0x09,0x1f,0x08,0x04};
00129 
00130 const char udc_None[]    =  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 
00131 const char udc_All[]     =  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 
00132     
00133 /** Create a TextLCD_Base interface
00134   *
00135   * @param type  Sets the panel size/addressing mode (default = LCD16x2)
00136   * @param ctrl  LCD controller (default = HD44780)           
00137   */
00138 TextLCD_Base::TextLCD_Base(LCDType type, LCDCtrl ctrl) : _type(type), _ctrl(ctrl) {
00139     
00140   // Extract LCDType data  
00141 
00142   // Columns encoded in b7..b0
00143   _nr_cols = (_type & 0xFF);          
00144 
00145   // Rows encoded in b15..b8  
00146   _nr_rows = ((_type >> 8) & 0xFF);  
00147 
00148   // Addressing mode encoded in b19..b16  
00149   _addr_mode = _type & LCD_T_ADR_MSK;
00150 }
00151 
00152 
00153 /**  Init the LCD Controller(s)
00154   *  Clear display 
00155   */
00156 void TextLCD_Base::_init() {
00157   
00158   // Select and configure second LCD controller when needed
00159   if(_type==LCD40x4) {
00160     _ctrl_idx=_LCDCtrl_1;        // Select 2nd controller   
00161     _initCtrl();                 // Init 2nd controller   
00162   }
00163     
00164   // Select and configure primary LCD controller
00165   _ctrl_idx=_LCDCtrl_0;          // Select primary controller  
00166   _initCtrl();                   // Init primary controller
00167 
00168   // Clear whole display and Reset Cursor location
00169   // Note: This will make sure that some 3-line displays that skip topline of a 4-line configuration 
00170   //       are cleared and init cursor correctly.
00171   cls();   
00172 } 
00173 
00174 /**  Init the LCD controller
00175   *  4-bit mode, number of lines, fonttype, no cursor etc
00176   *
00177   *  Note: some configurations are commented out because they have not yet been tested due to lack of hardware
00178   */
00179 void TextLCD_Base::_initCtrl() {
00180   int _bias_lines=0; // Set Bias and lines (Instr Set 1), temporary variable.
00181   int _lines=0;      // Set lines (Ext Instr Set), temporary variable.
00182       
00183     this->_setRS(false); // command mode
00184     
00185     wait_ms(20);         // Wait 20ms to ensure powered up
00186 
00187     // The Controller could be in 8 bit mode (power-on reset) or in 4 bit mode (warm reboot) at this point.
00188     // Follow this procedure to make sure the Controller enters the correct state. The hardware interface
00189     // between the uP and the LCD can only write the 4 most significant bits (Most Significant Nibble, MSN).
00190     // In 4 bit mode the LCD expects the MSN first, followed by the LSN.
00191     //
00192     //    Current state:               8 bit mode                |  4 bit mode, MSN is next      | 4 bit mode, LSN is next          
00193                          //-------------------------------------------------------------------------------------------------                          
00194     _writeNibble(0x3);   //  set 8 bit mode (MSN) and dummy LSN, |   set 8 bit mode (MSN),       |    set dummy LSN, 
00195                          //  remains in 8 bit mode               |    change to 8 bit mode       |  remains in 4 bit mode
00196     wait_ms(15);         //                           
00197     
00198     _writeNibble(0x3);   //  set 8 bit mode and dummy LSN,       | set 8 bit mode and dummy LSN, |    set 8bit mode (MSN), 
00199                          //  remains in 8 bit mode               |   remains in 8 bit mode       |  remains in 4 bit mode
00200     wait_ms(15);         // 
00201     
00202     _writeNibble(0x3);   //  set 8 bit mode and dummy LSN,       | set 8 bit mode and dummy LSN, |    set dummy LSN, 
00203                          //  remains in 8 bit mode               |   remains in 8 bit mode       |  change to 8 bit mode
00204     wait_ms(15);         // 
00205 
00206     // Controller is now in 8 bit mode
00207 
00208     _writeNibble(0x2);   // Change to 4-bit mode (MSN), the LSN is undefined dummy
00209     wait_us(40);         // most instructions take 40us
00210 
00211     // Display is now in 4-bit mode
00212     // Note: 4/8 bit mode is ignored for most native SPI and I2C devices. They dont use the parallel bus.
00213     //       However, _writeNibble() method is void anyway for native SPI and I2C devices.
00214    
00215     // Device specific initialisations: DC/DC converter to generate VLCD or VLED, number of lines etc
00216     switch (_ctrl) {
00217 
00218       case KS0078:
00219           // Initialise Display configuration
00220           switch (_type) {
00221             case LCD8x1:         //8x1 is a regular 1 line display
00222             case LCD8x2B:        //8x2B is a special case of 16x1
00223 //            case LCD12x1:                                
00224             case LCD16x1:                                            
00225 //            case LCD20x1:
00226             case LCD24x1:
00227               _function  = 0x02;    // Function set 001 DL N RE(0) DH REV (Std Regs)
00228                                     //   DL=0  (4 bits bus)             
00229                                     //    N=0  (1 line mode), N=1 (2 line mode)
00230                                     //   RE=0  (Dis. Extended Regs, special mode for KS0078)
00231                                     //   DH=1  (Disp shift enable, special mode for KS0078)                                
00232                                     //   REV=0 (Reverse normal, special mode for KS0078)
00233                                     
00234               _function_1 = 0x04;   // Function set 001 DL N RE(1) BE 0 (Ext Regs)
00235                                     //   DL=0  (4 bits bus)             
00236                                     //    N=0  (1 line mode), N=1 (2 line mode)
00237                                     //   RE=1  (Ena Extended Regs, special mode for KS0078)
00238                                     //   BE=0  (Blink Enable, CG/SEG RAM, special mode for KS0078)                                
00239                                     //      0 
00240 
00241               _function_x = 0x00;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00242                                     //    NW=0  (1,2 line), NW=1 (4 Line, special mode for KS0078)                                
00243               break;                                
00244 
00245 //            case LCD12x3D:         // Special mode for KS0078 and PCF21XX            
00246 //            case LCD12x3D1:        // Special mode for KS0078 and PCF21XX            
00247 //            case LCD12x4D:         // Special mode for KS0078 and PCF21XX            
00248 //            case LCD16x3D:         // Special mode for KS0078             
00249 //            case LCD16x4D:         // Special mode for KS0078            
00250 //            case LCD24x3D:         // Special mode for KS0078
00251 //            case LCD24x3D1:        // Special mode for KS0078
00252             case LCD24x4D:         // Special mode for KS0078
00253               _function  = 0x02;    // Function set 001 DL N RE(0) DH REV (Std Regs)
00254                                     //   DL=0  (4 bits bus)             
00255                                     //    N=0  (dont care for 4 line mode)              
00256                                     //   RE=0  (Dis. Extended Regs, special mode for KS0078)
00257                                     //   DH=1  (Disp shift enable, special mode for KS0078)                                
00258                                     //   REV=0 (Reverse normal, special mode for KS0078)
00259                                     
00260               _function_1 = 0x04;   // Function set 001 DL N RE(1) BE 0 (Ext Regs)
00261                                     //   DL=0  (4 bits bus)             
00262                                     //    N=0  (1 line mode), N=1 (2 line mode)
00263                                     //   RE=1  (Ena Extended Regs, special mode for KS0078)
00264                                     //   BE=0  (Blink Enable, CG/SEG RAM, special mode for KS0078)                                
00265                                     //      0 
00266 
00267               _function_x = 0x01;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00268                                     //    NW=0  (1,2 line), NW=1 (4 Line, special mode for KS0078)                                
00269               break;                                
00270 
00271             case LCD16x3G:            // Special mode for ST7036                        
00272               error("Error: LCD Controller type does not support this Display type\n\r"); 
00273               break;  
00274               
00275             default:
00276               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)            
00277               _function  = 0x0A;    // Function set 001 DL N RE(0) DH REV (Std Regs)
00278                                     //   DL=0  (4 bits bus)             
00279                                     //    N=1  (1 line mode), N=1 (2 line mode)
00280                                     //   RE=0  (Dis. Extended Regs, special mode for KS0078)
00281                                     //   DH=1  (Disp shift enable, special mode for KS0078)                                
00282                                     //   REV=0 (Reverse normal, special mode for KS0078)
00283                                     
00284               _function_1 = 0x0C;   // Function set 001 DL N RE(1) BE 0 (Ext Regs)
00285                                     //   DL=0  (4 bits bus)             
00286                                     //    N=1  (1 line mode), N=1 (2 line mode)
00287                                     //   RE=1  (Ena Extended Regs, special mode for KS0078)
00288                                     //   BE=0  (Blink Enable, CG/SEG RAM, special mode for KS0078)                                
00289                                     //      0 
00290 
00291               _function_x = 0x00;   // Ext Function set 0000 1 FW BW NW (Ext Regs)
00292                                     //   NW=0  (1,2 line), NW=1 (4 Line, special mode for KS0078)                                
00293               break;
00294           } // switch type
00295 
00296           // init special features
00297           _writeCommand(0x20 | _function_1);// Function set 001 DL N RE(1) BE 0 (Ext Regs)
00298                                            //   DL=0 (4 bits bus), DL=1 (8 bits mode)            
00299                                            //    N=0 (1 line mode), N=1 (2 line mode)
00300                                            //   RE=1 (Ena Extended Regs, special mode for KS0078)
00301                                            //   BE=0 (Blink Enable/Disable, CG/SEG RAM, special mode for KS0078)                                
00302                                            //      0 
00303 
00304           _writeCommand(0x08 | _function_x); // Ext Function set 0000 1 FW BW NW (Ext Regs)
00305                                            //   FW=0  (5-dot font, special mode for KS0078)
00306                                            //   BW=0  (Cur BW invert disable, special mode for KS0078)
00307                                            //   NW=0  (1,2 Line), NW=1 (4 line, special mode for KS0078)                                
00308 
00309           _writeCommand(0x10);             // Scroll/Shift set 0001 DS/HS4 DS/HS3 DS/HS2 DS/HS1 (Ext Regs)
00310                                            //   Dotscroll/Display shift enable (Special mode for KS0078)
00311 
00312           _writeCommand(0x80);             // Scroll Quantity set 1 0 SQ5 SQ4 SQ3 SQ2 SQ1 SQ0 (Ext Regs)
00313                                            //   Scroll quantity (Special mode for KS0078)
00314 
00315           _writeCommand(0x20 | _function); // Function set 001 DL N RE(0) DH REV (Std Regs)
00316                                            //   DL=0  (4 bits bus), DL=1 (8 bits mode)             
00317                                            //    N=0  (1 line mode), N=1 (2 line mode)
00318                                            //   RE=0  (Dis. Extended Regs, special mode for KS0078)
00319                                            //   DH=1  (Disp shift enable/disable, special mode for KS0078)                                
00320                                            //   REV=0 (Reverse/Normal, special mode for KS0078)
00321           break; // case KS0078 Controller
00322               
00323       case ST7032_3V3:
00324           // ST7032 controller: Initialise Voltage booster for VLCD. VDD=3V3
00325       case ST7032_5V:
00326           // ST7032 controller: Disable Voltage booster for VLCD. VDD=5V
00327 
00328           // Initialise Display configuration
00329           switch (_type) {
00330             case LCD8x1:         //8x1 is a regular 1 line display
00331             case LCD8x2B:        //8x2B is a special case of 16x1
00332 //            case LCD12x1:                                
00333             case LCD16x1:                                            
00334 //            case LCD20x1:                    
00335             case LCD24x1:
00336               _function = 0x00;       // FUNCTION SET 0 0 1 DL=0 (4 bit), N=0 (1-line display mode), F=0 (5*7dot), 0, IS
00337                                       // Note: 4 bit mode is ignored for native SPI and I2C devices
00338                                       // Saved to allow switch between Instruction sets at later time
00339               break;  
00340 
00341             case LCD12x3D:            // Special mode for KS0078 and PCF21XX
00342             case LCD12x3D1:           // Special mode for KS0078 and PCF21XX
00343             case LCD12x4D:            // Special mode for KS0078 and PCF21XX
00344             case LCD16x3G:            // Special mode for ST7036                        
00345             case LCD24x4D:            // Special mode for KS0078
00346               error("Error: LCD Controller type does not support this Display type\n\r"); 
00347               break;  
00348 
00349             default:
00350               // All other LCD types are initialised as 2 Line displays        
00351               _function = 0x08;       // FUNCTION SET 0 0 1 DL=0 (4 bit), N=1 (2-line display mode), F=0 (5*7dot), 0, IS              
00352                                       // Note: 4 bit mode is ignored for native SPI and I2C devices
00353                                       // Saved to allow switch between Instruction sets at later time
00354               break;                                                                        
00355           } // switch type    
00356                                      
00357           // init special features 
00358           _writeCommand(0x20 | _function | 0x01);           // Set function,  0 0 1 DL N F 0 IS=1 Select Instr Set = 1              
00359 
00360           _writeCommand(0x1C);                              // Internal OSC frequency adjustment Framefreq=183HZ, Bias will be 1/4 (Instr Set=1)
00361 
00362           _contrast = LCD_ST7032_CONTRAST;              
00363           _writeCommand(0x70 | (_contrast & 0x0F));         // Set Contrast Low bits, 0 1 1 1 C3 C2 C1 C0 (IS=1)
00364 
00365 
00366           if (_ctrl == ST7032_3V3) {
00367             _icon_power = 0x04;                             // Icon display off, Booster circuit is turned on  (IS=1)
00368                                                             // Saved to allow contrast change at later time
00369           }
00370           else { 
00371             _icon_power = 0x00;                             // Icon display off, Booster circuit is turned off  (IS=1)
00372                                                             // Saved to allow contrast change at later time
00373           }
00374           _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03));  // Set Icon, Booster and Contrast High bits, 0 1 0 1 Ion Bon C5 C4 (IS=1)
00375           wait_ms(10);            // Wait 10ms to ensure powered up
00376           
00377           _writeCommand(0x68 | (LCD_ST7032_RAB & 0x07));      // Voltage follower, 0 1 1 0 FOn=1, Ampl ratio Rab2=1, Rab1=0, Rab0=0  (IS=1)
00378           wait_ms(10);            // Wait 10ms to ensure powered up
00379           
00380           _writeCommand(0x20 | _function);                  // Select Instruction Set = 0
00381 
00382           break; // case ST7032_3V3 Controller
00383                  // case ST7032_5V Controller
00384 
00385       case ST7036_3V3:
00386           // ST7036 controller: Initialise Voltage booster for VLCD. VDD=3V3
00387           // Note: supports 1,2 (LCD_T_A) or 3 lines (LCD_T_G)
00388       case ST7036_5V:
00389           // ST7036 controller: Disable Voltage booster for VLCD. VDD=5V
00390           // Note: supports 1,2 (LCD_T_A) or 3 lines (LCD_T_G)
00391                     
00392           // Initialise Display configuration
00393           switch (_type) {
00394             case LCD8x1:         //8x1 is a regular 1 line display
00395             case LCD8x2B:        //8x2D is a special case of 16x1
00396 //            case LCD12x1:                                
00397             case LCD16x1:   
00398             case LCD24x1:                                                                         
00399               _function = 0x00;     // Set function, 0 0 1 DL=0 (4-bit Databus), N=0 (1 Line), DH=0 (5x7font), IS2, IS1 (Select Instruction Set)
00400                                     // Note: 4 bit mode is ignored for native SPI and I2C devices
00401                                     // Saved to allow switch between Instruction sets at later time
00402               
00403               _bias_lines = 0x04;   // Bias: 1/5, 1 or 2-Lines LCD 
00404               break;  
00405 
00406 //            case LCD12x3G:          // Special mode for ST7036
00407             case LCD16x3G:          // Special mode for ST7036
00408               _function = 0x08;     // Set function, 0 0 1 DL=0 (4-bit Databus), N=1 (2 Line), DH=0 (5x7font), IS2,IS1 (Select Instruction Set)              
00409                                     // Note: 4 bit mode is ignored for native SPI and I2C devices
00410                                     // Saved to allow switch between Instruction sets at later time
00411               
00412               _bias_lines = 0x05;   // Bias: 1/5, 3-Lines LCD           
00413               break;  
00414 
00415 //            case LCD12x3D1:           // Special mode for KS0078 and PCF21XX
00416 //            case LCD16x3D1:           // Special mode for SSD1803
00417             case LCD12x4D:            // Special mode for PCF2116
00418             case LCD24x4D:            // Special mode for KS0078
00419               error("Error: LCD Controller type does not support this Display type\n\r"); 
00420               break;  
00421 
00422             default:
00423               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)       
00424               _function = 0x08;     // Set function, 0 0 1 DL=0 (4-bit Databus), N=1 (2 Line), DH=0 (5x7font), IS2,IS1 (Select Instruction Set)
00425                                     // Note: 4 bit mode is ignored for native SPI and I2C devices
00426                                     // Saved to allow switch between Instruction sets at later time
00427               
00428               _bias_lines = 0x04;   // Bias: 1/5, 1 or 2-Lines LCD 
00429               break;                
00430           } // switch type
00431 
00432 
00433           // init special features 
00434           _writeCommand(0x20 | _function | 0x01);   // Set function, IS2,IS1 = 01 (Select Instr Set = 1)
00435           _writeCommand(0x10 | _bias_lines);        // Set Bias and 1,2 or 3 lines (Instr Set 1)
00436 
00437           _contrast = LCD_ST7036_CONTRAST;
00438           _writeCommand(0x70 | (_contrast & 0x0F)); // Set Contrast, 0 1 1 1 C3 C2 C1 C0 (Instr Set 1)
00439                            
00440           if (_ctrl == ST7036_3V3) {
00441             _icon_power = 0x04;                       // Set Icon, Booster, Contrast High bits, 0 1 0 1 Ion=0 Bon=1 C5 C4 (Instr Set 1)
00442                                                       // Saved to allow contrast change at later time
00443           } 
00444           else {
00445             _icon_power = 0x00;                       // Set Icon, Booster, Contrast High bits, 0 1 0 1 Ion=0 Bon=0 C5 C4 (Instr Set 1)             
00446           }
00447           
00448           _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03));   // Set Contrast C5, C4 (Instr Set 1)
00449           wait_ms(10);            // Wait 10ms to ensure powered up
00450 
00451           _writeCommand(0x68 | (LCD_ST7036_RAB & 0x07));  // Voltagefollower On = 1, Ampl ratio Rab2, Rab1, Rab0 = 1 0 1 (Instr Set 1)
00452           wait_ms(10);            // Wait 10ms to ensure powered up
00453 
00454           _writeCommand(0x20 | _function);          // Set function, IS2,IS1 = 00 (Select Instruction Set = 0)
00455          
00456           break; // case ST7036_3V3 Controller
00457                  // case ST7036_5V Controller
00458         
00459       case SSD1803_3V3:
00460           // SSD1803 controller: Initialise Voltage booster for VLCD. VDD=3V3
00461           // Note: supports 1,2, 3 or 4 lines
00462 //      case SSD1803_5V:
00463           // SSD1803 controller: No Voltage booster for VLCD. VDD=5V
00464                     
00465           // Initialise Display configuration
00466           switch (_type) {
00467             case LCD8x1:         //8x1 is a regular 1 line display
00468             case LCD8x2B:        //8x2D is a special case of 16x1
00469 //            case LCD12x1:                                
00470             case LCD16x1:   
00471             case LCD24x1:                                                                         
00472               _function = 0x00;     //  Set function 0 0 1 DL N DH RE(0) IS 
00473                                     //  Saved to allow switch between Instruction sets at later time
00474                                     //    DL=0 4-bit Databus,
00475                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00476                                     //     N=0 1 Line / 3 Line
00477                                     //    DH=0 Double Height disable 
00478                                     //    IS=0
00479           
00480               _function_1 = 0x02;   // Set function, 0 0 1 DL N BE RE(1) REV
00481                                     //  Saved to allow switch between Instruction sets at later time
00482                                     //    DL=0 4-bit Databus,
00483                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00484                                     //     N=0 1 Line / 3 Line
00485                                     //    BE=0 Blink Enable off, special feature of SSD1803
00486                                     //   REV=0 Reverse off, special feature of SSD1803            
00487                         
00488               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00489                                     //    NW=0 1-Line LCD (N=0)
00490               break;  
00491 
00492             case LCD12x3D:          // Special mode for KS0078 and PCF21XX                                  
00493 //            case LCD12x3D1:           // Special mode for KS0078 and PCF21XX            
00494             case LCD16x3D:          // Special mode for KS0078
00495 //            case LCD16x3D1:           // Special mode for SSD1803
00496 //            case LCD20x3D:            // Special mode for SSD1803
00497               _function = 0x00;     //  Set function 0 0 1 DL N DH RE(0) IS 
00498                                     //  Saved to allow switch between Instruction sets at later time
00499                                     //    DL=0 4-bit Databus,
00500                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00501                                     //     N=0 1 Line / 3 Line
00502                                     //    DH=0 Double Height disable 
00503                                     //    IS=0
00504           
00505               _function_1 = 0x02;   // Set function, 0 0 1 DL N BE RE(1) REV
00506                                     //  Saved to allow switch between Instruction sets at later time
00507                                     //    DL=0 4-bit Databus,
00508                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00509                                     //     N=0 1 Line / 3 Line
00510                                     //    BE=0 Blink Enable off, special feature of SSD1803
00511                                     //   REV=0 Reverse off, special feature of SSD1803            
00512                         
00513               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00514                                     //    NW=1 3-Line LCD (N=0)
00515               break;  
00516 
00517             case LCD20x4D:          // Special mode for SSD1803
00518               _function = 0x08;     //  Set function 0 0 1 DL N DH RE(0) IS 
00519                                     //  Saved to allow switch between Instruction sets at later time
00520                                     //    DL=0 4-bit Databus,
00521                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00522                                     //     N=1 4 Line
00523                                     //    DH=0 Double Height disable 
00524                                     //    IS=0
00525           
00526               _function_1 = 0x0A;   // Set function, 0 0 1 DL N BE RE(1) REV
00527                                     //  Saved to allow switch between Instruction sets at later time
00528                                     //    DL=0 4-bit Databus,
00529                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00530                                     //     N=1 4 Line
00531                                     //    BE=0 Blink Enable off, special feature of SSD1803
00532                                     //   REV=0 Reverse off, special feature of SSD1803            
00533                         
00534               _lines = 0x01;        // Ext function set 0 0 0 0 1 FW BW NW 
00535                                     //    NW=1 4-Line LCD (N=1)
00536               break;  
00537 
00538             case LCD16x3G:          // Special mode for ST7036            
00539             case LCD24x4D:          // Special mode for KS0078
00540               error("Error: LCD Controller type does not support this Display type\n\r"); 
00541               break;  
00542 
00543             default:
00544               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)       
00545               _function = 0x08;     //  Set function 0 0 1 DL N DH RE(0) IS 
00546                                     //  Saved to allow switch between Instruction sets at later time
00547                                     //    DL=0 4-bit Databus,
00548                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00549                                     //     N=1 2 line / 4 Line
00550                                     //    DH=0 Double Height disable 
00551                                     //    IS=0
00552           
00553               _function_1 = 0x0A;   // Set function, 0 0 1 DL N BE RE(1) REV
00554                                     //  Saved to allow switch between Instruction sets at later time
00555                                     //    DL=0 4-bit Databus,
00556                                     //         Note: 4 bit mode is ignored for native SPI and I2C devices
00557                                     //     N=1 2 line / 4 Line
00558                                     //    BE=0 Blink Enable off, special feature of SSD1803
00559                                     //   REV=0 Reverse off, special feature of SSD1803            
00560                         
00561               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00562                                     //    NW=0 2-Line LCD (N=1)
00563               break;                
00564           } // switch type
00565 
00566 
00567           // init special features 
00568           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
00569                                                     // Select Extended Instruction Set
00570           
00571           _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)
00572 //          _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)          
00573           wait_ms(5);                               // Wait to ensure completion or SSD1803 fails to set Top/Bottom after reset..
00574          
00575           _writeCommand(0x08 | _lines);             // Set ext function 0 0 0 0 1 FW BW NW 1,2,3 or 4 lines (Ext Instr Set)
00576 
00577           _writeCommand(0x10);                      // Double Height and Bias, 0 0 0 1 UD2=0, UD1=0, BS1=0 Bias 1/5, DH=0 (Ext Instr Set)
00578 
00579 //          _writeCommand(0x76);                      // Set TC Control, 0 1 1 1 0 1 1 0 (Ext Instr Set)
00580 //          _writeData(0x02);                         // Set TC data,    0 0 0 0 0 TC2,TC1,TC0 = 0 1 0 (Ext Instr Set)
00581 
00582           _writeCommand(0x20 | _function | 0x01);   // Set function, 0 0 1 DL N DH RE(0) IS=1 Select Instruction Set 1
00583                                                     // Select Std Instr set, Select IS=1  
00584 
00585           _contrast = LCD_SSD1_CONTRAST;
00586           _writeCommand(0x70 | (_contrast & 0x0F)); // Set Contrast 0 1 1 1 C3, C2, C1, C0 (Instr Set 1)
00587                            
00588           _icon_power = 0x04;                       // Icon off, Booster on (Instr Set 1)
00589                                                     // Saved to allow contrast change at later time
00590           _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03));   // Set Power, Icon and Contrast, 0 1 0 1 Ion Bon C5 C4 (Instr Set 1)
00591           wait_ms(10);            // Wait 10ms to ensure powered up
00592 
00593           _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)
00594           wait_ms(10);            // Wait 10ms to ensure powered up
00595 
00596           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
00597                                                     // Select Extended Instruction Set 1
00598           _writeCommand(0x10);                      // Shift/Scroll enable, 0 0 0 1 DS4/HS4 DS3/HS3 DS2/HS2 DS1/HS1  (Ext Instr Set 1)
00599 
00600 
00601           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
00602                                                     // Select Std Instr set, Select IS=0
00603          
00604           break; // case SSD1803 Controller
00605 
00606           
00607       // Note1: The PCF21XX family of controllers has several types that dont have an onboard voltage generator for V-LCD.
00608       //        You must supply this LCD voltage externally and not try to enable VGen. 
00609       // Note2: The early versions of PCF2116 controllers (eg PCF2116C) can not generate sufficiently negative voltage for the LCD at a VDD of 3V3. 
00610       //        You must supply this voltage externally and not enable VGen or you must use a higher VDD (e.g. 5V) and enable VGen.
00611       //        More recent versions of the controller (eg PCF2116K) have an improved VGen that will work with 3V3.
00612       // 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 
00613       //        contrast control similar to that of pin 3 on the standard 14pin LCD module connector.
00614       //        You can disable VGen by connecting Vo to VDD. VLCD will then be used directly as LCD voltage.
00615       // 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.
00616       //        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.                    
00617       // Note5: See datasheet, members of the PCF21XX family support different numbers of rows/columns. Not all can support 3 or 4 rows.
00618       // 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..
00619 
00620       case PCF2113_3V3:
00621           // PCF2113 controller: Initialise Voltage booster for VLCD. VDD=3V3. VA and VB control contrast.
00622           // Initialise Display configuration
00623           switch (_type) {
00624 //            case LCD12x1:                                
00625 //              _function = 0x02;       // FUNCTION SET 0 0 1 DL=0 4 bit, 0, M=0 1-line/12 chars display mode, SL=1, IS=0
00626                                       // Note: 4 bit mode is ignored for I2C mode
00627             case LCD24x1:                    
00628               _function = 0x00;       // FUNCTION SET 0 0 1 DL=0 4 bit, 0, M=0 1-line/24 chars display mode, SL=0, IS=0            
00629                                       // Note: 4 bit mode is ignored for I2C mode
00630               break;  
00631 
00632 //Tested OK for PCF2113
00633             case LCD12x2:                    
00634               _function = 0x04;       // FUNCTION SET 0 0 1 DL=0 4 bit, 0, M=1 2-line/12 chars display mode, SL=0, IS=0            
00635               break;  
00636              
00637             default:
00638               error("Error: LCD Controller type does not support this Display type\n\r"); 
00639               break;  
00640                          
00641           } // switch type    
00642 
00643           // Init special features
00644           _writeCommand(0x20 | _function | 0x01);          // Set function, Select Instr Set = 1              
00645 
00646           _writeCommand(0x04);                             // Display Conf Set         0000 0, 1, P=0, Q=0               (Instr. Set 1)
00647           _writeCommand(0x10);                             // Temp Compensation Set    0001 0, 0, TC1=0, TC2=0           (Instr. Set 1)
00648 //          _writeCommand(0x42);                             // HV GEN                   0100 S1=1, S2=0 (2x multiplier)   (Instr. Set 1)
00649           _writeCommand(0x40 | (LCD_PCF2_S12 & 0x03));     // HV Gen                   0100 S1=1, S2=0 (2x multiplier)   (Instr. Set 1)
00650           
00651           _contrast = LCD_PCF2_CONTRAST;              
00652           _writeCommand(0x80 | 0x00 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)  1, V=0, VA=contrast
00653           _writeCommand(0x80 | 0x40 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)  1, V=1, VB=contrast
00654           wait_ms(10);            // Wait 10ms to ensure powered up
00655           
00656           _writeCommand(0x02);                             // Screen Config            0000 001, L=0  (Instr. Set 1)
00657           _writeCommand(0x08);                             // ICON Conf                0000 1, IM=0 (Char mode), IB=0 (no icon blink) DM=0 (no direct mode) (Instr. Set 1) 
00658 
00659           _writeCommand(0x20 | _function);                 // Set function, Select Instr Set = 0             
00660 
00661           break; // case PCF2113_3V3 Controller
00662 
00663 
00664 //      case PCF2113_5V:
00665           // PCF2113 controller: No Voltage generator for VLCD. VDD=5V. Contrast voltage controlled by VA or VB.
00666 //@TODO                            
00667 
00668 
00669       case PCF2116_3V3:
00670           // PCF2116 controller: Voltage generator for VLCD. VDD=5V. V0 controls contrast voltage.                 
00671           // Initialise Display configuration
00672           switch (_type) {
00673 //            case LCD12x1:
00674 //            case LCD12x2:                                                                            
00675             case LCD24x1:                    
00676               _writeCommand(0x22);    //FUNCTION SET 4 bit, N/M=0 1-line/24 chars display mode, G=1 Vgen on 
00677                                       //Note: 4 bit mode is ignored for I2C mode
00678               wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00679               break;  
00680 
00681             case LCD12x3D:            // Special mode for KS0078 and PCF21XX                            
00682             case LCD12x3D1:           // Special mode for PCF21XX                     
00683             case LCD12x4D:            // Special mode for PCF21XX:
00684               _writeCommand(0x2E);    //FUNCTION SET 4 bit, N=1/M=1 4-line/12 chars display mode, G=1 VGen on                               
00685                                       //Note: 4 bit mode is ignored for I2C mode              
00686               wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00687               break;  
00688 
00689             case LCD24x2:
00690               _writeCommand(0x2A);    //FUNCTION SET 4 bit, N=1/M=0 2-line/24 chars display mode, G=1 VGen on
00691                                       //Note: 4 bit mode is ignored for I2C mode
00692               wait_ms(10);            // Wait 10ms to ensure powered up   
00693               break;  
00694               
00695             default:
00696               error("Error: LCD Controller type does not support this Display type\n\r"); 
00697               break;  
00698             
00699           } // switch type    
00700 
00701           break; // case PCF2116_3V3 Controller
00702 
00703 
00704 //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
00705 //@TODO                            
00706       case PCF2116_5V:
00707           // PCF2116 controller: No Voltage generator for VLCD. VDD=5V. V0 controls contrast voltage.                           
00708           // Initialise Display configuration
00709           switch (_type) {
00710 //            case LCD12x1:
00711 //            case LCD12x2:                                                                            
00712 //            case LCD24x1:                    
00713 //              _writeCommand(0x20);    //FUNCTION SET 4 bit, N/M=0 1-line/24 chars display mode 
00714                                       //Note: 4 bit mode is ignored for I2C mode
00715 //              wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00716 //              break;  
00717 
00718             case LCD12x3D:            // Special mode for KS0078 and PCF21XX                            
00719             case LCD12x3D1:           // Special mode for PCF21XX                     
00720             case LCD12x4D:            // Special mode for PCF21XX:
00721 //              _writeCommand(0x34);    //FUNCTION SET 8 bit, N=0/M=1 4-line/12 chars display mode      OK
00722 //              _writeCommand(0x24);    //FUNCTION SET 4 bit, N=0/M=1 4-line/12 chars display mode      OK                                            
00723               _writeCommand(0x2C);    //FUNCTION SET 4 bit, N=1/M=1 4-line/12 chars display mode        OK                                                   
00724                                       //Note: 4 bit mode is ignored for I2C mode              
00725               wait_ms(10);            // Wait 10ms to ensure powered up                                                    
00726               break;  
00727 
00728 //            case LCD24x2:
00729 //              _writeCommand(0x28);    //FUNCTION SET 4 bit, N=1/M=0 2-line/24 chars display mode
00730                                       //Note: 4 bit mode is ignored for I2C mode
00731 //              wait_ms(10);            // Wait 10ms to ensure powered up   
00732 //              break;  
00733               
00734             default:
00735               error("Error: LCD Controller type does not support this Display type\n\r"); 
00736               break;  
00737             
00738           } // switch type    
00739 
00740           break; // case PCF2116_5V Controller
00741 
00742       case PCF2119_3V3:
00743           // PCF2119 controller: Initialise Voltage booster for VLCD. VDD=3V3. VA and VB control contrast.
00744           // Note1: See datasheet, the PCF2119 supports icons and provides separate constrast control for Icons and characters.
00745           // Note2: Vgen is switched off when the contrast voltage VA or VB is set to 0x00.
00746                   
00747 //POR or Hardware Reset should be applied
00748           wait_ms(10);            // Wait 10ms to ensure powered up   
00749 
00750           // Initialise Display configuration
00751           switch (_type) {
00752             case LCD8x1:
00753 //            case LCD12x1:
00754             case LCD16x1:           
00755               _function = 0x02;       // FUNCTION SET DL=0 4 bit, 0 , M=0 1-line/16 chars display mode, SL=1
00756                                       // Note: 4 bit mode is ignored for I2C mode
00757               break;  
00758             
00759             case LCD24x1:                    
00760 //            case LCD32x1:                                
00761               _function = 0x00;       // FUNCTION SET DL=0 4 bit, 0 , M=0 1-line/32 chars display mode, SL=0
00762                                       // Note: 4 bit mode is ignored for I2C mode
00763               break;  
00764 
00765             case LCD8x2:
00766 //            case LCD12x2:            
00767             case LCD16x2:
00768               _function = 0x04;       // FUNCTION SET DL=0 4 bit, 0, M=1 2-line/16 chars display mode, SL=0
00769                                       // Note: 4 bit mode is ignored for I2C mode
00770               break;  
00771              
00772             default:
00773               error("Error: LCD Controller type does not support this Display type\n\r"); 
00774               break;  
00775             
00776           } // switch type    
00777 
00778           // Init special features 
00779           _writeCommand(0x20 | _function | 0x01);           // Set function, Select Instruction Set = 1              
00780 
00781           _writeCommand(0x04);    // DISP CONF SET (Instr. Set 1)   0000, 0, 1, P=0, Q=0 
00782           _writeCommand(0x10);    // TEMP CTRL SET (Instr. Set 1)   0001, 0, 0, TC1=0, TC2=0
00783 //          _writeCommand(0x42);    // HV GEN (Instr. Set 1)          0100, 0, 0, S1=1, S2=0 (2x multiplier)
00784           _writeCommand(0x40 | (LCD_PCF2_S12 & 0x03));      // HV GEN (Instr. Set 1)          0100, 0, 0, S1=1, S2=0 (2x multiplier)
00785 
00786           _contrast = LCD_PCF2_CONTRAST;              
00787           _writeCommand(0x80 | 0x00 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)    V=0, VA=contrast
00788           _writeCommand(0x80 | 0x40 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)    V=1, VB=contrast
00789           wait_ms(10);            // Wait 10ms to ensure powered up
00790           
00791           _writeCommand(0x02);    // SCRN CONF (Instr. Set 1)    L=0
00792           _writeCommand(0x08);    // ICON CONF (Instr. Set 1)    IM=0 (Char mode) IB=0 (no icon blink) DM=0 (no direct mode)
00793 
00794           _writeCommand(0x20 | _function);                  // Select Instruction Set = 0
00795 
00796           break; // case PCF2119_3V3 Controller
00797 
00798 //      case PCF2119_5V:
00799           // PCF2119 controller: No Voltage booster for VLCD. VDD=3V3. VA and VB control contrast.
00800           // Note1: See datasheet, the PCF2119 supports icons and provides separate constrast control for Icons and characters.
00801           // Note2: Vgen is switched off when the contrast voltage VA or VB is set to 0x00.                     
00802 //@TODO                            
00803 
00804       case WS0010:         
00805           // WS0010 OLED controller: Initialise DC/DC Voltage converter for LEDs
00806           // Note1: Identical to RS0010  
00807           // Note2: supports 1 or 2 lines (and 16x100 graphics)
00808           //        supports 4 fonts (English/Japanese (default), Western European-I, English/Russian, Western European-II)
00809                            // Cursor/Disp shift set 0001 SC RL  0 0
00810                            //
00811                            // Mode and Power set    0001 GC PWR 1 1                           
00812                            //  GC  = 0 (Graph Mode=1, Char Mode=0)             
00813                            //  PWR = 1 (DC/DC On/Off)
00814    
00815 //@Todo: This may be needed to enable a warm reboot
00816           //_writeCommand(0x13);   // Char mode, DC/DC off              
00817           //wait_ms(10);           // Wait 10ms to ensure powered down                  
00818           _writeCommand(0x17);   // Char mode, DC/DC on        
00819           wait_ms(10);           // Wait 10ms to ensure powered up        
00820 
00821           // Initialise Display configuration
00822           switch (_type) {                    
00823             case LCD8x1:         //8x1 is a regular 1 line display
00824             case LCD8x2B:        //8x2B is a special case of 16x1
00825 //            case LCD12x1:                                
00826             case LCD16x1:                                            
00827             case LCD24x1:
00828               _writeCommand(0x20); // Function set 001 DL N F FT1 FT0
00829                                    //  DL=0  (4 bits bus)             
00830                                    //   N=0  (1 line)
00831                                    //   F=0  (5x7 dots font)
00832                                    //  FT=00 (00 = Engl/Jap, 01 = WestEur1, 10 = Engl/Russian, 11 = WestEur2
00833               break;  
00834 
00835             case LCD12x3D:            // Special mode for KS0078 and PCF21XX                            
00836             case LCD12x3D1:           // Special mode for PCF21XX                     
00837             case LCD12x4D:            // Special mode for PCF21XX:
00838             case LCD16x3G:            // Special mode for ST7036            
00839             case LCD24x4D:            // Special mode for KS0078
00840               error("Error: LCD Controller type does not support this Display type\n\r"); 
00841               break;  
00842 
00843             default:
00844               // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)       
00845               _writeCommand(0x28); // Function set 001 DL N F FT1 FT0
00846                                    //  DL=0  (4 bits bus)
00847                                    //   N=1  (2 lines)
00848                                    //   F=0  (5x7 dots font)
00849                                    //  FT=00 (00 = Engl/Jap, 01 = WestEur1, 10 = Engl/Russian, 11 = WestEur2
00850 
00851               break;
00852            } // switch type
00853            
00854            break; // case WS0010 Controller
00855 
00856 
00857       case US2066_3V3:
00858           // US2066/SSD1311 OLED controller, Initialise for VDD=3V3
00859           // Note: supports 1,2, 3 or 4 lines
00860 //      case USS2066_5V:
00861           // US2066 controller, VDD=5V
00862                     
00863           // Initialise Display configuration
00864           switch (_type) {
00865             case LCD8x1:         //8x1 is a regular 1 line display
00866             case LCD8x2B:        //8x2D is a special case of 16x1
00867 //            case LCD12x1:                                
00868             case LCD16x1:   
00869 //            case LCD20x1:                                                                         
00870               _function = 0x00;     //  Set function 0 0 1 X N DH RE(0) IS 
00871                                     //  Saved to allow switch between Instruction sets at later time
00872                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead
00873                                     //     N=0 1 Line / 3 Line
00874                                     //    DH=0 Double Height disable 
00875                                     //    IS=0
00876           
00877               _function_1 = 0x02;   // Set function, 0 0 1 X N BE RE(1) REV
00878                                     //  Saved to allow switch between Instruction sets at later time
00879                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                    
00880                                     //     N=0 1 Line / 3 Line
00881                                     //    BE=0 Blink Enable off, special feature of SSD1803, US2066
00882                                     //   REV=0 Reverse off, special feature of SSD1803, US2066            
00883                         
00884               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00885                                     //    NW=0 1-Line LCD (N=0)
00886               break;  
00887 
00888             case LCD16x1C:
00889             case LCD8x2:
00890             case LCD16x2:
00891             case LCD20x2:            
00892               _function = 0x08;     //  Set function 0 0 1 X N DH RE(0) IS 
00893                                     //  Saved to allow switch between Instruction sets at later time
00894                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                                                        
00895                                     //     N=1 2 line / 4 Line
00896                                     //    DH=0 Double Height disable 
00897                                     //    IS=0
00898           
00899               _function_1 = 0x0A;   // Set function, 0 0 1 X N BE RE(1) REV
00900                                     //  Saved to allow switch between Instruction sets at later time
00901                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                                                        
00902                                     //     N=1 2 line / 4 Line
00903                                     //    BE=0 Blink Enable off, special feature of SSD1803, US2066
00904                                     //   REV=0 Reverse off, special feature of SSD1803, US2066            
00905                         
00906               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00907                                     //    NW=0 2-Line LCD (N=1)
00908               break;                
00909 
00910             case LCD12x3D:          // Special mode for KS0078 and PCF21XX 
00911 //            case LCD12x3D1:           // Special mode for KS0078 and PCF21XX            
00912             case LCD16x3D:          // Special mode for KS0078, SSD1803 and US2066
00913 //            case LCD16x3D1:           // Special mode for SSD1803, US2066
00914 //            case LCD20x3D:            // Special mode for SSD1803, US2066
00915               _function = 0x00;     //  Set function 0 0 1 X N DH RE(0) IS 
00916                                     //  Saved to allow switch between Instruction sets at later time
00917                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                    
00918                                     //     N=0 1 Line / 3 Line
00919                                     //    DH=0 Double Height disable 
00920                                     //    IS=0
00921           
00922               _function_1 = 0x02;   // Set function, 0 0 1 X N BE RE(1) REV
00923                                     //  Saved to allow switch between Instruction sets at later time
00924                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead                                    
00925                                     //     N=0 1 Line / 3 Line
00926                                     //    BE=0 Blink Enable off, special feature of SSD1803, US2066
00927                                     //   REV=0 Reverse off, special feature of SSD1803, US2066            
00928                         
00929               _lines = 0x00;        // Ext function set 0 0 0 0 1 FW BW NW 
00930                                     //    NW=1 3-Line LCD (N=0)
00931               break;  
00932 
00933             case LCD20x4D:          // Special mode for SSD1803, US2066
00934               _function = 0x08;     //  Set function 0 0 1 X N DH RE(0) IS 
00935                                     //  Saved to allow switch between Instruction sets at later time
00936                                     //    DL=X bit is ignored for US2066. Uses hardwired pins instead
00937                                     //     N=1 2 line / 4 Line
00938                                     //    DH=0 Double Height disable 
00939                                     //    IS=0
00940           
00941               _function_1 = 0x0A;   // Set function, 0 0 1 DL N BE RE(1) REV
00942                                     //  Saved to allow switch between Instruction sets at later time
00943                                     //    DL=0 bit is ignored for US2066. Uses hardwired pins instead                                    
00944                                     //     N=1 2 line / 4 Line
00945                                     //    BE=0 Blink Enable off, special feature of SSD1803, US2066
00946                                     //   REV=0 Reverse off, special feature of SSD1803, US2066            
00947                         
00948               _lines = 0x01;        // Ext function set 0 0 0 0 1 FW BW NW 
00949                                     //    NW=1 4-Line LCD (N=1)
00950               break;  
00951 
00952 //            case LCD24x1:                                                                         
00953 //            case LCD16x3G:          // Special mode for ST7036            
00954 //            case LCD24x4D:          // Special mode for KS0078
00955             default:            
00956               error("Error: LCD Controller type does not support this Display type\n\r"); 
00957               break;  
00958 
00959           } // switch type
00960 
00961 
00962           // init special features 
00963           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
00964                                                     // Select Extended Instruction Set
00965 
00966           _writeCommand(0x71);                      // Function Select A: 0 1 1 1 0 0 0 1 (Ext Instr Set)
00967           _writeData(0x00);                         // Disable Internal VDD
00968 
00969           _writeCommand(0x79);                      // Function Select OLED:  0 1 1 1 1 0 0 1 (Ext Instr Set)
00970 
00971           _writeCommand(0xD5);                      // Display Clock Divide Ratio: 1 1 0 1 0 1 0 1 (Ext Instr Set, OLED Instr Set)
00972           _writeCommand(0x70);                      // Display Clock Divide Ratio value: 0 1 1 1 0 0 0 0 (Ext Instr Set, OLED Instr Set)
00973                     
00974           _writeCommand(0x78);                      // Function Disable OLED: 0 1 1 1 1 0 0 0 (Ext Instr Set)
00975           
00976 //          _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)
00977           _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)          
00978          
00979           _writeCommand(0x08 | _lines);             // Set ext function 0 0 0 0 1 FW BW NW 1,2,3 or 4 lines (Ext Instr Set)
00980 
00981 //          _writeCommand(0x1C);                      // Double Height and Bias, 0 0 0 1 UD2=1, UD1=1, X, DH=0 (Ext Instr Set)
00982 //                                                    // Default
00983 
00984           _writeCommand(0x72);                      // Function Select B: 0 1 1 1 0 0 1 0 (Ext Instr Set)
00985           _writeData(0x01);                         // Select ROM A (CGRAM 8, CGROM 248)
00986 
00987           _writeCommand(0x79);                      // Function Select OLED:  0 1 1 1 1 0 0 1 (Ext Instr Set)
00988 
00989           _writeCommand(0xDA);                      // Set Segm Pins Config:  1 1 0 1 1 0 1 0 (Ext Instr Set, OLED)
00990           _writeCommand(0x10);                      // Set Segm Pins Config value: Altern Odd/Even, Disable Remap (Ext Instr Set, OLED)
00991 
00992           _writeCommand(0xDC);                      // Function Select C: 1 1 0 1 1 1 0 0 (Ext Instr Set, OLED)
00993 //          _writeCommand(0x00);                      // Set internal VSL, GPIO pin HiZ (always read low)
00994           _writeCommand(0x80);                      // Set external VSL, GPIO pin HiZ (always read low)
00995 
00996           _contrast = LCD_US20_CONTRAST;
00997           _writeCommand(0x81);                      // Set Contrast Control: 1 0 0 0 0 0 0 1 (Ext Instr Set, OLED)
00998           _writeCommand((_contrast << 2) | 0x03);   // Set Contrast Value: 8 bits, use 6 bits for compatibility 
00999 
01000           _writeCommand(0xD9);                      // Set Phase Length: 1 1 0 1 1 0 0 1 (Ext Instr Set, OLED)
01001           _writeCommand(0xF1);                      // Set Phase Length Value: 
01002 
01003           _writeCommand(0xDB);                      // Set VCOMH Deselect Lvl: 1 1 0 1 1 0 1 1 (Ext Instr Set, OLED)
01004           _writeCommand(0x30);                      // Set VCOMH Deselect Value: 0.83 x VCC
01005 
01006           wait_ms(10);            // Wait 10ms to ensure powered up
01007 
01008 //Test Fade/Blinking. Hard Blink on/off, No fade in/out ??
01009 //          _writeCommand(0x23);                      // Set (Ext Instr Set, OLED)
01010 //          _writeCommand(0x3F);                      // Set interval 128 frames
01011 //End Test Blinking
01012 
01013           _writeCommand(0x78);                      // Function Disable OLED: 0 1 1 1 1 0 0 0 (Ext Instr Set)
01014           
01015           _writeCommand(0x20 | _function | 0x01);   // Set function, 0 0 1 X N DH RE(0) IS=1 Select Instruction Set 1
01016                                                     // Select Std Instr set, Select IS=1  
01017 
01018           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
01019                                                     // Select Ext Instr Set, IS=1
01020           _writeCommand(0x10);                      // Shift/Scroll enable, 0 0 0 1 DS4/HS4 DS3/HS3 DS2/HS2 DS1/HS1  (Ext Instr Set, IS=1)
01021 
01022 
01023           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
01024                                                     // Select Std Instr set, Select IS=0
01025          
01026           break; // case US2066/SSD1311 Controller
01027 
01028            
01029         default:
01030           // Devices fully compatible to HD44780 that do not use any DC/DC Voltage converters but external VLCD, no icons etc
01031 
01032           // Initialise Display configuration
01033           switch (_type) {
01034             case LCD8x1:         //8x1 is a regular 1 line display
01035             case LCD8x2B:        //8x2B is a special case of 16x1
01036 //            case LCD12x1:                                
01037             case LCD16x1:                                            
01038 //            case LCD20x1:                                                        
01039             case LCD24x1:
01040 //            case LCD40x1:            
01041               _function = 0x00;    // Function set 001 DL N F - -
01042                                    //  DL=0 (4 bits bus)             
01043                                    //   N=0 (1 line)
01044                                    //   F=0 (5x7 dots font)
01045               _writeCommand(0x20 | _function);             
01046               break;                                
01047                                                   
01048             case LCD12x3D:            // Special mode for KS0078 and PCF21XX                            
01049             case LCD12x3D1:           // Special mode for KS0078 and PCF21XX                     
01050             case LCD12x4D:            // Special mode for KS0078 and PCF21XX:
01051             case LCD16x3D:            // Special mode for KS0078
01052 //            case LCD16x3D1:           // Special mode for KS0078
01053 //            case LCD24x3D:            // Special mode for KS0078
01054 //            case LCD24x3D1:           // Special mode for KS0078            
01055             case LCD24x4D:            // Special mode for KS0078
01056               error("Error: LCD Controller type does not support this Display type\n\r"); 
01057               break;  
01058 
01059             // All other LCD types are initialised as 2 Line displays (including LCD16x1C and LCD40x4)
01060             default:
01061               _function = 0x08;    // Function set 001 DL N F - -
01062                                    //  DL=0 (4 bits bus)
01063                                    //  Note: 4 bit mode is ignored for native SPI and I2C devices                                 
01064                                    //   N=1 (2 lines)
01065                                    //   F=0 (5x7 dots font, only option for 2 line display)
01066                                    //    -  (Don't care)
01067               _writeCommand(0x20 | _function);                         
01068               break;
01069           } // switch type
01070 
01071           break; // case default Controller
01072           
01073     } // switch Controller specific initialisations 
01074     
01075 
01076     // Controller general initialisations                                          
01077 //    _writeCommand(0x01); // cls, and set cursor to 0
01078 //    wait_ms(10);         // The CLS command takes 1.64 ms.
01079 //                         // Since we are not using the Busy flag, Lets be safe and take 10 ms  
01080 
01081     _writeCommand(0x02); // Return Home 
01082                          //   Cursor Home, DDRAM Address to Origin
01083 
01084     _writeCommand(0x06); // Entry Mode 0000 0 1 I/D S 
01085                          //   Cursor Direction and Display Shift
01086                          //   I/D=1 (Cur incr)
01087                          //     S=0 (No display shift)                        
01088 
01089     _writeCommand(0x14); // Cursor or Display shift 0001 S/C R/L x x 
01090                          //   S/C=0 Cursor moves
01091                          //   R/L=1 Right
01092                          // 
01093 
01094 //    _writeCommand(0x0C); // Display Ctrl 0000 1 D C B
01095 //                         //   Display On, Cursor Off, Blink Off   
01096     setCursor(CurOff_BlkOff);     
01097     setMode(DispOn);     
01098 }
01099 
01100 
01101 /** Clear the screen, Cursor home. 
01102   */
01103 void TextLCD_Base::cls() {
01104 
01105   // Select and configure second LCD controller when needed
01106   if(_type==LCD40x4) {
01107     _ctrl_idx=_LCDCtrl_1; // Select 2nd controller
01108 
01109     // Second LCD controller Cursor always Off
01110     _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
01111 
01112     // Second LCD controller Clearscreen
01113     _writeCommand(0x01);  // cls, and set cursor to 0    
01114     wait_ms(10);          // The CLS command takes 1.64 ms.
01115                           // Since we are not using the Busy flag, Lets be safe and take 10 ms
01116   
01117     _ctrl_idx=_LCDCtrl_0; // Select primary controller
01118   }
01119   
01120   // Primary LCD controller Clearscreen
01121   _writeCommand(0x01);    // cls, and set cursor to 0
01122   wait_ms(10);            // The CLS command takes 1.64 ms.
01123                           // Since we are not using the Busy flag, Lets be safe and take 10 ms
01124 
01125   // Restore cursormode on primary LCD controller when needed
01126   if(_type==LCD40x4) {
01127     _setCursorAndDisplayMode(_currentMode,_currentCursor);     
01128   }
01129                    
01130   setAddress(0, 0);  // Reset Cursor location
01131                      // Note: This is needed because some displays (eg PCF21XX) don't use line 0 in the '3 Line' mode.   
01132 }
01133 
01134 /** Locate cursor to a screen column and row
01135   *
01136   * @param column  The horizontal position from the left, indexed from 0
01137   * @param row     The vertical position from the top, indexed from 0
01138   */ 
01139 void TextLCD_Base::locate(int column, int row) {
01140     
01141    // setAddress() does all the heavy lifting:
01142    //   check column and row sanity, 
01143    //   switch controllers for LCD40x4 if needed
01144    //   switch cursor for LCD40x4 if needed
01145    //   set the new memory address to show cursor at correct location
01146    setAddress(column, row);      
01147 }
01148    
01149 
01150 /** Write a single character (Stream implementation)
01151   */
01152 int TextLCD_Base::_putc(int value) {
01153   int addr;
01154     
01155     if (value == '\n') {
01156       //No character to write
01157       
01158       //Update Cursor      
01159       _column = 0;
01160       _row++;
01161       if (_row >= rows()) {
01162         _row = 0;
01163       }      
01164     }
01165     else {
01166       //Character to write      
01167       _writeData(value); 
01168               
01169       //Update Cursor
01170       _column++;
01171       if (_column >= columns()) {
01172         _column = 0;
01173         _row++;
01174         if (_row >= rows()) {
01175           _row = 0;
01176         }
01177       }          
01178     } //else
01179 
01180     //Set next memoryaddress, make sure cursor blinks at next location
01181     addr = getAddress(_column, _row);
01182     _writeCommand(0x80 | addr);
01183             
01184     return value;
01185 }
01186 
01187 
01188 // get a single character (Stream implementation)
01189 int TextLCD_Base::_getc() {
01190     return -1;
01191 }
01192 
01193 
01194 // Write a nibble using the 4-bit interface
01195 void TextLCD_Base::_writeNibble(int value) {
01196 
01197 // Enable is Low
01198     this->_setEnable(true);        
01199     this->_setData(value & 0x0F);   // Low nibble
01200     wait_us(1); // Data setup time        
01201     this->_setEnable(false);    
01202     wait_us(1); // Datahold time
01203 
01204 // Enable is Low
01205 }
01206 
01207 // Write a byte using the 4-bit interface
01208 void TextLCD_Base::_writeByte(int value) {
01209 
01210 // Enable is Low
01211     this->_setEnable(true);          
01212     this->_setData(value >> 4);   // High nibble
01213     wait_us(1); // Data setup time    
01214     this->_setEnable(false);   
01215     wait_us(1); // Data hold time
01216     
01217     this->_setEnable(true);        
01218     this->_setData(value >> 0);   // Low nibble
01219     wait_us(1); // Data setup time        
01220     this->_setEnable(false);    
01221     wait_us(1); // Datahold time
01222 
01223 // Enable is Low
01224 }
01225 
01226 // Write a command byte to the LCD controller
01227 void TextLCD_Base::_writeCommand(int command) {
01228 
01229     this->_setRS(false);        
01230     wait_us(1);  // Data setup time for RS       
01231     
01232     this->_writeByte(command);   
01233     wait_us(40); // most instructions take 40us            
01234 }
01235 
01236 // Write a data byte to the LCD controller
01237 void TextLCD_Base::_writeData(int data) {
01238 
01239     this->_setRS(true);            
01240     wait_us(1);  // Data setup time for RS 
01241         
01242     this->_writeByte(data);
01243     wait_us(40); // data writes take 40us                
01244 }
01245 
01246 
01247 // This replaces the original _address() method.
01248 // It is confusing since it returns the memoryaddress or-ed with the set memorycommand 0x80.
01249 // Left it in here for compatibility with older code. New applications should use getAddress() instead.
01250 int TextLCD_Base::_address(int column, int row) {
01251   return 0x80 | getAddress(column, row);
01252 }
01253 
01254 
01255 // This is new method to return the memory address based on row, column and displaytype.
01256 //
01257 /** Return the memoryaddress of screen column and row location
01258    *
01259    * @param column  The horizontal position from the left, indexed from 0
01260    * @param row     The vertical position from the top, indexed from 0
01261    * @param return  The memoryaddress of screen column and row location
01262    *
01263    */
01264 int TextLCD_Base::getAddress(int column, int row) {
01265 
01266     switch (_addr_mode) {
01267 
01268         case LCD_T_A:
01269           //Default addressing mode for 1, 2 and 4 rows (except 40x4)
01270           //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.          
01271           //Displays top rows when less than four are used.          
01272           switch (row) {
01273             case 0:
01274               return 0x00 + column;
01275             case 1:
01276               return 0x40 + column;
01277             case 2:
01278               return 0x00 + _nr_cols + column;
01279             case 3:
01280               return 0x40 + _nr_cols + column;
01281             // Should never get here.
01282             default:            
01283               return 0x00;                    
01284             }
01285           
01286         case LCD_T_B:
01287           // LCD8x2B is a special layout of LCD16x1
01288           if (row==0) 
01289             return 0x00 + column;                        
01290           else   
01291 //            return _nr_cols + column;                                    
01292             return 0x08 + column;                        
01293 
01294         case LCD_T_C:
01295           // LCD16x1C is a special layout of LCD8x2
01296           // LCD32x1C is a special layout of LCD16x2                    
01297           // LCD40x1C is a special layout of LCD20x2          
01298 #if(0)
01299           if (column < 8) 
01300             return 0x00 + column;                        
01301           else   
01302             return 0x40 + (column - 8);                        
01303 #else
01304           if (column < (_nr_cols >> 1)) 
01305             return 0x00 + column;                        
01306           else   
01307             return 0x40 + (column - (_nr_cols >> 1));                        
01308 #endif
01309 
01310 // Not sure about this one, seems wrong.
01311 // Left in for compatibility with original library
01312 //        case LCD16x2B:      
01313 //            return 0x00 + (row * 40) + column;
01314 
01315         case LCD_T_D:
01316           //Alternate addressing mode for 3 and 4 row displays (except 40x4). Used by PCF21XX, KS0078, SSD1803
01317           //The 4 available rows start at a hardcoded address.                    
01318           //Displays top rows when less than four are used.
01319           switch (row) {
01320             case 0:
01321               return 0x00 + column;
01322             case 1:
01323               return 0x20 + column;
01324             case 2:
01325               return 0x40 + column;
01326             case 3:
01327               return 0x60 + column;
01328             // Should never get here.
01329             default:            
01330               return 0x00;                    
01331             }
01332 
01333         case LCD_T_D1:
01334           //Alternate addressing mode for 3 row displays. Used by PCF21XX, KS0078, SSD1803
01335           //The 4 available rows start at a hardcoded address.                              
01336           //Skips top row of 4 row display and starts display at row 1
01337           switch (row) {
01338             case 0:
01339               return 0x20 + column;
01340             case 1:
01341               return 0x40 + column;
01342             case 2:
01343               return 0x60 + column;
01344             // Should never get here.
01345             default:            
01346               return 0x00;                    
01347             }
01348         
01349         case LCD_T_E:                
01350           // LCD40x4 is a special case since it has 2 controllers.
01351           // Each controller is configured as 40x2 (Type A)
01352           if (row<2) { 
01353             // Test to see if we need to switch between controllers  
01354             if (_ctrl_idx != _LCDCtrl_0) {
01355 
01356               // Second LCD controller Cursor Off
01357               _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);    
01358 
01359               // Select primary controller
01360               _ctrl_idx = _LCDCtrl_0;
01361 
01362               // Restore cursormode on primary LCD controller
01363               _setCursorAndDisplayMode(_currentMode, _currentCursor);    
01364             }           
01365             
01366             return 0x00 + (row * 0x40) + column;          
01367           }
01368           else {
01369 
01370             // Test to see if we need to switch between controllers  
01371             if (_ctrl_idx != _LCDCtrl_1) {
01372               // Primary LCD controller Cursor Off
01373               _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);    
01374 
01375               // Select secondary controller
01376               _ctrl_idx = _LCDCtrl_1;
01377 
01378               // Restore cursormode on secondary LCD controller
01379               _setCursorAndDisplayMode(_currentMode, _currentCursor);    
01380             }           
01381                                    
01382             return 0x00 + ((row-2) * 0x40) + column;          
01383           } 
01384             
01385         case LCD_T_F:
01386           //Alternate addressing mode for 3 row displays.
01387           //The first half of 3rd row continues from 1st row, the second half continues from 2nd row.                              
01388           switch (row) {
01389             case 0:
01390               return 0x00 + column;
01391             case 1:
01392               return 0x40 + column;
01393             case 2:
01394               if (column < (_nr_cols >> 1)) // check first or second half of line
01395                 return (0x00 + _nr_cols + column);                        
01396               else   
01397                 return (0x40 + _nr_cols + (column - (_nr_cols >> 1)));                        
01398             // Should never get here.
01399             default:            
01400               return 0x00;                    
01401           }
01402 
01403         case LCD_T_G:
01404           //Alternate addressing mode for 3 row displays. Used by ST7036
01405           switch (row) {
01406             case 0:
01407               return 0x00 + column;
01408             case 1:
01409               return 0x10 + column;
01410             case 2:
01411               return 0x20 + column;
01412             // Should never get here.
01413             default:            
01414               return 0x00;                    
01415             }
01416 
01417         // Should never get here.
01418         default:            
01419             return 0x00;        
01420 
01421     } // switch _addr_mode
01422 }
01423 
01424 
01425 /** Set the memoryaddress of screen column and row location
01426   *
01427   * @param column  The horizontal position from the left, indexed from 0
01428   * @param row     The vertical position from the top, indexed from 0
01429   */
01430 void TextLCD_Base::setAddress(int column, int row) {
01431    
01432 // Sanity Check column
01433     if (column < 0) {
01434       _column = 0;
01435     }
01436     else if (column >= columns()) {
01437       _column = columns() - 1;
01438     } else _column = column;
01439     
01440 // Sanity Check row
01441     if (row < 0) {
01442       _row = 0;
01443     }
01444     else if (row >= rows()) {
01445       _row = rows() - 1;
01446     } else _row = row;
01447     
01448     
01449 // Compute the memory address
01450 // For LCD40x4:  switch controllers if needed
01451 //               switch cursor if needed
01452     int addr = getAddress(_column, _row);
01453     
01454     _writeCommand(0x80 | addr);
01455 }
01456 
01457 
01458 /** Return the number of columns
01459   *
01460   * @param return  The number of columns
01461   *
01462   * Note: some configurations are commented out because they have not yet been tested due to lack of hardware     
01463   */   
01464 int TextLCD_Base::columns() {
01465     
01466   // Columns encoded in b7..b0
01467   //return (_type & 0xFF);          
01468   return _nr_cols;           
01469 }
01470 
01471 /** Return the number of rows
01472   *
01473   * @param return  The number of rows
01474   *
01475   * Note: some configurations are commented out because they have not yet been tested due to lack of hardware     
01476   */
01477 int TextLCD_Base::rows() {
01478 
01479   // Rows encoded in b15..b8  
01480   //return ((_type >> 8) & 0xFF); 
01481   return _nr_rows;          
01482 }
01483 
01484 /** Set the Cursormode
01485   *
01486   * @param cursorMode  The Cursor mode (CurOff_BlkOff, CurOn_BlkOff, CurOff_BlkOn, CurOn_BlkOn)
01487   */
01488 void TextLCD_Base::setCursor(LCDCursor cursorMode) { 
01489 
01490   // Save new cursor mode, needed when 2 controllers are in use or when display is switched off/on
01491   _currentCursor = cursorMode;
01492     
01493   // Configure only current LCD controller
01494   _setCursorAndDisplayMode(_currentMode, _currentCursor);    
01495 }
01496 
01497 /** Set the Displaymode
01498   *
01499   * @param displayMode The Display mode (DispOff, DispOn)
01500   */
01501 void TextLCD_Base::setMode(LCDMode displayMode) { 
01502 
01503   // Save new displayMode, needed when 2 controllers are in use or when cursor is changed
01504   _currentMode = displayMode;
01505     
01506   // Select and configure second LCD controller when needed
01507   if(_type==LCD40x4) {
01508     if (_ctrl_idx==_LCDCtrl_0) {      
01509       // Configure primary LCD controller
01510       _setCursorAndDisplayMode(_currentMode, _currentCursor);
01511 
01512       // Select 2nd controller
01513       _ctrl_idx=_LCDCtrl_1;
01514   
01515       // Configure secondary LCD controller    
01516       _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
01517 
01518       // Restore current controller
01519       _ctrl_idx=_LCDCtrl_0;       
01520     }
01521     else {
01522       // Select primary controller
01523       _ctrl_idx=_LCDCtrl_0;
01524     
01525       // Configure primary LCD controller
01526       _setCursorAndDisplayMode(_currentMode, CurOff_BlkOff);
01527        
01528       // Restore current controller
01529       _ctrl_idx=_LCDCtrl_1;
01530 
01531       // Configure secondary LCD controller    
01532       _setCursorAndDisplayMode(_currentMode, _currentCursor);
01533     }
01534   }
01535   else {
01536     // Configure primary LCD controller
01537     _setCursorAndDisplayMode(_currentMode, _currentCursor);
01538   }       
01539 }
01540 
01541 
01542 /** Low level method to restore the cursortype and display mode for current controller
01543   */     
01544 void TextLCD_Base::_setCursorAndDisplayMode(LCDMode displayMode, LCDCursor cursorType) { 
01545     
01546     // Configure current LCD controller       
01547     _writeCommand(0x08 | displayMode | cursorType);
01548 }
01549 
01550 /** Set the Backlight mode
01551   *
01552   *  @param backlightMode The Backlight mode (LightOff, LightOn)
01553   */
01554 void TextLCD_Base::setBacklight(LCDBacklight backlightMode) {
01555 
01556     if (backlightMode == LightOn) {
01557       this->_setBL(true);
01558     }
01559     else {
01560       this->_setBL(false);    
01561     }
01562 } 
01563 
01564 /** Set User Defined Characters
01565   *
01566   * @param unsigned char c   The Index of the UDC (0..7)
01567   * @param char *udc_data    The bitpatterns for the UDC (8 bytes of 5 significant bits)     
01568   */
01569 void TextLCD_Base::setUDC(unsigned char c, char *udc_data) {
01570   
01571   // Select and configure second LCD controller when needed
01572   if(_type==LCD40x4) {
01573     _LCDCtrl_Idx current_ctrl_idx = _ctrl_idx; // Temp save current controller
01574    
01575     // Select primary controller     
01576     _ctrl_idx=_LCDCtrl_0;
01577     
01578     // Configure primary LCD controller
01579     _setUDC(c, udc_data);
01580 
01581     // Select 2nd controller
01582     _ctrl_idx=_LCDCtrl_1;
01583   
01584     // Configure secondary LCD controller    
01585     _setUDC(c, udc_data);
01586 
01587     // Restore current controller
01588     _ctrl_idx=current_ctrl_idx;       
01589   }
01590   else {
01591     // Configure primary LCD controller
01592     _setUDC(c, udc_data); 
01593   }
01594     
01595 }
01596 
01597 /** Low level method to store user defined characters for current controller
01598   */     
01599 void TextLCD_Base::_setUDC(unsigned char c, char *udc_data) {
01600   
01601   // Select CG RAM for current LCD controller
01602   _writeCommand(0x40 + ((c & 0x07) << 3)); //Set CG-RAM address,
01603                                            //8 sequential locations needed per UDC
01604   // Store UDC pattern 
01605   for (int i=0; i<8; i++) {
01606     _writeData(*udc_data++);
01607   }
01608    
01609   //Select DD RAM again for current LCD controller
01610   int addr = getAddress(_column, _row);
01611   _writeCommand(0x80 | addr);  
01612 }
01613 
01614 
01615 /** Set UDC Blink
01616   * setUDCBlink method is supported by some compatible devices (eg SSD1803) 
01617   *
01618   * @param blinkMode The Blink mode (BlinkOff, BlinkOn)
01619   */
01620 void TextLCD_Base::setUDCBlink(LCDBlink blinkMode){
01621   // Blinking UDCs are enabled when a specific controlbit (BE) is set.
01622   // The blinking pixels in the UDC can be controlled by setting additional bits in the UDC bitpattern.
01623   // UDCs are defined by an 8 byte bitpattern. The P0..P5 form the character pattern.
01624   //     P7 P6 P5 P4 P3 P2 P1 P0 
01625   // 0   B1 B0  x  0  1  1  1  0
01626   // 1   B1 B0  x  1  0  0  0  1
01627   //        .............
01628   // 7   B1 B0  x  1  0  0  0  1
01629   //
01630   // Bit 6 and Bit 7 in the pattern will control the blinking mode when Blink is enabled through BE. 
01631   //     B1 B0  Mode
01632   //      0  0  No Blinking in this row of the UDC
01633   //      0  1  Enabled pixels in P4 will blink
01634   //      1  x  Enabled pixels in P0..P4 will blink
01635 
01636   switch (blinkMode) {
01637     case BlinkOn: 
01638       // Controllers that support UDC Blink  
01639       switch (_ctrl) {
01640         case KS0078 :            
01641           _function_1 |= 0x02; // Enable UDC Blink        
01642           _writeCommand(0x20 | _function_1);        // Function set 0 0 1 DL N RE(1) BE 0 (Ext Regs)
01643 
01644           _writeCommand(0x20 | _function);          // Function set 0 0 1 DL N RE(0) DH REV (Std Regs)
01645           break; // case KS0078 Controller
01646     
01647         case US2066_3V3 :  
01648         case SSD1803_3V3 :  
01649           _function_1 |= 0x04; // Enable UDC Blink
01650           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
01651                                                     // Select Ext Instr Set
01652 
01653           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
01654                                                     // Select Std Instr set, Select IS=0
01655           break; // case SSD1803, US2066
01656        
01657         default:
01658           //Unsupported feature for other controllers        
01659           break; 
01660       } //switch _ctrl     
01661     
01662       break;      
01663 
01664     case BlinkOff:
01665       // Controllers that support UDC Blink  
01666       switch (_ctrl) {
01667         case KS0078 :            
01668           _function_1 &= ~0x02; // Disable UDC Blink        
01669           _writeCommand(0x20 | _function_1);        // Function set 0 0 1 DL N RE(1) BE 0 (Ext Regs)
01670 
01671           _writeCommand(0x20 | _function);          // Function set 0 0 1 DL N RE(0) DH REV (Std Regs)
01672           break; // case KS0078 Controller
01673     
01674         case US2066_3V3 :  
01675         case SSD1803_3V3 :  
01676           _function_1 &= ~0x04; // Disable UDC Blink
01677           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
01678                                                     // Select Ext Instr Set
01679 
01680           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
01681                                                     // Select Std Instr set, Select IS=0
01682           break; // case SSD1803, US2066          
01683        
01684         default:
01685           //Unsupported feature for other controllers        
01686           break; 
01687       } //switch _ctrl     
01688     
01689       break;        
01690       
01691     default:
01692       break;      
01693   } // blinkMode
01694   
01695 } // setUDCBlink()
01696 
01697 
01698 /** Set Contrast
01699   * setContrast method is supported by some compatible devices (eg ST7032i) that have onboard LCD voltage generation
01700   * Initial code for ST70XX imported from fork by JH1PJL
01701   *
01702   * @param unsigned char c   contrast data (6 significant bits, valid range 0..63, Value 0 will disable the Vgen)  
01703   * @return none
01704   */
01705 //@TODO Add support for 40x4 dual controller
01706 void TextLCD_Base::setContrast(unsigned char c) {
01707 
01708 // Function set mode stored during Init. Make sure we dont accidentally switch between 1-line and 2-line mode!
01709 // Icon/Booster mode stored during Init. Make sure we dont accidentally change this!
01710  
01711   _contrast = c & 0x3F; // Sanity check
01712   
01713   switch (_ctrl) {   
01714     case PCF2113_3V3 :  
01715     case PCF2119_3V3 :  
01716        if (_contrast <  5) _contrast = 0;  // See datasheet. Sanity check for PCF2113/PCF2119
01717        if (_contrast > 55) _contrast = 55;
01718       
01719        _writeCommand(0x20 | _function | 0x01);               // Set function, Select Instruction Set = 1              
01720        _writeCommand(0x80 | 0x00 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)    V=0, VA=contrast
01721        _writeCommand(0x80 | 0x40 | (_contrast & 0x3F));      // VLCD_set (Instr. Set 1)    V=1, VB=contrast
01722        _writeCommand(0x20 | _function);                      // Select Instruction Set = 0
01723        break;
01724         
01725     case ST7032_3V3 :  
01726     case ST7032_5V :      
01727     case ST7036_3V3 :      
01728 //    case ST7036_5V :          
01729     case SSD1803_3V3 :      
01730       _writeCommand(0x20 | _function | 0x01);                        // Select Instruction Set = 1
01731       _writeCommand(0x70 | (_contrast & 0x0F));                      // Contrast Low bits
01732       _writeCommand(0x50 | _icon_power | ((_contrast >> 4) & 0x03)); // Contrast High bits 
01733       _writeCommand(0x20 | _function);                               // Select Instruction Set = 0
01734       break;
01735 
01736     case US2066_3V3 :      
01737       _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 DL N BE RE(1) REV 
01738                                                 // Select Extended Instruction Set
01739 
01740       _writeCommand(0x79);                      // Function Select OLED:  0 1 1 1 1 0 0 1 (Ext Instr Set)
01741          
01742       _writeCommand(0x81);                      // Set Contrast Control: 1 0 0 0 0 0 0 1 (Ext Instr Set, OLED)
01743       _writeCommand((_contrast << 2) | 0x03);   // Set Contrast Value: 8 bits. Use 6 bits for compatibility    
01744       
01745       _writeCommand(0x78);                      // Function Disable OLED: 0 1 1 1 1 0 0 0 (Ext Instr Set)          
01746 
01747       _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
01748                                                 // Select Std Instr set, Select IS=0
01749       break;
01750 
01751  #if(0)
01752  //not yet tested
01753     case PT6314 :
01754       // Only 2 significant bits
01755       //   0x00 = 100%
01756       //   0x01 =  75%
01757       //   0x02 =  50%
01758       //   0x03 =  25%                
01759       _writeCommand(0x20 | _function | ((~_contrast) >> 4));        // Invert and shift to use 2 MSBs     
01760       break;
01761  #endif
01762             
01763     default:  
01764       //Unsupported feature for other controllers
01765       break;               
01766   } // end switch     
01767 } // end setContrast()
01768 
01769 
01770 /** Set Power
01771   * setPower method is supported by some compatible devices (eg SSD1803) that have power down modes
01772   *
01773   * @param bool powerOn  Power on/off   
01774   * @return none
01775   */
01776 //@TODO Add support for 40x4 dual controller  
01777 void TextLCD_Base::setPower(bool powerOn) {
01778   
01779   if (powerOn) {
01780     // Switch on  
01781     setMode(DispOn);       
01782 
01783     // Controllers that supports specific Power Down mode
01784     switch (_ctrl) {
01785     
01786 //    case PCF2113_3V3 :  
01787 //    case PCF2119_3V3 :  
01788 //    case ST7032_3V3 :  
01789 //@todo
01790 //    enable Booster Bon
01791 
01792       case WS0010:      
01793         _writeCommand(0x17);   // Char mode, DC/DC on        
01794         wait_ms(10);           // Wait 10ms to ensure powered up             
01795         break;
01796 
01797       case KS0078:        
01798       case SSD1803_3V3 :      
01799 //      case SSD1803_5V :            
01800         _writeCommand(0x20 | _function_1);                             // Select Ext Instr Set
01801         _writeCommand(0x02);                                           // Power On
01802         _writeCommand(0x20 | _function);                               // Select Std Instr Set
01803         break;
01804                     
01805       default:  
01806         //Unsupported feature for other controllers
01807         break;              
01808     } // end switch  
01809   }  
01810   else {
01811     // Switch off        
01812     setMode(DispOff);       
01813 
01814     // Controllers that support specific Power Down mode
01815     switch (_ctrl) {
01816     
01817 //    case PCF2113_3V3 :  
01818 //    case PCF2119_3V3 :  
01819 //    case ST7032_3V3 :  
01820 //@todo
01821 //    disable Booster Bon
01822 
01823       case WS0010:      
01824         _writeCommand(0x13);   // Char mode, DC/DC off              
01825         break;
01826         
01827       case KS0078:
01828       case SSD1803_3V3 :      
01829 //      case SSD1803_5V :            
01830         _writeCommand(0x20 | _function_1);                             // Select Ext Instr Set
01831         _writeCommand(0x03);                                           // Power Down
01832         _writeCommand(0x20 | _function);                               // Select Std Instr Set
01833         break;
01834 
01835       default:  
01836         //Unsupported feature for other controllers
01837         break;              
01838     } // end switch  
01839   }
01840 } // end setPower()
01841 
01842 
01843 /** Set Orient
01844   * setOrient method is supported by some compatible devices (eg SSD1803, US2066) that have top/bottom view modes
01845   *
01846   * @param LCDOrient orient Orientation 
01847   * @return none
01848   */
01849 void TextLCD_Base::setOrient(LCDOrient orient){
01850 
01851   switch (orient) {
01852        
01853     case Top:
01854       switch (_ctrl) {
01855         case SSD1803_3V3 :      
01856 //      case SSD1803_5V :
01857         case US2066_3V3 :      
01858           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
01859                                                     // Select Extended Instruction Set
01860 //          _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)
01861           _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)          
01862 
01863           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
01864                                                     // Select Std Instr set, Select IS=0       
01865           break;
01866           
01867         default:  
01868           //Unsupported feature for other controllers
01869           break;              
01870 
01871       } // end switch _ctrl     
01872       break; // end Top
01873                 
01874     case Bottom:
01875       switch (_ctrl) {
01876         case SSD1803_3V3 :      
01877 //      case SSD1803_5V :
01878         case US2066_3V3 :      
01879           _writeCommand(0x20 | _function_1);        // Set function, 0 0 1 X N BE RE(1) REV 
01880                                                     // Select Extended Instruction Set
01881           _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)
01882 //          _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)          
01883 
01884           _writeCommand(0x20 | _function);          // Set function, 0 0 1 DL N DH RE(0) IS=0 Select Instruction Set 0
01885                                                     // Select Std Instr set, Select IS=0       
01886           break;
01887           
01888         default:  
01889           //Unsupported feature for other controllers
01890           break;              
01891 
01892       } // end switch _ctrl     
01893     
01894       break; // end Bottom
01895   } // end switch orient
01896 } // end setOrient()
01897 
01898 
01899 
01900 //--------- End TextLCD_Base -----------
01901 
01902 
01903 //--------- Start TextLCD Bus -----------
01904 
01905 /* Create a TextLCD interface for using regular mbed pins
01906  *
01907  * @param rs     Instruction/data control line
01908  * @param e      Enable line (clock)
01909  * @param d4-d7  Data lines for using as a 4-bit interface
01910  * @param type   Sets the panel size/addressing mode (default = LCD16x2)
01911  * @param bl     Backlight control line (optional, default = NC)  
01912  * @param e2     Enable2 line (clock for second controller, LCD40x4 only) 
01913  * @param ctrl   LCD controller (default = HD44780)   
01914  */ 
01915 TextLCD::TextLCD(PinName rs, PinName e,
01916                  PinName d4, PinName d5, PinName d6, PinName d7,
01917                  LCDType type, PinName bl, PinName e2, LCDCtrl ctrl) :
01918                  TextLCD_Base(type, ctrl), 
01919                  _rs(rs), _e(e), _d(d4, d5, d6, d7) {
01920 
01921   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
01922   if (bl != NC) {
01923     _bl = new DigitalOut(bl);   //Construct new pin 
01924     _bl->write(0);              //Deactivate    
01925   }
01926   else {
01927     // No Hardware Backlight pin       
01928     _bl = NULL;                 //Construct dummy pin     
01929   }  
01930 
01931   // The hardware Enable2 pin is only needed for LCD40x4. Test and make sure whether it exists or not to prevent illegal access.
01932   if (e2 != NC) {
01933     _e2 = new DigitalOut(e2);   //Construct new pin 
01934     _e2->write(0);              //Deactivate    
01935   }
01936   else {
01937     // No Hardware Enable pin       
01938     _e2 = NULL;                 //Construct dummy pin     
01939   }  
01940                                                                            
01941   _init();
01942 }
01943 
01944 /** Destruct a TextLCD interface for using regular mbed pins
01945   *
01946   * @param  none
01947   * @return none
01948   */ 
01949 TextLCD::~TextLCD() {
01950    if (_bl != NULL) {delete _bl;}  // BL pin
01951    if (_e2 != NULL) {delete _e2;}  // E2 pin
01952 }
01953 
01954 
01955 /** Set E pin (or E2 pin)
01956   * Used for mbed pins, I2C bus expander or SPI shiftregister
01957   * Default PinName value for E2 is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
01958   *   @param  value true or false
01959   *   @return none 
01960   */
01961 void TextLCD::_setEnable(bool value) {
01962 
01963   if(_ctrl_idx==_LCDCtrl_0) {
01964     if (value) {
01965       _e  = 1;    // Set E bit 
01966     }  
01967     else { 
01968       _e  = 0;    // Reset E bit  
01969     }  
01970   }    
01971   else { 
01972     if (value) {
01973       if (_e2 != NULL) {_e2->write(1);}  //Set E2 bit
01974     }  
01975     else { 
01976       if (_e2 != NULL) {_e2->write(0);}  //Reset E2 bit     
01977     }  
01978   }    
01979 }    
01980 
01981 // Set RS pin
01982 // Used for mbed pins, I2C bus expander or SPI shiftregister
01983 void TextLCD::_setRS(bool value) {
01984 
01985   if (value) {
01986     _rs  = 1;    // Set RS bit 
01987   }  
01988   else  {
01989     _rs  = 0;    // Reset RS bit 
01990   }  
01991 }    
01992 
01993 /** Set BL pin
01994   * Used for mbed pins, I2C bus expander or SPI shiftregister
01995   * Default PinName value is NC, must be used as pointer to avoid issues with mbed lib and DigitalOut pins
01996   *   @param  value true or false
01997   *   @return none  
01998   */
01999 void TextLCD::_setBL(bool value) {
02000 
02001   if (value) {
02002     if (_bl != NULL) {_bl->write(1);}  //Set BL bit
02003   }  
02004   else { 
02005     if (_bl != NULL) {_bl->write(0);}  //Reset BL bit  
02006   }  
02007 }    
02008 
02009 // Place the 4bit data on the databus
02010 // Used for mbed pins, I2C bus expander or SPI shifregister
02011 void TextLCD::_setData(int value) {
02012   _d = value & 0x0F;   // Write Databits 
02013 }    
02014     
02015 //----------- End TextLCD ---------------
02016 
02017 
02018 //--------- Start TextLCD_I2C -----------
02019 
02020 /** Create a TextLCD interface using an I2C PC8574 (or PCF8574A) or MCP23008 portexpander
02021   *
02022   * @param i2c             I2C Bus
02023   * @param deviceAddress   I2C slave address (PCF8574, PCF8574A or MCP23008, default = 0x40)
02024   * @param type            Sets the panel size/addressing mode (default = LCD16x2)
02025   * @param ctrl            LCD controller (default = HD44780)    
02026   */
02027 TextLCD_I2C::TextLCD_I2C(I2C *i2c, char deviceAddress, LCDType type, LCDCtrl ctrl) :
02028                          TextLCD_Base(type, ctrl), 
02029                          _i2c(i2c){
02030                               
02031   _slaveAddress = deviceAddress & 0xFE;
02032 
02033   // Setup the I2C bus
02034   // The max bitrate for PCF8574 is 100kbit, the max bitrate for MCP23008 is 400kbit, 
02035   _i2c->frequency(100000);
02036   
02037 #if (MCP23008==1)
02038   // MCP23008 portexpander Init
02039   _write_register(IODIR,   0x00);  // All outputs
02040   _write_register(IPOL,    0x00);  // No reverse polarity 
02041   _write_register(GPINTEN, 0x00);  // No interrupt 
02042   _write_register(DEFVAL,  0x00);  // Default value to compare against for interrupts
02043   _write_register(INTCON,  0x00);  // No interrupt on changes 
02044   _write_register(IOCON,   0x00);  // Interrupt polarity   
02045   _write_register(GPPU,    0x00);  // No Pullup 
02046   _write_register(INTF,    0x00);  //    
02047   _write_register(INTCAP,  0x00);  //    
02048   _write_register(GPIO,    0x00);  // Output/Input pins   
02049   _write_register(OLAT,    0x00);  // Output Latch  
02050     
02051   // Init the portexpander bus
02052   _lcd_bus = D_LCD_BUS_DEF;
02053   
02054   // write the new data to the portexpander
02055   _write_register(GPIO, _lcd_bus);      
02056 #else
02057   // PCF8574 of PCF8574A portexpander
02058 
02059   // Init the portexpander bus
02060   _lcd_bus = D_LCD_BUS_DEF;
02061 
02062   // write the new data to the portexpander
02063   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
02064 #endif
02065 
02066   _init();    
02067 }
02068 
02069 // Set E pin (or E2 pin)
02070 // Used for mbed pins, I2C bus expander or SPI shiftregister
02071 void TextLCD_I2C::_setEnable(bool value) {
02072 
02073   if(_ctrl_idx==_LCDCtrl_0) {
02074     if (value) {
02075       _lcd_bus |= D_LCD_E;     // Set E bit 
02076     }  
02077     else {                    
02078       _lcd_bus &= ~D_LCD_E;    // Reset E bit                     
02079     }  
02080   }
02081   else {
02082     if (value) {
02083       _lcd_bus |= D_LCD_E2;    // Set E2 bit 
02084     }  
02085     else {
02086       _lcd_bus &= ~D_LCD_E2;   // Reset E2bit                     
02087     }  
02088   }    
02089 
02090 #if (MCP23008==1)
02091   // MCP23008 portexpander
02092   
02093   // write the new data to the portexpander
02094   _write_register(GPIO, _lcd_bus);      
02095 #else
02096   // PCF8574 of PCF8574A portexpander
02097 
02098   // write the new data to the I2C portexpander
02099   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
02100 #endif
02101 }    
02102 
02103 // Set RS pin
02104 // Used for mbed pins, I2C bus expander or SPI shiftregister
02105 void TextLCD_I2C::_setRS(bool value) {
02106 
02107   if (value) {
02108     _lcd_bus |= D_LCD_RS;    // Set RS bit 
02109   }  
02110   else {                    
02111     _lcd_bus &= ~D_LCD_RS;   // Reset RS bit                     
02112   }
02113 
02114 #if (MCP23008==1)
02115   // MCP23008 portexpander
02116   
02117   // write the new data to the portexpander
02118   _write_register(GPIO, _lcd_bus);      
02119 #else
02120   // PCF8574 of PCF8574A portexpander
02121 
02122   // write the new data to the I2C portexpander
02123   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
02124 #endif                  
02125 }    
02126 
02127 // Set BL pin
02128 // Used for mbed pins, I2C bus expander or SPI shiftregister
02129 void TextLCD_I2C::_setBL(bool value) {
02130 
02131 #if (DFROBOT==1)  
02132   value = !value; // The DFRobot module uses PNP transistor to drive the Backlight. Reverse logic level.
02133 #endif
02134   
02135   if (value) {
02136     _lcd_bus |= D_LCD_BL;    // Set BL bit 
02137   }  
02138   else {                    
02139     _lcd_bus &= ~D_LCD_BL;   // Reset BL bit                     
02140   }
02141   
02142 #if (MCP23008==1)
02143   // MCP23008 portexpander
02144   
02145   // write the new data to the portexpander
02146   _write_register(GPIO, _lcd_bus);      
02147 #else
02148   // PCF8574 of PCF8574A portexpander
02149 
02150   // write the new data to the I2C portexpander
02151   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
02152 #endif                 
02153 }    
02154 
02155 
02156 // Place the 4bit data on the databus
02157 // Used for mbed pins, I2C bus expander or SPI shifregister
02158 void TextLCD_I2C::_setData(int value) {
02159   int data;
02160 
02161   // Set bit by bit to support any mapping of expander portpins to LCD pins
02162   
02163   data = value & 0x0F;
02164   if (data & 0x01){
02165     _lcd_bus |= D_LCD_D4;   // Set Databit 
02166   }  
02167   else { 
02168     _lcd_bus &= ~D_LCD_D4;  // Reset Databit
02169   }  
02170 
02171   if (data & 0x02){
02172     _lcd_bus |= D_LCD_D5;   // Set Databit 
02173   }  
02174   else {
02175     _lcd_bus &= ~D_LCD_D5;  // Reset Databit
02176   }  
02177 
02178   if (data & 0x04) {
02179     _lcd_bus |= D_LCD_D6;   // Set Databit 
02180   }  
02181   else {                    
02182     _lcd_bus &= ~D_LCD_D6;  // Reset Databit
02183   }  
02184 
02185   if (data & 0x08) {
02186     _lcd_bus |= D_LCD_D7;   // Set Databit 
02187   }  
02188   else {
02189     _lcd_bus &= ~D_LCD_D7;  // Reset Databit
02190   }  
02191                     
02192 #if (MCP23008==1)
02193   // MCP23008 portexpander
02194   
02195   // write the new data to the portexpander
02196   _write_register(GPIO, _lcd_bus);      
02197 #else
02198   // PCF8574 of PCF8574A portexpander
02199 
02200   // write the new data to the I2C portexpander
02201   _i2c->write(_slaveAddress, &_lcd_bus, 1);    
02202 #endif
02203                  
02204 }    
02205 
02206 // Write data to MCP23008 I2C portexpander
02207 void TextLCD_I2C::_write_register (int reg, int value) {
02208   char data[] = {reg, value};
02209     
02210   _i2c->write(_slaveAddress, data, 2); 
02211 }
02212 
02213 //---------- End TextLCD_I2C ------------
02214 
02215 
02216 //--------- Start TextLCD_I2C_N ---------
02217 
02218  /** Create a TextLCD interface using a controller with native I2C interface
02219    *
02220    * @param i2c             I2C Bus
02221    * @param deviceAddress   I2C slave address (default = 0x7C)  
02222    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
02223    * @param bl              Backlight control line (optional, default = NC)     
02224    * @param ctrl            LCD controller (default = ST7032_3V3)                     
02225    */
02226 TextLCD_I2C_N::TextLCD_I2C_N(I2C *i2c, char deviceAddress, LCDType type, PinName bl, LCDCtrl ctrl) : 
02227                                TextLCD_Base(type, ctrl), 
02228 
02229                                _i2c(i2c){
02230   
02231   _slaveAddress = deviceAddress & 0xFE;
02232   
02233   // Setup the I2C bus
02234   // The max bitrate for ST7032i is 400kbit, lets stick to default here
02235   _i2c->frequency(100000);
02236 
02237        
02238   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
02239   if (bl != NC) {
02240     _bl = new DigitalOut(bl);   //Construct new pin 
02241     _bl->write(0);              //Deactivate    
02242   }
02243   else {
02244     // No Hardware Backlight pin       
02245     _bl = NULL;                 //Construct dummy pin     
02246   }  
02247   
02248   //Sanity check
02249   if (_ctrl & LCD_C_I2C) {
02250     _init();      
02251   }
02252   else {
02253     error("Error: LCD Controller type does not support native I2C interface\n\r");           
02254   }
02255 
02256 }
02257 
02258 TextLCD_I2C_N::~TextLCD_I2C_N() {
02259    if (_bl != NULL) {delete _bl;}  // BL pin
02260 }
02261 
02262 // Not used in this mode
02263 void TextLCD_I2C_N::_setEnable(bool value) {
02264 }    
02265 
02266 // Set RS pin
02267 // Used for mbed pins, I2C bus expander or SPI shiftregister and native I2C or SPI
02268 void TextLCD_I2C_N::_setRS(bool value) {
02269 // The controlbyte defines the meaning of the next byte. This next byte can either be data or command.
02270 // Start Slaveaddress+RW  b7 b6 b5 b4 b3 b2 b1 b0   b7...........b0  Stop
02271 //                        Co RS RW  0  0  0  0  0   command or data
02272 //
02273 //   C0=1 indicates that another controlbyte will follow after the next data or command byte 
02274 //   RS=1 means that next byte is data, RS=0 means that next byte is command
02275 //   RW=0 means write to controller. RW=1 means that controller will be read from after the next command. 
02276 //        Many native I2C controllers dont support this option and it is not used by this lib. 
02277 //
02278 
02279   if (value) {
02280     _controlbyte = 0x40; // Next byte is data, No more control bytes will follow
02281   }
02282   else {
02283     _controlbyte = 0x00; // Next byte is command, No more control bytes will follow     
02284   }
02285 }    
02286 
02287 // Set BL pin
02288 void TextLCD_I2C_N::_setBL(bool value) {
02289     if (_bl) {
02290         _bl->write(value);   
02291     }    
02292 }    
02293     
02294 // Not used in this mode
02295 void TextLCD_I2C_N::_setData(int value) {
02296 }    
02297 
02298 // Write a byte using I2C
02299 void TextLCD_I2C_N::_writeByte(int value) {
02300 // The controlbyte defines the meaning of the next byte. This next byte can either be data or command.
02301 // Start Slaveaddress+RW  b7 b6 b5 b4 b3 b2 b1 b0   b7...........b0  Stop
02302 //                        Co RS RW  0  0  0  0  0   command or data
02303 //
02304 //   C0=1 indicates that another controlbyte will follow after the next data or command byte 
02305 //   RS=1 means that next byte is data, RS=0 means that next byte is command
02306 //   RW=0 means write to controller. RW=1 means that controller will be read from after the next command. 
02307 //        Many native I2C controllers dont support this option and it is not used by this lib. 
02308 //
02309   char data[] = {_controlbyte, value};
02310     
02311 #if(LCD_I2C_ACK==1)
02312 //Controllers that support ACK
02313   _i2c->write(_slaveAddress, data, 2); 
02314 #else  
02315 //Controllers that dont support ACK
02316   _i2c->start(); 
02317   _i2c->write(_slaveAddress);   
02318   _i2c->write(data[0]); 
02319   _i2c->write(data[1]);     
02320   _i2c->stop();   
02321 #endif  
02322 }
02323 
02324 //-------- End TextLCD_I2C_N ------------
02325 
02326 
02327 //--------- Start TextLCD_SPI -----------
02328 
02329  /** Create a TextLCD interface using an SPI 74595 portexpander
02330    *
02331    * @param spi             SPI Bus
02332    * @param cs              chip select pin (active low)
02333    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
02334    * @param ctrl            LCD controller (default = HD44780)      
02335    */
02336 TextLCD_SPI::TextLCD_SPI(SPI *spi, PinName cs, LCDType type, LCDCtrl ctrl) :
02337                          TextLCD_Base(type, ctrl), 
02338                          _spi(spi),        
02339                          _cs(cs) {      
02340         
02341   // Init cs
02342   _setCS(true);  
02343 
02344   // Setup the spi for 8 bit data, low steady state clock,
02345   // rising edge capture, with a 500KHz or 1MHz clock rate  
02346   _spi->format(8,0);
02347   _spi->frequency(500000);    
02348   //_spi.frequency(1000000);    
02349 
02350   // Init the portexpander bus
02351   _lcd_bus = D_LCD_BUS_DEF;
02352   
02353   // write the new data to the portexpander
02354   _setCS(false);  
02355   _spi->write(_lcd_bus);   
02356   _setCS(true);  
02357 
02358   _init();   
02359 }
02360 
02361 // Set E pin (or E2 pin)
02362 // Used for mbed pins, I2C bus expander or SPI shiftregister
02363 void TextLCD_SPI::_setEnable(bool value) {
02364 
02365   if(_ctrl_idx==_LCDCtrl_0) {
02366     if (value) {
02367       _lcd_bus |= D_LCD_E;     // Set E bit 
02368     }  
02369     else {                    
02370       _lcd_bus &= ~D_LCD_E;    // Reset E bit                     
02371     }  
02372   }
02373   else {
02374     if (value) {
02375       _lcd_bus |= D_LCD_E2;    // Set E2 bit 
02376     }  
02377     else {
02378       _lcd_bus &= ~D_LCD_E2;   // Reset E2 bit                     
02379     }  
02380   }
02381                   
02382   // write the new data to the SPI portexpander
02383   _setCS(false);  
02384   _spi->write(_lcd_bus);   
02385   _setCS(true);    
02386 }    
02387 
02388 // Set RS pin
02389 // Used for mbed pins, I2C bus expander or SPI shiftregister
02390 void TextLCD_SPI::_setRS(bool value) {
02391 
02392   if (value) {
02393     _lcd_bus |= D_LCD_RS;    // Set RS bit 
02394   }  
02395   else {                    
02396     _lcd_bus &= ~D_LCD_RS;   // Reset RS bit                     
02397   }
02398      
02399   // write the new data to the SPI portexpander
02400   _setCS(false);  
02401   _spi->write(_lcd_bus);   
02402   _setCS(true);     
02403 }    
02404 
02405 // Set BL pin
02406 // Used for mbed pins, I2C bus expander or SPI shiftregister
02407 void TextLCD_SPI::_setBL(bool value) {
02408 
02409   if (value) {
02410     _lcd_bus |= D_LCD_BL;    // Set BL bit 
02411   }  
02412   else {
02413     _lcd_bus &= ~D_LCD_BL;   // Reset BL bit                     
02414   }
02415       
02416   // write the new data to the SPI portexpander
02417   _setCS(false);  
02418   _spi->write(_lcd_bus);   
02419   _setCS(true);      
02420 }    
02421 
02422 // Place the 4bit data on the databus
02423 // Used for mbed pins, I2C bus expander or SPI shiftregister
02424 void TextLCD_SPI::_setData(int value) {
02425   int data;
02426 
02427   // Set bit by bit to support any mapping of expander portpins to LCD pins
02428     
02429   data = value & 0x0F;
02430   if (data & 0x01) {
02431     _lcd_bus |= D_LCD_D4;   // Set Databit 
02432   }  
02433   else {                    
02434     _lcd_bus &= ~D_LCD_D4;  // Reset Databit                     
02435   }
02436   
02437   if (data & 0x02) {
02438     _lcd_bus |= D_LCD_D5;   // Set Databit 
02439   }  
02440   else {
02441     _lcd_bus &= ~D_LCD_D5;  // Reset Databit                     
02442   }
02443   
02444   if (data & 0x04) {
02445     _lcd_bus |= D_LCD_D6;   // Set Databit 
02446   }  
02447   else {
02448     _lcd_bus &= ~D_LCD_D6;  // Reset Databit                     
02449   }
02450   
02451   if (data & 0x08) {
02452     _lcd_bus |= D_LCD_D7;   // Set Databit 
02453   }  
02454   else {
02455     _lcd_bus &= ~D_LCD_D7;  // Reset Databit
02456   }  
02457                     
02458   // write the new data to the SPI portexpander
02459   _setCS(false);  
02460   _spi->write(_lcd_bus);   
02461   _setCS(true);          
02462 }    
02463 
02464 // Set CS line.
02465 // Only used for SPI bus
02466 void TextLCD_SPI::_setCS(bool value) {
02467 
02468   if (value) {   
02469     _cs  = 1;    // Set CS pin 
02470   }  
02471   else {
02472     _cs  = 0;    // Reset CS pin 
02473   }
02474 }
02475 
02476 //---------- End TextLCD_SPI ------------
02477 
02478 
02479 //--------- Start TextLCD_SPI_N ---------
02480 
02481  /** Create a TextLCD interface using a controller with a native SPI4 interface
02482    *
02483    * @param spi             SPI Bus
02484    * @param cs              chip select pin (active low)
02485    * @param rs              Instruction/data control line
02486    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
02487    * @param bl              Backlight control line (optional, default = NC)  
02488    * @param ctrl            LCD controller (default = ST7032_3V3) 
02489    */       
02490 TextLCD_SPI_N::TextLCD_SPI_N(SPI *spi, PinName cs, PinName rs, LCDType type, PinName bl, LCDCtrl ctrl) :
02491                              TextLCD_Base(type, ctrl), 
02492                              _spi(spi),        
02493                              _cs(cs),
02494                              _rs(rs) {      
02495         
02496   // Init CS
02497   _cs = 1;
02498 
02499   // Setup the spi for 8 bit data, low steady state clock,
02500   // rising edge capture, with a 500KHz or 1MHz clock rate  
02501   _spi->format(8,0);
02502   _spi->frequency(1000000);    
02503   
02504   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
02505   if (bl != NC) {
02506     _bl = new DigitalOut(bl);   //Construct new pin 
02507     _bl->write(0);              //Deactivate    
02508   }
02509   else {
02510     // No Hardware Backlight pin       
02511     _bl = NULL;                 //Construct dummy pin     
02512   }  
02513 
02514   //Sanity check
02515   if (_ctrl & LCD_C_SPI4) {
02516     _init();      
02517   }
02518   else {
02519     error("Error: LCD Controller type does not support native SPI4 interface\n\r");           
02520   }
02521 }
02522 
02523 TextLCD_SPI_N::~TextLCD_SPI_N() {
02524    if (_bl != NULL) {delete _bl;}  // BL pin
02525 }
02526 
02527 // Not used in this mode
02528 void TextLCD_SPI_N::_setEnable(bool value) {
02529 }    
02530 
02531 // Set RS pin
02532 // Used for mbed pins, I2C bus expander or SPI shiftregister
02533 void TextLCD_SPI_N::_setRS(bool value) {
02534     _rs = value;
02535 }    
02536 
02537 // Set BL pin
02538 void TextLCD_SPI_N::_setBL(bool value) {
02539     if (_bl) {
02540         _bl->write(value);   
02541     }    
02542 }    
02543 
02544 // Not used in this mode
02545 void TextLCD_SPI_N::_setData(int value) {
02546 }    
02547 
02548 // Write a byte using SPI
02549 void TextLCD_SPI_N::_writeByte(int value) {
02550     _cs = 0;
02551     wait_us(1);
02552     _spi->write(value);
02553     wait_us(1);
02554     _cs = 1;
02555 }
02556   
02557 //-------- End TextLCD_SPI_N ------------
02558 
02559 
02560 
02561 #if(1)
02562 //Code checked out on logic analyser. Not yet tested on hardware..
02563 
02564 //-------- Start TextLCD_SPI_N_3_9 --------
02565 
02566  /** Create a TextLCD interface using a controller with a native SPI3 9 bits interface
02567    *
02568    * @param spi             SPI Bus
02569    * @param cs              chip select pin (active low)
02570    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
02571    * @param bl              Backlight control line (optional, default = NC)  
02572    * @param ctrl            LCD controller (default = AIP31068) 
02573    */       
02574 TextLCD_SPI_N_3_9::TextLCD_SPI_N_3_9(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
02575                                      TextLCD_Base(type, ctrl), 
02576                                      _spi(spi),        
02577                                      _cs(cs) {      
02578 
02579   // Init CS
02580   _cs = 1;
02581 
02582   // Setup the spi for 9 bit data, low steady state clock,
02583   // rising edge capture, with a 500KHz or 1MHz clock rate  
02584 //  _spi->format(9,0);
02585   _spi->format(9,3);  
02586   _spi->frequency(1000000);    
02587   
02588   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
02589   if (bl != NC) {
02590     _bl = new DigitalOut(bl);   //Construct new pin 
02591     _bl->write(0);              //Deactivate    
02592   }
02593   else {
02594     // No Hardware Backlight pin       
02595     _bl = NULL;                 //Construct dummy pin     
02596   }  
02597 
02598   //Sanity check
02599   if (_ctrl & LCD_C_SPI3_9) {
02600     _init();      
02601   }
02602   else {
02603     error("Error: LCD Controller type does not support native SPI3 9 bits interface\n\r");           
02604   }
02605 }
02606 
02607 TextLCD_SPI_N_3_9::~TextLCD_SPI_N_3_9() {
02608    if (_bl != NULL) {delete _bl;}  // BL pin
02609 }
02610 
02611 // Not used in this mode
02612 void TextLCD_SPI_N_3_9::_setEnable(bool value) {
02613 }    
02614 
02615 // Set RS pin
02616 // Used for mbed pins, I2C bus expander or SPI shiftregister
02617 void TextLCD_SPI_N_3_9::_setRS(bool value) {
02618 // The controlbits define the meaning of the next byte. This next byte can either be data or command.
02619 //   b8  b7...........b0 
02620 //   RS  command or data
02621 //
02622 //   RS=1 means that next byte is data, RS=0 means that next byte is command
02623 //
02624 
02625   if (value) {
02626     _controlbyte = 0x01; // Next byte is data
02627   }
02628   else {
02629     _controlbyte = 0x00; // Next byte is command
02630   }
02631    
02632 }    
02633 
02634 // Set BL pin
02635 void TextLCD_SPI_N_3_9::_setBL(bool value) {
02636     if (_bl) {
02637         _bl->write(value);   
02638     }    
02639 }    
02640 
02641 // Not used in this mode
02642 void TextLCD_SPI_N_3_9::_setData(int value) {
02643 }    
02644 
02645 // Write a byte using SPI3 9 bits mode
02646 void TextLCD_SPI_N_3_9::_writeByte(int value) {
02647     _cs = 0;
02648     wait_us(1);
02649     _spi->write( (_controlbyte << 8) | (value & 0xFF));
02650     wait_us(1);
02651     _cs = 1;
02652 }
02653   
02654 //------- End TextLCD_SPI_N_3_9 -----------
02655 #endif
02656 
02657 
02658 #if(1)
02659 //------- Start TextLCD_SPI_N_3_10 --------
02660 
02661  /** Create a TextLCD interface using a controller with a native SPI3 10 bits interface
02662    *
02663    * @param spi             SPI Bus
02664    * @param cs              chip select pin (active low)
02665    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
02666    * @param bl              Backlight control line (optional, default = NC)  
02667    * @param ctrl            LCD controller (default = AIP31068) 
02668    */       
02669 TextLCD_SPI_N_3_10::TextLCD_SPI_N_3_10(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
02670                                        TextLCD_Base(type, ctrl), 
02671                                        _spi(spi),        
02672                                        _cs(cs) {      
02673         
02674   // Init CS
02675   _cs = 1;
02676 
02677   // Setup the spi for 10 bit data, low steady state clock,
02678   // rising edge capture, with a 500KHz or 1MHz clock rate  
02679   _spi->format(10,0);
02680   _spi->frequency(1000000);    
02681   
02682   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
02683   if (bl != NC) {
02684     _bl = new DigitalOut(bl);   //Construct new pin 
02685     _bl->write(0);              //Deactivate    
02686   }
02687   else {
02688     // No Hardware Backlight pin       
02689     _bl = NULL;                 //Construct dummy pin     
02690   }  
02691 
02692   //Sanity check
02693   if (_ctrl & LCD_C_SPI3_10) {
02694     _init();      
02695   }
02696   else {
02697     error("Error: LCD Controller type does not support native SPI3 10 bits interface\n\r");           
02698   }
02699 }
02700 
02701 TextLCD_SPI_N_3_10::~TextLCD_SPI_N_3_10() {
02702    if (_bl != NULL) {delete _bl;}  // BL pin
02703 }
02704 
02705 // Not used in this mode
02706 void TextLCD_SPI_N_3_10::_setEnable(bool value) {
02707 }    
02708 
02709 // Set RS pin
02710 // Used for mbed pins, I2C bus expander or SPI shiftregister
02711 void TextLCD_SPI_N_3_10::_setRS(bool value) {
02712 // The controlbits define the meaning of the next byte. This next byte can either be data or command.
02713 //   b9 b8  b7...........b0 
02714 //   RS RW  command or data
02715 //
02716 //   RS=1 means that next byte is data, RS=0 means that next byte is command
02717 //   RW=0 means that next byte is writen, RW=1 means that next byte is read (not used in this lib)
02718 //
02719 
02720   if (value) {
02721     _controlbyte = 0x02; // Next byte is data
02722   }
02723   else {
02724     _controlbyte = 0x00; // Next byte is command
02725   }
02726    
02727 }    
02728 
02729 // Set BL pin
02730 void TextLCD_SPI_N_3_10::_setBL(bool value) {
02731     if (_bl) {
02732         _bl->write(value);   
02733     }    
02734 }    
02735 
02736 // Not used in this mode
02737 void TextLCD_SPI_N_3_10::_setData(int value) {
02738 }    
02739 
02740 // Write a byte using SPI3 10 bits mode
02741 void TextLCD_SPI_N_3_10::_writeByte(int value) {
02742     _cs = 0;
02743     wait_us(1);
02744     _spi->write( (_controlbyte << 8) | (value & 0xFF));
02745     wait_us(1);
02746     _cs = 1;
02747 }
02748   
02749 //------- End TextLCD_SPI_N_3_10 ----------
02750 #endif
02751 
02752 #if(0)
02753 //Code to be checked out on logic analyser. Not yet tested on hardware..
02754 
02755 //------- Start TextLCD_SPI_N_3_16 --------
02756 
02757  /** Create a TextLCD interface using a controller with a native SPI3 16 bits interface
02758    *
02759    * @param spi             SPI Bus
02760    * @param cs              chip select pin (active low)
02761    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
02762    * @param bl              Backlight control line (optional, default = NC)  
02763    * @param ctrl            LCD controller (default = PT6314) 
02764    */       
02765 TextLCD_SPI_N_3_16::TextLCD_SPI_N_3_16(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
02766                                        TextLCD_Base(type, ctrl), 
02767                                        _spi(spi),        
02768                                        _cs(cs) {      
02769         
02770   // Init CS
02771   _cs = 1;
02772 
02773   // Setup the spi for 8 bit data, low steady state clock,
02774   // rising edge capture, with a 500KHz or 1MHz clock rate  
02775   _spi->format(8,0);
02776   _spi->frequency(1000000);    
02777   
02778   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
02779   if (bl != NC) {
02780     _bl = new DigitalOut(bl);   //Construct new pin 
02781     _bl->write(0);              //Deactivate    
02782   }
02783   else {
02784     // No Hardware Backlight pin       
02785     _bl = NULL;                 //Construct dummy pin     
02786   }  
02787 
02788   //Sanity check
02789   if (_ctrl & LCD_C_SPI3_16) {
02790     _init();      
02791   }
02792   else {
02793     error("Error: LCD Controller type does not support native SPI3 16 bits interface\n\r");           
02794   }
02795 }
02796 
02797 TextLCD_SPI_N_3_16::~TextLCD_SPI_N_3_16() {
02798    if (_bl != NULL) {delete _bl;}  // BL pin
02799 }
02800 
02801 // Not used in this mode
02802 void TextLCD_SPI_N_3_16::_setEnable(bool value) {
02803 }    
02804 
02805 // Set RS pin
02806 // Used for mbed pins, I2C bus expander or SPI shiftregister
02807 void TextLCD_SPI_N_3_16::_setRS(bool value) {
02808 // 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.
02809 // The 8 actual bits represent either a data or a command byte.
02810 //   b15 b14 b13 b12 b11 b10  b9  b8 - b7 b6 b5 b4 b3 b2 b1 b0 
02811 //     1   1   1   1   1  RW  RS   0   d7 d6 d5 d4 d3 d2 d1 d0
02812 //
02813 //   RS=1 means that next byte is data, RS=0 means that next byte is command
02814 //   RW=0 means that next byte is writen, RW=1 means that next byte is read (not used in this lib)
02815 //
02816 
02817   if (value) {
02818     _controlbyte = 0xFA; // Next byte is data
02819   }
02820   else {
02821     _controlbyte = 0xF8; // Next byte is command
02822   }  
02823 }    
02824 
02825 // Set BL pin
02826 void TextLCD_SPI_N_3_16::_setBL(bool value) {
02827     if (_bl) {
02828         _bl->write(value);   
02829     }    
02830 }    
02831 
02832 // Not used in this mode
02833 void TextLCD_SPI_N_3_16::_setData(int value) {
02834 }    
02835 
02836     
02837 // Write a byte using SPI3 16 bits mode
02838 void TextLCD_SPI_N_3_16::_writeByte(int value) {
02839     _cs = 0;
02840     wait_us(1);
02841 
02842     _spi->write(_controlbyte);
02843 
02844     _spi->write(value);     
02845 
02846     wait_us(1);
02847     _cs = 1;
02848 }
02849   
02850 //------- End TextLCD_SPI_N_3_16 ----------
02851 #endif
02852 
02853 #if(1)
02854 //------- Start TextLCD_SPI_N_3_24 --------
02855 
02856  /** Create a TextLCD interface using a controller with a native SPI3 24 bits interface
02857    *
02858    * @param spi             SPI Bus
02859    * @param cs              chip select pin (active low)
02860    * @param type            Sets the panel size/addressing mode (default = LCD16x2)
02861    * @param bl              Backlight control line (optional, default = NC)  
02862    * @param ctrl            LCD controller (default = SSD1803) 
02863    */       
02864 TextLCD_SPI_N_3_24::TextLCD_SPI_N_3_24(SPI *spi, PinName cs, LCDType type, PinName bl, LCDCtrl ctrl) :
02865                                        TextLCD_Base(type, ctrl), 
02866                                        _spi(spi),        
02867                                        _cs(cs) {      
02868         
02869   // Init CS
02870   _cs = 1;
02871 
02872   // Setup the spi for 8 bit data, low steady state clock,
02873   // rising edge capture, with a 500KHz or 1MHz clock rate  
02874   _spi->format(8,0);
02875   _spi->frequency(1000000);    
02876   
02877   // The hardware Backlight pin is optional. Test and make sure whether it exists or not to prevent illegal access.
02878   if (bl != NC) {
02879     _bl = new DigitalOut(bl);   //Construct new pin 
02880     _bl->write(0);              //Deactivate    
02881   }
02882   else {
02883     // No Hardware Backlight pin       
02884     _bl = NULL;                 //Construct dummy pin     
02885   }  
02886 
02887   //Sanity check
02888   if (_ctrl & LCD_C_SPI3_24) {
02889     _init();      
02890   }
02891   else {
02892     error("Error: LCD Controller type does not support native SPI3 24 bits interface\n\r");           
02893   }
02894 }
02895 
02896 TextLCD_SPI_N_3_24::~TextLCD_SPI_N_3_24() {
02897    if (_bl != NULL) {delete _bl;}  // BL pin
02898 }
02899 
02900 // Not used in this mode
02901 void TextLCD_SPI_N_3_24::_setEnable(bool value) {
02902 }    
02903 
02904 // Set RS pin
02905 // Used for mbed pins, I2C bus expander or SPI shiftregister
02906 void TextLCD_SPI_N_3_24::_setRS(bool value) {
02907 // 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.
02908 // Each byte encodes 4 actual bits. The 8 actual bits represent either a data or a command byte.
02909 //   b23 b22 b21 b20 b19 b18 b17 b16 -  b15 b14 b13 b12 b11 b10 b9 b8 - b7 b6 b5 b4 b3 b2 b1 b0 
02910 //     1   1   1   1   1  RW  RS   0     d0  d1  d2  d3   0   0  0  0   d4 d5 d6 d7  0  0  0  0
02911 //
02912 //   RS=1 means that next byte is data, RS=0 means that next byte is command
02913 //   RW=0 means that next byte is writen, RW=1 means that next byte is read (not used in this lib)
02914 //
02915 // Note: SPI3_24 expects LSB first. This is inconsistent with regular SPI convention (and hardware) that sends MSB first.
02916 
02917   if (value) {
02918     _controlbyte = 0xFA; // Next byte is data
02919   }
02920   else {
02921     _controlbyte = 0xF8; // Next byte is command
02922   }
02923    
02924 }    
02925 
02926 // Set BL pin
02927 void TextLCD_SPI_N_3_24::_setBL(bool value) {
02928     if (_bl) {
02929         _bl->write(value);   
02930     }    
02931 }    
02932 
02933 // Not used in this mode
02934 void TextLCD_SPI_N_3_24::_setData(int value) {
02935 }    
02936 
02937 //Mapping table to flip the bits around cause SPI3_24 expects LSB first.
02938 const uint8_t map3_24[16] = {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0};
02939     
02940 // Write a byte using SPI3 24 bits mode
02941 void TextLCD_SPI_N_3_24::_writeByte(int value) {
02942     _cs = 0;
02943     wait_us(1);
02944     _spi->write(_controlbyte);
02945 
02946     //Map and send the LSB nibble
02947     _spi->write( map3_24[value & 0x0F]);     
02948 
02949     //Map and send the MSB nibble
02950     _spi->write( map3_24[(value >> 4) & 0x0F]);     
02951 
02952     wait_us(1);
02953     _cs = 1;
02954 }
02955   
02956 //------- End TextLCD_SPI_N_3_24 ----------
02957 #endif