1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-02-18 15:06:03 +01:00

Compare commits

..

No commits in common. "0712eef97a49981f62a0a7a9ece4aa67bf4cfc1c" and "77de25099619f0bf7060dd857127e312c3ecf3f5" have entirely different histories.

14 changed files with 123 additions and 162 deletions

View File

@ -1121,7 +1121,7 @@ bool DCCEXParser::parseC(Print *stream, int16_t params, int16_t p[]) {
DCC::setGlobalSpeedsteps(128); DCC::setGlobalSpeedsteps(128);
DIAG(F("128 Speedsteps")); DIAG(F("128 Speedsteps"));
return true; return true;
#if defined(HAS_ENOUGH_MEMORY) && !defined(ARDUINO_ARCH_UNO) && !defined(ARDUINO_ARCH_ESP32) #if defined(HAS_ENOUGH_MEMORY) && !defined(ARDUINO_ARCH_UNO)
case "RAILCOM"_hk: case "RAILCOM"_hk:
{ // <C RAILCOM ON|OFF|DEBUG > { // <C RAILCOM ON|OFF|DEBUG >
if (params<2) return false; if (params<2) return false;

View File

@ -84,7 +84,7 @@ void IRAM_ATTR interrupt(rmt_channel_t channel, void *t) {
DCCTimer::updateMinimumFreeMemoryISR(0); DCCTimer::updateMinimumFreeMemoryISR(0);
} }
RMTChannel::RMTChannel(Pinpair pins, bool isMain) { RMTChannel::RMTChannel(pinpair pins, bool isMain) {
byte ch; byte ch;
byte plen; byte plen;
@ -253,7 +253,7 @@ bool RMTChannel::addPin(byte pin, bool inverted) {
if (err != ESP_OK) return false; if (err != ESP_OK) return false;
return true; return true;
} }
bool RMTChannel::addPin(Pinpair pins) { bool RMTChannel::addPin(pinpair pins) {
return addPin(pins.pin) && addPin(pins.invpin, true); return addPin(pins.pin) && addPin(pins.invpin, true);
} }
#endif //ESP32 #endif //ESP32

View File

@ -23,7 +23,7 @@
#include "driver/rmt.h" #include "driver/rmt.h"
#include "soc/rmt_reg.h" #include "soc/rmt_reg.h"
#include "soc/rmt_struct.h" #include "soc/rmt_struct.h"
#include "Pinpair.h" // for class Pinpair #include "MotorDriver.h" // for class pinpair
// make calculations easy and set up for microseconds // make calculations easy and set up for microseconds
#define RMT_CLOCK_DIVIDER 80 #define RMT_CLOCK_DIVIDER 80
@ -32,9 +32,9 @@
class RMTChannel { class RMTChannel {
public: public:
RMTChannel(Pinpair pins, bool isMain); RMTChannel(pinpair pins, bool isMain);
bool addPin(byte pin, bool inverted=0); bool addPin(byte pin, bool inverted=0);
bool addPin(Pinpair pins); bool addPin(pinpair pins);
void IRAM_ATTR RMTinterrupt(); void IRAM_ATTR RMTinterrupt();
void RMTprefill(); void RMTprefill();
//int RMTfillData(dccPacket packet); //int RMTfillData(dccPacket packet);

View File

@ -126,6 +126,22 @@ volatile bool DCCWaveform::railcomActive=false; // switched on by user
volatile bool DCCWaveform::railcomDebug=false; // switched on by user volatile bool DCCWaveform::railcomDebug=false; // switched on by user
volatile bool DCCWaveform::railcomSampleWindow=false; // true during packet transmit volatile bool DCCWaveform::railcomSampleWindow=false; // true during packet transmit
bool DCCWaveform::isRailcom() {
return railcomActive;
}
bool DCCWaveform::isRailcomSampleWindow() {
return railcomSampleWindow;
}
bool DCCWaveform::isRailcomPossible() {
return railcomPossible;
}
void DCCWaveform::setRailcomPossible(bool yes) {
railcomPossible=yes;
if (!yes) setRailcom(false,false);
}
bool DCCWaveform::setRailcom(bool on, bool debug) { bool DCCWaveform::setRailcom(bool on, bool debug) {
if (on && railcomPossible) { if (on && railcomPossible) {
// TODO check possible // TODO check possible
@ -149,28 +165,23 @@ void DCCWaveform::interrupt2() {
if (remainingPreambles > 0 ) { if (remainingPreambles > 0 ) {
state=WAVE_MID_1; // switch state to trigger LOW on next interrupt state=WAVE_MID_1; // switch state to trigger LOW on next interrupt
// predict railcom cutout on next interrupt
cutoutNextTime= remainingPreambles==requiredPreambles
&& railcomActive
&& isMainTrack;
remainingPreambles--; remainingPreambles--;
// As we get to the end of the preambles, open the reminder window. // As we get to the end of the preambles, open the reminder window.
// This delays any reminder insertion until the last moment so // This delays any reminder insertion until the last moment so
// that the reminder doesn't block a more urgent packet. // that the reminder doesn't block a more urgent packet.
reminderWindowOpen=transmitRepeats==0 && remainingPreambles<10 && remainingPreambles>1; reminderWindowOpen=transmitRepeats==0 && remainingPreambles<4 && remainingPreambles>1;
if (remainingPreambles==1) if (remainingPreambles==1) promotePendingPacket();
promotePendingPacket();
else if (isMainTrack && railcomActive) { else if (isMainTrack && railcomActive) {
if (remainingPreambles==(requiredPreambles-1)) { // cutout has ended so its now possible to poll the railcom detectors
// First look if we need to start a railcom cutout on next interrupt if (remainingPreambles==5) railcomSampleWindow=true;
cutoutNextTime= true; // cutout can be ended when read
} else if (remainingPreambles==(requiredPreambles-12)) { else if (remainingPreambles==14) DCCTimer::ackRailcomTimer();
// cutout has ended so its now possible to poll the railcom detectors
// requiredPreambles is one higher that preamble length so
// if preamble length is 16 then this evaluates to 5
railcomSampleWindow=true;
} else if (remainingPreambles==(requiredPreambles-3)) {
// cutout can be ended when read
// see above for requiredPreambles
DCCTimer::ackRailcomTimer();
}
} }
// Update free memory diagnostic as we don't have anything else to do this time. // Update free memory diagnostic as we don't have anything else to do this time.
// Allow for checkAck and its called functions using 22 bytes more. // Allow for checkAck and its called functions using 22 bytes more.
@ -255,13 +266,11 @@ void DCCWaveform::promotePendingPacket() {
transmitRepeats = 0; transmitRepeats = 0;
if (getResets() < 250) sentResetsSincePacket++; // only place to increment (private!) if (getResets() < 250) sentResetsSincePacket++; // only place to increment (private!)
} }
#endif //not ARDUINO_ARCH_ESP32 #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#include "DCCWaveform.h" #include "DCCWaveform.h"
#include "TrackManager.h"
#include "DCCACK.h" #include "DCCACK.h"
#include "Pinpair.h"
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true); DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true);
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false); DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);
@ -274,7 +283,7 @@ DCCWaveform::DCCWaveform(byte preambleBits, bool isMain) {
} }
void DCCWaveform::begin() { void DCCWaveform::begin() {
for(const auto& md: TrackManager::getMainDrivers()) { for(const auto& md: TrackManager::getMainDrivers()) {
Pinpair p = md->getSignalPin(); pinpair p = md->getSignalPin();
if(rmtMainChannel) { if(rmtMainChannel) {
//DIAG(F("added pins %d %d to MAIN channel"), p.pin, p.invpin); //DIAG(F("added pins %d %d to MAIN channel"), p.pin, p.invpin);
rmtMainChannel->addPin(p); // add pin to existing main channel rmtMainChannel->addPin(p); // add pin to existing main channel
@ -285,7 +294,7 @@ void DCCWaveform::begin() {
} }
MotorDriver *md = TrackManager::getProgDriver(); MotorDriver *md = TrackManager::getProgDriver();
if (md) { if (md) {
Pinpair p = md->getSignalPin(); pinpair p = md->getSignalPin();
if (rmtProgChannel) { if (rmtProgChannel) {
//DIAG(F("added pins %d %d to PROG channel"), p.pin, p.invpin); //DIAG(F("added pins %d %d to PROG channel"), p.pin, p.invpin);
rmtProgChannel->addPin(p); // add pin to existing prog channel rmtProgChannel->addPin(p); // add pin to existing prog channel
@ -343,9 +352,7 @@ void IRAM_ATTR DCCWaveform::loop() {
} }
bool DCCWaveform::setRailcom(bool on, bool debug) { bool DCCWaveform::setRailcom(bool on, bool debug) {
// todo // TODO... ESP32 railcom waveform
(void)on;
(void)debug;
return false; return false;
} }

View File

@ -25,7 +25,7 @@
#define DCCWaveform_h #define DCCWaveform_h
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#include "DCCRMT.h" #include "DCCRMT.h"
//#include "TrackManager.h" #include "TrackManager.h"
#endif #endif
@ -84,19 +84,10 @@ class DCCWaveform {
bool isReminderWindowOpen(); bool isReminderWindowOpen();
void promotePendingPacket(); void promotePendingPacket();
static bool setRailcom(bool on, bool debug); static bool setRailcom(bool on, bool debug);
inline static bool isRailcom() { static bool isRailcom();
return railcomActive; static bool isRailcomSampleWindow();
}; static bool isRailcomPossible();
inline static bool isRailcomSampleWindow() { static void setRailcomPossible(bool yes);
return railcomSampleWindow;
};
inline static bool isRailcomPossible() {
return railcomPossible;
};
inline static void setRailcomPossible(bool yes) {
railcomPossible=yes;
if (!yes) setRailcom(false,false);
};
private: private:
#ifndef ARDUINO_ARCH_ESP32 #ifndef ARDUINO_ARCH_ESP32
volatile bool packetPending; volatile bool packetPending;

View File

@ -87,8 +87,6 @@ LookList * RMFT2::onClockLookup=NULL;
LookList * RMFT2::onRotateLookup=NULL; LookList * RMFT2::onRotateLookup=NULL;
#endif #endif
LookList * RMFT2::onOverloadLookup=NULL; LookList * RMFT2::onOverloadLookup=NULL;
LookList * RMFT2::onBlockEnterLookup=NULL;
LookList * RMFT2::onBlockExitLookup=NULL;
byte * RMFT2::routeStateArray=nullptr; byte * RMFT2::routeStateArray=nullptr;
const FSH * * RMFT2::routeCaptionArray=nullptr; const FSH * * RMFT2::routeCaptionArray=nullptr;
int16_t * RMFT2::stashArray=nullptr; int16_t * RMFT2::stashArray=nullptr;
@ -133,11 +131,11 @@ int16_t LookList::find(int16_t value) {
void LookList::chain(LookList * chain) { void LookList::chain(LookList * chain) {
m_chain=chain; m_chain=chain;
} }
void LookList::handleEvent(const FSH* reason,int16_t id, int16_t loco) { void LookList::handleEvent(const FSH* reason,int16_t id) {
// New feature... create multiple ONhandlers // New feature... create multiple ONhandlers
for (int i=0;i<m_size;i++) for (int i=0;i<m_size;i++)
if (m_lookupArray[i]==id) if (m_lookupArray[i]==id)
RMFT2::startNonRecursiveTask(reason,id,m_resultArray[i],loco); RMFT2::startNonRecursiveTask(reason,id,m_resultArray[i]);
} }
@ -205,12 +203,6 @@ 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);
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
@ -387,7 +379,7 @@ char RMFT2::getRouteType(int16_t id) {
} }
RMFT2::RMFT2(int progCtr, int16_t _loco) { RMFT2::RMFT2(int progCtr) {
progCounter=progCtr; progCounter=progCtr;
// get an unused task id from the flags table // get an unused task id from the flags table
@ -400,7 +392,9 @@ RMFT2::RMFT2(int progCtr, int16_t _loco) {
} }
} }
delayTime=0; delayTime=0;
loco=_loco; loco=0;
speedo=0;
forward=true;
invert=false; invert=false;
blinkState=not_blink_task; blinkState=not_blink_task;
stackDepth=0; stackDepth=0;
@ -418,10 +412,7 @@ RMFT2::RMFT2(int progCtr, int16_t _loco) {
RMFT2::~RMFT2() { RMFT2::~RMFT2() {
// estop my loco if this is not an ONevent driveLoco(1); // ESTOP my loco if any
// (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;
@ -437,9 +428,23 @@ 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;
new RMFT2(pc,cab); RMFT2* task=new RMFT2(pc);
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.
@ -494,7 +499,7 @@ bool RMFT2::skipIfBlock() {
if (cv & LONG_ADDR_MARKER) { // maker bit indicates long addr if (cv & LONG_ADDR_MARKER) { // maker bit indicates long addr
progtrackLocoId = cv ^ LONG_ADDR_MARKER; // remove marker bit to get real long addr progtrackLocoId = cv ^ LONG_ADDR_MARKER; // remove marker bit to get real long addr
if (progtrackLocoId <= HIGHEST_SHORT_ADDR ) { // out of range for long addr if (progtrackLocoId <= HIGHEST_SHORT_ADDR ) { // out of range for long addr
DIAG(F("Long addr %d <= %d unsupported\n"), progtrackLocoId, HIGHEST_SHORT_ADDR); DIAG(F("Long addr %d <= %d unsupported"), progtrackLocoId, HIGHEST_SHORT_ADDR);
progtrackLocoId = -1; progtrackLocoId = -1;
} }
} else { } else {
@ -502,15 +507,6 @@ 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();
@ -575,15 +571,18 @@ void RMFT2::loop2() {
#endif #endif
case OPCODE_REV: case OPCODE_REV:
if (loco) DCC::setThrottle(loco,operand,invert); forward = false;
driveLoco(operand);
break; break;
case OPCODE_FWD: case OPCODE_FWD:
if (loco) DCC::setThrottle(loco,operand,!invert); forward = true;
break; driveLoco(operand);
break;
case OPCODE_SPEED: case OPCODE_SPEED:
if (loco) DCC::setThrottle(loco,operand,DCC::getThrottleDirection(loco)); forward=DCC::getThrottleDirection(loco)^invert;
driveLoco(operand);
break; break;
case OPCODE_FORGET: case OPCODE_FORGET:
@ -595,11 +594,12 @@ 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)) {
if (loco) DCC::setThrottle(loco,0,DCC::getThrottleDirection(loco)); driveLoco(0);
delayMe(500); delayMe(500);
return; return;
} }
@ -697,10 +697,6 @@ 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::setThrottle(0,1,true); // pause all locos on the track DCC::setThrottle(0,1,true); // pause all locos on the track
pausingTask=this; pausingTask=this;
break; break;
@ -745,8 +741,8 @@ void RMFT2::loop2() {
case OPCODE_RESUME: case OPCODE_RESUME:
pausingTask=NULL; pausingTask=NULL;
resume(); driveLoco(speedo);
for (RMFT2 * t=next; t!=this;t=t->next) t->resume(); for (RMFT2 * t=next; t!=this;t=t->next) if (t->loco >0) t->driveLoco(t->speedo);
break; break;
case OPCODE_IF: // do next operand if sensor set case OPCODE_IF: // do next operand if sensor set
@ -857,7 +853,8 @@ void RMFT2::loop2() {
case OPCODE_DRIVE: case OPCODE_DRIVE:
{ {
// Non functional but reserved byte analogSpeed=IODevice::readAnalogue(operand) *127 / 1024;
if (speedo!=analogSpeed) driveLoco(analogSpeed);
break; break;
} }
@ -947,6 +944,8 @@ void RMFT2::loop2() {
// which is intended so it can be checked // which is intended so it can be checked
// from within EXRAIL // from within EXRAIL
loco=progtrackLocoId; loco=progtrackLocoId;
speedo=0;
forward=true;
invert=false; invert=false;
break; break;
#endif #endif
@ -968,13 +967,16 @@ void RMFT2::loop2() {
{ {
int newPc=routeLookup->find(getOperand(1)); int newPc=routeLookup->find(getOperand(1));
if (newPc<0) break; if (newPc<0) break;
new RMFT2(newPc,operand); // create new task RMFT2* newtask=new RMFT2(newPc); // 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;
@ -1108,8 +1110,7 @@ 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:
@ -1301,14 +1302,6 @@ void RMFT2::activateEvent(int16_t addr, bool activate) {
else onDeactivateLookup->handleEvent(F("DEACTIVATE"),addr); else onDeactivateLookup->handleEvent(F("DEACTIVATE"),addr);
} }
void RMFT2::blockEvent(int16_t block, int16_t loco, bool entering) {
if (compileFeatures & FEATURE_BLOCK) {
// Hunt for an ONBLOCKENTER/ONBLOCKEXIT for this accessory
if (entering) onBlockEnterLookup->handleEvent(F("BLOCKENTER"),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) {
// Hunt for an ONCHANGE for this sensor // Hunt for an ONCHANGE for this sensor
if (change) onChangeLookup->handleEvent(F("CHANGE"),vpin); if (change) onChangeLookup->handleEvent(F("CHANGE"),vpin);
@ -1364,7 +1357,7 @@ void RMFT2::killBlinkOnVpin(VPIN pin, uint16_t count) {
} }
} }
void RMFT2::startNonRecursiveTask(const FSH* reason, int16_t id,int pc, int16_t loco) { void RMFT2::startNonRecursiveTask(const FSH* reason, int16_t id,int pc) {
// Check we dont already have a task running this handler // Check we dont already have a task running this handler
RMFT2 * task=loopTask; RMFT2 * task=loopTask;
while(task) { while(task) {
@ -1376,7 +1369,7 @@ void RMFT2::startNonRecursiveTask(const FSH* reason, int16_t id,int pc, int16_t
if (task==loopTask) break; if (task==loopTask) break;
} }
task=new RMFT2(pc,loco); // new task starts at this instruction task=new RMFT2(pc); // new task starts at this instruction
task->onEventStartPosition=pc; // flag for recursion detector task->onEventStartPosition=pc; // flag for recursion detector
} }

View File

@ -75,9 +75,8 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,OPCODE_TOGGLE_TURNOUT,
OPCODE_ROUTE_ACTIVE,OPCODE_ROUTE_INACTIVE,OPCODE_ROUTE_HIDDEN, OPCODE_ROUTE_ACTIVE,OPCODE_ROUTE_INACTIVE,OPCODE_ROUTE_HIDDEN,
OPCODE_ROUTE_DISABLED, OPCODE_ROUTE_DISABLED,
OPCODE_STASH,OPCODE_CLEAR_STASH,OPCODE_CLEAR_ALL_STASH,OPCODE_PICKUP_STASH, OPCODE_STASH,OPCODE_CLEAR_STASH,OPCODE_CLEAR_ALL_STASH,OPCODE_PICKUP_STASH,
OPCODE_ONBUTTON,OPCODE_ONSENSOR, OPCODE_ONBUTTON,OPCODE_ONSENSOR,
OPCODE_NEOPIXEL, OPCODE_NEOPIXEL,
OPCODE_ONBLOCKENTER,OPCODE_ONBLOCKEXIT,
// 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
// see skipIfBlock() // see skipIfBlock()
@ -137,7 +136,6 @@ enum SignalType {
static const byte FEATURE_STASH = 0x08; static const byte FEATURE_STASH = 0x08;
static const byte FEATURE_BLINK = 0x04; static const byte FEATURE_BLINK = 0x04;
static const byte FEATURE_SENSOR = 0x02; static const byte FEATURE_SENSOR = 0x02;
static const byte FEATURE_BLOCK = 0x01;
// Flag bits for status of hardware and TPL // Flag bits for status of hardware and TPL
@ -164,7 +162,7 @@ class LookList {
int16_t findPosition(int16_t value); // finds index int16_t findPosition(int16_t value); // finds index
int16_t size(); int16_t size();
void stream(Print * _stream); void stream(Print * _stream);
void handleEvent(const FSH* reason,int16_t id, int16_t loco=0); void handleEvent(const FSH* reason,int16_t id);
private: private:
int16_t m_size; int16_t m_size;
@ -178,7 +176,8 @@ class LookList {
public: public:
static void begin(); static void begin();
static void loop(); static void loop();
RMFT2(int progCounter, int16_t cab=0); RMFT2(int progCounter);
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);
@ -188,7 +187,6 @@ class LookList {
static void clockEvent(int16_t clocktime, bool change); static void clockEvent(int16_t clocktime, bool change);
static void rotateEvent(int16_t id, bool change); static void rotateEvent(int16_t id, bool change);
static void powerEvent(int16_t track, bool overload); static void powerEvent(int16_t track, bool overload);
static void blockEvent(int16_t block, int16_t loco, bool entering);
static bool signalAspectEvent(int16_t address, byte aspect ); static bool signalAspectEvent(int16_t address, byte aspect );
// Throttle Info Access functions built by exrail macros // Throttle Info Access functions built by exrail macros
static const byte rosterNameCount; static const byte rosterNameCount;
@ -202,7 +200,7 @@ class LookList {
static const FSH * getRosterFunctions(int16_t id); static const FSH * getRosterFunctions(int16_t id);
static const FSH * getTurntableDescription(int16_t id); static const FSH * getTurntableDescription(int16_t id);
static const FSH * getTurntablePositionDescription(int16_t turntableId, uint8_t positionId); static const FSH * getTurntablePositionDescription(int16_t turntableId, uint8_t positionId);
static void startNonRecursiveTask(const FSH* reason, int16_t id,int pc, int16_t loco=0); static void startNonRecursiveTask(const FSH* reason, int16_t id,int pc);
static bool readSensor(uint16_t sensorId); static bool readSensor(uint16_t sensorId);
static bool isSignal(int16_t id,char rag); static bool isSignal(int16_t id,char rag);
static SIGNAL_DEFINITION getSignalSlot(int16_t slotno); static SIGNAL_DEFINITION getSignalSlot(int16_t slotno);
@ -226,6 +224,7 @@ 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();
@ -234,8 +233,6 @@ 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[];
@ -257,9 +254,6 @@ private:
static LookList * onRotateLookup; static LookList * onRotateLookup;
#endif #endif
static LookList * onOverloadLookup; static LookList * onOverloadLookup;
static LookList * onBlockEnterLookup;
static LookList * onBlockExitLookup;
static const int countLCCLookup; static const int countLCCLookup;
static int onLCCLookup[]; static int onLCCLookup[];
@ -284,8 +278,9 @@ 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 pauseSpeed; byte speedo;
int onEventStartPosition; int onEventStartPosition;
byte stackDepth; byte stackDepth;
int callStack[MAX_STACK_DEPTH]; int callStack[MAX_STACK_DEPTH];

View File

@ -110,8 +110,6 @@
#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
@ -283,8 +281,6 @@
#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,14 +210,6 @@ 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;
} }
@ -236,9 +228,11 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
); );
} }
else { else {
StringFormatter::send(stream,F("\nID=%d,PC=%d,LOCO=%d %c"), StringFormatter::send(stream,F("\nID=%d,PC=%d,LOCO=%d%c,SPEED=%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;
@ -282,27 +276,19 @@ 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;
{ // pause all tasks DCC::setThrottle(0,1,true); // pause all locos on the track
RMFT2 * task=loopTask;
while(task) {
task->pause();
task=task->next;
if (task==loopTask) break;
}
}
DCC::setThrottle(0,1,true); // 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) {
task->resume(); if (task->loco) task->driveLoco(task->speedo);
task=task->next; task=task->next;
if (task==loopTask) break; if (task==loopTask) break;
} }
} }
return true; return true;
@ -315,7 +301,8 @@ 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;
new RMFT2(pc,cab); RMFT2* task=new RMFT2(pc);
task->loco=cab;
} }
return true; return true;

View File

@ -226,10 +226,6 @@ 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"
@ -574,8 +570,6 @@ 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),\

View File

@ -1 +1 @@
#define GITHUB_SHA "devel-railcom2-202409282036Z" #define GITHUB_SHA "devel-202409221903Z"

View File

@ -124,9 +124,21 @@ enum TRACK_MODE : byte {TRACK_MODE_NONE = 1, TRACK_MODE_MAIN = 2, TRACK_MODE_PRO
// Virtualised Motor shield 1-track hardware Interface // Virtualised Motor shield 1-track hardware Interface
#include "Pinpair.h" // for class Pinpair #ifndef UNUSED_PIN // sync define with the one in MotorDrivers.h
#define UNUSED_PIN 255 // inside uint8_t
#endif
#define MAX_PIN 254 #define MAX_PIN 254
class pinpair {
public:
pinpair(byte p1, byte p2) {
pin = p1;
invpin = p2;
};
byte pin = UNUSED_PIN;
byte invpin = UNUSED_PIN;
};
#if defined(__IMXRT1062__) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_STM32) #if defined(__IMXRT1062__) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_STM32)
typedef uint32_t portreg_t; typedef uint32_t portreg_t;
#else #else
@ -197,7 +209,7 @@ class MotorDriver {
pinMode(signalPin2, INPUT); pinMode(signalPin2, INPUT);
} }
}; };
inline Pinpair getSignalPin() { return Pinpair(signalPin,signalPin2); }; inline pinpair getSignalPin() { return pinpair(signalPin,signalPin2); };
inline int8_t getBrakePinSigned() { return invertBrake ? -brakePin : brakePin; }; inline int8_t getBrakePinSigned() { return invertBrake ? -brakePin : brakePin; };
void setDCSignal(byte speedByte, uint8_t frequency=0); void setDCSignal(byte speedByte, uint8_t frequency=0);
void throttleInrush(bool on); void throttleInrush(bool on);
@ -273,7 +285,7 @@ class MotorDriver {
else else
invertPhase = 0; invertPhase = 0;
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
Pinpair p = getSignalPin(); pinpair p = getSignalPin();
uint32_t *outreg = (uint32_t *)(GPIO_FUNC0_OUT_SEL_CFG_REG + 4*p.pin); uint32_t *outreg = (uint32_t *)(GPIO_FUNC0_OUT_SEL_CFG_REG + 4*p.pin);
if (invertPhase) // set or clear the invert bit in the gpio out register if (invertPhase) // set or clear the invert bit in the gpio out register
*outreg |= ((uint32_t)0x1 << GPIO_FUNC0_OUT_INV_SEL_S); *outreg |= ((uint32_t)0x1 << GPIO_FUNC0_OUT_INV_SEL_S);

View File

@ -1,14 +0,0 @@
#pragma once
#ifndef UNUSED_PIN // sync define with the one in MotorDrivers.h
#define UNUSED_PIN 255 // inside uint8_t
#endif
class Pinpair {
public:
Pinpair(byte p1, byte p2) {
pin = p1;
invpin = p2;
};
byte pin = UNUSED_PIN;
byte invpin = UNUSED_PIN;
};

View File

@ -218,7 +218,7 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
// remove pin from MUX matrix and turn it off // remove pin from MUX matrix and turn it off
Pinpair p = track[trackToSet]->getSignalPin(); pinpair p = track[trackToSet]->getSignalPin();
//DIAG(F("Track=%c remove pin %d"),trackToSet+'A', p.pin); //DIAG(F("Track=%c remove pin %d"),trackToSet+'A', p.pin);
gpio_reset_pin((gpio_num_t)p.pin); gpio_reset_pin((gpio_num_t)p.pin);
if (p.invpin != UNUSED_PIN) { if (p.invpin != UNUSED_PIN) {