diff --git a/IO_TM1638.cpp b/IO_TM1638.cpp new file mode 100644 index 0000000..395d745 --- /dev/null +++ b/IO_TM1638.cpp @@ -0,0 +1,127 @@ +/* + * © 2024, Chris Harlow. All rights reserved. + * + * This file is part of DCC++EX API + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * It is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CommandStation. If not, see . + */ + +#include +#include "IODevice.h" +#include "DIAG.h" +#include "IO_TM1638.h" +#include "TM1638x.h" + +const uint8_t HIGHFLASH _digits[16]={ + 0b00111111,0b00000110,0b01011011,0b01001111, + 0b01100110,0b01101101,0b01111101,0b00000111, + 0b01111111,0b01101111,0b01110111,0b01111100, + 0b00111001,0b01011110,0b01111001,0b01110001 + }; + + // Constructor + TM1638::TM1638(VPIN firstVpin, byte clk_pin,byte dio_pin,byte stb_pin){ + _firstVpin = firstVpin; + _nPins = 8; + tm=new TM1638x(clk_pin,dio_pin,stb_pin); + _buttons=0; + _leds=0; + _lastLoop=micros(); + addDevice(this); + } + + + void TM1638::create(VPIN firstVpin, byte clk_pin,byte dio_pin,byte stb_pin) { + if (checkNoOverlap(firstVpin,8)) + new TM1638(firstVpin, clk_pin,dio_pin,stb_pin); + } + + void TM1638::_begin() { + tm->reset(); + tm->test(); + _display(); + } + + + void TM1638::_loop(unsigned long currentMicros) { + if (currentMicros - _lastLoop > (1000000UL/LoopHz)) { + _buttons=tm->getButtons();// Read the buttons + _lastLoop=currentMicros; + } + // DIAG(F("TM1638 buttons %x"),_buttons); + } + + void TM1638::_display() { + DIAG(F("TM1638 Configured on Vpins:%u-%u"), _firstVpin, _firstVpin+_nPins-1); + } + +// digital read gets button state +int TM1638::_read(VPIN vpin) { + byte pin=vpin - _firstVpin; + bool result=bitRead(_buttons,pin); + // DIAG(F("TM1638 read (%d) buttons %x = %d"),pin,_buttons,result); + return result; +} + +// digital write sets led state +void TM1638::_write(VPIN vpin, int value) { + // TODO.. skip if no state change + tm->writeLed(vpin - _firstVpin + 1,value!=0); + } + +// Analog write sets digit displays + +void TM1638::_writeAnalogue(VPIN vpin, int lowBytes, uint8_t mode, uint16_t highBytes) { + DIAG(F("TM1638 w(v=%d,l=%d,m=%d,h=%d,lx=%x,hx=%x"), + vpin,lowBytes,mode,highBytes,lowBytes,highBytes); + // mode is in DataFormat defined above. + byte formatLength=mode & 0x0F; // last 4 bits + byte formatType=mode & 0xF0; // + int8_t leftDigit=vpin-_firstVpin; // 0..7 from left + int8_t rightDigit=leftDigit+formatLength-1; // 0..7 from left + + // loading is done right to left startDigit first + int8_t startDigit=7-rightDigit; // reverse as 7 on left + int8_t lastDigit=7-leftDigit; // reverse as 7 on left + uint32_t value=highBytes; + value<<=16; + value |= (uint16_t)lowBytes; + + DIAG(F("TM1638 fl=%d ft=%x sd=%d ld=%d v=%l vx=%X"), + formatLength,formatType, + startDigit,lastDigit,value,value); + while(startDigit<=lastDigit) { + switch (formatType) { + case _DF_DECIMAL:// decimal (leading zeros) + tm->displayDig(startDigit,GETHIGHFLASH(_digits,(value%10))); + value=value/10; + break; + case _DF_HEX:// HEX (leading zeros) + tm->displayDig(startDigit,GETHIGHFLASH(_digits,(value & 0x0F))); + value>>=4; + break; + case _DF_RAW:// Raw 7-segment pattern + tm->displayDig(startDigit,value & 0xFF); + value>>=8; + break; + default: + DIAG(F("TM1368 invalid mode 0x%x"),mode); + return; + } + startDigit++; + } + +} + + diff --git a/IO_TM1638.h b/IO_TM1638.h index 388ce95..beb3ead 100644 --- a/IO_TM1638.h +++ b/IO_TM1638.h @@ -32,19 +32,10 @@ private: uint8_t _leds; unsigned long _lastLoop; static const int LoopHz=20; - -private: + // Constructor - TM1638(VPIN firstVpin, byte clk_pin,byte dio_pin,byte stb_pin){ - _firstVpin = firstVpin; - _nPins = 8; - tm=new TM1638x(clk_pin,dio_pin,stb_pin); - _buttons=0; - _leds=0; - _lastLoop=micros(); - addDevice(this); - } - + TM1638(VPIN firstVpin, byte clk_pin,byte dio_pin,byte stb_pin); + public: enum DigitFormat : byte { // last 4 bits are length. @@ -61,89 +52,17 @@ public: // bits of data conversion type (ored with length) _DF_DECIMAL=0x00,// right adjusted decimal unsigned leading zeros _DF_HEX=0x10, // right adjusted hex leading zeros - _DF_RAW=0x20, // bytes are raw 7-segment pattern (max length 4) + _DF_RAW=0x20 // bytes are raw 7-segment pattern (max length 4) }; - static void create(VPIN firstVpin, byte clk_pin,byte dio_pin,byte stb_pin) { - if (checkNoOverlap(firstVpin,8)) - new TM1638(firstVpin, clk_pin,dio_pin,stb_pin); - } - - void _begin() override { - tm->reset(); - tm->test(); - _display(); - } + static void create(VPIN firstVpin, byte clk_pin,byte dio_pin,byte stb_pin); - - void _loop(unsigned long currentMicros) override { - if (currentMicros - _lastLoop > (1000000UL/LoopHz)) { - _buttons=tm->getButtons();// Read the buttons - _lastLoop=currentMicros; - } - // DIAG(F("TM1638 buttons %x"),_buttons); - } - - void _display() override { - DIAG(F("TM1638 Configured on Vpins:%u-%u"), _firstVpin, _firstVpin+_nPins-1); - } - -// digital read gets button state -int _read(VPIN vpin) override { - byte pin=vpin - _firstVpin; - bool result=bitRead(_buttons,pin); - // DIAG(F("TM1638 read (%d) buttons %x = %d"),pin,_buttons,result); - return result; -} - -// digital write sets led state -void _write(VPIN vpin, int value) override { - // TODO.. skip if no state change - tm->writeLed(vpin - _firstVpin + 1,value!=0); - } - -// Analog write sets digit displays - -void _writeAnalogue(VPIN vpin, int lowBytes, uint8_t mode, uint16_t highBytes) override { - DIAG(F("TM1638 w(v=%d,l=%d,m=%d,h=%d,lx=%x,hx=%x"), - vpin,lowBytes,mode,highBytes,lowBytes,highBytes); - // mode is in DataFormat defined above. - byte formatLength=mode & 0x0F; // last 4 bits - byte formatType=mode & 0xF0; // - int8_t leftDigit=vpin-_firstVpin; // 0..7 from left - int8_t rightDigit=leftDigit+formatLength-1; // 0..7 from left - - // loading is done right to left startDigit first - int8_t startDigit=7-rightDigit; // reverse as 7 on left - int8_t lastDigit=7-leftDigit; // reverse as 7 on left - uint32_t value=highBytes; - value<<=16; - value |= (uint16_t)lowBytes; - - DIAG(F("TM1638 fl=%d ft=%x sd=%d ld=%d v=%l vx=%X"), - formatLength,formatType, - startDigit,lastDigit,value,value); - while(startDigit<=lastDigit) { - switch (formatType) { - case _DF_DECIMAL:// decimal (leading zeros) - tm->displayVal(startDigit,value%10); - value=value/10; - break; - case _DF_HEX:// HEX (leading zeros) - tm->displayVal(startDigit,value & 0x0F); - value>>=4; - break; - case _DF_RAW:// Raw 7-segment pattern - tm->displayDig(startDigit,value & 0xFF); - value>>=8; - break; - default: - DIAG(F("TM1368 invalid mode 0x%x"),mode); - return; - } - startDigit++; - } - -} + // Functions overridden in IODevice + void _begin(); + void _loop(unsigned long currentMicros) override ; + void _writeAnalogue(VPIN vpin, int value, uint8_t param1, uint16_t param2) override; + void _display() override ; + int _read(VPIN pin) override; + void _write(VPIN pin,int value) override; }; -#endif // IO_TM1638_h +#endif diff --git a/TM1638x.cpp b/TM1638x.cpp index 7df23b9..45c8625 100644 --- a/TM1638x.cpp +++ b/TM1638x.cpp @@ -2,10 +2,6 @@ #include "TM1638x.h" #include "DIAG.h" -bool TM1638x::getButton(button_t s){ - _buttons = getButtons(); - return bitRead(_buttons, s); -} // buttons K3/KS1-8 uint8_t TM1638x::getButtons(){ @@ -38,14 +34,6 @@ void TM1638x::reset(){ digitalWrite(_stb_pin, HIGH); } -void TM1638x::displayVal(uint8_t digitId, uint8_t val){ - DIAG(F("TM1638x displayVal(%d,%d)"),digitId,val); - if ((digitId>7) | (val>15) | (val<0)) return; - setDisplayMode(DISPLAY_TURN_ON | _pulse); - setDataInstruction(INSTRUCTION_WRITE_DATA| INSTRUCTION_ADDRESS_FIXED); - writeDataAt(FIRST_DISPLAY_ADDRESS+14-(digitId*2), _digits[val]); -} - void TM1638x::displayDig(uint8_t digitId, uint8_t pgfedcba){ if (digitId>7) return; setDisplayMode(DISPLAY_TURN_ON | _pulse); @@ -69,15 +57,6 @@ void TM1638x::writeLed(uint8_t num,bool state){ writeDataAt(FIRST_DISPLAY_ADDRESS + (num*2-1), state); } -void TM1638x::writeLeds(uint8_t val){ - setDisplayMode(DISPLAY_TURN_ON | _pulse); - setDataInstruction(INSTRUCTION_WRITE_DATA | INSTRUCTION_ADDRESS_FIXED); - for(uint8_t i=1;i<9;i++){ - writeDataAt(FIRST_DISPLAY_ADDRESS + (i*2-1), val & 0x01); - val >>= 1; - } -} - void TM1638x::displayTurnOn(){ setDisplayMode(DISPLAY_TURN_ON | _pulse); _isOn = true; diff --git a/TM1638x.h b/TM1638x.h index baaa9d6..6bbb23d 100644 --- a/TM1638x.h +++ b/TM1638x.h @@ -50,12 +50,6 @@ class TM1638x{ #define DISPLAY_TURN_OFF 0x80 #define DISPLAY_TURN_ON 0x88 - uint8_t _digits[16]={ - 0b00111111,0b00000110,0b01011011,0b01001111, - 0b01100110,0b01101101,0b01111101,0b00000111, - 0b01111111,0b01101111,0b01110111,0b01111100, - 0b00111001,0b01011110,0b01111001,0b01110001 - }; uint8_t _clk_pin; uint8_t _stb_pin; @@ -80,12 +74,6 @@ class TM1638x{ digitalWrite(dio_pin, HIGH); } - /** - * @fn getButton - * @param s num of button (S1-S8) - * @return state of button - */ - bool getButton(button_t s); /** * @fn getButtons * @return state of 8 buttons @@ -99,22 +87,7 @@ class TM1638x{ * @param state (true or false) */ void writeLed(uint8_t num, bool state); - - /** - * @fn writeLeds - * @brief set all 8 leds ON or OFF - * @param val 8bits - */ - void writeLeds(uint8_t val); - - /** - * @fn displayVal - * @brief put value on 7 segment display - * @param digitId num of digit(0-7) - * @param val value(0->F) - */ - void displayVal(uint8_t digitId, uint8_t val); - + /** * @fn displayDig