1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-27 06:11:25 +01:00

UNTESTED ONRED/ONAMBER/ONGREEN

with genericl code tidy for other ON handlers.
This commit is contained in:
Asbelos 2022-06-17 11:48:37 +01:00
parent 044b467085
commit d0e71875e0
4 changed files with 76 additions and 99 deletions

View File

@ -87,6 +87,9 @@ LookList * RMFT2::onThrowLookup=NULL;
LookList * RMFT2::onCloseLookup=NULL;
LookList * RMFT2::onActivateLookup=NULL;
LookList * RMFT2::onDeactivateLookup=NULL;
LookList * RMFT2::onRedLookup=NULL;
LookList * RMFT2::onAmberLookup=NULL;
LookList * RMFT2::onGreenLookup=NULL;
#define GET_OPCODE GETFLASH(RMFT2::RouteCode+progCounter)
#define GET_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3))
@ -116,56 +119,40 @@ int16_t LookList::find(int16_t value) {
return -1;
}
/* static */ void RMFT2::begin() {
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
for (int f=0;f<MAX_FLAGS;f++) flags[f]=0;
LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
int progCounter;
// counters to create lookup arrays
int sequenceCount=0; // to allow for seq 0 at start
int onThrowCount=0;
int onCloseCount=0;
int onActivateCount=0;
int onDeactivateCount=0;
// first pass count sizes for fast lookup arrays
int16_t count=0;
// find size for list
for (progCounter=0;; SKIPOP) {
byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break;
switch (opcode) {
case OPCODE_ROUTE:
case OPCODE_AUTOMATION:
case OPCODE_SEQUENCE:
sequenceCount++;
break;
case OPCODE_ONTHROW:
onThrowCount++;
break;
case OPCODE_ONCLOSE:
onCloseCount++;
break;
case OPCODE_ONACTIVATE:
onActivateCount++;
break;
case OPCODE_ONDEACTIVATE:
onDeactivateCount++;
break;
default: // Ignore
break;
}
if (opcode==op1 || opcode==op2 || opcode==op3) count++;
}
// create list
LookList* list=new LookList(count);
if (count==0) return list;
for (progCounter=0;; SKIPOP) {
byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break;
if (opcode==op1 || opcode==op2 || opcode==op3) list->add(GET_OPERAND(0),progCounter);
}
return list;
}
/* static */ void RMFT2::begin() {
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
for (int f=0;f<MAX_FLAGS;f++) flags[f]=0;
// create lookups
sequenceLookup=new LookList(sequenceCount);
onThrowLookup=new LookList(onThrowCount);
onCloseLookup=new LookList(onCloseCount);
onActivateLookup=new LookList(onActivateCount);
onDeactivateLookup=new LookList(onDeactivateCount);
sequenceLookup=LookListLoader(OPCODE_ROUTE, OPCODE_AUTOMATION,OPCODE_SEQUENCE);
onThrowLookup=LookListLoader(OPCODE_ONTHROW);
onCloseLookup=LookListLoader(OPCODE_ONCLOSE);
onActivateLookup=LookListLoader(OPCODE_ONACTIVATE);
onDeactivateLookup=LookListLoader(OPCODE_ONDEACTIVATE);
onRedLookup=LookListLoader(OPCODE_ONRED);
onAmberLookup=LookListLoader(OPCODE_ONAMBER);
onGreenLookup=LookListLoader(OPCODE_ONGREEN);
// Second pass startup, define any turnouts or servos, set signals red
// add sequences onRoutines to the lookups
@ -175,6 +162,7 @@ int16_t LookList::find(int16_t value) {
doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED);
}
int progCounter;
for (progCounter=0;; SKIPOP){
byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break;
@ -215,32 +203,11 @@ int16_t LookList::find(int16_t value) {
setTurnoutHiddenState(VpinTurnout::create(id,pin));
break;
}
case OPCODE_ROUTE:
case OPCODE_AUTOMATION:
case OPCODE_SEQUENCE:
sequenceLookup->add(operand,progCounter);
break;
case OPCODE_ONTHROW:
onThrowLookup->add(operand,progCounter);
break;
case OPCODE_ONCLOSE:
onCloseLookup->add(operand,progCounter);
break;
case OPCODE_ONACTIVATE:
onActivateLookup->add(operand,progCounter);
break;
case OPCODE_ONDEACTIVATE:
onDeactivateLookup->add(operand,progCounter);
break;
case OPCODE_AUTOSTART:
// automatically create a task from here at startup.
new RMFT2(progCounter);
// but we will do one at 0 anyway by default.
if (progCounter>0) new RMFT2(progCounter);
break;
default: // Ignore
@ -249,9 +216,7 @@ int16_t LookList::find(int16_t value) {
}
SKIPOP; // include ENDROUTES opcode
DIAG(F("EXRAIL %db, fl=%d seq=%d, onT=%d, onC=%d"),
progCounter,MAX_FLAGS,
sequenceCount, onThrowCount, onCloseCount);
DIAG(F("EXRAIL %db, fl=%d"),progCounter,MAX_FLAGS);
new RMFT2(0); // add the startup route
}
@ -461,7 +426,7 @@ RMFT2::RMFT2(int progCtr) {
invert=false;
timeoutFlag=false;
stackDepth=0;
onTurnoutId=-1; // Not handling an ONTHROW/ONCLOSE
onEventStartPosition=-1; // Not handling an ONxxx
// chain into ring of RMFTs
if (loopTask==NULL) {
@ -1013,6 +978,13 @@ int16_t RMFT2::getSignalSlot(VPIN id) {
}
/* static */ void RMFT2::doSignal(VPIN id,char rag) {
if (diag) DIAG(F(" doSignal %d %x"),id,rag);
// Schedule any event handler for this signal change.
// Thjis will work even without a signal definition.
if (rag==SIGNAL_RED) handleEvent(F("RED"),onRedLookup,id);
else if (rag==SIGNAL_GREEN) handleEvent(F("GREEN"), onGreenLookup,id);
else handleEvent(F("AMBER"), onAmberLookup,id);
int16_t sigslot=getSignalSlot(id);
if (sigslot<0) return;
@ -1027,6 +999,7 @@ int16_t RMFT2::getSignalSlot(VPIN id) {
VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+3);
if (diag) DIAG(F("signal %d %d %d %d"),sigid,redpin,amberpin,greenpin);
if (sigid & SERVO_SIGNAL_FLAG) {
// A servo signal, the pin numbers are actually servo positions
// Note, setting a signal to a zero position has no effect.
@ -1059,46 +1032,36 @@ int16_t RMFT2::getSignalSlot(VPIN id) {
void RMFT2::turnoutEvent(int16_t turnoutId, bool closed) {
// Hunt for an ONTHROW/ONCLOSE for this turnout
int pc= (closed?onCloseLookup:onThrowLookup)->find(turnoutId);
if (pc<0) return;
// Check we dont already have a task running this turnout
RMFT2 * task=loopTask;
while(task) {
if (task->onTurnoutId==turnoutId) {
DIAG(F("Recursive ONTHROW/ONCLOSE for Turnout %d"),turnoutId);
return;
}
task=task->next;
if (task==loopTask) break;
}
task=new RMFT2(pc); // new task starts at this instruction
task->onTurnoutId=turnoutId; // flag for recursion detector
if (closed) handleEvent(F("CLOSE"),onCloseLookup,turnoutId);
else handleEvent(F("THROW"),onThrowLookup,turnoutId);
}
void RMFT2::activateEvent(int16_t addr, bool activate) {
// Hunt for an ONACTIVATE/ONDEACTIVATE for this accessory
int pc= (activate?onActivateLookup:onDeactivateLookup)->find(addr);
if (activate) handleEvent(F("ACTIVATE"),onActivateLookup,addr);
else handleEvent(F("DEACTIVATE"),onDeactivateLookup,addr);
}
void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) {
int pc= handlers->find(id);
if (pc<0) return;
// Check we dont already have a task running this address
// Check we dont already have a task running this handler
RMFT2 * task=loopTask;
while(task) {
if (task->onActivateAddr==addr) {
DIAG(F("Recursive ON(DE)ACTIVATE for %d"),addr);
if (task->onEventStartPosition==pc) {
DIAG(F("Recursive ON%S(%d)"),reason, id);
return;
}
task=task->next;
if (task==loopTask) break;
}
task->onActivateAddr=addr; // flag for recursion detector
task=new RMFT2(pc); // new task starts at this instruction
task->onEventStartPosition=pc; // flag for recursion detector
}
void RMFT2::printMessage2(const FSH * msg) {
DIAG(F("EXRAIL(%d) %S"),loco,msg);
}

View File

@ -53,6 +53,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_ROUTE,OPCODE_AUTOMATION,OPCODE_SEQUENCE,
OPCODE_ENDTASK,OPCODE_ENDEXRAIL,
OPCODE_SET_TRACK,
OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN,
// OPcodes below this point are skip-nesting IF operations
// placed here so that they may be skipped as a group
@ -63,7 +64,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_IFTIMEOUT,
OPCODE_IF,OPCODE_IFNOT,
OPCODE_IFRANDOM,OPCODE_IFRESERVE,
OPCODE_IFCLOSED, OPCODE_IFTHROWN
OPCODE_IFCLOSED,OPCODE_IFTHROWN
};
@ -132,6 +133,9 @@ private:
static bool isSignal(VPIN id,char rag);
static int16_t getSignalSlot(VPIN id);
static void setTurnoutHiddenState(Turnout * t);
static LookList* LookListLoader(OPCODE op1,
OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL);
static void handleEvent(const FSH* reason,LookList* handlers, int16_t id);
static RMFT2 * loopTask;
static RMFT2 * pausingTask;
void delayMe(long millisecs);
@ -144,7 +148,6 @@ private:
void printMessage(uint16_t id); // Built by RMFTMacros.h
void printMessage2(const FSH * msg);
static bool diag;
static const FLASH byte RouteCode[];
static const FLASH int16_t SignalDefinitions[];
@ -154,7 +157,10 @@ private:
static LookList * onCloseLookup;
static LookList * onActivateLookup;
static LookList * onDeactivateLookup;
static LookList * onRedLookup;
static LookList * onAmberLookup;
static LookList * onGreenLookup;
// Local variables - exist for each instance/task
RMFT2 *next; // loop chain
@ -172,8 +178,7 @@ private:
bool forward;
bool invert;
byte speedo;
int16_t onTurnoutId;
int16_t onActivateAddr;
int onEventStartPosition;
byte stackDepth;
int callStack[MAX_STACK_DEPTH];
};

View File

@ -79,9 +79,12 @@
#undef LCN
#undef ONACTIVATE
#undef ONACTIVATEL
#undef ONAMBER
#undef ONDEACTIVATE
#undef ONDEACTIVATEL
#undef ONCLOSE
#undef ONGREEN
#undef ONRED
#undef ONTHROW
#undef PARSE
#undef PAUSE
@ -183,9 +186,12 @@
#define LCN(msg)
#define ONACTIVATE(addr,subaddr)
#define ONACTIVATEL(linear)
#define ONAMBER(signal_id)
#define ONDEACTIVATE(addr,subaddr)
#define ONDEACTIVATEL(linear)
#define ONCLOSE(turnout_id)
#define ONGREEN(signal_id)
#define ONRED(signal_id)
#define ONTHROW(turnout_id)
#define PAUSE
#define PIN_TURNOUT(id,pin,description...)

View File

@ -263,9 +263,12 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = {
#define LCN(msg) PRINT(msg)
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
#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 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),
#define ONRED(signal_id) OPCODE_ONRED,V(signal_id),
#define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id),
#define PAUSE OPCODE_PAUSE,0,0,
#define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin),