1 /*! \file resid/sid.h */
2 
3 //  ---------------------------------------------------------------------------
4 //  This file is part of reSID, a MOS6581 SID emulator engine.
5 //  Copyright (C) 2010  Dag Lem <resid@nimrod.no>
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License as published by
9 //  the Free Software Foundation; either version 2 of the License, or
10 //  (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 //  ---------------------------------------------------------------------------
21 
22 #ifndef RESID_SID_H
23 #define RESID_SID_H
24 
25 #include "resid-config.h"
26 #include "voice.h"
27 #if NEW_8580_FILTER
28 #include "filter8580new.h"
29 #else
30 #include "filter.h"
31 #endif
32 #include "extfilt.h"
33 #include "pot.h"
34 
35 namespace reSID
36 {
37 
38 class SID
39 {
40 public:
41   SID();
42   ~SID();
43 
44   void set_chip_model(chip_model model);
45   void set_voice_mask(reg4 mask);
46   void enable_filter(bool enable);
47   void adjust_filter_bias(double dac_bias);
48   void enable_external_filter(bool enable);
49   bool set_sampling_parameters(double clock_freq, sampling_method method,
50   double sample_freq, double pass_freq = -1,
51   double filter_scale = 0.97);
52   void adjust_sampling_frequency(double sample_freq);
53 
54   void clock();
55   void clock(cycle_count delta_t);
56   int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1);
57   void reset();
58 
59   // Read/write registers.
60   reg8 read(reg8 offset);
61   void write(reg8 offset, reg8 value);
62 
63   // Read/write state.
64   class State
65   {
66   public:
67     State();
68 
69     char sid_register[0x20];
70 
71     reg8 bus_value;
72     cycle_count bus_value_ttl;
73     cycle_count write_pipeline;
74     reg8 write_address;
75     reg4 voice_mask;
76 
77     reg24 accumulator[3];
78     reg24 shift_register[3];
79     cycle_count shift_register_reset[3];
80     cycle_count shift_pipeline[3];
81     reg16 pulse_output[3];
82     cycle_count floating_output_ttl[3];
83 
84     reg16 rate_counter[3];
85     reg16 rate_counter_period[3];
86     reg16 exponential_counter[3];
87     reg16 exponential_counter_period[3];
88     reg8 envelope_counter[3];
89     EnvelopeGenerator::State envelope_state[3];
90     bool hold_zero[3];
91     cycle_count envelope_pipeline[3];
92   };
93 
94   State read_state();
95   void write_state(const State& state);
96 
97   // 16-bit input (EXT IN).
98   void input(short sample);
99 
100   // 16-bit output (AUDIO OUT).
101   short output();
102 
103  protected:
104   static double I0(double x);
105   int clock_fast(cycle_count& delta_t, short* buf, int n, int interleave);
106   int clock_interpolate(cycle_count& delta_t, short* buf, int n, int interleave);
107   int clock_resample(cycle_count& delta_t, short* buf, int n, int interleave);
108   int clock_resample_fastmem(cycle_count& delta_t, short* buf, int n, int interleave);
109   void write();
110 
111   chip_model sid_model;
112   Voice voice[3];
113   Filter filter;
114   ExternalFilter extfilt;
115   Potentiometer potx;
116   Potentiometer poty;
117 
118   reg8 bus_value;
119   cycle_count bus_value_ttl;
120 
121   // The data bus TTL for the selected chip model
122   cycle_count databus_ttl;
123 
124   // Pipeline for writes on the MOS8580.
125   cycle_count write_pipeline;
126   reg8 write_address;
127 
128   double clock_frequency;
129 
130   enum {
131     // Resampling constants.
132     // The error in interpolated lookup is bounded by 1.234/L^2,
133     // while the error in non-interpolated lookup is bounded by
134     // 0.7854/L + 0.4113/L^2, see
135     // http://www-ccrma.stanford.edu/~jos/resample/Choice_Table_Size.html
136     // For a resolution of 16 bits this yields L >= 285 and L >= 51473,
137     // respectively.
138     FIR_N = 125,
139     FIR_RES = 285,
140     FIR_RES_FASTMEM = 51473,
141     FIR_SHIFT = 15,
142 
143     RINGSIZE = 1 << 14,
144     RINGMASK = RINGSIZE - 1,
145 
146     // Fixed point constants (16.16 bits).
147     FIXP_SHIFT = 16,
148     FIXP_MASK = 0xffff
149   };
150 
151   // Sampling variables.
152   sampling_method sampling;
153   cycle_count cycles_per_sample;
154   cycle_count sample_offset;
155   int sample_index;
156   short sample_prev, sample_now;
157   int fir_N;
158   int fir_RES;
159   double fir_beta;
160   double fir_f_cycles_per_sample;
161   double fir_filter_scale;
162 
163   // Ring buffer with overflow for contiguous storage of RINGSIZE samples.
164   short* sample;
165 
166   // FIR_RES filter tables (FIR_N*FIR_RES).
167   short* fir;
168 };
169 
170 
171 // ----------------------------------------------------------------------------
172 // Inline functions.
173 // The following functions are defined inline because they are called every
174 // time a sample is calculated.
175 // ----------------------------------------------------------------------------
176 
177 #if RESID_INLINING || defined(RESID_SID_CC)
178 
179 // ----------------------------------------------------------------------------
180 // Read 16-bit sample from audio output.
181 // ----------------------------------------------------------------------------
182 RESID_INLINE
output()183 short SID::output()
184 {
185   return extfilt.output();
186 }
187 
188 
189 // ----------------------------------------------------------------------------
190 // SID clocking - 1 cycle.
191 // ----------------------------------------------------------------------------
192 RESID_INLINE
clock()193 void SID::clock()
194 {
195   int i;
196 
197   // Clock amplitude modulators.
198   for (i = 0; i < 3; i++) {
199     voice[i].envelope.clock();
200   }
201 
202   // Clock oscillators.
203   for (i = 0; i < 3; i++) {
204     voice[i].wave.clock();
205   }
206 
207   // Synchronize oscillators.
208   for (i = 0; i < 3; i++) {
209     voice[i].wave.synchronize();
210   }
211 
212   // Calculate waveform output.
213   for (i = 0; i < 3; i++) {
214     voice[i].wave.set_waveform_output();
215   }
216 
217   // Clock filter.
218   filter.clock(voice[0].output(), voice[1].output(), voice[2].output());
219 
220   // Clock external filter.
221   extfilt.clock(filter.output());
222 
223   // Pipelined writes on the MOS8580.
224   if (unlikely(write_pipeline)) {
225     write();
226   }
227 
228   // Age bus value.
229   if (unlikely(!--bus_value_ttl)) {
230     bus_value = 0;
231   }
232 }
233 
234 #endif // RESID_INLINING || defined(RESID_SID_CC)
235 
236 } // namespace reSID
237 
238 #endif // not RESID_SID_H
239