spectrusty_formats/tap/pulse/
decoding.rs1use core::num::NonZeroU32;
9use core::slice;
10use std::io::{Result, Write};
11
12use super::consts::*;
13
14const SYNC_PULSE_TOLERANCE: u32 = (SYNC_PULSE2_LENGTH.get() - SYNC_PULSE1_LENGTH.get())/2;
15const SYNC_PULSE1_MIN: u32 = SYNC_PULSE1_LENGTH.get() - SYNC_PULSE_TOLERANCE;
16const SYNC_PULSE1_MAX: u32 = SYNC_PULSE1_LENGTH.get() + SYNC_PULSE_TOLERANCE - 1;
17const SYNC_PULSE2_MIN: u32 = SYNC_PULSE2_LENGTH.get() - SYNC_PULSE_TOLERANCE;
18const SYNC_PULSE2_MAX: u32 = SYNC_PULSE2_LENGTH.get() + SYNC_PULSE_TOLERANCE - 1;
19const LEAD_PULSE_TOLERANCE: u32 = 250;
20const LEAD_PULSE_MIN: u32 = LEAD_PULSE_LENGTH.get() - LEAD_PULSE_TOLERANCE;
21const LEAD_PULSE_MAX: u32 = LEAD_PULSE_LENGTH.get() + LEAD_PULSE_TOLERANCE - 1;
22const DATA_PULSE_TOLERANCE: u32 = 250;
23const DATA_PULSE_MIN: u32 = ZERO_PULSE_LENGTH.get() - DATA_PULSE_TOLERANCE;
24const DATA_PULSE_MAX: u32 = ONE_PULSE_LENGTH.get() + DATA_PULSE_TOLERANCE - 1;
25const DATA_PULSE_THRESHOLD: u32 = (ZERO_PULSE_LENGTH.get() + ONE_PULSE_LENGTH.get())/2;
26const MIN_LEAD_COUNT: u32 = 16;
27
28#[derive(Clone, Copy, Debug, PartialEq, Eq)]
30pub enum PulseDecodeState {
31 Idle,
33 Lead {
35 counter: u32
36 },
37 Sync1,
39 Sync2,
41 Data{
43 current: u8,
45 pulse: u8,
47 written: u32
49 },
50}
51
52#[derive(Debug)]
68pub struct PulseDecodeWriter<W> {
69 state: PulseDecodeState,
70 wr: W,
71}
72
73impl PulseDecodeState {
74 pub fn is_idle(&self) -> bool {
76 matches!(self, PulseDecodeState::Idle)
77 }
78 pub fn is_lead(&self) -> bool {
80 matches!(self, PulseDecodeState::Lead {..})
81 }
82 pub fn is_data(&self) -> bool {
84 matches!(self, PulseDecodeState::Data {..})
85 }
86 pub fn is_sync1(&self) -> bool {
88 matches!(self, PulseDecodeState::Sync1)
89 }
90 pub fn is_sync2(&self) -> bool {
92 matches!(self, PulseDecodeState::Sync2)
93 }
94}
95
96impl<W> PulseDecodeWriter<W> {
97 pub fn reset(&mut self) {
101 self.state = PulseDecodeState::Idle;
102 }
103 pub fn is_idle(&self) -> bool {
105 self.state.is_idle()
106 }
107 pub fn into_inner(self) -> W {
109 self.wr
110 }
111 pub fn state(&self) -> PulseDecodeState {
113 self.state
114 }
115 pub fn get_mut(&mut self) -> &mut W {
117 &mut self.wr
118 }
119 pub fn get_ref(&self) -> &W {
121 &self.wr
122 }
123 pub fn data_size(&self) -> Option<NonZeroU32> {
126 NonZeroU32::new(if let PulseDecodeState::Data { written, .. } = self.state {
127 written
128 }
129 else {
130 0
131 })
132 }
133 pub fn with_state(mut self, state: PulseDecodeState) -> Self {
136 self.state = state;
137 self
138 }
139}
140
141impl<W: Write> PulseDecodeWriter<W> {
142 pub fn new(wr: W) -> Self {
144 PulseDecodeWriter { state: PulseDecodeState::Idle, wr }
145 }
146 pub fn end(&mut self) -> Result<Option<NonZeroU32>> {
156 let res = if let PulseDecodeState::Data { mut current, pulse, written } = self.state {
157 NonZeroU32::new(if pulse <= 1 {
158 written
159 }
160 else {
161 if pulse & 1 == 1 {
162 current &= !1;
163 }
164 current <<= (16 - (pulse & 15)) >> 1;
165 self.write_byte(current)?;
166 written + 1
167 })
168 }
169 else {
170 None
171 };
172 self.state = PulseDecodeState::Idle;
173 Ok(res)
174 }
175 pub fn write_decoded_pulses<I>(&mut self, iter: I) -> Result<Option<NonZeroU32>>
193 where I: Iterator<Item=NonZeroU32>
194 {
195 let mut iter = iter.peekable();
196 if iter.peek().is_none() {
197 return self.end(); }
199
200 for delta in iter {
201 match self.state {
202 PulseDecodeState::Idle => {
203 if let LEAD_PULSE_MIN..=LEAD_PULSE_MAX = delta.get() {
204 self.state = PulseDecodeState::Lead { counter: 1 };
205 }
206 }
207 PulseDecodeState::Lead { counter } => match delta.get() {
208 SYNC_PULSE1_MIN..=SYNC_PULSE1_MAX if counter >= MIN_LEAD_COUNT => {
209 self.state = PulseDecodeState::Sync1;
210 }
211 LEAD_PULSE_MIN..=LEAD_PULSE_MAX => {
212 self.state = PulseDecodeState::Lead { counter: counter.saturating_add(1) };
213 }
214 _ => { self.state = PulseDecodeState::Idle },
215 }
216 PulseDecodeState::Sync1 => match delta.get() {
217 SYNC_PULSE2_MIN..=SYNC_PULSE2_MAX => {
218 self.state = PulseDecodeState::Sync2;
219 }
220 _ => { self.state = PulseDecodeState::Idle },
221 }
222 PulseDecodeState::Sync2 => match delta.get() {
223 delta @ DATA_PULSE_MIN..=DATA_PULSE_MAX => {
224 let current = (delta > DATA_PULSE_THRESHOLD) as u8;
225 self.state = PulseDecodeState::Data { current, pulse: 1, written: 0 }
226 }
227 _ => { self.state = PulseDecodeState::Idle },
228 }
229 PulseDecodeState::Data { current, pulse, written } => match delta.get() {
230 delta @ DATA_PULSE_MIN..=DATA_PULSE_MAX => {
231 let bit = (delta > DATA_PULSE_THRESHOLD) as u8;
232 let current = if pulse & 1 == 1 {
233 if (current ^ bit) & 1 == 1 {
234 return self.end();
235 }
236 if pulse == 15 {
237 self.state = PulseDecodeState::Data { current: 0, pulse: 0, written: written + 1 };
238 self.write_byte(current)?;
239 continue;
240 }
241 current
242 }
243 else {
244 (current << 1) | bit
245 };
246 self.state = PulseDecodeState::Data { current, pulse: pulse + 1, written }
247 }
248 _ => return self.end()
249 }
250 }
251 }
252 Ok(None)
253 }
254
255 #[inline]
256 fn write_byte(&mut self, byte: u8) -> Result<()> {
257 if let Err(e) = self.wr.write_all(slice::from_ref(&byte)) {
259 self.state = PulseDecodeState::Idle;
260 return Err(e);
261 }
262 Ok(())
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269 use std::io::Cursor;
270
271 #[test]
272 fn write_mic_works() {
273 let wr = Cursor::new(Vec::new());
274 let mut mpw = PulseDecodeWriter::new(wr);
275 let pulses = [];
276 assert_eq!(PulseDecodeState::Idle, mpw.state());
277 assert_eq!(None, mpw.write_decoded_pulses(&mut pulses.iter().copied()).unwrap());
278 assert_eq!(PulseDecodeState::Idle, mpw.state());
279 assert_eq!(None, mpw.data_size());
280 let pulses = [PAUSE_PULSE_LENGTH, LEAD_PULSE_LENGTH];
281 assert_eq!(None, mpw.write_decoded_pulses(&mut pulses.iter().copied()).unwrap());
282 assert_eq!(PulseDecodeState::Lead {counter:1} , mpw.state());
283 assert_eq!(None, mpw.data_size());
284 let pulses = vec![LEAD_PULSE_LENGTH;LEAD_PULSES_HEAD as usize];
285 assert_eq!(None, mpw.write_decoded_pulses(&mut pulses.into_iter()).unwrap());
286 assert_eq!(PulseDecodeState::Lead {counter:LEAD_PULSES_HEAD as u32 + 1} , mpw.state());
287 assert_eq!(None, mpw.data_size());
288 let pulses = [SYNC_PULSE1_LENGTH, SYNC_PULSE2_LENGTH,
289 ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH,
290 ONE_PULSE_LENGTH, ONE_PULSE_LENGTH];
291 assert_eq!(None, mpw.write_decoded_pulses(&mut pulses.iter().copied()).unwrap());
292 assert_eq!(PulseDecodeState::Data {current: 0b0000_0001, pulse: 4, written: 0} , mpw.state());
293 assert_eq!(None, mpw.data_size());
294 assert_eq!(0, mpw.get_ref().position());
295 let pulses = [ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH,
296 ONE_PULSE_LENGTH, ONE_PULSE_LENGTH,
297 ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH,
298 ONE_PULSE_LENGTH, ONE_PULSE_LENGTH,
299 ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH,
300 ONE_PULSE_LENGTH, ONE_PULSE_LENGTH];
301 assert_eq!(None, mpw.write_decoded_pulses(&mut pulses.iter().copied()).unwrap());
302 assert_eq!(PulseDecodeState::Data {current: 0, pulse: 0, written: 1} , mpw.state());
303 assert_eq!(NonZeroU32::new(1), mpw.data_size());
304 assert_eq!(1, mpw.get_ref().position());
305 assert_eq!(&[0b0101_0101], &mpw.get_ref().get_ref()[..]);
306 assert_eq!(NonZeroU32::new(1), mpw.end().unwrap());
307 assert_eq!(PulseDecodeState::Idle, mpw.state());
308 assert_eq!(None, mpw.data_size());
309 }
310
311 #[test]
312 fn write_mic_missing_bits_works() {
313 let wr = Cursor::new(Vec::new());
314 let mut mpw = PulseDecodeWriter::new(wr);
315 let pulses = vec![LEAD_PULSE_LENGTH;LEAD_PULSES_DATA as usize];
316 assert_eq!(None, mpw.write_decoded_pulses(&mut pulses.into_iter()).unwrap());
317 assert_eq!(PulseDecodeState::Lead {counter:LEAD_PULSES_DATA as u32} , mpw.state());
318 assert_eq!(None, mpw.data_size());
319 let pulses = [SYNC_PULSE1_LENGTH, SYNC_PULSE2_LENGTH,
320 ONE_PULSE_LENGTH, ONE_PULSE_LENGTH,
321 ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH,
322 ONE_PULSE_LENGTH];
323 assert_eq!(None, mpw.write_decoded_pulses(&mut pulses.iter().copied()).unwrap());
324 assert_eq!(PulseDecodeState::Data {current: 0b0000_0101, pulse: 5, written: 0} , mpw.state());
325 assert_eq!(None, mpw.data_size());
326 assert_eq!(NonZeroU32::new(1), mpw.end().unwrap());
327 assert_eq!(1, mpw.get_ref().position());
328 assert_eq!(&[0b1000_0000], &mpw.get_ref().get_ref()[..]);
329 assert_eq!(PulseDecodeState::Idle, mpw.state());
330 assert_eq!(None, mpw.data_size());
331 }
332}