#![allow(dead_code)]
use crate::util::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum AlpideProtocolExtension {
Padding,
StripStart,
DetectorTimeout,
OutOfTable,
ProtocolError,
LaneFifoOverflowError,
FsmError,
PendingDetectorEventLimit,
PendingLaneEventLimit,
O2nError,
RateMissingTriggerError,
PeDataMissing,
OotDataMissing,
}
impl AlpideProtocolExtension {
const APE_PADDING: u8 = 0x00;
const APE_STRIP_START: u8 = 0xF2; const APE_DET_TIMEOUT: u8 = 0xF4; const APE_OOT: u8 = 0xF5; const APE_PROTOCOL_ERROR: u8 = 0xF6; const APE_LANE_FIFO_OVERFLOW_ERROR: u8 = 0xF7; const APE_FSM_ERROR: u8 = 0xF8; const APE_PENDING_DETECTOR_EVENT_LIMIT: u8 = 0xF9; const APE_PENDING_LANE_EVENT_LIMIT: u8 = 0xFA; const APE_O2N_ERROR: u8 = 0xFB; const APE_RATE_MISSING_TRG_ERROR: u8 = 0xFC; const APE_PE_DATA_MISSING: u8 = 0xFD; const APE_OOT_DATA_MISSING: u8 = 0xFE;
#[inline]
fn from_byte(b: u8) -> Result<AlpideWord, ()> {
match b {
Self::APE_STRIP_START => Ok(AlpideWord::Ape(AlpideProtocolExtension::StripStart)),
Self::APE_DET_TIMEOUT => Ok(AlpideWord::Ape(AlpideProtocolExtension::DetectorTimeout)),
Self::APE_OOT => Ok(AlpideWord::Ape(AlpideProtocolExtension::OutOfTable)),
Self::APE_PROTOCOL_ERROR => Ok(AlpideWord::Ape(AlpideProtocolExtension::ProtocolError)),
Self::APE_LANE_FIFO_OVERFLOW_ERROR => Ok(AlpideWord::Ape(
AlpideProtocolExtension::LaneFifoOverflowError,
)),
Self::APE_FSM_ERROR => Ok(AlpideWord::Ape(AlpideProtocolExtension::FsmError)),
Self::APE_PENDING_DETECTOR_EVENT_LIMIT => Ok(AlpideWord::Ape(
AlpideProtocolExtension::PendingDetectorEventLimit,
)),
Self::APE_PENDING_LANE_EVENT_LIMIT => Ok(AlpideWord::Ape(
AlpideProtocolExtension::PendingLaneEventLimit,
)),
Self::APE_O2N_ERROR => Ok(AlpideWord::Ape(AlpideProtocolExtension::O2nError)),
Self::APE_RATE_MISSING_TRG_ERROR => Ok(AlpideWord::Ape(
AlpideProtocolExtension::RateMissingTriggerError,
)),
Self::APE_PE_DATA_MISSING => {
Ok(AlpideWord::Ape(AlpideProtocolExtension::PeDataMissing))
}
Self::APE_OOT_DATA_MISSING => {
Ok(AlpideWord::Ape(AlpideProtocolExtension::OotDataMissing))
}
Self::APE_PADDING => Ok(AlpideWord::Ape(AlpideProtocolExtension::Padding)),
_ => Err(()),
}
}
}
impl fmt::Display for AlpideProtocolExtension {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AlpideProtocolExtension::Padding => write!(f, "APE_PADDING"),
AlpideProtocolExtension::StripStart => write!(f, "APE_STRIP_START"),
AlpideProtocolExtension::DetectorTimeout => write!(f, "APE_DET_TIMEOUT"),
AlpideProtocolExtension::OutOfTable => write!(f, "APE_OOT"),
AlpideProtocolExtension::ProtocolError => write!(f, "APE_PROTOCOL_ERROR"),
AlpideProtocolExtension::LaneFifoOverflowError => {
write!(f, "APE_LANE_FIFO_OVERFLOW_ERROR")
}
AlpideProtocolExtension::FsmError => write!(f, "APE_FSM_ERROR"),
AlpideProtocolExtension::PendingDetectorEventLimit => {
write!(f, "APE_PENDING_DETECTOR_EVENT_LIMIT")
}
AlpideProtocolExtension::PendingLaneEventLimit => {
write!(f, "APE_PENDING_LANE_EVENT_LIMIT")
}
AlpideProtocolExtension::O2nError => write!(f, "APE_O2N_ERROR"),
AlpideProtocolExtension::RateMissingTriggerError => {
write!(f, "APE_RATE_MISSING_TRG_ERROR")
}
AlpideProtocolExtension::PeDataMissing => write!(f, "APE_PE_DATA_MISSING"),
AlpideProtocolExtension::OotDataMissing => write!(f, "APE_OOT_DATA_MISSING"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum AlpideWord {
ChipHeader, ChipEmptyFrame, ChipTrailer, RegionHeader, DataShort, DataLong, BusyOn, BusyOff, Ape(AlpideProtocolExtension),
}
impl AlpideWord {
const CHIP_HEADER: u8 = 0xA0; const CHIP_HEADER_RANGE: RangeInclusive<u8> = 0xA0..=0xAF;
const CHIP_EMPTY_FRAME: u8 = 0xE0; const CHIP_EMPTY_FRAME_RANGE: RangeInclusive<u8> = 0xE0..=0xEF;
const CHIP_TRAILER: u8 = 0xB0; const CHIP_TRAILER_RANGE: RangeInclusive<u8> = 0xB0..=0xBF;
const REGION_HEADER: u8 = 0xC0; const REGION_HEADER_RANGE: RangeInclusive<u8> = 0xC0..=0xDF;
const DATA_SHORT: u8 = 0b0100_0000; const DATA_SHORT_RANGE: RangeInclusive<u8> = 0x40..=0x7F;
const DATA_LONG: u8 = 0b0000_0000; const DATA_LONG_RANGE: RangeInclusive<u8> = 0x00..=0x3F;
const BUSY_ON: u8 = 0xF0;
const BUSY_OFF: u8 = 0xF1;
#[inline]
pub fn from_byte(b: u8) -> Result<AlpideWord, ()> {
match b {
c if c & 0xC0 == Self::DATA_SHORT => Ok(AlpideWord::DataShort),
c if c & 0xC0 == Self::DATA_LONG => Ok(AlpideWord::DataLong),
c if c & 0xE0 == Self::REGION_HEADER => Ok(AlpideWord::RegionHeader),
c if c & 0xF0 == Self::CHIP_EMPTY_FRAME => Ok(AlpideWord::ChipEmptyFrame),
c if Self::CHIP_HEADER_RANGE.contains(&c) => Ok(AlpideWord::ChipHeader),
c if c & 0xF0 == Self::CHIP_TRAILER => Ok(AlpideWord::ChipTrailer),
_ => Self::match_exact(b),
}
}
#[inline]
fn match_exact(b: u8) -> Result<AlpideWord, ()> {
match b {
Self::BUSY_ON => Ok(AlpideWord::BusyOn),
Self::BUSY_OFF => Ok(AlpideWord::BusyOff),
_ => AlpideProtocolExtension::from_byte(b),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn alpide_word_from_byte_variants() {
assert_eq!(AlpideWord::from_byte(0xA0).unwrap(), AlpideWord::ChipHeader);
assert_eq!(
AlpideWord::from_byte(0xE0).unwrap(),
AlpideWord::ChipEmptyFrame
);
assert_eq!(
AlpideWord::from_byte(0xB0).unwrap(),
AlpideWord::ChipTrailer
);
assert_eq!(
AlpideWord::from_byte(0xC0).unwrap(),
AlpideWord::RegionHeader
);
assert_eq!(
AlpideWord::from_byte(0b0100_0000).unwrap(),
AlpideWord::DataShort
);
assert_eq!(
AlpideWord::from_byte(0b0000_0000).unwrap(),
AlpideWord::DataLong
);
assert_eq!(AlpideWord::from_byte(0xF0).unwrap(), AlpideWord::BusyOn);
assert_eq!(AlpideWord::from_byte(0xF1).unwrap(), AlpideWord::BusyOff);
}
#[test]
fn alpide_word_from_byte_ape_variants() {
assert_eq!(
AlpideWord::from_byte(0xF2).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::StripStart)
);
assert_eq!(
AlpideWord::from_byte(0xF4).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::DetectorTimeout)
);
assert_eq!(
AlpideWord::from_byte(0xF5).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::OutOfTable)
);
assert_eq!(
AlpideWord::from_byte(0xF6).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::ProtocolError)
);
assert_eq!(
AlpideWord::from_byte(0xF7).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::LaneFifoOverflowError)
);
assert_eq!(
AlpideWord::from_byte(0xF8).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::FsmError)
);
assert_eq!(
AlpideWord::from_byte(0xF9).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::PendingDetectorEventLimit)
);
assert_eq!(
AlpideWord::from_byte(0xFA).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::PendingLaneEventLimit)
);
assert_eq!(
AlpideWord::from_byte(0xFB).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::O2nError)
);
assert_eq!(
AlpideWord::from_byte(0xFC).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::RateMissingTriggerError)
);
assert_eq!(
AlpideWord::from_byte(0xFD).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::PeDataMissing)
);
assert_eq!(
AlpideWord::from_byte(0xFE).unwrap(),
AlpideWord::Ape(AlpideProtocolExtension::OotDataMissing)
);
}
#[test]
fn alpide_word_from_byte_variants_ranges() {
for b in 0xA0..=0xAF {
assert_eq!(AlpideWord::from_byte(b).unwrap(), AlpideWord::ChipHeader);
}
for b in 0xE0..=0xEF {
assert_eq!(
AlpideWord::from_byte(b).unwrap(),
AlpideWord::ChipEmptyFrame
);
}
for b in 0xB0..=0xBF {
assert_eq!(AlpideWord::from_byte(b).unwrap(), AlpideWord::ChipTrailer);
}
for b in 0xC0..=0xDF {
assert_eq!(AlpideWord::from_byte(b).unwrap(), AlpideWord::RegionHeader);
}
for b in 0x40..=0x7F {
assert_eq!(AlpideWord::from_byte(b).unwrap(), AlpideWord::DataShort);
}
for b in 0x00..=0x3F {
assert_eq!(AlpideWord::from_byte(b).unwrap(), AlpideWord::DataLong);
}
}
}