diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index 6e6fe60..85df03b 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -122,7 +122,7 @@ void CommandDistributor::broadcastLoco(byte slot) { void CommandDistributor::broadcastPower() { bool main=TrackManager::getMainPower()==POWERMODE::ON; bool prog=TrackManager::getProgPower()==POWERMODE::ON; - bool join=DCCWaveform::isJoined(); + bool join=TrackManager::isJoined(); const FSH * reason=F(""); char state='1'; if (main && prog && join) reason=F(" JOIN"); diff --git a/DCC.cpp b/DCC.cpp index 5188cda..977a304 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -557,8 +557,7 @@ void DCC::forgetAllLocos() { // removes all speed reminders byte DCC::loopStatus=0; void DCC::loop() { - DCCWaveform::loop(); // power overload checks - DCCACK::loop(); // maintain prog track ack manager + TrackManager::loop(); // power overload checks issueReminders(); } diff --git a/DCCACK.cpp b/DCCACK.cpp index bc115c0..7c159b8 100644 --- a/DCCACK.cpp +++ b/DCCACK.cpp @@ -77,10 +77,10 @@ void DCCACK::Setup(int cv, byte byteValueOrBitnum, ackOp const program[], ACK_C return; } - ackManagerRejoin=DCCWaveform::isJoined(); + ackManagerRejoin=TrackManager::isJoined(); if (ackManagerRejoin ) { // Change from JOIN must zero resets packet. - DCCWaveform::setJoin(false); + TrackManager::setJoin(false); DCCWaveform::progTrack.sentResetsSincePacket = 0; } @@ -403,7 +403,7 @@ void DCCACK::callback(int value) { } // Restore <1 JOIN> to state before BASELINE if (ackManagerRejoin) { - DCCWaveform::setJoin(true); + TrackManager::setJoin(true); if (Diag::ACK) DIAG(F("Auto JOIN")); } diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 6237e48..4d478cb 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -397,7 +397,7 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream) } if (main) TrackManager::setMainPower(POWERMODE::ON); if (prog) TrackManager::setProgPower(POWERMODE::ON); - DCCWaveform::setJoin(join); + TrackManager::setJoin(join); CommandDistributor::broadcastPower(); return; @@ -424,10 +424,10 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream) if (main) TrackManager::setMainPower(POWERMODE::OFF); if (prog) { - DCCWaveform::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off + TrackManager::progTrackBoosted=false; // Prog track boost mode will not outlive prog track off TrackManager::setProgPower(POWERMODE::OFF); } - DCCWaveform::setJoin(false); + TrackManager::setJoin(false); CommandDistributor::broadcastPower(); return; @@ -772,8 +772,8 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) #endif case HASH_KEYWORD_PROGBOOST: - DCCWaveform::progTrackBoosted=true; - return true; + TrackManager::progTrackBoosted=true; + return true; case HASH_KEYWORD_RESET: { diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index c51a18e..0258627 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -21,7 +21,8 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ - +#ifndef ARDUINO_ARCH_ESP32 + // This code is replaced entirely on an ESP32 #include #include "DCCWaveform.h" @@ -34,19 +35,38 @@ DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true); DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false); -bool DCCWaveform::progTrackSyncMain=false; -bool DCCWaveform::progTrackBoosted=false; -int16_t DCCWaveform::joinRelay=UNUSED_PIN; + +// This bitmask has 9 entries as each byte is trasmitted as a zero + 8 bits. +const byte bitMask[] = {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; + +const byte idlePacket[] = {0xFF, 0x00, 0xFF}; +const byte resetPacket[] = {0x00, 0x00, 0x00}; + + +// For each state of the wave nextState=stateTransform[currentState] +const WAVE_STATE stateTransform[]={ + /* WAVE_START -> */ WAVE_PENDING, + /* WAVE_MID_1 -> */ WAVE_START, + /* WAVE_HIGH_0 -> */ WAVE_MID_0, + /* WAVE_MID_0 -> */ WAVE_LOW_0, + /* WAVE_LOW_0 -> */ WAVE_START, + /* WAVE_PENDING (should not happen) -> */ WAVE_PENDING}; + +// For each state of the wave, signal pin is HIGH or LOW +const bool signalTransform[]={ + /* WAVE_START -> */ HIGH, + /* WAVE_MID_1 -> */ LOW, + /* WAVE_HIGH_0 -> */ HIGH, + /* WAVE_MID_0 -> */ LOW, + /* WAVE_LOW_0 -> */ LOW, + /* WAVE_PENDING (should not happen) -> */ LOW}; void DCCWaveform::begin() { - - TrackManager::setPower(POWERMODE::OFF); DCCTimer::begin(DCCWaveform::interruptHandler); } void DCCWaveform::loop() { - DCCACK::loop(); - TrackManager::loop(DCCACK::isActive() || progTrackSyncMain || progTrackBoosted ); + // empty placemarker in case ESP32 needs something here } #pragma GCC push_options @@ -55,7 +75,7 @@ void DCCWaveform::interruptHandler() { // call the timer edge sensitive actions for progtrack and maintrack // member functions would be cleaner but have more overhead byte sigMain=signalTransform[mainTrack.state]; - byte sigProg=progTrackSyncMain? sigMain : signalTransform[progTrack.state]; + byte sigProg=TrackManager::progTrackSyncMain? sigMain : signalTransform[progTrack.state]; // Set the signal state for both tracks TrackManager::setDCCSignal(sigMain); @@ -73,18 +93,6 @@ void DCCWaveform::interruptHandler() { } #pragma GCC push_options -void DCCWaveform::setJoinRelayPin(byte joinRelayPin) { - joinRelay=joinRelayPin; - if (joinRelay!=UNUSED_PIN) { - pinMode(joinRelay,OUTPUT); - digitalWrite(joinRelay,LOW); // LOW is relay disengaged - } -} - -void DCCWaveform::setJoin(bool joined) { - progTrackSyncMain=joined; - if (joinRelay!=UNUSED_PIN) digitalWrite(joinRelay,joined?HIGH:LOW); -} // An instance of this class handles the DCC transmissions for one track. (main or prog) // Interrupts are marshalled via the statics. @@ -92,9 +100,6 @@ void DCCWaveform::setJoin(bool joined) { // When the current buffer is exhausted, either the pending buffer (if there is one waiting) or an idle buffer. -// This bitmask has 9 entries as each byte is trasmitted as a zero + 8 bits. -const byte bitMask[] = {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; - DCCWaveform::DCCWaveform( byte preambleBits, bool isMain) { isMainTrack = isMain; @@ -110,25 +115,7 @@ DCCWaveform::DCCWaveform( byte preambleBits, bool isMain) { -// For each state of the wave nextState=stateTransform[currentState] -const WAVE_STATE DCCWaveform::stateTransform[]={ - /* WAVE_START -> */ WAVE_PENDING, - /* WAVE_MID_1 -> */ WAVE_START, - /* WAVE_HIGH_0 -> */ WAVE_MID_0, - /* WAVE_MID_0 -> */ WAVE_LOW_0, - /* WAVE_LOW_0 -> */ WAVE_START, - /* WAVE_PENDING (should not happen) -> */ WAVE_PENDING}; - -// For each state of the wave, signal pin is HIGH or LOW -const bool DCCWaveform::signalTransform[]={ - /* WAVE_START -> */ HIGH, - /* WAVE_MID_1 -> */ LOW, - /* WAVE_HIGH_0 -> */ HIGH, - /* WAVE_MID_0 -> */ LOW, - /* WAVE_LOW_0 -> */ LOW, - /* WAVE_PENDING (should not happen) -> */ LOW}; -#pragma GCC push_options #pragma GCC optimize ("-O3") void DCCWaveform::interrupt2() { // calculate the next bit to be sent: @@ -185,8 +172,6 @@ void DCCWaveform::interrupt2() { } } } -#pragma GCC pop_options - // Wait until there is no packet pending, then make this pending void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repeats) { @@ -205,7 +190,4 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea packetPending = true; sentResetsSincePacket=0; } - -#pragma GCC push_options -#pragma GCC optimize ("-O3") -#pragma GCC pop_options +#endif \ No newline at end of file diff --git a/DCCWaveform.h b/DCCWaveform.h index 2ad1c67..667e220 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -33,19 +33,14 @@ const int PREAMBLE_BITS_MAIN = 16; const int PREAMBLE_BITS_PROG = 22; const byte MAX_PACKET_SIZE = 5; // NMRA standard extended packets, payload size WITHOUT checksum. + // The WAVE_STATE enum is deliberately numbered because a change of order would be catastrophic // to the transform array. enum WAVE_STATE : byte {WAVE_START=0,WAVE_MID_1=1,WAVE_HIGH_0=2,WAVE_MID_0=3,WAVE_LOW_0=4,WAVE_PENDING=5}; - // NOTE: static functions are used for the overall controller, then // one instance is created for each track. - - -const byte idlePacket[] = {0xFF, 0x00, 0xFF}; -const byte resetPacket[] = {0x00, 0x00, 0x00}; - class DCCWaveform { public: DCCWaveform( byte preambleBits, bool isMain); @@ -53,26 +48,12 @@ class DCCWaveform { static void loop(); static DCCWaveform mainTrack; static DCCWaveform progTrack; - - void beginTrack(); - static void setJoin(bool join); - static bool isJoined() { return progTrackSyncMain;} void clearRepeats() {pendingRepeats=0;} void schedulePacket(const byte buffer[], byte byteCount, byte repeats); volatile bool packetPending; - static bool progTrackBoosted; // true when prog track is not current limited volatile byte sentResetsSincePacket; - static void setJoinRelayPin(byte joinRelayPin); - static int16_t joinRelay; private: - static bool progTrackSyncMain; // true when prog track is a siding switched to main - -// For each state of the wave nextState=stateTransform[currentState] - static const WAVE_STATE stateTransform[6]; - -// For each state of the wave, signal pin is HIGH or LOW - static const bool signalTransform[6]; static void interruptHandler(); void interrupt2(); diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 381d043..e4451a2 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -665,7 +665,7 @@ void RMFT2::loop2() { case OPCODE_POWEROFF: TrackManager::setPower(POWERMODE::OFF); - DCCWaveform::setJoin(false); + TrackManager::setJoin(false); CommandDistributor::broadcastPower(); break; @@ -811,18 +811,18 @@ void RMFT2::loop2() { case OPCODE_JOIN: TrackManager::setPower(POWERMODE::ON); - DCCWaveform::setJoin(true); + TrackManager::setJoin(true); CommandDistributor::broadcastPower(); break; case OPCODE_POWERON: TrackManager::setMainPower(POWERMODE::ON); - DCCWaveform::setJoin(false); + TrackManager::setJoin(false); CommandDistributor::broadcastPower(); break; case OPCODE_UNJOIN: - DCCWaveform::setJoin(false); + TrackManager::setJoin(false); CommandDistributor::broadcastPower(); break; diff --git a/TrackManager.cpp b/TrackManager.cpp index 17dd754..470e039 100644 --- a/TrackManager.cpp +++ b/TrackManager.cpp @@ -41,6 +41,10 @@ MotorDriver * TrackManager::track[MAX_TRACKS]; int16_t TrackManager::trackMode[MAX_TRACKS]; POWERMODE TrackManager::mainPowerGuess=POWERMODE::OFF; byte TrackManager::lastTrack=0; +bool TrackManager::progTrackSyncMain=false; +bool TrackManager::progTrackBoosted=false; +int16_t TrackManager::joinRelay=UNUSED_PIN; + // The setup call is done this way so that the tracks can be in a list // from the config... the tracks default to NULL in the declaration @@ -158,7 +162,10 @@ bool TrackManager::parseJ(Print *stream, int16_t params, int16_t p[]) byte TrackManager::nextCycleTrack=MAX_TRACKS; -void TrackManager::loop(bool dontLimitProg) { +void TrackManager::loop() { + DCCWaveform::loop(); + DCCACK::loop(); + bool dontLimitProg=DCCACK::isActive() || progTrackSyncMain || progTrackBoosted; nextCycleTrack++; if (nextCycleTrack>lastTrack) nextCycleTrack=0; if (track[nextCycleTrack]==NULL) return; @@ -193,3 +200,15 @@ POWERMODE TrackManager::getProgPower() { return POWERMODE::OFF; } +void TrackManager::setJoinRelayPin(byte joinRelayPin) { + joinRelay=joinRelayPin; + if (joinRelay!=UNUSED_PIN) { + pinMode(joinRelay,OUTPUT); + digitalWrite(joinRelay,LOW); // LOW is relay disengaged + } +} + +void TrackManager::setJoin(bool joined) { + progTrackSyncMain=joined; + if (joinRelay!=UNUSED_PIN) digitalWrite(joinRelay,joined?HIGH:LOW); +} diff --git a/TrackManager.h b/TrackManager.h index f861edb..18a073f 100644 --- a/TrackManager.h +++ b/TrackManager.h @@ -53,10 +53,16 @@ class TrackManager { static const int16_t MAX_TRACKS=8; static bool setTrackMode(byte track, int16_t DCaddrOrMode); static bool parseJ(Print * stream, int16_t params, int16_t p[]); - static void loop(bool dontLimitProg); + static void loop(); static POWERMODE getMainPower() {return mainPowerGuess;} static POWERMODE getProgPower(); - + static void setJoin(bool join); + static bool isJoined() { return progTrackSyncMain;} + static void setJoinRelayPin(byte joinRelayPin); + static int16_t joinRelay; + static bool progTrackSyncMain; // true when prog track is a siding switched to main + static bool progTrackBoosted; // true when prog track is not current limited + private: static void addTrack(byte t, MotorDriver* driver); diff --git a/WiThrottle.cpp b/WiThrottle.cpp index 1ac93f6..fed5078 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -543,7 +543,7 @@ void WiThrottle::getLocoCallback(int16_t locoid) { itoa(locoid,addcmd+4,10); stashInstance->multithrottle(stashStream, (byte *)addcmd); TrackManager::setMainPower(POWERMODE::ON); - DCCWaveform::setJoin(true); // <1 JOIN> so we can drive loco away + TrackManager::setJoin(true); // <1 JOIN> so we can drive loco away stashStream->commit(); CommandDistributor::broadcastPower();