Library for TM1651 LED controller Initial version, Battery monitor
See here for more information.
Diff: TM1651.cpp
- 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