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
38namespace reSIDfp
39{
40
94{
95private:
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
163private:
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
176public:
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
283namespace reSIDfp
284{
285
286RESID_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
351RESID_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