libresidfp 1.1.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{
93 friend class State;
94
95private:
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
163private:
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
204public:
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
311namespace reSIDfp
312{
313
314RESIDFP_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
379RESIDFP_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 ((waveform & 3) && !is6581)
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 msb_rising = false;
413 accumulator &= 0x7fffff;
414 }
415
416 write_shift_register();
417 }
418 else
419 {
420 // Age floating DAC input.
421 if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
422 {
423 waveBitfade();
424 }
425 }
426
427 // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
428 // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
429 // results without any branching (and thus without any pipeline stalls).
430 // NB! This expression relies on that the result of a boolean expression
431 // is either 0 or 1, and furthermore requires two's complement integer.
432 // A few more cycles may be saved by storing the pulse width left shifted
433 // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
434 // used as a bit mask on 12 bit values), yielding the expression
435 // -(accumulator >= pw24). However this only results in negligible savings.
436
437 // The result of the pulse width compare is delayed one cycle.
438 // Push next pulse level into pulse level pipeline.
439 pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
440
441 return waveform_output;
442}
443
444} // namespace reSIDfp
445
446#endif
447
448#endif
Definition WaveformGenerator.h:92
void setModel(bool new_is6581)
Definition WaveformGenerator.h:220
bool readTest() const
Definition WaveformGenerator.h:299
void writeFREQ_LO(uint8_t freq_lo)
Definition WaveformGenerator.h:239
uint32_t output()
Definition WaveformGenerator.h:380
uint32_t readAccumulator() const
Definition WaveformGenerator.h:289
void writeCONTROL_REG(uint8_t control)
Definition WaveformGenerator.cpp:354
void clock()
Definition WaveformGenerator.h:315
uint32_t readFreq() const
Definition WaveformGenerator.h:294
void writeFREQ_HI(uint8_t freq_hi)
Definition WaveformGenerator.h:246
uint8_t readOSC() const
Definition WaveformGenerator.h:284
void writePW_HI(uint8_t pw_hi)
Definition WaveformGenerator.h:260
bool readFollowingVoiceSync() const
Definition WaveformGenerator.h:304
void reset()
Definition WaveformGenerator.cpp:431
void writePW_LO(uint8_t pw_lo)
Definition WaveformGenerator.h:253
void synchronize() const
Definition WaveformGenerator.cpp:338
Definition State.h:47