use crate::{
Baud, Data, FifoControl, InterruptEnable, LineControl, LineStatus, ModemControl, Uart,
UartAddress,
};
pub struct UartWriter<A: UartAddress>(Uart<A, Data>);
impl<A: UartAddress> UartWriter<A> {
pub unsafe fn new(address: A, loopback_test: bool) -> Self {
let mut uart = unsafe { Uart::<A, Data>::new(address) };
uart.write_line_control(LineControl::empty());
uart.write_fifo_control(FifoControl::empty());
uart.write_interrupt_enable(InterruptEnable::empty());
let mut uart = uart.into_dlab_mode();
uart.set_baud(Baud::B115200);
let mut uart = uart.into_data_mode();
uart.write_line_control(LineControl::BITS_8);
if loopback_test {
uart.write_modem_control(
ModemControl::REQUEST_TO_SEND
| ModemControl::OUT_1
| ModemControl::OUT_2
| ModemControl::LOOPBACK_MODE,
);
uart.write_byte(0x1F);
assert!(uart.read_byte() == 0x1F, "loopback test failed");
}
uart.write_modem_control(
ModemControl::TERMINAL_READY | ModemControl::REQUEST_TO_SEND | ModemControl::OUT_1,
);
Self(uart)
}
}
impl<A: UartAddress> core::fmt::Write for UartWriter<A> {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
s.chars().try_for_each(|c| self.write_char(c))
}
fn write_char(&mut self, c: char) -> core::fmt::Result {
while !self.0.read_line_status().contains(LineStatus::THR_EMPTY) {
core::hint::spin_loop();
}
self.0.write_byte({
if c.is_ascii() { c as u8 } else { b'?' }
});
Ok(())
}
}