]> code.octet-stream.net Git - m17rt/blob - m17core/src/tnc.rs
3f9eb0241473037d803325413cfa1db6f06ed77c
[m17rt] / m17core / src / tnc.rs
1 use crate::kiss::{KissBuffer, KissFrame};
2 use crate::protocol::{Frame, LichCollection, LsfFrame};
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) -> Result<(), SoftTncError> {
30 Ok(())
31 }
32
33 /// Update the number of samples that have been received by the incoming stream, as a form of timekeeping
34 pub fn advance_samples(&mut self, _samples: u64) {}
35
36 pub fn set_data_carrier_detect(&mut self, _dcd: bool) {}
37
38 pub fn read_tx_frame(&mut self) -> Result<Option<Frame>, SoftTncError> {
39 // yes we want to deal with Frames here
40 // it's important to establish successful decode that SoftDemodulator is aware of the frame innards
41 Ok(None)
42 }
43
44 /// Read KISS message to be sent to host.
45 ///
46 /// After each frame input, this should be consumed in a loop until length 0 is returned.
47 /// This component will never block. Upstream interface can provide blocking `read()` if desired.
48 pub fn read_kiss(&mut self, target_buf: &mut [u8]) -> Result<usize, SoftTncError> {
49 match self.outgoing_kiss.as_mut() {
50 Some(outgoing) => {
51 let n = (outgoing.kiss_frame.len - outgoing.sent).min(target_buf.len());
52 target_buf[0..n]
53 .copy_from_slice(&outgoing.kiss_frame.data[outgoing.sent..(outgoing.sent + n)]);
54 outgoing.sent += n;
55 Ok(n)
56 }
57 None => Ok(0),
58 }
59 }
60
61 pub fn write_kiss(&mut self, buf: &[u8]) -> Result<usize, SoftTncError> {
62 let target_buf = self.kiss_buffer.buf_remaining();
63 let n = buf.len().min(target_buf.len());
64 target_buf[0..n].copy_from_slice(&buf[0..n]);
65 self.kiss_buffer.did_write(n);
66 while let Some(_kiss_frame) = self.kiss_buffer.next_frame() {
67 // TODO: handle host-to-TNC message
68 }
69 Ok(n)
70 }
71 }
72
73 #[derive(Debug)]
74 pub enum SoftTncError {
75 General(&'static str),
76 }
77
78 struct OutgoingKiss {
79 kiss_frame: KissFrame,
80 sent: usize,
81 }
82
83 enum State {
84 /// Nothing happening.
85 Idle,
86
87 /// We received some stream data but missed the leading LSF so we are trying to assemble from LICH.
88 RxAcquiringStream(RxAcquiringStreamState),
89
90 /// We have acquired an identified stream transmission and are sending data payloads to the host.
91 RxStream(RxStreamState),
92
93 /// We are receiving a packet. All is well so far, and there is more data to come before we tell the host.
94 RxPacket(RxPacketState),
95 // TODO: TX
96 }
97
98 struct RxAcquiringStreamState {
99 /// Partial assembly of LSF by accumulating LICH fields.
100 lich: LichCollection,
101 }
102
103 struct RxStreamState {
104 /// Track identifying information for this transmission so we can tell if it changes.
105 lsf: LsfFrame,
106 }
107
108 struct RxPacketState {
109 /// Accumulation of packet data that we have received so far.
110 packet: [u8; 825],
111
112 /// Number of frames we have received. If we are stably in the RxPacket state,
113 /// this will be between 1 and 32 inclusive. The first frame gets us into the
114 /// rx state, and the maximum 33rd frame must end the transmission and state.
115 count: usize,
116 }