use crate::command::{FlushTx, WriteTxPayload};
use crate::config::Configuration;
use crate::device::Device;
use crate::registers::{FifoStatus, ObserveTx, Status};
use crate::standby::StandbyMode;
use core::fmt;
pub struct TxMode<D: Device> {
device: D,
}
impl<D: Device> fmt::Debug for TxMode<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TxMode")
}
}
impl<D: Device> TxMode<D> {
pub(crate) fn new(device: D) -> Self {
TxMode { device }
}
pub fn standby(mut self) -> Result<StandbyMode<D>, D::Error> {
self.wait_empty()?;
Ok(StandbyMode::from_rx_tx(self.device))
}
pub fn is_empty(&mut self) -> Result<bool, D::Error> {
let (_, fifo_status) = self.device.read_register::<FifoStatus>()?;
Ok(fifo_status.tx_empty())
}
pub fn is_full(&mut self) -> Result<bool, D::Error> {
let (_, fifo_status) = self.device.read_register::<FifoStatus>()?;
Ok(fifo_status.tx_full())
}
pub fn can_send(&mut self) -> Result<bool, D::Error> {
let full = self.is_full()?;
Ok(!full)
}
pub fn send(&mut self, packet: &[u8]) -> Result<(), D::Error> {
self.device.send_command(&WriteTxPayload::new(packet))?;
self.device.ce_enable();
Ok(())
}
pub fn poll_send(&mut self) -> nb::Result<bool, D::Error> {
let (status, fifo_status) = self.device.read_register::<FifoStatus>()?;
if status.max_rt() {
self.device.send_command(&FlushTx)?;
self.clear_interrupts_and_ce()?;
Ok(false)
} else if fifo_status.tx_empty() {
self.clear_interrupts_and_ce()?;
Ok(true)
} else {
self.device.ce_enable();
Err(nb::Error::WouldBlock)
}
}
fn clear_interrupts_and_ce(&mut self) -> nb::Result<(), D::Error> {
let mut clear = Status(0);
clear.set_tx_ds(true);
clear.set_max_rt(true);
self.device.write_register(clear)?;
self.device.ce_disable();
Ok(())
}
pub fn wait_empty(&mut self) -> Result<(), D::Error> {
let mut empty = false;
while !empty {
let (status, fifo_status) = self.device.read_register::<FifoStatus>()?;
empty = fifo_status.tx_empty();
if !empty {
self.device.ce_enable();
}
if status.max_rt() {
let mut clear = Status(0);
self.device.send_command(&FlushTx)?;
clear.set_tx_ds(true);
clear.set_max_rt(true);
self.device.write_register(clear)?;
}
}
self.device.ce_disable();
Ok(())
}
pub fn observe(&mut self) -> Result<ObserveTx, D::Error> {
let (_, observe_tx) = self.device.read_register()?;
Ok(observe_tx)
}
}
impl<D: Device> Configuration for TxMode<D> {
type Inner = D;
fn device(&mut self) -> &mut Self::Inner {
&mut self.device
}
}