mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-22 23:56:13 +01:00
Add <W locoid> command
Automatically clears consist and manages short/long addresses
This commit is contained in:
parent
b537d7a318
commit
7d90e4241a
63
DCC.cpp
63
DCC.cpp
|
@ -399,6 +399,44 @@ const ackOp PROGMEM LOCO_ID_PROG[] = {
|
|||
FAIL
|
||||
};
|
||||
|
||||
const ackOp PROGMEM SHORT_LOCO_ID_PROG[] = {
|
||||
BASELINE,
|
||||
SETCV,(ackOp)19,
|
||||
SETBYTE, (ackOp)0,
|
||||
WB,WACK, // ignore router without cv19 support
|
||||
// Turn off long address flag
|
||||
SETCV,(ackOp)29,
|
||||
SETBIT,(ackOp)5,
|
||||
W0,WACK,NAKFAIL,
|
||||
SETCV, (ackOp)1,
|
||||
SETBYTEL, // low byte of word
|
||||
WB,WACK,NAKFAIL,
|
||||
VB,WACK,ITCB,
|
||||
FAIL
|
||||
};
|
||||
|
||||
const ackOp PROGMEM LONG_LOCO_ID_PROG[] = {
|
||||
BASELINE,
|
||||
// Clear consist CV 19
|
||||
SETCV,(ackOp)19,
|
||||
SETBYTE, (ackOp)0,
|
||||
WB,WACK, // ignore router without cv19 support
|
||||
// Turn on long address flag cv29 bit 5
|
||||
SETCV,(ackOp)29,
|
||||
SETBIT,(ackOp)5,
|
||||
W1,WACK,NAKFAIL,
|
||||
// Store high byte of address in cv 17
|
||||
SETCV, (ackOp)17,
|
||||
SETBYTEH, // high byte of word
|
||||
WB,WACK,NAKFAIL,
|
||||
VB,WACK,NAKFAIL,
|
||||
// store
|
||||
SETCV, (ackOp)18,
|
||||
SETBYTEL, // low byte of word
|
||||
WB,WACK,NAKFAIL,
|
||||
VB,WACK,ITC1, // callback(1) means Ok
|
||||
FAIL
|
||||
};
|
||||
|
||||
// On the following prog-track functions blocking defaults to false.
|
||||
// blocking=true forces the API to block, waiting for the response and invoke the callback BEFORE returning.
|
||||
|
@ -441,6 +479,13 @@ void DCC::getLocoId(ACK_CALLBACK callback, bool blocking) {
|
|||
ackManagerSetup(0,0, LOCO_ID_PROG, callback, blocking);
|
||||
}
|
||||
|
||||
void DCC::setLocoId(int id,ACK_CALLBACK callback, bool blocking) {
|
||||
if (id<=0 || id>9999) callback(-1);
|
||||
int wordval;
|
||||
if (id<=127) ackManagerSetup(id,SHORT_LOCO_ID_PROG, callback, blocking);
|
||||
else ackManagerSetup(id | 0xc000,LONG_LOCO_ID_PROG, callback, blocking);
|
||||
}
|
||||
|
||||
void DCC::forgetLoco(int cab) { // removes any speed reminders for this loco
|
||||
int reg=lookupSpeedTable(cab);
|
||||
if (reg>=0) speedTable[reg].loco=0;
|
||||
|
@ -573,7 +618,8 @@ int DCC::nextLoco = 0;
|
|||
ackOp const * DCC::ackManagerProg;
|
||||
byte DCC::ackManagerByte;
|
||||
byte DCC::ackManagerStash;
|
||||
int DCC::ackManagerCv;
|
||||
int DCC::ackManagerWord;
|
||||
int DCC::ackManagerCv;
|
||||
byte DCC::ackManagerBitNum;
|
||||
bool DCC::ackReceived;
|
||||
|
||||
|
@ -588,6 +634,13 @@ void DCC::ackManagerSetup(int cv, byte byteValueOrBitnum, ackOp const program[]
|
|||
if (blocking) ackManagerLoop(blocking);
|
||||
}
|
||||
|
||||
void DCC::ackManagerSetup(int wordval, ackOp const program[], ACK_CALLBACK callback, bool blocking) {
|
||||
ackManagerWord=wordval;
|
||||
ackManagerProg = program;
|
||||
ackManagerCallback = callback;
|
||||
if (blocking) ackManagerLoop(blocking);
|
||||
}
|
||||
|
||||
const byte RESET_MIN=8; // tuning of reset counter before sending message
|
||||
|
||||
// checkRessets return true if the caller should yield back to loop and try later.
|
||||
|
@ -742,6 +795,14 @@ void DCC::ackManagerLoop(bool blocking) {
|
|||
ackManagerByte=pgm_read_byte_near(ackManagerProg);
|
||||
break;
|
||||
|
||||
case SETBYTEH:
|
||||
ackManagerByte=highByte(ackManagerWord);
|
||||
break;
|
||||
|
||||
case SETBYTEL:
|
||||
ackManagerByte=lowByte(ackManagerWord);
|
||||
break;
|
||||
|
||||
case STASHLOCOID:
|
||||
ackManagerStash=ackManagerByte; // stash value from CV17
|
||||
break;
|
||||
|
|
5
DCC.h
5
DCC.h
|
@ -45,6 +45,8 @@ enum ackOp
|
|||
SETBIT, // sets bit number to next prog byte
|
||||
SETCV, // sets cv number to next prog byte
|
||||
SETBYTE, // sets current byte to next prog byte
|
||||
SETBYTEH, // sets current byte to word high byte
|
||||
SETBYTEL, // sets current byte to word low byte
|
||||
STASHLOCOID, // keeps current byte value for later
|
||||
COMBINELOCOID, // combines current value with stashed value and returns it
|
||||
ITSKIP, // skip to SKIPTARGET if ack true
|
||||
|
@ -90,6 +92,7 @@ public:
|
|||
static void verifyCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback, bool blocking = false);
|
||||
|
||||
static void getLocoId(ACK_CALLBACK callback, bool blocking = false);
|
||||
static void setLocoId(int id,ACK_CALLBACK callback, bool blocking = false);
|
||||
|
||||
// Enhanced API functions
|
||||
static void forgetLoco(int cab); // removes any speed reminders for this loco
|
||||
|
@ -126,10 +129,12 @@ private:
|
|||
static byte ackManagerByte;
|
||||
static byte ackManagerBitNum;
|
||||
static int ackManagerCv;
|
||||
static int ackManagerWord;
|
||||
static byte ackManagerStash;
|
||||
static bool ackReceived;
|
||||
static ACK_CALLBACK ackManagerCallback;
|
||||
static void ackManagerSetup(int cv, byte bitNumOrbyteValue, ackOp const program[], ACK_CALLBACK callback, bool blocking);
|
||||
static void ackManagerSetup(int wordval, ackOp const program[], ACK_CALLBACK callback, bool blocking);
|
||||
static void ackManagerLoop(bool blocking);
|
||||
static bool checkResets(bool blocking, uint8_t numResets);
|
||||
static const int PROG_REPEATS = 8; // repeats of programming commands (some decoders need at least 8 to be reliable)
|
||||
|
|
|
@ -351,9 +351,12 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking)
|
|||
return;
|
||||
|
||||
case 'W': // WRITE CV ON PROG <W CV VALUE CALLBACKNUM CALLBACKSUB>
|
||||
if (!stashCallback(stream, p))
|
||||
break;
|
||||
DCC::writeCVByte(p[0], p[1], callback_W, blocking);
|
||||
if (!stashCallback(stream, p))
|
||||
break;
|
||||
if (params == 1) // <W id> Write new loco id (clearing consist and managing short/long)
|
||||
DCC::setLocoId(p[0],callback_Wloco, blocking);
|
||||
else // WRITE CV ON PROG <W CV VALUE [CALLBACKNUM] [CALLBACKSUB]>
|
||||
DCC::writeCVByte(p[0], p[1], callback_W, blocking);
|
||||
return;
|
||||
|
||||
case 'V': // VERIFY CV ON PROG <V CV VALUE> <V CV BIT 0|1>
|
||||
|
@ -780,6 +783,13 @@ void DCCEXParser::callback_R(int result)
|
|||
|
||||
void DCCEXParser::callback_Rloco(int result)
|
||||
{
|
||||
StringFormatter::send(stashStream, F("<r %d>"), result);
|
||||
StringFormatter::send(stashStream, F("<r %d>"), result & 0x3FFF);
|
||||
stashBusy = false;
|
||||
}
|
||||
|
||||
void DCCEXParser::callback_Wloco(int result)
|
||||
{
|
||||
if (result==1) result=stashP[0]; // pick up original requested id from command
|
||||
StringFormatter::send(stashStream, F("<w %d>"), result);
|
||||
stashBusy = false;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ struct DCCEXParser
|
|||
static void callback_B(int result);
|
||||
static void callback_R(int result);
|
||||
static void callback_Rloco(int result);
|
||||
static void callback_Wloco(int result);
|
||||
static void callback_Vbit(int result);
|
||||
static void callback_Vbyte(int result);
|
||||
static FILTER_CALLBACK filterCallback;
|
||||
|
|
Loading…
Reference in New Issue
Block a user