mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-04-13 00:40:12 +02:00
STASH upgrade
This commit is contained in:
parent
5d18c910fa
commit
6d8ca67a2b
@ -119,6 +119,7 @@ Once a new OPCODE is decided upon, update this list.
|
||||
#include "version.h"
|
||||
#include "KeywordHasher.h"
|
||||
#include "CamParser.h"
|
||||
#include "Stash.h"
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "WifiESP32.h"
|
||||
#endif
|
||||
@ -777,7 +778,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||
|
||||
case 'J' : // throttle info access
|
||||
{
|
||||
if ((params<1) | (params>3)) break; // <J>
|
||||
if (params<1) break; // <J>
|
||||
//if ((params<1) | (params>2)) break; // <J>
|
||||
int16_t id=(params==2)?p[1]:0;
|
||||
switch(p[0]) {
|
||||
@ -801,7 +802,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||
return;
|
||||
|
||||
case "L"_hk: // <JL display row> track state and mA value on display
|
||||
if (params<3) break;
|
||||
if (params!=3) break;
|
||||
TrackManager::reportCurrentLCD(p[1], p[2]); // Track power status
|
||||
return;
|
||||
|
||||
@ -810,11 +811,10 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||
StringFormatter::send(stream, F("<jA>\n"));
|
||||
return;
|
||||
|
||||
case "M"_hk: // <JM> intercepted by EXRAIL
|
||||
if (params>1) break; // invalid cant do
|
||||
// <JM> requests stash size so say none.
|
||||
StringFormatter::send(stream,F("<jM 0>\n"));
|
||||
return;
|
||||
case "M"_hk: // <JM> Stash management
|
||||
if (parseJM(stream, params, p))
|
||||
return;
|
||||
break;
|
||||
|
||||
case "R"_hk: // <JR> returns rosters
|
||||
StringFormatter::send(stream, F("<jR"));
|
||||
@ -1405,6 +1405,40 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[])
|
||||
}
|
||||
#endif
|
||||
|
||||
bool DCCEXParser::parseJM(Print *stream, int16_t params, int16_t p[]) {
|
||||
switch (params) {
|
||||
case 1: // <JM> list all stashed automations
|
||||
Stash::list(stream);
|
||||
return true;
|
||||
|
||||
case 2: // <JM id> get stash value
|
||||
Stash::list(stream, p[1]);
|
||||
return true;
|
||||
|
||||
case 3: //
|
||||
if (p[1]=="CLEAR"_hk) {
|
||||
if (p[2]=="ALL"_hk) { // <JM CLEAR ALL>
|
||||
Stash::clearAll();
|
||||
return true;
|
||||
}
|
||||
Stash::clear(p[2]); // <JM CLEAR id>
|
||||
return true;
|
||||
}
|
||||
Stash::set(p[1], p[2]); // <JM id loco>
|
||||
return true;
|
||||
|
||||
case 4: // <JM CLEAR ANY id>
|
||||
if (p[1]=="CLEAR"_hk && p[2]=="ANY"_hk) {
|
||||
// <JM CLEAR ANY id>
|
||||
Stash::clearAny(p[3]);
|
||||
return true;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// CALLBACKS must be static
|
||||
bool DCCEXParser::stashCallback(Print *stream, int16_t p[MAX_COMMAND_PARAMS], RingStream * ringStream)
|
||||
{
|
||||
|
@ -52,6 +52,7 @@ struct DCCEXParser
|
||||
static bool parsef(Print * stream, int16_t params, int16_t p[]);
|
||||
static bool parseC(Print * stream, int16_t params, int16_t p[]);
|
||||
static bool parseD(Print * stream, int16_t params, int16_t p[]);
|
||||
static bool parseJM(Print * stream, int16_t params, int16_t p[]);
|
||||
#ifndef IO_NO_HAL
|
||||
static bool parseI(Print * stream, int16_t params, int16_t p[]);
|
||||
#endif
|
||||
|
56
EXRAIL2.cpp
56
EXRAIL2.cpp
@ -57,6 +57,7 @@
|
||||
#include "Turntables.h"
|
||||
#include "IODevice.h"
|
||||
#include "EXRAILSensor.h"
|
||||
#include "Stash.h"
|
||||
|
||||
|
||||
// One instance of RMFT clas is used for each "thread" in the automation.
|
||||
@ -92,8 +93,7 @@ LookList * RMFT2::onBlockEnterLookup=NULL;
|
||||
LookList * RMFT2::onBlockExitLookup=NULL;
|
||||
byte * RMFT2::routeStateArray=nullptr;
|
||||
const FSH * * RMFT2::routeCaptionArray=nullptr;
|
||||
int16_t * RMFT2::stashArray=nullptr;
|
||||
int16_t RMFT2::maxStashId=0;
|
||||
|
||||
|
||||
// getOperand instance version, uses progCounter from instance.
|
||||
uint16_t RMFT2::getOperand(byte n) {
|
||||
@ -258,13 +258,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
||||
IODevice::configureInput((VPIN)pin,true);
|
||||
break;
|
||||
}
|
||||
case OPCODE_STASH:
|
||||
case OPCODE_CLEAR_STASH:
|
||||
case OPCODE_PICKUP_STASH: {
|
||||
maxStashId=max(maxStashId,((int16_t)operand));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case OPCODE_ATGTE:
|
||||
case OPCODE_ATLT:
|
||||
case OPCODE_IFGTE:
|
||||
@ -352,13 +346,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) {
|
||||
}
|
||||
SKIPOP; // include ENDROUTES opcode
|
||||
|
||||
if (compileFeatures & FEATURE_STASH) {
|
||||
// create the stash array from the highest id found
|
||||
if (maxStashId>0) stashArray=(int16_t*)calloc(maxStashId+1, sizeof(int16_t));
|
||||
//TODO check EEPROM and fetch stashArray
|
||||
}
|
||||
|
||||
DIAG(F("EXRAIL %db, fl=%d, stash=%d"),progCounter,MAX_FLAGS, maxStashId);
|
||||
DIAG(F("EXRAIL %db, fl=%d"),progCounter,MAX_FLAGS);
|
||||
|
||||
// Removed for 4.2.31 new RMFT2(0); // add the startup route
|
||||
diag=saved_diag;
|
||||
@ -815,6 +803,10 @@ void RMFT2::loop2() {
|
||||
case OPCODE_IFCLOSED:
|
||||
skipIf=Turnout::isThrown(operand);
|
||||
break;
|
||||
|
||||
case OPCODE_IFSTASH:
|
||||
skipIf=Stash::get(operand)==0;
|
||||
break;
|
||||
|
||||
#ifndef IO_NO_HAL
|
||||
case OPCODE_IFTTPOSITION: // do block if turntable at this position
|
||||
@ -1067,30 +1059,32 @@ void RMFT2::loop2() {
|
||||
break;
|
||||
|
||||
case OPCODE_STASH:
|
||||
if (compileFeatures & FEATURE_STASH)
|
||||
stashArray[operand] = invert? -loco : loco;
|
||||
Stash::set(operand,invert? -loco : loco);
|
||||
break;
|
||||
|
||||
case OPCODE_CLEAR_STASH:
|
||||
if (compileFeatures & FEATURE_STASH)
|
||||
stashArray[operand] = 0;
|
||||
Stash::clear(operand);
|
||||
break;
|
||||
|
||||
case OPCODE_CLEAR_ALL_STASH:
|
||||
if (compileFeatures & FEATURE_STASH)
|
||||
for (int i=0;i<=maxStashId;i++) stashArray[operand]=0;
|
||||
Stash::clearAll();
|
||||
break;
|
||||
|
||||
case OPCODE_CLEAR_ANY_STASH:
|
||||
if (loco) Stash::clearAny(loco);
|
||||
break;
|
||||
|
||||
case OPCODE_PICKUP_STASH:
|
||||
if (compileFeatures & FEATURE_STASH) {
|
||||
int16_t x=stashArray[operand];
|
||||
if (x>=0) {
|
||||
loco=x;
|
||||
invert=false;
|
||||
break;
|
||||
}
|
||||
loco=-x;
|
||||
invert=true;
|
||||
{
|
||||
auto x=Stash::get(operand);
|
||||
if (x>=0) {
|
||||
loco=x;
|
||||
invert=false;
|
||||
}
|
||||
else {
|
||||
loco=-x;
|
||||
invert=true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -77,6 +77,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,OPCODE_TOGGLE_TURNOUT,
|
||||
OPCODE_ROUTE_ACTIVE,OPCODE_ROUTE_INACTIVE,OPCODE_ROUTE_HIDDEN,
|
||||
OPCODE_ROUTE_DISABLED,
|
||||
OPCODE_STASH,OPCODE_CLEAR_STASH,OPCODE_CLEAR_ALL_STASH,OPCODE_PICKUP_STASH,
|
||||
OPCODE_CLEAR_ANY_STASH,
|
||||
OPCODE_ONBUTTON,OPCODE_ONSENSOR,
|
||||
OPCODE_NEOPIXEL,
|
||||
OPCODE_ONBLOCKENTER,OPCODE_ONBLOCKEXIT,
|
||||
@ -93,7 +94,8 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,OPCODE_TOGGLE_TURNOUT,
|
||||
OPCODE_IFCLOSED,OPCODE_IFTHROWN,
|
||||
OPCODE_IFRE,
|
||||
OPCODE_IFLOCO,
|
||||
OPCODE_IFTTPOSITION
|
||||
OPCODE_IFTTPOSITION,
|
||||
OPCODE_IFSTASH,
|
||||
};
|
||||
|
||||
// Ensure thrunge_lcd is put last as there may be more than one display,
|
||||
@ -137,7 +139,7 @@ enum SignalType {
|
||||
static const byte FEATURE_LCC = 0x40;
|
||||
static const byte FEATURE_ROSTER= 0x20;
|
||||
static const byte FEATURE_ROUTESTATE= 0x10;
|
||||
static const byte FEATURE_STASH = 0x08;
|
||||
// spare = 0x08;
|
||||
static const byte FEATURE_BLINK = 0x04;
|
||||
static const byte FEATURE_SENSOR = 0x02;
|
||||
static const byte FEATURE_BLOCK = 0x01;
|
||||
|
@ -46,6 +46,7 @@
|
||||
#undef CALL
|
||||
#undef CLEAR_STASH
|
||||
#undef CLEAR_ALL_STASH
|
||||
#undef CLEAR_ANY_STASH
|
||||
#undef CLOSE
|
||||
#undef CONFIGURE_SERVO
|
||||
#undef DCC_SIGNAL
|
||||
@ -88,6 +89,7 @@
|
||||
#undef IFRANDOM
|
||||
#undef IFRED
|
||||
#undef IFRESERVE
|
||||
#undef IFSTASH
|
||||
#undef IFTHROWN
|
||||
#undef IFTIMEOUT
|
||||
#undef IFTTPOSITION
|
||||
@ -338,6 +340,11 @@
|
||||
* @brief Clears all stashed loco values
|
||||
*/
|
||||
#define CLEAR_ALL_STASH
|
||||
/**
|
||||
* @def CLEAR_ANY_STASH
|
||||
* @brief Clears loco value from all stash entries
|
||||
*/
|
||||
#define CLEAR_ANY_STASH
|
||||
/**
|
||||
* @def CLOSE(turnout_id)
|
||||
* @brief Close turnout by id
|
||||
@ -602,6 +609,13 @@
|
||||
* @param signal_id
|
||||
*/
|
||||
#define IFRED(signal_id)
|
||||
/**
|
||||
* @def IFSTASH(stash_id)
|
||||
* @brief Checks if given stash entry has a non zero value
|
||||
* @see IF
|
||||
* @param stash_id
|
||||
*/
|
||||
#define IFSTASH(stash_id)
|
||||
/**
|
||||
* @def IFTHROWN(turnout_id)
|
||||
* @brief Checks if given turnout is in THROWN state
|
||||
|
@ -181,36 +181,7 @@ void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "M"_hk:
|
||||
// NOTE: we only need to handle valid calls here because
|
||||
// DCCEXParser has to have code to handle the <J<> cases where
|
||||
// exrail isnt involved anyway.
|
||||
// This entire code block is compiled out if STASH macros not used
|
||||
if (!(compileFeatures & FEATURE_STASH)) return;
|
||||
if (paramCount==1) { // <JM>
|
||||
StringFormatter::send(stream,F("<jM %d>\n"),maxStashId);
|
||||
opcode=0;
|
||||
break;
|
||||
}
|
||||
if (paramCount==2) { // <JM id>
|
||||
if (p[1]<=0 || p[1]>maxStashId) break;
|
||||
StringFormatter::send(stream,F("<jM %d %d>\n"),
|
||||
p[1],stashArray[p[1]]);
|
||||
opcode=0;
|
||||
break;
|
||||
}
|
||||
if (paramCount==3) { // <JM id cab>
|
||||
if (p[1]<=0 || p[1]>maxStashId) break;
|
||||
stashArray[p[1]]=p[2];
|
||||
opcode=0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'K': // <K blockid loco> Block enter
|
||||
case 'k': // <k blockid loco> Block exit
|
||||
@ -223,6 +194,7 @@ void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
|
||||
|
||||
@ -268,15 +240,6 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
|
||||
slot.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (compileFeatures & FEATURE_STASH) {
|
||||
for (int i=1;i<=maxStashId;i++) {
|
||||
if (stashArray[i])
|
||||
StringFormatter::send(stream,F("\nSTASH[%d] Loco=%d"),
|
||||
i, stashArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
StringFormatter::send(stream,F(" *>\n"));
|
||||
return true;
|
||||
}
|
||||
|
@ -136,11 +136,11 @@ constexpr bool unsafePin(const int16_t value, const uint16_t pos=0 ) {
|
||||
|
||||
// check duplicate sequences
|
||||
#undef SEQUENCE
|
||||
#define SEQUENCE(id) static_assert(seqCount(id)==1,"\n\nUSER ERROR: Duplicate ROUTE/AUTOMATION/SEQUENCE(" #id")\n");
|
||||
#define SEQUENCE(id) static_assert(seqCount(id)==1,"\n\nUSER ERROR: Duplicate ROUTE/AUTOMATION/SEQUENCE(" #id ")\n");
|
||||
#undef AUTOMATION
|
||||
#define AUTOMATION(id,description) static_assert(seqCount(id)==1,"\n\nUSER ERROR: Duplicate ROUTE/AUTOMATION/SEQUENCE(" #id")\n");
|
||||
#define AUTOMATION(id,description) static_assert(seqCount(id)==1,"\n\nUSER ERROR: Duplicate ROUTE/AUTOMATION/SEQUENCE(" #id ")\n");
|
||||
#undef ROUTE
|
||||
#define ROUTE(id,description) static_assert(seqCount(id)==1,"\n\nUSER ERROR: Duplicate ROUTE/AUTOMATION/SEQUENCE(" #id")\n");
|
||||
#define ROUTE(id,description) static_assert(seqCount(id)==1,"\n\nUSER ERROR: Duplicate ROUTE/AUTOMATION/SEQUENCE(" #id ")\n");
|
||||
|
||||
// check dangerous pins
|
||||
#define _PIN_RESERVED_ "\n\nUSER ERROR: Pin is used by Motor Shield or other critical function.\n"
|
||||
|
@ -154,14 +154,6 @@ bool exrailHalSetup() {
|
||||
#undef ROUTE_CAPTION
|
||||
#define ROUTE_CAPTION(id,caption) | FEATURE_ROUTESTATE
|
||||
|
||||
#undef CLEAR_STASH
|
||||
#define CLEAR_STASH(id) | FEATURE_STASH
|
||||
#undef CLEAR_ALL_STASH
|
||||
#define CLEAR_ALL_STASH | FEATURE_STASH
|
||||
#undef PICKUP_STASH
|
||||
#define PICKUP_STASH(id) | FEATURE_STASH
|
||||
#undef STASH
|
||||
#define STASH(id) | FEATURE_STASH
|
||||
#undef BLINK
|
||||
#define BLINK(vpin,onDuty,offDuty) | FEATURE_BLINK
|
||||
#undef ONBUTTON
|
||||
@ -435,6 +427,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
|
||||
#define CALL(route) OPCODE_CALL,V(route),
|
||||
#define CLEAR_STASH(id) OPCODE_CLEAR_STASH,V(id),
|
||||
#define CLEAR_ALL_STASH OPCODE_CLEAR_ALL_STASH,V(0),
|
||||
#define CLEAR_ANY_STASH OPCODE_CLEAR_ANY_STASH,V(0),
|
||||
#define CLOSE(id) OPCODE_CLOSE,V(id),
|
||||
#define CONFIGURE_SERVO(vpin,pos1,pos2,profile)
|
||||
#ifndef IO_NO_HAL
|
||||
@ -481,6 +474,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
|
||||
#define IFRANDOM(percent) OPCODE_IFRANDOM,V(percent),
|
||||
#define IFRED(signal_id) OPCODE_IFRED,V(signal_id),
|
||||
#define IFRESERVE(block) OPCODE_IFRESERVE,V(block),
|
||||
#define IFSTASH(stash_id) OPCODE_IFSTASH,V(stash_id),
|
||||
#define IFTHROWN(turnout_id) OPCODE_IFTHROWN,V(turnout_id),
|
||||
#define IFTIMEOUT OPCODE_IFTIMEOUT,0,0,
|
||||
#ifndef IO_NO_HAL
|
||||
|
21
Release_Notes/Stash.md
Normal file
21
Release_Notes/Stash.md
Normal file
@ -0,0 +1,21 @@
|
||||
# The STASH feature of exrail.
|
||||
|
||||
STASH is used for scenarios where it is helpful to relate a loco id to where it is parked. For example a fiddle yard may have 10 tracks and it's much easier for the operator to select a train to depart by using the track number, or pressing a button relating to that track, rather than by knowing the loco id which may be difficult to see.
|
||||
|
||||
Automated yard parking can use the stash to determine which tracks are empty without the need for block occupancy detectors.
|
||||
|
||||
Note that a negative locoid may be stashed to indicate that the loco will operate with inverted direction. For example a loco facing backwards, with the INVERT_DRECTION state may be stashed by exrail and the invert state will be restored along with the loco id when using the PICKUP_STASH. CLEAR_ANY_STASH will clear all references to the loco regardless of direction.
|
||||
|
||||
The following Stash commands are available:
|
||||
| EXRAIL command | Serial protocol | function |
|
||||
| -------------- | --------------- | -------- |
|
||||
| STASH(s) | `<JM s locoid>` | Save the current loco id in the stash array element s. |
|
||||
| CLEAR_STASH(s) | `<JM s 0>` | Sets stash array element s to zero. |
|
||||
| CLEAR_ALL_STASH | `<JM CLEAR ALL>` | sets all stash entries to zero |
|
||||
| CLEAR_ANY_STASH | `<JM CLEAR ANY locoid>` | removes current loco from all stash elements |
|
||||
| PICKUP_STASH(s) | N/A | sets current loco to stash element s |
|
||||
| IFSTASH(s) | N/A | True if stash element s is not zero |
|
||||
| N/A | `<JM>` | query all stashes (returns `<jM s loco>` where loco is not zero)
|
||||
| N/A | `<JM stash>` | Query loco in stash (returns `<jM s loco>`)
|
||||
|
||||
|
89
Stash.cpp
Normal file
89
Stash.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* © 2024 Chris Harlow
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of DCC-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "Stash.h"
|
||||
#include "StringFormatter.h"
|
||||
|
||||
Stash::Stash(int16_t stash_id, int16_t loco_id) {
|
||||
this->stashId = stash_id;
|
||||
this->locoId = loco_id;
|
||||
this->next = first;
|
||||
first = this;
|
||||
}
|
||||
|
||||
void Stash::clearAll() {
|
||||
for (auto s=first;s;s=s->next) {
|
||||
s->locoId = 0;
|
||||
s->stashId =0;
|
||||
}
|
||||
}
|
||||
|
||||
void Stash::clearAny(int16_t loco_id) {
|
||||
auto lid=abs(loco_id);
|
||||
for (auto s=first;s;s=s->next)
|
||||
if (abs(s->locoId) == lid) {
|
||||
s->locoId = 0;
|
||||
s->stashId =0;
|
||||
}
|
||||
}
|
||||
|
||||
void Stash::clear(int16_t stash_id) {
|
||||
set(stash_id,0);
|
||||
}
|
||||
|
||||
int16_t Stash::get(int16_t stash_id) {
|
||||
for (auto s=first;s;s=s->next)
|
||||
if (s->stashId == stash_id) return s->locoId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Stash::set(int16_t stash_id, int16_t loco_id) {
|
||||
// replace any existing stash
|
||||
for (auto s=first;s;s=s->next)
|
||||
if (s->stashId == stash_id) {
|
||||
s->locoId=loco_id;
|
||||
if (loco_id==0) s->stashId=0; // recycle
|
||||
return;
|
||||
}
|
||||
if (loco_id==0) return; // no need to create a zero entry.
|
||||
|
||||
// replace any empty stash
|
||||
for (auto s=first;s;s=s->next)
|
||||
if (s->locoId == 0) {
|
||||
s->locoId=loco_id;
|
||||
s->stashId=stash_id;
|
||||
return;
|
||||
}
|
||||
// create a new stash
|
||||
new Stash(stash_id, loco_id);
|
||||
}
|
||||
|
||||
void Stash::list(Print * stream, int16_t stash_id) {
|
||||
bool sent=false;
|
||||
for (auto s=first;s;s=s->next)
|
||||
if ((s->locoId) && (stash_id==0 || s->stashId==stash_id)) {
|
||||
StringFormatter::send(stream,F("<jM %d %d>\n"),
|
||||
s->stashId,s->locoId);
|
||||
sent=true;
|
||||
}
|
||||
if (!sent) StringFormatter::send(stream,F("<jM %d 0>\n"),
|
||||
stash_id);
|
||||
}
|
||||
|
||||
Stash* Stash::first=nullptr;
|
39
Stash.h
Normal file
39
Stash.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* © 2024 Chris Harlow
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is part of DCC-EX
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* It is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef Stash_h
|
||||
#define Stash_h
|
||||
#include <Arduino.h>
|
||||
|
||||
class Stash {
|
||||
public:
|
||||
static void clear(int16_t stash_id);
|
||||
static void clearAll();
|
||||
static void clearAny(int16_t loco_id);
|
||||
static int16_t get(int16_t stash_id);
|
||||
static void set(int16_t stash_id, int16_t loco_id);
|
||||
static void list(Print * stream, int16_t stash_id=0); // id0 = LIST ALL
|
||||
private:
|
||||
Stash(int16_t stash_id, int16_t loco_id);
|
||||
static Stash* first;
|
||||
Stash* next;
|
||||
int16_t stashId;
|
||||
int16_t locoId;
|
||||
};
|
||||
#endif
|
@ -3,7 +3,11 @@
|
||||
|
||||
#include "StringFormatter.h"
|
||||
|
||||
#define VERSION "5.5.17"
|
||||
#define VERSION "5.5.18"
|
||||
// 5.5.18 - New STASH internals
|
||||
// - EXRAIL IFSTASH/CLEAR_ANY_STASH
|
||||
// - <JM CLEAR ANY id> to clear any stash with loco id
|
||||
// - See Release_Notes/Stash.md
|
||||
// 5.5.17 - Extensive new compile time checking in exrail scripts (duplicate sequences etc), no function change
|
||||
// 5.5.16 - DOXYGEN comments in EXRAIL2MacroReset.h
|
||||
// 5.5.15 - Support for F429ZI/F329ZI
|
||||
|
Loading…
Reference in New Issue
Block a user