mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-24 21:21:24 +01:00
Merge branch 'hash' into mergefix
This commit is contained in:
commit
9b04e7dfd6
20
DCC.cpp
20
DCC.cpp
@ -157,7 +157,9 @@ void DCC::writeCVBitMain(int cab, int cv, byte bNum, bool bValue) {
|
|||||||
DCCWaveform::mainTrack.schedulePacket(b, nB, 4);
|
DCCWaveform::mainTrack.schedulePacket(b, nB, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DCC::setProgTrackSyncMain(bool on) {
|
||||||
|
DCCWaveform::progTrackSyncMain=on;
|
||||||
|
}
|
||||||
|
|
||||||
const ackOp PROGMEM WRITE_BIT0_PROG[] = {
|
const ackOp PROGMEM WRITE_BIT0_PROG[] = {
|
||||||
BASELINE,
|
BASELINE,
|
||||||
@ -347,10 +349,12 @@ bool DCC::issueReminder(int reg) {
|
|||||||
case 4: // remind function group 4 F13-F20
|
case 4: // remind function group 4 F13-F20
|
||||||
if (flags & FN_GROUP_4)
|
if (flags & FN_GROUP_4)
|
||||||
setFunctionInternal(loco,222, ((functions>>13)& 0xFF));
|
setFunctionInternal(loco,222, ((functions>>13)& 0xFF));
|
||||||
|
flags&= ~FN_GROUP_4; // dont send them again
|
||||||
break;
|
break;
|
||||||
case 5: // remind function group 5 F21-F28
|
case 5: // remind function group 5 F21-F28
|
||||||
if (flags & FN_GROUP_5)
|
if (flags & FN_GROUP_5)
|
||||||
setFunctionInternal(loco,223, ((functions>>21)& 0xFF));
|
setFunctionInternal(loco,223, ((functions>>21)& 0xFF));
|
||||||
|
flags&= ~FN_GROUP_5; // dont send them again
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
loopStatus++;
|
loopStatus++;
|
||||||
@ -390,7 +394,7 @@ int DCC::lookupSpeedTable(int locoId) {
|
|||||||
}
|
}
|
||||||
if (reg==firstEmpty){
|
if (reg==firstEmpty){
|
||||||
speedTable[reg].loco = locoId;
|
speedTable[reg].loco = locoId;
|
||||||
speedTable[reg].speedCode=0;
|
speedTable[reg].speedCode=128; // default direction forward
|
||||||
speedTable[reg].groupFlags=0;
|
speedTable[reg].groupFlags=0;
|
||||||
speedTable[reg].functions=0;
|
speedTable[reg].functions=0;
|
||||||
}
|
}
|
||||||
@ -452,9 +456,10 @@ void DCC::ackManagerLoop() {
|
|||||||
case W1: // write 1 bit
|
case W1: // write 1 bit
|
||||||
{
|
{
|
||||||
if (resets<RESET_MIN) return; // try later
|
if (resets<RESET_MIN) return; // try later
|
||||||
|
if (debugMode) DIAG(F("\nW%d cv=%d bit=%d"),opcode==W1, ackManagerCv,ackManagerBitNum);
|
||||||
byte instruction = WRITE_BIT | (opcode==W1 ? BIT_ON : BIT_OFF) | ackManagerBitNum;
|
byte instruction = WRITE_BIT | (opcode==W1 ? BIT_ON : BIT_OFF) | ackManagerBitNum;
|
||||||
byte message[] = {cv1(BIT_MANIPULATE, ackManagerCv), cv2(ackManagerCv), instruction };
|
byte message[] = {cv1(BIT_MANIPULATE, ackManagerCv), cv2(ackManagerCv), instruction };
|
||||||
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 6);
|
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), PROG_REPEATS);
|
||||||
DCCWaveform::progTrack.setAckPending(debugMode);
|
DCCWaveform::progTrack.setAckPending(debugMode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -462,8 +467,9 @@ void DCC::ackManagerLoop() {
|
|||||||
case WB: // write byte
|
case WB: // write byte
|
||||||
{
|
{
|
||||||
if (resets<RESET_MIN) return; // try later
|
if (resets<RESET_MIN) return; // try later
|
||||||
|
if (debugMode) DIAG(F("\nWB cv=%d value=%d"),ackManagerCv,ackManagerByte);
|
||||||
byte message[] = {cv1(WRITE_BYTE, ackManagerCv), cv2(ackManagerCv), ackManagerByte};
|
byte message[] = {cv1(WRITE_BYTE, ackManagerCv), cv2(ackManagerCv), ackManagerByte};
|
||||||
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 6);
|
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), PROG_REPEATS);
|
||||||
DCCWaveform::progTrack.setAckPending(debugMode);
|
DCCWaveform::progTrack.setAckPending(debugMode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -471,9 +477,9 @@ void DCC::ackManagerLoop() {
|
|||||||
case VB: // Issue validate Byte packet
|
case VB: // Issue validate Byte packet
|
||||||
{
|
{
|
||||||
if (resets<RESET_MIN) return; // try later
|
if (resets<RESET_MIN) return; // try later
|
||||||
if (debugMode) DIAG(F("\nVB %d %d"),ackManagerCv,ackManagerByte);
|
if (debugMode) DIAG(F("\nVB cv=%d value=%d"),ackManagerCv,ackManagerByte);
|
||||||
byte message[] = { cv1(VERIFY_BYTE, ackManagerCv), cv2(ackManagerCv), ackManagerByte};
|
byte message[] = { cv1(VERIFY_BYTE, ackManagerCv), cv2(ackManagerCv), ackManagerByte};
|
||||||
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 5);
|
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), PROG_REPEATS);
|
||||||
DCCWaveform::progTrack.setAckPending(debugMode);
|
DCCWaveform::progTrack.setAckPending(debugMode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -485,7 +491,7 @@ void DCC::ackManagerLoop() {
|
|||||||
if (debugMode) DIAG(F("\nV%d cv=%d bit=%d"),opcode==V1, ackManagerCv,ackManagerBitNum);
|
if (debugMode) DIAG(F("\nV%d cv=%d bit=%d"),opcode==V1, ackManagerCv,ackManagerBitNum);
|
||||||
byte instruction = VERIFY_BIT | (opcode==V0?BIT_OFF:BIT_ON) | ackManagerBitNum;
|
byte instruction = VERIFY_BIT | (opcode==V0?BIT_OFF:BIT_ON) | ackManagerBitNum;
|
||||||
byte message[] = {cv1(BIT_MANIPULATE, ackManagerCv), cv2(ackManagerCv), instruction };
|
byte message[] = {cv1(BIT_MANIPULATE, ackManagerCv), cv2(ackManagerCv), instruction };
|
||||||
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 5);
|
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), PROG_REPEATS);
|
||||||
DCCWaveform::progTrack.setAckPending(debugMode);
|
DCCWaveform::progTrack.setAckPending(debugMode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
2
DCC.h
2
DCC.h
@ -63,6 +63,7 @@ class DCC {
|
|||||||
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);
|
||||||
static void setDebug(bool on);
|
static void setDebug(bool on);
|
||||||
|
static void setProgTrackSyncMain(bool on); // when true, prog track becomes driveable
|
||||||
|
|
||||||
// ACKable progtrack calls bitresults callback 0,0 or -1, cv returns value or -1
|
// ACKable progtrack calls bitresults callback 0,0 or -1, cv returns value or -1
|
||||||
static void readCV(int cv, ACK_CALLBACK callback);
|
static void readCV(int cv, ACK_CALLBACK callback);
|
||||||
@ -107,6 +108,7 @@ private:
|
|||||||
static ACK_CALLBACK ackManagerCallback;
|
static ACK_CALLBACK ackManagerCallback;
|
||||||
static void ackManagerSetup(int cv, byte bitNumOrbyteValue, ackOp const program[], ACK_CALLBACK callback);
|
static void ackManagerSetup(int cv, byte bitNumOrbyteValue, ackOp const program[], ACK_CALLBACK callback);
|
||||||
static void ackManagerLoop();
|
static void ackManagerLoop();
|
||||||
|
static const int PROG_REPEATS=8; // repeats of programming commands (some decoders need at least 8 to be reliable)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,10 +131,9 @@ void DCCEXParser::parse(Print & stream, const byte *com, bool banAsync) {
|
|||||||
DIAG(F("\nPARSING:%s\n"),com);
|
DIAG(F("\nPARSING:%s\n"),com);
|
||||||
asyncBanned=banAsync;
|
asyncBanned=banAsync;
|
||||||
(void) EEPROM; // tell compiler not to warn thi is unused
|
(void) EEPROM; // tell compiler not to warn thi is unused
|
||||||
int p[MAX_PARAMS];
|
int p[MAX_PARAMS];
|
||||||
|
while (com[0]=='<' || com[0]==' ') com++; // strip off any number of < or spaces
|
||||||
byte params=splitValues(p, com);
|
byte params=splitValues(p, com);
|
||||||
|
|
||||||
if (com[0]=='<') com++;
|
|
||||||
byte opcode=com[0];
|
byte opcode=com[0];
|
||||||
|
|
||||||
if (filterCallback) filterCallback(stream,opcode,params,p);
|
if (filterCallback) filterCallback(stream,opcode,params,p);
|
||||||
|
@ -26,7 +26,7 @@ DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false, (int)(PROG_MAX_MI
|
|||||||
|
|
||||||
const int ACK_MIN_PULSE_RAW=65 / PROG_SENSE_FACTOR;
|
const int ACK_MIN_PULSE_RAW=65 / PROG_SENSE_FACTOR;
|
||||||
|
|
||||||
|
bool DCCWaveform::progTrackSyncMain=false;
|
||||||
|
|
||||||
void DCCWaveform::begin() {
|
void DCCWaveform::begin() {
|
||||||
Hardware::init();
|
Hardware::init();
|
||||||
@ -99,8 +99,11 @@ void DCCWaveform::setPowerMode(POWERMODE mode) {
|
|||||||
|
|
||||||
|
|
||||||
void DCCWaveform::checkPowerOverload() {
|
void DCCWaveform::checkPowerOverload() {
|
||||||
|
|
||||||
if (millis() - lastSampleTaken < sampleDelay) return;
|
if (millis() - lastSampleTaken < sampleDelay) return;
|
||||||
lastSampleTaken = millis();
|
lastSampleTaken = millis();
|
||||||
|
int tripValue= rawCurrentTripValue;
|
||||||
|
if (!isMainTrack && (ackPending || progTrackSyncMain)) tripValue=ACK_CURRENT_TRIP;
|
||||||
|
|
||||||
switch (powerMode) {
|
switch (powerMode) {
|
||||||
case POWERMODE::OFF:
|
case POWERMODE::OFF:
|
||||||
@ -109,11 +112,11 @@ void DCCWaveform::checkPowerOverload() {
|
|||||||
case POWERMODE::ON:
|
case POWERMODE::ON:
|
||||||
// Check current
|
// Check current
|
||||||
lastCurrent = Hardware::getCurrentRaw(isMainTrack);
|
lastCurrent = Hardware::getCurrentRaw(isMainTrack);
|
||||||
if (lastCurrent <= rawCurrentTripValue) sampleDelay = POWER_SAMPLE_ON_WAIT;
|
if (lastCurrent <= tripValue) sampleDelay = POWER_SAMPLE_ON_WAIT;
|
||||||
else {
|
else {
|
||||||
setPowerMode(POWERMODE::OVERLOAD);
|
setPowerMode(POWERMODE::OVERLOAD);
|
||||||
unsigned int mA=Hardware::getCurrentMilliamps(isMainTrack,lastCurrent);
|
unsigned int mA=Hardware::getCurrentMilliamps(isMainTrack,lastCurrent);
|
||||||
unsigned int maxmA=Hardware::getCurrentMilliamps(isMainTrack,rawCurrentTripValue);
|
unsigned int maxmA=Hardware::getCurrentMilliamps(isMainTrack,tripValue);
|
||||||
DIAG(F("\n*** %S TRACK POWER OVERLOAD current=%d max=%d ***\n"), isMainTrack ? F("MAIN") : F("PROG"), mA, maxmA);
|
DIAG(F("\n*** %S TRACK POWER OVERLOAD current=%d max=%d ***\n"), isMainTrack ? F("MAIN") : F("PROG"), mA, maxmA);
|
||||||
sampleDelay = POWER_SAMPLE_OVERLOAD_WAIT;
|
sampleDelay = POWER_SAMPLE_OVERLOAD_WAIT;
|
||||||
}
|
}
|
||||||
@ -139,19 +142,19 @@ bool DCCWaveform::interrupt1() {
|
|||||||
// otherwise can cause hangs in main loop waiting for the pendingBuffer.
|
// otherwise can cause hangs in main loop waiting for the pendingBuffer.
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 0: // start of bit transmission
|
case 0: // start of bit transmission
|
||||||
Hardware::setSignal(isMainTrack, HIGH);
|
setSignal(HIGH);
|
||||||
state = 1;
|
state = 1;
|
||||||
return true; // must call interrupt2 to set currentBit
|
return true; // must call interrupt2 to set currentBit
|
||||||
|
|
||||||
case 1: // 58us after case 0
|
case 1: // 58us after case 0
|
||||||
if (currentBit) {
|
if (currentBit) {
|
||||||
Hardware::setSignal(isMainTrack, LOW);
|
setSignal(LOW);
|
||||||
state = 0;
|
state = 0;
|
||||||
}
|
}
|
||||||
else state = 2;
|
else state = 2;
|
||||||
break;
|
break;
|
||||||
case 2: // 116us after case 0
|
case 2: // 116us after case 0
|
||||||
Hardware::setSignal(isMainTrack, LOW);
|
setSignal(LOW);
|
||||||
state = 3;
|
state = 3;
|
||||||
break;
|
break;
|
||||||
case 3: // finished sending zero bit
|
case 3: // finished sending zero bit
|
||||||
@ -167,7 +170,17 @@ bool DCCWaveform::interrupt1() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DCCWaveform::setSignal(bool high) {
|
||||||
|
if (progTrackSyncMain) {
|
||||||
|
if (!isMainTrack) return; // ignore PROG track waveform while in sync
|
||||||
|
// set both tracks to same signal
|
||||||
|
Hardware::setSignal(true, high);
|
||||||
|
Hardware::setSignal(false, high);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Hardware::setSignal(isMainTrack,high);
|
||||||
|
}
|
||||||
|
|
||||||
void DCCWaveform::interrupt2() {
|
void DCCWaveform::interrupt2() {
|
||||||
// set currentBit to be the next bit to be sent.
|
// set currentBit to be the next bit to be sent.
|
||||||
|
|
||||||
|
@ -62,13 +62,15 @@ class DCCWaveform {
|
|||||||
void setAckBaseline(bool debug); //prog track only
|
void setAckBaseline(bool debug); //prog track only
|
||||||
void setAckPending(bool debug); //prog track only
|
void setAckPending(bool debug); //prog track only
|
||||||
byte getAck(bool debug); //prog track only 0=NACK, 1=ACK 2=keep waiting
|
byte getAck(bool debug); //prog track only 0=NACK, 1=ACK 2=keep waiting
|
||||||
|
static bool progTrackSyncMain; // true when prog track is a siding switched to main
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static void interruptHandler();
|
static void interruptHandler();
|
||||||
bool interrupt1();
|
bool interrupt1();
|
||||||
void interrupt2();
|
void interrupt2();
|
||||||
void checkAck();
|
void checkAck();
|
||||||
|
void setSignal(bool high);
|
||||||
|
|
||||||
bool isMainTrack;
|
bool isMainTrack;
|
||||||
|
|
||||||
@ -94,7 +96,8 @@ class DCCWaveform {
|
|||||||
unsigned long lastSampleTaken;
|
unsigned long lastSampleTaken;
|
||||||
unsigned int sampleDelay;
|
unsigned int sampleDelay;
|
||||||
int rawCurrentTripValue;
|
int rawCurrentTripValue;
|
||||||
|
static const int ACK_CURRENT_TRIP=1000; // During ACK processing limit can be higher
|
||||||
|
|
||||||
// ACK management (Prog track only)
|
// ACK management (Prog track only)
|
||||||
bool ackPending;
|
bool ackPending;
|
||||||
bool ackDetected;
|
bool ackDetected;
|
||||||
|
@ -51,27 +51,22 @@
|
|||||||
|
|
||||||
WiThrottle * WiThrottle::firstThrottle=NULL;
|
WiThrottle * WiThrottle::firstThrottle=NULL;
|
||||||
|
|
||||||
WiThrottle* WiThrottle::getThrottle(Print & stream, int wifiClient) {
|
WiThrottle* WiThrottle::getThrottle( int wifiClient) {
|
||||||
for (WiThrottle* wt=firstThrottle; wt!=NULL ; wt=wt->nextThrottle)
|
for (WiThrottle* wt=firstThrottle; wt!=NULL ; wt=wt->nextThrottle)
|
||||||
if (wt->clientid==wifiClient) return wt;
|
if (wt->clientid==wifiClient) return wt;
|
||||||
return new WiThrottle(stream, wifiClient);
|
return new WiThrottle( wifiClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
// One instance of WiTHrottle per connected client, so we know what the locos are
|
// One instance of WiTHrottle per connected client, so we know what the locos are
|
||||||
|
|
||||||
WiThrottle::WiThrottle(Print & stream, int wificlientid) {
|
WiThrottle::WiThrottle( int wificlientid) {
|
||||||
DIAG(F("\nCreating new WiThrottle for client %d\n"),wificlientid);
|
DIAG(F("\nCreating new WiThrottle for client %d\n"),wificlientid);
|
||||||
nextThrottle=firstThrottle;
|
nextThrottle=firstThrottle;
|
||||||
firstThrottle= this;
|
firstThrottle= this;
|
||||||
clientid=wificlientid;
|
clientid=wificlientid;
|
||||||
for (int loco=0;loco<MAX_MY_LOCO; loco++) myLocos[loco].throttle='\0';
|
heartBeatEnable=false; // until client turns it on
|
||||||
StringFormatter::send(stream,F("VN2.0\nHTDCC++EX\nRL0\nPPA%x\nPTT]\\[Turnouts}|{Turnout]\\[Closed}|{2]\\[Thrown}|{4\\PTL"), DCCWaveform::mainTrack.getPowerMode()==POWERMODE::ON);
|
firstCall=true;
|
||||||
|
for (int loco=0;loco<MAX_MY_LOCO; loco++) myLocos[loco].throttle='\0';
|
||||||
for(Turnout *tt=Turnout::firstTurnout;tt!=NULL;tt=tt->nextTurnout){
|
|
||||||
StringFormatter::send(stream,F("]\\[LT&d}|{%d}|{%d"), tt->data.id, tt->data.id, (bool)(tt->data.tStatus & STATUS_ACTIVE));
|
|
||||||
}
|
|
||||||
StringFormatter::send(stream,F("\n*10\n"));
|
|
||||||
heartBeatEnable=false; // until client turns it on
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WiThrottle::~WiThrottle() {
|
WiThrottle::~WiThrottle() {
|
||||||
@ -87,10 +82,33 @@ WiThrottle::~WiThrottle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiThrottle::parse(Print & stream, byte * cmd) {
|
void WiThrottle::parse(Print & stream, byte * cmdx) {
|
||||||
|
|
||||||
|
// we have to take a copy of the cmd buffer as the reply will get built into the cmdx
|
||||||
|
byte local[50];
|
||||||
|
for (byte i=0;i<sizeof(local);i++) {
|
||||||
|
local[i]=cmdx[i];
|
||||||
|
if (!cmdx[i]) break;
|
||||||
|
}
|
||||||
|
local[49]='\0'; // prevent runaway parser
|
||||||
|
|
||||||
|
byte * cmd=local;
|
||||||
|
|
||||||
heartBeat=millis();
|
heartBeat=millis();
|
||||||
DIAG(F("\nWiThrottle(%d) [%e]"),clientid, cmd);
|
DIAG(F("\nWiThrottle(%d) [%e]"),clientid, cmd);
|
||||||
|
|
||||||
|
if (firstCall) {
|
||||||
|
firstCall=false;
|
||||||
|
StringFormatter::send(stream,F("VN2.0\nHTDCC++EX\nRL0\nPPA%x\nPTT]\\[Turnouts}|{Turnout]\\[Closed}|{2]\\[Thrown}|{4\\PTL"),
|
||||||
|
DCCWaveform::mainTrack.getPowerMode()==POWERMODE::ON);
|
||||||
|
|
||||||
|
for(Turnout *tt=Turnout::firstTurnout;tt!=NULL;tt=tt->nextTurnout){
|
||||||
|
StringFormatter::send(stream,F("]\\[LT&d}|{%d}|{%d"), tt->data.id, tt->data.id, (bool)(tt->data.tStatus & STATUS_ACTIVE));
|
||||||
|
}
|
||||||
|
StringFormatter::send(stream,F("\n*10\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cmd[0]) {
|
||||||
switch (cmd[0]) {
|
switch (cmd[0]) {
|
||||||
case '*': // heartbeat control
|
case '*': // heartbeat control
|
||||||
if (cmd[1]=='+') heartBeatEnable=true;
|
if (cmd[1]=='+') heartBeatEnable=true;
|
||||||
@ -119,6 +137,10 @@ void WiThrottle::parse(Print & stream, byte * cmd) {
|
|||||||
DIAG(F("\nWiThrottle Quit"));
|
DIAG(F("\nWiThrottle Quit"));
|
||||||
delete this;
|
delete this;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
// skip over cmd until 0 or past \r or \n
|
||||||
|
while(*cmd !='\0' && *cmd != '\r' && *cmd !='\n') cmd++;
|
||||||
|
if (*cmd!='\0') cmd++; // skip \r or \n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int WiThrottle::getInt(byte * cmd) {
|
int WiThrottle::getInt(byte * cmd) {
|
||||||
@ -196,12 +218,12 @@ void WiThrottle::locoAction(Print & stream, byte* aval, char throttleChar, int c
|
|||||||
case 'q':
|
case 'q':
|
||||||
if (aval[1]=='V') { //qV
|
if (aval[1]=='V') { //qV
|
||||||
LOOPLOCOS(throttleChar, cab) {
|
LOOPLOCOS(throttleChar, cab) {
|
||||||
StringFormatter::send(stream,F("M%cAL%d<;>V%d"), throttleChar, myLocos[loco].cab, DCC::getThrottleSpeed(myLocos[loco].cab));
|
StringFormatter::send(stream,F("M%cAL%d<;>V%d\n"), throttleChar, myLocos[loco].cab, DCC::getThrottleSpeed(myLocos[loco].cab));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (aval[1]=='R') { // qR
|
else if (aval[1]=='R') { // qR
|
||||||
LOOPLOCOS(throttleChar, cab) {
|
LOOPLOCOS(throttleChar, cab) {
|
||||||
StringFormatter::send(stream,F("M%cAL%d<;>R%d"), throttleChar, myLocos[loco].cab, DCC::getThrottleDirection(myLocos[loco].cab));
|
StringFormatter::send(stream,F("M%cAL%d<;>R%d\n"), throttleChar, myLocos[loco].cab, DCC::getThrottleDirection(myLocos[loco].cab));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -29,10 +29,10 @@ class WiThrottle {
|
|||||||
public:
|
public:
|
||||||
static void loop();
|
static void loop();
|
||||||
void parse(Print & stream, byte * cmd);
|
void parse(Print & stream, byte * cmd);
|
||||||
static WiThrottle* getThrottle(Print & stream, int wifiClient);
|
static WiThrottle* getThrottle( int wifiClient);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WiThrottle(Print & stream, int wifiClientId);
|
WiThrottle( int wifiClientId);
|
||||||
~WiThrottle();
|
~WiThrottle();
|
||||||
|
|
||||||
static const int MAX_MY_LOCO=10;
|
static const int MAX_MY_LOCO=10;
|
||||||
@ -46,6 +46,7 @@ class WiThrottle {
|
|||||||
|
|
||||||
MYLOCO myLocos[MAX_MY_LOCO];
|
MYLOCO myLocos[MAX_MY_LOCO];
|
||||||
bool heartBeatEnable;
|
bool heartBeatEnable;
|
||||||
|
bool firstCall;
|
||||||
unsigned long heartBeat;
|
unsigned long heartBeat;
|
||||||
|
|
||||||
void multithrottle(Print & stream, byte * cmd);
|
void multithrottle(Print & stream, byte * cmd);
|
||||||
|
@ -172,12 +172,12 @@ void WifiInterface::loop(Stream & wifiStream) {
|
|||||||
}
|
}
|
||||||
else if (buffer[0]=='<') parser.parse(streamer,buffer, true); // tell JMRI parser that callbacks are diallowed because we dont want to handle the async
|
else if (buffer[0]=='<') parser.parse(streamer,buffer, true); // tell JMRI parser that callbacks are diallowed because we dont want to handle the async
|
||||||
|
|
||||||
else WiThrottle::getThrottle(streamer, connectionId)->parse(streamer, buffer);
|
else WiThrottle::getThrottle(connectionId)->parse(streamer, buffer);
|
||||||
|
|
||||||
|
|
||||||
if (streamer.available()) { // there is a reply to send
|
if (streamer.available()) { // there is a reply to send
|
||||||
streamer.write('\0');
|
streamer.write('\0');
|
||||||
DIAG(F("WiFiInterface Responding client (%d) l(%d) %e\n"),connectionId,streamer.available()-1,buffer);
|
DIAG(F("\nWiFiInterface reply c(%d) l(%d) [%e]\n"),connectionId,streamer.available()-1,buffer);
|
||||||
|
|
||||||
StringFormatter::send(wifiStream,F("AT+CIPSEND=%d,%d\r\n"),connectionId,streamer.available()-1);
|
StringFormatter::send(wifiStream,F("AT+CIPSEND=%d,%d\r\n"),connectionId,streamer.available()-1);
|
||||||
if (checkForOK(wifiStream,1000,PROMPT_SEARCH,true)) wifiStream.print((char *) buffer);
|
if (checkForOK(wifiStream,1000,PROMPT_SEARCH,true)) wifiStream.print((char *) buffer);
|
||||||
|
Loading…
Reference in New Issue
Block a user