-
Notifications
You must be signed in to change notification settings - Fork 0
/
SerialDataLink.h
185 lines (146 loc) · 5.85 KB
/
SerialDataLink.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/**
* @file SerialDataLink.h
* @brief Half-Duplex Serial Data Link for Arduino
*
* This file contains the definition of the SerialDataLink class, designed to facilitate
* half-duplex communication between Arduino controllers. The class employs a non-blocking,
* poll-based approach to transmit and receive data, making it suitable for applications
* where continuous monitoring and variable transfer between controllers are required.
*
* The half-duplex nature of this implementation allows for data transfer in both directions,
* but not simultaneously, ensuring a controlled communication flow and reducing the likelihood
* of data collision.
*
*
* @author MackElec
* @web https://github.com/mackelec/SerialDataLink
* @license MIT
*/
// ... Class definition ...
/**
* @class SerialDataLink
* @brief Class for managing half-duplex serial communication.
*
* Provides functions to send and receive data in a half-duplex manner over a serial link.
* It supports non-blocking operation with a polling approach to check for new data and
* transmission errors.
*
* Public Methods:
* - SerialDataLink(): Constructor to initialize the communication parameters.
* - run(): Main method to be called frequently to handle data transmission and reception.
* - updateData(): Method to update data to be transmitted.
* - getReceivedData(): Retrieves data received from the serial link.
* - checkNewData(): Checks if new data has been received.
* - checkTransmissionError(): Checks for transmission errors.
* - checkReadError(): Checks for read errors.
* - setUpdateInterval(): Sets the interval for data updates.
* - setAckTimeout(): Sets the timeout for acknowledgments.
* - setPacketTimeout(): Sets the timeout for packet reception.
* - setHeaderChar(): Sets the character used to denote the start of a packet.
* - setEOTChar(): Sets the character used to denote the end of a packet.
*/
#ifndef SERIALDATALINK_H
#define SERIALDATALINK_H
#include <Arduino.h>
class SerialDataLink {
public:
// Constructor
SerialDataLink(Stream &serial, uint8_t transmitID, uint8_t receiveID, uint8_t maxIndexTX, uint8_t maxIndexRX, bool enableRetransmit = false);
// Method to handle data transmission and reception
void run();
void updateData(uint8_t index, int16_t value);
// Check if new data has been received
bool checkNewData(bool resetFlag);
int16_t getReceivedData(uint8_t index);
// Check for errors
bool checkTransmissionError(bool resetFlag);
int getLastAcknowledge(bool resetFlag);
bool checkReadError(bool resetFlag);
// Setter methods for various parameters and special characters
void setUpdateInterval(unsigned long interval);
void setAckTimeout(unsigned long timeout);
void setPacketTimeout(unsigned long timeout);
void setHeaderChar(char header);
void setEOTChar(char eot);
void muteACK(bool mute);
private:
enum class DataLinkState
{
Idle,
WaitTobuildPacket,
Transmitting,
WaitingForAck,
Receiving,
SendingAck,
Wait,
Error
};
DataLinkState currentState;
Stream &serial;
uint8_t transmitID;
uint8_t receiveID;
// Separate max indices for TX and RX
const uint8_t maxIndexTX;
const uint8_t maxIndexRX;
// Buffer and state management
static const uint8_t txBufferSize = 128; // Adjust size as needed
static const uint8_t rxBufferSize = 128; // Adjust size as needed
uint8_t txBuffer[txBufferSize];
uint8_t rxBuffer[rxBufferSize];
uint8_t txBufferIndex;
uint8_t rxBufferIndex;
uint8_t sendBufferIndex = 0;
bool isTransmitting;
bool transmissionComplete = false;
bool isReceiving;
bool readComplete = false;
bool retransmitEnabled;
bool transmissionError = false;
int lastAcknowledgeStatus = 0;
bool readError = false;
bool muteAcknowledgement = false;
// Data arrays and update management
static const uint8_t dataArraySizeTX = 20; // Adjust size as needed for TX
static const uint8_t dataArraySizeRX = 20; // Adjust size as needed for RX
int16_t dataArrayTX[dataArraySizeTX];
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;
unsigned long stateChangeTimeout = 300;
unsigned long lastStateChangeTime = 0;
// Special characters for packet framing
char headerChar = '<';
char eotChar = '>';
static const uint8_t ACK_CODE = 0x06; // Standard acknowledgment
static const uint8_t ACK_RTT_CODE = 0x07; // Acknowledgment with request to transmit
static const uint8_t NACK_CODE = 0x08; // Negative acknowledgment
static const uint8_t NACK_RTT_CODE = 0x09; // Negative acknowledgment with request to transmit
// Internal methods for packet construction, transmission, and reception
bool shouldTransmit();
void constructPacket();
void addToTxBuffer(uint8_t byte);
bool sendNextByte();
bool ackReceived();
bool ackTimeout();
void updateState(DataLinkState newState);
// Internal methods for reception
void read();
void handleResendRequest();
bool isCompletePacket();
void processPacket();
void sendACK();
bool checkCRC();
uint16_t calculateCRC16(const uint8_t* data, size_t length);
unsigned long lastTransmissionTime;
bool requestToSend = false;
unsigned long lastHeaderTime = 0;
bool newData = false;
bool needToACK = false;
bool needToNACK = false;
uint8_t eotPosition = 0;
};
#endif // SERIALDATALINK_H