use super::*;
use crate::common::{
embedded_io::{BufRead, ErrorType, Read, ReadReady, Write, WriteReady},
os_trait::Duration,
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, OS> Write for UartInterruptTx<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
return Err(Error::Other);
}
self.waiter
.wait_with(&Duration::<OS>::micros(self.timeout.ticks()), 1, || {
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(
&Duration::<OS>::micros(self.flush_timeout.ticks()),
1,
|| {
if self.uart.is_tx_complete() && self.w.is_empty() {
return Some(());
} else if !self.uart.is_interrupt_enable(Event::TxEmpty) {
self.uart.set_interrupt(Event::TxEmpty, true);
}
None
},
)
.ok_or(Error::Other)
}
}
impl<U, OS> WriteReady for UartInterruptTx<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
fn write_ready(&mut self) -> Result<bool, Self::Error> {
Ok(!self.w.is_full())
}
}
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(wrote_data) = self.uart.write_with(|| {
let data = self.r.pop();
data.map_or(None, |d| Some(d as u16))
}) {
if wrote_data {
if self.r.buffer().capacity() - self.r.slots() < 4 {
self.notifier.notify();
}
} else {
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(&Duration::<OS>::micros(self.timeout.ticks()), 1, || {
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)
}
}
impl<U, OS> BufRead for UartInterruptRx<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
self.waiter
.wait_with(&Duration::<OS>::micros(self.timeout.ticks()), 1, || {
if let Some(chunk) = self.r.get_read_chunk() {
let buf = chunk.get_slice();
let p = buf.as_ptr();
return unsafe { Some(core::slice::from_raw_parts(p, buf.len())) };
} else if !self.uart.is_interrupt_enable(Event::RxNotEmpty) {
self.uart.set_interrupt(Event::RxNotEmpty, true);
}
None
})
.ok_or(Error::Other)
}
fn consume(&mut self, amt: usize) {
let chunk = self.r.get_read_chunk().unwrap();
chunk.commit(amt);
}
}
impl<U, OS> ReadReady for UartInterruptRx<U, OS>
where
U: UartPeriph,
OS: OsInterface,
{
fn read_ready(&mut self) -> Result<bool, Self::Error> {
Ok(self.r.peek().is_ok())
}
}
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();
if self.w.buffer().capacity() - self.w.slots() < 4 {
self.notifier.notify();
}
}
}
}