use crate::hal::generic::serial::{SerialRxTx, ReadHandlerResult, SerialError, SerialPortMode};
use crate::event::{EventSink, OxideEvent};
use core::marker::PhantomData;
use crate::hal::generic::port::{Pin, PinMode};
#[derive(PartialEq,Eq,Clone,Copy)]
pub enum SerialState {
ReadAvailable,
SerialCommsError,
BreakDetected,
ReadBufferOverflow
}
pub struct SerialPort<P,T,R,S>
where
P: 'static + SerialRxTx,
T: 'static + Pin,
R: 'static + Pin,
S: EventSink
{
port: &'static mut P,
tx: &'static mut T,
rx: &'static mut R,
phantom: PhantomData<S>
}
impl<P,T,R,S> SerialPort<P,T,R,S>
where
P: 'static + SerialRxTx,
T: 'static + Pin,
R: 'static + Pin,
S: EventSink
{
pub fn using_port_and_pins(port: &'static mut P, tx: &'static mut T, rx: &'static mut R) -> Self {
rx.listen(None);
port.set_write_complete_callback(None);
port.set_read_callback(Some(|byte|{
S::event(OxideEvent::SerialEvent(SerialState::ReadAvailable));
ReadHandlerResult::Buffer(byte)
}));
port.set_error_callback(Some(|error|{
match error {
SerialError::BufferOverflow => {
S::event(OxideEvent::SerialEvent(SerialState::ReadBufferOverflow));
},
SerialError::Break => {
S::event(OxideEvent::SerialEvent(SerialState::BreakDetected));
},
_ => {
S::event(OxideEvent::SerialEvent(SerialState::SerialCommsError));
}
}
}));
port.enable_rxtx(true);
tx.set_mode(PinMode::Output);
rx.set_mode(PinMode::InputFloating);
SerialPort {
port, tx, rx,
phantom: PhantomData::default()
}
}
pub fn mode(self, mode: SerialPortMode) -> Self {
self.tx.set_mode(PinMode::InputFloating);
self.rx.set_mode(PinMode::InputFloating);
self.port.mode(mode);
self.port.enable_rxtx(true);
self.tx.set_mode(PinMode::Output);
self
}
}
impl<P,T,R,S> crate::io::Read for SerialPort<P,T,R,S>
where
P: 'static + SerialRxTx,
T: 'static + Pin,
R: 'static + Pin,
S: EventSink
{
fn read(&mut self, buf: &mut [u8]) -> crate::io::Result<usize> {
todo!()
}
}
impl<P,T,R,S> crate::io::Write for SerialPort<P,T,R,S>
where
P: 'static + SerialRxTx,
T: 'static + Pin,
R: 'static + Pin,
S: EventSink
{
fn write(&mut self, buf: &[u8]) -> crate::io::Result<usize> {
let cnt : usize = 0;
for byte in buf {
self.port.write_u8(*byte);
}
Ok(cnt)
}
fn flush(&mut self) -> crate::io::Result<()> {
self.port.flush();
Ok(())
}
}
impl<P,T,R,S> core::fmt::Write for SerialPort<P,T,R,S>
where
P: 'static + SerialRxTx,
T: 'static + Pin,
R: 'static + Pin,
S: EventSink
{
fn write_str(&mut self, s: &str) -> core::fmt::Result {
let _ignore = crate::io::Write::write(self, s.as_bytes());
Ok(())
}
}