Skip to content

Commit ea7cddd

Browse files
author
Bas Visscher
committed
Simplified slip framing
1 parent 1aa3de9 commit ea7cddd

File tree

1 file changed

+44
-79
lines changed

1 file changed

+44
-79
lines changed

ESPTool/Communication/SlipFraming.cs

Lines changed: 44 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -9,129 +9,94 @@
99

1010
namespace EspDotNet.Communication
1111
{
12+
/* In slipframing, the following rules apply:
13+
* 0xC0 => 0xDB 0xDC
14+
* 0xDC => 0xDB 0xDD
15+
*/
16+
1217
public class SlipFraming
1318
{
1419
private const byte FrameDelimiter = 0xC0;
1520
private const byte EscapeByte = 0xDB;
16-
private const byte EscapeFrameDelimiter = 0xDC;
21+
private const byte EscapeFrameDelimiter = 0xDC;
1722
private const byte EscapeEscapeByte = 0xDD;
18-
1923
private readonly SerialPort _serialPort;
2024

2125
public SlipFraming(SerialPort serialPort)
2226
{
2327
_serialPort = serialPort;
2428
}
2529

26-
/// <summary>
27-
/// Writes a SLIP-encoded frame asynchronously to the stream.
28-
/// </summary>
29-
/// <param name="frame">The frame to be written to the stream.</param>
30-
/// <param name="token">Cancellation token to cancel the operation.</param>
31-
/// <returns>A task representing the asynchronous operation.</returns>
32-
/// <exception cref="OperationCanceledException">Thrown if the operation is canceled via the cancellation token.</exception>
33-
/// <exception cref="IOException">Thrown if an I/O error occurs during writing.</exception>
3430
public async Task WriteFrameAsync(Frame frame, CancellationToken token)
3531
{
36-
byte[] encodedFrame = Encode(frame);
37-
//Debug.Write($"(TX) ");
38-
//foreach(var b in encodedFrame)
39-
// Debug.Write($"{b:X2} ");
40-
//Debug.WriteLine($"");
41-
await _serialPort.BaseStream.WriteAsync(encodedFrame, 0, encodedFrame.Length, token);
32+
byte[] escapedFrame = EscapeFrame(frame);
33+
_serialPort.BaseStream.WriteByte(FrameDelimiter); // Start of frame
34+
await _serialPort.BaseStream.WriteAsync(escapedFrame, 0, escapedFrame.Length, token);
35+
_serialPort.BaseStream.WriteByte(FrameDelimiter); // end of frame
4236
await _serialPort.BaseStream.FlushAsync(token); // Ensure all data is sent
4337
}
4438

45-
/// <summary>
46-
/// Reads and decodes a SLIP-encoded frame asynchronously from the stream.
47-
/// Reads until the end of the frame is received.
48-
/// </summary>
49-
/// <param name="token">Cancellation token to cancel the operation.</param>
50-
/// <returns>The decoded frame, or null if the end of the stream is reached.</returns>
51-
/// <exception cref="OperationCanceledException">Thrown if the operation is canceled via the cancellation token.</exception>
52-
/// <exception cref="IOException">Thrown if an I/O error occurs during reading.</exception>
5339
public async Task<Frame?> ReadFrameAsync(CancellationToken token)
5440
{
55-
List<byte> buffer = new List<byte>();
56-
bool startFound = false;
41+
List<byte> escapedFrameBuffer = new List<byte>();
5742

43+
// In slipframing, all delimiters are replaced, so we can record everything between delimeters and decode it later
5844
while (true)
5945
{
60-
// Wait for data
61-
while (_serialPort.BytesToRead == 0)
62-
{
63-
// Prevent busy waiting
64-
await Task.Delay(10, token);
65-
}
66-
67-
byte currentByte = (byte)_serialPort.ReadByte();
46+
byte currentByte = await ReadByte(token);
6847

6948
if (currentByte == FrameDelimiter)
7049
{
71-
if (startFound)
72-
{
73-
// End of the frame
74-
if (buffer.Count == 0)
75-
continue;
76-
77-
return Decode(buffer.ToArray());
78-
}
79-
else
80-
{
81-
// Start of the frame
82-
startFound = true;
83-
buffer.Clear();
84-
//Debug.Write($"(RX) SOF ");
85-
}
50+
// If we havent recieved any data yet, this is the SOF
51+
if (escapedFrameBuffer.Count > 0)
52+
return Unescape(escapedFrameBuffer.ToArray());
8653
}
87-
else if (startFound)
54+
else
8855
{
89-
// Add byte to the buffer
90-
buffer.Add(currentByte);
91-
//Debug.Write($"{currentByte:X2} ");
56+
escapedFrameBuffer.Add(currentByte);
9257
}
9358
}
9459
}
9560

96-
/// <summary>
97-
/// Encodes the frame into SLIP format.
98-
/// </summary>
99-
/// <param name="frame">The frame to encode.</param>
100-
/// <returns>A byte array containing the SLIP-encoded frame.</returns>
101-
private byte[] Encode(Frame frame)
61+
private async Task<byte> ReadByte(CancellationToken token)
62+
{
63+
// Wait for data
64+
while (_serialPort.BytesToRead == 0)
65+
{
66+
// Prevent busy waiting
67+
await Task.Delay(10, token);
68+
}
69+
70+
return (byte)_serialPort.ReadByte();
71+
}
72+
73+
private byte[] EscapeFrame(Frame frame)
10274
{
103-
List<byte> encoded = new List<byte> { FrameDelimiter };
75+
List<byte> buffer = new();
10476

10577
foreach (byte b in frame.Data)
10678
{
10779
if (b == FrameDelimiter)
10880
{
109-
encoded.Add(EscapeByte);
110-
encoded.Add(EscapeFrameDelimiter);
81+
buffer.Add(EscapeByte);
82+
buffer.Add(EscapeFrameDelimiter);
11183
}
11284
else if (b == EscapeByte)
11385
{
114-
encoded.Add(EscapeByte);
115-
encoded.Add(EscapeEscapeByte);
86+
buffer.Add(EscapeByte);
87+
buffer.Add(EscapeEscapeByte);
11688
}
11789
else
11890
{
119-
encoded.Add(b);
91+
buffer.Add(b);
12092
}
12193
}
122-
123-
encoded.Add(FrameDelimiter);
124-
return encoded.ToArray();
94+
return buffer.ToArray();
12595
}
12696

127-
/// <summary>
128-
/// Decodes the SLIP-encoded data into a Frame.
129-
/// </summary>
130-
/// <param name="data">The SLIP-encoded byte array.</param>
131-
/// <returns>The decoded frame.</returns>
132-
private Frame? Decode(byte[] data)
97+
private Frame? Unescape(byte[] data)
13398
{
134-
List<byte> decoded = new List<byte>();
99+
List<byte> buffer = new List<byte>();
135100

136101
for (int i = 0; i < data.Length; i++)
137102
{
@@ -142,20 +107,20 @@ private byte[] Encode(Frame frame)
142107

143108
if (data[i] == EscapeFrameDelimiter)
144109
{
145-
decoded.Add(FrameDelimiter);
110+
buffer.Add(FrameDelimiter);
146111
}
147112
else if (data[i] == EscapeEscapeByte)
148113
{
149-
decoded.Add(EscapeByte);
114+
buffer.Add(EscapeByte);
150115
}
151116
}
152117
else
153118
{
154-
decoded.Add(data[i]);
119+
buffer.Add(data[i]);
155120
}
156121
}
157122

158-
return new Frame(decoded.ToArray());
123+
return new Frame(buffer.ToArray());
159124
}
160125
}
161126
}

0 commit comments

Comments
 (0)