diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 1111810..816cf85 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -672,14 +672,10 @@ bool DCCEXParser::parseT(Print *stream, int16_t params, int16_t p[]) StringFormatter::send(stream, F("\n")); return true; - case 2: // activate turnout - { - Turnout *tt = Turnout::get(p[0]); - if (!tt) - return false; - tt->activate(p[1]); - StringFormatter::send(stream, F("\n"), p[0], tt->data.active); - } + case 2: // turnout 0=CLOSE,1=THROW + if (p[1]>1 || p[1]<0 ) return false; + if (!Turnout::setClosed(p[0],p[1]==0)) return false; + StringFormatter::send(stream, F("\n"), p[0], p[1]); return true; default: // Anything else is handled by Turnout class. diff --git a/LCN.cpp b/LCN.cpp index df1b4ea..e9d0886 100644 --- a/LCN.cpp +++ b/LCN.cpp @@ -50,7 +50,7 @@ void LCN::loop() { if (Diag::LCN) DIAG(F("LCN IN %d%c"),id,(char)ch); Turnout * tt = Turnout::get(id); if (!tt) tt=Turnout::createLCN(id); - tt->setActive(ch=='t'); + Turnout::setClosedStateOnly(id,ch=='t'); Turnout::turnoutlistHash++; // signals ED update of turnout data id = 0; } diff --git a/RMFT2.cpp b/RMFT2.cpp index 735d016..5e4fd62 100644 --- a/RMFT2.cpp +++ b/RMFT2.cpp @@ -382,11 +382,11 @@ void RMFT2::loop2() { switch ((OPCODE)opcode) { case OPCODE_THROW: - Turnout::activate(operand, false); + Turnout::setClosed(operand, false); break; case OPCODE_CLOSE: - Turnout::activate(operand, true); + Turnout::setClosed(operand, true); break; case OPCODE_REV: @@ -666,8 +666,8 @@ void RMFT2::kill(const FSH * reason, int operand) { return; } } - void RMFT2::turnoutEvent(VPIN id, bool state) { - byte huntFor=state ? OPCODE_ONCLOSE : OPCODE_ONTHROW ; + void RMFT2::turnoutEvent(VPIN id, bool closed) { + byte huntFor=closed ? OPCODE_ONCLOSE : OPCODE_ONTHROW ; // caution hides class progCounter; for (int progCounter=0;; SKIPOP){ byte opcode=GET_OPCODE; diff --git a/RMFT2.h b/RMFT2.h index 8ab26c3..77e21bc 100644 --- a/RMFT2.h +++ b/RMFT2.h @@ -68,7 +68,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, static void readLocoCallback(int cv); static void emitWithrottleRouteList(Print* stream); static void createNewTask(int route, uint16_t cab); - static void turnoutEvent(VPIN id, bool thrown); + static void turnoutEvent(VPIN id, bool closed); private: static void ComandFilter(Print * stream, byte & opcode, byte & paramCount, int p[]); static bool parseSlash(Print * stream, byte & paramCount, int p[]) ; diff --git a/Turnouts.cpp b/Turnouts.cpp index 79a2d65..c18337b 100644 --- a/Turnouts.cpp +++ b/Turnouts.cpp @@ -18,6 +18,12 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ + +// >>>>>> ATTENTION: This class requires major cleaning. +// The public interface has been narrowed to avoid the ambuguity of "activated". + + + //#define EESTOREDEBUG #include "defines.h" #include "Turnouts.h" @@ -40,6 +46,10 @@ enum unit8_t { TURNOUT_LCN = 4, }; + + + + /////////////////////////////////////////////////////////////////////////////// // Static function to print all Turnout states to stream in form "" @@ -82,10 +92,25 @@ void Turnout::print(Print *stream){ } } + +// Public interface to turnout throw/close +bool Turnout::setClosed(int id, bool closed) { + // hides the internal activate argument to a single place + return activate(id, closed? false: true ); /// Needs cleaning up +} +bool Turnout::isClosed(int id) { + // hides the internal activate argument to a single place + return !isActive(id); /// Needs cleaning up +} +int Turnout::getId() { + return data.id; +} + /////////////////////////////////////////////////////////////////////////////// // Static function to activate/deactivate Turnout with ID 'n'. // Returns false if turnout not found. + bool Turnout::activate(int n, bool state){ Turnout * tt=get(n); if (!tt) return false; @@ -145,7 +170,7 @@ void Turnout::activate(bool state) { EEPROM.put(num, data.tStatus); #if defined(RMFT_ACTIVE) - RMFT2::turnoutEvent(data.id, state); + RMFT2::turnoutEvent(data.id, !state); #endif } diff --git a/Turnouts.h b/Turnouts.h index a89b68a..db73214 100644 --- a/Turnouts.h +++ b/Turnouts.h @@ -33,6 +33,7 @@ #include "LCN.h" #include "IODevice.h" + const byte STATUS_ACTIVE=0x80; // Flag as activated in tStatus field const byte STATUS_TYPE = 0x7f; // Mask for turnout type in tStatus field @@ -91,13 +92,13 @@ class Turnout { public: static Turnout *firstTurnout; static int turnoutlistHash; - TurnoutData data; Turnout *nextTurnout; - static bool activate(int n, bool state); static Turnout* get(int); static bool remove(int); - static bool isActive(int); - static void setActive(int n, bool state); + static bool isClosed(int); + static bool setClosed(int n, bool closed); // return false if not found. + static void setClosedStateOnly(int n, bool closed); + int getId(); static void load(); static void store(); static Turnout *createServo(int id , VPIN vpin , uint16_t activeAngle, uint16_t inactiveAngle, uint8_t profile=1, uint8_t initialState=0); @@ -106,9 +107,6 @@ public: static Turnout *createLCN(int id, uint8_t initialState=0); static Turnout *create(int id, int params, int16_t p[]); static Turnout *create(int id); - void activate(bool state); - void setActive(bool state); - bool isActive(); static void printAll(Print *); void print(Print *stream); #ifdef EESTOREDEBUG @@ -116,6 +114,12 @@ public: #endif private: int num; // EEPROM address of tStatus in TurnoutData struct, or zero if not stored. -}; // Turnout + TurnoutData data; + static bool activate(int n, bool thrown); + static bool isActive(int); + bool isActive(); + void activate(bool state); + void setActive(bool state); + }; // Turnout #endif diff --git a/WiThrottle.cpp b/WiThrottle.cpp index 3aab78e..e9cfdfd 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -121,7 +121,8 @@ void WiThrottle::parse(RingStream * stream, byte * cmdx) { if (turnoutListHash != Turnout::turnoutlistHash) { StringFormatter::send(stream,F("PTL")); for(Turnout *tt=Turnout::firstTurnout;tt!=NULL;tt=tt->nextTurnout){ - StringFormatter::send(stream,F("]\\[%d}|{%d}|{%c"), tt->data.id, tt->data.id, Turnout::isActive(tt->data.id)?'4':'2'); + int id=tt->getId(); + StringFormatter::send(stream,F("]\\[%d}|{%d}|{%c"), id, id, Turnout::isClosed(id)?'2':'4'); } StringFormatter::send(stream,F("\n")); turnoutListHash = Turnout::turnoutlistHash; // keep a copy of hash for later comparison @@ -160,7 +161,6 @@ void WiThrottle::parse(RingStream * stream, byte * cmdx) { #endif else if (cmd[1]=='T' && cmd[2]=='A') { // PTA accessory toggle int id=getInt(cmd+4); - byte newstate=2; // newstate can be 0,1 or 2. 2 is "invalid". Turnout * tt=Turnout::get(id); if (!tt) { // If turnout does not exist, create it @@ -170,17 +170,22 @@ void WiThrottle::parse(RingStream * stream, byte * cmdx) { StringFormatter::send(stream, F("HmTurnout %d created\n"),id); } switch (cmd[3]) { - // T and C according to RCN-213 where 0 is Stop, Red, Thrown, Diverging. - case 'T': newstate=0; break; - case 'C': newstate=1; break; - case '2': newstate=!Turnout::isActive(id); break; - default : /* newstate still invalid */ break; + // T and C according to RCN-213 where 0 is Stop, Red, Thrown, Diverging. + case 'T': + Turnout::setClosed(id,false); + break; + case 'C': + Turnout::setClosed(id,true); + break; + case '2': + Turnout::setClosed(id,!Turnout::isClosed(id)); + break; + default : + Turnout::setClosed(id,true); + break; } - if (newstate != 2) { - Turnout::activate(id,newstate); - StringFormatter::send(stream, F("PTA%c%d\n"),newstate?'4':'2',id ); - } - } + StringFormatter::send(stream, F("PTA%c%d\n"),Turnout::isClosed(id)?'2':'4',id ); + } break; case 'N': // Heartbeat (2), only send if connection completed by 'HU' message if (initSent) { @@ -194,7 +199,7 @@ void WiThrottle::parse(RingStream * stream, byte * cmdx) { if (cmd[1] == 'U') { StringFormatter::send(stream,F("VN2.0\nHTDCC-EX\nRL0\n")); StringFormatter::send(stream,F("HtDCC-EX v%S, %S, %S, %S\n"), F(VERSION), F(ARDUINO_TYPE), DCC::getMotorShieldName(), F(GITHUB_SHA)); - StringFormatter::send(stream,F("PTT]\\[Turnouts}|{Turnout]\\[Closed}|{2]\\[Thrown}|{4\n")); + StringFormatter::send(stream,F("PTT]\\[Turnouts}|{Turnout]\\[THROW}|{2]\\[CLOSE}|{4\n")); StringFormatter::send(stream,F("PPA%x\n"),DCCWaveform::mainTrack.getPowerMode()==POWERMODE::ON); lastPowerState = (DCCWaveform::mainTrack.getPowerMode()==POWERMODE::ON); //remember power state sent for comparison later StringFormatter::send(stream,F("*%d\n"),HEARTBEAT_SECONDS);