1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-03-14 18:13:09 +01:00

onblock...

This commit is contained in:
Asbelos 2024-08-06 14:14:11 +01:00
parent 0188fc6b22
commit 343a526241
5 changed files with 77 additions and 58 deletions

View File

@ -204,8 +204,12 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
onRotateLookup=LookListLoader(OPCODE_ONROTATE); onRotateLookup=LookListLoader(OPCODE_ONROTATE);
#endif #endif
onOverloadLookup=LookListLoader(OPCODE_ONOVERLOAD); onOverloadLookup=LookListLoader(OPCODE_ONOVERLOAD);
onBlockEnterLookup=LookListLoader(OPCODE_ONBLOCKENTER);
onBlockExitLookup=LookListLoader(OPCODE_ONBLOCKEXIT); if (compileFeatures & FEATURE_BLOCK) {
onBlockEnterLookup=LookListLoader(OPCODE_ONBLOCKENTER);
onBlockExitLookup=LookListLoader(OPCODE_ONBLOCKEXIT);
}
// onLCCLookup is not the same so not loaded here. // onLCCLookup is not the same so not loaded here.
// Second pass startup, define any turnouts or servos, set signals red // Second pass startup, define any turnouts or servos, set signals red
@ -370,7 +374,7 @@ char RMFT2::getRouteType(int16_t id) {
} }
RMFT2::RMFT2(int progCtr) { RMFT2::RMFT2(int progCtr, int16_t _loco) {
progCounter=progCtr; progCounter=progCtr;
// get an unused task id from the flags table // get an unused task id from the flags table
@ -383,9 +387,7 @@ RMFT2::RMFT2(int progCtr) {
} }
} }
delayTime=0; delayTime=0;
loco=0; loco=_loco;
speedo=0;
forward=true;
invert=false; invert=false;
blinkState=not_blink_task; blinkState=not_blink_task;
stackDepth=0; stackDepth=0;
@ -403,7 +405,10 @@ RMFT2::RMFT2(int progCtr) {
RMFT2::~RMFT2() { RMFT2::~RMFT2() {
driveLoco(1); // ESTOP my loco if any // estop my loco if this is not an ONevent
// (prevents DONE stopping loco at the end of an
// ONBLOCKENTER or ONBLOCKEXIT )
if (loco>0 && this->onEventStartPosition==-1) DCC::setThrottle(loco,1,DCC::getThrottleDirection(loco));
setFlag(taskId,0,TASK_FLAG); // we are no longer using this id setFlag(taskId,0,TASK_FLAG); // we are no longer using this id
if (next==this) if (next==this)
loopTask=NULL; loopTask=NULL;
@ -419,23 +424,9 @@ RMFT2::~RMFT2() {
void RMFT2::createNewTask(int route, uint16_t cab) { void RMFT2::createNewTask(int route, uint16_t cab) {
int pc=routeLookup->find(route); int pc=routeLookup->find(route);
if (pc<0) return; if (pc<0) return;
RMFT2* task=new RMFT2(pc); new RMFT2(pc,cab);
task->loco=cab;
} }
void RMFT2::driveLoco(byte speed) {
if (loco<=0) return; // Prevent broadcast!
//if (diag) DIAG(F("EXRAIL drive %d %d %d"),loco,speed,forward^invert);
/* TODO.....
power on appropriate track if DC or main if dcc
if (TrackManager::getMainPowerMode()==POWERMODE::OFF) {
TrackManager::setMainPower(POWERMODE::ON);
}
**********/
DCC::setThrottle(loco,speed, forward^invert);
speedo=speed;
}
bool RMFT2::readSensor(uint16_t sensorId) { bool RMFT2::readSensor(uint16_t sensorId) {
// Exrail operands are unsigned but we need the signed version as inserted by the macros. // Exrail operands are unsigned but we need the signed version as inserted by the macros.
@ -493,6 +484,15 @@ bool RMFT2::skipIfBlock() {
} }
} }
void RMFT2::pause() {
if (loco)
pauseSpeed=DCC::getThrottleSpeedByte(loco);
}
void RMFT2::resume() {
if (loco)
DCC::setThrottle(loco,pauseSpeed & 0x7f, pauseSpeed & 0x80);
}
void RMFT2::loop() { void RMFT2::loop() {
if (compileFeatures & FEATURE_SENSOR) if (compileFeatures & FEATURE_SENSOR)
EXRAILSensor::checkAll(); EXRAILSensor::checkAll();
@ -557,18 +557,15 @@ void RMFT2::loop2() {
#endif #endif
case OPCODE_REV: case OPCODE_REV:
forward = false; if (loco) DCC::setThrottle(loco,operand,invert);
driveLoco(operand);
break; break;
case OPCODE_FWD: case OPCODE_FWD:
forward = true; if (loco) DCC::setThrottle(loco,operand,!invert);
driveLoco(operand); break;
break;
case OPCODE_SPEED: case OPCODE_SPEED:
forward=DCC::getThrottleDirection(loco)^invert; if (loco) DCC::setThrottle(loco,operand,DCC::getThrottleDirection(loco));
driveLoco(operand);
break; break;
case OPCODE_MOMENTUM: case OPCODE_MOMENTUM:
@ -584,12 +581,11 @@ void RMFT2::loop2() {
case OPCODE_INVERT_DIRECTION: case OPCODE_INVERT_DIRECTION:
invert= !invert; invert= !invert;
driveLoco(speedo);
break; break;
case OPCODE_RESERVE: case OPCODE_RESERVE:
if (getFlag(operand,SECTION_FLAG)) { if (getFlag(operand,SECTION_FLAG)) {
driveLoco(0); if (loco) DCC::setThrottle(loco,0,DCC::getThrottleDirection(loco));
delayMe(500); delayMe(500);
return; return;
} }
@ -687,6 +683,10 @@ void RMFT2::loop2() {
break; break;
case OPCODE_PAUSE: case OPCODE_PAUSE:
// all tasks save their speed bytes
pause();
for (RMFT2 * t=next; t!=this;t=t->next) t->pause();
DCC::estopAll(); // pause all locos on the track DCC::estopAll(); // pause all locos on the track
pausingTask=this; pausingTask=this;
break; break;
@ -731,8 +731,8 @@ void RMFT2::loop2() {
case OPCODE_RESUME: case OPCODE_RESUME:
pausingTask=NULL; pausingTask=NULL;
driveLoco(speedo); resume();
for (RMFT2 * t=next; t!=this;t=t->next) if (t->loco >0) t->driveLoco(t->speedo); for (RMFT2 * t=next; t!=this;t=t->next) t->resume();
break; break;
case OPCODE_IF: // do next operand if sensor set case OPCODE_IF: // do next operand if sensor set
@ -843,8 +843,7 @@ void RMFT2::loop2() {
case OPCODE_DRIVE: case OPCODE_DRIVE:
{ {
byte analogSpeed=IODevice::readAnalogue(operand) *127 / 1024; // Non functional but reserved
if (speedo!=analogSpeed) driveLoco(analogSpeed);
break; break;
} }
@ -935,8 +934,6 @@ void RMFT2::loop2() {
} }
loco=progtrackLocoId; loco=progtrackLocoId;
speedo=0;
forward=true;
invert=false; invert=false;
break; break;
#endif #endif
@ -958,16 +955,13 @@ void RMFT2::loop2() {
{ {
int newPc=routeLookup->find(getOperand(1)); int newPc=routeLookup->find(getOperand(1));
if (newPc<0) break; if (newPc<0) break;
RMFT2* newtask=new RMFT2(newPc); // create new task new RMFT2(newPc,operand); // create new task
newtask->loco=operand;
} }
break; break;
case OPCODE_SETLOCO: case OPCODE_SETLOCO:
{ {
loco=operand; loco=operand;
speedo=0;
forward=true;
invert=false; invert=false;
} }
break; break;
@ -1091,7 +1085,8 @@ void RMFT2::loop2() {
case OPCODE_ONROTATE: case OPCODE_ONROTATE:
#endif #endif
case OPCODE_ONOVERLOAD: case OPCODE_ONOVERLOAD:
case OPCODE_ONBLOCKENTER:
case OPCODE_ONBLOCKEXIT:
break; break;
default: default:
@ -1286,9 +1281,11 @@ void RMFT2::activateEvent(int16_t addr, bool activate) {
} }
void RMFT2::blockEvent(int16_t block, int16_t loco, bool entering) { void RMFT2::blockEvent(int16_t block, int16_t loco, bool entering) {
if (compileFeatures & FEATURE_BLOCK) {
// Hunt for an ONBLOCKENTER/ONBLOCKEXIT for this accessory // Hunt for an ONBLOCKENTER/ONBLOCKEXIT for this accessory
if (entering) onBlockEnterLookup->handleEvent(F("BLOCKENTER"),block,loco); if (entering) onBlockEnterLookup->handleEvent(F("BLOCKENTER"),block,loco);
else onBlockExitLookup->handleEvent(F("BLOCKEXIT"),block,loco); else onBlockExitLookup->handleEvent(F("BLOCKEXIT"),block,loco);
}
} }
void RMFT2::changeEvent(int16_t vpin, bool change) { void RMFT2::changeEvent(int16_t vpin, bool change) {

View File

@ -161,8 +161,7 @@ class LookList {
public: public:
static void begin(); static void begin();
static void loop(); static void loop();
RMFT2(int progCounter); RMFT2(int progCounter, int16_t cab=0);
RMFT2(int route, uint16_t cab);
~RMFT2(); ~RMFT2();
static void readLocoCallback(int16_t cv); static void readLocoCallback(int16_t cv);
static void createNewTask(int route, uint16_t cab); static void createNewTask(int route, uint16_t cab);
@ -215,7 +214,6 @@ private:
static RMFT2 * loopTask; static RMFT2 * loopTask;
static RMFT2 * pausingTask; static RMFT2 * pausingTask;
void delayMe(long millisecs); void delayMe(long millisecs);
void driveLoco(byte speedo);
bool skipIfBlock(); bool skipIfBlock();
bool readLoco(); bool readLoco();
void loop2(); void loop2();
@ -224,6 +222,8 @@ private:
void printMessage2(const FSH * msg); void printMessage2(const FSH * msg);
void thrungeString(uint32_t strfar, thrunger mode, byte id=0); void thrungeString(uint32_t strfar, thrunger mode, byte id=0);
uint16_t getOperand(byte n); uint16_t getOperand(byte n);
void pause();
void resume();
static bool diag; static bool diag;
static const HIGHFLASH3 byte RouteCode[]; static const HIGHFLASH3 byte RouteCode[];
@ -271,9 +271,8 @@ private:
byte taskId; byte taskId;
BlinkState blinkState; // includes AT_TIMEOUT flag. BlinkState blinkState; // includes AT_TIMEOUT flag.
uint16_t loco; uint16_t loco;
bool forward;
bool invert; bool invert;
byte speedo; byte pauseSpeed;
int onEventStartPosition; int onEventStartPosition;
byte stackDepth; byte stackDepth;
int callStack[MAX_STACK_DEPTH]; int callStack[MAX_STACK_DEPTH];

View File

@ -108,6 +108,8 @@
#undef ONACTIVATE #undef ONACTIVATE
#undef ONACTIVATEL #undef ONACTIVATEL
#undef ONAMBER #undef ONAMBER
#undef ONBLOCKENTER
#undef ONBLOCKEXIT
#undef ONDEACTIVATE #undef ONDEACTIVATE
#undef ONDEACTIVATEL #undef ONDEACTIVATEL
#undef ONCLOSE #undef ONCLOSE
@ -278,6 +280,8 @@
#define ONACTIVATE(addr,subaddr) #define ONACTIVATE(addr,subaddr)
#define ONACTIVATEL(linear) #define ONACTIVATEL(linear)
#define ONAMBER(signal_id) #define ONAMBER(signal_id)
#define ONBLOCKENTER(blockid)
#define ONBLOCKEXIT(blockid)
#define ONTIME(value) #define ONTIME(value)
#define ONCLOCKTIME(hours,mins) #define ONCLOCKTIME(hours,mins)
#define ONCLOCKMINS(mins) #define ONCLOCKMINS(mins)

View File

@ -210,6 +210,14 @@ void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16
default: default:
break; break;
} }
case 'K': // <K blockid loco> Block enter
case 'k': // <k blockid loco> Block exit
if (paramCount!=2) break;
blockEvent(p[0],p[1],opcode=='K');
opcode=0;
break;
default: // other commands pass through default: // other commands pass through
break; break;
} }
@ -228,11 +236,9 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
); );
} }
else { else {
StringFormatter::send(stream,F("\nID=%d,PC=%d,LOCO=%d%c,SPEED=%d%c"), StringFormatter::send(stream,F("\nID=%d,PC=%d,LOCO=%d %c"),
(int)(task->taskId),task->progCounter,task->loco, (int)(task->taskId),task->progCounter,task->loco,
task->invert?'I':' ', task->invert?'I':' '
task->speedo,
task->forward?'F':'R'
); );
} }
task=task->next; task=task->next;
@ -276,19 +282,27 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
switch (p[0]) { switch (p[0]) {
case "PAUSE"_hk: // </ PAUSE> case "PAUSE"_hk: // </ PAUSE>
if (paramCount!=1) return false; if (paramCount!=1) return false;
DCC::estopAll(); // pause all locos on the track { // pause all tasks
RMFT2 * task=loopTask;
while(task) {
task->pause();
task=task->next;
if (task==loopTask) break;
}
}
DCC::estopAll(); // stop all locos on the track
pausingTask=(RMFT2 *)1; // Impossible task address pausingTask=(RMFT2 *)1; // Impossible task address
return true; return true;
case "RESUME"_hk: // </ RESUME> case "RESUME"_hk: // </ RESUME>
if (paramCount!=1) return false; if (paramCount!=1) return false;
pausingTask=NULL; pausingTask=NULL;
{ { // resume all tasks
RMFT2 * task=loopTask; RMFT2 * task=loopTask;
while(task) { while(task) {
if (task->loco) task->driveLoco(task->speedo); task->resume();
task=task->next; task=task->next;
if (task==loopTask) break; if (task==loopTask) break;
} }
} }
return true; return true;
@ -301,8 +315,7 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
uint16_t cab=(paramCount==2)? 0 : p[1]; uint16_t cab=(paramCount==2)? 0 : p[1];
int pc=routeLookup->find(route); int pc=routeLookup->find(route);
if (pc<0) return false; if (pc<0) return false;
RMFT2* task=new RMFT2(pc); new RMFT2(pc,cab);
task->loco=cab;
} }
return true; return true;

View File

@ -222,6 +222,10 @@ bool exrailHalSetup() {
#define ONBUTTON(vpin) | FEATURE_SENSOR #define ONBUTTON(vpin) | FEATURE_SENSOR
#undef ONSENSOR #undef ONSENSOR
#define ONSENSOR(vpin) | FEATURE_SENSOR #define ONSENSOR(vpin) | FEATURE_SENSOR
#undef ONBLOCKENTER
#define ONBLOCKENTER(blockid) | FEATURE_BLOCK
#undef ONBLOCKEXIT
#define ONBLOCKEXIT(blockid) | FEATURE_BLOCK
const byte RMFT2::compileFeatures = 0 const byte RMFT2::compileFeatures = 0
#include "myAutomation.h" #include "myAutomation.h"
@ -556,6 +560,8 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#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 ONAMBER(signal_id) OPCODE_ONAMBER,V(signal_id),
#define ONBLOCKENTER(block_id) OPCODE_ONBLOCKENTER,V(block_id),
#define ONBLOCKEXIT(block_id) OPCODE_ONBLOCKEXIT,V(block_id),
#define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id), #define ONCLOSE(turnout_id) OPCODE_ONCLOSE,V(turnout_id),
#define ONLCC(sender,event) OPCODE_ONLCC,V(event),\ #define ONLCC(sender,event) OPCODE_ONLCC,V(event),\
OPCODE_PAD,V((((uint64_t)sender)>>32)&0xFFFF),\ OPCODE_PAD,V((((uint64_t)sender)>>32)&0xFFFF),\