spectrusty_formats/tap/pulse/
encoding.rs

1/*
2    Copyright (C) 2020-2022  Rafal Michalski
3
4    This file is part of SPECTRUSTY, a Rust library for building emulators.
5
6    For the full copyright notice, see the lib.rs file.
7*/
8use core::num::NonZeroU32;
9use std::io::{Error, Read};
10use super::consts::*;
11
12/// The current state of the [ReadEncPulseIter].
13#[derive(Debug)]
14pub enum PulseIterState {
15    /// Emitting lead pulses.
16    Lead{
17        /// How many pulses left to the end of this lead.
18        countdown: u16
19    },
20    /// Emitting the 1st sync pulse.
21    Sync1,
22    /// Emitting the 2nd sync pulse.
23    Sync2,
24    /// Emitting data pulses.
25    Data{
26        /// A current byte.
27        /// The highest bit determines the last (`pulse` is odd) or next (`pulse` is even) pulse being emitted.
28        current: u8,
29        /// A pulse counter for the current byte.
30        /// There are two pulses per each bit (16 pulses per byte).
31        pulse: u8 },
32    /// Emitting is done.
33    Done,
34    /// There was an error from an underlying reader.
35    Error(Error)
36}
37
38/// Encodes data read from an underlying reader as *TAPE* T-state pulse intervals via an [Iterator] interface.
39///
40/// The timing of the pulses matches those expected by ZX Spectrum's ROM loading routines.
41///
42/// After invoking [ReadEncPulseIter::reset] or [ReadEncPulseIter::new] the first byte is read and checked
43/// to determine the duration of the *LEAD PULSE* signal. If it's less than 128 the number of 
44/// generated lead pulses is [LEAD_PULSES_HEAD]. Otherwise, it's [LEAD_PULSES_DATA].
45///
46/// After the lead pulses, two synchronization pulses are being emitted following by data pulses
47/// for each byte read including the initial flag byte.
48///
49/// This iterator may be used to feed pulses to the `EAR IN` buffer of the ZX Spectrum emulator
50/// (e.g. via [EarIn::feed_ear_in][spectrusty_core::chip::EarIn::feed_ear_in])
51/// or to produce sound with a help of [Bandwidth-Limited Pulse Buffer][spectrusty_core::audio::Blep].
52///
53/// Best used with [tap][crate::tap] utilities.
54#[derive(Debug)]
55pub struct ReadEncPulseIter<R> {
56    rd: R,
57    state: PulseIterState,
58    flag: u8,
59}
60
61impl PulseIterState {
62    /// Returns an error from the underlying reader if there was one.
63    pub fn err(&self) -> Option<&Error> {
64        match self {
65            PulseIterState::Error(ref error) => Some(error),
66            _ => None
67        }
68    }
69    /// Returns `true` if there are no more pulses to emit or there
70    /// was an error while reading bytes.
71    pub fn is_done(&self) -> bool {
72        matches!(self, PulseIterState::Done|PulseIterState::Error(..))
73    }
74    /// Returns `true` if emitting lead pulses.
75    pub fn is_lead(&self) -> bool {
76        matches!(self, PulseIterState::Lead {..})
77    }
78    /// Returns `true` if emitting data pulses.
79    pub fn is_data(&self) -> bool {
80        matches!(self, PulseIterState::Data {..})
81    }
82    /// Returns `true` if emitting sync1 pulse.
83    pub fn is_sync1(&self) -> bool {
84        matches!(self, PulseIterState::Sync1)
85    }
86    /// Returns `true` if emitting sync2 pulse.
87    pub fn is_sync2(&self) -> bool {
88        matches!(self, PulseIterState::Sync2)
89    }
90}
91
92impl<R> ReadEncPulseIter<R> {
93    /// Returns a reference to the current state.
94    pub fn state(&self) -> &PulseIterState {
95        &self.state
96    }
97    /// Returns a flag byte.
98    pub fn flag(&self) -> u8 {
99        self.flag
100    }
101    /// Returns an error from the underlying reader if there was one.
102    pub fn err(&self) -> Option<&Error> {
103        self.state.err()
104    }
105    /// Returns `true` if there are no more pulses to emit or there
106    /// was an error while bytes were read.
107    pub fn is_done(&self) -> bool {
108        self.state.is_done()
109    }
110    /// Returns a mutable reference to the inner reader.
111    pub fn get_mut(&mut self) -> &mut R {
112        &mut self.rd
113    }
114    /// Returns a shared reference to the inner reader.
115    pub fn get_ref(&self) -> &R {
116        &self.rd
117    }
118    /// Returns the underlying reader.
119    pub fn into_inner(self) -> R {
120        self.rd
121    }
122    /// Allows to manually assign a `state` and a `flag`.
123    /// Can be used to deserialize ReadEncPulseIter.
124    pub fn with_state_and_flag(mut self, state: PulseIterState, flag: u8) -> Self {
125        self.state = state;
126        self.flag = flag;
127        self
128    }
129}
130
131impl<R: Read> ReadEncPulseIter<R> {
132    /// Creates a new `ReadEncPulseIter` from a given [Reader][Read].
133    pub fn new(rd: R) -> Self {
134        let mut epi = ReadEncPulseIter { rd, state: PulseIterState::Done, flag: 0 };
135        epi.reset();
136        epi
137    }
138    /// Resets the state of the iterator.
139    ///
140    /// The next byte read from the inner reader is interpreted as a flag byte to determine
141    /// the number of lead pulses. In this instance the `state` becomes [PulseIterState::Lead].
142    ///
143    /// If there are no more bytes to be read the `state` becomes [PulseIterState::Done].
144    ///
145    /// In case of an error while reading from the underlying reader the `state` becomes [PulseIterState::Error].
146    pub fn reset(&mut self) {
147        let (flag, state) = match self.rd.by_ref().bytes().next() {
148            Some(Ok(flag)) => (flag, PulseIterState::Lead {
149                countdown: if flag & 0x80 == 0 {
150                    LEAD_PULSES_HEAD
151                } else {
152                    LEAD_PULSES_DATA
153                }
154            }),
155            Some(Err(error)) => (0, PulseIterState::Error(error)),
156            None => (0, PulseIterState::Done)
157        };
158        self.flag = flag;
159        self.state = state;
160    }
161    /// Attempts to set the state of the iterator as [PulseIterState::Data] from the next byte.
162    ///
163    /// The next byte read from the inner reader is interpreted as a data byte.
164    /// In this instance, the `state` becomes [PulseIterState::Data].
165    ///
166    /// If there are no more bytes to be read the `state` becomes [PulseIterState::Done].
167    ///
168    /// In case of an error while reading from the underlying reader the `state` becomes [PulseIterState::Error].
169    pub fn data_from_next(&mut self) {
170        self.state = match self.rd.by_ref().bytes().next() {
171            Some(Ok(current)) => PulseIterState::Data { current, pulse: 0 },
172            Some(Err(error)) => PulseIterState::Error(error),
173            None => PulseIterState::Done
174        };
175    }
176}
177
178impl<R: Read> Iterator for ReadEncPulseIter<R> {
179    type Item = NonZeroU32;
180    fn next(&mut self) -> Option<NonZeroU32> {
181        match self.state {
182            PulseIterState::Lead {ref mut countdown} => {
183                match *countdown - 1 {
184                    0 => {
185                        self.state = PulseIterState::Sync1
186                    }
187                    res => {
188                        *countdown = res
189                    }
190                }
191                Some(LEAD_PULSE_LENGTH)
192            }
193            PulseIterState::Sync1 => {
194                self.state = PulseIterState::Sync2;
195                Some(SYNC_PULSE1_LENGTH)
196            }
197            PulseIterState::Sync2 => {
198                self.state = PulseIterState::Data { current: self.flag, pulse: 0 };
199                Some(SYNC_PULSE2_LENGTH)
200            }
201            PulseIterState::Data { ref mut current, ref mut pulse } => {
202                let bit_one: bool = *current & 0x80 != 0;
203                if *pulse == 15 {
204                    self.state = match self.rd.by_ref().bytes().next() {
205                        Some(Ok(current)) => PulseIterState::Data { current, pulse: 0 },
206                        Some(Err(error)) => PulseIterState::Error(error),
207                        None => PulseIterState::Done
208                    };
209                }
210                else {
211                    if *pulse & 1 == 1 {
212                        *current = current.rotate_left(1);
213                    }
214                    *pulse += 1;
215                }
216                Some(if bit_one { ONE_PULSE_LENGTH } else { ZERO_PULSE_LENGTH })
217            }
218            _ => None
219        }
220    }
221}
222
223
224#[cfg(test)]
225mod tests {
226    use super::*;
227    use std::io::Cursor;
228
229    #[test]
230    fn read_enc_pulse_iter_works() {
231        let data = [0xFF, 0xA5, 0x00];
232        let mut iter = ReadEncPulseIter::new(Cursor::new(data));
233        assert_eq!(false, iter.is_done());
234        for delta in iter.by_ref().take(LEAD_PULSES_DATA as usize) {
235            assert_eq!(LEAD_PULSE_LENGTH, delta);
236        }
237        assert_eq!(false, iter.is_done());
238        assert_eq!(Some(SYNC_PULSE1_LENGTH), iter.next());
239        assert_eq!(Some(SYNC_PULSE2_LENGTH), iter.next());
240        assert_eq!(false, iter.is_done());
241        assert_eq!(vec![
242            ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, 
243            ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, 
244            ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, 
245            ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, 
246
247            ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH,
248            ONE_PULSE_LENGTH, ONE_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH,
249            ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH,
250            ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ONE_PULSE_LENGTH, ONE_PULSE_LENGTH,
251
252            ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, 
253            ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, 
254            ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, 
255            ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, ZERO_PULSE_LENGTH, 
256        ], iter.by_ref().collect::<Vec<_>>());
257        assert_eq!(true, iter.is_done());
258
259        let data = [0x00];
260        let mut iter = ReadEncPulseIter::new(Cursor::new(data));
261        assert_eq!(false, iter.is_done());
262        for delta in iter.by_ref().take(LEAD_PULSES_HEAD as usize) {
263            assert_eq!(LEAD_PULSE_LENGTH, delta);
264        }
265        assert_eq!(false, iter.is_done());
266        assert_eq!(Some(SYNC_PULSE1_LENGTH), iter.next());
267        assert_eq!(Some(SYNC_PULSE2_LENGTH), iter.next());
268        assert_eq!(false, iter.is_done());
269        assert_eq!(vec![ZERO_PULSE_LENGTH; 16], iter.by_ref().collect::<Vec<_>>());
270        assert_eq!(true, iter.is_done());
271
272        let mut iter = ReadEncPulseIter::new(Cursor::new([]));
273        assert_eq!(true, iter.is_done());
274        assert_eq!(None, iter.next());
275    }
276}