use bitflags::bitflags;
use ufmt::{derive::uDebug, uDebug, uwrite, uwriteln};
use volatile_register::{RO, RW};
#[repr(C, packed)]
pub struct RegisterBlock {
software_iec_bus_id: RO<u8>,
control: RW<u8>,
command_data: RW<u8>,
response_data: RO<u8>,
status_data: RO<u8>,
}
impl RegisterBlock {
pub fn status(&self) -> Status {
Status::from_bits(self.control.read()).expect("No unknown bits")
}
}
bitflags! {
struct Control: u8 {
const PUSH_CMD = 0b00000001;
const DATA_ACC = 0b00000010;
const ABORT = 0b00000100;
const CLR_ERR = 0b00001000;
const RESERVED = 0b00010000;
const IRQ = 0b00100000;
const TRIGGER = 0b01000000;
const DMA = 0b10000000;
}
}
bitflags! {
pub struct Status: u8 {
const CMD_BUSY = 0b00000001;
const DATA_ACC = 0b00000010;
const ABORT_P = 0b00000100;
const ERROR = 0b00001000;
const STATE_0 = 0b00010000;
const STATE_1 = 0b00100000;
const STAT_AV = 0b01000000;
const DATA_AV = 0b10000000;
}
}
impl uDebug for Status {
fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
where
W: ufmt::uWrite + ?Sized,
{
uwriteln!(f, "UCI Status:")?;
uwriteln!(f, " cmd busy: {}", self.cmd_busy())?;
uwriteln!(f, " aborting: {}", self.aborting())?;
uwriteln!(f, " error: {}", self.error())?;
uwriteln!(f, " state: {:?}", self.state())?;
uwrite!(f, " data available:")?;
if self.status_data_available() {
uwrite!(f, " status")?;
}
if self.response_data_available() {
uwrite!(f, " response")?;
}
Ok(())
}
}
impl Status {
pub fn cmd_busy(&self) -> bool {
self.contains(Self::CMD_BUSY)
}
pub fn aborting(&self) -> bool {
self.contains(Self::ABORT_P)
}
pub fn error(&self) -> bool {
self.contains(Self::ERROR)
}
pub fn state(&self) -> State {
match (
!self.intersection(Self::STATE_1).is_empty(),
!self.intersection(Self::STATE_0).is_empty(),
) {
(false, false) => State::Idle,
(false, true) => State::CommandBusy,
(true, false) => State::DataLast,
(true, true) => State::DataMore,
}
}
pub fn status_data_available(&self) -> bool {
self.contains(Self::STAT_AV)
}
pub fn response_data_available(&self) -> bool {
self.contains(Self::DATA_AV)
}
}
#[derive(uDebug)]
pub enum State {
Idle,
CommandBusy,
DataLast,
DataMore,
}