]>
code.octet-stream.net Git - m17rt/blob - m17core/src/tnc.rs
a847683a548d360f3a25f11a912e6e8c2a663018
1 use crate::kiss
::{KissBuffer
, KissFrame
};
2 use crate::protocol
::{Frame
, LichCollection
, LsfFrame
, Mode
, PacketFrameCounter
};
4 /// Handles the KISS protocol and frame management for `SoftModulator` and `SoftDemodulator`.
6 /// These components work alongside each other. User is responsible for chaining them together
7 /// or doing something else with the data.
9 /// Handle framing of KISS commands from the host, which may arrive in arbitrary binary blobs.
10 kiss_buffer
: KissBuffer
,
12 /// Kiss message that needs to be sent to the host.
13 outgoing_kiss
: Option
<OutgoingKiss
>,
15 /// Current RX or TX function of the TNC.
20 pub fn new() -> Self {
22 kiss_buffer
: KissBuffer
::new(),
28 /// Process an individual `Frame` that has been decoded by the modem.
29 pub fn handle_frame(&mut self, frame
: Frame
) -> Result
<(), SoftTncError
> {
32 // A new LSF implies a clean slate.
33 // If we were partway through decoding something else then we missed it.
36 self.state
= State
::RxPacket(RxPacketState
{
43 self.state
= State
::RxStream(RxStreamState
{ lsf
, index
: 0 });
47 Frame
::Packet(packet
) => {
48 match &mut self.state
{
49 State
::RxPacket(ref mut rx
) => {
50 match packet
.counter
{
51 PacketFrameCounter
::Frame
{ index
} => {
52 if index
== rx
.count
&& index
< 32 {
53 let start
= 25 * index
;
54 rx
.packet
[start
..(start
+ 25)].copy_from_slice(&packet
.payload
);
57 // unexpected order - something has gone wrong
58 self.state
= State
::Idle
;
61 PacketFrameCounter
::FinalFrame
{ payload_len
} => {
62 let start
= 25 * rx
.count
;
63 let end
= start
+ payload_len
;
64 rx
.packet
[start
..(start
+ payload_len
)]
65 .copy_from_slice(&packet
.payload
);
67 KissFrame
::new_full_packet(&rx
.lsf
.0, &rx
.packet
[0..end
])
69 self.kiss_to_host(kiss
);
70 self.state
= State
::Idle
;
76 self.state
= State
::Idle
;
80 Frame
::Stream(stream
) => {
81 match &mut self.state
{
82 State
::RxStream(ref mut rx
) => {
83 // TODO: consider wraparound from 0x7fff
84 if stream
.frame
_n
umber
< rx
.index
{
85 let mut lich
= LichCollection
::new();
86 lich
.set_segment(stream
.lich_idx
, stream
.lich_part
);
87 self.state
= State
::RxAcquiringStream(RxAcquiringStreamState
{ lich
});
89 rx
.index
= stream
.frame
_n
umber
+ 1;
90 let kiss
= KissFrame
::new_stream_data(&stream
.stream_data
).unwrap
();
91 self.kiss_to_host(kiss
);
92 // TODO: handle LICH contents to track META content
93 // TODO: end stream if LICH updates indicate non-META part has changed
94 // (this implies a new station)
95 if stream
.end_of_stream
{
96 self.state
= State
::Idle
;
100 State
::RxAcquiringStream(ref mut rx
) => {
101 rx
.lich
.set_segment(stream
.lich_idx
, stream
.lich_part
);
102 if let Some(maybe_lsf
) = rx
.lich
.try_assemble() {
103 let lsf
= LsfFrame(maybe_lsf
);
104 // LICH can change mid-transmission so wait until the CRC is correct
105 // to ensure (to high probability) we haven't done a "torn read"
107 let kiss
= KissFrame
::new_stream_setup(&lsf
.0).unwrap
();
108 self.kiss_to_host(kiss
);
109 // TODO: avoid discarding the first data payload here
110 // need a queue depth of 2 for outgoing kiss
111 self.state
= State
::RxStream(RxStreamState
{
113 index
: stream
.frame
_n
umber
+ 1,
119 // If coming from another state, we have missed something.
120 // Never mind, let's start tracking LICH.
121 let mut lich
= LichCollection
::new();
122 lich
.set_segment(stream
.lich_idx
, stream
.lich_part
);
123 self.state
= State
::RxAcquiringStream(RxAcquiringStreamState
{ lich
})
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) {}
134 pub fn set_data_carrier_detect(&mut self, _dcd
: bool
) {}
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
142 /// Read KISS message to be sent to host.
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]) -> Result
<usize, SoftTncError
> {
147 match self.outgoing_kiss
.as_mut() {
149 let n
= (outgoing
.kiss_frame
.len
- outgoing
.sent
).min(target_buf
.len());
151 .copy_from_slice(&outgoing
.kiss_frame
.data
[outgoing
.sent
..(outgoing
.sent
+ n
)]);
153 if outgoing
.sent
== outgoing
.kiss_frame
.len
{
154 self.outgoing_kiss
= None
;
162 pub fn write_kiss(&mut self, buf
: &[u8]) -> Result
<usize, SoftTncError
> {
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
173 fn kiss_to_host(&mut self, kiss_frame
: KissFrame
) {
174 self.outgoing_kiss
= Some(OutgoingKiss
{
182 pub enum SoftTncError
{
183 General(&'
static str),
187 struct OutgoingKiss
{
188 kiss_frame
: KissFrame
,
193 /// Nothing happening.
196 /// We received some stream data but missed the leading LSF so we are trying to assemble from LICH.
197 RxAcquiringStream(RxAcquiringStreamState
),
199 /// We have acquired an identified stream transmission and are sending data payloads to the host.
200 RxStream(RxStreamState
),
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
),
207 struct RxAcquiringStreamState
{
208 /// Partial assembly of LSF by accumulating LICH fields.
209 lich
: LichCollection
,
212 struct RxStreamState
{
213 /// Track identifying information for this transmission so we can tell if it changes.
216 /// Expected next frame number. Allowed to skip values on RX, but not go backwards.
220 struct RxPacketState
{
224 /// Accumulation of packet data that we have received so far.
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.