use super::*;
use crate::common::{
embedded_io::{ErrorType, Read, Write},
ringbuf::*,
};
pub struct UartInterruptTx<U, OS: OsInterface> {
uart: U,
timeout: MicrosDurationU32,
flush_timeout: MicrosDurationU32,
w: Producer<u8>,
waiter: OS::NotifyWaiter,
}
impl<U, OS> UartInterruptTx<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
pub fn new(
uart: [U; 2],
buf_size: usize,
baudrate: u32,
timeout: MicrosDurationU32,
) -> (Self, UartInterruptTxHandler<U, OS>) {
let (notifier, waiter) = OS::notify();
let [uart, u2] = uart;
let (w, r) = RingBuffer::<u8>::new(buf_size);
(
Self {
uart,
timeout,
flush_timeout: calculate_timeout(baudrate, buf_size + 10),
w,
waiter,
},
UartInterruptTxHandler::new(u2, r, notifier),
)
}
}
impl<U: UartPeriph, OS: OsInterface> ErrorType for UartInterruptTx<U, OS> {
type Error = Error;
}
impl<U: UartPeriph, OS: OsInterface> Write for UartInterruptTx<U, OS> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
return Err(Error::Other);
}
self.waiter
.wait_with(OS::O, self.timeout, 2, || {
if let n @ 1.. = self.w.push_slice(buf) {
self.uart.set_interrupt(Event::TxEmpty, true);
return Some(n);
} else if !self.uart.is_interrupt_enable(Event::TxEmpty) {
self.uart.set_interrupt(Event::TxEmpty, true);
}
None
})
.ok_or(Error::Busy)
}
fn flush(&mut self) -> Result<(), Self::Error> {
self.waiter
.wait_with(OS::O, self.flush_timeout, 4, || {
if self.uart.is_tx_complete() && self.w.slots() == self.w.buffer().capacity() {
return Some(());
} else if !self.uart.is_interrupt_enable(Event::TxEmpty) {
self.uart.set_interrupt(Event::TxEmpty, true);
}
None
})
.ok_or(Error::Other)
}
}
pub struct UartInterruptTxHandler<U, OS: OsInterface> {
uart: U,
r: Consumer<u8>,
notifier: OS::Notifier,
}
impl<U, OS> UartInterruptTxHandler<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
pub fn new(uart: U, r: Consumer<u8>, notifier: OS::Notifier) -> Self {
Self { uart, r, notifier }
}
}
impl<U, OS> UartInterruptTxHandler<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
pub fn handler(&mut self) {
if let Some(has_data) = self.uart.write_with(|| {
let data = self.r.pop();
data.map_or(None, |d| Some(d as u16))
}) {
if has_data {
self.notifier.notify();
} else if self.uart.is_interrupt_enable(Event::TxEmpty) {
self.uart.set_interrupt(Event::TxEmpty, false);
}
}
}
}
pub struct UartInterruptRx<U, OS: OsInterface> {
uart: U,
timeout: MicrosDurationU32,
r: Consumer<u8>,
waiter: OS::NotifyWaiter,
}
impl<U, OS> UartInterruptRx<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
pub fn new(
uart: [U; 2],
buf_size: usize,
timeout: MicrosDurationU32,
) -> (Self, UartInterruptRxHandler<U, OS>) {
let (notifier, waiter) = OS::notify();
let [uart, u2] = uart;
let (w, r) = RingBuffer::<u8>::new(buf_size);
(
Self {
uart,
timeout,
r,
waiter,
},
UartInterruptRxHandler::new(u2, w, notifier),
)
}
}
impl<U: UartPeriph, OS: OsInterface> ErrorType for UartInterruptRx<U, OS> {
type Error = Error;
}
impl<U, OS> Read for UartInterruptRx<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
return Err(Error::Other);
}
self.waiter
.wait_with(OS::O, self.timeout, 2, || {
if let n @ 1.. = self.r.pop_slice(buf) {
return Some(n);
} else if !self.uart.is_interrupt_enable(Event::RxNotEmpty) {
self.uart.set_interrupt(Event::RxNotEmpty, true);
}
None
})
.ok_or(Error::Other)
}
}
pub struct UartInterruptRxHandler<U, OS: OsInterface> {
uart: U,
w: Producer<u8>,
notifier: OS::Notifier,
}
impl<U, OS> UartInterruptRxHandler<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
pub fn new(mut uart: U, w: Producer<u8>, notifier: OS::Notifier) -> Self {
uart.set_interrupt(Event::RxNotEmpty, true);
Self {
uart,
w,
notifier,
}
}
pub fn handler(&mut self) {
if let Ok(data) = self.uart.read() {
self.w.push(data as u8).ok();
self.notifier.notify();
}
}
}