Wim Huiskamp / TM1651

Dependents:   mbed_TM1651

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TM1651.cpp Source File

TM1651.cpp

00001 /* mbed TM1651 Library, for TM1651 LED controller
00002  * Copyright (c) 2017, v01: WH, Initial version, Battery monitor
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, inclumosig without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUmosiG BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020  * THE SOFTWARE.
00021  */
00022 #include "mbed.h" 
00023 #include "TM1651.h"
00024 
00025 
00026 /** Constructor for class for driving TM1651 LED controller with Serial bus interface device. 
00027  *  @brief Supports 4 digits @ 7 segments and 7 Keys. 
00028  *   
00029  *  @param  PinName dio Serial bus DIO pin 
00030  *  @param  PinName clk Serial bus CLK pin
00031 */
00032 TM1651::TM1651(PinName dio, PinName clk) : _dio(dio), _clk(clk) {
00033 
00034   _init();
00035 }
00036 
00037 
00038 /** Init the Serial interface and the controller
00039   * @param  none
00040   * @return none
00041   */ 
00042 void TM1651::_init(){
00043   
00044 //TM1651 uses a Serial bus that looks like I2C, but really is not.
00045 //It has Start and Stop conditions like I2C and an Ack pulse, but instead of slaveaddresses and a RW bit it just transmits commands and data.
00046 
00047 //init Serial bus
00048   _dio.output();
00049 //  _dio.mode(PullUp);
00050   wait_us(1);
00051 
00052   _dio=1;  
00053   _clk=1;  
00054 
00055 //init controller  
00056   _display = TM1651_DSP_ON;
00057   _bright  = TM1651_BRT_DEF; 
00058   _writeCmd(TM1651_DSP_CTRL_CMD, _display | _bright );                                 // Display control cmd, display on/off, brightness   
00059   
00060   _writeCmd(TM1651_DATA_SET_CMD, TM1651_DATA_WR | TM1651_ADDR_INC | TM1651_MODE_NORM); // Data set cmd, normal mode, auto incr, write data  
00061 }   
00062 
00063 
00064 /** Clear the screen and locate to 0
00065  */  
00066 void TM1651::cls() {
00067 
00068   _start();  
00069 
00070   _write(TM1651_ADDR_SET_CMD | 0x00); // Address set cmd, 0      
00071   for (int cnt=0; cnt<TM1651_DISPLAY_MEM; cnt++) {
00072     _write(0x00); // data 
00073   }
00074 
00075   _stop();  
00076 }  
00077 
00078 /** Set Brightness
00079   *
00080   * @param  char brightness (3 significant bits, valid range 0..7 (1/16 .. 14/14 dutycycle)  
00081   * @return none
00082   */
00083 void TM1651::setBrightness(char brightness){
00084 
00085   _bright = brightness & TM1651_BRT_MSK; // mask invalid bits
00086   
00087   _writeCmd(TM1651_DSP_CTRL_CMD, _display | _bright );  // Display control cmd, display on/off, brightness  
00088 }
00089 
00090 /** Set the Display mode On/off
00091   *
00092   * @param bool display mode
00093   */
00094 void TM1651::setDisplay(bool on) {
00095   
00096   if (on) {
00097     _display = TM1651_DSP_ON;
00098   }
00099   else {
00100     _display = TM1651_DSP_OFF;
00101   }
00102   
00103   _writeCmd(TM1651_DSP_CTRL_CMD, _display | _bright );  // Display control cmd, display on/off, brightness   
00104 }
00105 
00106 /** Write databyte to TM1651
00107   *  @param  int address display memory location to write byte
00108   *  @param  char data byte written at given address
00109   *  @return none
00110   */ 
00111 void TM1651::writeData(char data, int address) {
00112   
00113   _start();
00114 
00115   _write(TM1651_ADDR_SET_CMD | (address & TM1651_ADDR_MSK)); // Set Address cmd     
00116   _write(data); // data 
00117 
00118   _stop();  
00119 }
00120 
00121 /** Write Display datablock to TM1651
00122   *  @param  DisplayData_t data Array of TM1651_DISPLAY_MEM (=4) bytes for displaydata
00123   *  @param  length number bytes to write (valid range 0..(TM1651_MAX_NR_GRIDS * TM1651_BYTES_PER_GRID) (=4), when starting at address 0)  
00124   *  @param  int address display memory location to write bytes (default = 0) 
00125   *  @return none
00126   */  
00127 void TM1651::writeData(DisplayData_t data, int length, int address) {
00128 
00129   _start();
00130 
00131 // sanity check
00132   address &= TM1651_ADDR_MSK;
00133   if (length < 0) {length = 0;}
00134   if ((length + address) > TM1651_DISPLAY_MEM) {length = (TM1651_DISPLAY_MEM - address);}
00135     
00136 //  _write(TM1651_ADDR_SET_CMD | 0x00); // Set Address at 0
00137   _write(TM1651_ADDR_SET_CMD | address); // Set Address
00138   
00139   for (int idx=0; idx<length; idx++) {    
00140 //    _write(data[idx]); // data 
00141     _write(data[address + idx]); // data 
00142   }
00143   
00144   _stop();  
00145 }
00146 
00147 /** Read keydata block from TM1651
00148   *  @param  *keydata Ptr to bytes for keydata
00149   *  @return bool keypress True when at least one key was pressed
00150   */   
00151 bool TM1651::getKeys(KeyData_t *keydata) {
00152 
00153   _start();
00154 
00155   // Enable Key Read mode
00156   _write(TM1651_DATA_SET_CMD | TM1651_KEY_RD | TM1651_ADDR_INC | TM1651_MODE_NORM); // Data set cmd, normal mode, auto incr, read data
00157 
00158   // Read keys
00159   // Bitpattern S0 S1 S2 K1 K2 1 1 1  
00160   *keydata = _read();
00161 //  printf("Key = 0x%02x\r\n", *keydata);
00162 
00163   _stop();  
00164   
00165   // Restore Data Write mode
00166   _writeCmd(TM1651_DATA_SET_CMD, TM1651_DATA_WR | TM1651_ADDR_INC | TM1651_MODE_NORM); // Data set cmd, normal mode, auto incr, write data  
00167       
00168   return (*keydata != TM1651_SW_NONE);    
00169 }
00170   
00171 
00172 /** Generate Start condition for TM1651
00173   *  @param  none
00174   *  @return none
00175   */ 
00176 void TM1651::_start() {
00177 
00178   _dio=0;
00179   wait_us(1);
00180   _clk=0;
00181   wait_us(1);
00182 }
00183   
00184 /** Generate Stop condition for TM1651
00185   *  @param  none
00186   *  @return none
00187   */ 
00188 void TM1651::_stop() {
00189 
00190   _dio=0;
00191   wait_us(1);  
00192   _clk=1;
00193   wait_us(1);
00194   _dio=1;
00195   wait_us(1);
00196 }
00197 
00198 /** Send byte to TM1651
00199   *  @param  int data
00200   *  @return none
00201   */ 
00202 void TM1651::_write(int data) {
00203  
00204   for (int bit=0; bit<8; bit++) {    
00205     //The TM1651 expects LSB first
00206     if (((data >> bit) & 0x01) == 0x01) {
00207       _dio=1;      
00208     }
00209     else {    
00210       _dio=0;      
00211     }  
00212     wait_us(1);
00213     _clk=1;
00214     wait_us(1);
00215     _clk=0;  
00216     wait_us(1);
00217   }  
00218 
00219   _dio=1;
00220   
00221   // Prepare DIO to read data
00222   _dio.input();
00223   wait_us(3);
00224       
00225   // dummy Ack
00226   _clk=1;
00227   wait_us(1);
00228 //  _ack = _dio;  
00229   _clk=0;  
00230   wait_us(1); 
00231   
00232   // Return DIO to output mode
00233   _dio.output();  
00234   wait_us(3);  
00235 
00236   _dio=1; //idle  
00237 }
00238 
00239 /** Read byte from TM1651
00240   *  @return read byte 
00241   */ 
00242 char TM1651::_read() {
00243   char keycode = 0;
00244 
00245   // Prepare DIO to read data
00246   _dio.input();
00247   wait_us(3);
00248     
00249   for (int bit=0; bit<8; bit++) {    
00250    
00251     //The TM1651 sends bitpattern: S0 S1 S2 K1 K2 1 1 1
00252     //Data is shifted out by the TM1651 on the falling edge of CLK
00253     //Observe sufficient delay to allow the Open Drain DIO to rise to H levels
00254     // Prepare to read next bit, LSB (ie S0) first. 
00255     // The code below flips bits for easier matching with datasheet
00256     keycode = keycode << 1;  
00257 
00258     _clk=1;
00259     wait_us(1);
00260     
00261     // Read next bit
00262     if (_dio) { keycode |= 0x01; }        
00263 
00264     _clk=0;        
00265     wait_us(5); // Delay to allow for slow risetime
00266   }  
00267   
00268   // Return DIO to output mode
00269   _dio.output();
00270   wait_us(3);  
00271 
00272   // dummy Ack
00273   _dio=0; //Ack   
00274   wait_us(1);
00275   
00276   _clk=1;
00277   wait_us(1);
00278   _clk=0;  
00279   wait_us(1); 
00280 
00281   _dio=1; //idle
00282 
00283   return keycode;
00284 }
00285 
00286 /** Write command and parameter to TM1651
00287   *  @param  int cmd Command byte
00288   *  &Param  int data Parameters for command
00289   *  @return none
00290   */  
00291 void TM1651::_writeCmd(int cmd, int data){
00292     
00293   _start();
00294 
00295   _write((cmd & TM1651_CMD_MSK) | (data & ~TM1651_CMD_MSK));   
00296  
00297   _stop();          
00298 }  
00299 
00300 
00301 #if (OPENSMART_TEST == 1) 
00302 // Derived class for TM1651 used in OPEN_SMART battery display unit
00303 //
00304 
00305 /** Constructor for class for driving TM1651 LED controller
00306  *
00307  * @brief Supports battery display unit with 10 segments.
00308  *        Serial bus interface device. 
00309  *
00310  *  @param  PinName dio Serial bus DIO pin
00311  *  @param  PinName sck Serial bus CLK pin 
00312  */
00313 TM1651_OPENSMART::TM1651_OPENSMART(PinName dio, PinName clk) : TM1651(dio, clk) {
00314 
00315 }  
00316     
00317 /** Clear the screen and locate to 0
00318   * @param none
00319   * @return none
00320   */ 
00321 void TM1651_OPENSMART::cls() {  
00322 
00323   //clear local buffer
00324   for (int idx=0; idx < OPENSMART_NR_GRIDS; idx++) {
00325     _displaybuffer[idx] = 0x00;  
00326   }
00327 
00328   writeData(_displaybuffer, (OPENSMART_NR_GRIDS * TM1651_BYTES_PER_GRID), 0);
00329 }     
00330 
00331 /** Set Icon
00332   *
00333   * @param Icon Icon Enums Icon has Grid position encoded in 8 MSBs, Pattern encoded in 16 LSBs
00334   * @return none
00335   */
00336 void TM1651_OPENSMART::setIcon(Icon icon) {
00337   int addr, ld;
00338 
00339    ld =          icon & 0x7F;
00340   addr = (icon >> 24) & 0xFF; 
00341   addr = (addr - 1);
00342     
00343   //Set bits for Icon to write
00344   _displaybuffer[addr] |= ld;      
00345   writeData(_displaybuffer, TM1651_BYTES_PER_GRID, addr);  
00346 }
00347 
00348 /** Clr Icon
00349   *
00350   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Pattern encoded in 16 LSBs
00351   * @return none
00352   */
00353 void TM1651_OPENSMART::clrIcon(Icon icon) {
00354   int addr, ld;
00355 
00356    ld =          icon & 0x7F;
00357   addr = (icon >> 24) & 0xFF; 
00358   addr = (addr - 1);
00359     
00360   //Set bits for Icon to clear
00361   _displaybuffer[addr] &= ~ld;      
00362   writeData(_displaybuffer, TM1651_BYTES_PER_GRID, addr);  
00363 }
00364 
00365 
00366 /** Set Level
00367   *
00368   * @param Level level Enums Level indicates the Battery level to be displayed  
00369   * @return none
00370   */
00371 void TM1651_OPENSMART::setLevel(Level level) {
00372 
00373   //clear local buffer
00374   _displaybuffer[0] = 0x00;  
00375 
00376   //Set bits for level to write
00377   switch (level) {
00378     case LVL_0 :
00379             _displaybuffer[0] = R12;
00380             break;
00381 
00382     case LVL_1 :
00383             _displaybuffer[0] = R12 | Y3;
00384             break;
00385 
00386     case LVL_2 :
00387             _displaybuffer[0] = R12 | Y3 | Y4;
00388             break;
00389 
00390     case LVL_3 :
00391             _displaybuffer[0] = R12 | Y3 | Y4 | Y5;
00392             break;
00393 
00394     case LVL_4 :
00395             _displaybuffer[0] = R12 | Y3 | Y4 | Y5 | G67;
00396             break;
00397 
00398     case LVL_5 :
00399             _displaybuffer[0] = R12 | Y3 | Y4 | Y5 | G67 | G89;
00400             break;
00401 
00402     case LVL_6 :
00403             _displaybuffer[0] = R12 | Y3 | Y4 | Y5 | G67 | G89 | B10;
00404             break;
00405 
00406     default:
00407             _displaybuffer[0] = 0;    
00408             break;
00409   }    
00410  
00411   writeData(_displaybuffer, TM1651_BYTES_PER_GRID, 0);  
00412 }
00413 
00414 #endif