libsidplayfp  2.15.0
WaveformGenerator.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2025 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 
158 
159  const WaveformGenerator* prevVoice;
160  WaveformGenerator* nextVoice;
162 
163 private:
164  void shift_phase2(unsigned int waveform_old, unsigned int waveform_new);
165 
166  void write_shift_register();
167 
168  void set_noise_output();
169 
170  void set_no_noise_or_noise_output();
171 
172  void waveBitfade();
173 
174  void shiftregBitfade();
175 
176 public:
177  void setWaveformModels(matrix_t* models);
178  void setPulldownModels(matrix_t* models);
179 
180  void setOtherWaveforms(const WaveformGenerator* prev, WaveformGenerator* next)
181  {
182  prevVoice = prev;
183  nextVoice = next;
184  }
185 
192  void setModel(bool is6581) { this->is6581 = is6581; }
193 
197  void clock();
198 
204  void synchronize() const;
205 
211  void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
212 
218  void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
219 
225  void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
226 
232  void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
233 
239  void writeCONTROL_REG(unsigned char control);
240 
244  void reset();
245 
251  unsigned int output();
252 
256  unsigned char readOSC() const { return static_cast<unsigned char>(osc3 >> 4); }
257 
261  unsigned int readAccumulator() const { return accumulator; }
262 
266  unsigned int readFreq() const { return freq; }
267 
271  bool readTest() const { return test; }
272 
276  bool readFollowingVoiceSync() const { return nextVoice->sync; }
277 };
278 
279 } // namespace reSIDfp
280 
281 #if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP)
282 
283 namespace reSIDfp
284 {
285 
286 RESID_INLINE
288 {
289  if (unlikely(test))
290  {
291  if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
292  {
293 #ifdef TRACE
294  std::cout << "shiftregBitfade" << std::endl;
295 #endif
296  shiftregBitfade();
297  shift_latch = shift_register;
298 
299  // New noise waveform output.
300  set_noise_output();
301  }
302 
303  // Latch the test bit value for shift phase 2.
304  test_or_reset = true;
305 
306  // The test bit sets pulse high.
307  pulse_output = 0xfff;
308  }
309  else
310  {
311  // Calculate new accumulator value;
312  const unsigned int accumulator_old = accumulator;
313  accumulator = (accumulator + freq) & 0xffffff;
314 
315  // Check which bit have changed from low to high
316  const unsigned int accumulator_bits_set = ~accumulator_old & accumulator;
317 
318  // Check whether the MSB is set high. This is used for synchronization.
319  msb_rising = (accumulator_bits_set & 0x800000) != 0;
320 
321  // Shift noise register once for each time accumulator bit 19 is set high.
322  // The shift is delayed 2 cycles.
323  if (unlikely((accumulator_bits_set & 0x080000) != 0))
324  {
325  // Pipeline: Detect rising bit, shift phase 1, shift phase 2.
326  shift_pipeline = 2;
327  }
328  else if (unlikely(shift_pipeline != 0))
329  {
330  switch (--shift_pipeline)
331  {
332  case 0:
333 #ifdef TRACE
334  std::cout << "shift phase 2" << std::endl;
335 #endif
336  shift_phase2(waveform, waveform);
337  break;
338  case 1:
339 #ifdef TRACE
340  std::cout << "shift phase 1" << std::endl;
341 #endif
342  // Start shift phase 1.
343  test_or_reset = false;
344  shift_latch = shift_register;
345  break;
346  }
347  }
348  }
349 }
350 
351 RESID_INLINE
353 {
354  // Set output value.
355  if (likely(waveform != 0))
356  {
357  const unsigned int ix = (accumulator ^ (~prevVoice->accumulator & ring_msb_mask)) >> 12;
358 
359  // The bit masks no_pulse and no_noise are used to achieve branch-free
360  // calculation of the output value.
361  waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
362  if (pulldown != nullptr)
363  waveform_output = pulldown[waveform_output];
364 
365  // Triangle/Sawtooth output is delayed half cycle on 8580.
366  // This will appear as a one cycle delay on OSC3 as it is latched
367  // in the first phase of the clock.
368  if ((waveform & 3) && !is6581)
369  {
370  osc3 = tri_saw_pipeline & (no_pulse | pulse_output) & no_noise_or_noise_output;
371  if (pulldown != nullptr)
372  osc3 = pulldown[osc3];
373  tri_saw_pipeline = wave[ix];
374  }
375  else
376  {
377  osc3 = waveform_output;
378  }
379 
380  // In the 6581 the top bit of the accumulator may be driven low by combined waveforms
381  // when the sawtooth is selected
382  if (is6581 && (waveform & 0x2) && ((waveform_output & 0x800) == 0))
383  {
384  msb_rising = false;
385  accumulator &= 0x7fffff;
386  }
387 
388  write_shift_register();
389  }
390  else
391  {
392  // Age floating DAC input.
393  if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
394  {
395  waveBitfade();
396  }
397  }
398 
399  // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
400  // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
401  // results without any branching (and thus without any pipeline stalls).
402  // NB! This expression relies on that the result of a boolean expression
403  // is either 0 or 1, and furthermore requires two's complement integer.
404  // A few more cycles may be saved by storing the pulse width left shifted
405  // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
406  // used as a bit mask on 12 bit values), yielding the expression
407  // -(accumulator >= pw24). However this only results in negligible savings.
408 
409  // The result of the pulse width compare is delayed one cycle.
410  // Push next pulse level into pulse level pipeline.
411  pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
412 
413  return waveform_output;
414 }
415 
416 } // namespace reSIDfp
417 
418 #endif
419 
420 #endif
Definition: WaveformGenerator.h:94
bool readTest() const
Definition: WaveformGenerator.h:271
void clock()
Definition: WaveformGenerator.h:287
unsigned int readFreq() const
Definition: WaveformGenerator.h:266
void writePW_HI(unsigned char pw_hi)
Definition: WaveformGenerator.h:232
void writeFREQ_HI(unsigned char freq_hi)
Definition: WaveformGenerator.h:218
void writePW_LO(unsigned char pw_lo)
Definition: WaveformGenerator.h:225
unsigned char readOSC() const
Definition: WaveformGenerator.h:256
void writeFREQ_LO(unsigned char freq_lo)
Definition: WaveformGenerator.h:211
void writeCONTROL_REG(unsigned char control)
Definition: WaveformGenerator.cpp:354
unsigned int output()
Definition: WaveformGenerator.h:352
unsigned int readAccumulator() const
Definition: WaveformGenerator.h:261
void setModel(bool is6581)
Definition: WaveformGenerator.h:192
bool readFollowingVoiceSync() const
Definition: WaveformGenerator.h:276
void reset()
Definition: WaveformGenerator.cpp:453
void synchronize() const
Definition: WaveformGenerator.cpp:338