libsidplayfp  2.12.0
WaveformGenerator.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2023 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 // print SR debugging info
32 //#define TRACE 1
33 
34 #ifdef TRACE
35 # include <iostream>
36 #endif
37 
38 namespace reSIDfp
39 {
40 
94 {
95 private:
96  matrix_t* model_wave = nullptr;
97  matrix_t* model_pulldown = nullptr;
98 
99  short* wave = nullptr;
100  short* pulldown = nullptr;
101 
102  // PWout = (PWn/40.95)%
103  unsigned int pw = 0;
104 
105  unsigned int shift_register = 0;
106 
108  unsigned int shift_latch = 0;
109 
111  int shift_pipeline = 0;
112 
113  unsigned int ring_msb_mask = 0;
114  unsigned int no_noise = 0;
115  unsigned int noise_output = 0;
116  unsigned int no_noise_or_noise_output = 0;
117  unsigned int no_pulse = 0;
118  unsigned int pulse_output = 0;
119 
121  unsigned int waveform = 0;
122 
123  unsigned int waveform_output = 0;
124 
126  unsigned int accumulator = 0x555555; // Accumulator's even bits are high on powerup
127 
128  // Fout = (Fn*Fclk/16777216)Hz
129  unsigned int freq = 0;
130 
132  unsigned int tri_saw_pipeline = 0x555;
133 
135  unsigned int osc3 = 0;
136 
138  unsigned int shift_register_reset = 0;
139 
140  // The wave signal TTL when no waveform is selected.
141  unsigned int floating_output_ttl = 0;
142 
144 
145  bool test = false;
146  bool sync = false;
148 
150  bool test_or_reset;
151 
153  bool msb_rising = false;
154 
155  bool is6581; //-V730_NOINIT this is initialized in the SID constructor
156 
157 private:
158  void shift_phase2(unsigned int waveform_old, unsigned int waveform_new);
159 
160  void write_shift_register();
161 
162  void set_noise_output();
163 
164  void set_no_noise_or_noise_output();
165 
166  void waveBitfade();
167 
168  void shiftregBitfade();
169 
170 public:
171  void setWaveformModels(matrix_t* models);
172  void setPulldownModels(matrix_t* models);
173 
180  void setModel(bool is6581) { this->is6581 = is6581; }
181 
185  void clock();
186 
195  void synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const;
196 
202  void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
203 
209  void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
210 
216  void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
217 
223  void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
224 
230  void writeCONTROL_REG(unsigned char control);
231 
235  void reset();
236 
243  unsigned int output(const WaveformGenerator* ringModulator);
244 
248  unsigned char readOSC() const { return static_cast<unsigned char>(osc3 >> 4); }
249 
253  unsigned int readAccumulator() const { return accumulator; }
254 
258  unsigned int readFreq() const { return freq; }
259 
263  bool readTest() const { return test; }
264 
268  bool readSync() const { return sync; }
269 };
270 
271 } // namespace reSIDfp
272 
273 #if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP)
274 
275 namespace reSIDfp
276 {
277 
278 RESID_INLINE
280 {
281  if (unlikely(test))
282  {
283  if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
284  {
285 #ifdef TRACE
286  std::cout << "shiftregBitfade" << std::endl;
287 #endif
288  shiftregBitfade();
289  shift_latch = shift_register;
290 
291  // New noise waveform output.
292  set_noise_output();
293  }
294 
295  // Latch the test bit value for shift phase 2.
296  test_or_reset = true;
297 
298  // The test bit sets pulse high.
299  pulse_output = 0xfff;
300  }
301  else
302  {
303  // Calculate new accumulator value;
304  const unsigned int accumulator_old = accumulator;
305  accumulator = (accumulator + freq) & 0xffffff;
306 
307  // Check which bit have changed from low to high
308  const unsigned int accumulator_bits_set = ~accumulator_old & accumulator;
309 
310  // Check whether the MSB is set high. This is used for synchronization.
311  msb_rising = (accumulator_bits_set & 0x800000) != 0;
312 
313  // Shift noise register once for each time accumulator bit 19 is set high.
314  // The shift is delayed 2 cycles.
315  if (unlikely((accumulator_bits_set & 0x080000) != 0))
316  {
317  // Pipeline: Detect rising bit, shift phase 1, shift phase 2.
318  shift_pipeline = 2;
319  }
320  else if (unlikely(shift_pipeline != 0))
321  {
322  switch (--shift_pipeline)
323  {
324  case 0:
325 #ifdef TRACE
326  std::cout << "shift phase 2" << std::endl;
327 #endif
328  shift_phase2(waveform, waveform);
329  break;
330  case 1:
331 #ifdef TRACE
332  std::cout << "shift phase 1" << std::endl;
333 #endif
334  // Start shift phase 1.
335  test_or_reset = false;
336  shift_latch = shift_register;
337  break;
338  }
339  }
340  }
341 }
342 
343 RESID_INLINE
344 unsigned int WaveformGenerator::output(const WaveformGenerator* ringModulator)
345 {
346  // Set output value.
347  if (likely(waveform != 0))
348  {
349  const unsigned int ix = (accumulator ^ (~ringModulator->accumulator & ring_msb_mask)) >> 12;
350 
351  // The bit masks no_pulse and no_noise are used to achieve branch-free
352  // calculation of the output value.
353  waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
354  if (pulldown != nullptr)
355  waveform_output = pulldown[waveform_output];
356 
357  // Triangle/Sawtooth output is delayed half cycle on 8580.
358  // This will appear as a one cycle delay on OSC3 as it is latched
359  // in the first phase of the clock.
360  if ((waveform & 3) && !is6581)
361  {
362  osc3 = tri_saw_pipeline & (no_pulse | pulse_output) & no_noise_or_noise_output;
363  if (pulldown != nullptr)
364  osc3 = pulldown[osc3];
365  tri_saw_pipeline = wave[ix];
366  }
367  else
368  {
369  osc3 = waveform_output;
370  }
371 
372  // In the 6581 the top bit of the accumulator may be driven low by combined waveforms
373  // when the sawtooth is selected
374  if (is6581 && (waveform & 0x2) && ((waveform_output & 0x800) == 0))
375  {
376  msb_rising = 0;
377  accumulator &= 0x7fffff;
378  }
379 
380  write_shift_register();
381  }
382  else
383  {
384  // Age floating DAC input.
385  if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
386  {
387  waveBitfade();
388  }
389  }
390 
391  // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
392  // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
393  // results without any branching (and thus without any pipeline stalls).
394  // NB! This expression relies on that the result of a boolean expression
395  // is either 0 or 1, and furthermore requires two's complement integer.
396  // A few more cycles may be saved by storing the pulse width left shifted
397  // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
398  // used as a bit mask on 12 bit values), yielding the expression
399  // -(accumulator >= pw24). However this only results in negligible savings.
400 
401  // The result of the pulse width compare is delayed one cycle.
402  // Push next pulse level into pulse level pipeline.
403  pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
404 
405  return waveform_output;
406 }
407 
408 } // namespace reSIDfp
409 
410 #endif
411 
412 #endif
Definition: WaveformGenerator.h:94
void synchronize(WaveformGenerator *syncDest, const WaveformGenerator *syncSource) const
Definition: WaveformGenerator.cpp:338
bool readTest() const
Definition: WaveformGenerator.h:263
unsigned int output(const WaveformGenerator *ringModulator)
Definition: WaveformGenerator.h:344
void clock()
Definition: WaveformGenerator.h:279
unsigned int readFreq() const
Definition: WaveformGenerator.h:258
void writePW_HI(unsigned char pw_hi)
Definition: WaveformGenerator.h:223
void writeFREQ_HI(unsigned char freq_hi)
Definition: WaveformGenerator.h:209
void writePW_LO(unsigned char pw_lo)
Definition: WaveformGenerator.h:216
unsigned char readOSC() const
Definition: WaveformGenerator.h:248
void writeFREQ_LO(unsigned char freq_lo)
Definition: WaveformGenerator.h:202
void writeCONTROL_REG(unsigned char control)
Definition: WaveformGenerator.cpp:354
unsigned int readAccumulator() const
Definition: WaveformGenerator.h:253
bool readSync() const
Definition: WaveformGenerator.h:268
void setModel(bool is6581)
Definition: WaveformGenerator.h:180
void reset()
Definition: WaveformGenerator.cpp:453