1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Attempts a full audio wiring.

This commit is contained in:
Thomas Harte 2021-03-18 12:23:54 -04:00
parent 4a4da90d56
commit 17f551e89d

View File

@ -49,6 +49,7 @@ template<Model model> class ConcreteMachine:
speaker_(mixer_) speaker_(mixer_)
{ {
set_clock_rate(ClockRate); set_clock_rate(ClockRate);
speaker_.set_input_rate(float(ClockRate) / 2.0f);
// With only the +2a and +3 currently supported, the +3 ROM is always // With only the +2a and +3 currently supported, the +3 ROM is always
// the one required. // the one required.
@ -64,12 +65,21 @@ template<Model model> class ConcreteMachine:
(void)target; (void)target;
} }
~ConcreteMachine() {
audio_queue_.flush();
}
// MARK: - TimedMachine // MARK: - TimedMachine
void run_for(const Cycles cycles) override { void run_for(const Cycles cycles) override {
z80_.run_for(cycles); z80_.run_for(cycles);
} }
void flush() {
update_audio();
audio_queue_.perform();
}
// MARK: - ScanProducer // MARK: - ScanProducer
void set_scan_target(Outputs::Display::ScanTarget *scan_target) final { void set_scan_target(Outputs::Display::ScanTarget *scan_target) final {
@ -84,6 +94,8 @@ template<Model model> class ConcreteMachine:
// MARK: - BusHandler // MARK: - BusHandler
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) { forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
time_since_audio_update_ += cycle.length;
// Ignore all but terminal cycles. // Ignore all but terminal cycles.
// TODO: I doubt this is correct for timing. // TODO: I doubt this is correct for timing.
if(!cycle.is_terminal()) return HalfCycles(0); if(!cycle.is_terminal()) return HalfCycles(0);
@ -103,22 +115,42 @@ template<Model model> class ConcreteMachine:
case PartialMachineCycle::Output: case PartialMachineCycle::Output:
if(!(address&1)) { if(!(address&1)) {
// TODO: port FE. // TODO: rest of port FE.
update_audio();
audio_toggle_.set_output(*cycle.value & 0x10);
} }
switch(address) { switch(address) {
default: break; default: break;
case 0x1ffd: case 0x1ffd:
// Write to +2a/+3 paging register.
port1ffd_ = *cycle.value; port1ffd_ = *cycle.value;
update_memory_map(); update_memory_map();
break; break;
case 0x7ffd: case 0x7ffd:
// Write to classic 128kb paging register.
disable_paging_ |= *cycle.value & 0x20; disable_paging_ |= *cycle.value & 0x20;
port7ffd_ = *cycle.value; port7ffd_ = *cycle.value;
update_memory_map(); update_memory_map();
break; break;
case 0xfffd:
// Select AY register.
update_audio();
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BDIR | GI::AY38910::BC2 | GI::AY38910::BC1));
ay_.set_data_input(*cycle.value);
ay_.set_control_lines(GI::AY38910::ControlLines(0));
break;
case 0xbffd:
// Write to AY register.
update_audio();
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BDIR | GI::AY38910::BC2));
ay_.set_data_input(*cycle.value);
ay_.set_control_lines(GI::AY38910::ControlLines(0));
break;
} }
break; break;
@ -126,6 +158,18 @@ template<Model model> class ConcreteMachine:
if(!(address&1)) { if(!(address&1)) {
// TODO: port FE. // TODO: port FE.
} }
switch(address) {
default: break;
case 0xfffd:
// Read from AY register.
update_audio();
ay_.set_control_lines(GI::AY38910::ControlLines(GI::AY38910::BC2 | GI::AY38910::BC1));
*cycle.value &= ay_.get_data_output();
ay_.set_control_lines(GI::AY38910::ControlLines(0));
break;
}
break; break;
} }
@ -213,6 +257,11 @@ template<Model model> class ConcreteMachine:
Audio::Toggle audio_toggle_; Audio::Toggle audio_toggle_;
Outputs::Speaker::CompoundSource<GI::AY38910::AY38910<false>, Audio::Toggle> mixer_; Outputs::Speaker::CompoundSource<GI::AY38910::AY38910<false>, Audio::Toggle> mixer_;
Outputs::Speaker::LowpassSpeaker<Outputs::Speaker::CompoundSource<GI::AY38910::AY38910<false>, Audio::Toggle>> speaker_; Outputs::Speaker::LowpassSpeaker<Outputs::Speaker::CompoundSource<GI::AY38910::AY38910<false>, Audio::Toggle>> speaker_;
HalfCycles time_since_audio_update_;
void update_audio() {
speaker_.run_for(audio_queue_, time_since_audio_update_.divide_cycles(Cycles(2)));
}
}; };