resid/
sid.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
6use super::envelope::State as EnvState;
7use super::sampler::{Sampler, SamplingMethod};
8use super::synth::Synth;
9use super::ChipModel;
10
11pub mod reg {
12    pub const FREQLO1: u8 = 0x00;
13    pub const FREQHI1: u8 = 0x01;
14    pub const PWLO1: u8 = 0x02;
15    pub const PWHI1: u8 = 0x03;
16    pub const CR1: u8 = 0x04;
17    pub const AD1: u8 = 0x05;
18    pub const SR1: u8 = 0x06;
19    pub const FREQLO2: u8 = 0x07;
20    pub const FREQHI2: u8 = 0x08;
21    pub const PWLO2: u8 = 0x09;
22    pub const PWHI2: u8 = 0x0a;
23    pub const CR2: u8 = 0x0b;
24    pub const AD2: u8 = 0x0c;
25    pub const SR2: u8 = 0x0d;
26    pub const FREQLO3: u8 = 0x0e;
27    pub const FREQHI3: u8 = 0x0f;
28    pub const PWLO3: u8 = 0x10;
29    pub const PWHI3: u8 = 0x11;
30    pub const CR3: u8 = 0x12;
31    pub const AD3: u8 = 0x13;
32    pub const SR3: u8 = 0x14;
33    pub const FCLO: u8 = 0x15;
34    pub const FCHI: u8 = 0x16;
35    pub const RESFILT: u8 = 0x17;
36    pub const MODVOL: u8 = 0x18;
37    pub const POTX: u8 = 0x19;
38    pub const POTY: u8 = 0x1a;
39    pub const OSC3: u8 = 0x1b;
40    pub const ENV3: u8 = 0x1c;
41}
42
43#[derive(Debug)]
44pub struct State {
45    // Sid
46    pub sid_register: [u8; 32],
47    pub bus_value: u8,
48    pub bus_value_ttl: u32,
49    pub ext_in: i32,
50    // Wave
51    pub accumulator: [u32; 3],
52    pub shift_register: [u32; 3],
53    // Envelope
54    pub envelope_state: [u8; 3],
55    pub envelope_counter: [u8; 3],
56    pub exponential_counter: [u8; 3],
57    pub exponential_counter_period: [u8; 3],
58    pub hold_zero: [u8; 3],
59    pub rate_counter: [u16; 3],
60    pub rate_counter_period: [u16; 3],
61}
62
63#[derive(Clone)]
64pub struct Sid {
65    // Functional Units
66    sampler: Sampler,
67    // Runtime State
68    bus_value: u8,
69    bus_value_ttl: u32,
70}
71
72impl Sid {
73    pub fn new(chip_model: ChipModel) -> Self {
74        let synth = Synth::new(chip_model);
75        let mut sid = Sid {
76            sampler: Sampler::new(synth),
77            bus_value: 0,
78            bus_value_ttl: 0,
79        };
80        sid.set_sampling_parameters(SamplingMethod::Fast, 985_248, 44100);
81        sid
82    }
83
84    pub fn set_sampling_parameters(
85        &mut self,
86        method: SamplingMethod,
87        clock_freq: u32,
88        sample_freq: u32,
89    ) {
90        self.sampler.set_parameters(method, clock_freq, sample_freq);
91    }
92
93    pub fn clock(&mut self) {
94        // Age bus value.
95        if self.bus_value_ttl > 0 {
96            self.bus_value_ttl -= 1;
97            if self.bus_value_ttl == 0 {
98                self.bus_value = 0;
99            }
100        }
101        // Clock synthesizer.
102        self.sampler.synth.clock();
103    }
104
105    pub fn clock_delta(&mut self, delta: u32) {
106        // Age bus value.
107        if self.bus_value_ttl >= delta {
108            self.bus_value_ttl -= delta;
109        } else {
110            self.bus_value_ttl = 0;
111        }
112        if self.bus_value_ttl == 0 {
113            self.bus_value = 0;
114        }
115        // Clock synthesizer.
116        self.sampler.synth.clock_delta(delta);
117    }
118
119    pub fn enable_external_filter(&mut self, enabled: bool) {
120        self.sampler.synth.ext_filter.set_enabled(enabled);
121    }
122
123    pub fn enable_filter(&mut self, enabled: bool) {
124        self.sampler.synth.filter.set_enabled(enabled);
125    }
126
127    pub fn input(&mut self, sample: i32) {
128        // Voice outputs are 20 bits. Scale up to match three voices in order
129        // to facilitate simulation of the MOS8580 "digi boost" hardware hack.
130        self.sampler.synth.ext_in = (sample << 4) * 3;
131    }
132
133    pub fn output(&self) -> i16 {
134        self.sampler.synth.output()
135    }
136
137    pub fn reset(&mut self) {
138        self.sampler.reset();
139        self.bus_value = 0;
140        self.bus_value_ttl = 0;
141    }
142
143    /// SID clocking with audio sampling.
144    /// Fixpoint arithmetics is used.
145    ///
146    /// The example below shows how to clock the SID a specified amount of cycles
147    /// while producing audio output:
148    /// ``` ignore,
149    /// let mut buffer = [0i16; 8192];
150    /// while delta > 0 {
151    ///     let (samples, next_delta) = self.resid.sample(delta, &mut buffer[..], 1);
152    ///     let mut output = self.sound_buffer.lock().unwrap();
153    ///     for i in 0..samples {
154    ///         output.write(buffer[i]);
155    ///     }
156    ///     delta = next_delta;
157    /// }
158    /// ```
159    pub fn sample(&mut self, delta: u32, buffer: &mut [i16], interleave: usize) -> (usize, u32) {
160        self.sampler.clock(delta, buffer, interleave)
161    }
162
163    // -- Device I/O
164
165    pub fn read(&self, reg: u8) -> u8 {
166        self.sampler.synth.read(reg, self.bus_value)
167    }
168
169    pub fn write(&mut self, reg: u8, value: u8) {
170        self.bus_value = value;
171        self.bus_value_ttl = 0x2000;
172        self.sampler.synth.write(reg, value);
173    }
174
175    // -- State
176
177    pub fn read_state(&self) -> State {
178        let mut state = State {
179            sid_register: [0; 32],
180            bus_value: 0,
181            bus_value_ttl: 0,
182            ext_in: 0,
183            accumulator: [0; 3],
184            shift_register: [0; 3],
185            envelope_state: [0; 3],
186            envelope_counter: [0; 3],
187            exponential_counter: [0; 3],
188            exponential_counter_period: [0; 3],
189            hold_zero: [0; 3],
190            rate_counter: [0; 3],
191            rate_counter_period: [0; 3],
192        };
193        for i in 0..3 {
194            let j = i * 7;
195            let wave = &self.sampler.synth.voices[i].wave;
196            let envelope = &self.sampler.synth.voices[i].envelope;
197            state.sid_register[j] = wave.get_frequency_lo();
198            state.sid_register[j + 1] = wave.get_frequency_hi();
199            state.sid_register[j + 2] = wave.get_pulse_width_lo();
200            state.sid_register[j + 3] = wave.get_pulse_width_hi();
201            state.sid_register[j + 4] = wave.get_control() | envelope.get_control();
202            state.sid_register[j + 5] = envelope.get_attack_decay();
203            state.sid_register[j + 6] = envelope.get_sustain_release();
204        }
205        let filter = &self.sampler.synth.filter;
206        state.sid_register[0x15] = filter.get_fc_lo();
207        state.sid_register[0x16] = filter.get_fc_hi();
208        state.sid_register[0x17] = filter.get_res_filt();
209        state.sid_register[0x18] = filter.get_mode_vol();
210        for i in 0x19..0x1d {
211            state.sid_register[i] = self.read(i as u8);
212        }
213        for i in 0x1d..0x20 {
214            state.sid_register[i] = 0;
215        }
216        state.bus_value = self.bus_value;
217        state.bus_value_ttl = self.bus_value_ttl;
218        state.ext_in = self.sampler.synth.ext_in;
219        for i in 0..3 {
220            let wave = &self.sampler.synth.voices[i].wave;
221            let envelope = &self.sampler.synth.voices[i].envelope;
222            state.accumulator[i] = wave.get_acc();
223            state.shift_register[i] = wave.get_shift();
224            state.envelope_state[i] = envelope.state as u8;
225            state.envelope_counter[i] = envelope.envelope_counter;
226            state.exponential_counter[i] = envelope.exponential_counter;
227            state.exponential_counter_period[i] = envelope.exponential_counter_period;
228            state.hold_zero[i] = if envelope.hold_zero { 1 } else { 0 };
229            state.rate_counter[i] = envelope.rate_counter;
230            state.rate_counter_period[i] = envelope.rate_counter_period;
231        }
232        state
233    }
234
235    pub fn write_state(&mut self, state: &State) {
236        for i in 0..0x19 {
237            self.write(i, state.sid_register[i as usize]);
238        }
239        self.bus_value = state.bus_value;
240        self.bus_value_ttl = state.bus_value_ttl;
241        self.sampler.synth.ext_in = state.ext_in;
242        for i in 0..3 {
243            let envelope = &mut self.sampler.synth.voices[i].envelope;
244            self.sampler.synth.voices[i].wave.acc = state.accumulator[i];
245            self.sampler.synth.voices[i].wave.shift = state.shift_register[i];
246            envelope.state = match state.envelope_state[i] {
247                0 => EnvState::Attack,
248                1 => EnvState::DecaySustain,
249                2 => EnvState::Release,
250                _ => panic!("invalid envelope state"),
251            };
252            envelope.envelope_counter = state.envelope_counter[i];
253            envelope.exponential_counter = state.exponential_counter[i];
254            envelope.exponential_counter_period = state.exponential_counter_period[i];
255            envelope.hold_zero = state.hold_zero[i] != 0;
256            envelope.rate_counter = state.rate_counter[i];
257            envelope.rate_counter_period = state.rate_counter_period[i];
258        }
259    }
260}