use super::{FifoWatermark, UartDevice, ValidUartPinout};
use crate::dma::{EndlessReadTarget, ReadTarget};
use crate::pac::uart0::RegisterBlock;
use embedded_hal::serial::Read;
use nb::Error::*;
#[cfg(feature = "eh1_0_alpha")]
use eh_nb_1_0_alpha::serial as eh1nb;
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug)]
pub struct ReadError<'err> {
pub err_type: ReadErrorType,
pub discarded: &'err [u8],
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug)]
pub enum ReadErrorType {
Overrun,
Break,
Parity,
Framing,
}
#[cfg(feature = "eh1_0_alpha")]
impl eh1nb::Error for ReadErrorType {
fn kind(&self) -> eh1nb::ErrorKind {
match self {
ReadErrorType::Overrun => eh1nb::ErrorKind::Overrun,
ReadErrorType::Break => eh1nb::ErrorKind::Other,
ReadErrorType::Parity => eh1nb::ErrorKind::Parity,
ReadErrorType::Framing => eh1nb::ErrorKind::FrameFormat,
}
}
}
pub(crate) fn is_readable<D: UartDevice>(device: &D) -> bool {
device.uartfr.read().rxfe().bit_is_clear()
}
pub fn set_fifos(rb: &RegisterBlock, enable: bool) {
if enable {
rb.uartlcr_h.modify(|_r, w| w.fen().set_bit())
} else {
rb.uartlcr_h.modify(|_r, w| w.fen().clear_bit())
}
}
pub fn set_rx_watermark(rb: &RegisterBlock, watermark: FifoWatermark) {
let wm = match watermark {
FifoWatermark::Bytes4 => 0,
FifoWatermark::Bytes8 => 1,
FifoWatermark::Bytes16 => 2,
FifoWatermark::Bytes24 => 3,
FifoWatermark::Bytes28 => 4,
};
rb.uartifls.modify(|_r, w| unsafe { w.rxiflsel().bits(wm) });
}
pub(crate) fn enable_rx_interrupt(rb: &RegisterBlock) {
rb.uartimsc.modify(|_r, w| {
w.rxim().set_bit();
w.rtim().set_bit();
w
});
}
pub(crate) fn disable_rx_interrupt(rb: &RegisterBlock) {
rb.uartimsc.modify(|_r, w| {
w.rxim().clear_bit();
w.rtim().clear_bit();
w
});
}
pub(crate) fn read_raw<'b, D: UartDevice>(
device: &D,
buffer: &'b mut [u8],
) -> nb::Result<usize, ReadError<'b>> {
let mut bytes_read = 0;
Ok(loop {
if !is_readable(device) {
if bytes_read == 0 {
return Err(WouldBlock);
} else {
break bytes_read;
}
}
if bytes_read < buffer.len() {
let mut error: Option<ReadErrorType> = None;
let read = device.uartdr.read();
if read.oe().bit_is_set() {
error = Some(ReadErrorType::Overrun);
}
if read.be().bit_is_set() {
error = Some(ReadErrorType::Break);
}
if read.pe().bit_is_set() {
error = Some(ReadErrorType::Parity);
}
if read.fe().bit_is_set() {
error = Some(ReadErrorType::Framing);
}
if let Some(err_type) = error {
return Err(Other(ReadError {
err_type,
discarded: &buffer[..bytes_read],
}));
}
buffer[bytes_read] = read.data().bits();
bytes_read += 1;
} else {
break bytes_read;
}
})
}
pub(crate) fn read_full_blocking<D: UartDevice>(
device: &D,
buffer: &mut [u8],
) -> Result<(), ReadErrorType> {
let mut offset = 0;
while offset != buffer.len() {
offset += match read_raw(device, &mut buffer[offset..]) {
Ok(bytes_read) => bytes_read,
Err(e) => match e {
Other(inner) => return Err(inner.err_type),
WouldBlock => continue,
},
}
}
Ok(())
}
pub struct Reader<D: UartDevice, P: ValidUartPinout<D>> {
pub(super) device: D,
pub(super) pins: P,
}
impl<D: UartDevice, P: ValidUartPinout<D>> Reader<D, P> {
pub fn read_raw<'b>(&self, buffer: &'b mut [u8]) -> nb::Result<usize, ReadError<'b>> {
read_raw(&self.device, buffer)
}
pub fn read_full_blocking(&self, buffer: &mut [u8]) -> Result<(), ReadErrorType> {
read_full_blocking(&self.device, buffer)
}
pub fn enable_rx_interrupt(&mut self) {
enable_rx_interrupt(&self.device)
}
pub fn disable_rx_interrupt(&mut self) {
disable_rx_interrupt(&self.device)
}
}
impl<D: UartDevice, P: ValidUartPinout<D>> Read<u8> for Reader<D, P> {
type Error = ReadErrorType;
fn read(&mut self) -> nb::Result<u8, Self::Error> {
let byte: &mut [u8] = &mut [0; 1];
match self.read_raw(byte) {
Ok(_) => Ok(byte[0]),
Err(e) => match e {
Other(inner) => Err(Other(inner.err_type)),
WouldBlock => Err(WouldBlock),
},
}
}
}
unsafe impl<D: UartDevice, P: ValidUartPinout<D>> ReadTarget for Reader<D, P> {
type ReceivedWord = u8;
fn rx_treq() -> Option<u8> {
Some(D::rx_dreq())
}
fn rx_address_count(&self) -> (u32, u32) {
(&self.device.uartdr as *const _ as u32, u32::MAX)
}
fn rx_increment(&self) -> bool {
false
}
}
impl<D: UartDevice, P: ValidUartPinout<D>> EndlessReadTarget for Reader<D, P> {}
#[cfg(feature = "eh1_0_alpha")]
impl<D: UartDevice, P: ValidUartPinout<D>> eh1nb::ErrorType for Reader<D, P> {
type Error = ReadErrorType;
}
#[cfg(feature = "eh1_0_alpha")]
impl<D: UartDevice, P: ValidUartPinout<D>> eh1nb::Read<u8> for Reader<D, P> {
fn read(&mut self) -> nb::Result<u8, Self::Error> {
let byte: &mut [u8] = &mut [0; 1];
match self.read_raw(byte) {
Ok(_) => Ok(byte[0]),
Err(e) => match e {
Other(inner) => Err(Other(inner.err_type)),
WouldBlock => Err(WouldBlock),
},
}
}
}