use super::clock::Ts;
use super::pio::PioDevice;
#[allow(unused_imports)]
use log::{error, warn, info, debug, trace, Level};
pub trait PioSink {
fn flush(&mut self, data: u8) -> bool;
}
pub trait PioStream {
fn slurp(&mut self) -> Option<u8>;
}
pub struct PioInput<T> {
source: T,
ready: bool
}
pub struct PioOutput<T> {
sink: T,
pending: Option<u8>
}
impl<T: PioStream> PioInput<T> {
pub fn new(source: T) -> PioInput<T> {
PioInput { source, ready: false }
}
pub fn into_inner(self) -> T {
self.source
}
}
impl<T: PioSink> PioOutput<T> {
pub fn new(sink: T) -> PioOutput<T> {
PioOutput { sink, pending: None }
}
pub fn into_inner(self) -> T {
self.sink
}
}
impl<T: PioStream> PioDevice for PioInput<T> {
type Timestamp = Ts;
fn set_floating_bus(&mut self, _ts: Self::Timestamp) {
self.ready = true;
}
fn set_bus_data(&mut self, _data: u8, _ts: Self::Timestamp) {
self.ready = false;
}
fn ready(&mut self, _ts: Self::Timestamp) {
self.ready = true;
}
fn try_sample_data(&mut self, _ts: Self::Timestamp) -> Option<u8> {
if self.ready {
if let Some(data) = self.source.slurp() {
self.ready = false;
return Some(data)
}
}
None
}
}
impl<T: PioSink> PioDevice for PioOutput<T> {
type Timestamp = Ts;
fn set_floating_bus(&mut self, _ts: Self::Timestamp) {
self.pending = None;
}
fn set_bus_data(&mut self, _data: u8, _ts: Self::Timestamp) {}
fn ready_with_data(&mut self, data: u8, _ts: Self::Timestamp) {
if !self.sink.flush(data) {
self.pending = Some(data);
}
}
fn was_strobe(&mut self, _ts: Self::Timestamp) -> bool {
if let Some(data) = self.pending.take() {
if !self.sink.flush(data) {
self.pending = Some(data);
return false;
}
}
true
}
}