mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-03-14 01:53:07 +01:00
More EXRAIL mem clean
This commit is contained in:
parent
306f91b322
commit
7840c24e21
91
EXRAIL2.cpp
91
EXRAIL2.cpp
@ -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,18 +161,16 @@ 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;
|
||||||
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
|
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
|
||||||
@ -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;
|
||||||
|
@ -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
26
FSH.h
@ -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
|
Loading…
Reference in New Issue
Block a user