libsidplayfp 1.0.3
|
00001 /* 00002 * This file is part of libsidplayfp, a SID player engine. 00003 * 00004 * Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net> 00005 * Copyright 2007-2010 Antti Lankila 00006 * Copyright 2004 Dag Lem <resid@nimrod.no> 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #ifndef WAVEFORMGENERATOR_H 00024 #define WAVEFORMGENERATOR_H 00025 00026 #include "siddefs-fp.h" 00027 #include "array.h" 00028 00029 namespace reSIDfp 00030 { 00031 00046 class WaveformGenerator 00047 { 00048 private: 00049 array<short>* model_wave; 00050 00051 // PWout = (PWn/40.95)% 00052 int pw; 00053 00054 int shift_register; 00055 00059 int shift_register_reset; 00060 00064 int shift_pipeline; 00065 00066 int ring_msb_mask; 00067 int no_noise; 00068 int noise_output; 00069 int no_noise_or_noise_output; 00070 int no_pulse; 00071 int pulse_output; 00072 00076 int waveform; 00077 00078 int floating_output_ttl; 00079 00080 short* wave; 00081 00082 int waveform_output; 00083 00085 int accumulator; 00086 00087 // Fout = (Fn*Fclk/16777216)Hz 00088 int freq; 00089 00093 bool test; 00094 bool sync; 00095 00099 bool msb_rising; 00100 00101 short dac[4096]; 00102 00103 private: 00104 void clock_shift_register(); 00105 00106 void write_shift_register(); 00107 00108 void reset_shift_register(); 00109 00110 void set_noise_output(); 00111 00112 public: 00113 void setWaveformModels(array<short>* models); 00114 00122 void setChipModel(ChipModel chipModel); 00123 00127 void clock(); 00128 00137 void synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const; 00138 00142 WaveformGenerator() : 00143 model_wave(0), 00144 pw(0), 00145 shift_register(0), 00146 shift_register_reset(0), 00147 shift_pipeline(0), 00148 ring_msb_mask(0), 00149 no_noise(0), 00150 noise_output(0), 00151 no_noise_or_noise_output(no_noise | noise_output), 00152 no_pulse(0), 00153 pulse_output(0), 00154 waveform(0), 00155 floating_output_ttl(0), 00156 wave(0), 00157 waveform_output(0), 00158 accumulator(0), 00159 freq(0), 00160 test(false), 00161 sync(false), 00162 msb_rising(false) {} 00163 00169 void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); } 00170 00176 void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); } 00177 00186 void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); } 00187 00193 void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); } 00194 00200 void writeCONTROL_REG(unsigned char control); 00201 00205 void reset(); 00206 00213 short output(const WaveformGenerator* ringModulator); 00214 00220 unsigned char readOSC() const { return (unsigned char)(waveform_output >> 4); } 00221 00225 int readAccumulator() const { return accumulator; } 00226 00230 int readFreq() const { return freq; } 00231 00235 bool readTest() const { return test; } 00236 00240 bool readSync() const { return sync; } 00241 }; 00242 00243 } // namespace reSIDfp 00244 00245 #if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP) 00246 00247 namespace reSIDfp 00248 { 00249 00250 RESID_INLINE 00251 void WaveformGenerator::clock() 00252 { 00253 if (test) 00254 { 00255 if (shift_register_reset != 0 && -- shift_register_reset == 0) 00256 { 00257 reset_shift_register(); 00258 } 00259 00260 // The test bit sets pulse high. 00261 pulse_output = 0xfff; 00262 } 00263 else 00264 { 00265 // Calculate new accumulator value; 00266 const int accumulator_next = (accumulator + freq) & 0xffffff; 00267 const int accumulator_bits_set = ~accumulator & accumulator_next; 00268 accumulator = accumulator_next; 00269 00270 // Check whether the MSB is set high. This is used for synchronization. 00271 msb_rising = (accumulator_bits_set & 0x800000) != 0; 00272 00273 // Shift noise register once for each time accumulator bit 19 is set high. 00274 // The shift is delayed 2 cycles. 00275 if ((accumulator_bits_set & 0x080000) != 0) 00276 { 00277 // Pipeline: Detect rising bit, shift phase 1, shift phase 2. 00278 shift_pipeline = 2; 00279 } 00280 else if (shift_pipeline != 0 && -- shift_pipeline == 0) 00281 { 00282 clock_shift_register(); 00283 } 00284 } 00285 } 00286 00287 RESID_INLINE 00288 short WaveformGenerator::output(const WaveformGenerator* ringModulator) 00289 { 00290 // Set output value. 00291 if (waveform != 0) 00292 { 00293 // The bit masks no_pulse and no_noise are used to achieve branch-free 00294 // calculation of the output value. 00295 const int ix = (accumulator ^ (ringModulator->accumulator & ring_msb_mask)) >> 12; 00296 waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output; 00297 00298 if (waveform > 0x8) 00299 { 00300 // Combined waveforms write to the shift register. 00301 write_shift_register(); 00302 } 00303 } 00304 else 00305 { 00306 // Age floating DAC input. 00307 if (floating_output_ttl != 0 && -- floating_output_ttl == 0) 00308 { 00309 waveform_output = 0; 00310 } 00311 } 00312 00313 // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000. 00314 // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same 00315 // results without any branching (and thus without any pipeline stalls). 00316 // NB! This expression relies on that the result of a boolean expression 00317 // is either 0 or 1, and furthermore requires two's complement integer. 00318 // A few more cycles may be saved by storing the pulse width left shifted 00319 // 12 bits, and dropping the and with 0xfff (this is valid since pulse is 00320 // used as a bit mask on 12 bit values), yielding the expression 00321 // -(accumulator >= pw24). However this only results in negligible savings. 00322 00323 // The result of the pulse width compare is delayed one cycle. 00324 // Push next pulse level into pulse level pipeline. 00325 pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000; 00326 00327 // DAC imperfections are emulated by using waveform_output as an index 00328 // into a DAC lookup table. readOSC() uses waveform_output directly. 00329 return dac[waveform_output]; 00330 } 00331 00332 } // namespace reSIDfp 00333 00334 #endif 00335 00336 #endif