Wim Huiskamp / LC75711

Dependents:   mbed_LC75711

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LC75711.cpp Source File

LC75711.cpp

00001 /* mbed LC75710 Library, for Sanyo LC7571X VFD controller
00002  * Note: The LC75710, LC75711 and LC75712 differ only in the built-in character ROM
00003  *
00004  * Copyright (c) 2017, v01: WH, Initial version
00005  *               2017, v02: WH, Cleaned up docs  
00006  *               2017, v03: WH, Modified setBlink  
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a copy
00009  * of this software and associated documentation files (the "Software"), to deal
00010  * in the Software without restriction, including without limitation the rights
00011  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00012  * copies of the Software, and to permit persons to whom the Software is
00013  * furnished to do so, subject to the following conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be included in
00016  * all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00019  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00021  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00022  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00023  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00024  * THE SOFTWARE.
00025  */
00026 
00027 #include "mbed.h" 
00028 #include "LC75711.h"
00029 #include "LC75711_UDC.inc"
00030 
00031 
00032  /** Constructor for class for driving Sanyo LC75711 VFD controller
00033   *
00034   *  @brief Supports upto 16 Grids of 35 matrix segments. Also supports 3-8 additional segments (depending on number of grids).
00035   *         SPI bus interface device. 
00036   *  @param  PinName mosi, sclk, cs SPI bus pins
00037   *  @param  Mode selects number of Grids and Segments (default 11 Grids, 35 matrix segments, 8 additional segments)
00038   */
00039 LC75711::LC75711(PinName mosi, PinName sclk, PinName cs, Mode mode) : _spi(mosi,NC,sclk), _cs(cs), _mode(mode) {
00040 
00041   _init();
00042 }
00043 
00044 /** Init the LC75711 interface and the controller
00045   *
00046   * @param  none
00047   * @return none
00048   */ 
00049 void LC75711::_init(){
00050   
00051 //init SPI
00052   _cs=0;
00053   _spi.format(8,0); //LC75711 uses mode 0 (Clock Low on Idle, Data latched on first (=rising) edge)
00054 //  _spi.frequency(100000);   
00055   _spi.frequency(250000);     
00056 
00057 //init controller  
00058 
00059   // Set number of Grids
00060   _writeCmd((LC75711_GRID_REG | _mode),      // B16..B23, Command register & value
00061              0x00,                           // B8..B15, Dummy
00062              0x00,                           // B0..B7, Dummy
00063              LC75711_GRID_DLY);              // Command Delay    
00064 
00065   _setAddress(0, 0); // No shift
00066 
00067   setBlink(false);   // No Blink
00068   setBrightness(LC75711_BRT_DEF); // Default Brightness
00069 
00070   // Clear the DCRAM (undefined at Reset)
00071   cls(); 
00072 
00073   // Clear the UDC RAM (undefined at Reset)
00074   const char udc_none[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
00075   for (int idx=0; idx < LC75711_NR_UDC; idx++) {
00076     setUDC(idx, (char *)udc_none);
00077   }
00078        
00079   setDisplay(true);  // Display On
00080 }   
00081 
00082 
00083 /** Clear the screen and locate to 0
00084   *
00085   * @param none
00086   * @return none  
00087   */  
00088 void LC75711::cls() {
00089 
00090   for (int cnt=0; cnt<LC75711_DISPLAY_MEM; cnt++) {
00091     writeData(char (' '), cnt); // data 
00092 //    writeData(0x00, cnt);       // data     
00093   }
00094 
00095   for (int cnt=0; cnt<LC75711_ADD_MEM; cnt++) {
00096     writeData(0x00, cnt);       // adata 
00097   }  
00098 }  
00099 
00100 /** Set the Blink mode
00101   *
00102   * @param int  grids selected grids for Blinking enable (default = all)
00103   * @return none  
00104   */
00105 void LC75711::setBlink(int grids) {
00106   
00107   // Sanity check and update of local shadow
00108   _blink = _blink | (grids & LC75711_GR_MSK);    // Set grid bits
00109 
00110   _writeCmd((LC75711_BLNK_REG | LC75711_BLNK_ON),  // B16..B23, Command register & value
00111              ((_blink >> 8) & 0xFF),               // B8..B15, GR8..GR16  
00112              ( _blink       & 0xFF),               // B0..B7, GR1..GR7            
00113              LC75711_BLNK_DLY);                    // Command Delay    
00114 }
00115 
00116 /** Clr the Blink mode
00117   *
00118   * @param int  grids selected grids for Blinking disable (default = all)
00119   * @return none  
00120   */
00121 void LC75711::clrBlink(int grids) {
00122   
00123   // Sanity check and update of local shadow
00124   _blink = _blink & ~(grids & LC75711_GR_MSK);   // Clr grid bits   
00125 
00126   _writeCmd((LC75711_BLNK_REG | LC75711_BLNK_ON),  // B16..B23, Command register & value
00127              ((_blink >> 8) & 0xFF),               // B8..B15, GR8..GR16  
00128              ( _blink       & 0xFF),               // B0..B7, GR1..GR7            
00129              LC75711_BLNK_DLY);                    // Command Delay    
00130 }
00131 
00132 /** Set Brightness
00133   *
00134   * @param  char brightness (8 significant bits, valid range 0..239 (dutycycle linked to number of grids)  
00135   * @return none
00136   */
00137 void LC75711::setBrightness(char brightness){
00138   
00139 //Sanity check
00140   brightness = brightness & LC75711_BRT_MSK; // mask invalid bits
00141   if (brightness > 239) {brightness = 239;} 
00142  
00143   _writeCmd((LC75711_BRT_REG),               // B16..B23, Command register
00144              brightness,                     // B8..B15, Brightness
00145              0x00,                           // B0..B7, Dummy
00146              LC75711_BRT_DLY);               // Command Delay      
00147 }
00148 
00149 /** Set the Display mode On/off
00150   *
00151   * @param bool display mode
00152   * @return none  
00153   */
00154 void LC75711::setDisplay(bool on) {
00155   char display;
00156      
00157   if (on) {
00158     display = LC75711_DSPL_ON;
00159   }
00160   else {
00161     display = LC75711_DSPL_OFF;
00162   }
00163 
00164   _writeCmd((LC75711_DSPL_REG | display),    // B16..B23, Command register & value
00165              0xFF,                           // B8..B15, GR8..GR16  
00166              0xFF,                           // B0..B7, GR1..GR7
00167              LC75711_DSPL_DLY);              // Command Delay    
00168 }
00169 
00170 
00171 /** Set User Defined Characters (UDC)
00172   *
00173   * @param unsigned char udc_idx   The Index of the UDC (0..7)
00174   * @param UDCData_t udc_data      The bitpattern for the UDC (7 bytes)
00175   * @return none  
00176   */
00177 void LC75711::setUDC(unsigned char udc_idx, UDCData_t udc_data) {
00178   char data;
00179   
00180 //Sanity check
00181   udc_idx = udc_idx & LC75711_UDC_MSK; // mask invalid bits
00182 
00183   _cs=0; // Prepare to send Address
00184   wait_us(1);    
00185 
00186   _spi.write(_flip(LC75711_ADDRESS)); // Address 
00187 
00188   _cs=1; // Latch Address, Prepare to send Command & Params 
00189   wait_us(1);
00190   
00191   data = ((udc_data[1] & 0x07) << 5) | ((udc_data[0] & 0x1F) << 0); 
00192   _spi.write(_flip(data));            // B0..B7, AM1-AM8
00193 
00194   data = ((udc_data[3] & 0x01) << 7) | ((udc_data[2] & 0x1F) << 2) | ((udc_data[1] & 0x18) >> 3);
00195   _spi.write(_flip(data));            // B8..B15, AM9-AM16  
00196     
00197   data = ((udc_data[4] & 0x0F) << 4) | ((udc_data[3] & 0x1E) >> 1);
00198   _spi.write(_flip(data));            // B16..B23, AM17-AM24  
00199 
00200   data = ((udc_data[6] & 0x03) << 6) | ((udc_data[5] & 0x1F) << 1) | ((udc_data[4] & 0x10) >> 4);
00201   _spi.write(_flip(data));            // B24..B31, AM25-AM32  
00202 
00203   data = ((udc_data[6] & 0x1C) >> 2);
00204   _spi.write(_flip(data));            // B32..B39, AM32-AM35  
00205 
00206   _spi.write(_flip(udc_idx));         // B40..B47, CA0-CA7  
00207   
00208   _spi.write(_flip(LC75711_UDC_REG)); // B48..B55, Command register
00209 
00210   wait_us(1);
00211   _cs=0; // Latch Command & Params
00212 
00213   wait_us(LC75711_UDC_DLY);           // Command Delay  
00214 }
00215 
00216 
00217 /** Write Data to LC75711
00218   *
00219   *  @param char data Character code
00220   *  @param char address Parameter for data
00221   *  @return none
00222   */  
00223 void LC75711::writeData(char data, char address){
00224 
00225 //Sanity check
00226   address = address & LC75711_DADR_MSK; // mask invalid bits
00227 
00228   _writeCmd((LC75711_DATA_REG),         // B16..B23, Command register
00229              address,                   // B8..B15, DCRAM address
00230              data,                      // B0..B7, Character code
00231              LC75711_DATA_DLY);         // Command Delay    
00232 }  
00233 
00234 /** Write Additional Data to LC75711
00235   *
00236   *  @param char adata Additional code (annunciator)
00237   *  @param char address Parameter for data
00238   *  @return none
00239   */  
00240 void LC75711::writeAData(char adata, char address){
00241 
00242 //Sanity check
00243   address = address & LC75711_AADR_MSK; // mask invalid bits
00244  
00245   _writeCmd((LC75711_ADAT_REG | address), // B16..B23, Command register & ADRAM address
00246              adata,                       // B8..B15, ADATA
00247              0x00,                        // B0..B7, Dummy
00248              LC75711_ADAT_DLY);           // Command Delay
00249 }  
00250 
00251 
00252 /** Set Address
00253   *
00254   *  @param char RAM address for data displayed at Grid1 (0..63)
00255   *  @param char RAM address for adata displayed at Grid1 (0..15) 
00256   *  @return none
00257   *
00258   *  Note that a Shift (L/R) command will change the Address of data displayed at Grid1
00259   */  
00260 void LC75711::_setAddress(char data_addr, char adata_addr){
00261 
00262 //Sanity check
00263   data_addr  =  data_addr & LC75711_DADR_MSK; // mask invalid bits
00264   adata_addr = adata_addr & LC75711_AADR_MSK; // mask invalid bits
00265 
00266   _writeCmd((LC75711_AC_REG | adata_addr),   // B16..B23, Command register & ADRAM address
00267              data_addr,                      // B8..B15, DCRAM address
00268              0x00,                           // B0..B7, Dummy
00269              LC75711_AC_DLY);                // Command Delay    
00270 }  
00271 
00272 
00273 /** Write command and parameters to LC75711
00274   *
00275   *  @param char cmd Command byte
00276   *  @param char data1 Parameters for command
00277   *  @param char data0 Parameters for command  
00278   *  @param char delay Delay for command execution
00279   *  @return none
00280   */  
00281 void LC75711::_writeCmd(char cmd, char data1, char data0, char delay){
00282 
00283   _cs=0; // Prepare to send Address
00284   wait_us(1);    
00285 
00286   _spi.write(_flip(LC75711_ADDRESS)); // Address 
00287 
00288   _cs=1; // Latch Address, Prepare to send Command & Params 
00289   wait_us(1);
00290 
00291   _spi.write(_flip(data0));        // B0..B7
00292 
00293   _spi.write(_flip(data1));        // B8..B15  
00294     
00295   _spi.write(_flip(cmd));          // B16..B23, Command register & value
00296 
00297   wait_us(1);
00298   _cs=0; // Latch Command & Params
00299 
00300   wait_us(delay);                  // Command Delay        
00301 }  
00302 
00303 
00304 /** Helper to reverse all command or databits. The LC75711 expects LSB first, whereas SPI is MSB first
00305   *
00306   *  @param  char data
00307   *  @return bitreversed data
00308   */ 
00309 char LC75711::_flip(char data) {
00310  char value=0;
00311   
00312  if (data & 0x01) {value |= 0x80;} ;  
00313  if (data & 0x02) {value |= 0x40;} ;
00314  if (data & 0x04) {value |= 0x20;} ;
00315  if (data & 0x08) {value |= 0x10;} ;
00316  if (data & 0x10) {value |= 0x08;} ;
00317  if (data & 0x20) {value |= 0x04;} ;
00318  if (data & 0x40) {value |= 0x02;} ;
00319  if (data & 0x80) {value |= 0x01;} ;
00320  return value;       
00321 }
00322 
00323 
00324 
00325 
00326 #if (ASTON_TEST == 1) 
00327 
00328 /** Constructor for class for Sanyo LC75711 VFD controller as used in ASTON
00329   *
00330   *  @brief Supports 10 Grids of 35 Segments without additional Segments and uses Grid 11 for Icon segments.
00331   *  
00332   *  @param  PinName mosi, miso, sclk, cs SPI bus pins
00333   */
00334 LC75711_ASTON::LC75711_ASTON(PinName mosi, PinName sclk, PinName cs) : LC75711(mosi, sclk, cs, Grid11_Add8) {
00335   _column   = 0;
00336   _columns  = ASTON_NR_DIGITS;
00337   
00338   // Clear the _udc_icon (should be cleared at Reset)
00339 //  for (int idx=0; idx < 7; idx++) {
00340 //    _udc_icon = 0x00;
00341 //  }
00342 }
00343 
00344 /** Locate cursor to a screen column
00345   *
00346   * @param column  The horizontal position from the left, indexed from 0
00347   * @return none  
00348   */
00349 void LC75711_ASTON::locate(int column) {
00350   //sanity check
00351   if (column < 0) {column = 0;}
00352   if (column > (_columns - 1)) {column = _columns - 1;}  
00353   
00354   _column = column;       
00355 }
00356 
00357 
00358 /** Number of screen columns
00359   *
00360   * @param none
00361   * @return columns
00362   */
00363 int LC75711_ASTON::columns() {
00364     return _columns;
00365 }
00366 
00367 
00368 /** Clear the screen and locate to 0
00369   *
00370   * @param bool clrAll Clear Icons also (default = false)
00371   * @return none  
00372   */ 
00373 void LC75711_ASTON::cls(bool clrAll) {  
00374 
00375   for (int cnt=0; cnt<ASTON_NR_DIGITS; cnt++) {
00376     writeData(char (' '), cnt); // data 
00377   }
00378 
00379   if (clrAll) {
00380     for (int cnt=0; cnt<ASTON_NR_DIGITS; cnt++) {
00381       writeAData(0x00, cnt);      // adata 
00382     }
00383     
00384     //Clear Icons
00385     //
00386   }  
00387 
00388   _column = 0;   
00389 }    
00390 
00391 
00392 /** Set Icon
00393   *
00394   * @param Icon Enums Icon Encodes UDC_0 byte index in 8 MSBs and encodes Icon bit/segment in 8 LSBs
00395   * @return none
00396   */
00397 void LC75711_ASTON::setIcon(Icon icon){
00398   int byte_idx, bits;
00399   
00400   byte_idx = (icon >> 8) & 0x07;          // Decode byte index and sanity mask
00401   bits     = (1 << (icon & 0x07)) & 0x1F; // Decode bits and sanity mask  
00402     
00403   //Set the segment bit for the Icon
00404   _udc_icon[byte_idx] |= bits;
00405   
00406   //Update UDC_0 used to display the Icons at Grid 11
00407   setUDC(0, _udc_icon);
00408 }
00409 
00410 /** Clr Icon
00411   *
00412   * @param Icon Enums Icon Encodes UDC_0 byte index in 8 MSBs and encodes Icon bit/segment in 8 LSBs     
00413   * @return none
00414   */
00415 void LC75711_ASTON::clrIcon(Icon icon) {
00416   int byte_idx, bits;
00417   
00418   byte_idx = (icon >> 8) & 0x07;          // Decode byte index and sanity mask
00419   bits     = (1 << (icon & 0x07)) & 0x1F; // Decode bits and sanity mask
00420     
00421   //Clear the segment bit for the Icon
00422   _udc_icon[byte_idx] &= ~bits;
00423   
00424   //Update UDC_0 used to display the Icons at Grid 11
00425   setUDC(0, _udc_icon);
00426 }
00427 
00428 /** Write a single character (Stream implementation)
00429   * 
00430   * @param value char to print
00431   * @return value;
00432   */
00433 int LC75711_ASTON::_putc(int value) {
00434     int addr;
00435     
00436     if ((value == '\n') || (value == '\r')) {
00437       //No character to write
00438      
00439       //Update Cursor      
00440       _column = 0;
00441     }
00442     else if ((value >= 0) && (value < 192)) {
00443       //Character to write
00444 
00445       //Translate between _column and displaybuffer entries
00446       //Note that the ASTON has 1 digit/grids. 
00447       //_column ==  0 => Grid10 => addr = 9
00448       //_column ==  1 => Grid9  => addr = 8
00449       // ....
00450       //_column ==  9 => Grid1  => addr = 0            
00451       addr = (9 - _column); // 1 Byte for every Grid;
00452       
00453       writeData(value, addr);
00454                                 
00455       //Update Cursor
00456       _column++;
00457       if (_column > (ASTON_NR_DIGITS - 1)) {        
00458         _column = 0;
00459       }
00460 
00461     } // if validChar           
00462 
00463     return value;
00464 }
00465 
00466 /** Get a single character (Stream implementation)
00467   *
00468   * @param none  
00469   * @return -1
00470   */
00471 int LC75711_ASTON::_getc() {
00472     return -1;
00473 }
00474 #endif