use super::field::{FieldLogarithm, FieldOperation};
pub const CCSDS_PRIMITIVE_POLYNOMIAL: FieldOperation = 0x187;
pub const CCSDS_FIRST_CONSECUTIVE_ROOT: FieldLogarithm = 112;
pub const CCSDS_GENERATOR_ROOT_GAP: FieldLogarithm = 11;
pub const CCSDS_NUM_ROOTS: usize = 32;
const T_ALPHA: [[u8; 8]; 8] = [
[1, 0, 0, 0, 1, 1, 0, 1],
[1, 1, 1, 0, 1, 1, 1, 1],
[1, 1, 1, 0, 1, 1, 0, 0],
[1, 0, 0, 0, 0, 1, 1, 0],
[1, 1, 1, 1, 1, 0, 1, 0],
[1, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 0, 1, 1],
];
const fn conv_to_dual_byte(x: u8) -> u8 {
let mut z = [0u8; 8];
let mut r = 0;
while r < 8 {
if (x >> (7 - r)) & 1 == 1 {
let mut c = 0;
while c < 8 {
z[c] ^= T_ALPHA[r][c];
c += 1;
}
}
r += 1;
}
let mut out = 0u8;
let mut c = 0;
while c < 8 {
if z[c] == 1 {
out |= 1 << (7 - c);
}
c += 1;
}
out
}
const fn build_conv_to_dual() -> [u8; 256] {
let mut t = [0u8; 256];
let mut i = 0;
while i < 256 {
t[i] = conv_to_dual_byte(i as u8);
i += 1;
}
t
}
const fn build_dual_to_conv(fwd: &[u8; 256]) -> [u8; 256] {
let mut t = [0u8; 256];
let mut i = 0;
while i < 256 {
t[fwd[i] as usize] = i as u8;
i += 1;
}
t
}
pub const CONV_TO_DUAL: [u8; 256] = build_conv_to_dual();
pub const DUAL_TO_CONV: [u8; 256] = build_dual_to_conv(&CONV_TO_DUAL);
#[inline]
pub fn conv_to_dual(byte: u8) -> u8 {
CONV_TO_DUAL[byte as usize]
}
#[inline]
pub fn dual_to_conv(byte: u8) -> u8 {
DUAL_TO_CONV[byte as usize]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tables_are_inverses() {
for i in 0..256usize {
assert_eq!(DUAL_TO_CONV[CONV_TO_DUAL[i] as usize], i as u8);
assert_eq!(CONV_TO_DUAL[DUAL_TO_CONV[i] as usize], i as u8);
}
}
#[test]
fn matches_ccsds_table_d1_anchors() {
assert_eq!(CONV_TO_DUAL[0x00], 0x00);
assert_eq!(CONV_TO_DUAL[0x01], 0x7b); assert_eq!(CONV_TO_DUAL[0x02], 0xaf); assert_eq!(CONV_TO_DUAL[0x04], 0x99); assert_eq!(CONV_TO_DUAL[0x80], 0x8d); assert_eq!(CONV_TO_DUAL[0xc3], 0xb6); }
}