From d01e1f3bb13a7ac0b017cdc591bb9683b4422b05 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 13 Nov 2025 17:34:57 -0500 Subject: [PATCH] Block and synchronise threads for voice 3 readback. --- Components/SID/SID.cpp | 19 ++++++++++++++++--- Components/SID/SID.hpp | 11 +++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Components/SID/SID.cpp b/Components/SID/SID.cpp index 3cb5f85da..390654f38 100644 --- a/Components/SID/SID.cpp +++ b/Components/SID/SID.cpp @@ -133,8 +133,18 @@ void SID::update_filter() { } uint8_t SID::read(const Numeric::SizedInt<5> address) { - (void)address; - return last_write_; + switch(address.get()) { + default: return last_write_; + + case 0x19: return 0x00; // TODO: potentometer x. + case 0x1a: return 0x00; // TODO: potentometer y. + + case 0x1b: + case 0x1c: + // Ensure all channels are entirely up to date. + audio_queue_.flush(); + return (address == 0x1c) ? voices_[2].adsr.envelope : uint8_t(voices_[2].output(voices_[1]) >> 4); + } } // MARK: - Oscillators. @@ -160,7 +170,7 @@ uint16_t Voice::Oscillator::sawtooth_output() const { uint16_t Voice::NoiseGenerator::output() const { // Uses bits: 20, 18, 14, 11, 9, 5, 2 and 0, plus four more zero bits. - return + const uint16_t output = ((noise >> 9) & 0b1000'0000'0000) | // b20 -> b11 ((noise >> 8) & 0b0100'0000'0000) | // b18 -> b10 ((noise >> 5) & 0b0010'0000'0000) | // b14 -> b9 @@ -169,6 +179,9 @@ uint16_t Voice::NoiseGenerator::output() const { ((noise << 1) & 0b0000'0100'0000) | // b5 -> b6 ((noise << 3) & 0b0000'0010'0000) | // b2 -> b5 ((noise << 4) & 0b0000'0001'0000); // b0 -> b4 + + assert(output <= Voice::MaxWaveformValue); + return output; } void Voice::NoiseGenerator::update(const bool test) { diff --git a/Components/SID/SID.hpp b/Components/SID/SID.hpp index c3d9f6499..79a0b3ee6 100644 --- a/Components/SID/SID.hpp +++ b/Components/SID/SID.hpp @@ -17,6 +17,8 @@ namespace MOS::SID { struct Voice { + static constexpr uint16_t MaxWaveformValue = (1 << 12) - 1; + struct Oscillator { // Programmer inputs. uint32_t pitch = 0; @@ -84,8 +86,6 @@ private: bool sync() const; bool gate() const; - static constexpr uint16_t MaxWaveformValue = (1 << 12) - 1; - uint16_t pulse_output() const; uint16_t triangle_output(const Voice &prior) const; }; @@ -99,17 +99,12 @@ public: // Outputs::Speaker::BufferSource. template - void apply_samples(std::size_t number_of_samples, Outputs::Speaker::MonoSample *target); + void apply_samples(std::size_t, Outputs::Speaker::MonoSample *); bool is_zero_level() const; void set_sample_volume_range(std::int16_t); private: Concurrency::AsyncTaskQueue &audio_queue_; - - // TODO: an emulator thread copy of voices needs to be kept too, to do the digital stuff, as - // the current output of voice 3 can be read. Probably best if the audio thread posts its most - // recent copy atomically and the emulator thread just catches up from whatever it has? I don't - // think that spinning on voice 3 is common. Voice voices_[3]; uint8_t last_write_;