255 lines
7.0 KiB
Plaintext
255 lines
7.0 KiB
Plaintext
// ---------------------------------------------------------------------------
|
|
// This file is part of reSID, a MOS6581 SID emulator engine.
|
|
// Copyright (C) 2010 Dag Lem <resid@nimrod.no>
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
// ---------------------------------------------------------------------------
|
|
|
|
#define RESID_WAVE_CC
|
|
|
|
#include "wave.h"
|
|
#include "dac.h"
|
|
|
|
namespace reSID
|
|
{
|
|
|
|
// Waveform lookup tables.
|
|
unsigned short WaveformGenerator::model_wave[2][8][1 << 12] = {
|
|
{
|
|
{0},
|
|
{0},
|
|
{0},
|
|
#include "wave6581__ST.h"
|
|
{0},
|
|
#include "wave6581_P_T.h"
|
|
#include "wave6581_PS_.h"
|
|
#include "wave6581_PST.h"
|
|
},
|
|
{
|
|
{0},
|
|
{0},
|
|
{0},
|
|
#include "wave8580__ST.h"
|
|
{0},
|
|
#include "wave8580_P_T.h"
|
|
#include "wave8580_PS_.h"
|
|
#include "wave8580_PST.h"
|
|
}
|
|
};
|
|
|
|
|
|
// DAC lookup tables.
|
|
unsigned short WaveformGenerator::model_dac[2][1 << 12] = {
|
|
{0},
|
|
{0},
|
|
};
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Constructor.
|
|
// ----------------------------------------------------------------------------
|
|
WaveformGenerator::WaveformGenerator()
|
|
{
|
|
static bool class_init;
|
|
|
|
if (!class_init) {
|
|
// Calculate tables for normal waveforms.
|
|
accumulator = 0;
|
|
for (int i = 0; i < (1 << 12); i++) {
|
|
reg24 msb = accumulator & 0x800000;
|
|
|
|
// Noise mask, triangle, sawtooth, pulse mask.
|
|
// The triangle calculation is made branch-free, just for the hell of it.
|
|
model_wave[0][0][i] = model_wave[1][0][i] = 0xfff;
|
|
model_wave[0][1][i] = model_wave[1][1][i] =
|
|
((accumulator ^ -!!msb) >> 11) & 0xffe;
|
|
model_wave[0][2][i] = model_wave[1][2][i] = accumulator >> 12;
|
|
model_wave[0][4][i] = model_wave[1][4][i] = 0xfff;
|
|
|
|
accumulator += 0x1000;
|
|
}
|
|
|
|
// Build DAC lookup tables for 12-bit DACs.
|
|
// MOS 6581: 2R/R ~ 2.20, missing termination resistor.
|
|
build_dac_table(model_dac[0], 12, 2.20, false);
|
|
// MOS 8580: 2R/R ~ 2.00, correct termination.
|
|
build_dac_table(model_dac[1], 12, 2.00, true);
|
|
|
|
class_init = true;
|
|
}
|
|
|
|
sync_source = this;
|
|
|
|
sid_model = MOS6581;
|
|
reset();
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Set sync source.
|
|
// ----------------------------------------------------------------------------
|
|
void WaveformGenerator::set_sync_source(WaveformGenerator* source)
|
|
{
|
|
sync_source = source;
|
|
source->sync_dest = this;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Set chip model.
|
|
// ----------------------------------------------------------------------------
|
|
void WaveformGenerator::set_chip_model(chip_model model)
|
|
{
|
|
sid_model = model;
|
|
wave = model_wave[model][waveform & 0x7];
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Register functions.
|
|
// ----------------------------------------------------------------------------
|
|
void WaveformGenerator::writeFREQ_LO(reg8 freq_lo)
|
|
{
|
|
freq = (freq & 0xff00) | (freq_lo & 0x00ff);
|
|
}
|
|
|
|
void WaveformGenerator::writeFREQ_HI(reg8 freq_hi)
|
|
{
|
|
freq = ((freq_hi << 8) & 0xff00) | (freq & 0x00ff);
|
|
}
|
|
|
|
void WaveformGenerator::writePW_LO(reg8 pw_lo)
|
|
{
|
|
pw = (pw & 0xf00) | (pw_lo & 0x0ff);
|
|
// Push next pulse level into pulse level pipeline.
|
|
pulse_output = (accumulator >> 12) >= pw ? 0xfff : 0x000;
|
|
}
|
|
|
|
void WaveformGenerator::writePW_HI(reg8 pw_hi)
|
|
{
|
|
pw = ((pw_hi << 8) & 0xf00) | (pw & 0x0ff);
|
|
// Push next pulse level into pulse level pipeline.
|
|
pulse_output = (accumulator >> 12) >= pw ? 0xfff : 0x000;
|
|
}
|
|
|
|
void WaveformGenerator::writeCONTROL_REG(reg8 control)
|
|
{
|
|
reg8 waveform_prev = waveform;
|
|
reg8 test_prev = test;
|
|
waveform = (control >> 4) & 0x0f;
|
|
test = control & 0x08;
|
|
ring_mod = control & 0x04;
|
|
sync = control & 0x02;
|
|
|
|
// Set up waveform table.
|
|
wave = model_wave[sid_model][waveform & 0x7];
|
|
|
|
// Substitution of accumulator MSB when sawtooth = 0, ring_mod = 1.
|
|
ring_msb_mask = ((~control >> 5) & (control >> 2) & 0x1) << 23;
|
|
|
|
// no_noise and no_pulse are used in set_waveform_output() as bitmasks to
|
|
// only let the noise or pulse influence the output when the noise or pulse
|
|
// waveforms are selected.
|
|
no_noise = waveform & 0x8 ? 0x000 : 0xfff;
|
|
no_noise_or_noise_output = no_noise | noise_output;
|
|
no_pulse = waveform & 0x4 ? 0x000 : 0xfff;
|
|
|
|
// Test bit rising.
|
|
// The accumulator is cleared, while the the shift register is prepared for
|
|
// shifting by interconnecting the register bits. The internal SRAM cells
|
|
// start to slowly rise up towards one. The SRAM cells reach one within
|
|
// approximately $8000 cycles, yielding a shift register value of
|
|
// 0x7fffff.
|
|
if (!test_prev && test) {
|
|
// Reset accumulator.
|
|
accumulator = 0;
|
|
|
|
// Flush shift pipeline.
|
|
shift_pipeline = 0;
|
|
|
|
// Set reset time for shift register.
|
|
shift_register_reset = 0x8000;
|
|
|
|
// The test bit sets pulse high.
|
|
pulse_output = 0xfff;
|
|
}
|
|
else if (test_prev && !test) {
|
|
// When the test bit is falling, the second phase of the shift is
|
|
// completed by enabling SRAM write.
|
|
|
|
// bit0 = (bit22 | test) ^ bit17 = 1 ^ bit17 = ~bit17
|
|
reg24 bit0 = (~shift_register >> 17) & 0x1;
|
|
shift_register = ((shift_register << 1) | bit0) & 0x7fffff;
|
|
|
|
// Set new noise waveform output.
|
|
set_noise_output();
|
|
}
|
|
|
|
if (waveform) {
|
|
// Set new waveform output.
|
|
set_waveform_output();
|
|
}
|
|
else if (waveform_prev) {
|
|
// Change to floating DAC input.
|
|
// Reset fading time for floating DAC input.
|
|
//
|
|
// We have two SOAS/C samplings showing that floating DAC
|
|
// keeps its state for at least 0x14000 cycles.
|
|
//
|
|
// This can't be found via sampling OSC3, it seems that
|
|
// the actual analog output must be sampled and timed.
|
|
floating_output_ttl = 0x14000;
|
|
}
|
|
|
|
// The gate bit is handled by the EnvelopeGenerator.
|
|
}
|
|
|
|
reg8 WaveformGenerator::readOSC()
|
|
{
|
|
return waveform_output >> 4;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// SID reset.
|
|
// ----------------------------------------------------------------------------
|
|
void WaveformGenerator::reset()
|
|
{
|
|
accumulator = 0;
|
|
freq = 0;
|
|
pw = 0;
|
|
|
|
msb_rising = false;
|
|
|
|
waveform = 0;
|
|
test = 0;
|
|
ring_mod = 0;
|
|
sync = 0;
|
|
|
|
wave = model_wave[sid_model][0];
|
|
|
|
ring_msb_mask = 0;
|
|
no_noise = 0xfff;
|
|
no_pulse = 0xfff;
|
|
pulse_output = 0xfff;
|
|
|
|
reset_shift_register();
|
|
shift_pipeline = 0;
|
|
|
|
waveform_output = 0;
|
|
floating_output_ttl = 0;
|
|
}
|
|
|
|
} // namespace reSID
|