1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-23 16:16:13 +01:00

Merge pull request #134 from DCC-EX/EDdriveaway

ED driveaway
This commit is contained in:
mstevetodd 2021-03-12 09:31:21 -05:00 committed by GitHub
commit 9e49167be9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 14 deletions

17
DCC.cpp
View File

@ -659,6 +659,7 @@ void DCC::ackManagerLoop() {
// (typically waiting for a reset counter or ACK waiting, or when all finished.) // (typically waiting for a reset counter or ACK waiting, or when all finished.)
switch (opcode) { switch (opcode) {
case BASELINE: case BASELINE:
setProgTrackSyncMain(false);
if (DCCWaveform::progTrack.getPowerMode() == POWERMODE::OFF) { if (DCCWaveform::progTrack.getPowerMode() == POWERMODE::OFF) {
if (Diag::ACK) DIAG(F("\nAuto Prog power on")); if (Diag::ACK) DIAG(F("\nAuto Prog power on"));
DCCWaveform::progTrack.setPowerMode(POWERMODE::ON); DCCWaveform::progTrack.setPowerMode(POWERMODE::ON);
@ -725,23 +726,20 @@ void DCC::ackManagerLoop() {
case ITC0: case ITC0:
case ITC1: // If True Callback(0 or 1) (if prevous WACK got an ACK) case ITC1: // If True Callback(0 or 1) (if prevous WACK got an ACK)
if (ackReceived) { if (ackReceived) {
ackManagerProg = NULL; // all done now callback(opcode==ITC0?0:1);
callback(opcode==ITC0?0:1);
return; return;
} }
break; break;
case ITCB: // If True callback(byte) case ITCB: // If True callback(byte)
if (ackReceived) { if (ackReceived) {
ackManagerProg = NULL; // all done now
callback(ackManagerByte); callback(ackManagerByte);
return; return;
} }
break; break;
case ITCB7: // If True callback(byte & 0xF) case ITCB7: // If True callback(byte & 0x7F)
if (ackReceived) { if (ackReceived) {
ackManagerProg = NULL; // all done now
callback(ackManagerByte & 0x7F); callback(ackManagerByte & 0x7F);
return; return;
} }
@ -749,15 +747,13 @@ void DCC::ackManagerLoop() {
case NAKFAIL: // If nack callback(-1) case NAKFAIL: // If nack callback(-1)
if (!ackReceived) { if (!ackReceived) {
ackManagerProg = NULL; // all done now callback(-1);
callback(-1);
return; return;
} }
break; break;
case FAIL: // callback(-1) case FAIL: // callback(-1)
ackManagerProg = NULL; callback(-1);
callback(-1);
return; return;
case STARTMERGE: case STARTMERGE:
@ -801,7 +797,6 @@ void DCC::ackManagerLoop() {
case COMBINELOCOID: case COMBINELOCOID:
// ackManagerStash is cv17, ackManagerByte is CV 18 // ackManagerStash is cv17, ackManagerByte is CV 18
ackManagerProg=NULL;
callback( ackManagerByte + ((ackManagerStash - 192) << 8)); callback( ackManagerByte + ((ackManagerStash - 192) << 8));
return; return;
@ -817,7 +812,6 @@ void DCC::ackManagerLoop() {
break; break;
default: default:
DIAG(F("\n!! ackOp %d FAULT!!"),opcode); DIAG(F("\n!! ackOp %d FAULT!!"),opcode);
ackManagerProg=NULL;
callback( -1); callback( -1);
return; return;
@ -826,6 +820,7 @@ void DCC::ackManagerLoop() {
} }
} }
void DCC::callback(int value) { void DCC::callback(int value) {
ackManagerProg=NULL; // no more steps to execute
if (DCCWaveform::progTrack.autoPowerOff) { if (DCCWaveform::progTrack.autoPowerOff) {
if (Diag::ACK) DIAG(F("\nAuto Prog power off")); if (Diag::ACK) DIAG(F("\nAuto Prog power off"));
DCCWaveform::progTrack.doAutoPowerOff(); DCCWaveform::progTrack.doAutoPowerOff();

View File

@ -207,6 +207,7 @@ int WiThrottle::getLocoId(byte * cmd) {
if (cmd[0]!='L' && cmd[0]!='S') return 0; // should not match any locos if (cmd[0]!='L' && cmd[0]!='S') return 0; // should not match any locos
return getInt(cmd+1); return getInt(cmd+1);
} }
void WiThrottle::multithrottle(RingStream * stream, byte * cmd){ void WiThrottle::multithrottle(RingStream * stream, byte * cmd){
char throttleChar=cmd[1]; char throttleChar=cmd[1];
int locoid=getLocoId(cmd+3); // -1 for * int locoid=getLocoId(cmd+3); // -1 for *
@ -217,6 +218,17 @@ void WiThrottle::multithrottle(RingStream * stream, byte * cmd){
// DIAG(F("\nMultithrottle aval=%c cab=%d"), aval[0],locoid); // DIAG(F("\nMultithrottle aval=%c cab=%d"), aval[0],locoid);
switch(cmd[2]) { switch(cmd[2]) {
case '+': // add loco request case '+': // add loco request
if (cmd[3]=='*') {
// M+* means get loco from prog track, then join tracks ready to drive away
// Stash the things the callback will need later
stashStream= stream;
stashClient=stream->peekTargetMark();
stashThrottleChar=throttleChar;
stashInstance=this;
// ask DCC to call us back when the loco id has been read
DCC::getLocoId(getLocoCallback); // will remove any previous join
return; // return nothing in stream as response is sent later in the callback
}
//return error if address zero requested //return error if address zero requested
if (locoid==0) { if (locoid==0) {
StringFormatter::send(stream, F("HMAddress '0' not supported!\n"), cmd[3] ,locoid); StringFormatter::send(stream, F("HMAddress '0' not supported!\n"), cmd[3] ,locoid);
@ -236,7 +248,7 @@ void WiThrottle::multithrottle(RingStream * stream, byte * cmd){
//Get known Fn states from DCC //Get known Fn states from DCC
for(int fKey=0; fKey<=28; fKey++) { for(int fKey=0; fKey<=28; fKey++) {
int fstate=DCC::getFn(locoid,fKey); int fstate=DCC::getFn(locoid,fKey);
if (fstate>=0) StringFormatter::send(stream,F("M%cA%c%d<;>F%d%d\n"),throttleChar,cmd[3],locoid,fstate,fKey); if (fstate>=0) StringFormatter::send(stream,F("M%cA%c%d<;>F%d%d\n"),throttleChar,cmd[3],locoid,fstate,fKey);
} }
StringFormatter::send(stream, F("M%cA%c%d<;>V%d\n"), throttleChar, cmd[3], locoid, DCCToWiTSpeed(DCC::getThrottleSpeed(locoid))); StringFormatter::send(stream, F("M%cA%c%d<;>V%d\n"), throttleChar, cmd[3], locoid, DCCToWiTSpeed(DCC::getThrottleSpeed(locoid)));
StringFormatter::send(stream, F("M%cA%c%d<;>R%d\n"), throttleChar, cmd[3], locoid, DCC::getThrottleDirection(locoid)); StringFormatter::send(stream, F("M%cA%c%d<;>R%d\n"), throttleChar, cmd[3], locoid, DCC::getThrottleDirection(locoid));
@ -368,3 +380,23 @@ void WiThrottle::checkHeartbeat() {
char WiThrottle::LorS(int cab) { char WiThrottle::LorS(int cab) {
return (cab<127)?'S':'L'; return (cab<127)?'S':'L';
} }
// Drive Away feature. Callback handling
RingStream * WiThrottle::stashStream;
WiThrottle * WiThrottle::stashInstance;
byte WiThrottle::stashClient;
char WiThrottle::stashThrottleChar;
void WiThrottle::getLocoCallback(int locoid) {
stashStream->mark(stashClient);
if (locoid<0) StringFormatter::send(stashStream,F("HMNo loco found on prog track\n"));
else {
char addcmd[20]={'M',stashThrottleChar,'+',LorS(locoid) };
itoa(locoid,addcmd+4,10);
stashInstance->multithrottle(stashStream, (byte *)addcmd);
DCCWaveform::progTrack.setPowerMode(POWERMODE::ON);
DCC::setProgTrackSyncMain(true); // <1 JOIN> so we can drive loco away
}
stashStream->commit();
}

View File

@ -61,5 +61,13 @@ class WiThrottle {
void locoAction(RingStream * stream, byte* aval, char throttleChar, int cab); void locoAction(RingStream * stream, byte* aval, char throttleChar, int cab);
void accessory(RingStream *, byte* cmd); void accessory(RingStream *, byte* cmd);
void checkHeartbeat(); void checkHeartbeat();
// callback stuff to support prog track acquire
static RingStream * stashStream;
static WiThrottle * stashInstance;
static byte stashClient;
static char stashThrottleChar;
static void getLocoCallback(int locoid);
}; };
#endif #endif