From f906bab1a5f7490d7243e959fe202378e42c7ec5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 13 Nov 2021 11:05:39 -0500 Subject: [PATCH] Provides feedback on interrupt flags, starts on state machine. --- Machines/Amiga/Audio.cpp | 23 +++++++++++++++++++++++ Machines/Amiga/Audio.hpp | 8 +++++++- Machines/Amiga/Chipset.cpp | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Machines/Amiga/Audio.cpp b/Machines/Amiga/Audio.cpp index d64f5b2fb..3cb36159b 100644 --- a/Machines/Amiga/Audio.cpp +++ b/Machines/Amiga/Audio.cpp @@ -8,6 +8,8 @@ #include "Audio.hpp" +#include "Flags.hpp" + #define LOG_PREFIX "[Audio] " #include "../../Outputs/Log.hpp" @@ -61,10 +63,31 @@ void Audio::set_channel_enables(uint16_t enables) { void Audio::set_modulation_flags(uint16_t) { } +void Audio::set_interrupt_requests(uint16_t requests) { + channels_[0].interrupt_pending = requests & uint16_t(InterruptFlag::AudioChannel0); + channels_[1].interrupt_pending = requests & uint16_t(InterruptFlag::AudioChannel1); + channels_[2].interrupt_pending = requests & uint16_t(InterruptFlag::AudioChannel2); + channels_[3].interrupt_pending = requests & uint16_t(InterruptFlag::AudioChannel3); +} + void Audio::run_for([[maybe_unused]] Cycles duration) { // TODO: // // Check whether any channel's period counter is exhausted and, if // so, attempt to consume another sample. If there are no more samples // and length is 0, trigger an interrupt. + + using State = Channel::State; + for(int c = 0; c < 4; c++) { + switch(channels_[c].state) { + case State::Disabled: + if(channels_[c].has_data && !channels_[c].dma_enabled && !channels_[c].interrupt_pending) { + channels_[c].state = Channel::State::PlayingHigh; + // TODO: [volcntrld, percntrld, pbufldl, AUDxID] + } + break; + + default: break; + } + } } diff --git a/Machines/Amiga/Audio.hpp b/Machines/Amiga/Audio.hpp index e595cf2fb..867be81df 100644 --- a/Machines/Amiga/Audio.hpp +++ b/Machines/Amiga/Audio.hpp @@ -53,6 +53,9 @@ class Audio: public DMADevice<4> { /// their neighbours. void set_modulation_flags(uint16_t); + /// Sets which interrupt requests are currently active. + void set_interrupt_requests(uint16_t); + private: struct Channel { // The data latch plus a count of unused samples @@ -74,6 +77,9 @@ class Audio: public DMADevice<4> { // Indicates whether DMA is enabled for this channel. bool dma_enabled = false; + // Records whether this audio interrupt is pending. + bool interrupt_pending = false; + // Replicates the Hardware Reference Manual state machine; // comments indicate which of the documented states each // label refers to. @@ -83,7 +89,7 @@ class Audio: public DMADevice<4> { WaitingForDMA, // 101 PlayingHigh, // 010 PlayingLow, // 011 - } state_; + } state = State::Disabled; } channels_[4]; }; diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 3dbf31217..8972d529e 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -750,6 +750,7 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) { case Write(0x09c): // INTREQ ApplySetClear(interrupt_requests_, 0x7fff); update_interrupts(); + audio_->set_interrupt_requests(interrupt_requests_); break; case Read(0x01e): // INTREQR cycle.set_value16(interrupt_requests_);