From 84a6e9759a8436cf01467bca863682b75b1bac78 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Wed, 27 May 2020 09:24:56 +0100 Subject: [PATCH] Turnouts... compiling --- JMRIParser.cpp | 35 ++-------- JMRITurnout.cpp | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ JMRITurnout.h | 26 ++++++++ 3 files changed, 205 insertions(+), 29 deletions(-) create mode 100644 JMRITurnout.cpp create mode 100644 JMRITurnout.h diff --git a/JMRIParser.cpp b/JMRIParser.cpp index e78d2b6..d7e59dd 100644 --- a/JMRIParser.cpp +++ b/JMRIParser.cpp @@ -1,5 +1,6 @@ #include "StringParser.h" #include "JMRIParser.h" +#include "JMRITurnout.h" #include "DCC.h" #include "DCCWaveform.h" @@ -60,7 +61,6 @@ void JMRIParser::parse(Stream & stream,const char *com) { */ DCC::setAccessory(p[0],p[1],p[2]); break; -#ifdef THIS_IS_NOT_YET_COMPLETE /***** CREATE/EDIT/REMOVE/SHOW & OPERATE A TURN-OUT ****/ case 'T': // @@ -75,35 +75,12 @@ void JMRIParser::parse(Stream & stream,const char *com) { * *** SEE ACCESSORIES.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "T" COMMAND * USED TO CREATE/EDIT/REMOVE/SHOW TURNOUT DEFINITIONS */ - - int n,s,m; - Turnout *t; - - switch(sscanf(com+1,"%d %d %d",&n,&s,&m)){ - - case 2: // argument is string with id number of turnout followed by zero (not thrown) or one (thrown) - t=Turnout::get(n); - if(t!=NULL) - t->activate(s, (DCC*) mainTrack); - else - CommManager::printf(""); - break; - - case 3: // argument is string with id number of turnout followed by an address and subAddress - Turnout::create(n,s,m,1); - break; - - case 1: // argument is a string with id number only - Turnout::remove(n); - break; - - case -1: // no arguments - Turnout::show(1); // verbose show - break; - } - + JMRITurnout::parse(stream,params,p); break; - + + + #ifdef THIS_IS_NOT_YET_COMPLETE + /***** CREATE/EDIT/REMOVE/SHOW & OPERATE AN OUTPUT PIN ****/ case 'Z': // diff --git a/JMRITurnout.cpp b/JMRITurnout.cpp new file mode 100644 index 0000000..5c6514b --- /dev/null +++ b/JMRITurnout.cpp @@ -0,0 +1,173 @@ +/********************************************************************** + +Accessories.cpp +COPYRIGHT (c) 2013-2016 Gregg E. Berman + +Part of DCC++ BASE STATION for the Arduino + +**********************************************************************/ +/********************************************************************** + +DCC++ BASE STATION can keep track of the direction of any turnout that is controlled +by a DCC stationary accessory decoder. All turnouts, as well as any other DCC accessories +connected in this fashion, can always be operated using the DCC BASE STATION Accessory command: + + + +However, this general command simply sends the appropriate DCC instruction packet to the main tracks +to operate connected accessories. It does not store or retain any information regarding the current +status of that accessory. + +To have this sketch store and retain the direction of DCC-connected turnouts, as well as automatically +invoke the required command as needed, first define/edit/delete such turnouts using the following +variations of the "T" command: + + : creates a new turnout ID, with specified ADDRESS and SUBADDRESS + if turnout ID already exists, it is updated with specificed ADDRESS and SUBADDRESS + returns: if successful and if unsuccessful (e.g. out of memory) + + : deletes definition of turnout ID + returns: if successful and if unsuccessful (e.g. ID does not exist) + + : lists all defined turnouts + returns: for each defined turnout or if no turnouts defined + +where + + ID: the numeric ID (0-32767) of the turnout to control + ADDRESS: the primary address of the decoder controlling this turnout (0-511) + SUBADDRESS: the subaddress of the decoder controlling this turnout (0-3) + +Once all turnouts have been properly defined, use the command to store their definitions to EEPROM. +If you later make edits/additions/deletions to the turnout definitions, you must invoke the command if you want those +new definitions updated in the EEPROM. You can also clear everything stored in the EEPROM by invoking the command. + +To "throw" turnouts that have been defined use: + + : sets turnout ID to either the "thrown" or "unthrown" position + returns: , or if turnout ID does not exist + +where + + ID: the numeric ID (0-32767) of the turnout to control + THROW: 0 (unthrown) or 1 (thrown) + +When controlled as such, the Arduino updates and stores the direction of each Turnout in EEPROM so +that it is retained even without power. A list of the current directions of each Turnout in the form is generated +by this sketch whenever the status command is invoked. This provides an efficient way of initializing +the directions of any Turnouts being monitored or controlled by a separate interface or GUI program. + +**********************************************************************/ + +//#include "EEStore.h" +//#include +#include "JMRITurnout.h" +#include "StringParser.h" +#include "DCC.h" + +void JMRITurnout::parse(Stream & stream, int params, int p[]) { + + switch(params){ + case 0: // + showAll(stream); // verbose show + return; + case 1: // + if (!remove(p[0])) break; + StringParser::send(stream,F("")); + return; + case 2: // + if (!activate(p[0],p[1])) break; + show(stream,p[0],false); + return; + + case 3: // + if (!create(p[0],p[1],p[2])) break; + StringParser::send(stream,F("")); + break; + default: + break; // will + } + StringParser::send(stream,F("")); +} + +///////////////// ALL PRIVATE BELOW HERE ////////////////// + JMRITurnout::TurnoutEntry JMRITurnout::table[JMRITurnout::MAX_TURNOUTS]; + + bool JMRITurnout::create(int id, int add, byte subAdd){ + if (id<0 || id>=MAX_TURNOUTS || table[id].address!=0) return false; + table[id].address=add; + table[id].subAddress=subAdd; + table[id].thrown=false; + return true; +} + + +bool JMRITurnout::invalid(int id) { + return id<0 || id>=MAX_TURNOUTS || table[id].address==0; +} + +bool JMRITurnout::activate(int id,bool thrown){ + if (invalid(id)) return false; + table[id].thrown=thrown; + DCC::setAccessory(table[id].address,table[id].subAddress,table[id].thrown); + return true; +} + +bool JMRITurnout::remove(int id){ + if (invalid(id)) return false; + table[id].address=0; + return true; +} + + +bool JMRITurnout::show(Stream & stream ,int id, bool all){ + if (invalid(id)) return false; + if (all) StringParser::send(stream, F(""), + id, table[id].address, + table[id].subAddress, table[id].thrown); + else StringParser::send(stream, F(""), + id, table[id].thrown); + return true; +} + +void JMRITurnout::showAll(Stream & stream ){ + for (int id=0;iddata.nTurnouts;i++){ + EEPROM.get(EEStore::pointer(),data); + tt=create(data.id,data.address,data.subAddress); + tt->data.tStatus=data.tStatus; + tt->num=EEStore::pointer(); + EEStore::advance(sizeof(tt->data)); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void Turnout::store(){ + Turnout *tt; + + tt=firstTurnout; + EEStore::eeStore->data.nTurnouts=0; + + while(tt!=NULL){ + tt->num=EEStore::pointer(); + EEPROM.put(EEStore::pointer(),tt->data); + EEStore::advance(sizeof(tt->data)); + tt=tt->nextTurnout; + EEStore::eeStore->data.nTurnouts++; + } + +} +#endif +/////////////////////////////////////////////////////////////////////////////// diff --git a/JMRITurnout.h b/JMRITurnout.h new file mode 100644 index 0000000..a14ab3a --- /dev/null +++ b/JMRITurnout.h @@ -0,0 +1,26 @@ +#include + +class JMRITurnout { + + public: + static void parse(Stream & stream, int params, int p[]); + + + + private: + + static void showAll(Stream & stream); + static bool show(Stream & stream ,int id, bool all); + static bool create(int id, int address, byte subAddress); + static bool remove(int id); + static bool activate(int id, bool thrown); + static bool invalid(int id); + + struct TurnoutEntry { + int address; + byte subAddress; + bool thrown; + }; + static const int MAX_TURNOUTS=50; + static TurnoutEntry table[MAX_TURNOUTS]; +};