]> code.octet-stream.net Git - m17rt/blob - m17core/src/tnc.rs
Modem support for parsing packet frames
[m17rt] / m17core / src / tnc.rs
1 use crate::kiss::{KissBuffer, KissFrame};
2 use crate::protocol::{Frame, LichCollection, LsfFrame, Mode, PacketFrameCounter};
3
4 /// Handles the KISS protocol and frame management for `SoftModulator` and `SoftDemodulator`.
5 ///
6 /// These components work alongside each other. User is responsible for chaining them together
7 /// or doing something else with the data.
8 pub struct SoftTnc {
9 /// Handle framing of KISS commands from the host, which may arrive in arbitrary binary blobs.
10 kiss_buffer: KissBuffer,
11
12 /// Kiss message that needs to be sent to the host.
13 outgoing_kiss: Option<OutgoingKiss>,
14
15 /// Current RX or TX function of the TNC.
16 state: State,
17 }
18
19 impl SoftTnc {
20 pub fn new() -> Self {
21 Self {
22 kiss_buffer: KissBuffer::new(),
23 outgoing_kiss: None,
24 state: State::Idle,
25 }
26 }
27
28 /// Process an individual `Frame` that has been decoded by the modem.
29 pub fn handle_frame(&mut self, frame: Frame) {
30 match frame {
31 Frame::Lsf(lsf) => {
32 // A new LSF implies a clean slate.
33 // If we were partway through decoding something else then we missed it.
34 match lsf.mode() {
35 Mode::Packet => {
36 self.state = State::RxPacket(RxPacketState {
37 lsf,
38 packet: [0u8; 825],
39 count: 0,
40 })
41 }
42 Mode::Stream => {
43 let kiss = KissFrame::new_stream_setup(&lsf.0).unwrap();
44 self.kiss_to_host(kiss);
45 self.state = State::RxStream(RxStreamState { lsf, index: 0 });
46 }
47 }
48 }
49 Frame::Packet(packet) => {
50 match &mut self.state {
51 State::RxPacket(ref mut rx) => {
52 match packet.counter {
53 PacketFrameCounter::Frame { index } => {
54 if index == rx.count && index < 32 {
55 let start = 25 * index;
56 rx.packet[start..(start + 25)].copy_from_slice(&packet.payload);
57 rx.count += 1;
58 } else {
59 // unexpected order - something has gone wrong
60 self.state = State::Idle;
61 }
62 }
63 PacketFrameCounter::FinalFrame { payload_len } => {
64 let start = 25 * rx.count;
65 let end = start + payload_len;
66 rx.packet[start..(start + payload_len)]
67 .copy_from_slice(&packet.payload);
68 let kiss =
69 KissFrame::new_full_packet(&rx.lsf.0, &rx.packet[0..end])
70 .unwrap();
71 self.kiss_to_host(kiss);
72 self.state = State::Idle;
73 }
74 }
75 }
76 _ => {
77 // Invalid transition
78 self.state = State::Idle;
79 }
80 }
81 }
82 Frame::Stream(stream) => {
83 match &mut self.state {
84 State::RxStream(ref mut rx) => {
85 // TODO: consider wraparound from 0x7fff
86 if stream.frame_number < rx.index {
87 let mut lich = LichCollection::new();
88 lich.set_segment(stream.lich_idx, stream.lich_part);
89 self.state = State::RxAcquiringStream(RxAcquiringStreamState { lich });
90 } else {
91 rx.index = stream.frame_number + 1;
92 let kiss = KissFrame::new_stream_data(&stream).unwrap();
93 self.kiss_to_host(kiss);
94 // TODO: end stream if LICH updates indicate non-META part has changed
95 // (this implies a new station)
96 if stream.end_of_stream {
97 self.state = State::Idle;
98 }
99 }
100 }
101 State::RxAcquiringStream(ref mut rx) => {
102 rx.lich.set_segment(stream.lich_idx, stream.lich_part);
103 if let Some(maybe_lsf) = rx.lich.try_assemble() {
104 let lsf = LsfFrame(maybe_lsf);
105 // LICH can change mid-transmission so wait until the CRC is correct
106 // to ensure (to high probability) we haven't done a "torn read"
107 if lsf.crc() == 0 {
108 let kiss = KissFrame::new_stream_setup(&lsf.0).unwrap();
109 self.kiss_to_host(kiss);
110 // TODO: avoid discarding the first data payload here
111 // need a queue depth of 2 for outgoing kiss
112 self.state = State::RxStream(RxStreamState {
113 lsf,
114 index: stream.frame_number + 1,
115 });
116 }
117 }
118 }
119 _ => {
120 // If coming from another state, we have missed something.
121 // Never mind, let's start tracking LICH.
122 let mut lich = LichCollection::new();
123 lich.set_segment(stream.lich_idx, stream.lich_part);
124 self.state = State::RxAcquiringStream(RxAcquiringStreamState { lich })
125 }
126 }
127 }
128 }
129 }
130
131 /// Update the number of samples that have been received by the incoming stream, as a form of timekeeping
132 pub fn advance_samples(&mut self, _samples: u64) {}
133
134 pub fn set_data_carrier_detect(&mut self, _dcd: bool) {}
135
136 pub fn read_tx_frame(&mut self) -> Result<Option<Frame>, SoftTncError> {
137 // yes we want to deal with Frames here
138 // it's important to establish successful decode that SoftDemodulator is aware of the frame innards
139 Ok(None)
140 }
141
142 /// Read KISS message to be sent to host.
143 ///
144 /// After each frame input, this should be consumed in a loop until length 0 is returned.
145 /// This component will never block. Upstream interface can provide blocking `read()` if desired.
146 pub fn read_kiss(&mut self, target_buf: &mut [u8]) -> usize {
147 match self.outgoing_kiss.as_mut() {
148 Some(outgoing) => {
149 let n = (outgoing.kiss_frame.len - outgoing.sent).min(target_buf.len());
150 target_buf[0..n]
151 .copy_from_slice(&outgoing.kiss_frame.data[outgoing.sent..(outgoing.sent + n)]);
152 outgoing.sent += n;
153 if outgoing.sent == outgoing.kiss_frame.len {
154 self.outgoing_kiss = None;
155 }
156 n
157 }
158 None => 0,
159 }
160 }
161
162 pub fn write_kiss(&mut self, buf: &[u8]) -> usize {
163 let target_buf = self.kiss_buffer.buf_remaining();
164 let n = buf.len().min(target_buf.len());
165 target_buf[0..n].copy_from_slice(&buf[0..n]);
166 self.kiss_buffer.did_write(n);
167 while let Some(_kiss_frame) = self.kiss_buffer.next_frame() {
168 // TODO: handle host-to-TNC message
169 }
170 n
171 }
172
173 fn kiss_to_host(&mut self, kiss_frame: KissFrame) {
174 self.outgoing_kiss = Some(OutgoingKiss {
175 kiss_frame,
176 sent: 0,
177 });
178 }
179 }
180
181 #[derive(Debug, PartialEq, Eq, Clone)]
182 pub enum SoftTncError {
183 General(&'static str),
184 InvalidState,
185 }
186
187 struct OutgoingKiss {
188 kiss_frame: KissFrame,
189 sent: usize,
190 }
191
192 enum State {
193 /// Nothing happening.
194 Idle,
195
196 /// We received some stream data but missed the leading LSF so we are trying to assemble from LICH.
197 RxAcquiringStream(RxAcquiringStreamState),
198
199 /// We have acquired an identified stream transmission and are sending data payloads to the host.
200 RxStream(RxStreamState),
201
202 /// We are receiving a packet. All is well so far, and there is more data to come before we tell the host.
203 RxPacket(RxPacketState),
204 // TODO: TX
205 }
206
207 struct RxAcquiringStreamState {
208 /// Partial assembly of LSF by accumulating LICH fields.
209 lich: LichCollection,
210 }
211
212 struct RxStreamState {
213 /// Track identifying information for this transmission so we can tell if it changes.
214 lsf: LsfFrame,
215
216 /// Expected next frame number. Allowed to skip values on RX, but not go backwards.
217 index: u16,
218 }
219
220 struct RxPacketState {
221 /// Initial LSF
222 lsf: LsfFrame,
223
224 /// Accumulation of packet data that we have received so far.
225 packet: [u8; 825],
226
227 /// Number of payload frames we have received. If we are stably in the RxPacket state,
228 /// this will be between 0 and 32 inclusive.
229 count: usize,
230 }
231
232 #[cfg(test)]
233 mod tests {
234 use super::*;
235 use crate::kiss::{KissCommand, PORT_STREAM};
236 use crate::protocol::StreamFrame;
237
238 // TODO: finish all handle_frame tests as below
239 // this will be much more straightforward when we have a way to create LSFs programatically
240
241 // receiving a single-frame packet
242
243 // receiving a multi-frame packet
244
245 // part of one packet and then another
246
247 #[test]
248 fn tnc_receive_stream() {
249 let lsf = LsfFrame([
250 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,
251 0, 0, 0, 0, 0, 131, 53,
252 ]);
253 let stream1 = StreamFrame {
254 lich_idx: 0,
255 lich_part: [255, 255, 255, 255, 255],
256 frame_number: 0,
257 end_of_stream: false,
258 stream_data: [
259 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75,
260 ],
261 };
262 let stream2 = StreamFrame {
263 lich_idx: 1,
264 lich_part: [255, 0, 0, 0, 159],
265 frame_number: 1,
266 end_of_stream: true,
267 stream_data: [
268 17, 0, 94, 82, 216, 135, 181, 15, 30, 0, 125, 195, 152, 183, 41, 57,
269 ],
270 };
271 let mut tnc = SoftTnc::new();
272 let mut kiss = KissFrame::new_empty();
273 assert_eq!(tnc.read_kiss(&mut kiss.data), 0);
274
275 tnc.handle_frame(Frame::Lsf(lsf));
276 kiss.len = tnc.read_kiss(&mut kiss.data);
277 assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame);
278 assert_eq!(kiss.port().unwrap(), PORT_STREAM);
279
280 let mut payload_buf = [0u8; 2048];
281 let n = kiss.decode_payload(&mut payload_buf).unwrap();
282 assert_eq!(n, 30);
283
284 tnc.handle_frame(Frame::Stream(stream1));
285 kiss.len = tnc.read_kiss(&mut kiss.data);
286 assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame);
287 assert_eq!(kiss.port().unwrap(), PORT_STREAM);
288
289 let n = kiss.decode_payload(&mut payload_buf).unwrap();
290 assert_eq!(n, 26);
291
292 tnc.handle_frame(Frame::Stream(stream2));
293 kiss.len = tnc.read_kiss(&mut kiss.data);
294 assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame);
295 assert_eq!(kiss.port().unwrap(), PORT_STREAM);
296
297 let n = kiss.decode_payload(&mut payload_buf).unwrap();
298 assert_eq!(n, 26);
299 }
300
301 #[test]
302 fn tnc_acquire_stream() {
303 let frames = [
304 StreamFrame {
305 lich_idx: 0,
306 lich_part: [255, 255, 255, 255, 255],
307 frame_number: 0,
308 end_of_stream: false,
309 stream_data: [
310 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75,
311 ],
312 },
313 StreamFrame {
314 lich_idx: 1,
315 lich_part: [255, 0, 0, 0, 159],
316 frame_number: 1,
317 end_of_stream: false,
318 stream_data: [
319 17, 0, 94, 82, 216, 135, 181, 15, 30, 0, 125, 195, 152, 183, 41, 57,
320 ],
321 },
322 StreamFrame {
323 lich_idx: 2,
324 lich_part: [221, 81, 5, 5, 0],
325 frame_number: 2,
326 end_of_stream: false,
327 stream_data: [
328 17, 128, 93, 74, 154, 167, 169, 11, 20, 0, 116, 91, 158, 220, 45, 111,
329 ],
330 },
331 StreamFrame {
332 lich_idx: 3,
333 lich_part: [0, 0, 0, 0, 0],
334 frame_number: 3,
335 end_of_stream: false,
336 stream_data: [
337 15, 128, 114, 83, 218, 252, 59, 111, 31, 128, 116, 91, 84, 231, 45, 105,
338 ],
339 },
340 StreamFrame {
341 lich_idx: 4,
342 lich_part: [0, 0, 0, 0, 0],
343 frame_number: 4,
344 end_of_stream: false,
345 stream_data: [
346 9, 128, 119, 115, 220, 220, 57, 15, 48, 128, 124, 83, 158, 236, 181, 91,
347 ],
348 },
349 StreamFrame {
350 lich_idx: 5,
351 lich_part: [0, 0, 0, 131, 53],
352 frame_number: 5,
353 end_of_stream: false,
354 stream_data: [
355 52, 0, 116, 90, 152, 167, 225, 216, 32, 0, 116, 83, 156, 212, 33, 216,
356 ],
357 },
358 ];
359
360 let mut tnc = SoftTnc::new();
361 let mut kiss = KissFrame::new_empty();
362 for f in frames {
363 tnc.handle_frame(Frame::Stream(f));
364 }
365 kiss.len = tnc.read_kiss(&mut kiss.data);
366 let mut payload_buf = [0u8; 2048];
367 let n = kiss.decode_payload(&mut payload_buf).unwrap();
368 assert_eq!(n, 30);
369 assert_eq!(
370 &payload_buf[0..30],
371 [
372 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0,
373 0, 0, 0, 0, 0, 0, 131, 53,
374 ]
375 );
376 }
377
378 #[test]
379 fn tnc_handle_skipped_stream_frame() {
380 let lsf = LsfFrame([
381 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,
382 0, 0, 0, 0, 0, 131, 53,
383 ]);
384 let stream1 = StreamFrame {
385 lich_idx: 0,
386 lich_part: [255, 255, 255, 255, 255],
387 frame_number: 0,
388 end_of_stream: false,
389 stream_data: [
390 128, 0, 119, 115, 220, 252, 41, 235, 8, 0, 116, 195, 94, 244, 45, 75,
391 ],
392 };
393 let stream3 = StreamFrame {
394 lich_idx: 2,
395 lich_part: [221, 81, 5, 5, 0],
396 frame_number: 2,
397 end_of_stream: false,
398 stream_data: [
399 17, 128, 93, 74, 154, 167, 169, 11, 20, 0, 116, 91, 158, 220, 45, 111,
400 ],
401 };
402 let mut tnc = SoftTnc::new();
403 let mut kiss = KissFrame::new_empty();
404 assert_eq!(tnc.read_kiss(&mut kiss.data), 0);
405
406 tnc.handle_frame(Frame::Lsf(lsf));
407 kiss.len = tnc.read_kiss(&mut kiss.data);
408 assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame);
409 assert_eq!(kiss.port().unwrap(), PORT_STREAM);
410
411 let mut payload_buf = [0u8; 2048];
412 let n = kiss.decode_payload(&mut payload_buf).unwrap();
413 assert_eq!(n, 30);
414
415 tnc.handle_frame(Frame::Stream(stream1));
416 kiss.len = tnc.read_kiss(&mut kiss.data);
417 assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame);
418 assert_eq!(kiss.port().unwrap(), PORT_STREAM);
419
420 let n = kiss.decode_payload(&mut payload_buf).unwrap();
421 assert_eq!(n, 26);
422
423 tnc.handle_frame(Frame::Stream(stream3));
424 kiss.len = tnc.read_kiss(&mut kiss.data);
425 assert_eq!(kiss.command().unwrap(), KissCommand::DataFrame);
426 assert_eq!(kiss.port().unwrap(), PORT_STREAM);
427
428 let n = kiss.decode_payload(&mut payload_buf).unwrap();
429 assert_eq!(n, 26);
430 }
431 }