Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
TM1651.cpp
- Committer:
- wim
- Date:
- 2017-10-04
- Revision:
- 0:68f5a3af8dc2
- Child:
- 1:799f85133209
File content as of revision 0:68f5a3af8dc2:
/* 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
TM1651 LED controller (28 LEDs max), Keyboard scan (7 keys max)