From: Thomas Karpiniec Date: Mon, 6 Jan 2025 10:14:16 +0000 (+1100) Subject: Modem support for parsing packet frames X-Git-Url: https://code.octet-stream.net/m17rt/commitdiff_plain/bd5155840661f90aab8c06413fb1e9f256824b55 Modem support for parsing packet frames --- diff --git a/m17app/src/adapter.rs b/m17app/src/adapter.rs index 5fb6258..a03cf09 100644 --- a/m17app/src/adapter.rs +++ b/m17app/src/adapter.rs @@ -23,4 +23,6 @@ pub trait StreamAdapter: Send + Sync + 'static { // fn stream_assembled_text_block() // fn stream_gnss_data() // fn stream_extended_callsign_data() + + // fn stream_tx_ended_early(&self); // underrun/overrun } diff --git a/m17app/src/tnc.rs b/m17app/src/tnc.rs index 921585b..e7799b4 100644 --- a/m17app/src/tnc.rs +++ b/m17app/src/tnc.rs @@ -6,8 +6,20 @@ use std::io::{Read, Write}; /// via a working implementation of try_clone(). We do not require `Clone` directly /// as this could not be fulfilled by `TcpStream`. pub trait Tnc: Read + Write + Sized + Send + 'static { + /// Return a copy of this TNC. + /// + /// `M17App` will use this to create a second instance of the supplied TNC then use + /// one of them for reading and one of them for writing, concurrently across two threads. + /// + /// Implementations do not need to worry about trying to make two simultaneous reads or + /// two simultaneous writes do something sensible. `M17App` will not do this and it would + /// probably produce garbled KISS messages anyway. fn try_clone(&mut self) -> Result; + + /// Start I/O. fn start(&mut self) -> Result<(), TncError>; + + /// Shut down I/O - it is assumed we cannot restart. fn close(&mut self) -> Result<(), TncError>; } diff --git a/m17core/src/decode.rs b/m17core/src/decode.rs index 60c210e..ba21a27 100755 --- a/m17core/src/decode.rs +++ b/m17core/src/decode.rs @@ -1,8 +1,11 @@ use crate::{ bits::BitsMut, - fec::{self, p_1, p_2}, + fec::{self, p_1, p_2, p_3}, interleave::interleave, - protocol::{LsfFrame, StreamFrame, BERT_SYNC, LSF_SYNC, PACKET_SYNC, STREAM_SYNC}, + protocol::{ + LsfFrame, PacketFrame, PacketFrameCounter, StreamFrame, BERT_SYNC, LSF_SYNC, PACKET_SYNC, + STREAM_SYNC, + }, random::random_xor, }; use log::debug; @@ -141,3 +144,26 @@ pub(crate) fn parse_stream(frame: &[f32] /* length 192 */) -> Option Option { + let deinterleaved = frame_initial_decode(frame); + let packet = match fec::decode(&deinterleaved, 206, p_3) { + Some(packet) => packet, + None => return None, + }; + let final_frame = (packet[25] & 0x80) > 0; + let number = (packet[25] >> 2) & 0x01f; + let counter = if final_frame { + PacketFrameCounter::FinalFrame { + payload_len: number as usize, + } + } else { + PacketFrameCounter::Frame { + index: number as usize, + } + }; + Some(PacketFrame { + payload: packet[0..25].try_into().unwrap(), + counter, + }) +} diff --git a/m17core/src/fec.rs b/m17core/src/fec.rs index 7538417..0716be0 100755 --- a/m17core/src/fec.rs +++ b/m17core/src/fec.rs @@ -181,6 +181,11 @@ pub(crate) fn p_2(step: usize) -> (bool, bool) { (true, mod6 != 5) } +pub(crate) fn p_3(step: usize) -> (bool, bool) { + let mod4 = step % 4; + (true, mod4 != 3) +} + fn best_previous(table: &[[u8; 32]; 244], step: usize, state: usize) -> u8 { if step == 0 { if state == 0 { diff --git a/m17core/src/modem.rs b/m17core/src/modem.rs index af36ab4..2f92ba9 100644 --- a/m17core/src/modem.rs +++ b/m17core/src/modem.rs @@ -1,4 +1,6 @@ -use crate::decode::{parse_lsf, parse_stream, sync_burst_correlation, SyncBurst, SYNC_THRESHOLD}; +use crate::decode::{ + parse_lsf, parse_packet, parse_stream, sync_burst_correlation, SyncBurst, SYNC_THRESHOLD, +}; use crate::protocol::Frame; use crate::shaping::RRC_48K; use log::debug; @@ -131,7 +133,11 @@ impl Demodulator for SoftDemodulator { } } SyncBurst::Packet => { - debug!("Found PACKET at sample {} diff {}", start_sample, c.diff) + debug!("Found PACKET at sample {} diff {}", start_sample, c.diff); + if let Some(frame) = parse_packet(&pkt_samples) { + self.suppress = 191 * 10; + return Some(Frame::Packet(frame)); + } } } }