1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-22 15:46:14 +01:00

ONBLOCKENTER/EXIT

This commit is contained in:
Asbelos 2022-08-18 22:38:20 +01:00
parent 9d6931c438
commit 8a96791937
7 changed files with 67 additions and 6 deletions

View File

@ -343,6 +343,15 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
return;
break;
case 'k': // <k blockid cabid> exiting block
case 'K': // <K blockid cabid> entering block
if (params!=2) break;
#ifdef EXRAIL_ACTIVE
// without EXrail, valid block commands are ignored
RMFT2::blockEvent(p[0],p[1],opcode=='K');
#endif
return;
case 'w': // WRITE CV on MAIN <w CAB CV VALUE>
DCC::writeCVByteMain(p[0], p[1], p[2]);
return;

View File

@ -90,6 +90,8 @@ LookList * RMFT2::onDeactivateLookup=NULL;
LookList * RMFT2::onRedLookup=NULL;
LookList * RMFT2::onAmberLookup=NULL;
LookList * RMFT2::onGreenLookup=NULL;
LookList * RMFT2::onBlockEnterLookup=NULL;
LookList * RMFT2::onBlockExitLookup=NULL;
#define GET_OPCODE GETFLASH(RMFT2::RouteCode+progCounter)
#define GET_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3))
@ -153,7 +155,9 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
onRedLookup=LookListLoader(OPCODE_ONRED);
onAmberLookup=LookListLoader(OPCODE_ONAMBER);
onGreenLookup=LookListLoader(OPCODE_ONGREEN);
onBlockEnterLookup=LookListLoader(OPCODE_ONBLOCKENTER);
onBlockExitLookup=LookListLoader(OPCODE_ONBLOCKEXIT);
// Second pass startup, define any turnouts or servos, set signals red
// add sequences onRoutines to the lookups
for (int sigpos=0;;sigpos+=4) {
@ -923,6 +927,8 @@ void RMFT2::loop2() {
case OPCODE_ONCLOSE: // Turnout event catchers ignored here
case OPCODE_ONTHROW:
case OPCODE_ONACTIVATE: // Activate event catchers ignored here
case OPCODE_ONBLOCKENTER:
case OPCODE_ONBLOCKEXIT:
case OPCODE_ONDEACTIVATE:
case OPCODE_ONRED:
case OPCODE_ONAMBER:
@ -1052,17 +1058,29 @@ void RMFT2::activateEvent(int16_t addr, bool activate) {
if (activate) handleEvent(F("ACTIVATE"),onActivateLookup,addr);
else handleEvent(F("DEACTIVATE"),onDeactivateLookup,addr);
}
void RMFT2::blockEvent(int16_t blockId, int16_t locoid, bool enterBlock) {
RMFT2 * task=enterBlock
? handleEvent(F("BLOCKENTER"),onBlockEnterLookup,blockId)
: handleEvent(F("BLOCKEXIT"),onBlockExitLookup,blockId);
if (task) {
// set task info from locoid
byte speed=DCC::getThrottleSpeedByte(locoid);
task->speedo=speed & 0x7f;
task->forward=speed >> 7;
}
}
void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) {
RMFT2 * RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) {
int pc= handlers->find(id);
if (pc<0) return;
if (pc<0) return NULL;
// Check we dont already have a task running this handler
RMFT2 * task=loopTask;
while(task) {
if (task->onEventStartPosition==pc) {
DIAG(F("Recursive ON%S(%d)"),reason, id);
return;
return NULL;
}
task=task->next;
if (task==loopTask) break;
@ -1070,6 +1088,7 @@ void RMFT2::handleEvent(const FSH* reason,LookList* handlers, int16_t id) {
task=new RMFT2(pc); // new task starts at this instruction
task->onEventStartPosition=pc; // flag for recursion detector
return task;
}
void RMFT2::printMessage2(const FSH * msg) {

View File

@ -54,6 +54,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_ENDTASK,OPCODE_ENDEXRAIL,
OPCODE_SET_TRACK,
OPCODE_ONRED,OPCODE_ONAMBER,OPCODE_ONGREEN,
OPCODE_ONBLOCKENTER,OPCODE_ONBLOCKEXIT,
// OPcodes below this point are skip-nesting IF operations
// placed here so that they may be skipped as a group
@ -107,6 +108,8 @@ class LookList {
static void createNewTask(int route, uint16_t cab);
static void turnoutEvent(int16_t id, bool closed);
static void activateEvent(int16_t addr, bool active);
static void blockEvent(int16_t blockId, int16_t locoid, bool enterBlock);
static const int16_t SERVO_SIGNAL_FLAG=0x4000;
static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000;
static const int16_t DCC_SIGNAL_FLAG=0x1000;
@ -136,7 +139,7 @@ private:
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 * handleEvent(const FSH* reason,LookList* handlers, int16_t id);
static RMFT2 * loopTask;
static RMFT2 * pausingTask;
void delayMe(long millisecs);
@ -161,6 +164,8 @@ private:
static LookList * onRedLookup;
static LookList * onAmberLookup;
static LookList * onGreenLookup;
static LookList * onBlockEnterLookup;
static LookList * onBlockExitLookup;
// Local variables - exist for each instance/task

View File

@ -82,6 +82,8 @@
#undef ONACTIVATE
#undef ONACTIVATEL
#undef ONAMBER
#undef ONBLOCKENTER
#undef ONBLOCKEXIT
#undef ONDEACTIVATE
#undef ONDEACTIVATEL
#undef ONCLOSE
@ -192,6 +194,8 @@
#define ONACTIVATE(addr,subaddr)
#define ONACTIVATEL(linear)
#define ONAMBER(signal_id)
#define ONBLOCKENTER(blockid)
#define ONBLOCKEXIT(blockid)
#define ONDEACTIVATE(addr,subaddr)
#define ONDEACTIVATEL(linear)
#define ONCLOSE(turnout_id)

View File

@ -271,6 +271,8 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = {
#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 ONBLOCKENTER(blockid) OPCODE_ONBLOCKENTER,V(blockid),
#define ONBLOCKEXIT(blockid) OPCODE_ONBLOCKEXIT,V(blockid),
#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),

22
LCN.cpp
View File

@ -16,13 +16,17 @@
* You should have received a copy of the GNU General Public License
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
*/
#include "defines.h"
#include "LCN.h"
#include "DIAG.h"
#include "Turnouts.h"
#include "Sensors.h"
#include "EXRAIL2.h"
int LCN::id = 0;
int LCN::id1 = 0;
int LCN::id2 = 0;
Stream * LCN::stream=NULL;
bool LCN::firstLoop=true;
@ -46,6 +50,12 @@ void LCN::loop() {
if (ch >= 0 && ch <= '9') { // accumulate id value
id = 10 * id + ch - '0';
}
else if (ch == ',') {
// push stack for new number
id2=id1;
id1=id;
id=0;
}
else if (ch == 't' || ch == 'T') { // Turnout opcodes
if (Diag::LCN) DIAG(F("LCN IN %d%c"),id,(char)ch);
if (!Turnout::exists(id)) LCNTurnout::create(id);
@ -64,6 +74,16 @@ void LCN::loop() {
ss->setState(ch == 'S');
id = 0;
}
else if (ch == 'k' || ch == 'K') {
// block enter id1 by loco id
if (Diag::LCN) DIAG(F("LCN IN %d,%d%c"),id1,id,(char)ch);
#ifdef EXRAIL_ACTIVE
// without EXrail, valid block commands are ignored
RMFT2::blockEvent(id1,id,ch=='K');
#endif
id=0;
}
else id = 0; // ignore any other garbage from LCN
}
}

2
LCN.h
View File

@ -31,6 +31,8 @@ class LCN {
static bool firstLoop;
static Stream * stream;
static int id;
static int id1;
static int id2;
};
#endif