use crate::kiss::{KissBuffer, KissFrame};
-use crate::protocol::{Frame, LichCollection, LsfFrame};
+use crate::protocol::{Frame, LichCollection, LsfFrame, Mode, PacketFrameCounter};
/// Handles the KISS protocol and frame management for `SoftModulator` and `SoftDemodulator`.
///
}
/// Process an individual `Frame` that has been decoded by the modem.
- pub fn handle_frame(&mut self, _frame: Frame) -> Result<(), SoftTncError> {
+ pub fn handle_frame(&mut self, frame: Frame) -> Result<(), SoftTncError> {
+ match frame {
+ Frame::Lsf(lsf) => {
+ // A new LSF implies a clean slate.
+ // If we were partway through decoding something else then we missed it.
+ match lsf.mode() {
+ Mode::Packet => {
+ self.state = State::RxPacket(RxPacketState {
+ lsf,
+ packet: [0u8; 825],
+ count: 0,
+ })
+ }
+ Mode::Stream => {
+ self.state = State::RxStream(RxStreamState { lsf, index: 0 });
+ }
+ }
+ }
+ Frame::Packet(packet) => {
+ match &mut self.state {
+ State::RxPacket(ref mut rx) => {
+ match packet.counter {
+ PacketFrameCounter::Frame { index } => {
+ if index == rx.count && index < 32 {
+ let start = 25 * index;
+ rx.packet[start..(start + 25)].copy_from_slice(&packet.payload);
+ rx.count += 1;
+ } else {
+ // unexpected order - something has gone wrong
+ self.state = State::Idle;
+ }
+ }
+ PacketFrameCounter::FinalFrame { payload_len } => {
+ let start = 25 * rx.count;
+ let end = start + payload_len;
+ rx.packet[start..(start + payload_len)]
+ .copy_from_slice(&packet.payload);
+ let kiss =
+ KissFrame::new_full_packet(&rx.lsf.0, &rx.packet[0..end])
+ .unwrap();
+ self.kiss_to_host(kiss);
+ self.state = State::Idle;
+ }
+ }
+ }
+ _ => {
+ // Invalid transition
+ self.state = State::Idle;
+ }
+ }
+ }
+ Frame::Stream(stream) => {
+ match &mut self.state {
+ State::RxStream(ref mut rx) => {
+ // TODO: consider wraparound from 0x7fff
+ if stream.frame_number < rx.index {
+ let mut lich = LichCollection::new();
+ lich.set_segment(stream.lich_idx, stream.lich_part);
+ self.state = State::RxAcquiringStream(RxAcquiringStreamState { lich });
+ } else {
+ rx.index = stream.frame_number + 1;
+ let kiss = KissFrame::new_stream_data(&stream.stream_data).unwrap();
+ self.kiss_to_host(kiss);
+ // TODO: handle LICH contents to track META content
+ // TODO: end stream if LICH updates indicate non-META part has changed
+ // (this implies a new station)
+ if stream.end_of_stream {
+ self.state = State::Idle;
+ }
+ }
+ }
+ State::RxAcquiringStream(ref mut rx) => {
+ rx.lich.set_segment(stream.lich_idx, stream.lich_part);
+ if let Some(maybe_lsf) = rx.lich.try_assemble() {
+ let lsf = LsfFrame(maybe_lsf);
+ // LICH can change mid-transmission so wait until the CRC is correct
+ // to ensure (to high probability) we haven't done a "torn read"
+ if lsf.crc() == 0 {
+ let kiss = KissFrame::new_stream_setup(&lsf.0).unwrap();
+ self.kiss_to_host(kiss);
+ // TODO: avoid discarding the first data payload here
+ // need a queue depth of 2 for outgoing kiss
+ self.state = State::RxStream(RxStreamState {
+ lsf,
+ index: stream.frame_number + 1,
+ });
+ }
+ }
+ }
+ _ => {
+ // If coming from another state, we have missed something.
+ // Never mind, let's start tracking LICH.
+ let mut lich = LichCollection::new();
+ lich.set_segment(stream.lich_idx, stream.lich_part);
+ self.state = State::RxAcquiringStream(RxAcquiringStreamState { lich })
+ }
+ }
+ }
+ }
Ok(())
}
target_buf[0..n]
.copy_from_slice(&outgoing.kiss_frame.data[outgoing.sent..(outgoing.sent + n)]);
outgoing.sent += n;
+ if outgoing.sent == outgoing.kiss_frame.len {
+ self.outgoing_kiss = None;
+ }
Ok(n)
}
None => Ok(0),
}
Ok(n)
}
+
+ fn kiss_to_host(&mut self, kiss_frame: KissFrame) {
+ self.outgoing_kiss = Some(OutgoingKiss {
+ kiss_frame,
+ sent: 0,
+ });
+ }
}
#[derive(Debug)]
pub enum SoftTncError {
General(&'static str),
+ InvalidState,
}
struct OutgoingKiss {
struct RxStreamState {
/// Track identifying information for this transmission so we can tell if it changes.
lsf: LsfFrame,
+
+ /// Expected next frame number. Allowed to skip values on RX, but not go backwards.
+ index: u16,
}
struct RxPacketState {
+ /// Initial LSF
+ lsf: LsfFrame,
+
/// Accumulation of packet data that we have received so far.
packet: [u8; 825],
- /// Number of frames we have received. If we are stably in the RxPacket state,
- /// this will be between 1 and 32 inclusive. The first frame gets us into the
- /// rx state, and the maximum 33rd frame must end the transmission and state.
+ /// Number of payload frames we have received. If we are stably in the RxPacket state,
+ /// this will be between 0 and 32 inclusive.
count: usize,
}