99
1010namespace 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