Forked from
CATS / ham-cats
53 commits behind the upstream repository.
ldpc.rs 4.00 KiB
use arrayvec::ArrayVec;
use labrador_ldpc::LDPCCode;
use crate::error::EncodeError;
macro_rules! enc_chunk {
($d:ident, $i:ident, $t:ident, $n:literal) => {
::paste::paste! {
let mut codeword = [0; $n * 2];
codeword[0..$n].copy_from_slice(&$d[$i..($i + $n)]);
labrador_ldpc::LDPCCode::[<$t>].encode(&mut codeword);
$d.try_extend_from_slice(&codeword[$n..])
.map_err(|_| EncodeError::CatsOverflow)?;
$i += $n;
}
};
}
// On failure this still modifies the data array!
pub(crate) fn encode<const N: usize>(data: &mut ArrayVec<u8, N>) -> Result<(), EncodeError> {
let mut i = 0;
let n = data.len();
loop {
match n - i {
512.. => {
enc_chunk!(data, i, TM8192, 512);
}
128.. => {
enc_chunk!(data, i, TM2048, 128);
}
32.. => {
enc_chunk!(data, i, TC512, 32);
}
16.. => {
enc_chunk!(data, i, TC256, 16);
}
8.. => {
enc_chunk!(data, i, TC128, 8);
}
0 => break,
_ => {
let mut codeword = [0xAA; 16];
codeword[0..(n - i)].copy_from_slice(&data[i..n]);
LDPCCode::TC128.encode(&mut codeword);
data.try_extend_from_slice(&codeword[8..])
.map_err(|_| EncodeError::CatsOverflow)?;
i = n;
}
}
}
data.try_extend_from_slice(&u16::try_from(n).unwrap().to_le_bytes())
.map_err(|_| EncodeError::CatsOverflow)?;
Ok(())
}
pub(crate) fn decode<const N: usize>(data: &mut ArrayVec<u8, N>) -> Option<()> {
if data.len() < 2 {
return None;
}
let len = [data[data.len() - 2], data[data.len() - 1]];
let len = u16::from_le_bytes(len).into();
let (data, parity) = data.split_at_mut(len);
let parity = parity.get(0..parity.len().checked_sub(2)?)?;
let mut di = 0;
let mut pi = 0;
let working = todo!();
loop {
match data.len() - di {
512.. => {}
128.. => {}
32.. => {}
16.. => {}
8.. => {}
0.. => {}
_ => {}
}
}
Some(())
}
#[cfg(test)]
mod tests {
use super::*;
use arrayvec::ArrayVec;
#[test]
fn len_test() {
// from the example in the docs
let mut data: ArrayVec<u8, 8191> = ArrayVec::new();
for _ in 0..41 {
data.extend(
b"Example packet data wueirpqwerwrywqoeiruy29346129384761"
.iter()
.cloned(),
);
}
data.extend(
b"Example packet data wueirpqwerwrywqoeiru346129384761"
.iter()
.cloned(),
);
assert_eq!(2349, data.len());
encode(&mut data).unwrap();
assert_eq!(4703, data.len());
}
#[test]
fn basic_encode_decode() {
let mut data: ArrayVec<u8, 8191> = ArrayVec::new();
for _ in 0..50 {
data.extend(
b"This is a test packet. jsalksjd093809324JASLD:LKD*#$)(*#@)"
.iter()
.cloned(),
);
}
let orig = data.clone();
encode(&mut data).unwrap();
assert_ne!(orig, data);
decode(&mut data).unwrap();
assert_eq!(orig, data);
}
#[test]
fn encode_decode_with_bit_flips() {
let mut data: ArrayVec<u8, 8191> = ArrayVec::new();
for _ in 0..50 {
data.extend(
b"jsalksjd093809324JASLD:LKD*#$)(*#@) Another test packet"
.iter()
.cloned(),
);
}
let orig = data.clone();
encode(&mut data).unwrap();
assert_ne!(orig, data);
data[234] ^= 0x55;
data[0] ^= 0xAA;
data[999] ^= 0x43;
decode(&mut data).unwrap();
assert_eq!(orig, data);
}
}