From ff7260b9bc7258a35df8b0ea4ed8f03a554f80cb Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Wed, 11 Jan 2023 17:36:11 +0000 Subject: [PATCH 01/27] Added code for FastClock Added code for both I2C fastclock and serial clocks --- CommandDistributor.cpp | 11 ++++ DCCEXParser.cpp | 22 ++++++- EXRAIL2.cpp | 12 +++- EXRAIL2.h | 4 ++ EXRAIL2MacroReset.h | 4 ++ EXRAILMacros.h | 10 +++ IO_EXFastclock.h | 134 +++++++++++++++++++++++++++++++++++++++++ myHal.cpp_example.txt | 15 ++++- 8 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 IO_EXFastclock.h diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index 9f2baa3..961df38 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -155,6 +155,17 @@ void CommandDistributor::broadcastTurnout(int16_t id, bool isClosed ) { #endif } +void CommandDistributor::broadcastClockTime(int16_t time, int8_t rate) { + // The JMRI clock command is of the form : PFT65871<;>4 + // The CS broadcast is of the form "\n"),time, rate); +#ifdef CD_HANDLE_RING + broadcastReply(WITHROTTLE_TYPE, F("PFT%d<;>%d\n"), time*60, rate); +#endif +} + void CommandDistributor::broadcastLoco(byte slot) { DCC::LOCO * sp=&DCC::speedTable[slot]; broadcastReply(COMMAND_TYPE, F("\n"), sp->loco,slot,sp->speedCode,sp->functions); diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index cbb152e..486ef32 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -97,6 +97,8 @@ Print *DCCEXParser::stashStream = NULL; RingStream *DCCEXParser::stashRingStream = NULL; byte DCCEXParser::stashTarget=0; +int16_t lastclocktime = 0; + // This is a JMRI command parser. // It doesnt know how the string got here, nor how it gets back. // It knows nothing about hardware or tracks... it just parses strings and @@ -570,9 +572,27 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) case 'J' : // throttle info access { - if ((params<1) | (params>2)) break; // + if ((params<1) | (params>3)) break; // int16_t id=(params==2)?p[1]:0; switch(p[0]) { + case HASH_KEYWORD_C: // sets time and speed + if (params==1) { // returns latest time + StringFormatter::send(stream, F("\n"), lastclocktime); + return; + } + if (p[1] != lastclocktime){ + if (Diag::CMD) { + DIAG(F("Clock Command Received")); + DIAG(F("Received Clock Time is: %d at rate: %d"), p[1], p[2]); + } + LCD(6,F("Clk Time:%d Sp %d"), p[1], p[2]); + //LCD(7,F("Clock Speed: %d"), p[2]); + RMFT2::clockEvent(p[1],1); + // Now tell everyone else what the time is. + CommandDistributor::broadcastClockTime(p[1], p[2]); + lastclocktime = p[1]; + } + return; case HASH_KEYWORD_A: // returns automations/routes StringFormatter::send(stream, F(" diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index f44f9dc..f969544 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -92,6 +92,7 @@ LookList * RMFT2::onRedLookup=NULL; LookList * RMFT2::onAmberLookup=NULL; LookList * RMFT2::onGreenLookup=NULL; LookList * RMFT2::onChangeLookup=NULL; +LookList * RMFT2::onClockLookup=NULL; #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define SKIPOP progCounter+=3 @@ -175,6 +176,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { onAmberLookup=LookListLoader(OPCODE_ONAMBER); onGreenLookup=LookListLoader(OPCODE_ONGREEN); onChangeLookup=LookListLoader(OPCODE_ONCHANGE); + onClockLookup=LookListLoader(OPCODE_ONTIME); // Second pass startup, define any turnouts or servos, set signals red // add sequences onRoutines to the lookups @@ -975,6 +977,7 @@ void RMFT2::loop2() { case OPCODE_ONAMBER: case OPCODE_ONGREEN: case OPCODE_ONCHANGE: + case OPCODE_ONTIME: break; @@ -1106,7 +1109,14 @@ void RMFT2::changeEvent(int16_t vpin, bool change) { // Hunt for an ONCHANGE for this sensor if (change) handleEvent(F("CHANGE"),onChangeLookup,vpin); } - + +void RMFT2::clockEvent(int16_t clocktime, bool change) { + // Hunt for an ONTIME for this time + if (Diag::CMD) + DIAG(F("Looking for clock event at : %d"), clocktime); + if (change) handleEvent(F("CHANGE"),onClockLookup,clocktime); +} + void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) { int pc= handlers->find(id); if (pc<0) return; diff --git a/EXRAIL2.h b/EXRAIL2.h index 2ea2ba1..69fd382 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -55,6 +55,8 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_SET_TRACK, OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN, OPCODE_ONCHANGE, + OPCODE_ONCLOCKTIME, + OPCODE_ONTIME, // OPcodes below this point are skip-nesting IF operations // placed here so that they may be skipped as a group @@ -116,6 +118,7 @@ class LookList { static void turnoutEvent(int16_t id, bool closed); static void activateEvent(int16_t addr, bool active); static void changeEvent(int16_t id, bool change); + static void clockEvent(int16_t clocktime, bool change); static const int16_t SERVO_SIGNAL_FLAG=0x4000; static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000; static const int16_t DCC_SIGNAL_FLAG=0x1000; @@ -173,6 +176,7 @@ private: static LookList * onAmberLookup; static LookList * onGreenLookup; static LookList * onChangeLookup; + static LookList * onClockLookup; // Local variables - exist for each instance/task RMFT2 *next; // loop chain diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index 32e28a2..a5e6d90 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -86,6 +86,8 @@ #undef ONDEACTIVATE #undef ONDEACTIVATEL #undef ONCLOSE +#undef ONTIME +#undef ONCLOCKTIME #undef ONGREEN #undef ONRED #undef ONTHROW @@ -198,6 +200,8 @@ #define ONACTIVATE(addr,subaddr) #define ONACTIVATEL(linear) #define ONAMBER(signal_id) +#define ONTIME(value) +#define ONCLOCKTIME(hours,mins) #define ONDEACTIVATE(addr,subaddr) #define ONDEACTIVATEL(linear) #define ONCLOSE(turnout_id) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index b5e78d9..7ef3acd 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -55,6 +55,14 @@ // helper macro for turnout description as HIDDEN #define HIDDEN "\x01" +// helper macro to strip leading zeros off time inputs +// (10#mins)%100) +#define STRIP_ZERO(value) 10##value%100 + +// helper macro to strip leading zeros off time inputs +// (10#mins)%100) +#define STRIP_ZERO(value) 10##value%100 + // Pass 1 Implements aliases #include "EXRAIL2MacroReset.h" #undef ALIAS @@ -297,6 +305,8 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3), #define ONAMBER(signal_id) OPCODE_ONAMBER,V(signal_id), #define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id), +#define ONTIME(value) OPCODE_ONTIME,V(value), +#define ONCLOCKTIME(hours,mins) OPCODE_ONTIME,V((STRIP_ZERO(hours)*60)+STRIP_ZERO(mins)), #define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr), #define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3), #define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id), diff --git a/IO_EXFastclock.h b/IO_EXFastclock.h new file mode 100644 index 0000000..c9985f2 --- /dev/null +++ b/IO_EXFastclock.h @@ -0,0 +1,134 @@ +/* + * © 2022, Colin Murdoch. All rights reserved. + * + * This file is part of CommandStation-EX + * + * 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 . +*/ + +/* +* The IO_EXFastclock device driver is used to interface the standalone fast clock and receive time data. +* +* The EX-fastClock code lives in a separate repo (https://github.com/DCC-EX/EX-Fastclock) and contains the clock logic. +* +* +*/ + +#ifndef IO_EXFastclock_h + #define IO_EXFastclock_h +#endif + +#include "IODevice.h" +#include "I2CManager.h" +#include "DIAG.h" +#include "EXRAIL2.h" +#include "CommandDistributor.h" + +bool FAST_CLOCK_EXISTS = true; + +class EXFastClock : public IODevice { +public: + // Constructor + EXFastClock(uint8_t I2CAddress){ + _I2CAddress = I2CAddress; + addDevice(this); + } + +static void EXFastClock::create(uint8_t _I2CAddress) { + + DIAG(F("Checking for Clock")); + // Start by assuming we will find the clock + // Check if specified I2C address is responding (blocking operation) + // Returns I2C_STATUS_OK (0) if OK, or error code. + uint8_t _checkforclock = I2CManager.checkAddress(_I2CAddress); + DIAG(F("Clock check result - %d"), _checkforclock); + if (_checkforclock == 0) { + FAST_CLOCK_EXISTS = true; + DIAG(F("I2C Fast Clock found at x%x"), _I2CAddress); + new EXFastClock(_I2CAddress); + } + else { + FAST_CLOCK_EXISTS = false; + DIAG(F("No Fast Clock found")); + LCD(6,F("CLOCK NOT FOUND")); + } + + } + +private: + //uint8_t _I2CAddress; + uint16_t _clocktime; + uint8_t _clockrate; + uint16_t _previousclocktime; + unsigned long _lastchecktime; + +// Initialisation of Fastclock +void _begin() override { + + if (FAST_CLOCK_EXISTS == true) { + I2CManager.begin(); + if (I2CManager.exists(_I2CAddress)) { + _deviceState = DEVSTATE_NORMAL; + #ifdef DIAG_IO + _display(); + #endif + } else { + _deviceState = DEVSTATE_FAILED; + LCD(6,F("CLOCK NOT FOUND")); + DIAG(F("Fast Clock Not Found at address %d"), _I2CAddress); + } + } +} + +// Processing loop to obtain clock time + +void _loop(unsigned long currentMicros) override{ + + if (FAST_CLOCK_EXISTS==true) { + uint8_t readBuffer[3]; + byte a,b; + #if defined(EXRAIL_ACTIVE) + I2CManager.read(_I2CAddress, readBuffer, 3); + a = readBuffer[0]; + b = readBuffer[1]; + _clocktime = (a << 8) + b; + _clockrate = readBuffer[2]; + + if (_clocktime != _previousclocktime) { + _previousclocktime = _clocktime; + if (Diag::CMD) + DIAG(F("Received Clock Time is: %d at rate: %d"), _clocktime, _clockrate); + LCD(6,F(("Clk Time:%d Sp %d")), _clocktime, _clockrate); + RMFT2::clockEvent(_clocktime,1); + // Now tell everyone else what the time is. + CommandDistributor::broadcastClockTime(_clocktime, _clockrate); + + // As the maximum clock increment is 2 seconds delay a bit - say 1 sec. + delayUntil(currentMicros + 1000000); // Wait 1000ms before checking again, + + } + _lastchecktime = currentMicros; + + #endif + + + } + +} + +// Display EX-FastClock device driver info. +void _display() { + DIAG(F("FastCLock on I2C:x%x - %S"), _I2CAddress, (_deviceState==DEVSTATE_FAILED) ? F("OFFLINE") : F("")); +} +}; diff --git a/myHal.cpp_example.txt b/myHal.cpp_example.txt index 5470f76..64adac1 100644 --- a/myHal.cpp_example.txt +++ b/myHal.cpp_example.txt @@ -21,7 +21,7 @@ #include "IO_VL53L0X.h" // Laser time-of-flight sensor #include "IO_DFPlayer.h" // MP3 sound player //#include "IO_EXTurntable.h" // Turntable-EX turntable controller - +//#include "IO_EXFastClock.h" // FastClock driver //========================================================================== // The function halSetup() is invoked from CS if it exists within the build. @@ -206,6 +206,19 @@ void halSetup() { //RotaryEncoder::create(700, 1, 0x70); //RotaryEncoder::create(701, 2, 0x71); + //======================================================================= + // The following directive defines an EX-FastClock instance. + //======================================================================= + // EXFastCLock::create(I2C Address) + // + // The parameters are: + // + // I2C address=0x55 (decimal 85) + // + // Note that the I2C address is defined in the EX-FastClock code, and 0x55 is the default. + + + // EXFastClock::create(0x55); } From 873d470f867f81a25cc9e85c6b5545beecaceeb5 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Wed, 11 Jan 2023 19:50:39 +0000 Subject: [PATCH 02/27] Supply missing function Supply missing function --- CommandDistributor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/CommandDistributor.h b/CommandDistributor.h index 633ff77..c816b94 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -45,6 +45,7 @@ public : static void broadcastLoco(byte slot); static void broadcastSensor(int16_t id, bool value); static void broadcastTurnout(int16_t id, bool isClosed); + static void broadcastClockTime(int16_t time, int8_t rate); static void broadcastPower(); static void broadcastText(const FSH * msg); template static void broadcastReply(clientType type, Targs... msg); From 8fac20a4518515a37c55d0d9542422445a2a9568 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Mon, 16 Jan 2023 18:16:25 +0000 Subject: [PATCH 03/27] Add #ifdef selections Add #ifdef selections linked to #define in config.exampe.h --- CommandDistributor.cpp | 2 ++ CommandDistributor.h | 2 ++ DCCEXParser.cpp | 9 +++++++++ EXRAIL2.cpp | 10 +++++++++- EXRAIL2.h | 6 ++++++ EXRAIL2MacroReset.h | 4 ++++ EXRAILMacros.h | 8 ++++---- IO_EXFastclock.h | 16 +++++++++------- config.example.h | 4 ++++ 9 files changed, 49 insertions(+), 12 deletions(-) diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index 961df38..3fe1e96 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -155,6 +155,7 @@ void CommandDistributor::broadcastTurnout(int16_t id, bool isClosed ) { #endif } +#ifdef USEFASTCLOCK void CommandDistributor::broadcastClockTime(int16_t time, int8_t rate) { // The JMRI clock command is of the form : PFT65871<;>4 // The CS broadcast is of the form "%d\n"), time*60, rate); #endif } +#endif void CommandDistributor::broadcastLoco(byte slot) { DCC::LOCO * sp=&DCC::speedTable[slot]; diff --git a/CommandDistributor.h b/CommandDistributor.h index c816b94..d51b2b6 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -45,7 +45,9 @@ public : static void broadcastLoco(byte slot); static void broadcastSensor(int16_t id, bool value); static void broadcastTurnout(int16_t id, bool isClosed); +#ifdef USEFASTCLOCK static void broadcastClockTime(int16_t time, int8_t rate); +#ifdef static void broadcastPower(); static void broadcastText(const FSH * msg); template static void broadcastReply(clientType type, Targs... msg); diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 486ef32..3898f95 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -97,7 +97,9 @@ Print *DCCEXParser::stashStream = NULL; RingStream *DCCEXParser::stashRingStream = NULL; byte DCCEXParser::stashTarget=0; +#ifdef USEFASTCLOCK int16_t lastclocktime = 0; +#endif // This is a JMRI command parser. // It doesnt know how the string got here, nor how it gets back. @@ -572,9 +574,15 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) case 'J' : // throttle info access { +#ifdef USEFASTCLOCK if ((params<1) | (params>3)) break; // +#endif +#ifndef USEFASTCLOCK + if ((params<1) | (params>2)) break; // +#endif int16_t id=(params==2)?p[1]:0; switch(p[0]) { +#ifdef USEFASTCLOCK case HASH_KEYWORD_C: // sets time and speed if (params==1) { // returns latest time StringFormatter::send(stream, F("\n"), lastclocktime); @@ -593,6 +601,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) lastclocktime = p[1]; } return; +#endif case HASH_KEYWORD_A: // returns automations/routes StringFormatter::send(stream, F(" diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index f969544..1b5b51e 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -92,7 +92,9 @@ LookList * RMFT2::onRedLookup=NULL; LookList * RMFT2::onAmberLookup=NULL; LookList * RMFT2::onGreenLookup=NULL; LookList * RMFT2::onChangeLookup=NULL; +#ifdef USEFASTCLOCK LookList * RMFT2::onClockLookup=NULL; +#endif #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define SKIPOP progCounter+=3 @@ -176,7 +178,9 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { onAmberLookup=LookListLoader(OPCODE_ONAMBER); onGreenLookup=LookListLoader(OPCODE_ONGREEN); onChangeLookup=LookListLoader(OPCODE_ONCHANGE); + #ifdef USEFASTCLOCK onClockLookup=LookListLoader(OPCODE_ONTIME); + #endif // Second pass startup, define any turnouts or servos, set signals red // add sequences onRoutines to the lookups @@ -977,7 +981,9 @@ void RMFT2::loop2() { case OPCODE_ONAMBER: case OPCODE_ONGREEN: case OPCODE_ONCHANGE: + #ifdef USEFASTCLOCK case OPCODE_ONTIME: + #endif break; @@ -1110,12 +1116,14 @@ void RMFT2::changeEvent(int16_t vpin, bool change) { if (change) handleEvent(F("CHANGE"),onChangeLookup,vpin); } +#ifdef USEFASTCLOCK void RMFT2::clockEvent(int16_t clocktime, bool change) { // Hunt for an ONTIME for this time if (Diag::CMD) DIAG(F("Looking for clock event at : %d"), clocktime); - if (change) handleEvent(F("CHANGE"),onClockLookup,clocktime); + if (change) handleEvent(F("CLOCK"),onClockLookup,clocktime); } +#endif void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) { int pc= handlers->find(id); diff --git a/EXRAIL2.h b/EXRAIL2.h index 69fd382..7f04458 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -55,8 +55,10 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_SET_TRACK, OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN, OPCODE_ONCHANGE, +#ifdef USEFASTCLOCK OPCODE_ONCLOCKTIME, OPCODE_ONTIME, +#endif // OPcodes below this point are skip-nesting IF operations // placed here so that they may be skipped as a group @@ -118,7 +120,9 @@ class LookList { static void turnoutEvent(int16_t id, bool closed); static void activateEvent(int16_t addr, bool active); static void changeEvent(int16_t id, bool change); + #ifdef USEFASTCLOCK static void clockEvent(int16_t clocktime, bool change); + #endif static const int16_t SERVO_SIGNAL_FLAG=0x4000; static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000; static const int16_t DCC_SIGNAL_FLAG=0x1000; @@ -176,7 +180,9 @@ private: static LookList * onAmberLookup; static LookList * onGreenLookup; static LookList * onChangeLookup; +#ifdef USEFASTCLOCK static LookList * onClockLookup; +#endif // Local variables - exist for each instance/task RMFT2 *next; // loop chain diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index a5e6d90..409cdcd 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -86,8 +86,10 @@ #undef ONDEACTIVATE #undef ONDEACTIVATEL #undef ONCLOSE +#ifdef USEFASTCLOCK #undef ONTIME #undef ONCLOCKTIME +#endif #undef ONGREEN #undef ONRED #undef ONTHROW @@ -200,8 +202,10 @@ #define ONACTIVATE(addr,subaddr) #define ONACTIVATEL(linear) #define ONAMBER(signal_id) +#ifdef USEFASTCLOCK #define ONTIME(value) #define ONCLOCKTIME(hours,mins) +#endif #define ONDEACTIVATE(addr,subaddr) #define ONDEACTIVATEL(linear) #define ONCLOSE(turnout_id) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 7ef3acd..0d807d1 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -55,13 +55,11 @@ // helper macro for turnout description as HIDDEN #define HIDDEN "\x01" +#ifdef USEFASTCLOCK // helper macro to strip leading zeros off time inputs // (10#mins)%100) #define STRIP_ZERO(value) 10##value%100 - -// helper macro to strip leading zeros off time inputs -// (10#mins)%100) -#define STRIP_ZERO(value) 10##value%100 +#endif // Pass 1 Implements aliases #include "EXRAIL2MacroReset.h" @@ -305,8 +303,10 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3), #define ONAMBER(signal_id) OPCODE_ONAMBER,V(signal_id), #define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id), +#ifdef USEFASTCLOCK #define ONTIME(value) OPCODE_ONTIME,V(value), #define ONCLOCKTIME(hours,mins) OPCODE_ONTIME,V((STRIP_ZERO(hours)*60)+STRIP_ZERO(mins)), +#endif #define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr), #define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3), #define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id), diff --git a/IO_EXFastclock.h b/IO_EXFastclock.h index c9985f2..22bb94e 100644 --- a/IO_EXFastclock.h +++ b/IO_EXFastclock.h @@ -26,8 +26,8 @@ */ #ifndef IO_EXFastclock_h - #define IO_EXFastclock_h -#endif +#define IO_EXFastclock_h + #include "IODevice.h" #include "I2CManager.h" @@ -55,12 +55,12 @@ static void EXFastClock::create(uint8_t _I2CAddress) { DIAG(F("Clock check result - %d"), _checkforclock); if (_checkforclock == 0) { FAST_CLOCK_EXISTS = true; - DIAG(F("I2C Fast Clock found at x%x"), _I2CAddress); + //DIAG(F("I2C Fast Clock found at x%x"), _I2CAddress); new EXFastClock(_I2CAddress); } else { FAST_CLOCK_EXISTS = false; - DIAG(F("No Fast Clock found")); + //DIAG(F("No Fast Clock found")); LCD(6,F("CLOCK NOT FOUND")); } @@ -85,7 +85,7 @@ void _begin() override { #endif } else { _deviceState = DEVSTATE_FAILED; - LCD(6,F("CLOCK NOT FOUND")); + //LCD(6,F("CLOCK NOT FOUND")); DIAG(F("Fast Clock Not Found at address %d"), _I2CAddress); } } @@ -107,8 +107,8 @@ void _loop(unsigned long currentMicros) override{ if (_clocktime != _previousclocktime) { _previousclocktime = _clocktime; - if (Diag::CMD) - DIAG(F("Received Clock Time is: %d at rate: %d"), _clocktime, _clockrate); + //if (Diag::CMD) + // DIAG(F("Received Clock Time is: %d at rate: %d"), _clocktime, _clockrate); LCD(6,F(("Clk Time:%d Sp %d")), _clocktime, _clockrate); RMFT2::clockEvent(_clocktime,1); // Now tell everyone else what the time is. @@ -132,3 +132,5 @@ void _display() { DIAG(F("FastCLock on I2C:x%x - %S"), _I2CAddress, (_deviceState==DEVSTATE_FAILED) ? F("OFFLINE") : F("")); } }; + +#endif diff --git a/config.example.h b/config.example.h index aae18a9..a2d97c5 100644 --- a/config.example.h +++ b/config.example.h @@ -224,4 +224,8 @@ The configuration file for DCC-EX Command Station // //#define SERIAL_BT_COMMANDS + +// FastClock Enabler +// To build the FastClock code into the CS please uncomment the line below +//#define USEFASTCLOCK ///////////////////////////////////////////////////////////////////////////////////// From b62c4da04da63b25b561abfe94756cd51d6977e7 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Tue, 17 Jan 2023 10:56:12 +0000 Subject: [PATCH 04/27] Update CommandDistributor.h Fixed #endif typo. --- CommandDistributor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommandDistributor.h b/CommandDistributor.h index d51b2b6..3df477c 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -47,7 +47,7 @@ public : static void broadcastTurnout(int16_t id, bool isClosed); #ifdef USEFASTCLOCK static void broadcastClockTime(int16_t time, int8_t rate); -#ifdef +#endif static void broadcastPower(); static void broadcastText(const FSH * msg); template static void broadcastReply(clientType type, Targs... msg); From fb36bd138066ffafc75c0af01a160db19fbe6162 Mon Sep 17 00:00:00 2001 From: pmantoine Date: Tue, 17 Jan 2023 20:15:30 +0800 Subject: [PATCH 05/27] Fix F446 Serial Pin Comment (Rx/Tx) --- DCCTimerSTM32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DCCTimerSTM32.cpp b/DCCTimerSTM32.cpp index 0976bcd..0f60507 100644 --- a/DCCTimerSTM32.cpp +++ b/DCCTimerSTM32.cpp @@ -39,7 +39,7 @@ HardwareSerial Serial1(PB7, PA15); // Rx=PB7, Tx=PA15 -- CN7 pins 17 and 21 - F HardwareSerial Serial6(PA12, PA11); // Rx=PA12, Tx=PA11 -- CN10 pins 12 and 14 - F411RE #elif defined(ARDUINO_NUCLEO_F446RE) // Nucleo-64 boards don't have Serial1 defined by default -HardwareSerial Serial1(PA10, PB6); // Rx=PA10, Tx=PB6 -- CN10 pins 17 and 33 - F446RE +HardwareSerial Serial1(PA10, PB6); // Rx=PA10, Tx=PB6 -- CN10 pins 33 and 17 - F446RE // Serial2 is defined to use USART2 by default, but is in fact used as the diag console // via the debugger on the Nucleo-64. It is therefore unavailable for other DCC-EX uses like WiFi, DFPlayer, etc. #elif defined(ARDUINO_NUCLEO_F412ZG) || defined(ARDUINO_NUCLEO_F429ZI) || defined(ARDUINO_NUCLEO_F446ZE) From cd46d3c9e07a4641843a154046cc7482504932fe Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Sat, 21 Jan 2023 10:18:54 +0000 Subject: [PATCH 06/27] Remove #ifdef and merge calcs Remove #idfef statements and merge duplicate routines into CommandDistributor --- CommandDistributor.cpp | 40 +++++++++++++++++++++++++++++++-- CommandDistributor.h | 6 +++-- DCCEXParser.cpp | 29 +++++------------------- EXRAIL2.cpp | 9 +------- EXRAIL2.h | 6 ----- EXRAIL2MacroReset.h | 4 ---- EXRAILMacros.h | 4 ---- IO_EXFastclock.h | 50 ++++++++++++++++++------------------------ 8 files changed, 69 insertions(+), 79 deletions(-) diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index 3fe1e96..652d852 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -29,6 +29,11 @@ #include "DCCWaveform.h" #include "DCC.h" #include "TrackManager.h" +#include "StringFormatter.h" + +// variables to hold clock time +int16_t lastclocktime; +int8_t lastclockrate; #if WIFI_ON || ETHERNET_ON || defined(SERIAL1_COMMANDS) || defined(SERIAL2_COMMANDS) || defined(SERIAL3_COMMANDS) @@ -155,7 +160,6 @@ void CommandDistributor::broadcastTurnout(int16_t id, bool isClosed ) { #endif } -#ifdef USEFASTCLOCK void CommandDistributor::broadcastClockTime(int16_t time, int8_t rate) { // The JMRI clock command is of the form : PFT65871<;>4 // The CS broadcast is of the form "%d\n"), time*60, rate); #endif } -#endif + +void CommandDistributor::setClockTime(int16_t clocktime, int8_t clockrate, byte opt) { + // opt - case 1 save the latest time if changed + // case 2 broadcast the time when requested + // case 3 display latest time + switch (opt) + { + case 1: + if (clocktime != lastclocktime){ + if (Diag::CMD) { + DIAG(F("Clock Command Received")); + DIAG(F("Received Clock Time is: %d at rate: %d"), clocktime, clockrate); + } + LCD(6,F("Clk Time:%d Sp %d"), clocktime, clockrate); + // look for an event for this time + RMFT2::clockEvent(clocktime,1); + // Now tell everyone else what the time is. + CommandDistributor::broadcastClockTime(clocktime, clockrate); + lastclocktime = clocktime; + lastclockrate = clockrate; + } + return; + + case 2: + CommandDistributor::broadcastClockTime(lastclocktime, lastclockrate); + return; + } + +} + +int16_t CommandDistributor::retClockTime() { + return lastclocktime; +} void CommandDistributor::broadcastLoco(byte slot) { DCC::LOCO * sp=&DCC::speedTable[slot]; diff --git a/CommandDistributor.h b/CommandDistributor.h index 3df477c..bbbc44c 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -25,6 +25,7 @@ #include "RingStream.h" #include "StringBuffer.h" #include "defines.h" +#include "EXRAIL2.h" #if WIFI_ON | ETHERNET_ON // Command Distributor must handle a RingStream of clients @@ -45,13 +46,14 @@ public : static void broadcastLoco(byte slot); static void broadcastSensor(int16_t id, bool value); static void broadcastTurnout(int16_t id, bool isClosed); -#ifdef USEFASTCLOCK static void broadcastClockTime(int16_t time, int8_t rate); -#endif + static void setClockTime(int16_t time, int8_t rate, byte opt); + static int16_t retClockTime(); static void broadcastPower(); static void broadcastText(const FSH * msg); template static void broadcastReply(clientType type, Targs... msg); static void forget(byte clientId); + }; #endif diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 3898f95..5c0cb84 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -97,10 +97,6 @@ Print *DCCEXParser::stashStream = NULL; RingStream *DCCEXParser::stashRingStream = NULL; byte DCCEXParser::stashTarget=0; -#ifdef USEFASTCLOCK -int16_t lastclocktime = 0; -#endif - // This is a JMRI command parser. // It doesnt know how the string got here, nor how it gets back. // It knows nothing about hardware or tracks... it just parses strings and @@ -574,34 +570,19 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) case 'J' : // throttle info access { -#ifdef USEFASTCLOCK if ((params<1) | (params>3)) break; // -#endif -#ifndef USEFASTCLOCK - if ((params<1) | (params>2)) break; // -#endif + //if ((params<1) | (params>2)) break; // int16_t id=(params==2)?p[1]:0; switch(p[0]) { -#ifdef USEFASTCLOCK case HASH_KEYWORD_C: // sets time and speed if (params==1) { // returns latest time - StringFormatter::send(stream, F("\n"), lastclocktime); + int16_t x = CommandDistributor::retClockTime(); + StringFormatter::send(stream, F("\n"), x); return; } - if (p[1] != lastclocktime){ - if (Diag::CMD) { - DIAG(F("Clock Command Received")); - DIAG(F("Received Clock Time is: %d at rate: %d"), p[1], p[2]); - } - LCD(6,F("Clk Time:%d Sp %d"), p[1], p[2]); - //LCD(7,F("Clock Speed: %d"), p[2]); - RMFT2::clockEvent(p[1],1); - // Now tell everyone else what the time is. - CommandDistributor::broadcastClockTime(p[1], p[2]); - lastclocktime = p[1]; - } + CommandDistributor::setClockTime(p[1], p[2], 1); return; -#endif + case HASH_KEYWORD_A: // returns automations/routes StringFormatter::send(stream, F(" diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 1b5b51e..75ec63b 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -92,9 +92,7 @@ LookList * RMFT2::onRedLookup=NULL; LookList * RMFT2::onAmberLookup=NULL; LookList * RMFT2::onGreenLookup=NULL; LookList * RMFT2::onChangeLookup=NULL; -#ifdef USEFASTCLOCK LookList * RMFT2::onClockLookup=NULL; -#endif #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define SKIPOP progCounter+=3 @@ -178,9 +176,8 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { onAmberLookup=LookListLoader(OPCODE_ONAMBER); onGreenLookup=LookListLoader(OPCODE_ONGREEN); onChangeLookup=LookListLoader(OPCODE_ONCHANGE); - #ifdef USEFASTCLOCK onClockLookup=LookListLoader(OPCODE_ONTIME); - #endif + // Second pass startup, define any turnouts or servos, set signals red // add sequences onRoutines to the lookups @@ -981,9 +978,7 @@ void RMFT2::loop2() { case OPCODE_ONAMBER: case OPCODE_ONGREEN: case OPCODE_ONCHANGE: - #ifdef USEFASTCLOCK case OPCODE_ONTIME: - #endif break; @@ -1116,14 +1111,12 @@ void RMFT2::changeEvent(int16_t vpin, bool change) { if (change) handleEvent(F("CHANGE"),onChangeLookup,vpin); } -#ifdef USEFASTCLOCK void RMFT2::clockEvent(int16_t clocktime, bool change) { // Hunt for an ONTIME for this time if (Diag::CMD) DIAG(F("Looking for clock event at : %d"), clocktime); if (change) handleEvent(F("CLOCK"),onClockLookup,clocktime); } -#endif void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) { int pc= handlers->find(id); diff --git a/EXRAIL2.h b/EXRAIL2.h index 7f04458..69fd382 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -55,10 +55,8 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_SET_TRACK, OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN, OPCODE_ONCHANGE, -#ifdef USEFASTCLOCK OPCODE_ONCLOCKTIME, OPCODE_ONTIME, -#endif // OPcodes below this point are skip-nesting IF operations // placed here so that they may be skipped as a group @@ -120,9 +118,7 @@ class LookList { static void turnoutEvent(int16_t id, bool closed); static void activateEvent(int16_t addr, bool active); static void changeEvent(int16_t id, bool change); - #ifdef USEFASTCLOCK static void clockEvent(int16_t clocktime, bool change); - #endif static const int16_t SERVO_SIGNAL_FLAG=0x4000; static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000; static const int16_t DCC_SIGNAL_FLAG=0x1000; @@ -180,9 +176,7 @@ private: static LookList * onAmberLookup; static LookList * onGreenLookup; static LookList * onChangeLookup; -#ifdef USEFASTCLOCK static LookList * onClockLookup; -#endif // Local variables - exist for each instance/task RMFT2 *next; // loop chain diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index 409cdcd..a5e6d90 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -86,10 +86,8 @@ #undef ONDEACTIVATE #undef ONDEACTIVATEL #undef ONCLOSE -#ifdef USEFASTCLOCK #undef ONTIME #undef ONCLOCKTIME -#endif #undef ONGREEN #undef ONRED #undef ONTHROW @@ -202,10 +200,8 @@ #define ONACTIVATE(addr,subaddr) #define ONACTIVATEL(linear) #define ONAMBER(signal_id) -#ifdef USEFASTCLOCK #define ONTIME(value) #define ONCLOCKTIME(hours,mins) -#endif #define ONDEACTIVATE(addr,subaddr) #define ONDEACTIVATEL(linear) #define ONCLOSE(turnout_id) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 0d807d1..2ffbc75 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -55,11 +55,9 @@ // helper macro for turnout description as HIDDEN #define HIDDEN "\x01" -#ifdef USEFASTCLOCK // helper macro to strip leading zeros off time inputs // (10#mins)%100) #define STRIP_ZERO(value) 10##value%100 -#endif // Pass 1 Implements aliases #include "EXRAIL2MacroReset.h" @@ -303,10 +301,8 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3), #define ONAMBER(signal_id) OPCODE_ONAMBER,V(signal_id), #define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id), -#ifdef USEFASTCLOCK #define ONTIME(value) OPCODE_ONTIME,V(value), #define ONCLOCKTIME(hours,mins) OPCODE_ONTIME,V((STRIP_ZERO(hours)*60)+STRIP_ZERO(mins)), -#endif #define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr), #define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3), #define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id), diff --git a/IO_EXFastclock.h b/IO_EXFastclock.h index 22bb94e..0e1bf76 100644 --- a/IO_EXFastclock.h +++ b/IO_EXFastclock.h @@ -45,7 +45,7 @@ public: addDevice(this); } -static void EXFastClock::create(uint8_t _I2CAddress) { +static void create(uint8_t _I2CAddress) { DIAG(F("Checking for Clock")); // Start by assuming we will find the clock @@ -53,6 +53,7 @@ static void EXFastClock::create(uint8_t _I2CAddress) { // Returns I2C_STATUS_OK (0) if OK, or error code. uint8_t _checkforclock = I2CManager.checkAddress(_I2CAddress); DIAG(F("Clock check result - %d"), _checkforclock); + // XXXX change thistosave2 bytes if (_checkforclock == 0) { FAST_CLOCK_EXISTS = true; //DIAG(F("I2C Fast Clock found at x%x"), _I2CAddress); @@ -67,11 +68,8 @@ static void EXFastClock::create(uint8_t _I2CAddress) { } private: - //uint8_t _I2CAddress; - uint16_t _clocktime; - uint8_t _clockrate; - uint16_t _previousclocktime; - unsigned long _lastchecktime; +uint8_t _I2CAddress; + // Initialisation of Fastclock void _begin() override { @@ -98,39 +96,33 @@ void _loop(unsigned long currentMicros) override{ if (FAST_CLOCK_EXISTS==true) { uint8_t readBuffer[3]; byte a,b; - #if defined(EXRAIL_ACTIVE) + #ifdef EXRAIL_ACTIVE I2CManager.read(_I2CAddress, readBuffer, 3); + // XXXX change this to save a few bytes a = readBuffer[0]; b = readBuffer[1]; - _clocktime = (a << 8) + b; - _clockrate = readBuffer[2]; + //_clocktime = (a << 8) + b; + //_clockrate = readBuffer[2]; - if (_clocktime != _previousclocktime) { - _previousclocktime = _clocktime; - //if (Diag::CMD) - // DIAG(F("Received Clock Time is: %d at rate: %d"), _clocktime, _clockrate); - LCD(6,F(("Clk Time:%d Sp %d")), _clocktime, _clockrate); - RMFT2::clockEvent(_clocktime,1); - // Now tell everyone else what the time is. - CommandDistributor::broadcastClockTime(_clocktime, _clockrate); - - // As the maximum clock increment is 2 seconds delay a bit - say 1 sec. - delayUntil(currentMicros + 1000000); // Wait 1000ms before checking again, + CommandDistributor::setClockTime(((a << 8) + b), readBuffer[2], 1); + //setClockTime(int16_t clocktime, int8_t clockrate, byte opt); + + // As the minimum clock increment is 2 seconds delay a bit - say 1 sec. + // Clock interval is 60/ clockspeed i.e 60/b seconds + delayUntil(currentMicros + ((60/b) * 1000000)); } - _lastchecktime = currentMicros; - + #endif - } - -} -// Display EX-FastClock device driver info. -void _display() { - DIAG(F("FastCLock on I2C:x%x - %S"), _I2CAddress, (_deviceState==DEVSTATE_FAILED) ? F("OFFLINE") : F("")); -} + + // Display EX-FastClock device driver info. + void _display() { + DIAG(F("FastCLock on I2C:x%x - %S"), _I2CAddress, (_deviceState==DEVSTATE_FAILED) ? F("OFFLINE") : F("")); + } + }; #endif From 286bdc3c4d817ed0a75c8021955b804ca15aa44b Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Sat, 21 Jan 2023 10:20:49 +0000 Subject: [PATCH 07/27] Create platformio.ini.original --- platformio.ini.original | 223 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 platformio.ini.original diff --git a/platformio.ini.original b/platformio.ini.original new file mode 100644 index 0000000..82167f2 --- /dev/null +++ b/platformio.ini.original @@ -0,0 +1,223 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = + mega2560 + uno + mega328 + unowifiR2 + nano + samd21-dev-usb + samd21-zero-usb + ESP32 + Nucleo-F411RE + Nucleo-F446RE + Teensy3.2 + Teensy3.5 + Teensy3.6 + Teensy4.0 + Teensy4.1 +src_dir = . +include_dir = . + +[env] +build_flags = -Wall -Wextra + +[env:samd21-dev-usb] +platform = atmelsam +board = sparkfun_samd21_dev_usb +framework = arduino +upload_protocol = sam-ba +lib_deps = ${env.lib_deps} +monitor_speed = 115200 +monitor_echo = yes +build_flags = -std=c++17 + +[env:samd21-zero-usb] +platform = atmelsam +board = zeroUSB +framework = arduino +upload_protocol = sam-ba +lib_deps = ${env.lib_deps} +monitor_speed = 115200 +monitor_echo = yes +build_flags = -std=c++17 + +[env:mega2560-debug] +platform = atmelavr +board = megaatmega2560 +framework = arduino +lib_deps = + ${env.lib_deps} + arduino-libraries/Ethernet + SPI +monitor_speed = 115200 +monitor_echo = yes +build_flags = -DDIAG_IO -DDIAG_LOOPTIMES + +[env:mega2560-no-HAL] +platform = atmelavr +board = megaatmega2560 +framework = arduino +lib_deps = + ${env.lib_deps} + arduino-libraries/Ethernet + SPI +monitor_speed = 115200 +monitor_echo = yes +build_flags = -DIO_NO_HAL + +[env:mega2560-I2C-wire] +platform = atmelavr +board = megaatmega2560 +framework = arduino +lib_deps = + ${env.lib_deps} + arduino-libraries/Ethernet + SPI +monitor_speed = 115200 +monitor_echo = yes +build_flags = -DI2C_USE_WIRE + +[env:mega2560] +platform = atmelavr +board = megaatmega2560 +framework = arduino +lib_deps = + ${env.lib_deps} + arduino-libraries/Ethernet + SPI +monitor_speed = 115200 +monitor_echo = yes +build_flags = -mcall-prologues + +[env:mega328] +platform = atmelavr +board = uno +framework = arduino +lib_deps = + ${env.lib_deps} + arduino-libraries/Ethernet + SPI +monitor_speed = 115200 +monitor_echo = yes + +[env:unowifiR2] +platform = atmelmegaavr +board = uno_wifi_rev2 +framework = arduino +lib_deps = + ${env.lib_deps} + arduino-libraries/Ethernet + SPI +monitor_speed = 115200 +monitor_echo = yes +build_flags = "-DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_UNO_WIFI_DEV_ED -DARDUINO_ARCH_AVR -DESP_CH_UART -DESP_CH_UART_BR=19200" + +[env:nanoevery] +platform = atmelmegaavr +board = nano_every +framework = arduino +lib_deps = + ${env.lib_deps} + arduino-libraries/Ethernet + SPI +monitor_speed = 115200 +monitor_echo = yes +upload_speed = 19200 +build_flags = -DDIAG_IO + +[env:uno] +platform = atmelavr +board = uno +framework = arduino +lib_deps = + ${env.lib_deps} + arduino-libraries/Ethernet + SPI +monitor_speed = 115200 +monitor_echo = yes +build_flags = -mcall-prologues + +[env:nano] +platform = atmelavr +board = nanoatmega328new +board_upload.maximum_size = 32256 +framework = arduino +lib_deps = ${env.lib_deps} +monitor_speed = 115200 +monitor_echo = yes + +[env:ESP32] +platform = espressif32 +board = esp32dev +framework = arduino +lib_deps = ${env.lib_deps} +build_flags = -std=c++17 + +[env:Nucleo-F411RE] +platform = ststm32 +board = nucleo_f411re +framework = arduino +lib_deps = ${env.lib_deps} +build_flags = -std=c++17 -Os -g2 -Wunused-variable +monitor_speed = 115200 +monitor_echo = yes + +[env:Nucleo-F446RE] +platform = ststm32 +board = nucleo_f446re +framework = arduino +lib_deps = ${env.lib_deps} +build_flags = -std=c++17 -Os -g2 -Wunused-variable +monitor_speed = 115200 +monitor_echo = yes + +[env:Teensy3.2] +platform = teensy +board = teensy31 +framework = arduino +build_flags = -std=c++17 -Os -g2 +lib_deps = ${env.lib_deps} +lib_ignore = NativeEthernet + +[env:Teensy3.5] +platform = teensy +board = teensy35 +framework = arduino +build_flags = -std=c++17 -Os -g2 +lib_deps = ${env.lib_deps} +lib_ignore = NativeEthernet + +[env:Teensy3.6] +platform = teensy +board = teensy36 +framework = arduino +build_flags = -std=c++17 -Os -g2 +lib_deps = ${env.lib_deps} +lib_ignore = NativeEthernet + +[env:Teensy4.0] +platform = teensy +board = teensy40 +framework = arduino +build_flags = -std=c++17 -Os -g2 +lib_deps = ${env.lib_deps} +lib_ignore = NativeEthernet + +[env:Teensy4.1] +platform = teensy +board = teensy41 +framework = arduino +build_flags = -std=c++17 -Os -g2 +lib_deps = ${env.lib_deps} +lib_ignore = + From fb9170ab8b80564fba5fd915728dcb1ad7cd8ee4 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 22 Jan 2023 19:25:00 +1000 Subject: [PATCH 08/27] SIGNAL/SIGNALH operating correctly --- EXRAIL2.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index f44f9dc..bf5b61a 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -1076,11 +1076,26 @@ int16_t RMFT2::getSignalSlot(int16_t id) { // Manage invert (HIGH on) pins bool aHigh=sigid & ACTIVE_HIGH_SIGNAL_FLAG; - + // set the three pins - if (redpin) IODevice::write(redpin,(rag==SIGNAL_RED || rag==SIMAMBER)^aHigh); - if (amberpin) IODevice::write(amberpin,(rag==SIGNAL_AMBER)^aHigh); - if (greenpin) IODevice::write(greenpin,(rag==SIGNAL_GREEN || rag==SIMAMBER)^aHigh); + if (redpin) { + bool redval=(rag==SIGNAL_RED || rag==SIMAMBER); + if (!aHigh) redval=!redval; + // IODevice::write(redpin,(rag==SIGNAL_RED || rag==SIMAMBER)^aHigh); + IODevice::write(redpin,redval); + } + if (amberpin) { + // IODevice::write(amberpin,(rag==SIGNAL_AMBER)^aHigh); + bool amberval=(rag==SIGNAL_AMBER); + if (!aHigh) amberval=!amberval; + IODevice::write(amberpin,amberval); + } + if (greenpin) { + // IODevice::write(greenpin,(rag==SIGNAL_GREEN || rag==SIMAMBER)^aHigh); + bool greenval=(rag==SIGNAL_GREEN || rag==SIMAMBER); + if (!aHigh) greenval=!greenval; + IODevice::write(greenpin,greenval); + } } /* static */ bool RMFT2::isSignal(int16_t id,char rag) { From aaf25d542618d348882c3ea241e6968731cf2a2f Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 23 Jan 2023 04:53:39 +1000 Subject: [PATCH 09/27] Remove excess comments --- EXRAIL2.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index bf5b61a..5f2bf8b 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -1081,17 +1081,14 @@ int16_t RMFT2::getSignalSlot(int16_t id) { if (redpin) { bool redval=(rag==SIGNAL_RED || rag==SIMAMBER); if (!aHigh) redval=!redval; - // IODevice::write(redpin,(rag==SIGNAL_RED || rag==SIMAMBER)^aHigh); IODevice::write(redpin,redval); } if (amberpin) { - // IODevice::write(amberpin,(rag==SIGNAL_AMBER)^aHigh); bool amberval=(rag==SIGNAL_AMBER); if (!aHigh) amberval=!amberval; IODevice::write(amberpin,amberval); } if (greenpin) { - // IODevice::write(greenpin,(rag==SIGNAL_GREEN || rag==SIMAMBER)^aHigh); bool greenval=(rag==SIGNAL_GREEN || rag==SIMAMBER); if (!aHigh) greenval=!greenval; IODevice::write(greenpin,greenval); From 7f4e3d9cea3caced0218e4a743a6f4ea8dfbede5 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 23 Jan 2023 11:49:23 +1000 Subject: [PATCH 10/27] Digital inputs optimised --- IO_EXIOExpander.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index 1e20fac..9aa9011 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -66,6 +66,8 @@ private: _i2cAddress = i2cAddress; _numDigitalPins = numDigitalPins; _numAnaloguePins = numAnaloguePins; + _digitalBytes = (numDigitalPins+7)/8; + _digitalPinStates=(byte*) calloc(_digitalBytes,1); addDevice(this); } @@ -125,6 +127,11 @@ private: return false; } + void _loop(unsigned long currentMicros) override { + _commandBuffer[0] = EXIORDD; + I2CManager.read(_i2cAddress, _digitalPinStates, _digitalBytes, _commandBuffer, 1); + } + int _readAnalogue(VPIN vpin) override { if (vpin < _firstVpin + _numDigitalPins) return false; int pin = vpin - _firstVpin; @@ -137,11 +144,9 @@ private: int _read(VPIN vpin) override { if (vpin >= _firstVpin + _numDigitalPins) return false; int pin = vpin - _firstVpin; - _digitalOutBuffer[0] = EXIORDD; - _digitalOutBuffer[1] = pin; - _digitalOutBuffer[2] = 0x00; // Don't need to use this for reading - I2CManager.read(_i2cAddress, _digitalInBuffer, 1, _digitalOutBuffer, 3); - return _digitalInBuffer[0]; + uint8_t pinByte = pin / 8; + bool value = _digitalPinStates[pinByte] >> (pin - pinByte * 8); + return value; } void _write(VPIN vpin, int value) override { @@ -182,6 +187,9 @@ private: uint8_t _majorVer = 0; uint8_t _minorVer = 0; uint8_t _patchVer = 0; + byte* _digitalPinStates; + uint8_t _digitalBytes = 0; + byte _commandBuffer[1]; enum { EXIOINIT = 0xE0, // Flag to initialise setup procedure From 878549d5384c21196a4e8a098b8a18f5d3b3162d Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 23 Jan 2023 16:26:07 +1000 Subject: [PATCH 11/27] Working on analogue inputs --- IO_EXIOExpander.h | 50 ++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index 9aa9011..77554b5 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -66,8 +66,10 @@ private: _i2cAddress = i2cAddress; _numDigitalPins = numDigitalPins; _numAnaloguePins = numAnaloguePins; - _digitalBytes = (numDigitalPins+7)/8; - _digitalPinStates=(byte*) calloc(_digitalBytes,1); + _digitalPinBytes = (numDigitalPins+7)/8; + _analoguePinBytes = (numAnaloguePins+7)/8; + _digitalInputStates=(byte*) calloc(_digitalPinBytes,1); + _analogueInputStates=(byte*) calloc(_analoguePinBytes,2); addDevice(this); } @@ -79,16 +81,16 @@ private: _digitalOutBuffer[1] = _numDigitalPins; _digitalOutBuffer[2] = _numAnaloguePins; // Send config, if EXIORDY returned, we're good, otherwise go offline - I2CManager.read(_i2cAddress, _digitalInBuffer, 1, _digitalOutBuffer, 3); - if (_digitalInBuffer[0] != EXIORDY) { + I2CManager.read(_i2cAddress, _commandBuffer, 1, _digitalOutBuffer, 3); + if (_commandBuffer[0] != EXIORDY) { DIAG(F("ERROR configuring EX-IOExpander device, I2C:x%x"), _i2cAddress); _deviceState = DEVSTATE_FAILED; return; } // Attempt to get version, if we don't get it, we don't care, don't go offline // Using digital in buffer in reverse to save RAM - _digitalInBuffer[0] = EXIOVER; - I2CManager.read(_i2cAddress, _versionBuffer, 3, _digitalInBuffer, 1); + _commandBuffer[0] = EXIOVER; + I2CManager.read(_i2cAddress, _versionBuffer, 3, _commandBuffer, 1); _majorVer = _versionBuffer[0]; _minorVer = _versionBuffer[1]; _patchVer = _versionBuffer[2]; @@ -123,29 +125,41 @@ private: int _configureAnalogIn(VPIN vpin) override { if (vpin < _firstVpin + _numDigitalPins) { DIAG(F("EX-IOExpander ERROR: Vpin %d is a digital pin, cannot use as an analogue pin"), vpin); + return false; } - return false; + int pin = vpin - _firstVpin; + _analogueOutBuffer[0] = EXIOENAN; + _analogueOutBuffer[1] = pin; + DIAG(F("Enable Vpin %d/pin %d"), vpin, pin); + I2CManager.write(_i2cAddress, _analogueOutBuffer, 2); + return true; } void _loop(unsigned long currentMicros) override { _commandBuffer[0] = EXIORDD; - I2CManager.read(_i2cAddress, _digitalPinStates, _digitalBytes, _commandBuffer, 1); + I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _commandBuffer, 1); + _commandBuffer[0] = EXIORDAN; + I2CManager.read(_i2cAddress, _analogueInputStates, _analoguePinBytes, _commandBuffer, 1); + delayUntil(currentMicros + 500000); } int _readAnalogue(VPIN vpin) override { if (vpin < _firstVpin + _numDigitalPins) return false; int pin = vpin - _firstVpin; - _analogueOutBuffer[0] = EXIORDAN; - _analogueOutBuffer[1] = pin; - I2CManager.read(_i2cAddress, _analogueInBuffer, 2, _analogueOutBuffer, 2); - return (_analogueInBuffer[1] << 8) + _analogueInBuffer[0]; + // _analogueOutBuffer[0] = EXIORDAN; + // _analogueOutBuffer[1] = pin; + // I2CManager.read(_i2cAddress, _analogueInBuffer, 2, _analogueOutBuffer, 2); + // return (_analogueInBuffer[1] << 8) + _analogueInBuffer[0]; + uint8_t _pinLSBByte = (pin / 4) * 2; + uint8_t _pinMSBByte = _pinLSBByte + 1; + return (_pinMSBByte << 8) + _pinLSBByte; } int _read(VPIN vpin) override { if (vpin >= _firstVpin + _numDigitalPins) return false; int pin = vpin - _firstVpin; uint8_t pinByte = pin / 8; - bool value = _digitalPinStates[pinByte] >> (pin - pinByte * 8); + bool value = _digitalInputStates[pinByte] >> (pin - pinByte * 8); return value; } @@ -177,18 +191,17 @@ private: uint8_t _i2cAddress; uint8_t _numDigitalPins; uint8_t _numAnaloguePins; - int _digitalPinBytes; - int _analoguePinBytes; byte _analogueInBuffer[2]; byte _analogueOutBuffer[2]; byte _digitalOutBuffer[3]; - byte _digitalInBuffer[1]; uint8_t _versionBuffer[3]; uint8_t _majorVer = 0; uint8_t _minorVer = 0; uint8_t _patchVer = 0; - byte* _digitalPinStates; - uint8_t _digitalBytes = 0; + byte* _digitalInputStates; + byte* _analogueInputStates; + uint8_t _digitalPinBytes = 0; + uint8_t _analoguePinBytes = 0; byte _commandBuffer[1]; enum { @@ -199,6 +212,7 @@ private: EXIORDAN = 0xE4, // Flag to read an analogue input EXIOWRD = 0xE5, // Flag for digital write EXIORDD = 0xE6, // Flag to read digital input + EXIOENAN = 0xE7, // Flag eo enable an analogue pin }; }; From 459904e5ddc16361d43cd033d7e2e1725f8f7211 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 23 Jan 2023 20:12:28 +1000 Subject: [PATCH 12/27] More analogue inputs --- IO_EXIOExpander.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index 77554b5..9fc6876 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -67,9 +67,9 @@ private: _numDigitalPins = numDigitalPins; _numAnaloguePins = numAnaloguePins; _digitalPinBytes = (numDigitalPins+7)/8; - _analoguePinBytes = (numAnaloguePins+7)/8; + _analoguePinBytes = numAnaloguePins * 2; _digitalInputStates=(byte*) calloc(_digitalPinBytes,1); - _analogueInputStates=(byte*) calloc(_analoguePinBytes,2); + _analogueInputStates=(byte*) calloc(_analoguePinBytes,1); addDevice(this); } @@ -130,7 +130,6 @@ private: int pin = vpin - _firstVpin; _analogueOutBuffer[0] = EXIOENAN; _analogueOutBuffer[1] = pin; - DIAG(F("Enable Vpin %d/pin %d"), vpin, pin); I2CManager.write(_i2cAddress, _analogueOutBuffer, 2); return true; } @@ -140,7 +139,6 @@ private: I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _commandBuffer, 1); _commandBuffer[0] = EXIORDAN; I2CManager.read(_i2cAddress, _analogueInputStates, _analoguePinBytes, _commandBuffer, 1); - delayUntil(currentMicros + 500000); } int _readAnalogue(VPIN vpin) override { @@ -150,9 +148,10 @@ private: // _analogueOutBuffer[1] = pin; // I2CManager.read(_i2cAddress, _analogueInBuffer, 2, _analogueOutBuffer, 2); // return (_analogueInBuffer[1] << 8) + _analogueInBuffer[0]; - uint8_t _pinLSBByte = (pin / 4) * 2; + uint8_t _pinLSBByte = pin * 2; uint8_t _pinMSBByte = _pinLSBByte + 1; - return (_pinMSBByte << 8) + _pinLSBByte; + // DIAG(F("Vpin %d LSB %d MSB %d"), vpin, _analogueInputStates[_pinLSBByte], _analogueInputStates[_pinMSBByte]); + return (_analogueInputStates[_pinMSBByte] << 8) + _analogueInputStates[_pinLSBByte]; } int _read(VPIN vpin) override { From 20b3e9064cc463e9e0ae313b2c3f7dcbb0559afa Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 23 Jan 2023 21:35:22 +1000 Subject: [PATCH 13/27] Analogue inputs functioning --- IO_EXIOExpander.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index 9fc6876..54b186e 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -143,14 +143,13 @@ private: int _readAnalogue(VPIN vpin) override { if (vpin < _firstVpin + _numDigitalPins) return false; - int pin = vpin - _firstVpin; + int pin = vpin - _firstVpin - _numDigitalPins; // _analogueOutBuffer[0] = EXIORDAN; // _analogueOutBuffer[1] = pin; // I2CManager.read(_i2cAddress, _analogueInBuffer, 2, _analogueOutBuffer, 2); // return (_analogueInBuffer[1] << 8) + _analogueInBuffer[0]; uint8_t _pinLSBByte = pin * 2; uint8_t _pinMSBByte = _pinLSBByte + 1; - // DIAG(F("Vpin %d LSB %d MSB %d"), vpin, _analogueInputStates[_pinLSBByte], _analogueInputStates[_pinMSBByte]); return (_analogueInputStates[_pinMSBByte] << 8) + _analogueInputStates[_pinLSBByte]; } From 4acf46db548108479f1afea52764a86ddef3f712 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Tue, 24 Jan 2023 08:17:43 +1000 Subject: [PATCH 14/27] EX-IO reads optimised for speed --- IO_EXIOExpander.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index 54b186e..cce101b 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -144,10 +144,6 @@ private: int _readAnalogue(VPIN vpin) override { if (vpin < _firstVpin + _numDigitalPins) return false; int pin = vpin - _firstVpin - _numDigitalPins; - // _analogueOutBuffer[0] = EXIORDAN; - // _analogueOutBuffer[1] = pin; - // I2CManager.read(_i2cAddress, _analogueInBuffer, 2, _analogueOutBuffer, 2); - // return (_analogueInBuffer[1] << 8) + _analogueInBuffer[0]; uint8_t _pinLSBByte = pin * 2; uint8_t _pinMSBByte = _pinLSBByte + 1; return (_analogueInputStates[_pinMSBByte] << 8) + _analogueInputStates[_pinLSBByte]; @@ -189,7 +185,6 @@ private: uint8_t _i2cAddress; uint8_t _numDigitalPins; uint8_t _numAnaloguePins; - byte _analogueInBuffer[2]; byte _analogueOutBuffer[2]; byte _digitalOutBuffer[3]; uint8_t _versionBuffer[3]; From 006c85e6ae60dc9c89502dc4a3cb1af8b82cf483 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Tue, 24 Jan 2023 12:21:28 +0000 Subject: [PATCH 15/27] Delete platformio.ini.original Delete file not required --- platformio.ini.original | 223 ---------------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 platformio.ini.original diff --git a/platformio.ini.original b/platformio.ini.original deleted file mode 100644 index 82167f2..0000000 --- a/platformio.ini.original +++ /dev/null @@ -1,223 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter -; Upload options: custom upload port, speed and extra flags -; Library options: dependencies, extra library storages -; Advanced options: extra scripting -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[platformio] -default_envs = - mega2560 - uno - mega328 - unowifiR2 - nano - samd21-dev-usb - samd21-zero-usb - ESP32 - Nucleo-F411RE - Nucleo-F446RE - Teensy3.2 - Teensy3.5 - Teensy3.6 - Teensy4.0 - Teensy4.1 -src_dir = . -include_dir = . - -[env] -build_flags = -Wall -Wextra - -[env:samd21-dev-usb] -platform = atmelsam -board = sparkfun_samd21_dev_usb -framework = arduino -upload_protocol = sam-ba -lib_deps = ${env.lib_deps} -monitor_speed = 115200 -monitor_echo = yes -build_flags = -std=c++17 - -[env:samd21-zero-usb] -platform = atmelsam -board = zeroUSB -framework = arduino -upload_protocol = sam-ba -lib_deps = ${env.lib_deps} -monitor_speed = 115200 -monitor_echo = yes -build_flags = -std=c++17 - -[env:mega2560-debug] -platform = atmelavr -board = megaatmega2560 -framework = arduino -lib_deps = - ${env.lib_deps} - arduino-libraries/Ethernet - SPI -monitor_speed = 115200 -monitor_echo = yes -build_flags = -DDIAG_IO -DDIAG_LOOPTIMES - -[env:mega2560-no-HAL] -platform = atmelavr -board = megaatmega2560 -framework = arduino -lib_deps = - ${env.lib_deps} - arduino-libraries/Ethernet - SPI -monitor_speed = 115200 -monitor_echo = yes -build_flags = -DIO_NO_HAL - -[env:mega2560-I2C-wire] -platform = atmelavr -board = megaatmega2560 -framework = arduino -lib_deps = - ${env.lib_deps} - arduino-libraries/Ethernet - SPI -monitor_speed = 115200 -monitor_echo = yes -build_flags = -DI2C_USE_WIRE - -[env:mega2560] -platform = atmelavr -board = megaatmega2560 -framework = arduino -lib_deps = - ${env.lib_deps} - arduino-libraries/Ethernet - SPI -monitor_speed = 115200 -monitor_echo = yes -build_flags = -mcall-prologues - -[env:mega328] -platform = atmelavr -board = uno -framework = arduino -lib_deps = - ${env.lib_deps} - arduino-libraries/Ethernet - SPI -monitor_speed = 115200 -monitor_echo = yes - -[env:unowifiR2] -platform = atmelmegaavr -board = uno_wifi_rev2 -framework = arduino -lib_deps = - ${env.lib_deps} - arduino-libraries/Ethernet - SPI -monitor_speed = 115200 -monitor_echo = yes -build_flags = "-DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_UNO_WIFI_DEV_ED -DARDUINO_ARCH_AVR -DESP_CH_UART -DESP_CH_UART_BR=19200" - -[env:nanoevery] -platform = atmelmegaavr -board = nano_every -framework = arduino -lib_deps = - ${env.lib_deps} - arduino-libraries/Ethernet - SPI -monitor_speed = 115200 -monitor_echo = yes -upload_speed = 19200 -build_flags = -DDIAG_IO - -[env:uno] -platform = atmelavr -board = uno -framework = arduino -lib_deps = - ${env.lib_deps} - arduino-libraries/Ethernet - SPI -monitor_speed = 115200 -monitor_echo = yes -build_flags = -mcall-prologues - -[env:nano] -platform = atmelavr -board = nanoatmega328new -board_upload.maximum_size = 32256 -framework = arduino -lib_deps = ${env.lib_deps} -monitor_speed = 115200 -monitor_echo = yes - -[env:ESP32] -platform = espressif32 -board = esp32dev -framework = arduino -lib_deps = ${env.lib_deps} -build_flags = -std=c++17 - -[env:Nucleo-F411RE] -platform = ststm32 -board = nucleo_f411re -framework = arduino -lib_deps = ${env.lib_deps} -build_flags = -std=c++17 -Os -g2 -Wunused-variable -monitor_speed = 115200 -monitor_echo = yes - -[env:Nucleo-F446RE] -platform = ststm32 -board = nucleo_f446re -framework = arduino -lib_deps = ${env.lib_deps} -build_flags = -std=c++17 -Os -g2 -Wunused-variable -monitor_speed = 115200 -monitor_echo = yes - -[env:Teensy3.2] -platform = teensy -board = teensy31 -framework = arduino -build_flags = -std=c++17 -Os -g2 -lib_deps = ${env.lib_deps} -lib_ignore = NativeEthernet - -[env:Teensy3.5] -platform = teensy -board = teensy35 -framework = arduino -build_flags = -std=c++17 -Os -g2 -lib_deps = ${env.lib_deps} -lib_ignore = NativeEthernet - -[env:Teensy3.6] -platform = teensy -board = teensy36 -framework = arduino -build_flags = -std=c++17 -Os -g2 -lib_deps = ${env.lib_deps} -lib_ignore = NativeEthernet - -[env:Teensy4.0] -platform = teensy -board = teensy40 -framework = arduino -build_flags = -std=c++17 -Os -g2 -lib_deps = ${env.lib_deps} -lib_ignore = NativeEthernet - -[env:Teensy4.1] -platform = teensy -board = teensy41 -framework = arduino -build_flags = -std=c++17 -Os -g2 -lib_deps = ${env.lib_deps} -lib_ignore = - From fcf16c1367d5397cc63861f0cbccebee390cdb4e Mon Sep 17 00:00:00 2001 From: peteGSX Date: Thu, 26 Jan 2023 18:53:25 +1000 Subject: [PATCH 16/27] Update version --- version.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/version.h b/version.h index a17babd..0e14288 100644 --- a/version.h +++ b/version.h @@ -4,7 +4,9 @@ #include "StringFormatter.h" -#define VERSION "4.2.9pre1" +#define VERSION "4.2.10pre1" +// 4.2.10 SIGNAL/SIGNALH bug fix as they were inverted +// IO_EXIOExpander.h input speed optimisation // 4.2.9 duinoNodes support // 4.2.8 HIGHMEM (EXRAIL support beyond 64kb) // Withrottle connect/disconnect improvements From 88b572a14838389fff1b07e6e9e43f3ab84093c3 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Thu, 26 Jan 2023 16:55:58 +0100 Subject: [PATCH 17/27] Add EXRAIL IFLOCO function --- EXRAIL2.cpp | 5 ++++- EXRAIL2.h | 1 + EXRAIL2MacroReset.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 09566cb..122bf4a 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -747,6 +747,10 @@ void RMFT2::loop2() { skipIf=IODevice::readAnalogue(operand)>=(int)(getOperand(1)); break; + case OPCODE_IFLOCO: // do if the loco is the active one + skipIf=loco!=operand; + break; + case OPCODE_IFNOT: // do next operand if sensor not set skipIf=readSensor(operand); break; @@ -1244,4 +1248,3 @@ void RMFT2::thrungeString(uint32_t strfar, thrunger mode, byte id) { default: break; } } - \ No newline at end of file diff --git a/EXRAIL2.h b/EXRAIL2.h index 69fd382..7acb839 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -69,6 +69,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_IFRANDOM,OPCODE_IFRESERVE, OPCODE_IFCLOSED,OPCODE_IFTHROWN, OPCODE_IFRE, + OPCODE_IFLOCO }; enum thrunger: byte { diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index a5e6d90..e59d1c9 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -65,6 +65,7 @@ #undef IFCLOSED #undef IFGREEN #undef IFGTE +#undef IFLOCO #undef IFLT #undef IFNOT #undef IFRANDOM @@ -182,6 +183,7 @@ #define IFCLOSED(turnout_id) #define IFGREEN(signal_id) #define IFGTE(sensor_id,value) +#define IFLOCO(loco_id) #define IFLT(sensor_id,value) #define IFNOT(sensor_id) #define IFRANDOM(percent) From 762742b4affa5d35c39e71530b75ab4554abfb4a Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Fri, 27 Jan 2023 13:05:36 +0100 Subject: [PATCH 18/27] Add the macro def --- EXRAILMacros.h | 1 + 1 file changed, 1 insertion(+) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 2ffbc75..25bb299 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -282,6 +282,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define IFCLOSED(turnout_id) OPCODE_IFCLOSED,V(turnout_id), #define IFGREEN(signal_id) OPCODE_IFGREEN,V(signal_id), #define IFGTE(sensor_id,value) OPCODE_IFGTE,V(sensor_id),OPCODE_PAD,V(value), +#define IFLOCO(loco_id) OPCODE_IFLOCO,V(loco_id), #define IFLT(sensor_id,value) OPCODE_IFLT,V(sensor_id),OPCODE_PAD,V(value), #define IFNOT(sensor_id) OPCODE_IFNOT,V(sensor_id), #define IFRANDOM(percent) OPCODE_IFRANDOM,V(percent), From 2c0886bc2f5415e63fdb9f976e31b6cc8f548472 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Fri, 27 Jan 2023 17:03:39 +0100 Subject: [PATCH 19/27] version and copyright info --- EXRAIL2.cpp | 2 +- EXRAIL2.h | 1 + EXRAIL2MacroReset.h | 4 ++-- EXRAILMacros.h | 1 + GITHUB_SHA.h | 2 +- version.h | 3 ++- 6 files changed, 8 insertions(+), 5 deletions(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 122bf4a..94d7481 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -1,6 +1,6 @@ /* * © 2021 Neil McKechnie - * © 2021-2022 Harald Barth + * © 2021-2023 Harald Barth * © 2020-2022 Chris Harlow * All rights reserved. * diff --git a/EXRAIL2.h b/EXRAIL2.h index 7acb839..12bca3b 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -1,6 +1,7 @@ /* * © 2021 Neil McKechnie * © 2020-2022 Chris Harlow + * © 2023 Harald Barth * All rights reserved. * * This file is part of CommandStation-EX diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index e59d1c9..e5f3ba0 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -1,6 +1,6 @@ /* - * © 2021-2022 Chris Harlow - * © 2020,2021 Chris Harlow. All rights reserved. + * © 2020-2022 Chris Harlow. All rights reserved. + * © 2023 Harald Barth * * This file is part of CommandStation-EX * diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 25bb299..fc05e6b 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -1,6 +1,7 @@ /* * © 2021 Neil McKechnie * © 2020-2022 Chris Harlow + * © 2023 Harald Barth * All rights reserved. * * This file is part of CommandStation-EX diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index d6c9738..5d48ec7 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202212051450Z" +#define GITHUB_SHA "devel-202301271500Z" diff --git a/version.h b/version.h index 0e14288..f55e502 100644 --- a/version.h +++ b/version.h @@ -4,7 +4,8 @@ #include "StringFormatter.h" -#define VERSION "4.2.10pre1" +#define VERSION "4.2.11pre1" +// 4.2.11 Exrail IFLOCO feature added // 4.2.10 SIGNAL/SIGNALH bug fix as they were inverted // IO_EXIOExpander.h input speed optimisation // 4.2.9 duinoNodes support From 9e5d780c140e532c83d543088df212358e5f7bef Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Fri, 27 Jan 2023 18:42:26 +0100 Subject: [PATCH 20/27] Bugfix for issue #299 TurnoutDescription NULL --- DCCEXParser.cpp | 19 ++++++++++++------- GITHUB_SHA.h | 2 +- version.h | 3 ++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 5c0cb84..e554895 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -626,14 +626,19 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) else { // Turnout * t=Turnout::get(id); if (!t || t->isHidden()) StringFormatter::send(stream, F(" %d X"),id); - else StringFormatter::send(stream, F(" %d %c \"%S\""), - id,t->isThrown()?'T':'C', + else { + const FSH *tdesc = NULL; #ifdef EXRAIL_ACTIVE - RMFT2::getTurnoutDescription(id) -#else - F("") -#endif - ); + tdesc = RMFT2::getTurnoutDescription(id); +#endif + if (tdesc == NULL) + StringFormatter::send(stream, F(" %d %c"), + id,t->isThrown()?'T':'C'); + else + StringFormatter::send(stream, F(" %d %c \"%S\""), + id,t->isThrown()?'T':'C', + tdesc); + } } StringFormatter::send(stream, F(">\n")); return; diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index 5d48ec7..ba13dba 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202301271500Z" +#define GITHUB_SHA "devel-202301271742Z" diff --git a/version.h b/version.h index f55e502..4afa186 100644 --- a/version.h +++ b/version.h @@ -4,7 +4,8 @@ #include "StringFormatter.h" -#define VERSION "4.2.11pre1" +#define VERSION "4.2.12pre1" +// 4.2.12 Bugfix for issue #299 TurnoutDescription NULL // 4.2.11 Exrail IFLOCO feature added // 4.2.10 SIGNAL/SIGNALH bug fix as they were inverted // IO_EXIOExpander.h input speed optimisation From c91d66549c11212979eeea17e380dbd36bf982bd Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Fri, 27 Jan 2023 19:42:55 +0100 Subject: [PATCH 21/27] Remove warnings --- EXRAIL2.cpp | 2 +- IO_EXIOExpander.h | 3 ++- WiThrottle.cpp | 11 +++++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 94d7481..e925d96 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -748,7 +748,7 @@ void RMFT2::loop2() { break; case OPCODE_IFLOCO: // do if the loco is the active one - skipIf=loco!=operand; + skipIf=loco!=(uint16_t)operand; // bad luck if someone enters negative loco numbers into EXRAIL break; case OPCODE_IFNOT: // do next operand if sensor not set diff --git a/IO_EXIOExpander.h b/IO_EXIOExpander.h index cce101b..d54feac 100644 --- a/IO_EXIOExpander.h +++ b/IO_EXIOExpander.h @@ -135,6 +135,7 @@ private: } void _loop(unsigned long currentMicros) override { + (void)currentMicros; // remove warning _commandBuffer[0] = EXIORDD; I2CManager.read(_i2cAddress, _digitalInputStates, _digitalPinBytes, _commandBuffer, 1); _commandBuffer[0] = EXIORDAN; @@ -209,4 +210,4 @@ private: }; }; -#endif \ No newline at end of file +#endif diff --git a/WiThrottle.cpp b/WiThrottle.cpp index 920ebd6..69c5d87 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -525,7 +525,7 @@ void WiThrottle::sendTurnouts(Print* stream) { } void WiThrottle::sendRoster(Print* stream) { rosterSent=true; - #ifdef EXRAIL_ACTIVE +#ifdef EXRAIL_ACTIVE StringFormatter::send(stream,F("RL%d"), RMFT2::rosterNameCount); for (int16_t r=0;r=0) StringFormatter::send(stream,F("M%cA%c%d<;>F%d%d\n"),myLocos[loco].throttle,LorS(locoid),locoid,fstate,fKey); } -} \ No newline at end of file +} From 6cc66e26c127ac3beabbec48f0fec35c6386a8ac Mon Sep 17 00:00:00 2001 From: pmantoine Date: Sat, 28 Jan 2023 13:58:55 +0800 Subject: [PATCH 22/27] Initial STM32F4xx fast ADC read implementation --- CommandStation-EX.ino | 3 + DCCTimer.h | 14 +++-- DCCTimerSAMD.cpp | 19 +------ DCCTimerSTM32.cpp | 129 ++++++++++++++++++++++++++++++++++++++++-- DCCWaveform.cpp | 1 - 5 files changed, 136 insertions(+), 30 deletions(-) diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index f003ef6..67a7e58 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -99,6 +99,9 @@ void setup() // Initialise HAL layer before reading EEprom or setting up MotorDrivers IODevice::begin(); + // As the setup of a motor shield may require a read of the current sense input from the ADC, + // let's make sure to initialise the ADCee class! + ADCee::begin(); // Responsibility 3: Start the DCC engine. // Note: this provides DCC with two motor drivers, main and prog, which handle the motor shield(s) // Standard supported devices have pre-configured macros but custome hardware installations require diff --git a/DCCTimer.h b/DCCTimer.h index ed87e1f..75be8cd 100644 --- a/DCCTimer.h +++ b/DCCTimer.h @@ -1,5 +1,5 @@ /* - * © 2022 Paul M. Antoine + * © 2022-2023 Paul M. Antoine * © 2021 Mike S * © 2021-2022 Harald Barth * © 2021 Fred Decker @@ -102,9 +102,14 @@ private: // that an offset can be initialized. class ADCee { public: - // init does add the pin to the list of scanned pins (if this + // begin is called for any setup that must be done before + // **init** can be called. On some architectures this involves ADC + // initialisation and clock routing, sampling times etc. + static void begin(); + // init adds the pin to the list of scanned pins (if this // platform's implementation scans pins) and returns the first - // read value. It is called before the regular scan is started. + // read value (which is why it required begin to have been called first!) + // It must be called before the regular scan is started. static int init(uint8_t pin); // read does read the pin value from the scanned cache or directly // if this is a platform that does not scan. fromISR is a hint if @@ -117,9 +122,6 @@ private: // On platforms that scan, it is called from waveform ISR // only on a regular basis. static void scan(); - // begin is called for any setup that must be done before - // scan can be called. - static void begin(); // bit array of used pins (max 16) static uint16_t usedpins; // cached analog values (malloc:ed to actual number of ADC channels) diff --git a/DCCTimerSAMD.cpp b/DCCTimerSAMD.cpp index 7f10169..463cc64 100644 --- a/DCCTimerSAMD.cpp +++ b/DCCTimerSAMD.cpp @@ -168,23 +168,6 @@ int ADCee::init(uint8_t pin) { if (id > NUM_ADC_INPUTS) return -1023; - // Dummy read using Arduino library - analogReadResolution(12); - value = analogRead(pin); - - // Reconfigure ADC - ADC->CTRLA.bit.ENABLE = 0; // disable ADC - while( ADC->STATUS.bit.SYNCBUSY == 1 ); // wait for synchronization - - ADC->CTRLB.reg &= 0b1111100011001111; // mask PRESCALER and RESSEL bits - ADC->CTRLB.reg |= ADC_CTRLB_PRESCALER_DIV64 | // divide Clock by 16 - ADC_CTRLB_RESSEL_12BIT; // Result 12 bits, 10 bits possible - ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 | // take 1 sample at a time - ADC_AVGCTRL_ADJRES(0x00ul); // adjusting result by 0 - ADC->SAMPCTRL.reg = 0x00ul; // sampling Time Length = 0 - ADC->CTRLA.bit.ENABLE = 1; // enable ADC - while( ADC->STATUS.bit.SYNCBUSY == 1 ); // wait for synchronization - // Permanently configure SAMD IO MUX for that pin pinPeripheral(pin, PIO_ANALOG); ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; // Selection for the positive ADC input @@ -205,9 +188,11 @@ int ADCee::init(uint8_t pin) { return value; } + int16_t ADCee::ADCmax() { return 4095; } + /* * Read function ADCee::read(pin) to get value instead of analogRead(pin) */ diff --git a/DCCTimerSTM32.cpp b/DCCTimerSTM32.cpp index 0f60507..b1a90ac 100644 --- a/DCCTimerSTM32.cpp +++ b/DCCTimerSTM32.cpp @@ -131,31 +131,148 @@ void DCCTimer::reset() { while(true) {}; } +#define NUM_ADC_INPUTS NUM_ANALOG_INPUTS + +// TODO: may need to use uint32_t on STMF4xx variants with > 16 analog inputs! +uint16_t ADCee::usedpins = 0; +int * ADCee::analogvals = NULL; +uint32_t * analogchans = NULL; +bool adc1configured = false; + int16_t ADCee::ADCmax() { return 4095; } int ADCee::init(uint8_t pin) { - return analogRead(pin); + uint id = pin - A0; + int value = 0; + PinName stmpin = digitalPin[analogInputPin[id]]; + uint32_t stmgpio = stmpin / 16; // 16-bits per GPIO port group on STM32 + uint32_t adcchan = STM_PIN_CHANNEL(pinmap_function(stmpin, PinMap_ADC)); // find ADC channel (only valid for ADC1!) + GPIO_TypeDef * gpioBase; + + // Port config - find which port we're on and power it up + switch(stmgpio) { + case 0x00: + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //Power up PORTA + gpioBase = GPIOA; + break; + case 0x01: + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; //Power up PORTB + gpioBase = GPIOB; + break; + case 0x02: + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; //Power up PORTC + gpioBase = GPIOC; + break; + } + + // Set pin mux mode to analog input + gpioBase->MODER |= (0b011 << (stmpin << 1)); // Set pin mux to analog mode + + // Set the sampling rate for that analog input + if (adcchan < 10) + ADC1->SMPR2 |= (0b111 << (adcchan * 3)); // Channel sampling rate 480 cycles. 16MHz bus clock for ADC. 1/16MHz = 62.5ns. 480*62.5ns=30us + else + ADC1->SMPR1 |= (0b111 << ((adcchan - 10) * 3)); // Channel sampling rate 480 cycles. 16MHz bus clock for ADC. 1/16MHz = 62.5ns. 480*62.5ns=30us + + // Read the inital ADC value for this analog input + ADC1->SQR3 = adcchan; // 1st conversion in regular sequence + ADC1->CR2 |= (1 << 30); // Start 1st conversion SWSTART + while(!(ADC1->SR & (1 << 1))); // Wait until conversion is complete + value = ADC1->DR; // Read value from register + + if (analogvals == NULL) + { + analogvals = (int *)calloc(NUM_ADC_INPUTS+1, sizeof(int)); + analogchans = (uint32_t *)calloc(NUM_ADC_INPUTS+1, sizeof(uint32_t)); + } + analogvals[id] = value; // Store sampled value + analogchans[id] = adcchan; // Keep track of which ADC channel is used for reading this pin + usedpins |= (1 << id); // This pin is now ready + + return value; } + /* * Read function ADCee::read(pin) to get value instead of analogRead(pin) */ int ADCee::read(uint8_t pin, bool fromISR) { - int current; - if (!fromISR) noInterrupts(); - current = analogRead(pin); - if (!fromISR) interrupts(); - return current; + uint8_t id = pin - A0; + // Was this pin initialised yet? + if ((usedpins & (1<SR & (1 << 1))) + return; // no result, continue to wait + // found value + analogvals[id] = ADC1->DR; + // advance at least one track + // for scope debug TrackManager::track[1]->setBrake(0); + waiting = false; + id++; + mask = mask << 1; + if (id == NUM_ADC_INPUTS+1) { + id = 0; + mask = 1; + } + } + if (!waiting) { + if (usedpins == 0) // otherwise we would loop forever + return; + // look for a valid track to sample or until we are around + while (true) { + if (mask & usedpins) { + // start new ADC aquire on id + ADC1->SQR3 = analogchans[id]; //1st conversion in regular sequence + ADC1->CR2 |= (1 << 30); //Start 1st conversion SWSTART + // for scope debug TrackManager::track[1]->setBrake(1); + waiting = true; + return; + } + id++; + mask = mask << 1; + if (id == NUM_ADC_INPUTS+1) { + id = 0; + mask = 1; + } + } + } } +#pragma GCC pop_options void ADCee::begin() { noInterrupts(); + //ADC1 config sequence + // TODO: currently defaults to ADC1, may need more to handle other members of STM32F4xx family + RCC->APB2ENR |= (1 << 8); //Enable ADC1 clock (Bit8) + // Set ADC prescaler - DIV8 ~ 40ms, DIV6 ~ 30ms, DIV4 ~ 20ms, DIV2 ~ 11ms + ADC->CCR = (0 << 16); // Set prescaler 0=DIV2, 1=DIV4, 2=DIV6, 3=DIV8 + ADC1->CR1 &= ~(1 << 8); //SCAN mode disabled (Bit8) + ADC1->CR1 &= ~(3 << 24); //12bit resolution (Bit24,25 0b00) + ADC1->SQR1 = (1 << 20); //Set number of conversions projected (L[3:0] 0b0001) -> 1 conversion + ADC1->CR2 &= ~(1 << 1); //Single conversion + ADC1->CR2 &= ~(1 << 11); //Right alignment of data bits bit12....bit0 + ADC1->SQR1 &= ~(0x3FFFFFFF); //Clear whole 1st 30bits in register + ADC1->SQR2 &= ~(0x3FFFFFFF); //Clear whole 1st 30bits in register + ADC1->SQR3 &= ~(0x3FFFFFFF); //Clear whole 1st 30bits in register + ADC1->CR2 |= (1 << 0); // Switch on ADC1 interrupts(); } #endif \ No newline at end of file diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index f807c34..e065648 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -62,7 +62,6 @@ const bool signalTransform[]={ /* WAVE_PENDING (should not happen) -> */ LOW}; void DCCWaveform::begin() { - ADCee::begin(); DCCTimer::begin(DCCWaveform::interruptHandler); } From be33bafa6676f8522fffbb5669389d57264dd39c Mon Sep 17 00:00:00 2001 From: pmantoine Date: Sat, 28 Jan 2023 14:39:00 +0800 Subject: [PATCH 23/27] Fixed logic of ADC ready --- DCCTimerSTM32.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DCCTimerSTM32.cpp b/DCCTimerSTM32.cpp index b1a90ac..df66c98 100644 --- a/DCCTimerSTM32.cpp +++ b/DCCTimerSTM32.cpp @@ -96,7 +96,7 @@ void DCCTimer::clearPWM() { void DCCTimer::getSimulatedMacAddress(byte mac[6]) { volatile uint32_t *serno1 = (volatile uint32_t *)0x1FFF7A10; volatile uint32_t *serno2 = (volatile uint32_t *)0x1FFF7A14; - volatile uint32_t *serno3 = (volatile uint32_t *)0x1FFF7A18; + // volatile uint32_t *serno3 = (volatile uint32_t *)0x1FFF7A18; volatile uint32_t m1 = *serno1; volatile uint32_t m2 = *serno2; @@ -172,9 +172,9 @@ int ADCee::init(uint8_t pin) { // Set the sampling rate for that analog input if (adcchan < 10) - ADC1->SMPR2 |= (0b111 << (adcchan * 3)); // Channel sampling rate 480 cycles. 16MHz bus clock for ADC. 1/16MHz = 62.5ns. 480*62.5ns=30us + ADC1->SMPR2 |= (0b111 << (adcchan * 3)); // Channel sampling rate 480 cycles else - ADC1->SMPR1 |= (0b111 << ((adcchan - 10) * 3)); // Channel sampling rate 480 cycles. 16MHz bus clock for ADC. 1/16MHz = 62.5ns. 480*62.5ns=30us + ADC1->SMPR1 |= (0b111 << ((adcchan - 10) * 3)); // Channel sampling rate 480 cycles // Read the inital ADC value for this analog input ADC1->SQR3 = adcchan; // 1st conversion in regular sequence @@ -219,7 +219,7 @@ void ADCee::scan() { if (waiting) { // look if we have a result - if ((ADC1->SR & (1 << 1))) + if (!(ADC1->SR & (1 << 1))) return; // no result, continue to wait // found value analogvals[id] = ADC1->DR; From 2a7588b1b542e23837806348e4a808395c7d8e73 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 28 Jan 2023 19:07:59 +0100 Subject: [PATCH 24/27] jT answer should contain empty string --- DCCEXParser.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index e554895..4070049 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -632,12 +632,10 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) tdesc = RMFT2::getTurnoutDescription(id); #endif if (tdesc == NULL) - StringFormatter::send(stream, F(" %d %c"), - id,t->isThrown()?'T':'C'); - else - StringFormatter::send(stream, F(" %d %c \"%S\""), - id,t->isThrown()?'T':'C', - tdesc); + tdesc = F(""); + StringFormatter::send(stream, F(" %d %c \"%S\""), + id,t->isThrown()?'T':'C', + tdesc); } } StringFormatter::send(stream, F(">\n")); From 290d878063beab9479cdfe87e58178a8da0b4b36 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 28 Jan 2023 19:09:16 +0100 Subject: [PATCH 25/27] version --- GITHUB_SHA.h | 2 +- version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index ba13dba..6b17a12 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202301271742Z" +#define GITHUB_SHA "devel-202301281808Z" diff --git a/version.h b/version.h index 4afa186..10f11f9 100644 --- a/version.h +++ b/version.h @@ -4,7 +4,7 @@ #include "StringFormatter.h" -#define VERSION "4.2.12pre1" +#define VERSION "4.2.12pre2" // 4.2.12 Bugfix for issue #299 TurnoutDescription NULL // 4.2.11 Exrail IFLOCO feature added // 4.2.10 SIGNAL/SIGNALH bug fix as they were inverted From 212bf8d80e34c7b3e96e0925dc43911df3fc2212 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 29 Jan 2023 08:13:52 +0100 Subject: [PATCH 26/27] Broadcast power for again --- DCCEXParser.cpp | 1 + GITHUB_SHA.h | 2 +- version.h | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 4070049..ef11763 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -510,6 +510,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) case 's': // StringFormatter::send(stream, F("\n"), F(VERSION), F(ARDUINO_TYPE), DCC::getMotorShieldName(), F(GITHUB_SHA)); + CommandDistributor::broadcastPower(); // is the only "get power status" command we have Turnout::printAll(stream); //send all Turnout states Output::printAll(stream); //send all Output states Sensor::printAll(stream); //send all Sensor states diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index 6b17a12..dc9ffe9 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202301281808Z" +#define GITHUB_SHA "devel-202301290713Z" diff --git a/version.h b/version.h index 10f11f9..0ad586f 100644 --- a/version.h +++ b/version.h @@ -4,7 +4,8 @@ #include "StringFormatter.h" -#define VERSION "4.2.12pre2" +#define VERSION "4.2.13" +// 4.2.13 Broadcast power for again // 4.2.12 Bugfix for issue #299 TurnoutDescription NULL // 4.2.11 Exrail IFLOCO feature added // 4.2.10 SIGNAL/SIGNALH bug fix as they were inverted From 95945eab4c7aedc132bc6b6226ce8ceb447cac8b Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 29 Jan 2023 08:50:19 +0100 Subject: [PATCH 27/27] version bump --- GITHUB_SHA.h | 2 +- version.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index dc9ffe9..919895a 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202301290713Z" +#define GITHUB_SHA "devel-202301290750Z" diff --git a/version.h b/version.h index 0ad586f..6788645 100644 --- a/version.h +++ b/version.h @@ -4,7 +4,8 @@ #include "StringFormatter.h" -#define VERSION "4.2.13" +#define VERSION "4.2.14" +// 4.2.14 STM32F4xx fast ADC read implementation // 4.2.13 Broadcast power for again // 4.2.12 Bugfix for issue #299 TurnoutDescription NULL // 4.2.11 Exrail IFLOCO feature added