libsidplayfp  2.0.2
WaveformGenerator.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2016 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 #include "sidcxx11.h"
30 
31 namespace reSIDfp
32 {
33 
87 {
88 private:
89  matrix_t* model_wave;
90 
91  short* wave;
92 
93  // PWout = (PWn/40.95)%
94  unsigned int pw;
95 
96  unsigned int shift_register;
97 
99  int shift_pipeline;
100 
101  unsigned int ring_msb_mask;
102  unsigned int no_noise;
103  unsigned int noise_output;
104  unsigned int no_noise_or_noise_output;
105  unsigned int no_pulse;
106  unsigned int pulse_output;
107 
109  unsigned int waveform;
110 
111  int floating_output_ttl;
112 
113  unsigned int waveform_output;
114 
116  unsigned int accumulator;
117 
118  // Fout = (Fn*Fclk/16777216)Hz
119  unsigned int freq;
120 
121  // 8580 tri/saw pipeline
122  unsigned int tri_saw_pipeline;
123  unsigned int osc3;
124 
126  int shift_register_reset;
127 
129  int model_shift_register_reset;
130 
132 
133  bool test;
134  bool sync;
136 
138  bool msb_rising;
139 
140  bool is6581;
141 
142  float dac[4096];
143 
144 private:
145  void clock_shift_register(unsigned int bit0);
146 
147  unsigned int get_noise_writeback();
148 
149  void write_shift_register();
150 
151  void reset_shift_register();
152 
153  void set_noise_output();
154 
155 public:
156  void setWaveformModels(matrix_t* models);
157 
165  void setChipModel(ChipModel chipModel);
166 
170  void clock();
171 
180  void synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const;
181 
186  model_wave(nullptr),
187  wave(nullptr),
188  pw(0),
189  shift_register(0),
190  shift_pipeline(0),
191  ring_msb_mask(0),
192  no_noise(0),
193  noise_output(0),
194  no_noise_or_noise_output(no_noise | noise_output),
195  no_pulse(0),
196  pulse_output(0),
197  waveform(0),
198  floating_output_ttl(0),
199  waveform_output(0),
200  accumulator(0x555555), // Accumulator's even bits are high on powerup
201  freq(0),
202  tri_saw_pipeline(0x555),
203  osc3(0),
204  shift_register_reset(0),
205  test(false),
206  sync(false),
207  msb_rising(false),
208  is6581(true) {}
209 
215  void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
216 
222  void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
223 
229  void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
230 
236  void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
237 
243  void writeCONTROL_REG(unsigned char control);
244 
248  void reset();
249 
256  float output(const WaveformGenerator* ringModulator);
257 
261  unsigned char readOSC() const { return static_cast<unsigned char>(osc3 >> 4); }
262 
266  unsigned int readAccumulator() const { return accumulator; }
267 
271  unsigned int readFreq() const { return freq; }
272 
276  bool readTest() const { return test; }
277 
281  bool readSync() const { return sync; }
282 };
283 
284 } // namespace reSIDfp
285 
286 #if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP)
287 
288 namespace reSIDfp
289 {
290 
291 RESID_INLINE
293 {
294  if (unlikely(test))
295  {
296  if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
297  {
298  reset_shift_register();
299 
300  // New noise waveform output.
301  set_noise_output();
302  }
303 
304  // The test bit sets pulse high.
305  pulse_output = 0xfff;
306  }
307  else
308  {
309  // Calculate new accumulator value;
310  const unsigned int accumulator_old = accumulator;
311  accumulator = (accumulator + freq) & 0xffffff;
312 
313  // Check which bit have changed
314  const unsigned int accumulator_bits_set = ~accumulator_old & accumulator;
315 
316  // Check whether the MSB is set high. This is used for synchronization.
317  msb_rising = (accumulator_bits_set & 0x800000) != 0;
318 
319  // Shift noise register once for each time accumulator bit 19 is set high.
320  // The shift is delayed 2 cycles.
321  if (unlikely((accumulator_bits_set & 0x080000) != 0))
322  {
323  // Pipeline: Detect rising bit, shift phase 1, shift phase 2.
324  shift_pipeline = 2;
325  }
326  else if (unlikely(shift_pipeline != 0) && --shift_pipeline == 0)
327  {
328  // bit0 = (bit22 | test) ^ bit17
329  clock_shift_register(((shift_register << 22) ^ (shift_register << 17)) & (1 << 22));
330  }
331  }
332 }
333 
334 RESID_INLINE
335 float WaveformGenerator::output(const WaveformGenerator* ringModulator)
336 {
337  // Set output value.
338  if (likely(waveform != 0))
339  {
340  const unsigned int ix = (accumulator ^ (~ringModulator->accumulator & ring_msb_mask)) >> 12;
341 
342  // The bit masks no_pulse and no_noise are used to achieve branch-free
343  // calculation of the output value.
344  waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
345 
346  // Triangle/Sawtooth output is delayed half cycle on 8580.
347  // This will appear as a one cycle delay on OSC3 as it is latched first phase of the clock.
348  if ((waveform & 3) && !is6581)
349  {
350  osc3 = tri_saw_pipeline & (no_pulse | pulse_output) & no_noise_or_noise_output;
351  tri_saw_pipeline = wave[ix];
352  }
353  else
354  {
355  osc3 = waveform_output;
356  }
357 
358  // In the 6581 the top bit of the accumulator may be driven low by combined waveforms
359  // when the sawtooth is selected
360  // FIXME doesn't seem to always happen
361  if ((waveform & 2) && unlikely(waveform & 0xd) && is6581)
362  accumulator &= (waveform_output << 12) | 0x7fffff;
363 
364  write_shift_register();
365  }
366  else
367  {
368  // Age floating DAC input.
369  if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
370  {
371  waveform_output = 0;
372  }
373  }
374 
375  // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
376  // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
377  // results without any branching (and thus without any pipeline stalls).
378  // NB! This expression relies on that the result of a boolean expression
379  // is either 0 or 1, and furthermore requires two's complement integer.
380  // A few more cycles may be saved by storing the pulse width left shifted
381  // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
382  // used as a bit mask on 12 bit values), yielding the expression
383  // -(accumulator >= pw24). However this only results in negligible savings.
384 
385  // The result of the pulse width compare is delayed one cycle.
386  // Push next pulse level into pulse level pipeline.
387  pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
388 
389  // DAC imperfections are emulated by using waveform_output as an index
390  // into a DAC lookup table. readOSC() uses waveform_output directly.
391  return dac[waveform_output];
392 }
393 
394 } // namespace reSIDfp
395 
396 #endif
397 
398 #endif
reSIDfp::WaveformGenerator::writePW_HI
void writePW_HI(unsigned char pw_hi)
Definition: WaveformGenerator.h:236
reSIDfp::WaveformGenerator::readSync
bool readSync() const
Definition: WaveformGenerator.h:281
reSIDfp::WaveformGenerator::writeCONTROL_REG
void writeCONTROL_REG(unsigned char control)
Definition: WaveformGenerator.cpp:199
reSIDfp::WaveformGenerator::readFreq
unsigned int readFreq() const
Definition: WaveformGenerator.h:271
reSIDfp::WaveformGenerator::readAccumulator
unsigned int readAccumulator() const
Definition: WaveformGenerator.h:266
reSIDfp::WaveformGenerator::writePW_LO
void writePW_LO(unsigned char pw_lo)
Definition: WaveformGenerator.h:229
reSIDfp::WaveformGenerator::synchronize
void synchronize(WaveformGenerator *syncDest, const WaveformGenerator *syncSource) const
Definition: WaveformGenerator.cpp:171
reSIDfp::WaveformGenerator::WaveformGenerator
WaveformGenerator()
Definition: WaveformGenerator.h:185
reSIDfp::WaveformGenerator::writeFREQ_LO
void writeFREQ_LO(unsigned char freq_lo)
Definition: WaveformGenerator.h:215
reSIDfp::WaveformGenerator::readTest
bool readTest() const
Definition: WaveformGenerator.h:276
reSIDfp::WaveformGenerator::clock
void clock()
Definition: WaveformGenerator.h:292
reSIDfp::WaveformGenerator::writeFREQ_HI
void writeFREQ_HI(unsigned char freq_hi)
Definition: WaveformGenerator.h:222
reSIDfp::WaveformGenerator::output
float output(const WaveformGenerator *ringModulator)
Definition: WaveformGenerator.h:335
reSIDfp::WaveformGenerator::reset
void reset()
Definition: WaveformGenerator.cpp:266
reSIDfp::WaveformGenerator::readOSC
unsigned char readOSC() const
Definition: WaveformGenerator.h:261
reSIDfp::WaveformGenerator::setChipModel
void setChipModel(ChipModel chipModel)
Definition: WaveformGenerator.cpp:153
matrix
Definition: array.h:43
reSIDfp::WaveformGenerator
Definition: WaveformGenerator.h:87