1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-23 21:01:25 +01:00

Reduced RAM/PROGMEM and CPU for signals.

This commit is contained in:
Asbelos 2022-01-03 12:43:06 +00:00
parent 230a119cd0
commit 7017c6bbf5
3 changed files with 51 additions and 44 deletions

View File

@ -77,7 +77,6 @@ RMFT2 * RMFT2::pausingTask=NULL; // Task causing a PAUSE.
byte RMFT2::flags[MAX_FLAGS];
LookList * RMFT2::sequenceLookup=NULL;
LookList * RMFT2::signalLookup=NULL;
LookList * RMFT2::onThrowLookup=NULL;
LookList * RMFT2::onCloseLookup=NULL;
LookList * RMFT2::onActivateLookup=NULL;
@ -122,17 +121,12 @@ LookList * RMFT2::onDeactivateLookup=NULL;
int onCloseCount=0;
int onActivateCount=0;
int onDeactivateCount=0;
int signalCount=0;
// first pass count sizes for fast lookup arrays
for (progCounter=0;; SKIPOP) {
byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break;
switch (opcode) {
case OPCODE_SIGNAL:
signalCount++;
break;
case OPCODE_ROUTE:
case OPCODE_AUTOMATION:
case OPCODE_SEQUENCE:
@ -162,14 +156,23 @@ LookList * RMFT2::onDeactivateLookup=NULL;
// create lookups
sequenceLookup=new LookList(sequenceCount);
signalLookup=new LookList(signalCount);
onThrowLookup=new LookList(onThrowCount);
onCloseLookup=new LookList(onCloseCount);
onActivateLookup=new LookList(onActivateCount);
onDeactivateLookup=new LookList(onDeactivateCount);
// Second pass startup, define any turnouts or servos, set signals red
// add signals, sequences onRoutines to the lookups
// add sequences onRoutines to the lookups
for (int sigpos=0;;sigpos+=3) {
VPIN redpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos);
if (redpin==0) break; // end of signal list
VPIN amberpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+1);
VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+2);
IODevice::write(redpin,true);
if (amberpin) IODevice::write(amberpin,false);
IODevice::write(greenpin,false);
}
for (progCounter=0;; SKIPOP){
byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break;
@ -186,18 +189,6 @@ LookList * RMFT2::onDeactivateLookup=NULL;
break;
}
case OPCODE_SIGNAL: {
VPIN red=operand;
VPIN amber=GET_OPERAND(1);
VPIN green=GET_OPERAND(2);
IODevice::write(red,true);
if (amber) IODevice::write(amber,false);
IODevice::write(green,false);
signalLookup->add(red,progCounter);
break;
}
case OPCODE_TURNOUT: {
VPIN id=operand;
int addr=GET_OPERAND(1);
@ -256,9 +247,9 @@ LookList * RMFT2::onDeactivateLookup=NULL;
}
SKIPOP; // include ENDROUTES opcode
DIAG(F("EXRAIL %db, fl=%d seq=%d, sig=%d, onT=%d, onC=%d"),
DIAG(F("EXRAIL %db, fl=%d seq=%d, onT=%d, onC=%d"),
progCounter,MAX_FLAGS,
sequenceCount, signalCount, onThrowCount, onCloseCount);
sequenceCount, onThrowCount, onCloseCount);
new RMFT2(0); // add the startup route
}
@ -871,7 +862,6 @@ void RMFT2::loop2() {
case OPCODE_AUTOSTART: // Handled only during begin process
case OPCODE_PAD: // Just a padding for previous opcode needing >1 operad byte.
case OPCODE_SIGNAL: // Signal definition ignore at run time
case OPCODE_TURNOUT: // Turnout definition ignored at runtime
case OPCODE_SERVOTURNOUT: // Turnout definition ignored at runtime
case OPCODE_PINTURNOUT: // Turnout definition ignored at runtime
@ -913,18 +903,26 @@ void RMFT2::kill(const FSH * reason, int operand) {
}
/* static */ void RMFT2::doSignal(VPIN id,bool red, bool amber, bool green) {
// CAUTION: hides class member progCounter
int progCounter=signalLookup->find(id);
if (progCounter<0) return;
VPIN redpin=GET_OPERAND(0);
if (redpin!=id) return; // something wrong in lookup
VPIN amberpin=GET_OPERAND(1);
VPIN greenpin=GET_OPERAND(2);
//if (diag) DIAG(F(" dosignal %d"),id);
for (int sigpos=0;;sigpos+=3) {
VPIN redpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos);
//if (diag) DIAG(F("red=%d"),redpin);
if (redpin==0) {
DIAG(F("EXRAIL Signal %d not defined"), id);
return; // signal not found
}
if (redpin==id) {
VPIN amberpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+1);
VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+2);
//if (diag) DIAG(F("signal %d %d %d"),redpin,amberpin,greenpin);
// If amberpin is zero, synthesise amber from red+green
IODevice::write(redpin,red || (amber && (amberpin==0)));
if (amberpin) IODevice::write(amberpin,amber);
if (greenpin) IODevice::write(greenpin,green || (amber && (amberpin==0)));
return;
}
}
}
void RMFT2::turnoutEvent(int16_t turnoutId, bool closed) {
// Hunt for an ONTHROW/ONCLOSE for this turnout

12
RMFT2.h
View File

@ -22,7 +22,7 @@
#include "IODevice.h"
// The following are the operation codes (or instructions) for a kind of virtual machine.
// Each instruction is normally 2 bytes long with an operation code followed by a parameter.
// Each instruction is normally 3 bytes long with an operation code followed by a parameter.
// In cases where more than one parameter is required, the first parameter is followed by one
// or more OPCODE_PAD instructions with the subsequent parameters. This wastes a byte but makes
// searching easier as a parameter can never be confused with an opcode.
@ -53,9 +53,11 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
// Flag bits for status of hardware and TPL
static const byte SECTION_FLAG = 0x01;
static const byte LATCH_FLAG = 0x02;
static const byte TASK_FLAG = 0x04;
static const byte SECTION_FLAG = 0x80;
static const byte LATCH_FLAG = 0x40;
static const byte TASK_FLAG = 0x20;
static const byte SPARE_FLAG = 0x10;
static const byte COUNTER_MASK= 0x0F;
static const byte MAX_STACK_DEPTH=4;
@ -116,9 +118,9 @@ private:
static bool diag;
static const FLASH byte RouteCode[];
static const FLASH int16_t SignalDefinitions[];
static byte flags[MAX_FLAGS];
static LookList * sequenceLookup;
static LookList * signalLookup;
static LookList * onThrowLookup;
static LookList * onCloseLookup;
static LookList * onActivateLookup;

View File

@ -140,11 +140,18 @@ const FSH * RMFT2::getRosterFunctions(int16_t cabid) {
}
}
// Pass 8 Signal definitions
#include "RMFT2MacroReset.h"
#undef SIGNAL
#define SIGNAL(redpin,amberpin,greenpin) redpin,amberpin,greenpin,
const FLASH int16_t RMFT2::SignalDefinitions[] = {
#include "myAutomation.h"
0,0,0 };
// Last Pass : create main routes table
// Only undef the macros, not dummy them.
#define RMFT2_UNDEF_ONLY
#include "RMFT2MacroReset.h"
// Define internal helper macros.
// Everything we generate here has to be compile-time evaluated to
// a constant.
@ -227,7 +234,7 @@ const FSH * RMFT2::getRosterFunctions(int16_t cabid) {
#define SERVO_TURNOUT(id,pin,activeAngle,inactiveAngle,profile,description...) OPCODE_SERVOTURNOUT,V(id),OPCODE_PAD,V(pin),OPCODE_PAD,V(activeAngle),OPCODE_PAD,V(inactiveAngle),OPCODE_PAD,V(PCA9685::ProfileType::profile),
#define SET(pin) OPCODE_SET,V(pin),
#define SETLOCO(loco) OPCODE_SETLOCO,V(loco),
#define SIGNAL(redpin,amberpin,greenpin) OPCODE_SIGNAL,V(redpin),OPCODE_PAD,V(amberpin),OPCODE_PAD,V(greenpin),
#define SIGNAL(redpin,amberpin,greenpin)
#define SPEED(speed) OPCODE_SPEED,V(speed),
#define START(route) OPCODE_START,V(route),
#define STOP OPCODE_SPEED,V(0),