1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-09 06:29:33 +00:00

Provides feedback on interrupt flags, starts on state machine.

This commit is contained in:
Thomas Harte 2021-11-13 11:05:39 -05:00
parent fffc03c4e4
commit f906bab1a5
3 changed files with 31 additions and 1 deletions

View File

@ -8,6 +8,8 @@
#include "Audio.hpp" #include "Audio.hpp"
#include "Flags.hpp"
#define LOG_PREFIX "[Audio] " #define LOG_PREFIX "[Audio] "
#include "../../Outputs/Log.hpp" #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_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) { void Audio::run_for([[maybe_unused]] Cycles duration) {
// TODO: // TODO:
// //
// Check whether any channel's period counter is exhausted and, if // Check whether any channel's period counter is exhausted and, if
// so, attempt to consume another sample. If there are no more samples // so, attempt to consume another sample. If there are no more samples
// and length is 0, trigger an interrupt. // 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;
}
}
} }

View File

@ -53,6 +53,9 @@ class Audio: public DMADevice<4> {
/// their neighbours. /// their neighbours.
void set_modulation_flags(uint16_t); void set_modulation_flags(uint16_t);
/// Sets which interrupt requests are currently active.
void set_interrupt_requests(uint16_t);
private: private:
struct Channel { struct Channel {
// The data latch plus a count of unused samples // 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. // Indicates whether DMA is enabled for this channel.
bool dma_enabled = false; bool dma_enabled = false;
// Records whether this audio interrupt is pending.
bool interrupt_pending = false;
// Replicates the Hardware Reference Manual state machine; // Replicates the Hardware Reference Manual state machine;
// comments indicate which of the documented states each // comments indicate which of the documented states each
// label refers to. // label refers to.
@ -83,7 +89,7 @@ class Audio: public DMADevice<4> {
WaitingForDMA, // 101 WaitingForDMA, // 101
PlayingHigh, // 010 PlayingHigh, // 010
PlayingLow, // 011 PlayingLow, // 011
} state_; } state = State::Disabled;
} channels_[4]; } channels_[4];
}; };

View File

@ -750,6 +750,7 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) {
case Write(0x09c): // INTREQ case Write(0x09c): // INTREQ
ApplySetClear(interrupt_requests_, 0x7fff); ApplySetClear(interrupt_requests_, 0x7fff);
update_interrupts(); update_interrupts();
audio_->set_interrupt_requests(interrupt_requests_);
break; break;
case Read(0x01e): // INTREQR case Read(0x01e): // INTREQR
cycle.set_value16(interrupt_requests_); cycle.set_value16(interrupt_requests_);