mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-06 03:50:13 +02:00
Final fixes from andy
This commit is contained in:
parent
ca21dae6ba
commit
90bb3fe843
7 changed files with 435 additions and 241 deletions
|
@ -109,6 +109,16 @@ bool SerialDataLink::checkTransmissionError(bool resetFlag)
|
|||
return currentStatus;
|
||||
}
|
||||
|
||||
int SerialDataLink::getLastAcknowledge(bool resetFlag)
|
||||
{
|
||||
int result = lastAcknowledgeStatus;
|
||||
if (resetFlag)
|
||||
{
|
||||
lastAcknowledgeStatus = 0; // Reset to default state
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SerialDataLink::checkReadError(bool reset)
|
||||
{
|
||||
bool error = readError;
|
||||
|
@ -134,115 +144,135 @@ void SerialDataLink::muteACK(bool mute)
|
|||
|
||||
void SerialDataLink::run()
|
||||
{
|
||||
unsigned long currentTime = millis();
|
||||
static DataLinkState oldstate;
|
||||
|
||||
|
||||
// Check if state has not changed for a prolonged period
|
||||
if (oldstate != currentState)
|
||||
{
|
||||
lastStateChangeTime = currentTime;
|
||||
oldstate = currentState;
|
||||
}
|
||||
if ((currentTime - lastStateChangeTime) > stateChangeTimeout) {
|
||||
// Reset the state to Idle and perform necessary cleanup
|
||||
currentState = DataLinkState::Idle;
|
||||
// Perform any additional cleanup or reinitialization here
|
||||
// ...
|
||||
|
||||
lastStateChangeTime = currentTime; // Reset the last state change time
|
||||
}
|
||||
switch (currentState)
|
||||
{
|
||||
case DataLinkState::Idle:
|
||||
// Decide if the device should start transmitting
|
||||
currentState = DataLinkState::Receiving;
|
||||
if (shouldTransmit())
|
||||
{
|
||||
currentState = DataLinkState::Transmitting;
|
||||
}
|
||||
break;
|
||||
|
||||
case DataLinkState::Transmitting:
|
||||
if (isTransmitting)
|
||||
{
|
||||
sendNextByte(); // Continue sending the current data
|
||||
}
|
||||
else
|
||||
{
|
||||
constructPacket(); // Construct a new packet if not currently transmitting
|
||||
|
||||
if (muteAcknowledgement && (needToACK || needToNACK))
|
||||
{
|
||||
needToACK = false;
|
||||
needToNACK = false;
|
||||
}
|
||||
uint8_t ack;
|
||||
// now it is known which acknoledge need sending since last Reception
|
||||
if (needToACK)
|
||||
{
|
||||
needToACK = false;
|
||||
ack = (txBufferIndex > 5) ? ACK_RTT_CODE : ACK_CODE;
|
||||
serial.write(ack);
|
||||
}
|
||||
if (needToNACK)
|
||||
{
|
||||
needToNACK = false;
|
||||
ack = (txBufferIndex > 5) ? NACK_RTT_CODE : NACK_CODE;
|
||||
serial.write(ack);
|
||||
}
|
||||
}
|
||||
|
||||
if (maxIndexTX < 1)
|
||||
{
|
||||
currentState = DataLinkState::Receiving;
|
||||
}
|
||||
// Check if the transmission is complete
|
||||
if (transmissionComplete)
|
||||
{
|
||||
transmissionComplete = false;
|
||||
isTransmitting = false;
|
||||
currentState = DataLinkState::WaitingForAck; // Move to WaitingForAck state
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DataLinkState::WaitingForAck:
|
||||
if (ackTimeout())
|
||||
{
|
||||
// Handle ACK timeout scenario
|
||||
transmissionError = true;
|
||||
isTransmitting = false;
|
||||
//handleAckTimeout();
|
||||
//--- if no ACK's etc received may as well move to Transmitting
|
||||
currentState = DataLinkState::Transmitting;
|
||||
}
|
||||
if (ackReceived())
|
||||
{
|
||||
// No data to send from the other device
|
||||
currentState = DataLinkState::Transmitting;
|
||||
}
|
||||
if (requestToSend)
|
||||
{
|
||||
// The other device has data to send (indicated by ACK+RTT)
|
||||
currentState = DataLinkState::Receiving;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DataLinkState::Receiving:
|
||||
read();
|
||||
if (readComplete)
|
||||
{
|
||||
readComplete = false;
|
||||
// transition to transmit mode
|
||||
currentState = DataLinkState::Transmitting;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
unsigned long currentTime = millis();
|
||||
static DataLinkState oldstate;
|
||||
|
||||
|
||||
// Check if state has not changed for a prolonged period
|
||||
if (oldstate != currentState)
|
||||
{
|
||||
lastStateChangeTime = currentTime;
|
||||
oldstate = currentState;
|
||||
}
|
||||
if ((currentTime - lastStateChangeTime) > stateChangeTimeout) {
|
||||
// Reset the state to Idle and perform necessary cleanup
|
||||
currentState = DataLinkState::Idle;
|
||||
// Perform any additional cleanup or reinitialization here
|
||||
// ...
|
||||
|
||||
lastStateChangeTime = currentTime; // Reset the last state change time
|
||||
}
|
||||
|
||||
switch (currentState)
|
||||
{
|
||||
case DataLinkState::Idle:
|
||||
// Decide if the device should start transmitting
|
||||
currentState = DataLinkState::Receiving;
|
||||
if (shouldTransmit())
|
||||
{
|
||||
currentState = DataLinkState::WaitTobuildPacket;
|
||||
}
|
||||
break;
|
||||
|
||||
case DataLinkState::WaitTobuildPacket:
|
||||
constructPacket();
|
||||
if (isTransmitting)
|
||||
{
|
||||
currentState = DataLinkState::Transmitting;
|
||||
}
|
||||
break;
|
||||
|
||||
case DataLinkState::Transmitting:
|
||||
sendNextByte();
|
||||
|
||||
// Check if the transmission is complete
|
||||
if (transmissionComplete)
|
||||
{
|
||||
transmissionComplete = false;
|
||||
isTransmitting = false;
|
||||
currentState = DataLinkState::WaitingForAck; // Move to WaitingForAck state
|
||||
}
|
||||
break;
|
||||
|
||||
case DataLinkState::WaitingForAck:
|
||||
|
||||
if (ackTimeout())
|
||||
{
|
||||
// Handle ACK timeout scenario
|
||||
transmissionError = true;
|
||||
lastAcknowledgeStatus = -1;
|
||||
//--- if no ACK's etc received may as well move to Transmitting
|
||||
currentState = DataLinkState::Idle;
|
||||
}
|
||||
}
|
||||
if (ackReceived())
|
||||
{
|
||||
// No data to send from the other device
|
||||
currentState = DataLinkState::Idle;
|
||||
}
|
||||
if (requestToSend)
|
||||
{
|
||||
// The other device has data to send (indicated by ACK+RTT)
|
||||
currentState = DataLinkState::Receiving;
|
||||
requestToSend = false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DataLinkState::Receiving:
|
||||
read();
|
||||
if (readComplete)
|
||||
{
|
||||
readComplete = false;
|
||||
currentState = DataLinkState::SendingAck;
|
||||
}
|
||||
break;
|
||||
|
||||
case DataLinkState::SendingAck:
|
||||
|
||||
constructPacket();
|
||||
|
||||
if (muteAcknowledgement && (needToACK || needToNACK))
|
||||
{
|
||||
needToACK = false;
|
||||
needToNACK = false;
|
||||
}
|
||||
uint8_t ack;
|
||||
// now it is known which acknoledge need sending since last Reception
|
||||
if (needToACK)
|
||||
{
|
||||
needToACK = false;
|
||||
ack = (txBufferIndex > 5) ? ACK_RTT_CODE : ACK_CODE;
|
||||
serial.write(ack);
|
||||
}
|
||||
if (needToNACK)
|
||||
{
|
||||
needToNACK = false;
|
||||
ack = (txBufferIndex > 5) ? NACK_RTT_CODE : NACK_CODE;
|
||||
serial.write(ack);
|
||||
}
|
||||
|
||||
currentState = DataLinkState::Idle;
|
||||
if (isTransmitting)
|
||||
{
|
||||
currentState = DataLinkState::Wait;
|
||||
}
|
||||
break;
|
||||
|
||||
case DataLinkState::Wait:
|
||||
{
|
||||
static unsigned long waitTimer=0;
|
||||
if (waitTimer == 0) waitTimer = currentTime;
|
||||
if (currentTime - waitTimer > 20)
|
||||
{
|
||||
waitTimer=0;
|
||||
currentState = DataLinkState::Transmitting;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
currentState = DataLinkState::Idle;
|
||||
}
|
||||
}
|
||||
|
||||
void SerialDataLink::updateState(DataLinkState newState)
|
||||
|
@ -343,42 +373,48 @@ bool SerialDataLink::sendNextByte()
|
|||
|
||||
bool SerialDataLink::ackReceived()
|
||||
{
|
||||
|
||||
// Check if there is data available to read
|
||||
if (serial.available() > 0)
|
||||
int count = 0;
|
||||
if (serial.available() )
|
||||
{
|
||||
// Peek at the next byte without removing it from the buffer
|
||||
uint8_t nextByte = serial.peek();
|
||||
count++;
|
||||
// Peek at the next byte without removing it from the buffer
|
||||
uint8_t nextByte = serial.peek();
|
||||
|
||||
if (nextByte == headerChar)
|
||||
{
|
||||
requestToSend = true;
|
||||
transmissionError = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t receivedByte = serial.read();
|
||||
|
||||
switch (receivedByte)
|
||||
{
|
||||
case ACK_CODE:
|
||||
// Handle standard ACK
|
||||
return true;
|
||||
|
||||
case ACK_RTT_CODE:
|
||||
// Handle ACK with request to transmit
|
||||
requestToSend = true;
|
||||
return true;
|
||||
|
||||
case NACK_RTT_CODE:
|
||||
requestToSend = true;
|
||||
case NACK_CODE:
|
||||
transmissionError = true;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (nextByte == headerChar)
|
||||
{
|
||||
requestToSend = true;
|
||||
transmissionError = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t receivedByte = serial.read();
|
||||
|
||||
switch (receivedByte)
|
||||
{
|
||||
case ACK_CODE:
|
||||
// Handle standard ACK
|
||||
lastAcknowledgeStatus = 1;
|
||||
return true;
|
||||
|
||||
case ACK_RTT_CODE:
|
||||
// Handle ACK with request to transmit
|
||||
requestToSend = true;
|
||||
lastAcknowledgeStatus = 1;
|
||||
return true;
|
||||
|
||||
case NACK_RTT_CODE:
|
||||
requestToSend = true;
|
||||
case NACK_CODE:
|
||||
transmissionError = true;
|
||||
lastAcknowledgeStatus = -2;
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false; // No ACK, NACK, or new packet received
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ public:
|
|||
|
||||
// Check for errors
|
||||
bool checkTransmissionError(bool resetFlag);
|
||||
int getLastAcknowledge(bool resetFlag);
|
||||
bool checkReadError(bool resetFlag);
|
||||
|
||||
// Setter methods for various parameters and special characters
|
||||
|
@ -84,9 +85,12 @@ private:
|
|||
enum class DataLinkState
|
||||
{
|
||||
Idle,
|
||||
WaitTobuildPacket,
|
||||
Transmitting,
|
||||
WaitingForAck,
|
||||
Receiving,
|
||||
SendingAck,
|
||||
Wait,
|
||||
Error
|
||||
};
|
||||
|
||||
|
@ -117,6 +121,7 @@ private:
|
|||
bool readComplete = false;
|
||||
bool retransmitEnabled;
|
||||
bool transmissionError = false;
|
||||
int lastAcknowledgeStatus = 0;
|
||||
bool readError = false;
|
||||
bool muteAcknowledgement = false;
|
||||
|
||||
|
@ -129,13 +134,15 @@ private:
|
|||
int16_t dataArrayRX[dataArraySizeRX];
|
||||
bool dataUpdated[dataArraySizeTX];
|
||||
unsigned long lastSent[dataArraySizeTX];
|
||||
|
||||
|
||||
// times in milliseconds
|
||||
unsigned long updateInterval = 1000;
|
||||
unsigned long ACK_TIMEOUT = 200;
|
||||
unsigned long PACKET_TIMEOUT = 200; // Timeout in milliseconds
|
||||
|
||||
unsigned long lastStateChangeTime = 0;
|
||||
unsigned long PACKET_TIMEOUT = 200;
|
||||
unsigned long stateChangeTimeout = 300;
|
||||
|
||||
unsigned long lastStateChangeTime = 0;
|
||||
|
||||
|
||||
// Special characters for packet framing
|
||||
char headerChar = '<';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue