libresidfp 0.9.1
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
36namespace reSIDfp
37{
38
92{
93private:
94 matrix_t* model_wave = nullptr;
95 matrix_t* model_pulldown = nullptr;
96
97 short* wave = nullptr;
98 short* pulldown = nullptr;
99
100 // PWout = (PWn/40.95)%
101 unsigned int pw = 0;
102
103 unsigned int shift_register = 0;
104
106 unsigned int shift_latch = 0;
107
109 int shift_pipeline = 0;
110
111 unsigned int ring_msb_mask = 0;
112 unsigned int no_noise = 0;
113 unsigned int noise_output = 0;
114 unsigned int no_noise_or_noise_output = 0;
115 unsigned int no_pulse = 0;
116 unsigned int pulse_output = 0;
117
119 unsigned int waveform = 0;
120
121 unsigned int waveform_output = 0;
122
124 unsigned int accumulator = 0x555555; // Accumulator's even bits are high on powerup
125
126 // Fout = (Fn*Fclk/16777216)Hz
127 unsigned int freq = 0;
128
130 unsigned int tri_saw_pipeline = 0x555;
131
133 unsigned int osc3 = 0;
134
136 unsigned int shift_register_reset = 0;
137
138 // The wave signal TTL when no waveform is selected.
139 unsigned int floating_output_ttl = 0;
140
142
143 bool test = false;
144 bool sync = false;
146
148 bool test_or_reset;
149
151 bool msb_rising = false;
152
153 bool is6581; //-V730_NOINIT this is initialized in the SID constructor
154
156
157 const WaveformGenerator* prevVoice;
158 WaveformGenerator* nextVoice;
160
161private:
162 void shift_phase2(unsigned int waveform_old, unsigned int waveform_new);
163
164 void write_shift_register();
165
166 void set_noise_output();
167
168 void set_no_noise_or_noise_output();
169
170 void waveBitfade();
171
172 void shiftregBitfade();
173
174public:
175 void setWaveformModels(matrix_t* models);
176 void setPulldownModels(matrix_t* models);
177
178 void setOtherWaveforms(const WaveformGenerator* prev, WaveformGenerator* next)
179 {
180 prevVoice = prev;
181 nextVoice = next;
182 }
183
190 void setModel(bool is6581) { this->is6581 = is6581; }
191
195 void clock();
196
202 void synchronize() const;
203
209 void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
210
216 void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
217
223 void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
224
230 void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
231
237 void writeCONTROL_REG(unsigned char control);
238
242 void reset();
243
249 unsigned int output();
250
254 unsigned char readOSC() const { return static_cast<unsigned char>(osc3 >> 4); }
255
259 unsigned int readAccumulator() const { return accumulator; }
260
264 unsigned int readFreq() const { return freq; }
265
269 bool readTest() const { return test; }
270
274 bool readFollowingVoiceSync() const { return nextVoice->sync; }
275};
276
277} // namespace reSIDfp
278
279#if RESIDFP_INLINING || defined(WAVEFORMGENERATOR_CPP)
280
281namespace reSIDfp
282{
283
284RESIDFP_INLINE
286{
287 if (unlikely(test))
288 {
289 if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
290 {
291#ifdef TRACE
292 std::cout << "shiftregBitfade" << std::endl;
293#endif
294 shiftregBitfade();
295 shift_latch = shift_register;
296
297 // New noise waveform output.
298 set_noise_output();
299 }
300
301 // Latch the test bit value for shift phase 2.
302 test_or_reset = true;
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 from low to high
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))
327 {
328 switch (--shift_pipeline)
329 {
330 case 0:
331#ifdef TRACE
332 std::cout << "shift phase 2" << std::endl;
333#endif
334 shift_phase2(waveform, waveform);
335 break;
336 case 1:
337#ifdef TRACE
338 std::cout << "shift phase 1" << std::endl;
339#endif
340 // Start shift phase 1.
341 test_or_reset = false;
342 shift_latch = shift_register;
343 break;
344 }
345 }
346 }
347}
348
349RESIDFP_INLINE
351{
352 // Set output value.
353 if (likely(waveform != 0))
354 {
355 const unsigned int ix = (accumulator ^ (~prevVoice->accumulator & ring_msb_mask)) >> 12;
356
357 // The bit masks no_pulse and no_noise are used to achieve branch-free
358 // calculation of the output value.
359 waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
360 if (pulldown != nullptr)
361 waveform_output = pulldown[waveform_output];
362
363 // Triangle/Sawtooth output is delayed half cycle on 8580.
364 // This will appear as a one cycle delay on OSC3 as it is latched
365 // in the first phase of the clock.
366 if ((waveform & 3) && !is6581)
367 {
368 osc3 = tri_saw_pipeline & (no_pulse | pulse_output) & no_noise_or_noise_output;
369 if (pulldown != nullptr)
370 osc3 = pulldown[osc3];
371 tri_saw_pipeline = wave[ix];
372 }
373 else
374 {
375 osc3 = waveform_output;
376 }
377
378 // In the 6581 the top bit of the accumulator may be driven low by combined waveforms
379 // when the sawtooth is selected
380 if (is6581 && (waveform & 0x2) && ((waveform_output & 0x800) == 0))
381 {
382 msb_rising = false;
383 accumulator &= 0x7fffff;
384 }
385
386 write_shift_register();
387 }
388 else
389 {
390 // Age floating DAC input.
391 if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
392 {
393 waveBitfade();
394 }
395 }
396
397 // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
398 // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
399 // results without any branching (and thus without any pipeline stalls).
400 // NB! This expression relies on that the result of a boolean expression
401 // is either 0 or 1, and furthermore requires two's complement integer.
402 // A few more cycles may be saved by storing the pulse width left shifted
403 // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
404 // used as a bit mask on 12 bit values), yielding the expression
405 // -(accumulator >= pw24). However this only results in negligible savings.
406
407 // The result of the pulse width compare is delayed one cycle.
408 // Push next pulse level into pulse level pipeline.
409 pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
410
411 return waveform_output;
412}
413
414} // namespace reSIDfp
415
416#endif
417
418#endif
Definition WaveformGenerator.h:92
bool readTest() const
Definition WaveformGenerator.h:269
unsigned int readFreq() const
Definition WaveformGenerator.h:264
void writePW_HI(unsigned char pw_hi)
Definition WaveformGenerator.h:230
void writeFREQ_HI(unsigned char freq_hi)
Definition WaveformGenerator.h:216
void writePW_LO(unsigned char pw_lo)
Definition WaveformGenerator.h:223
unsigned char readOSC() const
Definition WaveformGenerator.h:254
void clock()
Definition WaveformGenerator.h:285
void writeFREQ_LO(unsigned char freq_lo)
Definition WaveformGenerator.h:209
void writeCONTROL_REG(unsigned char control)
Definition WaveformGenerator.cpp:354
unsigned int readAccumulator() const
Definition WaveformGenerator.h:259
void setModel(bool is6581)
Definition WaveformGenerator.h:190
bool readFollowingVoiceSync() const
Definition WaveformGenerator.h:274
void reset()
Definition WaveformGenerator.cpp:453
unsigned int output()
Definition WaveformGenerator.h:350
void synchronize() const
Definition WaveformGenerator.cpp:338