TM1638 LED controller. Max 80 LEDs, Max 24 Key scan. Supports LED&KEY, QYF-TM1638 and JY-LKM1638 module.

Dependents:   mbed_TM1638 Otjimaniya RL0201-V1

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TM1638.cpp Source File

TM1638.cpp

00001 /* mbed TM1638 Library, for TM1638 LED controller
00002  * Copyright (c) 2015, v01: WH, Initial version
00003  *               2016, v02: WH, Added ASCII alphabet display selector, refactored display and keyboard defines 
00004  *               2016, v03: WH, Added QYF-TM1638 and LKM1638, refactoring of writeData() 
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a copy
00007  * of this software and associated documentation files (the "Software"), to deal
00008  * in the Software without restriction, including without limitation the rights
00009  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00010  * copies of the Software, and to permit persons to whom the Software is
00011  * furnished to do so, subject to the following conditions:
00012  *
00013  * The above copyright notice and this permission notice shall be included in
00014  * all copies or substantial portions of the Software.
00015  *
00016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00019  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00020  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00021  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00022  * THE SOFTWARE.
00023  */
00024 #include "mbed.h" 
00025 #include "TM1638.h"
00026 
00027 /** Constructor for class for driving TM1638 LED controller with SPI bus interface device. 
00028  *  @brief Supports 8 digits @ 10 segments. 
00029  *         Also supports a scanned keyboard of upto 24 keys.
00030  *   
00031  *  @param  PinName mosi, miso, sclk, cs SPI bus pins
00032 */
00033 TM1638::TM1638(PinName mosi, PinName miso, PinName sclk, PinName cs) : _spi(mosi,miso,sclk), _cs(cs) {
00034 
00035   _init();
00036 }
00037 
00038 /** Init the SPI interface and the controller
00039   * @param  none
00040   * @return none
00041   */ 
00042 void TM1638::_init(){
00043   
00044 //init SPI
00045   _cs=1;
00046   _spi.format(8,3); //TM1638 uses mode 3 (Clock High on Idle, Data latched on second (=rising) edge)
00047   _spi.frequency(500000);   
00048 
00049 //init controller  
00050   _display = TM1638_DSP_ON;
00051   _bright  = TM1638_BRT_DEF; 
00052   _writeCmd(TM1638_DSP_CTRL_CMD, _display | _bright );                                 // Display control cmd, display on/off, brightness   
00053   
00054   _writeCmd(TM1638_DATA_SET_CMD, TM1638_DATA_WR | TM1638_ADDR_INC | TM1638_MODE_NORM); // Data set cmd, normal mode, auto incr, write data  
00055 }   
00056 
00057 
00058 /** Clear the screen and locate to 0
00059  */  
00060 void TM1638::cls() {
00061   
00062   _cs=0;
00063   wait_us(1);    
00064   _spi.write(_flip(TM1638_ADDR_SET_CMD | 0x00)); // Address set cmd, 0
00065       
00066   for (int cnt=0; cnt<TM1638_DISPLAY_MEM; cnt++) {
00067     _spi.write(0x00); // data 
00068   }
00069   
00070   wait_us(1);
00071   _cs=1;      
00072 }  
00073 
00074 /** Set Brightness
00075   *
00076   * @param  char brightness (3 significant bits, valid range 0..7 (1/16 .. 14/14 dutycycle)  
00077   * @return none
00078   */
00079 void TM1638::setBrightness(char brightness){
00080 
00081   _bright = brightness & TM1638_BRT_MSK; // mask invalid bits
00082   
00083   _writeCmd(TM1638_DSP_CTRL_CMD, _display | _bright );  // Display control cmd, display on/off, brightness  
00084 }
00085 
00086 /** Set the Display mode On/off
00087   *
00088   * @param bool display mode
00089   */
00090 void TM1638::setDisplay(bool on) {
00091   
00092   if (on) {
00093     _display = TM1638_DSP_ON;
00094   }
00095   else {
00096     _display = TM1638_DSP_OFF;
00097   }
00098   
00099   _writeCmd(TM1638_DSP_CTRL_CMD, _display | _bright );  // Display control cmd, display on/off, brightness   
00100 }
00101 
00102 
00103 /** Write databyte to TM1638
00104   *  @param  char data byte written at given address
00105   *  @param  int address display memory location to write byte
00106   *  @return none
00107   */ 
00108 void TM1638::writeData(char data, int address) {
00109   _cs=0;
00110   wait_us(1);    
00111   _spi.write(_flip(TM1638_ADDR_SET_CMD | (address & TM1638_ADDR_MSK))); // Set Address cmd
00112       
00113   _spi.write(_flip(data)); // data 
00114   
00115   wait_us(1);
00116   _cs=1;             
00117 }
00118 
00119 
00120 /** Write Display datablock to TM1638
00121   *  @param  DisplayData_t data Array of TM1638_DISPLAY_MEM (=16) bytes for displaydata
00122   *  @param  length number bytes to write (valid range 0..TM1638_DISPLAY_MEM (=16), when starting at address 0)
00123   *  @param  int address display memory location to write bytes (default = 0)   
00124   *  @return none
00125   */ 
00126 void TM1638::writeData(DisplayData_t data, int length, int address) {
00127   _cs=0;
00128   wait_us(1);    
00129        
00130 // sanity check
00131   address &= TM1638_ADDR_MSK;
00132   if (length < 0) {length = 0;}
00133   if ((length + address) > TM1638_DISPLAY_MEM) {length = (TM1638_DISPLAY_MEM - address);}
00134 
00135   // _spi.write(_flip(TM1638_ADDR_SET_CMD | 0x00)); // Set Address at 0
00136   _spi.write(_flip(TM1638_ADDR_SET_CMD | address)); // Set Address
00137 
00138   for (int idx=0; idx<length; idx++) {    
00139     //_spi.write(_flip(data[idx])); // data 
00140     _spi.write(_flip(data[address + idx])); // data 
00141   }
00142   
00143   wait_us(1);
00144   _cs=1;             
00145 }
00146 
00147 
00148 /** Read keydata block from TM1638
00149   *  @param  *keydata Ptr to Array of TM1638_KEY_MEM (=4) bytes for keydata
00150   *  @return bool keypress True when at least one key was pressed
00151   *
00152   * Note: Due to the hardware configuration the TM1638 key matrix scanner will detect multiple keys pressed at same time,
00153   *       but this may also result in some spurious keys being set in keypress data array.
00154   *       It may be best to ignore all keys in those situations. That option is implemented in this method depending on #define setting.  
00155   */ 
00156 bool TM1638::getKeys(KeyData_t *keydata) {
00157   int keypress = 0;
00158   char data;
00159 
00160   // Read keys
00161   _cs=0;
00162   wait_us(1);    
00163   
00164   // Enable Key Read mode
00165   _spi.write(_flip(TM1638_DATA_SET_CMD | TM1638_KEY_RD | TM1638_ADDR_INC | TM1638_MODE_NORM)); // Data set cmd, normal mode, auto incr, read data
00166 
00167   for (int idx=0; idx < TM1638_KEY_MEM; idx++) {
00168     data = _flip(_spi.write(0xFF));    // read keys and correct bitorder
00169 
00170     data = data & TM1638_KEY_MSK; // Mask valid bits
00171     if (data != 0) {  // Check for any pressed key
00172       for (int bit=0; bit < 8; bit++) {
00173         if (data & (1 << bit)) {keypress++;} // Test all significant bits
00174       }
00175     }  
00176 
00177     (*keydata)[idx] = data;            // Store keydata after correcting bitorder
00178   }
00179 
00180   wait_us(1);
00181   _cs=1;    
00182 
00183   // Restore Data Write mode
00184   _writeCmd(TM1638_DATA_SET_CMD, TM1638_DATA_WR | TM1638_ADDR_INC | TM1638_MODE_NORM); // Data set cmd, normal mode, auto incr, write data  
00185       
00186 #if(1)
00187 // Dismiss multiple keypresses at same time
00188   return (keypress == 1);    
00189 #else
00190 // Allow multiple keypress and accept possible spurious keys
00191   return (keypress > 0);
00192 #endif  
00193 }
00194     
00195 
00196 /** Helper to reverse all command or databits. The TM1638 expects LSB first, whereas SPI is MSB first
00197   *  @param  char data
00198   *  @return bitreversed data
00199   */ 
00200 #if(1)
00201 char TM1638::_flip(char data) {
00202  char value=0;
00203   
00204  if (data & 0x01) {value |= 0x80;} ;  
00205  if (data & 0x02) {value |= 0x40;} ;
00206  if (data & 0x04) {value |= 0x20;} ;
00207  if (data & 0x08) {value |= 0x10;} ;
00208  if (data & 0x10) {value |= 0x08;} ;
00209  if (data & 0x20) {value |= 0x04;} ;
00210  if (data & 0x40) {value |= 0x02;} ;
00211  if (data & 0x80) {value |= 0x01;} ;
00212  return value;       
00213 }
00214 #else
00215 char TM1638::_flip(char data) {
00216 
00217  data   = (((data & 0xAA) >> 1) | ((data & 0x55) << 1));
00218  data   = (((data & 0xCC) >> 2) | ((data & 0x33) << 2));
00219  return   (((data & 0xF0) >> 4) | ((data & 0x0F) << 4));
00220 }
00221 #endif
00222 
00223 /** Write command and parameter to TM1638
00224   *  @param  int cmd Command byte
00225   *  &Param  int data Parameters for command
00226   *  @return none
00227   */  
00228 void TM1638::_writeCmd(int cmd, int data){
00229     
00230   _cs=0;
00231   wait_us(1);    
00232 //  _spi.write(_flip( (cmd & 0xF0) | (data & 0x0F)));  
00233   _spi.write(_flip( (cmd & TM1638_CMD_MSK) | (data & ~TM1638_CMD_MSK)));   
00234  
00235   wait_us(1);
00236   _cs=1;          
00237 }  
00238 
00239 
00240 #if (LEDKEY8_TEST == 1) 
00241 // Derived class for TM1638 used in LED&KEY display unit
00242 //
00243 
00244 /** Constructor for class for driving TM1638 LED controller as used in LEDKEY8
00245   *
00246   *  @brief Supports 8 Digits of 7 Segments + DP + LED Icons. Also supports a scanned keyboard of 8.
00247   *   
00248   *  @param  PinName mosi, miso, sclk, cs SPI bus pins
00249   */
00250 TM1638_LEDKEY8::TM1638_LEDKEY8(PinName mosi, PinName miso, PinName sclk, PinName cs) : TM1638(mosi, miso, sclk, cs) {
00251   _column  = 0;
00252   _columns = LEDKEY8_NR_DIGITS;    
00253 }  
00254 
00255 #if(0)
00256 #if DOXYGEN_ONLY
00257     /** Write a character to the Display
00258      *
00259      * @param c The character to write to the display
00260      */
00261     int putc(int c);
00262 
00263     /** Write a formatted string to the Display
00264      *
00265      * @param format A printf-style format string, followed by the
00266      *               variables to use in formatting the string.
00267      */
00268     int printf(const char* format, ...);   
00269 #endif
00270 #endif
00271 
00272 /** Locate cursor to a screen column
00273   *
00274   * @param column  The horizontal position from the left, indexed from 0
00275   */
00276 void TM1638_LEDKEY8::locate(int column) {
00277   //sanity check
00278   if (column < 0) {column = 0;}
00279   if (column > (_columns - 1)) {column = _columns - 1;}  
00280   
00281   _column = column;       
00282 }
00283 
00284 
00285 /** Number of screen columns
00286   *
00287   * @param none
00288   * @return columns
00289   */
00290 int TM1638_LEDKEY8::columns() {
00291     return _columns;
00292 }
00293 
00294     
00295 /** Clear the screen and locate to 0
00296   * @param bool clrAll Clear Icons also (default = false)
00297   */ 
00298 void TM1638_LEDKEY8::cls(bool clrAll) {  
00299 
00300   if (clrAll) {
00301     //clear local buffer (including Icons)
00302     for (int idx=0; idx < (LEDKEY8_NR_GRIDS << 1); idx++) {
00303       _displaybuffer[idx] = 0x00;  
00304     }
00305   }  
00306   else {
00307     //clear local buffer (preserving Icons)
00308     for (int idx=0; idx < LEDKEY8_NR_GRIDS; idx++) {
00309       _displaybuffer[(idx<<1)]     = _displaybuffer[(idx<<1)]     & MASK_ICON_GRID[idx][0];  
00310       _displaybuffer[(idx<<1) + 1] = _displaybuffer[(idx<<1) + 1] & MASK_ICON_GRID[idx][1];
00311     }  
00312   }
00313 
00314   writeData(_displaybuffer, (LEDKEY8_NR_GRIDS * TM1638_BYTES_PER_GRID));
00315 
00316   _column = 0;   
00317 }     
00318 
00319 /** Set Icon
00320   *
00321   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs
00322   * @return none
00323   */
00324 void TM1638_LEDKEY8::setIcon(Icon icon) {
00325   int addr, icn;
00326 
00327    icn =        icon  & 0xFFFF;
00328   addr = (icon >> 24) & 0xFF; 
00329   addr = (addr - 1) << 1;   // * TM1638_BYTES_PER_GRID
00330     
00331   //Save char...and set bits for icon to write
00332   _displaybuffer[addr]   = _displaybuffer[addr]   | LO(icn);      
00333   _displaybuffer[addr+1] = _displaybuffer[addr+1] | HI(icn);      
00334 //  writeData(_displaybuffer, (LEDKEY8_NR_GRIDS * TM1638_BYTES_PER_GRID));
00335   writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);      
00336 }
00337 
00338 /** Clr Icon
00339   *
00340   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs
00341   * @return none
00342   */
00343 void TM1638_LEDKEY8::clrIcon(Icon icon) {
00344   int addr, icn;
00345 
00346    icn =        icon  & 0xFFFF;
00347   addr = (icon >> 24) & 0xFF; 
00348   addr = (addr - 1) << 1;   // * TM1638_BYTES_PER_GRID
00349     
00350   //Save char...and clr bits for icon to write
00351   _displaybuffer[addr]   = _displaybuffer[addr]   & ~LO(icn);      
00352   _displaybuffer[addr+1] = _displaybuffer[addr+1] & ~HI(icn);      
00353 //  writeData(_displaybuffer, (LEDKEY8_NR_GRIDS * TM1638_BYTES_PER_GRID));
00354   writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);      
00355 }
00356 
00357 
00358 /** Set User Defined Characters (UDC)
00359   *
00360   * @param unsigned char udc_idx  The Index of the UDC (0..7)
00361   * @param int udc_data           The bitpattern for the UDC (8 bits)       
00362   */
00363 void TM1638_LEDKEY8::setUDC(unsigned char udc_idx, int udc_data) {
00364 
00365   //Sanity check
00366   if (udc_idx > (LEDKEY8_NR_UDC-1)) {
00367     return;
00368   }
00369   // Mask out Icon bits?
00370 
00371   _UDC_7S[udc_idx] = LO(udc_data);
00372 }
00373 
00374 
00375 /** Write a single character (Stream implementation)
00376   */
00377 int TM1638_LEDKEY8::_putc(int value) {
00378     int addr;
00379     bool validChar = false;
00380     char pattern   = 0x00;
00381     
00382     if ((value == '\n') || (value == '\r')) {
00383       //No character to write
00384       validChar = false;
00385       
00386       //Update Cursor      
00387       _column = 0;
00388     }
00389     else if ((value == '.') || (value == ',')) {
00390       //No character to write
00391       validChar = false;
00392       pattern = S7_DP; // placeholder for all DPs
00393       
00394       // Check to see that DP can be shown for current column
00395       if (_column > 0) {
00396         //Translate between _column and displaybuffer entries
00397         //Add DP to bitpattern of digit left of current column.
00398         addr = (_column - 1) << 1; // * TM1638_BYTES_PER_GRID
00399       
00400         //Save icons...and set bits for decimal point to write
00401         _displaybuffer[addr]   = _displaybuffer[addr] | pattern;
00402 //        _displaybuffer[addr+1] = _displaybuffer[addr+1] | pattern;
00403 
00404 //        writeData(_displaybuffer, (LEDKEY8_NR_GRIDS * TM1638_BYTES_PER_GRID));
00405         writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);    
00406           
00407         //No Cursor Update
00408       }
00409     }
00410     else if ((value >= 0) && (value < LEDKEY8_NR_UDC)) {
00411       //Character to write
00412       validChar = true;
00413       pattern = _UDC_7S[value];
00414     }  
00415     
00416 #if (SHOW_ASCII == 1)
00417     //display all ASCII characters
00418     else if ((value >= FONT_7S_START) && (value <= FONT_7S_END)) {   
00419       //Character to write
00420       validChar = true;
00421       pattern = FONT_7S[value - FONT_7S_START];
00422     } // else
00423 #else    
00424     //display only digits and hex characters      
00425     else if (value == '-') {
00426       //Character to write
00427       validChar = true;
00428       pattern = C7_MIN;         
00429     }
00430     else if ((value >= (int)'0') && (value <= (int) '9')) {   
00431       //Character to write
00432       validChar = true;
00433       pattern = FONT_7S[value - (int) '0'];
00434     }
00435     else if ((value >= (int) 'A') && (value <= (int) 'F')) {   
00436       //Character to write
00437       validChar = true;
00438       pattern = FONT_7S[10 + value - (int) 'A'];
00439     }
00440     else if ((value >= (int) 'a') && (value <= (int) 'f')) {   
00441       //Character to write
00442       validChar = true;
00443       pattern = FONT_7S[10 + value - (int) 'a'];
00444     } //else
00445 #endif
00446 
00447     if (validChar) {
00448       //Character to write
00449  
00450       //Translate between _column and displaybuffer entries
00451       addr = _column << 1; // * TM1638_BYTES_PER_GRID
00452 
00453       //Save icons...and set bits for character to write
00454       _displaybuffer[addr]   = (_displaybuffer[addr]   & MASK_ICON_GRID[_column][0]) | pattern;
00455 //      _displaybuffer[addr+1] = (_displaybuffer[addr+1] & MASK_ICON_GRID[_column][0]) | pattern;
00456 
00457 //      writeData(_displaybuffer, (LEDKEY8_NR_GRIDS * TM1638_BYTES_PER_GRID));
00458       writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);
00459       
00460       //Update Cursor
00461       _column++;
00462       if (_column > (LEDKEY8_NR_DIGITS - 1)) {
00463         _column = 0;
00464       }
00465 
00466     } // if validChar           
00467 
00468     return value;
00469 }
00470 
00471 
00472 // get a single character (Stream implementation)
00473 int TM1638_LEDKEY8::_getc() {
00474     return -1;
00475 }
00476 
00477 #endif
00478 
00479 
00480 #if (QYF_TEST == 1) 
00481 // Derived class for TM1638 used in QYF-TM1638 display unit
00482 //
00483 
00484 /** Constructor for class for driving TM1638 LED controller as used in QYF
00485   *
00486   *  @brief Supports 8 Digits of 7 Segments + DP. Also supports a scanned keyboard of 16 keys.
00487   *   
00488   *  @param  PinName mosi, miso, sclk, cs SPI bus pins
00489   */
00490 TM1638_QYF::TM1638_QYF(PinName mosi, PinName miso, PinName sclk, PinName cs) : TM1638(mosi, miso, sclk, cs) {
00491   _column  = 0;
00492   _columns = QYF_NR_DIGITS;    
00493 }  
00494 
00495 #if(0)
00496 #if DOXYGEN_ONLY
00497     /** Write a character to the Display
00498      *
00499      * @param c The character to write to the display
00500      */
00501     int putc(int c);
00502 
00503     /** Write a formatted string to the Display
00504      *
00505      * @param format A printf-style format string, followed by the
00506      *               variables to use in formatting the string.
00507      */
00508     int printf(const char* format, ...);   
00509 #endif
00510 #endif
00511 
00512 /** Locate cursor to a screen column
00513   *
00514   * @param column  The horizontal position from the left, indexed from 0
00515   */
00516 void TM1638_QYF::locate(int column) {
00517   //sanity check
00518   if (column < 0) {column = 0;}
00519   if (column > (_columns - 1)) {column = _columns - 1;}  
00520   
00521   _column = column;       
00522 }
00523 
00524 
00525 /** Number of screen columns
00526   *
00527   * @param none
00528   * @return columns
00529   */
00530 int TM1638_QYF::columns() {
00531     return _columns;
00532 }
00533 
00534     
00535 /** Clear the screen and locate to 0
00536   * @param bool clrAll Clear Icons also (default = false)
00537   */ 
00538 void TM1638_QYF::cls(bool clrAll) {  
00539 
00540   if (clrAll) {
00541     //clear local buffer (including Icons)
00542     for (int idx=0; idx < (QYF_NR_GRIDS << 1); idx++) {
00543       _displaybuffer[idx] = 0x00;  
00544     }
00545   }  
00546   else {
00547     //clear local buffer (preserving Icons)
00548     for (int idx=0; idx < QYF_NR_GRIDS; idx++) {
00549       _displaybuffer[(idx<<1)]     = _displaybuffer[(idx<<1)]     & MASK_ICON_GRID[idx][0];  
00550       _displaybuffer[(idx<<1) + 1] = _displaybuffer[(idx<<1) + 1] & MASK_ICON_GRID[idx][1];
00551     }  
00552   }
00553 
00554   writeData(_displaybuffer, (QYF_NR_GRIDS * TM1638_BYTES_PER_GRID));
00555 
00556   _column = 0;   
00557 }     
00558 
00559 /** Set Icon
00560   *
00561   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs
00562   * @return none
00563   */
00564 void TM1638_QYF::setIcon(Icon icon) {
00565   int addr, icn;
00566 
00567    icn =        icon  & 0xFFFF;
00568   addr = (icon >> 24) & 0xFF; 
00569   addr = (addr - 1) << 1;   // * TM1638_BYTES_PER_GRID
00570     
00571   //Save char...and set bits for icon to write
00572   _displaybuffer[addr]   = _displaybuffer[addr]   | LO(icn);      
00573   _displaybuffer[addr+1] = _displaybuffer[addr+1] | HI(icn);      
00574 //  writeData(_displaybuffer, (QYF_NR_GRIDS * TM1638_BYTES_PER_GRID));
00575   writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);    
00576 }
00577 
00578 /** Clr Icon
00579   *
00580   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs
00581   * @return none
00582   */
00583 void TM1638_QYF::clrIcon(Icon icon) {
00584   int addr, icn;
00585 
00586    icn =        icon  & 0xFFFF;
00587   addr = (icon >> 24) & 0xFF; 
00588   addr = (addr - 1) << 1;   // * TM1638_BYTES_PER_GRID
00589     
00590   //Save char...and clr bits for icon to write
00591   _displaybuffer[addr]   = _displaybuffer[addr]   & ~LO(icn);      
00592   _displaybuffer[addr+1] = _displaybuffer[addr+1] & ~HI(icn);      
00593 //  writeData(_displaybuffer, (QYF_NR_GRIDS * TM1638_BYTES_PER_GRID));
00594   writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);  
00595 }
00596 
00597 
00598 /** Set User Defined Characters (UDC)
00599   *
00600   * @param unsigned char udc_idx  The Index of the UDC (0..7)
00601   * @param int udc_data           The bitpattern for the UDC (8 bits)       
00602   */
00603 void TM1638_QYF::setUDC(unsigned char udc_idx, int udc_data) {
00604 
00605   //Sanity check
00606   if (udc_idx > (QYF_NR_UDC-1)) {
00607     return;
00608   }
00609   // Mask out Icon bits?
00610 
00611   _UDC_7S[udc_idx] = LO(udc_data);
00612 }
00613 
00614 
00615 /** Write a single character (Stream implementation)
00616   */
00617 int TM1638_QYF::_putc(int value) {
00618     bool validChar = false;
00619     char pattern   = 0x00;
00620     char bit       = 0x00;
00621         
00622     if ((value == '\n') || (value == '\r')) {
00623       //No character to write
00624       validChar = false;
00625       
00626       //Update Cursor      
00627       _column = 0;
00628     }
00629     else if ((value == '.') || (value == ',')) {
00630       //No character to write
00631       validChar = false;
00632       pattern = S7_DP; // placeholder for all DPs
00633       
00634       // Check to see that DP can be shown for current column
00635       if (_column > 0) {
00636         //Add DP to bitpattern of digit left of current column.
00637         bit = 1 << (8 - _column); // bitposition for the previous _column
00638 
00639         _displaybuffer[14] = (_displaybuffer[14] | bit); // set bit
00640 
00641         writeData(_displaybuffer, (QYF_NR_GRIDS * TM1638_BYTES_PER_GRID));
00642         
00643         //No Cursor Update
00644       }
00645     }
00646     else if ((value >= 0) && (value < QYF_NR_UDC)) {
00647       //Character to write
00648       validChar = true;
00649       pattern = _UDC_7S[value];
00650     }  
00651     
00652 #if (SHOW_ASCII == 1)
00653     //display all ASCII characters
00654     else if ((value >= FONT_7S_START) && (value <= FONT_7S_END)) {   
00655       //Character to write
00656       validChar = true;
00657       pattern = FONT_7S[value - FONT_7S_START];
00658     } // else
00659 #else    
00660     //display only digits and hex characters      
00661     else if (value == '-') {
00662       //Character to write
00663       validChar = true;
00664       pattern = C7_MIN;         
00665     }
00666     else if ((value >= (int)'0') && (value <= (int) '9')) {   
00667       //Character to write
00668       validChar = true;
00669       pattern = FONT_7S[value - (int) '0'];
00670     }
00671     else if ((value >= (int) 'A') && (value <= (int) 'F')) {   
00672       //Character to write
00673       validChar = true;
00674       pattern = FONT_7S[10 + value - (int) 'A'];
00675     }
00676     else if ((value >= (int) 'a') && (value <= (int) 'f')) {   
00677       //Character to write
00678       validChar = true;
00679       pattern = FONT_7S[10 + value - (int) 'a'];
00680     } //else
00681 #endif
00682 
00683     if (validChar) {
00684       //Character to write
00685 
00686       // Very annoying bitmapping :(
00687       // This display module uses a single byte of each grid to drive a specific segment of all digits.
00688       // So the bits in byte 0 (Grid 1) drive all A-segments, the bits in byte 2 (Grid 2) drive all B-segments etc.
00689       // Bit0 is for the segment in Digit 8, Bit1 is for the segment in Digit 7 etc.. This bit manipulation is handled in _putc().
00690       
00691       bit = 1 << (7 - _column); // bitposition for the current _column
00692 
00693       if (pattern & S7_A) {_displaybuffer[0] = (_displaybuffer[0] | bit); } // set bit
00694       else                {_displaybuffer[0] = (_displaybuffer[0] & ~bit);} // clr bit       
00695 
00696       if (pattern & S7_B) {_displaybuffer[2] = (_displaybuffer[2] | bit); } // set bit
00697       else                {_displaybuffer[2] = (_displaybuffer[2] & ~bit);} // clr bit       
00698 
00699       if (pattern & S7_C) {_displaybuffer[4] = (_displaybuffer[4] | bit); } // set bit
00700       else                {_displaybuffer[4] = (_displaybuffer[4] & ~bit);} // clr bit       
00701 
00702       if (pattern & S7_D) {_displaybuffer[6] = (_displaybuffer[6] | bit); } // set bit
00703       else                {_displaybuffer[6] = (_displaybuffer[6] & ~bit);} // clr bit       
00704 
00705       if (pattern & S7_E) {_displaybuffer[8] = (_displaybuffer[8] | bit); } // set bit
00706       else                {_displaybuffer[8] = (_displaybuffer[8] & ~bit);} // clr bit       
00707 
00708       if (pattern & S7_F) {_displaybuffer[10] = (_displaybuffer[10] | bit); } // set bit
00709       else                {_displaybuffer[10] = (_displaybuffer[10] & ~bit);} // clr bit       
00710 
00711       if (pattern & S7_G) {_displaybuffer[12] = (_displaybuffer[12] | bit); } // set bit
00712       else                {_displaybuffer[12] = (_displaybuffer[12] & ~bit);} // clr bit       
00713 
00714       if (pattern & S7_DP) {_displaybuffer[14] = (_displaybuffer[14] | bit); } // set bit
00715       else                 {_displaybuffer[14] = (_displaybuffer[14] & ~bit);} // clr bit       
00716 
00717       //Save icons...and set bits for character to write
00718 //      _displaybuffer[addr]   = (_displaybuffer[addr]   & MASK_ICON_GRID[_column][0]) | pattern;
00719 //      _displaybuffer[addr+1] = (_displaybuffer[addr+1] & MASK_ICON_GRID[_column][0]) | pattern;
00720 
00721       writeData(_displaybuffer, (QYF_NR_GRIDS * TM1638_BYTES_PER_GRID));
00722                                 
00723       //Update Cursor
00724       _column++;
00725       if (_column > (QYF_NR_DIGITS - 1)) {
00726         _column = 0;
00727       }
00728 
00729     } // if validChar           
00730 
00731     return value;
00732 }
00733 
00734 
00735 // get a single character (Stream implementation)
00736 int TM1638_QYF::_getc() {
00737     return -1;
00738 }
00739 
00740 #endif
00741 
00742 
00743 
00744 #if (LKM1638_TEST == 1) 
00745 // Derived class for TM1638 used in LMK1638 display unit
00746 //
00747 
00748 /** Constructor for class for driving TM1638 LED controller as used in LKM1638
00749   *
00750   *  @brief Supports 8 Digits of 7 Segments + DP + Bi-Color LED Icons. Also supports a scanned keyboard of 8.
00751   *   
00752   *  @param  PinName mosi, miso, sclk, cs SPI bus pins
00753   */
00754 TM1638_LKM1638::TM1638_LKM1638(PinName mosi, PinName miso, PinName sclk, PinName cs) : TM1638(mosi, miso, sclk, cs) {
00755   _column  = 0;
00756   _columns = LKM1638_NR_DIGITS;    
00757 }  
00758 
00759 #if(0)
00760 #if DOXYGEN_ONLY
00761     /** Write a character to the Display
00762      *
00763      * @param c The character to write to the display
00764      */
00765     int putc(int c);
00766 
00767     /** Write a formatted string to the Display
00768      *
00769      * @param format A printf-style format string, followed by the
00770      *               variables to use in formatting the string.
00771      */
00772     int printf(const char* format, ...);   
00773 #endif
00774 #endif
00775 
00776 /** Locate cursor to a screen column
00777   *
00778   * @param column  The horizontal position from the left, indexed from 0
00779   */
00780 void TM1638_LKM1638::locate(int column) {
00781   //sanity check
00782   if (column < 0) {column = 0;}
00783   if (column > (_columns - 1)) {column = _columns - 1;}  
00784   
00785   _column = column;       
00786 }
00787 
00788 
00789 /** Number of screen columns
00790   *
00791   * @param none
00792   * @return columns
00793   */
00794 int TM1638_LKM1638::columns() {
00795     return _columns;
00796 }
00797 
00798     
00799 /** Clear the screen and locate to 0
00800   * @param bool clrAll Clear Icons also (default = false)
00801   */ 
00802 void TM1638_LKM1638::cls(bool clrAll) {  
00803 
00804   if (clrAll) {
00805     //clear local buffer (including Icons)
00806     for (int idx=0; idx < (LKM1638_NR_GRIDS << 1); idx++) {
00807       _displaybuffer[idx] = 0x00;  
00808     }
00809   }  
00810   else {
00811     //clear local buffer (preserving Icons)
00812     for (int idx=0; idx < LKM1638_NR_GRIDS; idx++) {
00813       _displaybuffer[(idx<<1)]     = _displaybuffer[(idx<<1)]     & MASK_ICON_GRID[idx][0];  
00814       _displaybuffer[(idx<<1) + 1] = _displaybuffer[(idx<<1) + 1] & MASK_ICON_GRID[idx][1];
00815     }  
00816   }
00817 
00818   writeData(_displaybuffer, (LKM1638_NR_GRIDS * TM1638_BYTES_PER_GRID));
00819 
00820   _column = 0;   
00821 }     
00822 
00823 /** Set Icon
00824   *
00825   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs
00826   * @return none
00827   */
00828 void TM1638_LKM1638::setIcon(Icon icon) {
00829   int addr, icn;
00830 
00831    icn =        icon  & 0xFFFF;
00832   addr = (icon >> 24) & 0xFF; 
00833   addr = (addr - 1) << 1;   // * TM1638_BYTES_PER_GRID
00834     
00835   //Save char...and set bits for icon to write
00836   _displaybuffer[addr]   = _displaybuffer[addr]   | LO(icn);      
00837   _displaybuffer[addr+1] = _displaybuffer[addr+1] | HI(icn);      
00838 //  writeData(_displaybuffer, (LKM1638_NR_GRIDS * TM1638_BYTES_PER_GRID));
00839   writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);      
00840 }
00841 
00842 /** Clr Icon
00843   *
00844   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs
00845   * @return none
00846   */
00847 void TM1638_LKM1638::clrIcon(Icon icon) {
00848   int addr, icn;
00849 
00850    icn =        icon  & 0xFFFF;
00851   addr = (icon >> 24) & 0xFF; 
00852   addr = (addr - 1) << 1;   // * TM1638_BYTES_PER_GRID
00853     
00854   //Save char...and clr bits for icon to write
00855   _displaybuffer[addr]   = _displaybuffer[addr]   & ~LO(icn);      
00856   _displaybuffer[addr+1] = _displaybuffer[addr+1] & ~HI(icn);      
00857 //  writeData(_displaybuffer, (LKM1638_NR_GRIDS * TM1638_BYTES_PER_GRID));
00858   writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);      
00859 }
00860 
00861 
00862 /** Set User Defined Characters (UDC)
00863   *
00864   * @param unsigned char udc_idx  The Index of the UDC (0..7)
00865   * @param int udc_data           The bitpattern for the UDC (8 bits)       
00866   */
00867 void TM1638_LKM1638::setUDC(unsigned char udc_idx, int udc_data) {
00868 
00869   //Sanity check
00870   if (udc_idx > (LKM1638_NR_UDC-1)) {
00871     return;
00872   }
00873   // Mask out Icon bits?
00874 
00875   _UDC_7S[udc_idx] = LO(udc_data);
00876 }
00877 
00878 
00879 /** Write a single character (Stream implementation)
00880   */
00881 int TM1638_LKM1638::_putc(int value) {
00882     int addr;
00883     bool validChar = false;
00884     char pattern   = 0x00;
00885     
00886     if ((value == '\n') || (value == '\r')) {
00887       //No character to write
00888       validChar = false;
00889       
00890       //Update Cursor      
00891       _column = 0;
00892     }
00893     else if ((value == '.') || (value == ',')) {
00894       //No character to write
00895       validChar = false;
00896       pattern = S7_DP; // placeholder for all DPs
00897       
00898       // Check to see that DP can be shown for current column
00899       if (_column > 0) {
00900         //Translate between _column and displaybuffer entries
00901         //Add DP to bitpattern of digit left of current column.
00902         addr = (_column - 1) << 1; // * TM1638_BYTES_PER_GRID
00903       
00904         //Save icons...and set bits for decimal point to write
00905         _displaybuffer[addr]   = _displaybuffer[addr] | pattern;
00906 //        _displaybuffer[addr+1] = _displaybuffer[addr+1] | pattern;
00907 
00908 //        writeData(_displaybuffer, (LKM1638_NR_GRIDS * TM1638_BYTES_PER_GRID));
00909         writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);    
00910           
00911         //No Cursor Update
00912       }
00913     }
00914     else if ((value >= 0) && (value < LKM1638_NR_UDC)) {
00915       //Character to write
00916       validChar = true;
00917       pattern = _UDC_7S[value];
00918     }  
00919     
00920 #if (SHOW_ASCII == 1)
00921     //display all ASCII characters
00922     else if ((value >= FONT_7S_START) && (value <= FONT_7S_END)) {   
00923       //Character to write
00924       validChar = true;
00925       pattern = FONT_7S[value - FONT_7S_START];
00926     } // else
00927 #else    
00928     //display only digits and hex characters      
00929     else if (value == '-') {
00930       //Character to write
00931       validChar = true;
00932       pattern = C7_MIN;         
00933     }
00934     else if ((value >= (int)'0') && (value <= (int) '9')) {   
00935       //Character to write
00936       validChar = true;
00937       pattern = FONT_7S[value - (int) '0'];
00938     }
00939     else if ((value >= (int) 'A') && (value <= (int) 'F')) {   
00940       //Character to write
00941       validChar = true;
00942       pattern = FONT_7S[10 + value - (int) 'A'];
00943     }
00944     else if ((value >= (int) 'a') && (value <= (int) 'f')) {   
00945       //Character to write
00946       validChar = true;
00947       pattern = FONT_7S[10 + value - (int) 'a'];
00948     } //else
00949 #endif
00950 
00951     if (validChar) {
00952       //Character to write
00953  
00954       //Translate between _column and displaybuffer entries
00955       addr = _column << 1; // * TM1638_BYTES_PER_GRID
00956 
00957       //Save icons...and set bits for character to write
00958       _displaybuffer[addr]   = (_displaybuffer[addr]   & MASK_ICON_GRID[_column][0]) | pattern;
00959 //      _displaybuffer[addr+1] = (_displaybuffer[addr+1] & MASK_ICON_GRID[_column][0]) | pattern;
00960 
00961 //      writeData(_displaybuffer, (LKM1638_NR_GRIDS * TM1638_BYTES_PER_GRID));
00962       writeData(_displaybuffer, TM1638_BYTES_PER_GRID, addr);
00963       
00964       //Update Cursor
00965       _column++;
00966       if (_column > (LKM1638_NR_DIGITS - 1)) {
00967         _column = 0;
00968       }
00969 
00970     } // if validChar           
00971 
00972     return value;
00973 }
00974 
00975 
00976 // get a single character (Stream implementation)
00977 int TM1638_LKM1638::_getc() {
00978     return -1;
00979 }
00980 
00981 #endif
00982