mod block4k;
mod block512;
pub use block4k::*;
pub use block512::*;
pub const WIDE_BUS_WIDTH: usize = 4;
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DataLine {
Dat0 = 0,
Dat1 = 1,
Dat2 = 2,
Dat3 = 3,
}
impl DataLine {
pub const fn new() -> DataLine {
DataLine::Dat0
}
}
impl Default for DataLine {
fn default() -> Self {
Self::new()
}
}
#[inline(always)]
pub const fn wide_bus_encode(b: u8, byte_idx: usize, dat: DataLine) -> u8 {
let off_lo = dat as usize;
let off_hi = 4 + off_lo;
wide_bus_shift(
(b & (1 << off_hi)) | ((b & (1 << off_lo)) << 3),
byte_idx,
dat,
)
}
#[inline(always)]
pub const fn wide_bus_decode(b: u8, byte_idx: usize, dat: DataLine) -> u8 {
let c = b >> (6 - ((byte_idx % 4) * 2));
let shift_lo = dat as usize;
let shift_hi = 3 + shift_lo;
((c & 0b10) << shift_hi) | ((c & 1) << shift_lo)
}
#[inline(always)]
const fn wide_bus_shift(b: u8, byte_idx: usize, dat: DataLine) -> u8 {
match dat {
DataLine::Dat0 => match byte_idx % 4 {
0 => b << 3,
1 => b << 1,
2 => b >> 1,
_ => b >> 3,
},
DataLine::Dat1 => match byte_idx % 4 {
0 => b << 2,
1 => b,
2 => b >> 2,
_ => b >> 4,
},
DataLine::Dat2 => match byte_idx % 4 {
0 => b << 1,
1 => b >> 1,
2 => b >> 3,
_ => b >> 5,
},
DataLine::Dat3 => b >> ((byte_idx % 4) * 2),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_wide_encode() {
let b = [0b1010_1010, 0b0101_0101, 0b1100_1100, 0b0011_0011];
let exp_dat0 = 0b00_11_00_11;
let exp_dat1 = 0b11_00_00_11;
let exp_dat2 = 0b00_11_11_00;
let exp_dat3 = 0b11_00_11_00;
let [dat0, dat1, dat2, dat3] = b
.iter()
.enumerate()
.fold(0u32, |mut acc, (i, &c)| {
acc |= wide_bus_encode(c, i, DataLine::Dat0) as u32;
acc |= (wide_bus_encode(c, i, DataLine::Dat1) as u32) << 8;
acc |= (wide_bus_encode(c, i, DataLine::Dat2) as u32) << 16;
acc | ((wide_bus_encode(c, i, DataLine::Dat3) as u32) << 24)
})
.to_le_bytes();
assert_eq!(dat0, exp_dat0);
assert_eq!(dat1, exp_dat1);
assert_eq!(dat2, exp_dat2);
assert_eq!(dat3, exp_dat3);
let wide_data = [dat0, dat1, dat2, dat3];
let mut data = [0; 4];
data.iter_mut().enumerate().for_each(|(i, b)| {
let j = i.saturating_div(WIDE_BUS_WIDTH);
*b |= wide_bus_decode(wide_data[j], i, DataLine::Dat0);
*b |= wide_bus_decode(wide_data[j + 1], i, DataLine::Dat1);
*b |= wide_bus_decode(wide_data[j + 2], i, DataLine::Dat2);
*b |= wide_bus_decode(wide_data[j + 3], i, DataLine::Dat3);
});
assert_eq!(data, b);
}
}