use super::*;
use crate::pac::uart0::uartlcr_h::W as UART_LCR_H_Writer;
use core::convert::Infallible;
use core::fmt;
use embedded_hal::serial::{Read, Write};
use fugit::HertzU32;
use nb::Error::{Other, WouldBlock};
use rp2040_pac::{UART0, UART1};
#[cfg(feature = "eh1_0_alpha")]
use eh1_0_alpha::serial as eh1;
#[cfg(feature = "eh1_0_alpha")]
use eh_nb_1_0_alpha::serial as eh1nb;
use pac::Peripherals;
pub struct UartPeripheral<S: State, D: UartDevice, P: ValidUartPinout<D>> {
device: D,
_state: S,
pins: P,
}
impl<S: State, D: UartDevice, P: ValidUartPinout<D>> UartPeripheral<S, D, P> {
fn transition<To: State>(self, state: To) -> UartPeripheral<To, D, P> {
UartPeripheral {
device: self.device,
pins: self.pins,
_state: state,
}
}
pub fn free(self) -> (D, P) {
(self.device, self.pins)
}
}
impl<D: UartDevice, P: ValidUartPinout<D>> UartPeripheral<Disabled, D, P> {
pub fn new(device: D, pins: P, resets: &mut pac::RESETS) -> UartPeripheral<Disabled, D, P> {
device.reset_bring_down(resets);
device.reset_bring_up(resets);
UartPeripheral {
device,
_state: Disabled,
pins,
}
}
pub fn enable(
self,
config: UartConfig,
frequency: HertzU32,
) -> Result<UartPeripheral<Enabled, D, P>, Error> {
let (mut device, pins) = self.free();
configure_baudrate(&mut device, config.baudrate, frequency)?;
device.uartlcr_h.write(|w| {
w.fen().set_bit(); set_format(w, &config.data_bits, &config.stop_bits, &config.parity);
w
});
device.uartcr.write(|w| {
w.uarten().set_bit();
w.txe().bit(P::TX_ENABLED);
w.rxe().bit(P::RX_ENABLED);
w.ctsen().bit(P::CTS_ENABLED);
w.rtsen().bit(P::RTS_ENABLED);
w
});
device.uartdmacr.write(|w| {
w.txdmae().set_bit();
w.rxdmae().set_bit();
w
});
Ok(UartPeripheral {
device,
pins,
_state: Enabled,
})
}
}
impl<D: UartDevice, P: ValidUartPinout<D>> UartPeripheral<Enabled, D, P> {
pub fn disable(self) -> UartPeripheral<Disabled, D, P> {
self.device.uartcr.write(|w| {
w.uarten().clear_bit();
w.txe().clear_bit();
w.rxe().clear_bit();
w.ctsen().clear_bit();
w.rtsen().clear_bit();
w
});
self.transition(Disabled)
}
pub fn set_fifos(&mut self, enable: bool) {
super::reader::set_fifos(&self.device, enable)
}
pub fn set_rx_watermark(&mut self, watermark: FifoWatermark) {
super::reader::set_rx_watermark(&self.device, watermark)
}
pub fn set_tx_watermark(&mut self, watermark: FifoWatermark) {
super::writer::set_tx_watermark(&self.device, watermark)
}
pub fn enable_rx_interrupt(&mut self) {
super::reader::enable_rx_interrupt(&self.device)
}
pub fn enable_tx_interrupt(&mut self) {
super::writer::enable_tx_interrupt(&self.device)
}
pub fn disable_rx_interrupt(&mut self) {
super::reader::disable_rx_interrupt(&self.device)
}
pub fn disable_tx_interrupt(&mut self) {
super::writer::disable_tx_interrupt(&self.device)
}
pub fn uart_is_writable(&self) -> bool {
super::writer::uart_is_writable(&self.device)
}
pub fn uart_is_readable(&self) -> bool {
super::reader::is_readable(&self.device)
}
pub fn write_raw<'d>(&self, data: &'d [u8]) -> nb::Result<&'d [u8], Infallible> {
super::writer::write_raw(&self.device, data)
}
pub fn read_raw<'b>(&self, buffer: &'b mut [u8]) -> nb::Result<usize, ReadError<'b>> {
super::reader::read_raw(&self.device, buffer)
}
pub fn write_full_blocking(&self, data: &[u8]) {
super::writer::write_full_blocking(&self.device, data);
}
pub fn read_full_blocking(&self, buffer: &mut [u8]) -> Result<(), ReadErrorType> {
super::reader::read_full_blocking(&self.device, buffer)
}
pub fn join(reader: Reader<D, P>, writer: Writer<D, P>) -> Self {
let _ = writer;
Self {
device: reader.device,
_state: Enabled,
pins: reader.pins,
}
}
}
impl<P: ValidUartPinout<UART0>> UartPeripheral<Enabled, UART0, P> {
pub fn split(self) -> (Reader<UART0, P>, Writer<UART0, P>) {
let reader = Reader {
device: self.device,
pins: self.pins,
};
let device_copy = unsafe { Peripherals::steal().UART0 };
let writer = Writer {
device: device_copy,
device_marker: core::marker::PhantomData,
pins: core::marker::PhantomData,
};
(reader, writer)
}
}
impl<P: ValidUartPinout<UART1>> UartPeripheral<Enabled, UART1, P> {
pub fn split(self) -> (Reader<UART1, P>, Writer<UART1, P>) {
let reader = Reader {
device: self.device,
pins: self.pins,
};
let device_copy = unsafe { Peripherals::steal().UART1 };
let writer = Writer {
device: device_copy,
device_marker: core::marker::PhantomData,
pins: core::marker::PhantomData,
};
(reader, writer)
}
}
fn calculate_baudrate_dividers(
wanted_baudrate: HertzU32,
frequency: HertzU32,
) -> Result<(u16, u16), Error> {
let baudrate_div = frequency
.to_Hz()
.checked_mul(8)
.and_then(|r| r.checked_div(wanted_baudrate.to_Hz()))
.ok_or(Error::BadArgument)?;
Ok(match (baudrate_div >> 7, ((baudrate_div & 0x7F) + 1) / 2) {
(0, _) => (1, 0),
(int_part, _) if int_part >= 65535 => (65535, 0),
(int_part, frac_part) => (int_part as u16, frac_part as u16),
})
}
fn configure_baudrate(
device: &mut dyn UartDevice,
wanted_baudrate: HertzU32,
frequency: HertzU32,
) -> Result<HertzU32, Error> {
let (baud_div_int, baud_div_frac) = calculate_baudrate_dividers(wanted_baudrate, frequency)?;
device.uartibrd.write(|w| unsafe {
w.baud_divint().bits(baud_div_int);
w
});
device.uartfbrd.write(|w| unsafe {
w.baud_divfrac().bits(baud_div_frac as u8);
w
});
device.uartlcr_h.modify(|_, w| w);
Ok(HertzU32::from_raw(
(4 * frequency.to_Hz()) / (64 * baud_div_int as u32 + baud_div_frac as u32),
))
}
fn set_format<'w>(
w: &'w mut UART_LCR_H_Writer,
data_bits: &DataBits,
stop_bits: &StopBits,
parity: &Option<Parity>,
) -> &'w mut UART_LCR_H_Writer {
match parity {
Some(p) => {
w.pen().set_bit();
match p {
Parity::Odd => w.eps().clear_bit(),
Parity::Even => w.eps().set_bit(),
};
}
None => {
w.pen().bit(false);
}
};
unsafe {
w.wlen().bits(match data_bits {
DataBits::Five => 0b00,
DataBits::Six => 0b01,
DataBits::Seven => 0b10,
DataBits::Eight => 0b11,
})
};
match stop_bits {
StopBits::One => w.stp2().clear_bit(),
StopBits::Two => w.stp2().set_bit(),
};
w
}
impl<D: UartDevice, P: ValidUartPinout<D>> Read<u8> for UartPeripheral<Enabled, 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),
},
}
}
}
#[cfg(feature = "eh1_0_alpha")]
impl<D: UartDevice, P: ValidUartPinout<D>> eh1::ErrorType for UartPeripheral<Enabled, D, P> {
type Error = ReadErrorType;
}
#[cfg(feature = "eh1_0_alpha")]
impl<D: UartDevice, P: ValidUartPinout<D>> eh1nb::Read<u8> for UartPeripheral<Enabled, 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),
},
}
}
}
impl<D: UartDevice, P: ValidUartPinout<D>> Write<u8> for UartPeripheral<Enabled, D, P> {
type Error = Infallible;
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
if self.write_raw(&[word]).is_err() {
Err(WouldBlock)
} else {
Ok(())
}
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
super::writer::transmit_flushed(&self.device)
}
}
#[cfg(feature = "eh1_0_alpha")]
impl<D: UartDevice, P: ValidUartPinout<D>> eh1nb::Write<u8> for UartPeripheral<Enabled, D, P> {
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
if self.write_raw(&[word]).is_err() {
Err(WouldBlock)
} else {
Ok(())
}
}
fn flush(&mut self) -> nb::Result<(), Self::Error> {
super::writer::transmit_flushed(&self.device).map_err(|e| match e {
WouldBlock => WouldBlock,
Other(v) => match v {},
})
}
}
impl<D: UartDevice, P: ValidUartPinout<D>> fmt::Write for UartPeripheral<Enabled, D, P> {
fn write_str(&mut self, s: &str) -> fmt::Result {
s.bytes()
.try_for_each(|c| nb::block!(self.write(c)))
.map_err(|_| fmt::Error)
}
}