mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-26 17:46:14 +01:00
UNTESTED ONRED/ONAMBER/ONGREEN
with genericl code tidy for other ON handlers.
This commit is contained in:
parent
044b467085
commit
d0e71875e0
151
EXRAIL2.cpp
151
EXRAIL2.cpp
|
@ -87,6 +87,9 @@ LookList * RMFT2::onThrowLookup=NULL;
|
||||||
LookList * RMFT2::onCloseLookup=NULL;
|
LookList * RMFT2::onCloseLookup=NULL;
|
||||||
LookList * RMFT2::onActivateLookup=NULL;
|
LookList * RMFT2::onActivateLookup=NULL;
|
||||||
LookList * RMFT2::onDeactivateLookup=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_OPCODE GETFLASH(RMFT2::RouteCode+progCounter)
|
||||||
#define GET_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3))
|
#define GET_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3))
|
||||||
|
@ -116,56 +119,40 @@ int16_t LookList::find(int16_t value) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void RMFT2::begin() {
|
LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
||||||
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
|
|
||||||
for (int f=0;f<MAX_FLAGS;f++) flags[f]=0;
|
|
||||||
int progCounter;
|
int progCounter;
|
||||||
|
int16_t count=0;
|
||||||
// counters to create lookup arrays
|
// find size for list
|
||||||
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
|
|
||||||
for (progCounter=0;; SKIPOP) {
|
for (progCounter=0;; SKIPOP) {
|
||||||
byte opcode=GET_OPCODE;
|
byte opcode=GET_OPCODE;
|
||||||
if (opcode==OPCODE_ENDEXRAIL) break;
|
if (opcode==OPCODE_ENDEXRAIL) break;
|
||||||
switch (opcode) {
|
if (opcode==op1 || opcode==op2 || opcode==op3) count++;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// 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
|
// create lookups
|
||||||
sequenceLookup=new LookList(sequenceCount);
|
sequenceLookup=LookListLoader(OPCODE_ROUTE, OPCODE_AUTOMATION,OPCODE_SEQUENCE);
|
||||||
onThrowLookup=new LookList(onThrowCount);
|
onThrowLookup=LookListLoader(OPCODE_ONTHROW);
|
||||||
onCloseLookup=new LookList(onCloseCount);
|
onCloseLookup=LookListLoader(OPCODE_ONCLOSE);
|
||||||
onActivateLookup=new LookList(onActivateCount);
|
onActivateLookup=LookListLoader(OPCODE_ONACTIVATE);
|
||||||
onDeactivateLookup=new LookList(onDeactivateCount);
|
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
|
// Second pass startup, define any turnouts or servos, set signals red
|
||||||
// add sequences onRoutines to the lookups
|
// add sequences onRoutines to the lookups
|
||||||
|
@ -175,6 +162,7 @@ int16_t LookList::find(int16_t value) {
|
||||||
doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED);
|
doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int progCounter;
|
||||||
for (progCounter=0;; SKIPOP){
|
for (progCounter=0;; SKIPOP){
|
||||||
byte opcode=GET_OPCODE;
|
byte opcode=GET_OPCODE;
|
||||||
if (opcode==OPCODE_ENDEXRAIL) break;
|
if (opcode==OPCODE_ENDEXRAIL) break;
|
||||||
|
@ -215,32 +203,11 @@ int16_t LookList::find(int16_t value) {
|
||||||
setTurnoutHiddenState(VpinTurnout::create(id,pin));
|
setTurnoutHiddenState(VpinTurnout::create(id,pin));
|
||||||
break;
|
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:
|
case OPCODE_AUTOSTART:
|
||||||
// automatically create a task from here at startup.
|
// 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;
|
break;
|
||||||
|
|
||||||
default: // Ignore
|
default: // Ignore
|
||||||
|
@ -249,9 +216,7 @@ int16_t LookList::find(int16_t value) {
|
||||||
}
|
}
|
||||||
SKIPOP; // include ENDROUTES opcode
|
SKIPOP; // include ENDROUTES opcode
|
||||||
|
|
||||||
DIAG(F("EXRAIL %db, fl=%d seq=%d, onT=%d, onC=%d"),
|
DIAG(F("EXRAIL %db, fl=%d"),progCounter,MAX_FLAGS);
|
||||||
progCounter,MAX_FLAGS,
|
|
||||||
sequenceCount, onThrowCount, onCloseCount);
|
|
||||||
|
|
||||||
new RMFT2(0); // add the startup route
|
new RMFT2(0); // add the startup route
|
||||||
}
|
}
|
||||||
|
@ -461,7 +426,7 @@ RMFT2::RMFT2(int progCtr) {
|
||||||
invert=false;
|
invert=false;
|
||||||
timeoutFlag=false;
|
timeoutFlag=false;
|
||||||
stackDepth=0;
|
stackDepth=0;
|
||||||
onTurnoutId=-1; // Not handling an ONTHROW/ONCLOSE
|
onEventStartPosition=-1; // Not handling an ONxxx
|
||||||
|
|
||||||
// chain into ring of RMFTs
|
// chain into ring of RMFTs
|
||||||
if (loopTask==NULL) {
|
if (loopTask==NULL) {
|
||||||
|
@ -1013,6 +978,13 @@ int16_t RMFT2::getSignalSlot(VPIN id) {
|
||||||
}
|
}
|
||||||
/* static */ void RMFT2::doSignal(VPIN id,char rag) {
|
/* static */ void RMFT2::doSignal(VPIN id,char rag) {
|
||||||
if (diag) DIAG(F(" doSignal %d %x"),id,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);
|
int16_t sigslot=getSignalSlot(id);
|
||||||
if (sigslot<0) return;
|
if (sigslot<0) return;
|
||||||
|
|
||||||
|
@ -1027,6 +999,7 @@ int16_t RMFT2::getSignalSlot(VPIN id) {
|
||||||
VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+3);
|
VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+3);
|
||||||
if (diag) DIAG(F("signal %d %d %d %d"),sigid,redpin,amberpin,greenpin);
|
if (diag) DIAG(F("signal %d %d %d %d"),sigid,redpin,amberpin,greenpin);
|
||||||
|
|
||||||
|
|
||||||
if (sigid & SERVO_SIGNAL_FLAG) {
|
if (sigid & SERVO_SIGNAL_FLAG) {
|
||||||
// A servo signal, the pin numbers are actually servo positions
|
// A servo signal, the pin numbers are actually servo positions
|
||||||
// Note, setting a signal to a zero position has no effect.
|
// 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) {
|
void RMFT2::turnoutEvent(int16_t turnoutId, bool closed) {
|
||||||
// Hunt for an ONTHROW/ONCLOSE for this turnout
|
// Hunt for an ONTHROW/ONCLOSE for this turnout
|
||||||
int pc= (closed?onCloseLookup:onThrowLookup)->find(turnoutId);
|
if (closed) handleEvent(F("CLOSE"),onCloseLookup,turnoutId);
|
||||||
if (pc<0) return;
|
else handleEvent(F("THROW"),onThrowLookup,turnoutId);
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RMFT2::activateEvent(int16_t addr, bool activate) {
|
void RMFT2::activateEvent(int16_t addr, bool activate) {
|
||||||
// Hunt for an ONACTIVATE/ONDEACTIVATE for this accessory
|
// 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;
|
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;
|
RMFT2 * task=loopTask;
|
||||||
while(task) {
|
while(task) {
|
||||||
if (task->onActivateAddr==addr) {
|
if (task->onEventStartPosition==pc) {
|
||||||
DIAG(F("Recursive ON(DE)ACTIVATE for %d"),addr);
|
DIAG(F("Recursive ON%S(%d)"),reason, id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
task=task->next;
|
task=task->next;
|
||||||
if (task==loopTask) break;
|
if (task==loopTask) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
task->onActivateAddr=addr; // flag for recursion detector
|
|
||||||
task=new RMFT2(pc); // new task starts at this instruction
|
task=new RMFT2(pc); // new task starts at this instruction
|
||||||
|
task->onEventStartPosition=pc; // flag for recursion detector
|
||||||
}
|
}
|
||||||
|
|
||||||
void RMFT2::printMessage2(const FSH * msg) {
|
void RMFT2::printMessage2(const FSH * msg) {
|
||||||
DIAG(F("EXRAIL(%d) %S"),loco,msg);
|
DIAG(F("EXRAIL(%d) %S"),loco,msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
15
EXRAIL2.h
15
EXRAIL2.h
|
@ -53,6 +53,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
|
||||||
OPCODE_ROUTE,OPCODE_AUTOMATION,OPCODE_SEQUENCE,
|
OPCODE_ROUTE,OPCODE_AUTOMATION,OPCODE_SEQUENCE,
|
||||||
OPCODE_ENDTASK,OPCODE_ENDEXRAIL,
|
OPCODE_ENDTASK,OPCODE_ENDEXRAIL,
|
||||||
OPCODE_SET_TRACK,
|
OPCODE_SET_TRACK,
|
||||||
|
OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN,
|
||||||
|
|
||||||
// OPcodes below this point are skip-nesting IF operations
|
// OPcodes below this point are skip-nesting IF operations
|
||||||
// placed here so that they may be skipped as a group
|
// 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_IFTIMEOUT,
|
||||||
OPCODE_IF,OPCODE_IFNOT,
|
OPCODE_IF,OPCODE_IFNOT,
|
||||||
OPCODE_IFRANDOM,OPCODE_IFRESERVE,
|
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 bool isSignal(VPIN id,char rag);
|
||||||
static int16_t getSignalSlot(VPIN id);
|
static int16_t getSignalSlot(VPIN id);
|
||||||
static void setTurnoutHiddenState(Turnout * t);
|
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 * loopTask;
|
||||||
static RMFT2 * pausingTask;
|
static RMFT2 * pausingTask;
|
||||||
void delayMe(long millisecs);
|
void delayMe(long millisecs);
|
||||||
|
@ -144,7 +148,6 @@ private:
|
||||||
void printMessage(uint16_t id); // Built by RMFTMacros.h
|
void printMessage(uint16_t id); // Built by RMFTMacros.h
|
||||||
void printMessage2(const FSH * msg);
|
void printMessage2(const FSH * msg);
|
||||||
|
|
||||||
|
|
||||||
static bool diag;
|
static bool diag;
|
||||||
static const FLASH byte RouteCode[];
|
static const FLASH byte RouteCode[];
|
||||||
static const FLASH int16_t SignalDefinitions[];
|
static const FLASH int16_t SignalDefinitions[];
|
||||||
|
@ -154,7 +157,10 @@ private:
|
||||||
static LookList * onCloseLookup;
|
static LookList * onCloseLookup;
|
||||||
static LookList * onActivateLookup;
|
static LookList * onActivateLookup;
|
||||||
static LookList * onDeactivateLookup;
|
static LookList * onDeactivateLookup;
|
||||||
|
static LookList * onRedLookup;
|
||||||
|
static LookList * onAmberLookup;
|
||||||
|
static LookList * onGreenLookup;
|
||||||
|
|
||||||
|
|
||||||
// Local variables - exist for each instance/task
|
// Local variables - exist for each instance/task
|
||||||
RMFT2 *next; // loop chain
|
RMFT2 *next; // loop chain
|
||||||
|
@ -172,8 +178,7 @@ private:
|
||||||
bool forward;
|
bool forward;
|
||||||
bool invert;
|
bool invert;
|
||||||
byte speedo;
|
byte speedo;
|
||||||
int16_t onTurnoutId;
|
int onEventStartPosition;
|
||||||
int16_t onActivateAddr;
|
|
||||||
byte stackDepth;
|
byte stackDepth;
|
||||||
int callStack[MAX_STACK_DEPTH];
|
int callStack[MAX_STACK_DEPTH];
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,9 +79,12 @@
|
||||||
#undef LCN
|
#undef LCN
|
||||||
#undef ONACTIVATE
|
#undef ONACTIVATE
|
||||||
#undef ONACTIVATEL
|
#undef ONACTIVATEL
|
||||||
|
#undef ONAMBER
|
||||||
#undef ONDEACTIVATE
|
#undef ONDEACTIVATE
|
||||||
#undef ONDEACTIVATEL
|
#undef ONDEACTIVATEL
|
||||||
#undef ONCLOSE
|
#undef ONCLOSE
|
||||||
|
#undef ONGREEN
|
||||||
|
#undef ONRED
|
||||||
#undef ONTHROW
|
#undef ONTHROW
|
||||||
#undef PARSE
|
#undef PARSE
|
||||||
#undef PAUSE
|
#undef PAUSE
|
||||||
|
@ -183,9 +186,12 @@
|
||||||
#define LCN(msg)
|
#define LCN(msg)
|
||||||
#define ONACTIVATE(addr,subaddr)
|
#define ONACTIVATE(addr,subaddr)
|
||||||
#define ONACTIVATEL(linear)
|
#define ONACTIVATEL(linear)
|
||||||
|
#define ONAMBER(signal_id)
|
||||||
#define ONDEACTIVATE(addr,subaddr)
|
#define ONDEACTIVATE(addr,subaddr)
|
||||||
#define ONDEACTIVATEL(linear)
|
#define ONDEACTIVATEL(linear)
|
||||||
#define ONCLOSE(turnout_id)
|
#define ONCLOSE(turnout_id)
|
||||||
|
#define ONGREEN(signal_id)
|
||||||
|
#define ONRED(signal_id)
|
||||||
#define ONTHROW(turnout_id)
|
#define ONTHROW(turnout_id)
|
||||||
#define PAUSE
|
#define PAUSE
|
||||||
#define PIN_TURNOUT(id,pin,description...)
|
#define PIN_TURNOUT(id,pin,description...)
|
||||||
|
|
|
@ -263,9 +263,12 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = {
|
||||||
#define LCN(msg) PRINT(msg)
|
#define LCN(msg) PRINT(msg)
|
||||||
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
|
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
|
||||||
#define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3),
|
#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 ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id),
|
||||||
#define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr),
|
#define ONDEACTIVATE(addr,subaddr) OPCODE_ONDEACTIVATE,V(addr<<2|subaddr),
|
||||||
#define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3),
|
#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 ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id),
|
||||||
#define PAUSE OPCODE_PAUSE,0,0,
|
#define PAUSE OPCODE_PAUSE,0,0,
|
||||||
#define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin),
|
#define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user