mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-03-14 18:13:09 +01:00
Ring count improvements
Count is stashed at start of message so can be got without counting. Commit discards empty replies automatically.
This commit is contained in:
parent
b7fc055953
commit
6c0b5d82be
@ -29,58 +29,71 @@ RingStream::RingStream( const uint16_t len)
|
|||||||
_buffer[0]=0;
|
_buffer[0]=0;
|
||||||
_overflow=false;
|
_overflow=false;
|
||||||
_mark=0;
|
_mark=0;
|
||||||
|
_count=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RingStream::write(uint8_t b) {
|
size_t RingStream::write(uint8_t b) {
|
||||||
if (_overflow) return 0;
|
if (_overflow) return 0;
|
||||||
_buffer[_pos_write] = b;
|
_buffer[_pos_write] = b;
|
||||||
++_pos_write;
|
++_pos_write;
|
||||||
if (_pos_write>=_len) _pos_write=0;
|
if (_pos_write==_len) _pos_write=0;
|
||||||
if (_pos_write==_pos_read) {
|
if (_pos_write==_pos_read) {
|
||||||
_overflow=true;
|
_overflow=true;
|
||||||
DIAG(F("\nRingStream(%d) OVERFLOW %d %d \n"),_len, _pos_write, _pos_read);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
_count++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RingStream::read() {
|
int RingStream::read() {
|
||||||
if (_pos_read==_pos_write) return -1;
|
if ((_pos_read==_pos_write) && !_overflow) return -1; // empty
|
||||||
byte b=_buffer[_pos_read];
|
byte b=_buffer[_pos_read];
|
||||||
_pos_read++;
|
_pos_read++;
|
||||||
if (_pos_read>=_len) _pos_read=0;
|
if (_pos_read==_len) _pos_read=0;
|
||||||
_overflow=false;
|
_overflow=false;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int RingStream::count() {
|
int RingStream::count() {
|
||||||
int peek=_pos_read;
|
return (read()<<8) | read();
|
||||||
int counter=0;
|
|
||||||
while(_buffer[peek]) {
|
|
||||||
counter++;
|
|
||||||
peek++;
|
|
||||||
if (peek >= _len) peek=0;
|
|
||||||
}
|
|
||||||
return counter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int RingStream::freeSpace() {
|
int RingStream::freeSpace() {
|
||||||
if (_pos_read>_pos_write) return _pos_read-_pos_write-2;
|
// allow space for client flag and length bytes
|
||||||
else return _len - _pos_write + _pos_read-2;
|
if (_pos_read>_pos_write) return _pos_read-_pos_write-3;
|
||||||
|
else return _len - _pos_write + _pos_read-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RingStream::mark() {
|
// mark start of message with client id (0...9)
|
||||||
|
void RingStream::mark(uint8_t b) {
|
||||||
_mark=_pos_write;
|
_mark=_pos_write;
|
||||||
|
write(b); // client id
|
||||||
|
write((uint8_t)0); // count MSB placemarker
|
||||||
|
write((uint8_t)0); // count LSB placemarker
|
||||||
|
_count=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RingStream::commit() {
|
bool RingStream::commit() {
|
||||||
if (_overflow) {
|
if (_overflow) {
|
||||||
_pos_write=_mark;
|
DIAG(F("\nRingStream(%d) commit(%d) OVERFLOW\n"),_len, _count);
|
||||||
_overflow=false;
|
// just throw it away
|
||||||
return false; // commit failed
|
_pos_write=_mark;
|
||||||
|
_overflow=false;
|
||||||
|
return false; // commit failed
|
||||||
}
|
}
|
||||||
write((uint8_t)0);
|
if (_count==0) {
|
||||||
|
// ignore empty response
|
||||||
|
_pos_write=_mark;
|
||||||
|
return true; // true=commit ok
|
||||||
|
}
|
||||||
|
// Go back to the _mark and inject the count 1 byte later
|
||||||
|
_mark++;
|
||||||
|
if (_mark==_len) _mark=0;
|
||||||
|
_buffer[_mark]=highByte(_count);
|
||||||
|
_mark++;
|
||||||
|
if (_mark==_len) _mark=0;
|
||||||
|
_buffer[_mark]=lowByte(_count);
|
||||||
return true; // commit worked
|
return true; // commit worked
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ class RingStream : public Print {
|
|||||||
int read();
|
int read();
|
||||||
int count();
|
int count();
|
||||||
int freeSpace();
|
int freeSpace();
|
||||||
void mark();
|
void mark(uint8_t b);
|
||||||
bool commit();
|
bool commit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -40,6 +40,7 @@ class RingStream : public Print {
|
|||||||
int _pos_read;
|
int _pos_read;
|
||||||
bool _overflow;
|
bool _overflow;
|
||||||
int _mark;
|
int _mark;
|
||||||
|
int _count;
|
||||||
byte * _buffer;
|
byte * _buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,18 +35,13 @@ void WifiInboundHandler::loop1() {
|
|||||||
|
|
||||||
// if nothing is already CIPSEND pending, we can CIPSEND one reply
|
// if nothing is already CIPSEND pending, we can CIPSEND one reply
|
||||||
if (clientPendingCIPSEND<0) {
|
if (clientPendingCIPSEND<0) {
|
||||||
int next=outboundRing->read();
|
clientPendingCIPSEND=outboundRing->read();
|
||||||
if (next>=0) {
|
if (clientPendingCIPSEND>=0) {
|
||||||
currentReplySize=outboundRing->count();
|
currentReplySize=outboundRing->count();
|
||||||
if (currentReplySize==0) {
|
pendingCipsend=true;
|
||||||
outboundRing->read(); // drop end marker
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clientPendingCIPSEND=next-'0'; // convert back to int
|
|
||||||
pendingCipsend=true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (pendingCipsend) {
|
if (pendingCipsend) {
|
||||||
if (Diag::WIFI) DIAG( F("\nWiFi: [[CIPSEND=%d,%d]]"), clientPendingCIPSEND, currentReplySize);
|
if (Diag::WIFI) DIAG( F("\nWiFi: [[CIPSEND=%d,%d]]"), clientPendingCIPSEND, currentReplySize);
|
||||||
@ -57,21 +52,19 @@ void WifiInboundHandler::loop1() {
|
|||||||
|
|
||||||
|
|
||||||
// if something waiting to execute, we can call it
|
// if something waiting to execute, we can call it
|
||||||
int next=inboundRing->read();
|
int clientId=inboundRing->read();
|
||||||
if (next>0) {
|
if (clientId>=0) {
|
||||||
int clientId=next-'0'; //convert char to int
|
|
||||||
int count=inboundRing->count();
|
int count=inboundRing->count();
|
||||||
if (Diag::WIFI) DIAG(F("\nExec waiting %d %d:"),clientId,count);
|
if (Diag::WIFI) DIAG(F("\nWifi EXEC: %d %d:"),clientId,count);
|
||||||
byte cmd[count+1];
|
byte cmd[count+1];
|
||||||
for (int i=0;i<count;i++) cmd[i]=inboundRing->read();
|
for (int i=0;i<count;i++) cmd[i]=inboundRing->read();
|
||||||
cmd[count]=0;
|
cmd[count]=0;
|
||||||
if (Diag::WIFI) DIAG(F("%e\n"),cmd);
|
if (Diag::WIFI) DIAG(F("%e\n"),cmd);
|
||||||
|
|
||||||
outboundRing->mark(); // remember start of outbound data
|
outboundRing->mark(clientId); // remember start of outbound data
|
||||||
outboundRing->print(clientId);
|
|
||||||
CommandDistributor::parse(clientId,cmd,outboundRing);
|
CommandDistributor::parse(clientId,cmd,outboundRing);
|
||||||
// The commit call will either write the null byte at the end of the output,
|
// The commit call will either write the lenbgth bytes
|
||||||
// OR rollback to the mark because the commend generated more than fits rthe buffer
|
// OR rollback to the mark because the reply is empty or commend generated more than fits the buffer
|
||||||
outboundRing->commit();
|
outboundRing->commit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -92,7 +85,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (loopState) {
|
switch (loopState) {
|
||||||
case ANYTHING: // looking for +IPD, > , busy , n,CONNECTED, n,CLOSED
|
case ANYTHING: // looking for +IPD, > , busy , n,CONNECTED, n,CLOSED, ERROR
|
||||||
|
|
||||||
if (ch == '+') {
|
if (ch == '+') {
|
||||||
loopState = IPD;
|
loopState = IPD;
|
||||||
@ -100,12 +93,12 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ch=='>') {
|
if (ch=='>') {
|
||||||
|
if (Diag::WIFI) DIAG(F("[XMIT %d]"),currentReplySize);
|
||||||
for (int i=0;i<currentReplySize;i++) {
|
for (int i=0;i<currentReplySize;i++) {
|
||||||
int cout=outboundRing->read();
|
int cout=outboundRing->read();
|
||||||
wifiStream->write(cout);
|
wifiStream->write(cout);
|
||||||
if (Diag::WIFI) StringFormatter::printEscape(cout); // DIAG in disguise
|
if (Diag::WIFI) StringFormatter::printEscape(cout); // DIAG in disguise
|
||||||
}
|
}
|
||||||
outboundRing->read(); // drop the end marker
|
|
||||||
clientPendingCIPSEND=-1;
|
clientPendingCIPSEND=-1;
|
||||||
pendingCipsend=false;
|
pendingCipsend=false;
|
||||||
loopState=SKIPTOEND;
|
loopState=SKIPTOEND;
|
||||||
@ -170,10 +163,10 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
|||||||
if (inboundRing->freeSpace()<=(dataLength+1)) {
|
if (inboundRing->freeSpace()<=(dataLength+1)) {
|
||||||
// This input would overflow the inbound ring, ignore it
|
// This input would overflow the inbound ring, ignore it
|
||||||
loopState=IPD_IGNORE_DATA;
|
loopState=IPD_IGNORE_DATA;
|
||||||
|
if (Diag::WIFI) DIAG(F("\nWifi OVERFLOW IGNORING:"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
inboundRing->mark();
|
inboundRing->mark(runningClientId);
|
||||||
inboundRing->print(runningClientId); // prefix inbound with client id
|
|
||||||
loopState=IPD_DATA;
|
loopState=IPD_DATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -181,10 +174,10 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IPD_DATA: // reading data
|
case IPD_DATA: // reading data
|
||||||
inboundRing->write(ch);
|
inboundRing->write(ch);
|
||||||
dataLength--;
|
dataLength--;
|
||||||
if (dataLength == 0) {
|
if (dataLength == 0) {
|
||||||
inboundRing->commit();
|
inboundRing->commit();
|
||||||
loopState = ANYTHING;
|
loopState = ANYTHING;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user