use caravel_pac::{UartEnabledOutRegister, UartRegisters};
use embedded_io::{ErrorType, Read, Write};
pub struct Uart {
regs: &'static UartRegisters,
}
unsafe impl Send for Uart {}
impl Uart {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
let enable = UartEnabledOutRegister::new();
unsafe {
enable.value.write(1); }
Self {
regs: UartRegisters::new(),
}
}
#[inline(always)]
pub fn rx_ready(&self) -> bool {
self.regs.rxempty.read() == 0 }
#[inline(always)]
pub fn tx_ready(&self) -> bool {
self.regs.txfull.read() == 0
}
#[inline(always)]
pub fn tx_event_enable(&self, enable: bool) {
unsafe {
self.regs.ev_enable.modify(|x| x.with_tx(enable));
}
}
#[inline(always)]
pub fn rx_event_enable(&self, enable: bool) {
unsafe {
self.regs.ev_enable.modify(|x| x.with_rx(enable));
}
}
#[inline(always)]
pub fn rx_event_pending(&self) -> bool {
self.regs.ev_pending.read().rx()
}
#[inline(always)]
pub fn clear_rx_event(&self) {
unsafe {
self.regs.ev_pending.modify(|x| x.with_rx(true));
}
}
#[inline(always)]
pub fn tx_event_pending(&self) -> bool {
self.regs.ev_pending.read().tx()
}
#[inline(always)]
pub fn clear_tx_event(&self) {
unsafe {
self.regs.ev_pending.modify(|x| x.with_tx(true));
}
}
}
impl ErrorType for Uart {
type Error = core::convert::Infallible;
}
impl Read for Uart {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
return Ok(0);
}
while !self.rx_ready() {}
let mut n = 0;
loop {
buf[n] = self.regs.rxtx.read() as u8;
unsafe {
self.regs.ev_pending.modify(|x| x.with_rx(true));
}
n += 1;
if !self.rx_ready() || n == buf.len() {
break;
}
}
Ok(n)
}
}
impl Write for Uart {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
if buf.is_empty() {
return Ok(0);
}
while !self.tx_ready() {}
let mut n = 0;
for &byte in buf {
if !self.tx_ready() {
break;
}
unsafe {
self.regs.rxtx.write(byte as u32);
}
n += 1;
}
Ok(n)
}
fn flush(&mut self) -> Result<(), Self::Error> {
while !self.tx_ready() {}
Ok(())
}
}