use crate::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum CsActiveByte {
#[default]
Low = 0,
High = 1,
}
impl CsActiveByte {
pub fn from_byte(byte: u8) -> Result<Self, Error> {
match byte {
0 => Ok(CsActiveByte::Low),
1 => Ok(CsActiveByte::High),
_ => Err(Error::ParseError),
}
}
pub fn to_byte(&self) -> u8 {
*self as u8
}
}
impl From<CsActive> for CsActiveByte {
fn from(cs: CsActive) -> Self {
match cs {
CsActive::Low => CsActiveByte::Low,
CsActive::High => CsActiveByte::High,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
pub enum CsActive {
#[allow(dead_code)]
High,
#[default]
Low,
}
impl core::fmt::Display for CsActive {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
CsActive::High => write!(f, "Active High"),
CsActive::Low => write!(f, "Active Low"),
}
}
}
impl From<CsActiveByte> for CsActive {
fn from(byte: CsActiveByte) -> Self {
match byte {
CsActiveByte::Low => CsActive::Low,
CsActiveByte::High => CsActive::High,
}
}
}
impl CsActive {
fn bit(&self) -> usize {
match self {
CsActive::High => 1,
CsActive::Low => 0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum RomTypeByte {
Type2364 = 0x00,
Type2332 = 0x01,
Type2316 = 0x02,
Type23128 = 0x03,
Type27512 = 0x04,
}
impl RomTypeByte {
pub fn from_byte(byte: u8) -> Result<Self, Error> {
match byte {
0x00 => Ok(RomTypeByte::Type2364),
0x01 => Ok(RomTypeByte::Type2332),
0x02 => Ok(RomTypeByte::Type2316),
0x03 => Ok(RomTypeByte::Type23128),
0x04 => Ok(RomTypeByte::Type27512),
_ => Err(Error::ParseError),
}
}
pub fn to_byte(&self) -> u8 {
*self as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum RomType {
Type27512,
Type23128 {
cs1: CsActive,
cs2: CsActive,
cs3: CsActive,
},
Type2364 { cs: CsActive },
Type2332 { cs1: CsActive, cs2: CsActive },
Type2316 {
cs1: CsActive,
cs2: CsActive,
cs3: CsActive,
},
}
impl core::fmt::Display for RomType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{} ({})", self.type_str(), self.cs_str())
}
}
impl RomType {
const CS1_23128_ADDR: usize = 17;
const CS2_23128_ADDR: usize = 16;
const CS3_23128_ADDR: usize = 14;
const CS_2364_ADDR: usize = 13;
const CS1_2332_ADDR: usize = 13;
const CS2_2332_ADDR: usize = 12;
const CS1_2316_ADDR: usize = 13;
const CS2_2316_ADDR: usize = 11;
const CS3_2316_ADDR: usize = 12;
pub const fn max_size() -> usize {
65536
}
pub const fn size(&self) -> usize {
match self {
RomType::Type27512 => 65536,
RomType::Type23128 { .. } => 16384,
RomType::Type2364 { .. } => 8192,
RomType::Type2332 { .. } => 4096,
RomType::Type2316 { .. } => 2048,
}
}
pub const fn rom_pins(&self) -> usize {
match self {
RomType::Type27512 => 28,
RomType::Type23128 { .. } => 28,
RomType::Type2364 { .. } => 24,
RomType::Type2332 { .. } => 24,
RomType::Type2316 { .. } => 24,
}
}
pub const fn invalid_addr_lines(&self) -> &'static [u8] {
match self {
RomType::Type27512 => &[],
RomType::Type23128 { .. } => &[15],
RomType::Type2364 { .. } => &[],
RomType::Type2332 { .. } => &[],
RomType::Type2316 { .. } => &[],
}
}
pub fn cs_active_mask(&self) -> usize {
match self {
RomType::Type27512 => 0,
RomType::Type23128 { cs1, cs2, cs3 } => {
cs1.bit() << Self::CS1_23128_ADDR
| cs2.bit() << Self::CS2_23128_ADDR
| cs3.bit() << Self::CS3_23128_ADDR
}
RomType::Type2364 { cs } => cs.bit() << Self::CS_2364_ADDR,
RomType::Type2332 { cs1, cs2 } => {
cs1.bit() << Self::CS1_2332_ADDR | cs2.bit() << Self::CS2_2332_ADDR
}
RomType::Type2316 { cs1, cs2, cs3 } => {
cs1.bit() << Self::CS1_2316_ADDR
| cs2.bit() << Self::CS2_2316_ADDR
| cs3.bit() << Self::CS3_2316_ADDR
}
}
}
pub const fn all() -> &'static [RomType] {
&ALL_ROM_TYPES
}
pub const fn type_str(&self) -> &'static str {
match self {
RomType::Type27512 => "27512",
RomType::Type23128 { .. } => "23128",
RomType::Type2364 { .. } => "2364",
RomType::Type2332 { .. } => "2332",
RomType::Type2316 { .. } => "2316",
}
}
pub const fn cs_str(&self) -> &'static str {
match self {
RomType::Type27512 => "N/A",
RomType::Type23128 { cs1, cs2, cs3 } => match (cs1, cs2, cs3) {
(CsActive::Low, CsActive::Low, CsActive::Low) => "CS1 Low, CS2 Low, CS3 Low",
(CsActive::Low, CsActive::Low, CsActive::High) => "CS1 Low, CS2 Low, CS3 High",
(CsActive::Low, CsActive::High, CsActive::Low) => "CS1 Low, CS2 High, CS3 Low",
(CsActive::Low, CsActive::High, CsActive::High) => "CS1 Low, CS2 High, CS3 High",
(CsActive::High, CsActive::Low, CsActive::Low) => "CS1 High, CS2 Low, CS3 Low",
(CsActive::High, CsActive::Low, CsActive::High) => "CS1 High, CS2 Low, CS3 High",
(CsActive::High, CsActive::High, CsActive::Low) => "CS1 High, CS2 High, CS3 Low",
(CsActive::High, CsActive::High, CsActive::High) => "CS1 High, CS2 High, CS3 High",
},
RomType::Type2364 { cs } => match cs {
CsActive::Low => "CS Low",
CsActive::High => "CS High",
},
RomType::Type2332 { cs1, cs2 } => match (cs1, cs2) {
(CsActive::Low, CsActive::Low) => "CS1 Low, CS2 Low",
(CsActive::Low, CsActive::High) => "CS1 Low, CS2 High",
(CsActive::High, CsActive::Low) => "CS1 High, CS2 Low",
(CsActive::High, CsActive::High) => "CS1 High, CS2 High",
},
RomType::Type2316 { cs1, cs2, cs3 } => match (cs1, cs2, cs3) {
(CsActive::Low, CsActive::Low, CsActive::Low) => "CS1 Low, CS2 Low, CS3 Low",
(CsActive::Low, CsActive::Low, CsActive::High) => "CS1 Low, CS2 Low, CS3 High",
(CsActive::Low, CsActive::High, CsActive::Low) => "CS1 Low, CS2 High, CS3 Low",
(CsActive::Low, CsActive::High, CsActive::High) => "CS1 Low, CS2 High, CS3 High",
(CsActive::High, CsActive::Low, CsActive::Low) => "CS1 High, CS2 Low, CS3 Low",
(CsActive::High, CsActive::Low, CsActive::High) => "CS1 High, CS2 Low, CS3 High",
(CsActive::High, CsActive::High, CsActive::Low) => "CS1 High, CS2 High, CS3 Low",
(CsActive::High, CsActive::High, CsActive::High) => "CS1 High, CS2 High, CS3 High",
},
}
}
pub const fn binary_size() -> usize {
4
}
pub fn from_bytes(buf: &[u8]) -> Result<Self, Error> {
if buf.len() < Self::binary_size() {
return Err(Error::ParseError);
}
match RomTypeByte::from_byte(buf[0])? {
RomTypeByte::Type27512 => Ok(RomType::Type27512 {}),
RomTypeByte::Type23128 => {
let cs1 = CsActiveByte::from_byte(buf[1])?.into();
let cs2 = CsActiveByte::from_byte(buf[2])?.into();
let cs3 = CsActiveByte::from_byte(buf[3])?.into();
Ok(RomType::Type23128 { cs1, cs2, cs3 })
}
RomTypeByte::Type2364 => {
let cs = CsActiveByte::from_byte(buf[1])?.into();
Ok(RomType::Type2364 { cs })
}
RomTypeByte::Type2332 => {
let cs1 = CsActiveByte::from_byte(buf[1])?.into();
let cs2 = CsActiveByte::from_byte(buf[2])?.into();
Ok(RomType::Type2332 { cs1, cs2 })
}
RomTypeByte::Type2316 => {
let cs1 = CsActiveByte::from_byte(buf[1])?.into();
let cs2 = CsActiveByte::from_byte(buf[2])?.into();
let cs3 = CsActiveByte::from_byte(buf[3])?.into();
Ok(RomType::Type2316 { cs1, cs2, cs3 })
}
}
}
pub fn to_bytes(&self, buf: &mut [u8]) -> Result<(), Error> {
if buf.len() < Self::binary_size() {
return Err(Error::ParseError);
}
match self {
RomType::Type27512 => {
buf[0] = RomTypeByte::Type27512.to_byte();
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
}
RomType::Type23128 { cs1, cs2, cs3 } => {
buf[0] = RomTypeByte::Type23128.to_byte();
buf[1] = CsActiveByte::from(*cs1).to_byte();
buf[2] = CsActiveByte::from(*cs2).to_byte();
buf[3] = CsActiveByte::from(*cs3).to_byte();
}
RomType::Type2364 { cs } => {
buf[0] = RomTypeByte::Type2364.to_byte();
buf[1] = CsActiveByte::from(*cs).to_byte();
buf[2] = 0;
buf[3] = 0;
}
RomType::Type2332 { cs1, cs2 } => {
buf[0] = RomTypeByte::Type2332.to_byte();
buf[1] = CsActiveByte::from(*cs1).to_byte();
buf[2] = CsActiveByte::from(*cs2).to_byte();
buf[3] = 0;
}
RomType::Type2316 { cs1, cs2, cs3 } => {
buf[0] = RomTypeByte::Type2316.to_byte();
buf[1] = CsActiveByte::from(*cs1).to_byte();
buf[2] = CsActiveByte::from(*cs2).to_byte();
buf[3] = CsActiveByte::from(*cs3).to_byte();
}
}
Ok(())
}
}
const NUM_ROM_TYPES: usize = 23;
const ALL_ROM_TYPES: [RomType; NUM_ROM_TYPES] = [
RomType::Type27512 {},
RomType::Type23128 {
cs1: CsActive::Low,
cs2: CsActive::Low,
cs3: CsActive::Low,
},
RomType::Type23128 {
cs1: CsActive::Low,
cs2: CsActive::Low,
cs3: CsActive::High,
},
RomType::Type23128 {
cs1: CsActive::Low,
cs2: CsActive::High,
cs3: CsActive::Low,
},
RomType::Type23128 {
cs1: CsActive::Low,
cs2: CsActive::High,
cs3: CsActive::High,
},
RomType::Type23128 {
cs1: CsActive::High,
cs2: CsActive::Low,
cs3: CsActive::Low,
},
RomType::Type23128 {
cs1: CsActive::High,
cs2: CsActive::Low,
cs3: CsActive::High,
},
RomType::Type23128 {
cs1: CsActive::High,
cs2: CsActive::High,
cs3: CsActive::Low,
},
RomType::Type23128 {
cs1: CsActive::High,
cs2: CsActive::High,
cs3: CsActive::High,
},
RomType::Type2364 { cs: CsActive::Low },
RomType::Type2364 { cs: CsActive::High },
RomType::Type2332 {
cs1: CsActive::Low,
cs2: CsActive::Low,
},
RomType::Type2332 {
cs1: CsActive::Low,
cs2: CsActive::High,
},
RomType::Type2332 {
cs1: CsActive::High,
cs2: CsActive::Low,
},
RomType::Type2332 {
cs1: CsActive::High,
cs2: CsActive::High,
},
RomType::Type2316 {
cs1: CsActive::Low,
cs2: CsActive::Low,
cs3: CsActive::Low,
},
RomType::Type2316 {
cs1: CsActive::Low,
cs2: CsActive::Low,
cs3: CsActive::High,
},
RomType::Type2316 {
cs1: CsActive::Low,
cs2: CsActive::High,
cs3: CsActive::Low,
},
RomType::Type2316 {
cs1: CsActive::Low,
cs2: CsActive::High,
cs3: CsActive::High,
},
RomType::Type2316 {
cs1: CsActive::High,
cs2: CsActive::Low,
cs3: CsActive::Low,
},
RomType::Type2316 {
cs1: CsActive::High,
cs2: CsActive::Low,
cs3: CsActive::High,
},
RomType::Type2316 {
cs1: CsActive::High,
cs2: CsActive::High,
cs3: CsActive::Low,
},
RomType::Type2316 {
cs1: CsActive::High,
cs2: CsActive::High,
cs3: CsActive::High,
},
];