diff --git a/DCC.cpp b/DCC.cpp index 83a8ec0..badb6e6 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -248,7 +248,7 @@ void DCC::updateGroupflags(byte & flags, int16_t functionNumber) { flags |= groupMask; } -uint16_t DCC::getFunctionMap(int cab) { +uint32_t DCC::getFunctionMap(int cab) { if (cab<=0) return 0; // unknown pretend all functions off int reg = lookupSpeedTable(cab); return (reg<0)?0:speedTable[reg].functions; diff --git a/DCC.h b/DCC.h index bb65095..0b02b5b 100644 --- a/DCC.h +++ b/DCC.h @@ -101,7 +101,7 @@ public: static void setFn(int cab, int16_t functionNumber, bool on); static int changeFn(int cab, int16_t functionNumber, bool pressed); static int getFn(int cab, int16_t functionNumber); - static uint16_t getFunctionMap(int cab); + static uint32_t getFunctionMap(int cab); static void updateGroupflags(byte &flags, int16_t functionNumber); static void setAccessory(int aAdd, byte aNum, bool activate); static bool writeTextPacket(byte *b, int nBytes); diff --git a/WiThrottle.cpp b/WiThrottle.cpp index 7dc8d41..f799d4b 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -278,16 +278,17 @@ void WiThrottle::multithrottle(RingStream * stream, byte * cmd){ for (int loco=0;loco\n"), throttleChar, cmd[3] ,locoid); //tell client to add loco - //Get known Fn states from DCC + for(int fKey=0; fKey<=28; 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); } - 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)); + //speed and direction will be published at next broadcast cycle StringFormatter::send(stream, F("M%cA%c%d<;>s1\n"), throttleChar, cmd[3], locoid); //default speed step 128 return; } @@ -334,15 +335,11 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar, } break; case 'q': - if (aval[1]=='V') { //qV + if (aval[1]=='V' || aval[1]=='R' ) { //qV or qR + // just flag the loco for broadcast and it will happen. LOOPLOCOS(throttleChar, cab) { - StringFormatter::send(stream,F("M%cA%c%d<;>V%d\n"), throttleChar, LorS(myLocos[loco].cab), myLocos[loco].cab, DCCToWiTSpeed(DCC::getThrottleSpeed(myLocos[loco].cab))); - } - } - else if (aval[1]=='R') { // qR - LOOPLOCOS(throttleChar, cab) { - StringFormatter::send(stream,F("M%cA%c%d<;>R%d\n"), throttleChar, LorS(myLocos[loco].cab), myLocos[loco].cab, DCC::getThrottleDirection(myLocos[loco].cab)); - } + myLocos[loco].broadcastPending=true; + } } break; case 'R': @@ -351,15 +348,15 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar, LOOPLOCOS(throttleChar, cab) { mostRecentCab=myLocos[loco].cab; DCC::setThrottle(myLocos[loco].cab, DCC::getThrottleSpeed(myLocos[loco].cab), forward); - StringFormatter::send(stream,F("M%cA%c%d<;>R%d\n"), throttleChar, LorS(myLocos[loco].cab), myLocos[loco].cab, forward); - } + // setThrottle will cause a broadcast so notification will be sent + } } break; case 'X': //Emergency Stop (speed code 1) LOOPLOCOS(throttleChar, cab) { DCC::setThrottle(myLocos[loco].cab, 1, DCC::getThrottleDirection(myLocos[loco].cab)); - StringFormatter::send(stream,F("M%cA%c%d<;>V%d\n"), throttleChar, LorS(myLocos[loco].cab), myLocos[loco].cab, -1); + // setThrottle will cause a broadcast so notification will be sent } break; case 'I': // Idle, set speed to 0 @@ -367,7 +364,7 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar, LOOPLOCOS(throttleChar, cab) { mostRecentCab=myLocos[loco].cab; DCC::setThrottle(myLocos[loco].cab, 0, DCC::getThrottleDirection(myLocos[loco].cab)); - StringFormatter::send(stream,F("M%cA%c%d<;>V%d\n"), throttleChar, LorS(myLocos[loco].cab), myLocos[loco].cab, 0); + // setThrottle will cause a broadcast so notification will be sent } break; } @@ -409,10 +406,15 @@ void WiThrottle::checkHeartbeat(RingStream * stream) { return; } - // send any speed/direction/function changes for this loco + // send any outstanding speed/direction/function changes for this clients locos + // Changes may have been caused by this client, or another non-Withrottle or Exrail + bool streamHasBeenMarked=false; LOOPLOCOS('*', -1) { if (myLocos[loco].throttle!='\0' && myLocos[loco].broadcastPending) { - stream->mark(clientid); + if (!streamHasBeenMarked) { + stream->mark(clientid); + streamHasBeenMarked=true; + } myLocos[loco].broadcastPending=false; int cab=myLocos[loco].cab; char lors=LorS(cab); @@ -423,8 +425,8 @@ void WiThrottle::checkHeartbeat(RingStream * stream) { throttle, lors , cab, DCC::getThrottleDirection(cab)); // compare the DCC functionmap with the local copy and send changes - uint16_t dccFunctionMap=DCC::getFunctionMap(cab); - uint16_t myFunctionMap=myLocos[loco].functionMap; + uint32_t dccFunctionMap=DCC::getFunctionMap(cab); + uint32_t myFunctionMap=myLocos[loco].functionMap; myLocos[loco].functionMap=dccFunctionMap; // loop the maps sending any bit changed @@ -438,9 +440,9 @@ void WiThrottle::checkHeartbeat(RingStream * stream) { dccFunctionMap>>=1; myFunctionMap>>=1; } - stream->commit(); } } + if (streamHasBeenMarked) stream->commit(); } void WiThrottle::markForBroadcast(int cab) { diff --git a/WiThrottle.h b/WiThrottle.h index 7cbdb88..0e1f525 100644 --- a/WiThrottle.h +++ b/WiThrottle.h @@ -25,7 +25,7 @@ struct MYLOCO { char throttle; //indicates which throttle letter on client, often '0','1' or '2' int cab; //address of this loco bool broadcastPending; - uint16_t functionMap; + uint32_t functionMap; }; class WiThrottle {