Attempt audio, fix computer clock rate.
This commit is contained in:
1 parent
b4c41e13a0
commit
beca7c2738
1 file changed
+61
-6
@@ -20,6 +20,10 @@
|
||||
#include "Machines/MachineTypes.hpp"
|
||||
#include "Machines/Utility/MemoryFuzzer.hpp"
|
||||
|
||||
#include "Components/AudioToggle/AudioToggle.hpp"
|
||||
#include "Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
|
||||
#include "Outputs/Speaker/Implementation/BufferSource.hpp"
|
||||
|
||||
using namespace Tandy::CoCo;
|
||||
|
||||
namespace {
|
||||
@@ -80,6 +84,7 @@ struct Joystick: public Inputs::ConcreteJoystick {
|
||||
bool buttons[2]{};
|
||||
};
|
||||
|
||||
static constexpr uint8_t MaxDACLevel = 0b111'111;
|
||||
static constexpr double ClockRate = 1'789'772.5;
|
||||
|
||||
}
|
||||
@@ -90,6 +95,7 @@ class ConcreteMachine:
|
||||
public Activity::Source,
|
||||
public Configurable::Device,
|
||||
public Machine,
|
||||
public MachineTypes::AudioProducer,
|
||||
public MachineTypes::JoystickMachine,
|
||||
public MachineTypes::MappedKeyboardMachine,
|
||||
public MachineTypes::MediaChangeObserver,
|
||||
@@ -107,9 +113,12 @@ public:
|
||||
pia1_(pia1_handler_),
|
||||
sam_(memory_),
|
||||
m6847_(sam_),
|
||||
tape_player_(int(ClockRate))
|
||||
tape_player_(int(ClockRate)),
|
||||
audio_(audio_queue_, MaxDACLevel),
|
||||
speaker_(audio_)
|
||||
{
|
||||
set_clock_rate(ClockRate);
|
||||
speaker_.set_input_rate(ClockRate);
|
||||
construct_joysticks();
|
||||
|
||||
const auto BasicROM = ROM::Name::TandyCoCoColourBasic12;
|
||||
@@ -133,6 +142,10 @@ public:
|
||||
type_string(target.loading_command);
|
||||
}
|
||||
|
||||
~ConcreteMachine() {
|
||||
audio_queue_.lock_flush();
|
||||
}
|
||||
|
||||
template <
|
||||
CPU::M6809::BusPhase bus_phase,
|
||||
CPU::M6809::LIC lic,
|
||||
@@ -155,6 +168,7 @@ public:
|
||||
if(typer_) {
|
||||
typer_->run_for(duration);
|
||||
}
|
||||
time_since_audio_update_ += duration;
|
||||
|
||||
using namespace CPU::M6809;
|
||||
if(address >> 8 == 0xff) {
|
||||
@@ -290,7 +304,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
return duration;
|
||||
return delay;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -314,6 +328,9 @@ private:
|
||||
if(outputs & Output::Video) {
|
||||
m6847_.flush();
|
||||
}
|
||||
if(outputs & Output::Audio) {
|
||||
update_audio();
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - PIAs.
|
||||
@@ -397,9 +414,11 @@ private:
|
||||
void observe(const bool value) {
|
||||
if constexpr (control == Motorola::MC6821::Control::CA2) {
|
||||
joystick_ = value;
|
||||
machine_.mux_ = (machine_.mux_ & 1) | (value ? 2 : 0);
|
||||
}
|
||||
if constexpr (control == Motorola::MC6821::Control::CB2) {
|
||||
axis_ = value;
|
||||
machine_.mux_ = (machine_.mux_ & 2) | (value ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,7 +470,7 @@ private:
|
||||
// b4–b6: VDG GM inputs; also b5 = 6847 invert; b4 = 6847 shift toggle
|
||||
// b3: colour set select (and RGB monitor detecting input? Probably CoCo3)
|
||||
// b2: ram size input
|
||||
// b1: 1-bit sound/tape output
|
||||
// b1: 1-bit sound/tape something?
|
||||
// b0: RS232 data input
|
||||
//
|
||||
// CB1: cartridge interrupt input
|
||||
@@ -477,7 +496,10 @@ private:
|
||||
template <Motorola::MC6821::Port port>
|
||||
void output(const uint8_t value) {
|
||||
if constexpr (port == Motorola::MC6821::Port::A) {
|
||||
machine_.dac_level_ = (value >> 2) & 0b111111;
|
||||
machine_.dac_level_ = value >> 2;
|
||||
if(!machine_.mux_) {
|
||||
machine_.set_audio(true, value >> 2); // std::nullopt
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (port == Motorola::MC6821::Port::B) {
|
||||
@@ -508,6 +530,7 @@ private:
|
||||
}
|
||||
|
||||
if constexpr (control == Motorola::MC6821::Control::CB2) {
|
||||
// machine_.set_audio(value, std::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,8 +540,6 @@ private:
|
||||
PIA1Handler pia1_handler_;
|
||||
Motorola::MC6821::MC6821<PIA1Handler> pia1_;
|
||||
|
||||
uint8_t dac_level_ = 0;
|
||||
|
||||
// MARK: - SAM.
|
||||
|
||||
struct SAM {
|
||||
@@ -751,6 +772,40 @@ private:
|
||||
return *static_cast<Joystick *>(joysticks_[index].get());
|
||||
}
|
||||
|
||||
// MARK: - AudioProducer.
|
||||
|
||||
Concurrency::AsyncTaskQueue<false> audio_queue_;
|
||||
Audio::DAC audio_;
|
||||
Outputs::Speaker::PullLowpass<Audio::DAC> speaker_;
|
||||
|
||||
Cycles time_since_audio_update_;
|
||||
void update_audio() {
|
||||
const auto cycles = time_since_audio_update_.flush();
|
||||
speaker_.run_for(audio_queue_, cycles);
|
||||
}
|
||||
|
||||
Outputs::Speaker::Speaker *get_speaker() override {
|
||||
return &speaker_;
|
||||
}
|
||||
|
||||
bool audio_enabled_ = false;
|
||||
uint8_t audio_level_ = 0;
|
||||
void set_audio(const std::optional<bool> enabled, const std::optional<uint8_t> level) {
|
||||
const auto new_audio_enabled = enabled.value_or(audio_enabled_);
|
||||
const auto new_audio_level = level.value_or(audio_level_);
|
||||
if(new_audio_level == audio_level_ && new_audio_enabled == audio_enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
audio_level_ = new_audio_level;
|
||||
audio_enabled_ = new_audio_enabled;
|
||||
update_audio();
|
||||
audio_.set_output(audio_enabled_ ? audio_level_ : 0);
|
||||
}
|
||||
|
||||
uint8_t dac_level_ = 0;
|
||||
uint8_t mux_ = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user