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:
parent
9d6931c438
commit
8a96791937
|
@ -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;
|
||||
|
|
27
EXRAIL2.cpp
27
EXRAIL2.cpp
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
22
LCN.cpp
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user