use super::Protocol;
pub fn data_chunks<P: Protocol>() -> Vec<(usize, usize)> {
let blocks = P::SYNC_MODE.blocks();
let n_sym = P::N_SYMBOLS as usize;
let mut chunks: Vec<(usize, usize)> = Vec::with_capacity(blocks.len() + 1);
if let Some(first) = blocks.first() {
let pre = first.start_symbol as usize;
if pre > 0 {
chunks.push((0, pre));
}
} else if n_sym > 0 {
chunks.push((0, n_sym));
return chunks;
}
for i in 0..blocks.len().saturating_sub(1) {
let after = blocks[i].start_symbol as usize + blocks[i].pattern.len();
let before_next = blocks[i + 1].start_symbol as usize;
if before_next > after {
chunks.push((after, before_next - after));
}
}
if let Some(last) = blocks.last() {
let after_last = last.start_symbol as usize + last.pattern.len();
if n_sym > after_last {
chunks.push((after_last, n_sym - after_last));
}
}
chunks
}
pub fn codeword_to_itone<P: Protocol>(cw: &[u8]) -> Vec<u8> {
let n_sym = P::N_SYMBOLS as usize;
let bps = P::BITS_PER_SYMBOL as usize;
let gray = P::GRAY_MAP;
let interleave = P::CODEWORD_INTERLEAVE;
let mut itone = vec![0u8; n_sym];
for block in P::SYNC_MODE.blocks() {
let start = block.start_symbol as usize;
for (i, &c) in block.pattern.iter().enumerate() {
itone[start + i] = c;
}
}
let chunks = data_chunks::<P>();
let mut cw_offset = 0usize;
for (start_sym, chunk_len) in chunks {
for k in 0..chunk_len {
let b = cw_offset + k * bps;
let mut v = 0u8;
for j in 0..bps {
let cw_idx = match interleave {
Some(table) => table[b + j] as usize,
None => b + j,
};
v = (v << 1) | (cw[cw_idx] & 1);
}
itone[start_sym + k] = gray[v as usize];
}
cw_offset += chunk_len * bps;
}
itone
}