libsidplayfp  1.8.3
WaveformGenerator.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
5  * Copyright 2007-2010 Antti Lankila
6  * Copyright 2004,2010 Dag Lem <resid@nimrod.no>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef WAVEFORMGENERATOR_H
24 #define WAVEFORMGENERATOR_H
25 
26 #include "siddefs-fp.h"
27 #include "array.h"
28 
29 namespace reSIDfp
30 {
31 
87 {
88 private:
89  matrix_t* model_wave;
90 
91  short* wave;
92 
93  // PWout = (PWn/40.95)%
94  int pw;
95 
96  unsigned int shift_register;
97 
99  int shift_register_reset;
100 
102  int shift_pipeline;
103 
104  int ring_msb_mask;
105  int no_noise;
106  int noise_output;
107  int no_noise_or_noise_output;
108  int no_pulse;
109  int pulse_output;
110 
112  int waveform;
113 
114  int floating_output_ttl;
115 
116  int waveform_output;
117 
119  int accumulator;
120 
121  // Fout = (Fn*Fclk/16777216)Hz
122  int freq;
123 
125 
126  bool test;
127  bool sync;
129 
131  bool msb_rising;
132 
133  short dac[4096];
134 
135 private:
136  void clock_shift_register();
137 
138  void write_shift_register();
139 
140  void reset_shift_register();
141 
142  void set_noise_output();
143 
144 public:
145  void setWaveformModels(matrix_t* models);
146 
154  void setChipModel(ChipModel chipModel);
155 
159  void clock();
160 
169  void synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const;
170 
175  model_wave(0),
176  wave(0),
177  pw(0),
178  shift_register(0),
179  shift_register_reset(0),
180  shift_pipeline(0),
181  ring_msb_mask(0),
182  no_noise(0),
183  noise_output(0),
184  no_noise_or_noise_output(no_noise | noise_output),
185  no_pulse(0),
186  pulse_output(0),
187  waveform(0),
188  floating_output_ttl(0),
189  waveform_output(0),
190  accumulator(0),
191  freq(0),
192  test(false),
193  sync(false),
194  msb_rising(false) {}
195 
201  void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
202 
208  void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
209 
218  void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
219 
225  void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
226 
232  void writeCONTROL_REG(unsigned char control);
233 
237  void reset();
238 
246  short output(const WaveformGenerator* ringModulator);
247 
251  unsigned char readOSC() const { return (unsigned char)(waveform_output >> 4); }
252 
256  int readAccumulator() const { return accumulator; }
257 
261  int readFreq() const { return freq; }
262 
266  bool readTest() const { return test; }
267 
271  bool readSync() const { return sync; }
272 };
273 
274 } // namespace reSIDfp
275 
276 #if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP)
277 
278 namespace reSIDfp
279 {
280 
281 RESID_INLINE
283 {
284  if (unlikely(test))
285  {
286  if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
287  {
288  reset_shift_register();
289  }
290 
291  // The test bit sets pulse high.
292  pulse_output = 0xfff;
293  }
294  else
295  {
296  // Calculate new accumulator value;
297  const int accumulator_next = (accumulator + freq) & 0xffffff;
298  const int accumulator_bits_set = ~accumulator & accumulator_next;
299  accumulator = accumulator_next;
300 
301  // Check whether the MSB is set high. This is used for synchronization.
302  msb_rising = (accumulator_bits_set & 0x800000) != 0;
303 
304  // Shift noise register once for each time accumulator bit 19 is set high.
305  // The shift is delayed 2 cycles.
306  if (unlikely((accumulator_bits_set & 0x080000) != 0))
307  {
308  // Pipeline: Detect rising bit, shift phase 1, shift phase 2.
309  shift_pipeline = 2;
310  }
311  else if (unlikely(shift_pipeline) != 0 && --shift_pipeline == 0)
312  {
313  clock_shift_register();
314  }
315  }
316 }
317 
318 RESID_INLINE
319 short WaveformGenerator::output(const WaveformGenerator* ringModulator)
320 {
321  // Set output value.
322  if (likely(waveform != 0))
323  {
324  // The bit masks no_pulse and no_noise are used to achieve branch-free
325  // calculation of the output value.
326  const int ix = (accumulator ^ (ringModulator->accumulator & ring_msb_mask)) >> 12;
327  waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
328 
329  if (unlikely(waveform > 0x8))
330  {
331  // Combined waveforms that include noise
332  // write to the shift register.
333  write_shift_register();
334  }
335  }
336  else
337  {
338  // Age floating DAC input.
339  if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
340  {
341  waveform_output = 0;
342  }
343  }
344 
345  // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
346  // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
347  // results without any branching (and thus without any pipeline stalls).
348  // NB! This expression relies on that the result of a boolean expression
349  // is either 0 or 1, and furthermore requires two's complement integer.
350  // A few more cycles may be saved by storing the pulse width left shifted
351  // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
352  // used as a bit mask on 12 bit values), yielding the expression
353  // -(accumulator >= pw24). However this only results in negligible savings.
354 
355  // The result of the pulse width compare is delayed one cycle.
356  // Push next pulse level into pulse level pipeline.
357  pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
358 
359  // DAC imperfections are emulated by using waveform_output as an index
360  // into a DAC lookup table. readOSC() uses waveform_output directly.
361  return dac[waveform_output];
362 }
363 
364 } // namespace reSIDfp
365 
366 #endif
367 
368 #endif
Definition: array.h:41
Definition: Dac.cpp:25
int readFreq() const
Definition: WaveformGenerator.h:261
void writeCONTROL_REG(unsigned char control)
Definition: WaveformGenerator.cpp:135
void writePW_LO(unsigned char pw_lo)
Definition: WaveformGenerator.h:218
void writeFREQ_LO(unsigned char freq_lo)
Definition: WaveformGenerator.h:201
unsigned char readOSC() const
Definition: WaveformGenerator.h:251
bool readTest() const
Definition: WaveformGenerator.h:266
void writeFREQ_HI(unsigned char freq_hi)
Definition: WaveformGenerator.h:208
bool readSync() const
Definition: WaveformGenerator.h:271
WaveformGenerator()
Definition: WaveformGenerator.h:174
int readAccumulator() const
Definition: WaveformGenerator.h:256
short output(const WaveformGenerator *ringModulator)
Definition: WaveformGenerator.h:319
void clock()
Definition: WaveformGenerator.h:282
void reset()
Definition: WaveformGenerator.cpp:202
void setChipModel(ChipModel chipModel)
Definition: WaveformGenerator.cpp:96
void synchronize(WaveformGenerator *syncDest, const WaveformGenerator *syncSource) const
Definition: WaveformGenerator.cpp:124
void writePW_HI(unsigned char pw_hi)
Definition: WaveformGenerator.h:225
Definition: WaveformGenerator.h:86