Newer
Older
use labrador_ldpc::decoder::DecodeFrom;
const START_STATE: u16 = 0xE9CF;
for d in data.iter_mut() {
let b;
(b, state) = lfsr_byte(state);
*d ^= b;
}
}
// One bit per element
pub(crate) fn whiten_soft<T: DecodeFrom>(data: &mut [T]) {
let mut state = START_STATE;
for d in data.iter_mut() {
let b = state & 1;
if b > 0 {
// flip the soft bit. In LLR speak, this just means flip the sign
*d = -*d;
}
state = lfsr(state);
}
}
// (byte, state)
fn lfsr_byte(mut state: u16) -> (u8, u16) {
let mut out = 0;
for i in (0..8).rev() {
out |= u8::try_from(state & 1).unwrap() << i;
state = lfsr(state);
}
(out, state)
}
// https://en.wikipedia.org/wiki/Linear-feedback_shift_register#Galois_LFSRs
fn lfsr(mut state: u16) -> u16 {
let lsb = state & 1;
state >>= 1;
if lsb > 0 {
state ^= 0xB400; // apply toggle mask
let mut data = [0; 64];
data[0..57]
.clone_from_slice(&b"Hello world! The quick brown fox jumped over the lazy dog"[..]);
whiten(&mut data);
assert_ne!(orig, data);
whiten(&mut data);
assert_eq!(orig, data);
}
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#[test]
fn basic_soft() {
let mut data = [-2.3, 4.7, 0.0, 2.7, 7.8, 45.2, -0.1, -0.82];
let orig = data;
whiten_soft(&mut data);
assert_eq!([2.3, -4.7, -0.0, -2.7, 7.8, 45.2, 0.1, 0.82], data);
whiten_soft(&mut data);
assert_eq!(orig, data);
}
#[test]
fn compare_soft_and_hard() {
let mut data = [0; 64];
data[0..57]
.clone_from_slice(&b"Hello world! The quick brown fox jumped over the lazy dog"[..]);
let orig = data;
whiten(&mut data);
let mut soft = [0.0; 64 * 8];
for (i, b) in data.iter().enumerate() {
for j in 0..8 {
soft[8 * i + j] = f32::from_hard_bit(b & (1 << (7 - j)) > 0);
}
}
whiten_soft(&mut soft);
assert_eq!(orig.len() * 8, soft.len());
for (i, b) in orig.iter().enumerate() {
for j in 0..8 {
assert_eq!(soft[8 * i + j].hard_bit(), *b & (1 << (7 - j)) > 0);
}
}
}
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#[test]
fn test_lfsr() {
let start = 0xACE1;
let end_expected = 0xE270;
let state = lfsr(start);
assert_eq!(end_expected, state);
}
#[test]
fn test_lfsr_byte() {
let start = 0xE9CF;
let (out, state) = lfsr_byte(start);
assert_eq!(0xF3, out);
assert_eq!(0xE3B1, state);
}
#[test]
fn test_doc_example() {
let start = 0xE9CF;
let expected_out = [
0xF3, 0x8D, 0xD0, 0x6E, 0x1F, 0x65, 0x75, 0x75, 0xA5, 0xBA, 0xA9, 0xD0, 0x7A, 0x1D,
0x1, 0x21,
];
let mut actual_out = [0; 16];
let mut state = start;
}
assert_eq!(expected_out, actual_out);
}
#[test]
fn test_doc_example_through_whitener() {
let expected_out = [
0xF3, 0x8D, 0xD0, 0x6E, 0x1F, 0x65, 0x75, 0x75, 0xA5, 0xBA, 0xA9, 0xD0, 0x7A, 0x1D,
0x1, 0x21,
];
let mut actual_out = [0; 16];
whiten(&mut actual_out);
assert_eq!(expected_out, actual_out);
}