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