libsidplayfp 2.4.0
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
91 short* wave;
92
93 // PWout = (PWn/40.95)%
94 unsigned int pw;
95
96 unsigned int shift_register;
97
99 int shift_pipeline;
100
101 unsigned int ring_msb_mask;
102 unsigned int no_noise;
103 unsigned int noise_output;
104 unsigned int no_noise_or_noise_output;
105 unsigned int no_pulse;
106 unsigned int pulse_output;
107
109 unsigned int waveform;
110
111 unsigned int waveform_output;
112
114 unsigned int accumulator;
115
116 // Fout = (Fn*Fclk/16777216)Hz
117 unsigned int freq;
118
120 unsigned int tri_saw_pipeline;
121
123 unsigned int osc3;
124
126 unsigned int shift_register_reset;
127
128 // The wave signal TTL when no waveform is selected
129 unsigned int floating_output_ttl;
130
132
133 bool test;
134 bool sync;
136
138 bool msb_rising;
139
140 bool is6581; //-V730_NOINIT this is initialized in the SID constructor
141
142private:
143 void clock_shift_register(unsigned int bit0);
144
145 unsigned int get_noise_writeback();
146
147 void write_shift_register();
148
149 void set_noise_output();
150
151 void set_no_noise_or_noise_output();
152
153 void waveBitfade();
154
155 void shiftregBitfade();
156
157public:
158 void setWaveformModels(matrix_t* models);
159
166 void setModel(bool is6581) { this->is6581 = is6581; }
167
171 void clock();
172
181 void synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const;
182
187 model_wave(nullptr),
188 wave(nullptr),
189 pw(0),
190 shift_register(0),
191 shift_pipeline(0),
192 ring_msb_mask(0),
193 no_noise(0),
194 noise_output(0),
195 no_noise_or_noise_output(0),
196 no_pulse(0),
197 pulse_output(0),
198 waveform(0),
199 waveform_output(0),
200 accumulator(0x555555), // Accumulator's even bits are high on powerup
201 freq(0),
202 tri_saw_pipeline(0x555),
203 osc3(0),
204 shift_register_reset(0),
205 floating_output_ttl(0),
206 test(false),
207 sync(false),
208 msb_rising(false) {}
209
215 void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
216
222 void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
223
229 void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
230
236 void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
237
243 void writeCONTROL_REG(unsigned char control);
244
248 void reset();
249
256 unsigned int output(const WaveformGenerator* ringModulator);
257
261 unsigned char readOSC() const { return static_cast<unsigned char>(osc3 >> 4); }
262
266 unsigned int readAccumulator() const { return accumulator; }
267
271 unsigned int readFreq() const { return freq; }
272
276 bool readTest() const { return test; }
277
281 bool readSync() const { return sync; }
282};
283
284} // namespace reSIDfp
285
286#if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP)
287
288namespace reSIDfp
289{
290
291RESID_INLINE
293{
294 if (unlikely(test))
295 {
296 if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
297 {
298 shiftregBitfade();
299
300 // New noise waveform output.
301 set_noise_output();
302 }
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) && --shift_pipeline == 0)
327 {
328 // bit0 = (bit22 | test) ^ bit17
329 clock_shift_register(((shift_register << 22) ^ (shift_register << 17)) & (1 << 22));
330 }
331 }
332}
333
334RESID_INLINE
335unsigned int WaveformGenerator::output(const WaveformGenerator* ringModulator)
336{
337 // Set output value.
338 if (likely(waveform != 0))
339 {
340 const unsigned int ix = (accumulator ^ (~ringModulator->accumulator & ring_msb_mask)) >> 12;
341
342 // The bit masks no_pulse and no_noise are used to achieve branch-free
343 // calculation of the output value.
344 waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
345
346 // Triangle/Sawtooth output is delayed half cycle on 8580.
347 // This will appear as a one cycle delay on OSC3 as it is latched first phase of the clock.
348 if ((waveform & 3) && !is6581)
349 {
350 osc3 = tri_saw_pipeline & (no_pulse | pulse_output) & no_noise_or_noise_output;
351 tri_saw_pipeline = wave[ix];
352 }
353 else
354 {
355 osc3 = waveform_output;
356 }
357
358 // In the 6581 the top bit of the accumulator may be driven low by combined waveforms
359 // when the sawtooth is selected
360 if (is6581
361 && (waveform & 0x2)
362 && ((waveform_output & 0x800) == 0))
363 accumulator &= 0x7fffff;
364
365 write_shift_register();
366 }
367 else
368 {
369 // Age floating DAC input.
370 if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
371 {
372 waveBitfade();
373 }
374 }
375
376 // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
377 // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
378 // results without any branching (and thus without any pipeline stalls).
379 // NB! This expression relies on that the result of a boolean expression
380 // is either 0 or 1, and furthermore requires two's complement integer.
381 // A few more cycles may be saved by storing the pulse width left shifted
382 // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
383 // used as a bit mask on 12 bit values), yielding the expression
384 // -(accumulator >= pw24). However this only results in negligible savings.
385
386 // The result of the pulse width compare is delayed one cycle.
387 // Push next pulse level into pulse level pipeline.
388 pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
389
390 return waveform_output;
391}
392
393} // namespace reSIDfp
394
395#endif
396
397#endif
Definition: array.h:43
Definition: WaveformGenerator.h:87
void synchronize(WaveformGenerator *syncDest, const WaveformGenerator *syncSource) const
Definition: WaveformGenerator.cpp:188
bool readTest() const
Definition: WaveformGenerator.h:276
unsigned int output(const WaveformGenerator *ringModulator)
Definition: WaveformGenerator.h:335
void clock()
Definition: WaveformGenerator.h:292
unsigned int readFreq() const
Definition: WaveformGenerator.h:271
void writePW_HI(unsigned char pw_hi)
Definition: WaveformGenerator.h:236
void writeFREQ_HI(unsigned char freq_hi)
Definition: WaveformGenerator.h:222
void writePW_LO(unsigned char pw_lo)
Definition: WaveformGenerator.h:229
unsigned char readOSC() const
Definition: WaveformGenerator.h:261
void writeFREQ_LO(unsigned char freq_lo)
Definition: WaveformGenerator.h:215
void writeCONTROL_REG(unsigned char control)
Definition: WaveformGenerator.cpp:258
WaveformGenerator()
Definition: WaveformGenerator.h:186
unsigned int readAccumulator() const
Definition: WaveformGenerator.h:266
bool readSync() const
Definition: WaveformGenerator.h:281
void setModel(bool is6581)
Definition: WaveformGenerator.h:166
void reset()
Definition: WaveformGenerator.cpp:338