#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PnScrambler {
taps: u32,
width: u32,
seed: u32,
}
impl PnScrambler {
pub fn new(taps: u32, width: u32, seed: u32) -> Self {
assert!((2..=32).contains(&width), "LFSR width must be in 2..=32");
let mask = Self::mask_for(width);
assert!(seed != 0, "LFSR seed must be nonzero");
assert!(seed & !mask == 0, "LFSR seed must fit in `width` bits");
assert!(taps & !mask == 0, "LFSR taps must fit in `width` bits");
Self { taps, width, seed }
}
#[inline]
fn mask_for(width: u32) -> u32 {
if width == 32 {
u32::MAX
} else {
(1u32 << width) - 1
}
}
pub fn scramble(&self, data: &mut [u8]) {
let mask = Self::mask_for(self.width);
let top = self.width - 1;
let mut reg = self.seed & mask;
for byte in data.iter_mut() {
*byte = scramble_byte(*byte, &mut reg, self.taps, top, mask);
}
}
pub fn taps(&self) -> u32 {
self.taps
}
pub fn width(&self) -> u32 {
self.width
}
pub fn seed(&self) -> u32 {
self.seed
}
pub fn into_stream(self) -> PnScramblerStream {
PnScramblerStream::new(self.taps, self.width, self.seed)
}
}
#[inline]
fn scramble_byte(byte: u8, reg: &mut u32, taps: u32, top: u32, mask: u32) -> u8 {
let mut out = 0u8;
for bit in 0..8 {
let pn = (*reg & 1) as u8;
out |= (((byte >> bit) & 1) ^ pn) << bit;
let fb = (*reg & taps).count_ones() & 1;
*reg = ((*reg >> 1) | (fb << top)) & mask;
}
out
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PnScramblerStream {
taps: u32,
width: u32,
seed: u32,
mask: u32,
top: u32,
reg: u32,
}
impl PnScramblerStream {
pub fn new(taps: u32, width: u32, seed: u32) -> Self {
assert!((2..=32).contains(&width), "LFSR width must be in 2..=32");
let mask = PnScrambler::mask_for(width);
assert!(seed != 0, "LFSR seed must be nonzero");
assert!(seed & !mask == 0, "LFSR seed must fit in `width` bits");
assert!(taps & !mask == 0, "LFSR taps must fit in `width` bits");
Self {
taps,
width,
seed,
mask,
top: width - 1,
reg: seed & mask,
}
}
pub fn reset(&mut self) {
self.reg = self.seed & self.mask;
}
pub fn taps(&self) -> u32 {
self.taps
}
pub fn width(&self) -> u32 {
self.width
}
pub fn seed(&self) -> u32 {
self.seed
}
pub fn feed(&mut self, data: &[u8]) -> Vec<u8> {
data.iter()
.map(|&b| scramble_byte(b, &mut self.reg, self.taps, self.top, self.mask))
.collect()
}
pub fn feed_in_place(&mut self, data: &mut [u8]) {
for byte in data.iter_mut() {
*byte = scramble_byte(*byte, &mut self.reg, self.taps, self.top, self.mask);
}
}
}