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