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

More EXRAIL mem clean

This commit is contained in:
Asbelos 2022-11-22 09:21:23 +00:00
parent 306f91b322
commit 7840c24e21
3 changed files with 76 additions and 47 deletions

View File

@ -92,12 +92,35 @@ LookList * RMFT2::onRedLookup=NULL;
LookList * RMFT2::onAmberLookup=NULL; LookList * RMFT2::onAmberLookup=NULL;
LookList * RMFT2::onGreenLookup=NULL; LookList * RMFT2::onGreenLookup=NULL;
#define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter)
#define GET_OPERAND(n) GETHIGHFLASHW(RMFT2::RouteCode,progCounter+1+(n*3))
#define SKIPOP progCounter+=3 #define SKIPOP progCounter+=3
// RouteCodeFar is a far pointer to flash on anything other than a uno/nano where it is just a near pointer to flash
uint32_t RMFT2::RouteCodeFar;
uint16_t RMFT2::getOperand2(uint32_t farAddr) {
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
// AVR_MEGA memory uses far pointers
return pgm_read_word_far(farAddr);
#elif defined(ARDUINO_ARCH_AVR)
// UNO/NANO have no far memory
return pgm_read_word_near(farAddr);
#else
// other cpus dont care but may be averse to reading an int16_tr at an odd byte boundary.
const byte * op=farAddr;
return *op | (*(op+1) << 8);
#endif
}
// getOperand instance version, uses progCounter from instance.
uint16_t RMFT2::getOperand(byte n) {
return getOperand(progCounter,n);
}
// getOperand static version, must be provided prog counter from loop etc.
uint16_t RMFT2::getOperand(int progCounter,byte n) {
return getOperand2(RouteCodeFar+progCounter+1+(n*3));
}
LookList::LookList(int16_t size) { LookList::LookList(int16_t size) {
m_size=size; m_size=size;
@ -138,17 +161,15 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
for (progCounter=0;; SKIPOP) { for (progCounter=0;; SKIPOP) {
byte opcode=GET_OPCODE; byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break; if (opcode==OPCODE_ENDEXRAIL) break;
if (opcode==op1 || opcode==op2 || opcode==op3) list->add(GET_OPERAND(0),progCounter); if (opcode==op1 || opcode==op2 || opcode==op3) list->add(getOperand(progCounter,0),progCounter);
} }
return list; return list;
} }
/* static */ void RMFT2::begin() { /* static */ void RMFT2::begin() {
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) RouteCodeFar=GETFARPTR(RMFT2::RouteCode);
// AVR_MEGA memory position for diagnostic only DIAG(F("EXRAIL RouteAddr=%l"),RouteCodeFar);
DIAG(F("EXRAIL RouteAddr=%l"),pgm_get_far_address(RMFT2::RouteCode));
#endif
bool saved_diag=diag; bool saved_diag=diag;
diag=true; diag=true;
@ -177,7 +198,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
for (progCounter=0;; SKIPOP){ for (progCounter=0;; SKIPOP){
byte opcode=GET_OPCODE; byte opcode=GET_OPCODE;
if (opcode==OPCODE_ENDEXRAIL) break; if (opcode==OPCODE_ENDEXRAIL) break;
VPIN operand=GET_OPERAND(0); VPIN operand=getOperand(progCounter,0);
switch (opcode) { switch (opcode) {
case OPCODE_AT: case OPCODE_AT:
@ -202,25 +223,25 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
case OPCODE_TURNOUT: { case OPCODE_TURNOUT: {
VPIN id=operand; VPIN id=operand;
int addr=GET_OPERAND(1); int addr=getOperand(progCounter,1);
byte subAddr=GET_OPERAND(2); byte subAddr=getOperand(progCounter,2);
setTurnoutHiddenState(DCCTurnout::create(id,addr,subAddr)); setTurnoutHiddenState(DCCTurnout::create(id,addr,subAddr));
break; break;
} }
case OPCODE_SERVOTURNOUT: { case OPCODE_SERVOTURNOUT: {
VPIN id=operand; VPIN id=operand;
VPIN pin=GET_OPERAND(1); VPIN pin=getOperand(progCounter,1);
int activeAngle=GET_OPERAND(2); int activeAngle=getOperand(progCounter,2);
int inactiveAngle=GET_OPERAND(3); int inactiveAngle=getOperand(progCounter,3);
int profile=GET_OPERAND(4); int profile=getOperand(progCounter,4);
setTurnoutHiddenState(ServoTurnout::create(id,pin,activeAngle,inactiveAngle,profile)); setTurnoutHiddenState(ServoTurnout::create(id,pin,activeAngle,inactiveAngle,profile));
break; break;
} }
case OPCODE_PINTURNOUT: { case OPCODE_PINTURNOUT: {
VPIN id=operand; VPIN id=operand;
VPIN pin=GET_OPERAND(1); VPIN pin=getOperand(progCounter,1);
setTurnoutHiddenState(VpinTurnout::create(id,pin)); setTurnoutHiddenState(VpinTurnout::create(id,pin));
break; break;
} }
@ -564,7 +585,7 @@ void RMFT2::loop2() {
if (delayTime!=0 && millis()-delayStart < delayTime) return; if (delayTime!=0 && millis()-delayStart < delayTime) return;
byte opcode = GET_OPCODE; byte opcode = GET_OPCODE;
int16_t operand = GET_OPERAND(0); int16_t operand = getOperand(0);
// skipIf will get set to indicate a failing IF condition // skipIf will get set to indicate a failing IF condition
bool skipIf=false; bool skipIf=false;
@ -630,13 +651,13 @@ void RMFT2::loop2() {
case OPCODE_ATGTE: // wait for analog sensor>= value case OPCODE_ATGTE: // wait for analog sensor>= value
timeoutFlag=false; timeoutFlag=false;
if (IODevice::readAnalogue(operand) >= (int)(GET_OPERAND(1))) break; if (IODevice::readAnalogue(operand) >= (int)(getOperand(1))) break;
delayMe(50); delayMe(50);
return; return;
case OPCODE_ATLT: // wait for analog sensor < value case OPCODE_ATLT: // wait for analog sensor < value
timeoutFlag=false; timeoutFlag=false;
if (IODevice::readAnalogue(operand) < (int)(GET_OPERAND(1))) break; if (IODevice::readAnalogue(operand) < (int)(getOperand(1))) break;
delayMe(50); delayMe(50);
return; return;
@ -647,7 +668,7 @@ void RMFT2::loop2() {
case OPCODE_ATTIMEOUT2: case OPCODE_ATTIMEOUT2:
if (readSensor(operand)) break; // success without timeout if (readSensor(operand)) break; // success without timeout
if (millis()-timeoutStart > 100*GET_OPERAND(1)) { if (millis()-timeoutStart > 100*getOperand(1)) {
timeoutFlag=true; timeoutFlag=true;
break; // and drop through break; // and drop through
} }
@ -690,7 +711,7 @@ void RMFT2::loop2() {
break; break;
case OPCODE_POM: case OPCODE_POM:
if (loco) DCC::writeCVByteMain(loco, operand, GET_OPERAND(1)); if (loco) DCC::writeCVByteMain(loco, operand, getOperand(1));
break; break;
case OPCODE_POWEROFF: case OPCODE_POWEROFF:
@ -724,11 +745,11 @@ void RMFT2::loop2() {
break; break;
case OPCODE_IFGTE: // do next operand if sensor>= value case OPCODE_IFGTE: // do next operand if sensor>= value
skipIf=IODevice::readAnalogue(operand)<(int)(GET_OPERAND(1)); skipIf=IODevice::readAnalogue(operand)<(int)(getOperand(1));
break; break;
case OPCODE_IFLT: // do next operand if sensor< value case OPCODE_IFLT: // do next operand if sensor< value
skipIf=IODevice::readAnalogue(operand)>=(int)(GET_OPERAND(1)); skipIf=IODevice::readAnalogue(operand)>=(int)(getOperand(1));
break; break;
case OPCODE_IFNOT: // do next operand if sensor not set case OPCODE_IFNOT: // do next operand if sensor not set
@ -811,11 +832,11 @@ void RMFT2::loop2() {
} }
case OPCODE_XFON: case OPCODE_XFON:
DCC::setFn(operand,GET_OPERAND(1),true); DCC::setFn(operand,getOperand(1),true);
break; break;
case OPCODE_XFOFF: case OPCODE_XFOFF:
DCC::setFn(operand,GET_OPERAND(1),false); DCC::setFn(operand,getOperand(1),false);
break; break;
case OPCODE_DCCACTIVATE: { case OPCODE_DCCACTIVATE: {
@ -907,7 +928,7 @@ void RMFT2::loop2() {
case OPCODE_SENDLOCO: // cab, route case OPCODE_SENDLOCO: // cab, route
{ {
int newPc=sequenceLookup->find(GET_OPERAND(1)); int newPc=sequenceLookup->find(getOperand(1));
if (newPc<0) break; if (newPc<0) break;
RMFT2* newtask=new RMFT2(newPc); // create new task RMFT2* newtask=new RMFT2(newPc); // create new task
newtask->loco=operand; newtask->loco=operand;
@ -925,7 +946,7 @@ void RMFT2::loop2() {
case OPCODE_SERVO: // OPCODE_SERVO,V(vpin),OPCODE_PAD,V(position),OPCODE_PAD,V(profile),OPCODE_PAD,V(duration) case OPCODE_SERVO: // OPCODE_SERVO,V(vpin),OPCODE_PAD,V(position),OPCODE_PAD,V(profile),OPCODE_PAD,V(duration)
IODevice::writeAnalogue(operand,GET_OPERAND(1),GET_OPERAND(2),GET_OPERAND(3)); IODevice::writeAnalogue(operand,getOperand(1),getOperand(2),getOperand(3));
break; break;
case OPCODE_WAITFOR: // OPCODE_SERVO,V(pin) case OPCODE_WAITFOR: // OPCODE_SERVO,V(pin)
@ -1139,19 +1160,23 @@ void RMFT2::thrungeString(uint32_t strfar, thrunger mode, byte id) {
} }
if (!stream) return; if (!stream) return;
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
// if mega stream it out // if mega stream it out
for (;;strfar++) { for (;;strfar++) {
char c=pgm_read_byte_far(strfar); char c=pgm_read_byte_far(strfar);
if (c=='\0') break; if (c=='\0') break;
stream->write(c); stream->write(c);
} }
// else other CPUs #else
// stream.print((FSH *)strfar) // UNO/NANO CPUs dont have high memory
// 32 bit cpus dont care anyway
stream.print((FSH *)strfar)
#endif
// and decide what to do next // and decide what to do next
switch (mode) { switch (mode) {
case thrunge_print: case thrunge_print:
StringFormatter::send(&Serial,F(" *>/n")); StringFormatter::send(&Serial,F(" *>\n"));
break; break;
// TODO more serials for SAMx case thrunge_serial4: stream=&Serial4; break; // TODO more serials for SAMx case thrunge_serial4: stream=&Serial4; break;
case thrunge_parse: case thrunge_parse:
@ -1161,7 +1186,7 @@ void RMFT2::thrungeString(uint32_t strfar, thrunger mode, byte id) {
// TODO CommandDistributor::broadcastText(buffer->getString()); // TODO CommandDistributor::broadcastText(buffer->getString());
break; break;
case thrunge_lcd: case thrunge_lcd:
LCD(id,F("%s%"),buffer->getString()); LCD(id,F("%s"),buffer->getString());
break; break;
default: break; default: break;

View File

@ -141,6 +141,8 @@ private:
static LookList* LookListLoader(OPCODE op1, static LookList* LookListLoader(OPCODE op1,
OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL); OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL);
static void handleEvent(const FSH* reason,LookList* handlers, int16_t id); static void handleEvent(const FSH* reason,LookList* handlers, int16_t id);
static uint16_t getOperand(int progCounter,byte n);
static uint16_t getOperand2(uint32_t farAddr);
static RMFT2 * loopTask; static RMFT2 * loopTask;
static RMFT2 * pausingTask; static RMFT2 * pausingTask;
void delayMe(long millisecs); void delayMe(long millisecs);
@ -153,6 +155,7 @@ private:
void printMessage(uint16_t id); // Built by RMFTMacros.h void printMessage(uint16_t id); // Built by RMFTMacros.h
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);
static bool diag; static bool diag;
static const HIGHFLASH byte RouteCode[]; static const HIGHFLASH byte RouteCode[];
@ -166,7 +169,8 @@ private:
static LookList * onRedLookup; static LookList * onRedLookup;
static LookList * onAmberLookup; static LookList * onAmberLookup;
static LookList * onGreenLookup; static LookList * onGreenLookup;
// RouteCodeFar is a far pointer to RouteCode flash on anything other than a uno/nano where it is just a near pointer to flash
static uint32_t RouteCodeFar;
// Local variables - exist for each instance/task // Local variables - exist for each instance/task
RMFT2 *next; // loop chain RMFT2 *next; // loop chain

26
FSH.h
View File

@ -43,23 +43,25 @@
#include <Arduino.h> #include <Arduino.h>
#ifdef ARDUINO_ARCH_AVR #ifdef ARDUINO_ARCH_AVR
// AVR devices have flash memory mapped differently // AVR devices have flash memory mapped differently
// progmem can be accessed by _near functions // progmem can be accessed by _near functions or _far
typedef __FlashStringHelper FSH; typedef __FlashStringHelper FSH;
#define FLASH PROGMEM #define FLASH PROGMEM
#define GETFLASH(addr) pgm_read_byte_near(addr) #define GETFLASH(addr) pgm_read_byte_near(addr)
#define GETFLASHW(addr) pgm_read_word_near(addr)
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) #if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
// AVR_MEGA memory deliberately placed at end of link may need _far functions // AVR_MEGA memory deliberately placed at end of link may need _far functions
#define HIGHFLASH __attribute__((section(".fini2"))) #define HIGHFLASH __attribute__((section(".fini2")))
#define GETHIGHFLASH(data,offset) pgm_read_byte_far(pgm_get_far_address(data)+offset) #define GETFARPTR(data) pgm_get_far_address(data)
#define GETHIGHFLASHW(data,offset) pgm_read_word_far(pgm_get_far_address(data)+offset) #define GETHIGHFLASH(data,offset) pgm_read_byte_far(GETFARPTR(data)+offset)
#define GETHIGHFLASHW(data,offset) pgm_read_word_far(GETFARPTR(data)+offset)
#else #else
// AVR_UNO/NANO runtime does not support _far functions so just use _near equivalent // AVR_UNO/NANO runtime does not support _far functions so just use _near equivalent
// as there is no progmem above 32kb anyway. // as there is no progmem above 32kb anyway.
#define HIGHFLASH FLASH #define HIGHFLASH PROGMEM
#define GETHIGHFLASH(data,offset) pgm_read_byte_near(((byte*)data)+(offset)) #define GETFARPTR(data) ((const byte *)(data))
#define GETHIGHFLASHW(data,offset) pgm_read_word_near(((byte*)data)+(offset)) #define GETHIGHFLASH(data,offset) pgm_read_byte_near(GETFARPTR(data)+(offset))
#define GETHIGHFLASHW(data,offset) pgm_read_word_near(GETFARPTR(data)+(offset))
#endif #endif
#else #else
@ -71,11 +73,9 @@ typedef __FlashStringHelper FSH;
typedef char FSH; typedef char FSH;
#define FLASH #define FLASH
#define HIGHFLASH #define HIGHFLASH
#define GETFLASH(addr) (*(const unsigned char *)(addr)) #define GETFARPTR(data) ((const byte *)(data))
#define GETFLASHW(addr) ((*(const unsigned int8_t *)(addr)) | ((*(const unsigned int8_t *)(addr+1)) << 8)) #define GETFLASH(addr) (*(const byte *)(addr))
#define GETHIGHFLASH(data,offset) GETFLASH(((byte*)data)+(offset)) #define GETHIGHFLASH(data,offset) (*(const byte *)(GETFARPTR(data)+offset))
#define GETHIGHFLASHW(data,offset) GETFLASHW(((byte*)data)+(offset)) #define GETHIGHFLASHW(data,offset) (*(const uint16_t *)(GETFARPTR(data)+offset))
//#define strlen_P strlen
//#define strcpy_P strcpy
#endif #endif
#endif #endif