use crate::codec::varicode::{varicode_encode, VaricodeEncoder, VaricodeDecoder};
use crate::codec::psk31_conv::{conv_encode, viterbi_decode_hard};
use crate::modulate::psk31::{psk31_sps, PSK31_BAUD, PSK31_SPS_8000, PSK31_SPS_12000};
#[test]
fn varicode_encode_space() {
let (cw, len) = varicode_encode(b' ');
assert_eq!(len, 1);
assert_eq!(cw, 1);
}
#[test]
fn varicode_decode_roundtrip() {
use crate::codec::varicode::varicode_encode as enc;
use crate::codec::varicode::varicode_decode as dec;
for b in 32u8..127u8 {
let (cw, len) = enc(b);
let decoded = dec(cw, len);
assert!(decoded.is_some(), "no decode for byte {}", b);
let d = decoded.unwrap();
let (cw2, len2) = enc(d);
assert_eq!((cw2, len2), (cw, len),
"codeword mismatch: byte {} encoded to ({},{}) but decoded as byte {} \
which encodes to ({},{})", b, cw, len, d, cw2, len2);
}
}
#[test]
fn varicode_encoder_stream_cq() {
let mut enc = VaricodeEncoder::new();
enc.push_preamble(4);
enc.push_byte(b'C');
enc.push_byte(b'Q');
let bits = enc.drain_bits();
assert_eq!(&bits[..4], &[0, 0, 0, 0]);
let (c_cw, c_len) = varicode_encode(b'C');
let c_bits: Vec<u8> = (0..c_len).rev().map(|i| ((c_cw >> i) & 1) as u8).collect();
assert_eq!(&bits[4..4 + c_len as usize], c_bits.as_slice());
let gap_start = 4 + c_len as usize;
assert_eq!(bits[gap_start], 0);
assert_eq!(bits[gap_start + 1], 0);
let (q_cw, q_len) = varicode_encode(b'Q');
let q_bits: Vec<u8> = (0..q_len).rev().map(|i| ((q_cw >> i) & 1) as u8).collect();
assert_eq!(&bits[gap_start + 2..gap_start + 2 + q_len as usize], q_bits.as_slice());
}
#[test]
fn varicode_decoder_boundary() {
let (cw, len) = varicode_encode(b'C');
let mut dec = VaricodeDecoder::new();
for i in (0..len).rev() {
dec.push_bit(((cw >> i) & 1) as u8);
}
assert_eq!(dec.pop_char(), None); dec.push_bit(0);
dec.push_bit(0); assert_eq!(dec.pop_char(), Some(b'C'));
}
#[test]
fn psk31_sps_8000() {
assert_eq!(psk31_sps(8000.0), PSK31_SPS_8000);
}
#[test]
fn psk31_sps_12000() {
assert_eq!(psk31_sps(12000.0), PSK31_SPS_12000);
}
#[test]
fn psk31_hann_endpoints() {
let sps = psk31_sps(8000.0);
assert_eq!(sps, 256);
let denom = (sps - 1) as f32;
let h0 = 0.5 - 0.5 * (std::f32::consts::PI * 0.0 / denom).cos();
let hn = 0.5 - 0.5 * (std::f32::consts::PI * denom / denom).cos();
assert!(h0.abs() < 1e-4, "hann[0] = {}", h0);
assert!((hn - 1.0).abs() < 1e-4, "hann[sps-1] = {}", hn);
}
#[test]
fn bpsk31_decider_sign() {
use crate::demodulate::psk31::Bpsk31Decider;
use crate::core::Block;
let soft = [1.0f32, -1.0, 2.5, -0.5];
let mut out = [0u8; 4];
Bpsk31Decider::new().process(&soft, &mut out);
assert_eq!(out, [1, 0, 1, 0]);
}
#[test]
fn conv_encode_known() {
let input = vec![1u8, 0u8];
let encoded = conv_encode(&input);
assert_eq!(encoded.len(), 4);
assert_eq!(encoded[0], 1); assert_eq!(encoded[1], 1); assert_eq!(encoded[2], 0); assert_eq!(encoded[3], 0); }
#[test]
fn viterbi_decode_noiseless() {
let input: Vec<u8> = (0..32).map(|i| (i & 1) as u8).collect();
let encoded = conv_encode(&input);
let recovered = viterbi_decode_hard(&encoded);
assert_eq!(recovered.len(), input.len());
for i in 0..input.len() {
assert_eq!(recovered[i], input[i], "bit {} mismatch", i);
}
}
#[test]
fn qpsk31_modulate_preamble() {
use crate::modulate::psk31::Qpsk31Mod;
let mut mod_ = Qpsk31Mod::new(8000.0, 0.0, 1.0);
let iq = mod_.modulate_bits(&[0u8; 16]);
let sps = psk31_sps(8000.0);
assert_eq!(iq.len(), 16 * sps);
let power: f32 = iq.iter().map(|s| s.re * s.re + s.im * s.im).sum::<f32>() / iq.len() as f32;
assert!(power > 0.01, "expected non-zero power, got {}", power);
}
#[test]
fn psk31_baud_constant() {
assert!((PSK31_BAUD - 31.25).abs() < 1e-6);
}