Files
86Box/src/sound/resid-fp/WaveformGenerator.cpp

398 lines
13 KiB
C++
Raw Normal View History

/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2023 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define WAVEFORMGENERATOR_CPP
#include "WaveformGenerator.h"
namespace reSIDfp
{
/**
* Number of cycles after which the waveform output fades to 0 when setting
* the waveform register to 0.
* Values measured on warm chips (6581R3/R4 and 8580R5)
* checking OSC3.
* Times vary wildly with temperature and may differ
* from chip to chip so the numbers here represent
* only the big difference between the old and new models.
*
* See [VICE Bug #290](http://sourceforge.net/p/vice-emu/bugs/290/)
* and [VICE Bug #1128](http://sourceforge.net/p/vice-emu/bugs/1128/)
*/
// ~95ms
const unsigned int FLOATING_OUTPUT_TTL_6581R3 = 54000;
const unsigned int FLOATING_OUTPUT_FADE_6581R3 = 1400;
// ~1s
const unsigned int FLOATING_OUTPUT_TTL_6581R4 = 1000000;
// ~1s
const unsigned int FLOATING_OUTPUT_TTL_8580R5 = 800000;
const unsigned int FLOATING_OUTPUT_FADE_8580R5 = 50000;
/**
* Number of cycles after which the shift register is reset
* when the test bit is set.
* Values measured on warm chips (6581R3/R4 and 8580R5)
* checking OSC3.
* Times vary wildly with temperature and may differ
* from chip to chip so the numbers here represent
* only the big difference between the old and new models.
*/
// ~210ms
const unsigned int SHIFT_REGISTER_RESET_6581R3 = 50000;
const unsigned int SHIFT_REGISTER_FADE_6581R3 = 15000;
// ~2.15s
const unsigned int SHIFT_REGISTER_RESET_6581R4 = 2150000;
// ~2.8s
const unsigned int SHIFT_REGISTER_RESET_8580R5 = 986000;
const unsigned int SHIFT_REGISTER_FADE_8580R5 = 314300;
const unsigned int shift_mask =
~(
(1u << 2) | // Bit 20
(1u << 4) | // Bit 18
(1u << 8) | // Bit 14
(1u << 11) | // Bit 11
(1u << 13) | // Bit 9
(1u << 17) | // Bit 5
(1u << 20) | // Bit 2
(1u << 22) // Bit 0
);
/*
* This is what happens when the lfsr is clocked:
*
* cycle 0: bit 19 of the accumulator goes from low to high, the noise register acts normally,
* the output may pulldown a bit;
*
* cycle 1: first phase of the shift, the bits are interconnected and the output of each bit
* is latched into the following. The output may overwrite the latched value.
*
* cycle 2: second phase of the shift, the latched value becomes active in the first
* half of the clock and from the second half the register returns to normal operation.
*
* When the test or reset lines are active the first phase is executed at every cyle
* until the signal is released triggering the second phase.
*
* | | bit n | bit n+1
* | bit19 | latch output | latch output
* -----+-------+--------------+--------------
* phi1 | 0 | A <-> A | B <-> B
* phi2 | 0 | A <-> A | B <-> B
* -----+-------+--------------+--------------
* phi1 | 1 | A <-> A | B <-> B <- bit19 raises
* phi2 | 1 | A <-> A | B <-> B
* -----+-------+--------------+--------------
* phi1 | 1 | X A --|-> A B <- shift phase 1
* phi2 | 1 | X A --|-> A B
* -----+-------+--------------+--------------
* phi1 | 1 | X --> X | A --> A <- shift phase 2
* phi2 | 1 | X <-> X | A <-> A
*/
inline bool do_writeback(unsigned int waveform_old, unsigned int waveform_new, bool is6581)
{
// no writeback without combined waveforms
if (waveform_new <= 8)
return false;
if (waveform_old <= 8)
return false; // fixes SID/noisewriteback/noise_writeback_test2-{old,new}
// What's happening here?
if (is6581 &&
((((waveform_old & 0x3) == 0x1) && ((waveform_new & 0x3) == 0x2))
|| (((waveform_old & 0x3) == 0x2) && ((waveform_new & 0x3) == 0x1))))
{
// fixes
// noise_writeback_check_9_to_A_old
// noise_writeback_check_9_to_E_old
// noise_writeback_check_A_to_9_old
// noise_writeback_check_A_to_D_old
// noise_writeback_check_D_to_A_old
// noise_writeback_check_E_to_9_old
return false;
}
if (waveform_old == 0xc)
{
// fixes
// noise_writeback_check_C_to_A_new
return false;
}
if (waveform_new == 0xc)
{
// fixes
// noise_writeback_check_9_to_C_old
// noise_writeback_check_A_to_C_old
return false;
}
// ok do the writeback
return true;
}
inline unsigned int get_noise_writeback(unsigned int waveform_output)
{
return
((waveform_output & (1u << 11)) >> 9) | // Bit 11 -> bit 20
((waveform_output & (1u << 10)) >> 6) | // Bit 10 -> bit 18
((waveform_output & (1u << 9)) >> 1) | // Bit 9 -> bit 14
((waveform_output & (1u << 8)) << 3) | // Bit 8 -> bit 11
((waveform_output & (1u << 7)) << 6) | // Bit 7 -> bit 9
((waveform_output & (1u << 6)) << 11) | // Bit 6 -> bit 5
((waveform_output & (1u << 5)) << 15) | // Bit 5 -> bit 2
((waveform_output & (1u << 4)) << 18); // Bit 4 -> bit 0
}
/*
* Perform the actual shifting, moving the latched value into following bits.
* The XORing for bit0 is done in this cycle using the test bit latched during
* the previous phi2 cycle.
*/
void WaveformGenerator::shift_phase2(unsigned int waveform_old, unsigned int waveform_new)
{
if (do_writeback(waveform_old, waveform_new, is6581))
{
// if noise is combined with another waveform the output drives the SR bits
shift_latch = (shift_register & shift_mask) | get_noise_writeback(waveform_output);
}
// bit0 = (bit22 | test | reset) ^ bit17 = 1 ^ bit17 = ~bit17
const unsigned int bit22 = ((test_or_reset ? 1 : 0) | shift_latch) << 22;
const unsigned int bit0 = (bit22 ^ (shift_latch << 17)) & (1 << 22);
shift_register = (shift_latch >> 1) | bit0;
#ifdef TRACE
std::cout << std::hex << shift_latch << " -> " << shift_register << std::endl;
#endif
set_noise_output();
}
void WaveformGenerator::write_shift_register()
{
if (unlikely(waveform > 0x8))
{
if (waveform == 0xc)
return; // breaks SID/wf12nsr/wf12nsr
// Write changes to the shift register output caused by combined waveforms
// back into the shift register.
if (likely(shift_pipeline != 1) && !test)
{
#ifdef TRACE
std::cout << "write shift_register" << std::endl;
#endif
// the output pulls down the SR bits
shift_register = shift_register & (shift_mask | get_noise_writeback(waveform_output));
noise_output &= waveform_output;
}
else
{
#ifdef TRACE
std::cout << "write shift_latch" << std::endl;
#endif
// shift phase 1: the output drives the SR bits
noise_output = waveform_output;
}
set_no_noise_or_noise_output();
}
}
void WaveformGenerator::set_noise_output()
{
noise_output =
((shift_register & (1u << 2)) << 9) | // Bit 20 -> bit 11
((shift_register & (1u << 4)) << 6) | // Bit 18 -> bit 10
((shift_register & (1u << 8)) << 1) | // Bit 14 -> bit 9
((shift_register & (1u << 11)) >> 3) | // Bit 11 -> bit 8
((shift_register & (1u << 13)) >> 6) | // Bit 9 -> bit 7
((shift_register & (1u << 17)) >> 11) | // Bit 5 -> bit 6
((shift_register & (1u << 20)) >> 15) | // Bit 2 -> bit 5
((shift_register & (1u << 22)) >> 18); // Bit 0 -> bit 4
set_no_noise_or_noise_output();
}
void WaveformGenerator::setWaveformModels(matrix_t* models)
{
model_wave = models;
}
void WaveformGenerator::setPulldownModels(matrix_t* models)
{
model_pulldown = models;
}
void WaveformGenerator::synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const
{
// A special case occurs when a sync source is synced itself on the same
// cycle as when its MSB is set high. In this case the destination will
// not be synced. This has been verified by sampling OSC3.
if (unlikely(msb_rising) && syncDest->sync && !(sync && syncSource->msb_rising))
{
syncDest->accumulator = 0;
}
}
void WaveformGenerator::set_no_noise_or_noise_output()
{
no_noise_or_noise_output = no_noise | noise_output;
}
void WaveformGenerator::writeCONTROL_REG(unsigned char control)
{
const unsigned int waveform_prev = waveform;
const bool test_prev = test;
waveform = (control >> 4) & 0x0f;
test = (control & 0x08) != 0;
sync = (control & 0x02) != 0;
// Substitution of accumulator MSB when sawtooth = 0, ring_mod = 1.
ring_msb_mask = ((~control >> 5) & (control >> 2) & 0x1) << 23;
if (waveform != waveform_prev)
{
// Set up waveform tables
wave = (*model_wave)[waveform & 0x3];
// We assume tha combinations including noise
// behave the same as without
switch (waveform & 0x7)
{
case 3:
pulldown = (*model_pulldown)[0];
break;
case 4:
pulldown = (waveform & 0x8) ? (*model_pulldown)[4] : nullptr;
break;
case 5:
pulldown = (*model_pulldown)[1];
break;
case 6:
pulldown = (*model_pulldown)[2];
break;
case 7:
pulldown = (*model_pulldown)[3];
break;
default:
pulldown = nullptr;
break;
}
// 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) != 0 ? 0x000 : 0xfff;
set_no_noise_or_noise_output();
no_pulse = (waveform & 0x4) != 0 ? 0x000 : 0xfff;
if (waveform == 0)
{
// Change to floating DAC input.
// Reset fading time for floating DAC input.
floating_output_ttl = is6581 ? FLOATING_OUTPUT_TTL_6581R3 : FLOATING_OUTPUT_TTL_8580R5;
}
}
if (test != test_prev)
{
if (test)
{
// Reset accumulator.
accumulator = 0;
// Flush shift pipeline.
shift_pipeline = 0;
// Latch the shift register value.
shift_latch = shift_register;
#ifdef TRACE
std::cout << "shift phase 1 (test)" << std::endl;
#endif
// Set reset time for shift register.
shift_register_reset = is6581 ? SHIFT_REGISTER_RESET_6581R3 : SHIFT_REGISTER_RESET_8580R5;
}
else
{
// When the test bit is falling, the second phase of the shift is
// completed by enabling SRAM write.
shift_phase2(waveform_prev, waveform);
}
}
}
void WaveformGenerator::waveBitfade()
{
waveform_output &= waveform_output >> 1;
osc3 = waveform_output;
if (waveform_output != 0)
floating_output_ttl = is6581 ? FLOATING_OUTPUT_FADE_6581R3 : FLOATING_OUTPUT_FADE_8580R5;
}
void WaveformGenerator::shiftregBitfade()
{
shift_register |= shift_register >> 1;
shift_register |= 0x400000;
if (shift_register != 0x7fffff)
shift_register_reset = is6581 ? SHIFT_REGISTER_FADE_6581R3 : SHIFT_REGISTER_FADE_8580R5;
}
void WaveformGenerator::reset()
{
// accumulator is not changed on reset
freq = 0;
pw = 0;
msb_rising = false;
waveform = 0;
osc3 = 0;
test = false;
sync = false;
wave = model_wave ? (*model_wave)[0] : nullptr;
pulldown = nullptr;
ring_msb_mask = 0;
no_noise = 0xfff;
no_pulse = 0xfff;
pulse_output = 0xfff;
shift_register_reset = 0;
shift_register = 0x7fffff;
// when reset is released the shift register is clocked once
// so the lower bit is zeroed out
// bit0 = (bit22 | test) ^ bit17 = 1 ^ 1 = 0
test_or_reset = true;
shift_latch = shift_register;
shift_phase2(0, 0);
shift_pipeline = 0;
waveform_output = 0;
floating_output_ttl = 0;
}
} // namespace reSIDfp