resid/
wave.rs

1// This file is part of resid-rs.
2// Copyright (c) 2017-2019 Sebastian Jastrzebski <sebby2k@gmail.com>. All rights reserved.
3// Portions (c) 2004 Dag Lem <resid@nimrod.no>
4// Licensed under the GPLv3. See LICENSE file in the project root for full license text.
5
6#![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))]
7
8use bit_field::BitField;
9
10use super::data;
11use super::ChipModel;
12
13const ACC_MASK: u32 = 0x00ff_ffff;
14const ACC_BIT19_MASK: u32 = 0x0008_0000;
15const ACC_MSB_MASK: u32 = 0x0080_0000;
16const SHIFT_MASK: u32 = 0x007f_ffff;
17const OUTPUT_MASK: u16 = 0x0fff;
18
19/// A 24 bit accumulator is the basis for waveform generation. FREQ is added to
20/// the lower 16 bits of the accumulator each cycle.
21/// The accumulator is set to zero when TEST is set, and starts counting
22/// when TEST is cleared.
23/// The noise waveform is taken from intermediate bits of a 23 bit shift
24/// register. This register is clocked by bit 19 of the accumulator.
25#[derive(Clone, Copy)]
26pub struct WaveformGenerator {
27    // Configuration
28    frequency: u16,
29    pulse_width: u16,
30    // Control
31    waveform: u8,
32    ring: bool,
33    sync: bool,
34    test: bool,
35    // Runtime State
36    pub acc: u32,
37    pub shift: u32,
38    msb_rising: bool,
39    // Static Data
40    wave_ps: &'static [u8; 4096],
41    wave_pst: &'static [u8; 4096],
42    wave_pt: &'static [u8; 4096],
43    wave_st: &'static [u8; 4096],
44}
45
46pub struct Syncable<T> {
47    pub main: T,
48    pub sync_source: T,
49    pub sync_dest: T,
50}
51
52impl WaveformGenerator {
53    pub fn new(chip_model: ChipModel) -> Self {
54        let (wave_ps, wave_pst, wave_pt, wave_st) = match chip_model {
55            ChipModel::Mos6581 => (
56                &data::WAVE6581_PS,
57                &data::WAVE6581_PST,
58                &data::WAVE6581_PT,
59                &data::WAVE6581_ST,
60            ),
61            ChipModel::Mos8580 => (
62                &data::WAVE8580_PS,
63                &data::WAVE8580_PST,
64                &data::WAVE8580_PT,
65                &data::WAVE8580_ST,
66            ),
67        };
68        let mut waveform = WaveformGenerator {
69            frequency: 0,
70            pulse_width: 0,
71            waveform: 0,
72            ring: false,
73            sync: false,
74            test: false,
75            acc: 0,
76            shift: 0,
77            msb_rising: false,
78            wave_ps,
79            wave_pst,
80            wave_pt,
81            wave_st,
82        };
83        waveform.reset();
84        waveform
85    }
86
87    pub fn get_acc(&self) -> u32 {
88        self.acc
89    }
90
91    pub fn get_control(&self) -> u8 {
92        let mut value = 0u8;
93        value.set_bit(1, self.sync);
94        value.set_bit(2, self.ring);
95        value.set_bit(3, self.test);
96        value | (self.waveform << 4)
97    }
98
99    pub fn get_frequency(&self) -> u16 {
100        self.frequency
101    }
102
103    pub fn get_frequency_hi(&self) -> u8 {
104        (self.frequency >> 8) as u8
105    }
106
107    pub fn get_frequency_lo(&self) -> u8 {
108        (self.frequency & 0x00ff) as u8
109    }
110
111    pub fn get_pulse_width_hi(&self) -> u8 {
112        (self.pulse_width >> 8) as u8
113    }
114
115    pub fn get_pulse_width_lo(&self) -> u8 {
116        (self.pulse_width & 0x00ff) as u8
117    }
118
119    pub fn get_shift(&self) -> u32 {
120        self.shift
121    }
122
123    pub fn get_sync(&self) -> bool {
124        self.sync
125    }
126
127    pub fn is_msb_rising(&self) -> bool {
128        self.msb_rising
129    }
130
131    pub fn set_acc(&mut self, value: u32) {
132        self.acc = value;
133    }
134
135    pub fn set_control(&mut self, value: u8) {
136        self.waveform = (value >> 4) & 0x0f;
137        self.sync = value.get_bit(1);
138        self.ring = value.get_bit(2);
139        let test = value.get_bit(3);
140        if test {
141            // Test bit set.
142            // The accumulator and the shift register are both cleared.
143            // NB! The shift register is not really cleared immediately. It seems like
144            // the individual bits in the shift register start to fade down towards
145            // zero when test is set. All bits reach zero within approximately
146            // $2000 - $4000 cycles.
147            // This is not modeled. There should fortunately be little audible output
148            // from this peculiar behavior.
149            self.acc = 0;
150            self.shift = 0;
151        } else if self.test {
152            // Test bit cleared.
153            // The accumulator starts counting, and the shift register is reset to
154            // the value 0x7ffff8.
155            // NB! The shift register will not actually be set to this exact value if the
156            // shift register bits have not had time to fade to zero.
157            // This is not modeled.
158            self.shift = 0x007f_fff8;
159        }
160        self.test = test;
161    }
162
163    pub fn set_frequency_hi(&mut self, value: u8) {
164        let result = (((value as u16) << 8) & 0xff00) | (self.frequency & 0x00ff);
165        self.frequency = result;
166    }
167
168    pub fn set_frequency_lo(&mut self, value: u8) {
169        let result = (self.frequency & 0xff00) | ((value as u16) & 0x00ff);
170        self.frequency = result;
171    }
172
173    pub fn set_pulse_width_hi(&mut self, value: u8) {
174        let result = (((value as u16) << 8) & 0x0f00) | (self.pulse_width & 0x00ff);
175        self.pulse_width = result;
176    }
177
178    pub fn set_pulse_width_lo(&mut self, value: u8) {
179        let result = (self.pulse_width & 0x0f00) | ((value as u16) & 0x00ff);
180        self.pulse_width = result;
181    }
182
183    #[inline]
184    pub fn clock(&mut self) {
185        // No operation if test bit is set.
186        if !self.test {
187            let acc_prev = self.acc;
188            // Calculate new accumulator value;
189            self.acc = (self.acc + self.frequency as u32) & ACC_MASK;
190            // Check whether the MSB is set high. This is used for synchronization.
191            self.msb_rising = (acc_prev & ACC_MSB_MASK) == 0 && (self.acc & ACC_MSB_MASK) != 0;
192            if (acc_prev & ACC_BIT19_MASK) == 0 && (self.acc & ACC_BIT19_MASK) != 0 {
193                // Shift noise register once for each time accumulator bit 19 is set high.
194                let bit0 = ((self.shift >> 22) ^ (self.shift >> 17)) & 0x01;
195                self.shift = ((self.shift << 1) & SHIFT_MASK) | bit0;
196            }
197        }
198    }
199
200    #[inline]
201    pub fn clock_delta(&mut self, delta: u32) {
202        if !self.test {
203            let acc_prev = self.acc;
204            // Calculate new accumulator value;
205            let mut delta_acc = delta * self.frequency as u32;
206            self.acc = (self.acc + delta_acc) & ACC_MASK;
207            // Check whether the MSB is set high. This is used for synchronization.
208            self.msb_rising = (acc_prev & ACC_MSB_MASK) == 0 && (self.acc & ACC_MSB_MASK) != 0;
209            // Shift noise register once for each time accumulator bit 19 is set high.
210            // Bit 19 is set high each time 2^20 (0x100000) is added to the accumulator.
211            let mut shift_period = 0x0010_0000;
212            while delta_acc != 0 {
213                if delta_acc < shift_period {
214                    shift_period = delta_acc;
215                    // Determine whether bit 19 is set on the last period.
216                    // NB! Requires two's complement integer.
217                    if shift_period <= 0x0008_0000 {
218                        // Check for flip from 0 to 1.
219                        if ((self.acc as i32 - shift_period as i32) & ACC_BIT19_MASK as i32) != 0
220                            || (self.acc & ACC_BIT19_MASK) == 0
221                        {
222                            break;
223                        }
224                    // Check for flip from 0 (to 1 or via 1 to 0) or from 1 via 0 to 1.
225                    } else if ((self.acc as i32 - shift_period as i32) & ACC_BIT19_MASK as i32) != 0
226                        && (self.acc & ACC_BIT19_MASK) == 0
227                    {
228                        break;
229                    }
230                }
231                // Shift the noise/random register.
232                let bit0 = ((self.shift >> 22) ^ (self.shift >> 17)) & 0x01;
233                self.shift = (self.shift << 1) & SHIFT_MASK | bit0;
234                delta_acc -= shift_period;
235            }
236        }
237    }
238
239    /// 12-bit waveform output
240    #[inline]
241    pub fn output(&self, sync_source: Option<&WaveformGenerator>) -> u16 {
242        match self.waveform {
243            0x0 => 0,
244            0x1 => self.output_t(sync_source),
245            0x2 => self.output_s(),
246            0x3 => self.output_st(),
247            0x4 => self.output_p(),
248            0x5 => self.output_pt(sync_source),
249            0x6 => self.output_ps(),
250            0x7 => self.output_pst(),
251            0x8 => self.output_n(),
252            0x9 => 0,
253            0xa => 0,
254            0xb => 0,
255            0xc => 0,
256            0xd => 0,
257            0xe => 0,
258            0xf => 0,
259            _ => panic!("invalid waveform {}", self.waveform),
260        }
261    }
262
263    pub fn reset(&mut self) {
264        self.frequency = 0;
265        self.pulse_width = 0;
266        self.waveform = 0; // NOTE this is not in orig resid
267        self.ring = false;
268        self.sync = false;
269        self.test = false;
270        self.acc = 0;
271        self.shift = 0x007f_fff8;
272        self.msb_rising = false;
273    }
274
275    // -- Output Functions
276
277    /// Noise:
278    /// The noise output is taken from intermediate bits of a 23-bit shift register
279    /// which is clocked by bit 19 of the accumulator.
280    /// NB! The output is actually delayed 2 cycles after bit 19 is set high.
281    /// This is not modeled.
282    ///
283    /// Operation: Calculate EOR result, shift register, set bit 0 = result.
284    ///``` ignore,
285    ///                        ----------------------->---------------------
286    ///                        |                                            |
287    ///                   ----EOR----                                       |
288    ///                   |         |                                       |
289    ///                   2 2 2 1 1 1 1 1 1 1 1 1 1                         |
290    /// Register bits:    2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 <---
291    ///                   |   |       |     |   |       |     |   |
292    /// OSC3 bits  :      7   6       5     4   3       2     1   0
293    /// ```
294    /// Since waveform output is 12 bits the output is left-shifted 4 times.
295    #[inline]
296    fn output_n(&self) -> u16 {
297        (((self.shift & 0x0040_0000) >> 11)
298            | ((self.shift & 0x0010_0000) >> 10)
299            | ((self.shift & 0x0001_0000) >> 7)
300            | ((self.shift & 0x0000_2000) >> 5)
301            | ((self.shift & 0x0000_0800) >> 4)
302            | ((self.shift & 0x0000_0080) >> 1)
303            | ((self.shift & 0x0000_0010) << 1)
304            | ((self.shift & 0x0000_0004) << 2)) as u16
305    }
306
307    /// Pulse:
308    /// The upper 12 bits of the accumulator are used.
309    /// These bits are compared to the pulse width register by a 12 bit digital
310    /// comparator; output is either all one or all zero bits.
311    /// NB! The output is actually delayed one cycle after the compare.
312    /// This is not modeled.
313    ///
314    /// The test bit, when set to one, holds the pulse waveform output at 0xfff
315    /// regardless of the pulse width setting.
316    #[inline]
317    fn output_p(&self) -> u16 {
318        if self.test || ((self.acc >> 12) as u16 >= self.pulse_width) {
319            0x0fff
320        } else {
321            0x0000
322        }
323    }
324
325    /// Sawtooth:
326    /// The output is identical to the upper 12 bits of the accumulator.
327    #[inline]
328    fn output_s(&self) -> u16 {
329        (self.acc >> 12) as u16
330    }
331
332    /// Triangle:
333    /// The upper 12 bits of the accumulator are used.
334    /// The MSB is used to create the falling edge of the triangle by inverting
335    /// the lower 11 bits. The MSB is thrown away and the lower 11 bits are
336    /// left-shifted (half the resolution, full amplitude).
337    /// Ring modulation substitutes the MSB with MSB EOR sync_source MSB.
338    #[inline]
339    fn output_t(&self, sync_source: Option<&WaveformGenerator>) -> u16 {
340        let acc = if self.ring {
341            self.acc ^ sync_source.map(|x| x.acc).unwrap_or(0)
342        } else {
343            self.acc
344        };
345        let msb = acc & ACC_MSB_MASK;
346        let output = if msb != 0 { !self.acc } else { self.acc };
347        (output >> 11) as u16 & OUTPUT_MASK
348    }
349
350    // -- Combined Waveforms
351
352    #[inline]
353    fn output_ps(&self) -> u16 {
354        ((self.wave_ps[self.output_s() as usize] as u16) << 4) & self.output_p()
355    }
356
357    #[inline]
358    fn output_pst(&self) -> u16 {
359        ((self.wave_pst[self.output_s() as usize] as u16) << 4) & self.output_p()
360    }
361
362    #[inline]
363    fn output_pt(&self, sync_source: Option<&WaveformGenerator>) -> u16 {
364        ((self.wave_pt[(self.output_t(sync_source) >> 1) as usize] as u16) << 4) & self.output_p()
365    }
366
367    #[inline]
368    fn output_st(&self) -> u16 {
369        (self.wave_st[self.output_s() as usize] as u16) << 4
370    }
371}
372
373impl Syncable<&'_ WaveformGenerator> {
374    pub fn read_osc(&self) -> u8 {
375        (self.main.output(Some(self.sync_source)) >> 4) as u8
376    }
377}
378
379impl Syncable<&'_ mut WaveformGenerator> {
380    /// Synchronize oscillators.
381    /// This must be done after all the oscillators have been clock()'ed since the
382    /// oscillators operate in parallel.
383    /// Note that the oscillators must be clocked exactly on the cycle when the
384    /// MSB is set high for hard sync to operate correctly. See SID::clock().
385    #[inline]
386    pub fn synchronize(&mut self) {
387        // A special case occurs when a sync source is synced itself on the same
388        // cycle as when its MSB is set high. In this case the destination will
389        // not be synced. This has been verified by sampling OSC3.
390        if self.main.is_msb_rising() {
391            if self.sync_dest.sync {
392                if !(self.main.sync && self.sync_source.is_msb_rising()) {
393                    self.sync_dest.set_acc(0);
394                }
395            }
396        }
397    }
398}