libsidplayfp 2.3.1
WaveformGenerator.h
1/*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2011-2016 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
143 float* dac; //-V730_NOINIT this is initialized in the SID constructor
144
145private:
146 void clock_shift_register(unsigned int bit0);
147
148 unsigned int get_noise_writeback();
149
150 void write_shift_register();
151
152 void set_noise_output();
153
154 void set_no_noise_or_noise_output();
155
156 void waveBitfade();
157
158 void shiftregBitfade();
159
160public:
161 void setWaveformModels(matrix_t* models);
162
170 void setDAC(float* dac) { this->dac = dac; }
171
178 void setModel(bool is6581) { this->is6581 = is6581; }
179
183 void clock();
184
193 void synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const;
194
199 model_wave(nullptr),
200 wave(nullptr),
201 pw(0),
202 shift_register(0),
203 shift_pipeline(0),
204 ring_msb_mask(0),
205 no_noise(0),
206 noise_output(0),
207 no_noise_or_noise_output(0),
208 no_pulse(0),
209 pulse_output(0),
210 waveform(0),
211 waveform_output(0),
212 accumulator(0x555555), // Accumulator's even bits are high on powerup
213 freq(0),
214 tri_saw_pipeline(0x555),
215 osc3(0),
216 shift_register_reset(0),
217 floating_output_ttl(0),
218 test(false),
219 sync(false),
220 msb_rising(false) {}
221
227 void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); }
228
234 void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); }
235
241 void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); }
242
248 void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); }
249
255 void writeCONTROL_REG(unsigned char control);
256
260 void reset();
261
268 float output(const WaveformGenerator* ringModulator);
269
273 unsigned char readOSC() const { return static_cast<unsigned char>(osc3 >> 4); }
274
278 unsigned int readAccumulator() const { return accumulator; }
279
283 unsigned int readFreq() const { return freq; }
284
288 bool readTest() const { return test; }
289
293 bool readSync() const { return sync; }
294};
295
296} // namespace reSIDfp
297
298#if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP)
299
300namespace reSIDfp
301{
302
303RESID_INLINE
305{
306 if (unlikely(test))
307 {
308 if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0))
309 {
310 shiftregBitfade();
311
312 // New noise waveform output.
313 set_noise_output();
314 }
315
316 // The test bit sets pulse high.
317 pulse_output = 0xfff;
318 }
319 else
320 {
321 // Calculate new accumulator value;
322 const unsigned int accumulator_old = accumulator;
323 accumulator = (accumulator + freq) & 0xffffff;
324
325 // Check which bit have changed
326 const unsigned int accumulator_bits_set = ~accumulator_old & accumulator;
327
328 // Check whether the MSB is set high. This is used for synchronization.
329 msb_rising = (accumulator_bits_set & 0x800000) != 0;
330
331 // Shift noise register once for each time accumulator bit 19 is set high.
332 // The shift is delayed 2 cycles.
333 if (unlikely((accumulator_bits_set & 0x080000) != 0))
334 {
335 // Pipeline: Detect rising bit, shift phase 1, shift phase 2.
336 shift_pipeline = 2;
337 }
338 else if (unlikely(shift_pipeline != 0) && --shift_pipeline == 0)
339 {
340 // bit0 = (bit22 | test) ^ bit17
341 clock_shift_register(((shift_register << 22) ^ (shift_register << 17)) & (1 << 22));
342 }
343 }
344}
345
346RESID_INLINE
348{
349 // Set output value.
350 if (likely(waveform != 0))
351 {
352 const unsigned int ix = (accumulator ^ (~ringModulator->accumulator & ring_msb_mask)) >> 12;
353
354 // The bit masks no_pulse and no_noise are used to achieve branch-free
355 // calculation of the output value.
356 waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output;
357
358 // Triangle/Sawtooth output is delayed half cycle on 8580.
359 // This will appear as a one cycle delay on OSC3 as it is latched 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 tri_saw_pipeline = wave[ix];
364 }
365 else
366 {
367 osc3 = waveform_output;
368 }
369
370 // In the 6581 the top bit of the accumulator may be driven low by combined waveforms
371 // when the sawtooth is selected
372 // FIXME doesn't seem to always happen
373 if ((waveform & 2) && unlikely(waveform & 0xd) && is6581)
374 accumulator &= (waveform_output << 12) | 0x7fffff;
375
376 write_shift_register();
377 }
378 else
379 {
380 // Age floating DAC input.
381 if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0))
382 {
383 waveBitfade();
384 }
385 }
386
387 // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000.
388 // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same
389 // results without any branching (and thus without any pipeline stalls).
390 // NB! This expression relies on that the result of a boolean expression
391 // is either 0 or 1, and furthermore requires two's complement integer.
392 // A few more cycles may be saved by storing the pulse width left shifted
393 // 12 bits, and dropping the and with 0xfff (this is valid since pulse is
394 // used as a bit mask on 12 bit values), yielding the expression
395 // -(accumulator >= pw24). However this only results in negligible savings.
396
397 // The result of the pulse width compare is delayed one cycle.
398 // Push next pulse level into pulse level pipeline.
399 pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000;
400
401 // DAC imperfections are emulated by using waveform_output as an index
402 // into a DAC lookup table. readOSC() uses waveform_output directly.
403 return dac[waveform_output];
404}
405
406} // namespace reSIDfp
407
408#endif
409
410#endif
Definition: array.h:43
Definition: WaveformGenerator.h:87
void synchronize(WaveformGenerator *syncDest, const WaveformGenerator *syncSource) const
Definition: WaveformGenerator.cpp:173
bool readTest() const
Definition: WaveformGenerator.h:288
void clock()
Definition: WaveformGenerator.h:304
unsigned int readFreq() const
Definition: WaveformGenerator.h:283
void writePW_HI(unsigned char pw_hi)
Definition: WaveformGenerator.h:248
void writeFREQ_HI(unsigned char freq_hi)
Definition: WaveformGenerator.h:234
void writePW_LO(unsigned char pw_lo)
Definition: WaveformGenerator.h:241
unsigned char readOSC() const
Definition: WaveformGenerator.h:273
void writeFREQ_LO(unsigned char freq_lo)
Definition: WaveformGenerator.h:227
void writeCONTROL_REG(unsigned char control)
Definition: WaveformGenerator.cpp:243
WaveformGenerator()
Definition: WaveformGenerator.h:198
unsigned int readAccumulator() const
Definition: WaveformGenerator.h:278
void setDAC(float *dac)
Definition: WaveformGenerator.h:170
bool readSync() const
Definition: WaveformGenerator.h:293
void setModel(bool is6581)
Definition: WaveformGenerator.h:178
void reset()
Definition: WaveformGenerator.cpp:323
float output(const WaveformGenerator *ringModulator)
Definition: WaveformGenerator.h:347