Files
trx-rs/src/decoders/trx-ftx/src/common/protocol.rs
T
sjg ba48de2d30
Sync docs to Wiki / wiki (push) Has been cancelled
Initial commit
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-05-17 23:25:14 +02:00

185 lines
4.5 KiB
Rust

// SPDX-FileCopyrightText: 2026 Stan Grams <sjg@haxx.space>
//
// SPDX-License-Identifier: GPL-2.0-or-later
/// FTx protocol variants.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FtxProtocol {
Ft4,
Ft8,
#[cfg(feature = "ft2")]
Ft2,
}
impl FtxProtocol {
/// Symbol period in seconds.
pub fn symbol_period(self) -> f32 {
match self {
Self::Ft8 => FT8_SYMBOL_PERIOD,
Self::Ft4 => FT4_SYMBOL_PERIOD,
#[cfg(feature = "ft2")]
Self::Ft2 => FT2_SYMBOL_PERIOD,
}
}
/// Slot time in seconds.
pub fn slot_time(self) -> f32 {
match self {
Self::Ft8 => FT8_SLOT_TIME,
Self::Ft4 => FT4_SLOT_TIME,
#[cfg(feature = "ft2")]
Self::Ft2 => FT2_SLOT_TIME,
}
}
/// Whether this protocol uses FT4-style channel layout (FT4 and FT2).
pub fn uses_ft4_layout(self) -> bool {
#[cfg(feature = "ft2")]
if matches!(self, Self::Ft2) {
return true;
}
matches!(self, Self::Ft4)
}
/// Number of data symbols.
pub fn nd(self) -> usize {
if self.uses_ft4_layout() {
FT4_ND
} else {
FT8_ND
}
}
/// Total channel symbols.
pub fn nn(self) -> usize {
if self.uses_ft4_layout() {
FT4_NN
} else {
FT8_NN
}
}
/// Length of each sync group.
pub fn sync_length(self) -> usize {
if self.uses_ft4_layout() {
FT4_LENGTH_SYNC
} else {
FT8_LENGTH_SYNC
}
}
/// Number of sync groups.
pub fn num_sync(self) -> usize {
if self.uses_ft4_layout() {
FT4_NUM_SYNC
} else {
FT8_NUM_SYNC
}
}
/// Offset between sync groups.
pub fn sync_offset(self) -> usize {
if self.uses_ft4_layout() {
FT4_SYNC_OFFSET
} else {
FT8_SYNC_OFFSET
}
}
/// Number of FSK tones.
pub fn num_tones(self) -> usize {
if self.uses_ft4_layout() {
4
} else {
8
}
}
}
// FT8 timing
pub const FT8_SYMBOL_PERIOD: f32 = 0.160;
pub const FT8_SLOT_TIME: f32 = 15.0;
// FT4 timing
pub const FT4_SYMBOL_PERIOD: f32 = 0.048;
pub const FT4_SLOT_TIME: f32 = 7.5;
// FT2 timing
#[cfg(feature = "ft2")]
pub const FT2_SYMBOL_PERIOD: f32 = 0.024;
#[cfg(feature = "ft2")]
pub const FT2_SLOT_TIME: f32 = 3.75;
// FT8 symbol counts
pub const FT8_ND: usize = 58;
pub const FT8_NN: usize = 79;
pub const FT8_LENGTH_SYNC: usize = 7;
pub const FT8_NUM_SYNC: usize = 3;
pub const FT8_SYNC_OFFSET: usize = 36;
// FT4 symbol counts
pub const FT4_ND: usize = 87;
pub const FT4_NR: usize = 2;
pub const FT4_NN: usize = 105;
pub const FT4_LENGTH_SYNC: usize = 4;
pub const FT4_NUM_SYNC: usize = 4;
pub const FT4_SYNC_OFFSET: usize = 33;
// FT2 reuses FT4 layout
#[cfg(feature = "ft2")]
pub const FT2_ND: usize = FT4_ND;
#[cfg(feature = "ft2")]
pub const FT2_NR: usize = FT4_NR;
#[cfg(feature = "ft2")]
pub const FT2_NN: usize = FT4_NN;
#[cfg(feature = "ft2")]
pub const FT2_LENGTH_SYNC: usize = FT4_LENGTH_SYNC;
#[cfg(feature = "ft2")]
pub const FT2_NUM_SYNC: usize = FT4_NUM_SYNC;
#[cfg(feature = "ft2")]
pub const FT2_SYNC_OFFSET: usize = FT4_SYNC_OFFSET;
// LDPC parameters
pub const FTX_LDPC_N: usize = 174;
pub const FTX_LDPC_K: usize = 91;
pub const FTX_LDPC_M: usize = 83;
pub const FTX_LDPC_N_BYTES: usize = FTX_LDPC_N.div_ceil(8);
pub const FTX_LDPC_K_BYTES: usize = FTX_LDPC_K.div_ceil(8);
// CRC parameters
pub const FT8_CRC_POLYNOMIAL: u16 = 0x2757;
pub const FT8_CRC_WIDTH: u32 = 14;
// Message parameters
pub const FTX_PAYLOAD_LENGTH_BYTES: usize = 10;
pub const FTX_MAX_MESSAGE_LENGTH: usize = 35;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn protocol_timing() {
assert!((FtxProtocol::Ft8.symbol_period() - 0.160).abs() < 1e-6);
assert!((FtxProtocol::Ft4.symbol_period() - 0.048).abs() < 1e-6);
#[cfg(feature = "ft2")]
assert!((FtxProtocol::Ft2.symbol_period() - 0.024).abs() < 1e-6);
}
#[test]
fn ft4_layout() {
assert!(FtxProtocol::Ft4.uses_ft4_layout());
#[cfg(feature = "ft2")]
assert!(FtxProtocol::Ft2.uses_ft4_layout());
assert!(!FtxProtocol::Ft8.uses_ft4_layout());
}
#[test]
fn symbol_counts() {
assert_eq!(FtxProtocol::Ft8.nn(), 79);
assert_eq!(FtxProtocol::Ft4.nn(), 105);
#[cfg(feature = "ft2")]
assert_eq!(FtxProtocol::Ft2.nn(), 105);
}
}