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

Fixup functionMap and remove duplicates

This commit is contained in:
Asbelos 2021-12-15 22:04:09 +00:00
parent b0c9806f3b
commit e5c66a2755
4 changed files with 34 additions and 34 deletions

View File

@ -200,6 +200,7 @@ int DCC::changeFn( int cab, int16_t functionNumber, bool pressed) {
if (cab<=0 || functionNumber>28) return funcstate; if (cab<=0 || functionNumber>28) return funcstate;
int reg = lookupSpeedTable(cab); int reg = lookupSpeedTable(cab);
if (reg<0) return funcstate; if (reg<0) return funcstate;
uint32_t oldFunctionMap=speedTable[reg].functions;
// Take care of functions: // Take care of functions:
// Imitate how many command stations do it: Button press is // Imitate how many command stations do it: Button press is
@ -222,7 +223,7 @@ int DCC::changeFn( int cab, int16_t functionNumber, bool pressed) {
funcstate = (speedTable[reg].functions & funcmask)? 1 : 0; funcstate = (speedTable[reg].functions & funcmask)? 1 : 0;
} }
updateGroupflags(speedTable[reg].groupFlags, functionNumber); updateGroupflags(speedTable[reg].groupFlags, functionNumber);
CommandDistributor::broadcastLoco(reg); if (oldFunctionMap!=speedTable[reg].functions) CommandDistributor::broadcastLoco(reg);
return funcstate; return funcstate;
} }
@ -247,7 +248,7 @@ void DCC::updateGroupflags(byte & flags, int16_t functionNumber) {
flags |= groupMask; flags |= groupMask;
} }
uint16_t DCC::getFunctionMap(int cab) { uint32_t DCC::getFunctionMap(int cab) {
if (cab<=0) return 0; // unknown pretend all functions off if (cab<=0) return 0; // unknown pretend all functions off
int reg = lookupSpeedTable(cab); int reg = lookupSpeedTable(cab);
return (reg<0)?0:speedTable[reg].functions; return (reg<0)?0:speedTable[reg].functions;
@ -696,7 +697,7 @@ void DCC::updateLocoReminder(int loco, byte speedCode) {
// determine speed reg for this loco // determine speed reg for this loco
int reg=lookupSpeedTable(loco); int reg=lookupSpeedTable(loco);
if (reg>=0) { if (reg>=0 && speedTable[reg].speedCode!=speedCode) {
speedTable[reg].speedCode = speedCode; speedTable[reg].speedCode = speedCode;
CommandDistributor::broadcastLoco(reg); CommandDistributor::broadcastLoco(reg);
} }

2
DCC.h
View File

@ -101,7 +101,7 @@ public:
static void setFn(int cab, int16_t functionNumber, bool on); static void setFn(int cab, int16_t functionNumber, bool on);
static int changeFn(int cab, int16_t functionNumber, bool pressed); static int changeFn(int cab, int16_t functionNumber, bool pressed);
static int getFn(int cab, int16_t functionNumber); 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 updateGroupflags(byte &flags, int16_t functionNumber);
static void setAccessory(int aAdd, byte aNum, bool activate); static void setAccessory(int aAdd, byte aNum, bool activate);
static bool writeTextPacket(byte *b, int nBytes); static bool writeTextPacket(byte *b, int nBytes);

View File

@ -273,15 +273,16 @@ void WiThrottle::multithrottle(RingStream * stream, byte * cmd){
if (myLocos[loco].throttle=='\0') { if (myLocos[loco].throttle=='\0') {
myLocos[loco].throttle=throttleChar; myLocos[loco].throttle=throttleChar;
myLocos[loco].cab=locoid; myLocos[loco].cab=locoid;
myLocos[loco].functionMap=DCC::getFunctionMap(locoid);
myLocos[loco].broadcastPending=true; // means speed/dir will be sent later
mostRecentCab=locoid; mostRecentCab=locoid;
StringFormatter::send(stream, F("M%c+%c%d<;>\n"), throttleChar, cmd[3] ,locoid); //tell client to add loco StringFormatter::send(stream, F("M%c+%c%d<;>\n"), throttleChar, cmd[3] ,locoid); //tell client to add loco
//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))); //speed and direction will be published at next broadcast cycle
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<;>s1\n"), throttleChar, cmd[3], locoid); //default speed step 128 StringFormatter::send(stream, F("M%cA%c%d<;>s1\n"), throttleChar, cmd[3], locoid); //default speed step 128
return; return;
} }
@ -303,6 +304,7 @@ void WiThrottle::multithrottle(RingStream * stream, byte * cmd){
void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar, int cab){ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar, int cab){
// Note cab=-1 for all cabs in the consist called throttleChar. // Note cab=-1 for all cabs in the consist called throttleChar.
// DIAG(F("Loco Action aval=%c%c throttleChar=%c, cab=%d"), aval[0],aval[1],throttleChar, cab); // DIAG(F("Loco Action aval=%c%c throttleChar=%c, cab=%d"), aval[0],aval[1],throttleChar, cab);
(void) stream;
switch (aval[0]) { switch (aval[0]) {
case 'V': // Vspeed case 'V': // Vspeed
{ {
@ -310,32 +312,24 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar,
LOOPLOCOS(throttleChar, cab) { LOOPLOCOS(throttleChar, cab) {
mostRecentCab=myLocos[loco].cab; mostRecentCab=myLocos[loco].cab;
DCC::setThrottle(myLocos[loco].cab, WiTToDCCSpeed(witSpeed), DCC::getThrottleDirection(myLocos[loco].cab)); DCC::setThrottle(myLocos[loco].cab, WiTToDCCSpeed(witSpeed), DCC::getThrottleDirection(myLocos[loco].cab));
StringFormatter::send(stream,F("M%cA%c%d<;>V%d\n"), throttleChar, LorS(myLocos[loco].cab), myLocos[loco].cab, witSpeed); // SetThrottle will cause speed change broadcast
} }
} }
break; break;
case 'F': //F onOff function case 'F': //F onOff function
{ {
bool funcstate;
bool pressed=aval[1]=='1'; bool pressed=aval[1]=='1';
int fKey = getInt(aval+2); int fKey = getInt(aval+2);
LOOPLOCOS(throttleChar, cab) { LOOPLOCOS(throttleChar, cab) {
funcstate = DCC::changeFn(myLocos[loco].cab, fKey, pressed); DCC::changeFn(myLocos[loco].cab, fKey, pressed);
if(funcstate==0 || funcstate==1)
StringFormatter::send(stream,F("M%cA%c%d<;>F%d%d\n"), throttleChar, LorS(myLocos[loco].cab),
myLocos[loco].cab, funcstate, fKey);
}
} }
break; break;
}
case 'q': 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) { 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))); myLocos[loco].broadcastPending=true;
}
}
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));
} }
} }
break; break;
@ -345,7 +339,7 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar,
LOOPLOCOS(throttleChar, cab) { LOOPLOCOS(throttleChar, cab) {
mostRecentCab=myLocos[loco].cab; mostRecentCab=myLocos[loco].cab;
DCC::setThrottle(myLocos[loco].cab, DCC::getThrottleSpeed(myLocos[loco].cab), forward); 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; break;
@ -353,7 +347,7 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar,
//Emergency Stop (speed code 1) //Emergency Stop (speed code 1)
LOOPLOCOS(throttleChar, cab) { LOOPLOCOS(throttleChar, cab) {
DCC::setThrottle(myLocos[loco].cab, 1, DCC::getThrottleDirection(myLocos[loco].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; break;
case 'I': // Idle, set speed to 0 case 'I': // Idle, set speed to 0
@ -361,7 +355,7 @@ void WiThrottle::locoAction(RingStream * stream, byte* aval, char throttleChar,
LOOPLOCOS(throttleChar, cab) { LOOPLOCOS(throttleChar, cab) {
mostRecentCab=myLocos[loco].cab; mostRecentCab=myLocos[loco].cab;
DCC::setThrottle(myLocos[loco].cab, 0, DCC::getThrottleDirection(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; break;
} }
@ -403,10 +397,15 @@ void WiThrottle::checkHeartbeat(RingStream * stream) {
return; 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) { LOOPLOCOS('*', -1) {
if (myLocos[loco].throttle!='\0' && myLocos[loco].broadcastPending) { if (myLocos[loco].throttle!='\0' && myLocos[loco].broadcastPending) {
if (!streamHasBeenMarked) {
stream->mark(clientid); stream->mark(clientid);
streamHasBeenMarked=true;
}
myLocos[loco].broadcastPending=false; myLocos[loco].broadcastPending=false;
int cab=myLocos[loco].cab; int cab=myLocos[loco].cab;
char lors=LorS(cab); char lors=LorS(cab);
@ -417,8 +416,8 @@ void WiThrottle::checkHeartbeat(RingStream * stream) {
throttle, lors , cab, DCC::getThrottleDirection(cab)); throttle, lors , cab, DCC::getThrottleDirection(cab));
// compare the DCC functionmap with the local copy and send changes // compare the DCC functionmap with the local copy and send changes
uint16_t dccFunctionMap=DCC::getFunctionMap(cab); uint32_t dccFunctionMap=DCC::getFunctionMap(cab);
uint16_t myFunctionMap=myLocos[loco].functionMap; uint32_t myFunctionMap=myLocos[loco].functionMap;
myLocos[loco].functionMap=dccFunctionMap; myLocos[loco].functionMap=dccFunctionMap;
// loop the maps sending any bit changed // loop the maps sending any bit changed
@ -432,9 +431,9 @@ void WiThrottle::checkHeartbeat(RingStream * stream) {
dccFunctionMap>>=1; dccFunctionMap>>=1;
myFunctionMap>>=1; myFunctionMap>>=1;
} }
stream->commit();
} }
} }
if (streamHasBeenMarked) stream->commit();
} }
void WiThrottle::markForBroadcast(int cab) { void WiThrottle::markForBroadcast(int cab) {

View File

@ -25,7 +25,7 @@ struct MYLOCO {
char throttle; //indicates which throttle letter on client, often '0','1' or '2' char throttle; //indicates which throttle letter on client, often '0','1' or '2'
int cab; //address of this loco int cab; //address of this loco
bool broadcastPending; bool broadcastPending;
uint16_t functionMap; uint32_t functionMap;
}; };
class WiThrottle { class WiThrottle {