libresidfp  1.2.3
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 // print SR debugging info
30 //#define TRACE 1
31 
32 #ifdef TRACE
33 # include <iostream>
34 #endif
35 
36 namespace reSIDfp
37 {
38 
92 {
93  friend class State;
94 
95 private:
96  rc_matrix_t model_wave;
97  rc_matrix_t model_pulldown;
98 
99  int16_t* wave = nullptr;
100  int16_t* pulldown = nullptr;
101 
102  // PWout = (PWn/40.95)%
103  uint32_t pw = 0;
104 
105  uint32_t shift_register = 0;
106 
108  uint32_t shift_latch = 0;
109 
111  int shift_pipeline = 0;
112 
113  uint32_t ring_msb_mask = 0;
114  uint32_t no_noise = 0;
115  uint32_t noise_output = 0;
116  uint32_t no_noise_or_noise_output = 0;
117  uint32_t no_pulse = 0;
118  uint32_t pulse_output = 0;
119 
120  uint32_t waveform_output = 0;
121 
123  uint32_t accumulator = 0x555555; // Accumulator's even bits are high on powerup
124 
125  // Fout = (Fn*Fclk/16777216)Hz
126  uint32_t freq = 0;
127 
129  uint32_t tri_saw_pipeline = 0x555;
130 
132  uint32_t osc3 = 0;
133 
135  unsigned int shift_register_reset = 0;
136 
137  // The wave signal TTL when no waveform is selected.
138  unsigned int floating_output_ttl = 0;
139 
141  uint8_t waveform = 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(uint8_t waveform_old, uint8_t 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  inline void setWave() { wave = (*model_wave)[waveform & 0x3]; }
177 
178  inline void setPulldown()
179  {
180  // We assume tha combinations including noise
181  // behave the same as without
182  switch (waveform & 0x7)
183  {
184  case 3:
185  pulldown = (*model_pulldown)[0];
186  break;
187  case 4:
188  pulldown = (waveform & 0x8) ? (*model_pulldown)[4] : nullptr;
189  break;
190  case 5:
191  pulldown = (*model_pulldown)[1];
192  break;
193  case 6:
194  pulldown = (*model_pulldown)[2];
195  break;
196  case 7:
197  pulldown = (*model_pulldown)[3];
198  break;
199  default:
200  pulldown = nullptr;
201  }
202  }
203 
204 public:
205  void setWaveformModels(rc_matrix_t models);
206  void setPulldownModels(rc_matrix_t models);
207 
208  void setOtherWaveforms(const WaveformGenerator* prev, WaveformGenerator* next)
209  {
210  prevVoice = prev;
211  nextVoice = next;
212  }
213 
220  void setModel(bool new_is6581) { is6581 = new_is6581; }
221 
225  void clock();
226 
232  void synchronize() const;
233 
239  void writeFREQ_LO(uint8_t freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
240 
246  void writeFREQ_HI(uint8_t freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
247 
253  void writePW_LO(uint8_t pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
254 
260  void writePW_HI(uint8_t pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
261 
267  void writeCONTROL_REG(uint8_t control);
268 
272  void reset();
273 
279  uint32_t output();
280 
284  uint8_t readOSC() const { return static_cast<uint8_t>(osc3 >> 4); }
285 
289  uint32_t readAccumulator() const { return accumulator; }
290 
294  uint32_t readFreq() const { return freq; }
295 
299  bool readTest() const { return test; }
300 
304  bool readFollowingVoiceSync() const { return nextVoice->sync; }
305 };
306 
307 } // namespace reSIDfp
308 
309 #if RESIDFP_INLINING || defined(WAVEFORMGENERATOR_CPP)
310 
311 namespace reSIDfp
312 {
313 
314 RESIDFP_INLINE
316 {
317  if (unlikely(test))
318  {
319  if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
320  {
321 #ifdef TRACE
322  std::cout << "shiftregBitfade" << std::endl;
323 #endif
324  shiftregBitfade();
325  shift_latch = shift_register;
326 
327  // New noise waveform output.
328  set_noise_output();
329  }
330 
331  // Latch the test bit value for shift phase 2.
332  test_or_reset = true;
333 
334  // The test bit sets pulse high.
335  pulse_output = 0xfff;
336  }
337  else
338  {
339  // Calculate new accumulator value;
340  const uint32_t accumulator_old = accumulator;
341  accumulator = (accumulator + freq) & 0xffffff;
342 
343  // Check which bit have changed from low to high
344  const uint32_t accumulator_bits_set = ~accumulator_old & accumulator;
345 
346  // Check whether the MSB is set high. This is used for synchronization.
347  msb_rising = (accumulator_bits_set & 0x800000) != 0;
348 
349  // Shift noise register once for each time accumulator bit 19 is set high.
350  // The shift is delayed 2 cycles.
351  if (unlikely((accumulator_bits_set & 0x080000) != 0))
352  {
353  // Pipeline: Detect rising bit, shift phase 1, shift phase 2.
354  shift_pipeline = 2;
355  }
356  else if (unlikely(shift_pipeline != 0))
357  {
358  switch (--shift_pipeline)
359  {
360  case 0:
361 #ifdef TRACE
362  std::cout << "shift phase 2" << std::endl;
363 #endif
364  shift_phase2(waveform, waveform);
365  break;
366  case 1:
367 #ifdef TRACE
368  std::cout << "shift phase 1" << std::endl;
369 #endif
370  // Start shift phase 1.
371  test_or_reset = false;
372  shift_latch = shift_register;
373  break;
374  }
375  }
376  }
377 }
378 
379 RESIDFP_INLINE
381 {
382  // Set output value.
383  if (likely(waveform != 0))
384  {
385  const uint32_t ix = (accumulator ^ (~prevVoice->accumulator & ring_msb_mask)) >> 12;
386 
387  // The bit masks no_pulse and no_noise are used to achieve branch-free
388  // calculation of the output value.
389  waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
390  if (pulldown != nullptr)
391  waveform_output = pulldown[waveform_output];
392 
393  // Triangle/Sawtooth output is delayed half cycle on 8580.
394  // This will appear as a one cycle delay on OSC3 as it is latched
395  // in the first phase of the clock.
396  if (!is6581 && (waveform & 3))
397  {
398  osc3 = tri_saw_pipeline & (no_pulse | pulse_output) & no_noise_or_noise_output;
399  if (pulldown != nullptr)
400  osc3 = pulldown[osc3];
401  tri_saw_pipeline = wave[ix];
402  }
403  else
404  {
405  osc3 = waveform_output;
406  }
407 
408  // In the 6581 the top bit of the accumulator may be driven low by combined waveforms
409  // when the sawtooth is selected
410  if (is6581 && (waveform & 0x2) && ((waveform_output & 0x800) == 0))
411  {
412  // On some chips it doesn't happen with P+S
413  msb_rising = false;
414  accumulator &= 0x7fffff;
415  }
416 
417  write_shift_register();
418  }
419  else
420  {
421  // Age floating DAC input.
422  if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
423  {
424  waveBitfade();
425  }
426  }
427 
428  // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
429  // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
430  // results without any branching (and thus without any pipeline stalls).
431  // NB! This expression relies on that the result of a boolean expression
432  // is either 0 or 1, and furthermore requires two's complement integer.
433  // A few more cycles may be saved by storing the pulse width left shifted
434  // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
435  // used as a bit mask on 12 bit values), yielding the expression
436  // -(accumulator >= pw24). However this only results in negligible savings.
437 
438  // The result of the pulse width compare is delayed one cycle.
439  // Push next pulse level into pulse level pipeline.
440  pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
441 
442  return waveform_output;
443 }
444 
445 } // namespace reSIDfp
446 
447 #endif
448 
449 #endif
uint32_t readFreq() const
Definition: WaveformGenerator.h:294
void clock()
Definition: WaveformGenerator.h:315
Definition: Dac.cpp:27
void writePW_LO(uint8_t pw_lo)
Definition: WaveformGenerator.h:253
uint32_t readAccumulator() const
Definition: WaveformGenerator.h:289
void writeFREQ_HI(uint8_t freq_hi)
Definition: WaveformGenerator.h:246
uint8_t readOSC() const
Definition: WaveformGenerator.h:284
bool readTest() const
Definition: WaveformGenerator.h:299
uint32_t output()
Definition: WaveformGenerator.h:380
void setModel(bool new_is6581)
Definition: WaveformGenerator.h:220
void writePW_HI(uint8_t pw_hi)
Definition: WaveformGenerator.h:260
bool readFollowingVoiceSync() const
Definition: WaveformGenerator.h:304
void synchronize() const
Definition: WaveformGenerator.cpp:338
void writeFREQ_LO(uint8_t freq_lo)
Definition: WaveformGenerator.h:239
void writeCONTROL_REG(uint8_t control)
Definition: WaveformGenerator.cpp:354
void reset()
Definition: WaveformGenerator.cpp:431
Definition: State.h:45
Definition: WaveformGenerator.h:91