Library for TM1651 LED controller Initial version, Battery monitor

Dependents:   mbed_TM1651

See here for more information.

Revision:
0:68f5a3af8dc2
Child:
1:799f85133209
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TM1651.cpp	Wed Oct 04 19:54:30 2017 +0000
@@ -0,0 +1,413 @@
+/* mbed TM1651 Library, for TM1651 LED controller
+ * Copyright (c) 2016, v01: WH, Initial version, Battery monitor
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, inclumosig without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUmosiG BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "mbed.h" 
+#include "TM1651.h"
+
+
+/** Constructor for class for driving TM1651 LED controller with Serial bus interface device. 
+ *  @brief Supports 4 digits @ 7 segments and 7 Keys. 
+ *   
+ *  @param  PinName dio Serial bus DIO pin 
+ *  @param  PinName clk Serial bus CLK pin
+*/
+TM1651::TM1651(PinName dio, PinName clk) : _dio(dio), _clk(clk) {
+
+  _init();
+}
+
+
+/** Init the Serial interface and the controller
+  * @param  none
+  * @return none
+  */ 
+void TM1651::_init(){
+  
+//TM1651 uses a Serial bus that looks like I2C, but really is not.
+//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.
+
+//init Serial bus
+  _dio.output();
+//  _dio.mode(PullUp);
+  wait_us(1);
+
+  _dio=1;  
+  _clk=1;  
+
+//init controller  
+  _display = TM1651_DSP_ON;
+  _bright  = TM1651_BRT_DEF; 
+  _writeCmd(TM1651_DSP_CTRL_CMD, _display | _bright );                                 // Display control cmd, display on/off, brightness   
+  
+  _writeCmd(TM1651_DATA_SET_CMD, TM1651_DATA_WR | TM1651_ADDR_INC | TM1651_MODE_NORM); // Data set cmd, normal mode, auto incr, write data  
+}   
+
+
+/** Clear the screen and locate to 0
+ */  
+void TM1651::cls() {
+
+  _start();  
+
+  _write(TM1651_ADDR_SET_CMD | 0x00); // Address set cmd, 0      
+  for (int cnt=0; cnt<TM1651_DISPLAY_MEM; cnt++) {
+    _write(0x00); // data 
+  }
+
+  _stop();  
+}  
+
+/** Set Brightness
+  *
+  * @param  char brightness (3 significant bits, valid range 0..7 (1/16 .. 14/14 dutycycle)  
+  * @return none
+  */
+void TM1651::setBrightness(char brightness){
+
+  _bright = brightness & TM1651_BRT_MSK; // mask invalid bits
+  
+  _writeCmd(TM1651_DSP_CTRL_CMD, _display | _bright );  // Display control cmd, display on/off, brightness  
+}
+
+/** Set the Display mode On/off
+  *
+  * @param bool display mode
+  */
+void TM1651::setDisplay(bool on) {
+  
+  if (on) {
+    _display = TM1651_DSP_ON;
+  }
+  else {
+    _display = TM1651_DSP_OFF;
+  }
+  
+  _writeCmd(TM1651_DSP_CTRL_CMD, _display | _bright );  // Display control cmd, display on/off, brightness   
+}
+
+/** Write databyte to TM1651
+  *  @param  int address display memory location to write byte
+  *  @param  char data byte written at given address
+  *  @return none
+  */ 
+void TM1651::writeData(char data, int address) {
+  
+  _start();
+
+  _write(TM1651_ADDR_SET_CMD | (address & TM1651_ADDR_MSK)); // Set Address cmd     
+  _write(data); // data 
+
+  _stop();  
+}
+
+/** Write Display datablock to TM1651
+  *  @param  DisplayData_t data Array of TM1651_DISPLAY_MEM (=4) bytes for displaydata
+  *  @param  length number bytes to write (valid range 0..(TM1651_MAX_NR_GRIDS * TM1651_BYTES_PER_GRID) (=4), when starting at address 0)  
+  *  @param  int address display memory location to write bytes (default = 0) 
+  *  @return none
+  */  
+void TM1651::writeData(DisplayData_t data, int length, int address) {
+
+  _start();
+
+// sanity check
+  address &= TM1651_ADDR_MSK;
+  if (length < 0) {length = 0;}
+  if ((length + address) > TM1651_DISPLAY_MEM) {length = (TM1651_DISPLAY_MEM - address);}
+    
+//  _write(TM1651_ADDR_SET_CMD | 0x00); // Set Address at 0
+  _write(TM1651_ADDR_SET_CMD | address); // Set Address
+  
+  for (int idx=0; idx<length; idx++) {    
+//    _write(data[idx]); // data 
+    _write(data[address + idx]); // data 
+  }
+  
+  _stop();  
+}
+
+/** Read keydata block from TM1651
+  *  @param  *keydata Ptr to bytes for keydata
+  *  @return bool keypress True when at least one key was pressed
+  */   
+bool TM1651::getKeys(KeyData_t *keydata) {
+
+  _start();
+
+  // Enable Key Read mode
+  _write(TM1651_DATA_SET_CMD | TM1651_KEY_RD | TM1651_ADDR_INC | TM1651_MODE_NORM); // Data set cmd, normal mode, auto incr, read data
+
+  // Read keys
+  // Bitpattern S0 S1 S2 K1 K2 1 1 1  
+  *keydata = _read();
+//  printf("Key = 0x%02x\r\n", *keydata);
+
+  _stop();  
+  
+  // Restore Data Write mode
+  _writeCmd(TM1651_DATA_SET_CMD, TM1651_DATA_WR | TM1651_ADDR_INC | TM1651_MODE_NORM); // Data set cmd, normal mode, auto incr, write data  
+      
+  return (*keydata != TM1651_SW_NONE);    
+}
+  
+
+/** Generate Start condition for TM1651
+  *  @param  none
+  *  @return none
+  */ 
+void TM1651::_start() {
+
+  _dio=0;
+  wait_us(1);
+  _clk=0;
+  wait_us(1);
+}
+  
+/** Generate Stop condition for TM1651
+  *  @param  none
+  *  @return none
+  */ 
+void TM1651::_stop() {
+
+  _dio=0;
+  wait_us(1);  
+  _clk=1;
+  wait_us(1);
+  _dio=1;
+  wait_us(1);
+}
+
+/** Send byte to TM1651
+  *  @param  int data
+  *  @return none
+  */ 
+void TM1651::_write(int data) {
+ 
+  for (int bit=0; bit<8; bit++) {    
+    //The TM1651 expects LSB first
+    if (((data >> bit) & 0x01) == 0x01) {
+      _dio=1;      
+    }
+    else {    
+      _dio=0;      
+    }  
+    wait_us(1);
+    _clk=1;
+    wait_us(1);
+    _clk=0;  
+    wait_us(1);
+  }  
+
+  _dio=1;
+  
+  // Prepare DIO to read data
+  _dio.input();
+  wait_us(3);
+      
+  // dummy Ack
+  _clk=1;
+  wait_us(1);
+//  _ack = _dio;  
+  _clk=0;  
+  wait_us(1); 
+  
+  // Return DIO to output mode
+  _dio.output();  
+  wait_us(3);  
+
+  _dio=1; //idle  
+}
+
+/** Read byte from TM1651
+  *  @return read byte 
+  */ 
+char TM1651::_read() {
+  char keycode = 0;
+
+  // Prepare DIO to read data
+  _dio.input();
+  wait_us(3);
+    
+  for (int bit=0; bit<8; bit++) {    
+   
+    //The TM1651 sends bitpattern: S0 S1 S2 K1 K2 1 1 1
+    //Data is shifted out by the TM1651 on the falling edge of CLK
+    //Observe sufficient delay to allow the Open Drain DIO to rise to H levels
+    // Prepare to read next bit, LSB (ie S0) first. 
+    // The code below flips bits for easier matching with datasheet
+    keycode = keycode << 1;  
+
+    _clk=1;
+    wait_us(1);
+    
+    // Read next bit
+    if (_dio) { keycode |= 0x01; }        
+
+    _clk=0;        
+    wait_us(5); // Delay to allow for slow risetime
+  }  
+  
+  // Return DIO to output mode
+  _dio.output();
+  wait_us(3);  
+
+  // dummy Ack
+  _dio=0; //Ack   
+  wait_us(1);
+  
+  _clk=1;
+  wait_us(1);
+  _clk=0;  
+  wait_us(1); 
+
+  _dio=1; //idle
+
+  return keycode;
+}
+
+/** Write command and parameter to TM1651
+  *  @param  int cmd Command byte
+  *  &Param  int data Parameters for command
+  *  @return none
+  */  
+void TM1651::_writeCmd(int cmd, int data){
+    
+  _start();
+
+  _write((cmd & TM1651_CMD_MSK) | (data & ~TM1651_CMD_MSK));   
+ 
+  _stop();          
+}  
+
+
+#if (OPENSMART_TEST == 1) 
+// Derived class for TM1651 used in OPEN_SMART battery display unit
+//
+
+/** Constructor for class for driving TM1651 LED controller
+ *
+ * @brief Supports battery display unit with 10 segments.
+ *        Serial bus interface device. 
+ *
+ *  @param  PinName dio Serial bus DIO pin
+ *  @param  PinName sck Serial bus CLK pin 
+ */
+TM1651_OPENSMART::TM1651_OPENSMART(PinName dio, PinName clk) : TM1651(dio, clk) {
+
+}  
+    
+/** Clear the screen and locate to 0
+  * @param none
+  * @return none
+  */ 
+void TM1651_OPENSMART::cls() {  
+
+  //clear local buffer
+  for (int idx=0; idx < OPENSMART_NR_GRIDS; idx++) {
+    _displaybuffer[idx] = 0x00;  
+  }
+
+  writeData(_displaybuffer, (OPENSMART_NR_GRIDS * TM1651_BYTES_PER_GRID), 0);
+}     
+
+/** Set Icon
+  *
+  * @param Icon Icon Enums Icon has Grid position encoded in 8 MSBs, Pattern encoded in 16 LSBs
+  * @return none
+  */
+void TM1651_OPENSMART::setIcon(Icon icon) {
+  int addr, ld;
+
+   ld =          icon & 0x7F;
+  addr = (icon >> 24) & 0xFF; 
+  addr = (addr - 1);
+    
+  //Set bits for Icon to write
+  _displaybuffer[addr] |= ld;      
+  writeData(_displaybuffer, TM1651_BYTES_PER_GRID, addr);  
+}
+
+/** Clr Icon
+  *
+  * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Pattern encoded in 16 LSBs
+  * @return none
+  */
+void TM1651_OPENSMART::clrIcon(Icon icon) {
+  int addr, ld;
+
+   ld =          icon & 0x7F;
+  addr = (icon >> 24) & 0xFF; 
+  addr = (addr - 1);
+    
+  //Set bits for Icon to clear
+  _displaybuffer[addr] &= ~ld;      
+  writeData(_displaybuffer, TM1651_BYTES_PER_GRID, addr);  
+}
+
+
+/** Set Level
+  *
+  * @param Level level Enums Level indicates the Battery level to be displayed  
+  * @return none
+  */
+void TM1651_OPENSMART::setLevel(Level level) {
+
+  //clear local buffer
+  _displaybuffer[0] = 0x00;  
+
+  //Set bits for level to write
+  switch (level) {
+    case LVL_0 :
+            _displaybuffer[0] = R12;
+            break;
+
+    case LVL_1 :
+            _displaybuffer[0] = R12 | Y3;
+            break;
+
+    case LVL_2 :
+            _displaybuffer[0] = R12 | Y3 | Y4;
+            break;
+
+    case LVL_3 :
+            _displaybuffer[0] = R12 | Y3 | Y4 | Y5;
+            break;
+
+    case LVL_4 :
+            _displaybuffer[0] = R12 | Y3 | Y4 | Y5 | G67;
+            break;
+
+    case LVL_5 :
+            _displaybuffer[0] = R12 | Y3 | Y4 | Y5 | G67 | G89;
+            break;
+
+    case LVL_6 :
+            _displaybuffer[0] = R12 | Y3 | Y4 | Y5 | G67 | G89 | B10;
+            break;
+
+    default:
+            break;
+  }    
+ 
+  writeData(_displaybuffer, TM1651_BYTES_PER_GRID, 0);  
+}
+
+#endif