#![no_std]
#![deny(warnings, missing_docs)]
mod fcr;
mod ier;
mod iir;
mod lcr;
mod lsr;
mod mcr;
mod msr;
mod rbr_thr;
use core::cell::UnsafeCell;
pub use fcr::{FifoControl, TriggerLevel};
pub use ier::InterruptTypes;
pub use iir::{InterruptIdentification, PendingInterrupt};
pub use lcr::{CharLen, LineControl, PARITY};
pub use lsr::LineStatus;
pub use mcr::ModemControl;
pub use msr::ModemStatus;
pub trait Register: From<u8> {
fn val(self) -> u8;
}
impl Register for u8 {
#[inline]
fn val(self) -> u8 {
self
}
}
impl Register for u32 {
#[inline]
fn val(self) -> u8 {
self as _
}
}
#[allow(non_camel_case_types)]
#[repr(transparent)]
pub struct RBR_THR<R: Register>(UnsafeCell<R>);
#[repr(transparent)]
pub struct IER<R: Register>(UnsafeCell<R>);
#[allow(non_camel_case_types)]
#[repr(transparent)]
pub struct IIR_FCR<R: Register>(UnsafeCell<R>);
#[repr(transparent)]
pub struct LCR<R: Register>(UnsafeCell<R>);
#[repr(transparent)]
pub struct MCR<R: Register>(UnsafeCell<R>);
#[repr(transparent)]
pub struct LSR<R: Register>(UnsafeCell<R>);
#[repr(transparent)]
pub struct MSR<R: Register>(UnsafeCell<R>);
#[repr(C)]
pub struct Uart16550<R: Register> {
rbr_thr: RBR_THR<R>, ier: IER<R>, iir_fcr: IIR_FCR<R>, lcr: LCR<R>, mcr: MCR<R>, lsr: LSR<R>, msr: MSR<R>, }
impl<R: Register> Uart16550<R> {
#[inline]
pub fn rbr_thr(&self) -> &RBR_THR<R> {
&self.rbr_thr
}
#[inline]
pub fn ier(&self) -> &IER<R> {
&self.ier
}
#[inline]
pub fn iir_fcr(&self) -> &IIR_FCR<R> {
&self.iir_fcr
}
#[inline]
pub fn lcr(&self) -> &LCR<R> {
&self.lcr
}
#[inline]
pub fn mcr(&self) -> &MCR<R> {
&self.mcr
}
#[inline]
pub fn lsr(&self) -> &LSR<R> {
&self.lsr
}
#[inline]
pub fn msr(&self) -> &MSR<R> {
&self.msr
}
pub fn write_divisor(&self, divisor: u16) {
let lcr = self.lcr.read();
self.lcr.write(lcr.enable_dlr_access());
unsafe {
self.rbr_thr.0.get().write(R::from(divisor as _));
self.ier.0.get().write(R::from((divisor >> 8) as _));
}
self.lcr.write(lcr);
}
pub fn read(&self, buf: &mut [u8]) -> usize {
let mut count = 0usize;
for c in buf {
if self.lsr.read().is_data_ready() {
*c = self.rbr_thr.rx_data();
count += 1;
} else {
break;
}
}
count
}
pub fn write(&self, buf: &[u8]) -> usize {
let mut count = 0usize;
for c in buf {
if self.lsr.read().is_transmitter_fifo_empty() {
self.rbr_thr.tx_data(*c);
count += 1;
} else {
break;
}
}
count
}
}