mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-02-19 23:46:02 +01:00
Exrail high mem access
This commit is contained in:
parent
d60a55091f
commit
9dc16356db
@ -41,6 +41,14 @@
|
|||||||
#include "DCCTimer.h"
|
#include "DCCTimer.h"
|
||||||
#include "EXRAIL2.h"
|
#include "EXRAIL2.h"
|
||||||
|
|
||||||
|
// This macro can't be created easily as a portable function because the
|
||||||
|
// flashlist requires a far pointer for high flash access.
|
||||||
|
#define SENDFLASHLIST(stream,flashList) \
|
||||||
|
for (int16_t i=0;;i+=sizeof(flashList[0])) { \
|
||||||
|
int16_t value=GETHIGHFLASHW(flashList,i); \
|
||||||
|
if (value==0) break; \
|
||||||
|
StringFormatter::send(stream,F(" %d"),value); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// These keywords are used in the <1> command. The number is what you get if you use the keyword as a parameter.
|
// These keywords are used in the <1> command. The number is what you get if you use the keyword as a parameter.
|
||||||
@ -568,8 +576,8 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
StringFormatter::send(stream, F("<jA"));
|
StringFormatter::send(stream, F("<jA"));
|
||||||
if (params==1) {// <JA>
|
if (params==1) {// <JA>
|
||||||
#ifdef EXRAIL_ACTIVE
|
#ifdef EXRAIL_ACTIVE
|
||||||
sendFlashList(stream,RMFT2::routeIdList);
|
SENDFLASHLIST(stream,RMFT2::routeIdList)
|
||||||
sendFlashList(stream,RMFT2::automationIdList);
|
SENDFLASHLIST(stream,RMFT2::automationIdList)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else { // <JA id>
|
else { // <JA id>
|
||||||
@ -588,7 +596,9 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
case HASH_KEYWORD_R: // <JR> returns rosters
|
case HASH_KEYWORD_R: // <JR> returns rosters
|
||||||
StringFormatter::send(stream, F("<jR"));
|
StringFormatter::send(stream, F("<jR"));
|
||||||
#ifdef EXRAIL_ACTIVE
|
#ifdef EXRAIL_ACTIVE
|
||||||
if (params==1) sendFlashList(stream,RMFT2::rosterIdList);
|
if (params==1) {
|
||||||
|
SENDFLASHLIST(stream,RMFT2::rosterIdList)
|
||||||
|
}
|
||||||
else StringFormatter::send(stream,F(" %d \"%S\" \"%S\""),
|
else StringFormatter::send(stream,F(" %d \"%S\" \"%S\""),
|
||||||
id, RMFT2::getRosterName(id), RMFT2::getRosterFunctions(id));
|
id, RMFT2::getRosterName(id), RMFT2::getRosterFunctions(id));
|
||||||
#endif
|
#endif
|
||||||
@ -633,14 +643,6 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
StringFormatter::send(stream, F("<X>\n"));
|
StringFormatter::send(stream, F("<X>\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCEXParser::sendFlashList(Print * stream,const int16_t flashList[]) {
|
|
||||||
for (int16_t i=0;;i++) {
|
|
||||||
int16_t value=GETFLASHW(flashList+i);
|
|
||||||
if (value==0) return;
|
|
||||||
StringFormatter::send(stream,F(" %d"),value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DCCEXParser::parseZ(Print *stream, int16_t params, int16_t p[])
|
bool DCCEXParser::parseZ(Print *stream, int16_t params, int16_t p[])
|
||||||
{
|
{
|
||||||
|
|
||||||
|
41
EXRAIL2.cpp
41
EXRAIL2.cpp
@ -91,8 +91,10 @@ LookList * RMFT2::onRedLookup=NULL;
|
|||||||
LookList * RMFT2::onAmberLookup=NULL;
|
LookList * RMFT2::onAmberLookup=NULL;
|
||||||
LookList * RMFT2::onGreenLookup=NULL;
|
LookList * RMFT2::onGreenLookup=NULL;
|
||||||
|
|
||||||
#define GET_OPCODE GETFLASH(RMFT2::RouteCode+progCounter)
|
|
||||||
#define GET_OPERAND(n) GETFLASHW(RMFT2::RouteCode+progCounter+1+(n*3))
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
@ -141,6 +143,8 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void RMFT2::begin() {
|
/* static */ void RMFT2::begin() {
|
||||||
|
bool saved_diag=diag;
|
||||||
|
diag=true;
|
||||||
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
|
DCCEXParser::setRMFTFilter(RMFT2::ComandFilter);
|
||||||
for (int f=0;f<MAX_FLAGS;f++) flags[f]=0;
|
for (int f=0;f<MAX_FLAGS;f++) flags[f]=0;
|
||||||
|
|
||||||
@ -156,8 +160,8 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
|||||||
|
|
||||||
// Second pass startup, define any turnouts or servos, set signals red
|
// Second pass startup, define any turnouts or servos, set signals red
|
||||||
// add sequences onRoutines to the lookups
|
// add sequences onRoutines to the lookups
|
||||||
for (int sigpos=0;;sigpos+=4) {
|
for (int sigslot=0;;sigslot++) {
|
||||||
VPIN sigid=GETFLASHW(RMFT2::SignalDefinitions+sigpos);
|
VPIN sigid=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigslot*8);
|
||||||
if (sigid==0) break; // end of signal list
|
if (sigid==0) break; // end of signal list
|
||||||
doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED);
|
doSignal(sigid & SIGNAL_ID_MASK, SIGNAL_RED);
|
||||||
}
|
}
|
||||||
@ -229,20 +233,22 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
|||||||
DIAG(F("EXRAIL %db, fl=%d"),progCounter,MAX_FLAGS);
|
DIAG(F("EXRAIL %db, fl=%d"),progCounter,MAX_FLAGS);
|
||||||
|
|
||||||
new RMFT2(0); // add the startup route
|
new RMFT2(0); // add the startup route
|
||||||
|
diag=saved_diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RMFT2::setTurnoutHiddenState(Turnout * t) {
|
void RMFT2::setTurnoutHiddenState(Turnout * t) {
|
||||||
|
// turnout descriptions are in low flash F strings
|
||||||
t->setHidden(GETFLASH(getTurnoutDescription(t->getId()))==0x01);
|
t->setHidden(GETFLASH(getTurnoutDescription(t->getId()))==0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
char RMFT2::getRouteType(int16_t id) {
|
char RMFT2::getRouteType(int16_t id) {
|
||||||
for (int16_t i=0;;i++) {
|
for (int16_t i=0;;i+=2) {
|
||||||
int16_t rid= GETFLASHW(routeIdList+i);
|
int16_t rid= GETHIGHFLASHW(routeIdList,i);
|
||||||
if (rid==id) return 'R';
|
if (rid==id) return 'R';
|
||||||
if (rid==0) break;
|
if (rid==0) break;
|
||||||
}
|
}
|
||||||
for (int16_t i=0;;i++) {
|
for (int16_t i=0;;i+=2) {
|
||||||
int16_t rid= GETFLASHW(automationIdList+i);
|
int16_t rid= GETHIGHFLASHW(automationIdList,i);
|
||||||
if (rid==id) return 'A';
|
if (rid==id) return 'A';
|
||||||
if (rid==0) break;
|
if (rid==0) break;
|
||||||
}
|
}
|
||||||
@ -304,7 +310,7 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
|
|||||||
// do the signals
|
// do the signals
|
||||||
// flags[n] represents the state of the nth signal in the table
|
// flags[n] represents the state of the nth signal in the table
|
||||||
for (int sigslot=0;;sigslot++) {
|
for (int sigslot=0;;sigslot++) {
|
||||||
VPIN sigid=GETFLASHW(RMFT2::SignalDefinitions+sigslot*4);
|
VPIN sigid=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigslot*8);
|
||||||
if (sigid==0) break; // end of signal list
|
if (sigid==0) break; // end of signal list
|
||||||
byte flag=flags[sigslot] & SIGNAL_MASK; // obtain signal flags for this id
|
byte flag=flags[sigslot] & SIGNAL_MASK; // obtain signal flags for this id
|
||||||
StringFormatter::send(stream,F("\n%S[%d]"),
|
StringFormatter::send(stream,F("\n%S[%d]"),
|
||||||
@ -982,8 +988,8 @@ void RMFT2::kill(const FSH * reason, int operand) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int16_t RMFT2::getSignalSlot(int16_t id) {
|
int16_t RMFT2::getSignalSlot(int16_t id) {
|
||||||
for (int sigpos=0;;sigpos+=4) {
|
for (int sigslot=0;;sigslot++) {
|
||||||
int16_t sigid=GETFLASHW(RMFT2::SignalDefinitions+sigpos);
|
int16_t sigid=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigslot*8);
|
||||||
if (sigid==0) { // end of signal list
|
if (sigid==0) { // end of signal list
|
||||||
DIAG(F("EXRAIL Signal %d not defined"), id);
|
DIAG(F("EXRAIL Signal %d not defined"), id);
|
||||||
return -1;
|
return -1;
|
||||||
@ -993,9 +999,10 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
|
|||||||
// but for a servo signal it will also have SERVO_SIGNAL_FLAG set.
|
// but for a servo signal it will also have SERVO_SIGNAL_FLAG set.
|
||||||
|
|
||||||
if ((sigid & SIGNAL_ID_MASK)!= id) continue; // keep looking
|
if ((sigid & SIGNAL_ID_MASK)!= id) continue; // keep looking
|
||||||
return sigpos/4; // relative slot in signals table
|
return sigslot; // relative slot in signals table
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void RMFT2::doSignal(int16_t id,char rag) {
|
/* static */ void RMFT2::doSignal(int16_t id,char rag) {
|
||||||
if (diag) DIAG(F(" doSignal %d %x"),id,rag);
|
if (diag) DIAG(F(" doSignal %d %x"),id,rag);
|
||||||
|
|
||||||
@ -1012,11 +1019,11 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
|
|||||||
setFlag(sigslot,rag,SIGNAL_MASK);
|
setFlag(sigslot,rag,SIGNAL_MASK);
|
||||||
|
|
||||||
// Correct signal definition found, get the rag values
|
// Correct signal definition found, get the rag values
|
||||||
int16_t sigpos=sigslot*4;
|
int16_t sigpos=sigslot*8;
|
||||||
VPIN sigid=GETFLASHW(RMFT2::SignalDefinitions+sigpos);
|
VPIN sigid=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos);
|
||||||
VPIN redpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+1);
|
VPIN redpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+2);
|
||||||
VPIN amberpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+2);
|
VPIN amberpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+4);
|
||||||
VPIN greenpin=GETFLASHW(RMFT2::SignalDefinitions+sigpos+3);
|
VPIN greenpin=GETHIGHFLASHW(RMFT2::SignalDefinitions,sigpos+6);
|
||||||
if (diag) DIAG(F("signal %d %d %d %d %d"),sigid,id,redpin,amberpin,greenpin);
|
if (diag) DIAG(F("signal %d %d %d %d %d"),sigid,id,redpin,amberpin,greenpin);
|
||||||
|
|
||||||
VPIN sigtype=sigid & ~SIGNAL_ID_MASK;
|
VPIN sigtype=sigid & ~SIGNAL_ID_MASK;
|
||||||
|
10
EXRAIL2.h
10
EXRAIL2.h
@ -114,9 +114,9 @@ class LookList {
|
|||||||
|
|
||||||
// Throttle Info Access functions built by exrail macros
|
// Throttle Info Access functions built by exrail macros
|
||||||
static const byte rosterNameCount;
|
static const byte rosterNameCount;
|
||||||
static const int16_t FLASH routeIdList[];
|
static const int16_t HIGHFLASH routeIdList[];
|
||||||
static const int16_t FLASH automationIdList[];
|
static const int16_t HIGHFLASH automationIdList[];
|
||||||
static const int16_t FLASH rosterIdList[];
|
static const int16_t HIGHFLASH rosterIdList[];
|
||||||
static const FSH * getRouteDescription(int16_t id);
|
static const FSH * getRouteDescription(int16_t id);
|
||||||
static char getRouteType(int16_t id);
|
static char getRouteType(int16_t id);
|
||||||
static const FSH * getTurnoutDescription(int16_t id);
|
static const FSH * getTurnoutDescription(int16_t id);
|
||||||
@ -150,8 +150,8 @@ private:
|
|||||||
void printMessage2(const FSH * msg);
|
void printMessage2(const FSH * msg);
|
||||||
|
|
||||||
static bool diag;
|
static bool diag;
|
||||||
static const FLASH byte RouteCode[];
|
static const HIGHFLASH byte RouteCode[];
|
||||||
static const FLASH int16_t SignalDefinitions[];
|
static const HIGHFLASH int16_t SignalDefinitions[];
|
||||||
static byte flags[MAX_FLAGS];
|
static byte flags[MAX_FLAGS];
|
||||||
static LookList * sequenceLookup;
|
static LookList * sequenceLookup;
|
||||||
static LookList * onThrowLookup;
|
static LookList * onThrowLookup;
|
||||||
|
@ -73,14 +73,14 @@ void exrailHalSetup() {
|
|||||||
#include "EXRAIL2MacroReset.h"
|
#include "EXRAIL2MacroReset.h"
|
||||||
#undef ROUTE
|
#undef ROUTE
|
||||||
#define ROUTE(id, description) id,
|
#define ROUTE(id, description) id,
|
||||||
const int16_t FLASH RMFT2::routeIdList[]= {
|
const int16_t HIGHFLASH RMFT2::routeIdList[]= {
|
||||||
#include "myAutomation.h"
|
#include "myAutomation.h"
|
||||||
0};
|
0};
|
||||||
// Pass 2a create throttle automation list
|
// Pass 2a create throttle automation list
|
||||||
#include "EXRAIL2MacroReset.h"
|
#include "EXRAIL2MacroReset.h"
|
||||||
#undef AUTOMATION
|
#undef AUTOMATION
|
||||||
#define AUTOMATION(id, description) id,
|
#define AUTOMATION(id, description) id,
|
||||||
const int16_t FLASH RMFT2::automationIdList[]= {
|
const int16_t HIGHFLASH RMFT2::automationIdList[]= {
|
||||||
#include "myAutomation.h"
|
#include "myAutomation.h"
|
||||||
0};
|
0};
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ const byte RMFT2::rosterNameCount=0
|
|||||||
#include "EXRAIL2MacroReset.h"
|
#include "EXRAIL2MacroReset.h"
|
||||||
#undef ROSTER
|
#undef ROSTER
|
||||||
#define ROSTER(cabid,name,funcmap...) cabid,
|
#define ROSTER(cabid,name,funcmap...) cabid,
|
||||||
const int16_t FLASH RMFT2::rosterIdList[]={
|
const int16_t HIGHFLASH RMFT2::rosterIdList[]={
|
||||||
#include "myAutomation.h"
|
#include "myAutomation.h"
|
||||||
0};
|
0};
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ const FSH * RMFT2::getRosterFunctions(int16_t id) {
|
|||||||
#undef VIRTUAL_SIGNAL
|
#undef VIRTUAL_SIGNAL
|
||||||
#define VIRTUAL_SIGNAL(id) id,0,0,0,
|
#define VIRTUAL_SIGNAL(id) id,0,0,0,
|
||||||
|
|
||||||
const FLASH int16_t RMFT2::SignalDefinitions[] = {
|
const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
|
||||||
#include "myAutomation.h"
|
#include "myAutomation.h"
|
||||||
0,0,0,0 };
|
0,0,0,0 };
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = {
|
|||||||
|
|
||||||
// Build RouteCode
|
// Build RouteCode
|
||||||
const int StringMacroTracker2=__COUNTER__;
|
const int StringMacroTracker2=__COUNTER__;
|
||||||
const FLASH byte RMFT2::RouteCode[] = {
|
const HIGHFLASH byte RMFT2::RouteCode[] = {
|
||||||
#include "myAutomation.h"
|
#include "myAutomation.h"
|
||||||
OPCODE_ENDTASK,0,0,OPCODE_ENDEXRAIL,0,0 };
|
OPCODE_ENDTASK,0,0,OPCODE_ENDEXRAIL,0,0 };
|
||||||
|
|
||||||
|
50
FSH.h
50
FSH.h
@ -34,32 +34,48 @@
|
|||||||
* PROGMEM use FLASH instead
|
* PROGMEM use FLASH instead
|
||||||
* pgm_read_byte_near use GETFLASH instead.
|
* pgm_read_byte_near use GETFLASH instead.
|
||||||
* pgm_read_word_near use GETFLASHW instead.
|
* pgm_read_word_near use GETFLASHW instead.
|
||||||
|
*
|
||||||
|
* Also:
|
||||||
|
* HIGHFLASH - PROGMEM forced to end of link so needs far pointers.
|
||||||
|
* GETHIGHFLASH,GETHIGHFLASHW to access them
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#if defined(ARDUINO_ARCH_MEGAAVR)
|
#ifdef ARDUINO_ARCH_AVR
|
||||||
|
// AVR devices have flash memory mapped differently
|
||||||
|
// progmem can be accessed by _near functions
|
||||||
|
typedef __FlashStringHelper FSH;
|
||||||
|
#define FLASH PROGMEM
|
||||||
|
#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)
|
||||||
|
// AVR_MEGA memory deliberately placed at end of link may need _far functions
|
||||||
|
#define HIGHFLASH __attribute__((section(".fini2")))
|
||||||
|
#define GETHIGHFLASH(data,offset) pgm_read_byte_far(pgm_get_far_address(data)+offset)
|
||||||
|
#define GETHIGHFLASHW(data,offset) pgm_read_word_far(pgm_get_far_address(data)+offset)
|
||||||
|
#else
|
||||||
|
// AVR_UNO/NANO runtime does not support _far functions so just use _near equivalent
|
||||||
|
// as there is no progmem above 32kb anyway.
|
||||||
|
#define HIGHFLASH FLASH
|
||||||
|
#define GETHIGHFLASH(data,offset) pgm_read_byte_near(((byte*)data)+(offset))
|
||||||
|
#define GETHIGHFLASHW(data,offset) pgm_read_word_near(((byte*)data)+(offset))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Non-AVR Flat-memory devices have no need of this support so can be remapped to normal memory access
|
||||||
#ifdef F
|
#ifdef F
|
||||||
#undef F
|
#undef F
|
||||||
#endif
|
#endif
|
||||||
#define F(str) (str)
|
#define F(str) (str)
|
||||||
typedef char FSH;
|
typedef char FSH;
|
||||||
#define GETFLASH(addr) (*(const unsigned char *)(addr))
|
|
||||||
#define GETFLASHW(addr) (*(const unsigned short *)(addr))
|
|
||||||
#define FLASH
|
#define FLASH
|
||||||
|
#define HIGHFLASH
|
||||||
|
#define GETFLASH(addr) (*(const unsigned char *)(addr))
|
||||||
|
#define GETFLASHW(addr) ((*(const unsigned int8_t *)(addr)) | ((*(const unsigned int8_t *)(addr+1)) << 8))
|
||||||
|
#define GETHIGHFLASH(data,offset) GETFLASH(((byte*)data)+(offset))
|
||||||
|
#define GETHIGHFLASHW(data,offset) GETFLASHW(((byte*)data)+(offset))
|
||||||
#define strlen_P strlen
|
#define strlen_P strlen
|
||||||
#define strcpy_P strcpy
|
#define strcpy_P strcpy
|
||||||
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_STM32)
|
|
||||||
typedef __FlashStringHelper FSH;
|
|
||||||
#define GETFLASH(addr) pgm_read_byte(addr)
|
|
||||||
#define GETFLASHW(addr) (*(const unsigned int8_t *)(addr)) | ((*(const unsigned int8_t *)(addr+1)) << 8)
|
|
||||||
#ifdef FLASH
|
|
||||||
#undef FLASH
|
|
||||||
#endif
|
|
||||||
#define FLASH PROGMEM
|
|
||||||
#else
|
|
||||||
typedef __FlashStringHelper FSH;
|
|
||||||
#define GETFLASH(addr) pgm_read_byte_near(addr)
|
|
||||||
#define GETFLASHW(addr) pgm_read_word_near(addr)
|
|
||||||
#define FLASH PROGMEM
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
@ -216,8 +216,8 @@ void WiThrottle::parse(RingStream * stream, byte * cmdx) {
|
|||||||
StringFormatter::send(stream,F("PRT]\\[Routes}|{Route]\\[Set}|{2]\\[Handoff}|{4\nPRL"));
|
StringFormatter::send(stream,F("PRT]\\[Routes}|{Route]\\[Set}|{2]\\[Handoff}|{4\nPRL"));
|
||||||
for (byte pass=0;pass<2;pass++) {
|
for (byte pass=0;pass<2;pass++) {
|
||||||
// first pass automations, second pass routes.
|
// first pass automations, second pass routes.
|
||||||
for (int ix=0;;ix++) {
|
for (int ix=0;;ix+=2) {
|
||||||
int16_t id=GETFLASHW((pass?RMFT2::automationIdList:RMFT2::routeIdList)+ix);
|
int16_t id=GETHIGHFLASHW((pass?RMFT2::automationIdList:RMFT2::routeIdList),ix);
|
||||||
if (id==0) break;
|
if (id==0) break;
|
||||||
const FSH * desc=RMFT2::getRouteDescription(id);
|
const FSH * desc=RMFT2::getRouteDescription(id);
|
||||||
StringFormatter::send(stream,F("]\\[%c%d}|{%S}|{%c"),
|
StringFormatter::send(stream,F("]\\[%c%d}|{%S}|{%c"),
|
||||||
@ -297,8 +297,8 @@ void WiThrottle::parse(RingStream * stream, byte * cmdx) {
|
|||||||
StringFormatter::send(stream,F("PPA%x\n"),TrackManager::getMainPower()==POWERMODE::ON);
|
StringFormatter::send(stream,F("PPA%x\n"),TrackManager::getMainPower()==POWERMODE::ON);
|
||||||
#ifdef EXRAIL_ACTIVE
|
#ifdef EXRAIL_ACTIVE
|
||||||
StringFormatter::send(stream,F("RL%d"), RMFT2::rosterNameCount);
|
StringFormatter::send(stream,F("RL%d"), RMFT2::rosterNameCount);
|
||||||
for (int16_t r=0;r<RMFT2::rosterNameCount;r++) {
|
for (int16_t r=0;r<RMFT2::rosterNameCount;r+=2) {
|
||||||
int16_t cabid=GETFLASHW(RMFT2::rosterIdList+r);
|
int16_t cabid=GETHIGHFLASHW(RMFT2::rosterIdList,r);
|
||||||
StringFormatter::send(stream,F("]\\[%S}|{%d}|{%c"),
|
StringFormatter::send(stream,F("]\\[%S}|{%d}|{%c"),
|
||||||
RMFT2::getRosterName(cabid),cabid,cabid<128?'S':'L');
|
RMFT2::getRosterName(cabid),cabid,cabid<128?'S':'L');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user