libsidplayfp 2.5.1
WaveformGenerator.h
1/*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2011-2022 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
31namespace reSIDfp
32{
33
87{
88private:
89 matrix_t* model_wave;
90 matrix_t* model_pulldown;
91
92 short* wave;
93 short* pulldown;
94
95 // PWout = (PWn/40.95)%
96 unsigned int pw;
97
98 unsigned int shift_register;
99
101 int shift_pipeline;
102
103 unsigned int ring_msb_mask;
104 unsigned int no_noise;
105 unsigned int noise_output;
106 unsigned int no_noise_or_noise_output;
107 unsigned int no_pulse;
108 unsigned int pulse_output;
109
111 unsigned int waveform;
112
113 unsigned int waveform_output;
114
116 unsigned int accumulator;
117
118 // Fout = (Fn*Fclk/16777216)Hz
119 unsigned int freq;
120
122 unsigned int tri_saw_pipeline;
123
125 unsigned int osc3;
126
128 unsigned int shift_register_reset;
129
130 // The wave signal TTL when no waveform is selected
131 unsigned int floating_output_ttl;
132
134
135 bool test;
136 bool sync;
138
140 bool msb_rising;
141
142 bool is6581; //-V730_NOINIT this is initialized in the SID constructor
143
144private:
145 void clock_shift_register(unsigned int bit0);
146
147 unsigned int get_noise_writeback();
148
149 void write_shift_register();
150
151 void set_noise_output();
152
153 void set_no_noise_or_noise_output();
154
155 void waveBitfade();
156
157 void shiftregBitfade();
158
159public:
160 void setWaveformModels(matrix_t* models);
161 void setPulldownModels(matrix_t* models);
162
169 void setModel(bool is6581) { this->is6581 = is6581; }
170
174 void clock();
175
184 void synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const;
185
190 model_wave(nullptr),
191 model_pulldown(nullptr),
192 wave(nullptr),
193 pulldown(nullptr),
194 pw(0),
195 shift_register(0),
196 shift_pipeline(0),
197 ring_msb_mask(0),
198 no_noise(0),
199 noise_output(0),
200 no_noise_or_noise_output(0),
201 no_pulse(0),
202 pulse_output(0),
203 waveform(0),
204 waveform_output(0),
205 accumulator(0x555555), // Accumulator's even bits are high on powerup
206 freq(0),
207 tri_saw_pipeline(0x555),
208 osc3(0),
209 shift_register_reset(0),
210 floating_output_ttl(0),
211 test(false),
212 sync(false),
213 msb_rising(false) {}
214
220 void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
221
227 void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
228
234 void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
235
241 void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
242
248 void writeCONTROL_REG(unsigned char control);
249
253 void reset();
254
261 unsigned int output(const WaveformGenerator* ringModulator);
262
266 unsigned char readOSC() const { return static_cast<unsigned char>(osc3 >> 4); }
267
271 unsigned int readAccumulator() const { return accumulator; }
272
276 unsigned int readFreq() const { return freq; }
277
281 bool readTest() const { return test; }
282
286 bool readSync() const { return sync; }
287};
288
289} // namespace reSIDfp
290
291#if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP)
292
293namespace reSIDfp
294{
295
296RESID_INLINE
298{
299 if (unlikely(test))
300 {
301 if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
302 {
303 shiftregBitfade();
304
305 // New noise waveform output.
306 set_noise_output();
307 }
308
309 // The test bit sets pulse high.
310 pulse_output = 0xfff;
311 }
312 else
313 {
314 // Calculate new accumulator value;
315 const unsigned int accumulator_old = accumulator;
316 accumulator = (accumulator + freq) & 0xffffff;
317
318 // Check which bit have changed from low to high
319 const unsigned int accumulator_bits_set = ~accumulator_old & accumulator;
320
321 // Check whether the MSB is set high. This is used for synchronization.
322 msb_rising = (accumulator_bits_set & 0x800000) != 0;
323
324 // Shift noise register once for each time accumulator bit 19 is set high.
325 // The shift is delayed 2 cycles.
326 if (unlikely((accumulator_bits_set & 0x080000) != 0))
327 {
328 // Pipeline: Detect rising bit, shift phase 1, shift phase 2.
329 shift_pipeline = 2;
330 }
331 else if (unlikely(shift_pipeline != 0) && --shift_pipeline == 0)
332 {
333 // bit0 = (bit22 | test) ^ bit17
334 clock_shift_register(((shift_register << 22) ^ (shift_register << 17)) & (1u << 22));
335 }
336 }
337}
338
339RESID_INLINE
340unsigned int WaveformGenerator::output(const WaveformGenerator* ringModulator)
341{
342 // Set output value.
343 if (likely(waveform != 0))
344 {
345 const unsigned int ix = (accumulator ^ (~ringModulator->accumulator & ring_msb_mask)) >> 12;
346
347 // The bit masks no_pulse and no_noise are used to achieve branch-free
348 // calculation of the output value.
349 waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
350 if (pulldown != nullptr)
351 waveform_output = pulldown[waveform_output];
352
353 // Triangle/Sawtooth output is delayed half cycle on 8580.
354 // This will appear as a one cycle delay on OSC3 as it is latched
355 // in the first phase of the clock.
356 if ((waveform & 3) && !is6581)
357 {
358 osc3 = tri_saw_pipeline & (no_pulse | pulse_output) & no_noise_or_noise_output;
359 if (pulldown != nullptr)
360 osc3 = pulldown[osc3];
361 tri_saw_pipeline = wave[ix];
362 }
363 else
364 {
365 osc3 = waveform_output;
366 }
367
368 // In the 6581 the top bit of the accumulator may be driven low by combined waveforms
369 // when the sawtooth is selected
370 if (is6581
371 && (waveform & 0x2)
372 && ((waveform_output & 0x800) == 0))
373 accumulator &= 0x7fffff;
374
375 write_shift_register();
376 }
377 else
378 {
379 // Age floating DAC input.
380 if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
381 {
382 waveBitfade();
383 }
384 }
385
386 // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
387 // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
388 // results without any branching (and thus without any pipeline stalls).
389 // NB! This expression relies on that the result of a boolean expression
390 // is either 0 or 1, and furthermore requires two's complement integer.
391 // A few more cycles may be saved by storing the pulse width left shifted
392 // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
393 // used as a bit mask on 12 bit values), yielding the expression
394 // -(accumulator >= pw24). However this only results in negligible savings.
395
396 // The result of the pulse width compare is delayed one cycle.
397 // Push next pulse level into pulse level pipeline.
398 pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
399
400 return waveform_output;
401}
402
403} // namespace reSIDfp
404
405#endif
406
407#endif
Definition WaveformGenerator.h:87
void synchronize(WaveformGenerator *syncDest, const WaveformGenerator *syncSource) const
Definition WaveformGenerator.cpp:254
bool readTest() const
Definition WaveformGenerator.h:281
unsigned int output(const WaveformGenerator *ringModulator)
Definition WaveformGenerator.h:340
void clock()
Definition WaveformGenerator.h:297
unsigned int readFreq() const
Definition WaveformGenerator.h:276
void writePW_HI(unsigned char pw_hi)
Definition WaveformGenerator.h:241
void writeFREQ_HI(unsigned char freq_hi)
Definition WaveformGenerator.h:227
void writePW_LO(unsigned char pw_lo)
Definition WaveformGenerator.h:234
unsigned char readOSC() const
Definition WaveformGenerator.h:266
void writeFREQ_LO(unsigned char freq_lo)
Definition WaveformGenerator.h:220
void writeCONTROL_REG(unsigned char control)
Definition WaveformGenerator.cpp:290
WaveformGenerator()
Definition WaveformGenerator.h:189
unsigned int readAccumulator() const
Definition WaveformGenerator.h:271
bool readSync() const
Definition WaveformGenerator.h:286
void setModel(bool is6581)
Definition WaveformGenerator.h:169
void reset()
Definition WaveformGenerator.cpp:393