use crate::gpio::*;
use embedded_hal::serial::{Read, Write};
use esp8266::{UART0, UART1};
use void::Void;
pub trait UART0Ext {
fn serial(self, tdx: Gpio1<UART>, rxd: Gpio3<UART>) -> UART0Serial;
}
impl UART0Ext for UART0 {
fn serial(self, txd: Gpio1<UART>, rxd: Gpio3<UART>) -> UART0Serial {
UART0Serial {
uart: self,
txd,
rxd,
}
}
}
pub trait UART1Ext {
fn serial(self, txd: Gpio2<UART>) -> UART1Serial;
}
impl UART1Ext for UART1 {
fn serial(self, txd: Gpio2<UART>) -> UART1Serial {
UART1Serial { uart: self, txd }
}
}
pub struct UART0Serial {
uart: UART0,
txd: Gpio1<UART>,
rxd: Gpio3<UART>,
}
impl UART0Serial {
pub fn decompose(mut self) -> nb::Result<(UART0, Gpio1<UART>, Gpio3<UART>), Void> {
self.flush()?;
Ok((self.uart, self.txd, self.rxd))
}
}
impl Read<u8> for UART0Serial {
type Error = Void;
fn read(&mut self) -> nb::Result<u8, Self::Error> {
if self.uart.uart_status.read().rxfifo_cnt().bits() > 0 {
Ok(self.uart.uart_fifo.read().rxfifo_rd_byte().bits())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl Write<u8> for UART0Serial {
type Error = Void;
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
if self.uart.uart_status.read().txfifo_cnt().bits() < 128 {
self.uart
.uart_fifo
.write(|w| unsafe { w.rxfifo_write_byte().bits(word) });
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
fn flush(&mut self) -> nb::Result<(), Void> {
if self.uart.uart_status.read().txfifo_cnt().bits() > 0 {
Err(nb::Error::WouldBlock)
} else {
Ok(())
}
}
}
impl core::fmt::Write for UART0Serial {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
s.as_bytes()
.iter()
.try_for_each(|c| nb::block!(self.write(*c)))
.map_err(|_| core::fmt::Error)
}
}
pub struct UART1Serial {
uart: UART1,
txd: Gpio2<UART>,
}
impl UART1Serial {
pub fn decompose(mut self) -> nb::Result<(UART1, Gpio2<UART>), Void> {
self.flush()?;
Ok((self.uart, self.txd))
}
}
impl Write<u8> for UART1Serial {
type Error = Void;
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
if self.uart.uart_status.read().txfifo_cnt().bits() < 128 {
self.uart
.uart_fifo
.write(|w| unsafe { w.rxfifo_write_byte().bits(word) });
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
fn flush(&mut self) -> nb::Result<(), Void> {
if self.uart.uart_status.read().txfifo_cnt().bits() > 0 {
Err(nb::Error::WouldBlock)
} else {
Ok(())
}
}
}
impl core::fmt::Write for UART1Serial {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
s.as_bytes()
.iter()
.try_for_each(|c| nb::block!(self.write(*c)))
.map_err(|_| core::fmt::Error)
}
}
impl embedded_hal::blocking::serial::write::Default<u8> for UART0Serial {}
impl embedded_hal::blocking::serial::write::Default<u8> for UART1Serial {}
#[cfg(all(feature = "rt", feature = "interrupt"))]
mod interrupt {
use super::*;
int_handler!(UART => UartInterruptHandler(UART0Serial));
impl UART0Serial {
#[must_use = "the interrupt handler must be kept in scope for the interrupt to be handled"]
pub fn attach_interrupt<F: FnMut(&mut UART0Serial)>(
self,
mut f: F,
) -> Pin<UartInterruptHandler<impl FnMut(&mut UART0Serial)>> {
UartInterruptHandler::new(self, move |serial: &mut UART0Serial| {
f(serial);
serial.uart.uart_int_clr.write(|w| unsafe { w.bits(0xff) });
})
}
}
}