spectrusty_peripherals/
parallel.rs1use std::io;
11
12use spectrusty_core::clock::{TimestampOps, FTs};
13
14#[cfg(feature = "snapshot")]
15use serde::{Serialize, Deserialize};
16
17pub trait ParallelPortDevice {
24 type Timestamp: Sized;
25 fn write_data(&mut self, data: u8, timestamp: Self::Timestamp);
27 fn write_strobe(&mut self, strobe: bool, timestamp: Self::Timestamp) -> bool;
34 fn poll_busy(&mut self) -> bool;
37 fn next_frame(&mut self, eof_timestamp: Self::Timestamp);
39}
40
41#[derive(Default, Clone, Debug)]
43#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
44#[cfg_attr(feature = "snapshot", serde(rename_all = "camelCase"))]
45pub struct ParallelPortWriter<T, W> {
46 #[cfg_attr(feature = "snapshot", serde(default))]
47 pub writer: W,
48 busy: bool,
49 data: u8,
50 last_ts: T,
51}
52
53#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
55#[cfg_attr(feature = "snapshot", derive(Serialize, Deserialize))]
56pub struct NullParallelPort<T>(core::marker::PhantomData<T>);
57
58const STROBE_TSTATES_MAX: FTs = 10000;
59
60impl<V, W: io::Write> ParallelPortWriter<V, W> {
61 fn write_byte_to_writer(&mut self) -> bool {
62 let buf = core::slice::from_ref(&self.data);
63 loop {
64 return match self.writer.write(buf) {
65 Ok(0) => false,
66 Ok(..) => true,
67 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
68 Err(e) => panic!("an error occured while writing {}", e)
69 }
70 }
71 }
72}
73
74impl<T: TimestampOps, W: io::Write> ParallelPortDevice for ParallelPortWriter<T, W> {
75 type Timestamp = T;
76
77 fn write_data(&mut self, data: u8, timestamp: Self::Timestamp) {
78 self.data = data;
79 self.last_ts = timestamp;
80 }
81
82 fn write_strobe(&mut self, strobe: bool, timestamp: Self::Timestamp) -> bool {
83 if strobe {}
84 else if timestamp.diff_from(self.last_ts) < STROBE_TSTATES_MAX {
85 self.busy = !self.write_byte_to_writer();
86 self.last_ts = T::min_value();
87 }
88 else {
89 }
91 self.busy
92 }
93
94 fn poll_busy(&mut self) -> bool {
95 if self.busy {
96 self.busy = !self.write_byte_to_writer();
97 }
98 self.busy
99 }
100
101 fn next_frame(&mut self, eof_timestamp: T) {
102 self.last_ts = self.last_ts.saturating_sub(eof_timestamp);
103 }
104}
105
106impl<T> ParallelPortDevice for NullParallelPort<T> {
107 type Timestamp = T;
108
109 #[inline(always)]
110 fn write_data(&mut self, _data: u8, _timestamp: Self::Timestamp) {}
111 #[inline(always)]
112 fn write_strobe(&mut self, _strobe: bool, _timestamp: Self::Timestamp) -> bool {
113 false
114 }
115 #[inline(always)]
116 fn poll_busy(&mut self) -> bool {
117 false
118 }
119 #[inline(always)]
120 fn next_frame(&mut self, _eof_timestamp: Self::Timestamp) {}
121}