mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-16 18:30:32 +00:00
Starts in the direction of audio support.
This commit is contained in:
parent
c7ab3d4075
commit
98347cb1c3
@ -389,7 +389,7 @@ void IWM::propose_shift(uint8_t bit) {
|
|||||||
|
|
||||||
shift_register_ = uint8_t((shift_register_ << 1) | bit);
|
shift_register_ = uint8_t((shift_register_ << 1) | bit);
|
||||||
if(shift_register_ & 0x80) {
|
if(shift_register_ & 0x80) {
|
||||||
if(data_register_ & 0x80) LOG("Byte missed");
|
// if(data_register_ & 0x80) LOG("Byte missed");
|
||||||
data_register_ = shift_register_;
|
data_register_ = shift_register_;
|
||||||
shift_register_ = 0;
|
shift_register_ = 0;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "../../../Components/DiskII/IWM.hpp"
|
#include "../../../Components/DiskII/IWM.hpp"
|
||||||
#include "../../../Components/DiskII/MacintoshDoubleDensityDrive.hpp"
|
#include "../../../Components/DiskII/MacintoshDoubleDensityDrive.hpp"
|
||||||
|
|
||||||
|
#include "../../../Outputs/Speaker/Implementation/CompoundSource.hpp"
|
||||||
#include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
|
#include "../../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
|
||||||
|
|
||||||
#include "../../Utility/MemoryFuzzer.hpp"
|
#include "../../Utility/MemoryFuzzer.hpp"
|
||||||
@ -59,8 +60,10 @@ class ConcreteMachine:
|
|||||||
{CLOCK_RATE / 2, true},
|
{CLOCK_RATE / 2, true},
|
||||||
{CLOCK_RATE / 2, true}
|
{CLOCK_RATE / 2, true}
|
||||||
},
|
},
|
||||||
|
sound_glu_(audio_queue_),
|
||||||
audio_toggle_(audio_queue_),
|
audio_toggle_(audio_queue_),
|
||||||
speaker_(audio_toggle_) {
|
mixer_(sound_glu_, audio_toggle_),
|
||||||
|
speaker_(mixer_) {
|
||||||
|
|
||||||
set_clock_rate(double(CLOCK_RATE));
|
set_clock_rate(double(CLOCK_RATE));
|
||||||
speaker_.set_input_rate(float(CLOCK_RATE) / float(audio_divider));
|
speaker_.set_input_rate(float(CLOCK_RATE) / float(audio_divider));
|
||||||
@ -738,14 +741,18 @@ class ConcreteMachine:
|
|||||||
Apple::Macintosh::DoubleDensityDrive drives_[2];
|
Apple::Macintosh::DoubleDensityDrive drives_[2];
|
||||||
|
|
||||||
// The audio parts.
|
// The audio parts.
|
||||||
Apple::IIgs::Sound::GLU sound_glu_;
|
|
||||||
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
||||||
|
Apple::IIgs::Sound::GLU sound_glu_;
|
||||||
Audio::Toggle audio_toggle_;
|
Audio::Toggle audio_toggle_;
|
||||||
Outputs::Speaker::LowpassSpeaker<Audio::Toggle> speaker_;
|
using AudioSource = Outputs::Speaker::CompoundSource<Apple::IIgs::Sound::GLU, Audio::Toggle>;
|
||||||
|
AudioSource mixer_;
|
||||||
|
Outputs::Speaker::LowpassSpeaker<AudioSource> speaker_;
|
||||||
Cycles cycles_since_audio_update_;
|
Cycles cycles_since_audio_update_;
|
||||||
static constexpr int audio_divider = 8;
|
static constexpr int audio_divider = 8;
|
||||||
void update_audio() {
|
void update_audio() {
|
||||||
speaker_.run_for(audio_queue_, cycles_since_audio_update_.divide(Cycles(audio_divider)));
|
const auto divided_cycles = cycles_since_audio_update_.divide(Cycles(audio_divider));
|
||||||
|
sound_glu_.run_for(divided_cycles);
|
||||||
|
speaker_.run_for(audio_queue_, divided_cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Cards.
|
// MARK: - Cards.
|
||||||
|
@ -12,22 +12,64 @@
|
|||||||
|
|
||||||
using namespace Apple::IIgs::Sound;
|
using namespace Apple::IIgs::Sound;
|
||||||
|
|
||||||
void GLU::set_control(uint8_t control) {
|
GLU::GLU(Concurrency::DeferringAsyncTaskQueue &audio_queue) : audio_queue_(audio_queue) {}
|
||||||
// printf("UNIMPLEMENTED: set control %02x\n", control);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t GLU::get_control() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLU::set_data(uint8_t data) {
|
void GLU::set_data(uint8_t data) {
|
||||||
// printf("UNIMPLEMENTED: set data %02x\n", data);
|
if(control_ & 0x40) {
|
||||||
|
// RAM access.
|
||||||
|
local_.ram_[address_] = data;
|
||||||
|
} else {
|
||||||
|
// Register access.
|
||||||
|
switch(address_ & 0xe0) {
|
||||||
|
case 0x00:
|
||||||
|
// oscillators_[address_ & 0x1f].velocity = (oscillators_[address_ & 0x1f].velocity & 0xff00) | (data << 8);
|
||||||
|
break;
|
||||||
|
case 0x20:
|
||||||
|
// oscillators_[address_ & 0x1f].velocity = (oscillators_[address_ & 0x1f].velocity & 0x00ff) | (data << 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("Register write %04x\n", address_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(control_ & 0x20) {
|
||||||
|
++address_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GLU::get_data() {
|
uint8_t GLU::get_data() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Update logic.
|
||||||
|
|
||||||
|
void GLU::run_for(Cycles cycles) {
|
||||||
|
// Update local state, without generating audio.
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLU::get_samples(std::size_t number_of_samples, std::int16_t *target) {
|
||||||
|
// Update remote state, generating audio.
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLU::skip_samples(const std::size_t number_of_samples) {
|
||||||
|
// Update remote state, without generating audio.
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLU::set_sample_volume_range(std::int16_t range) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Interface boilerplate.
|
||||||
|
|
||||||
|
void GLU::set_control(uint8_t control) {
|
||||||
|
control_ = control;
|
||||||
|
|
||||||
|
// Low three bits are volume control: this probably needs to be fed off-thrad?
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t GLU::get_control() {
|
||||||
|
return control_;
|
||||||
|
}
|
||||||
|
|
||||||
void GLU::set_address_low(uint8_t low) {
|
void GLU::set_address_low(uint8_t low) {
|
||||||
address_ = uint16_t((address_ & 0xff00) | low);
|
address_ = uint16_t((address_ & 0xff00) | low);
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,17 @@
|
|||||||
#define Apple_IIgs_Sound_hpp
|
#define Apple_IIgs_Sound_hpp
|
||||||
|
|
||||||
#include "../../../ClockReceiver/ClockReceiver.hpp"
|
#include "../../../ClockReceiver/ClockReceiver.hpp"
|
||||||
|
#include "../../../Concurrency/AsyncTaskQueue.hpp"
|
||||||
|
#include "../../../Outputs/Speaker/Implementation/SampleSource.hpp"
|
||||||
|
|
||||||
namespace Apple {
|
namespace Apple {
|
||||||
namespace IIgs {
|
namespace IIgs {
|
||||||
namespace Sound {
|
namespace Sound {
|
||||||
|
|
||||||
class GLU {
|
class GLU: public Outputs::Speaker::SampleSource {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
GLU(Concurrency::DeferringAsyncTaskQueue &audio_queue);
|
||||||
|
|
||||||
void set_control(uint8_t);
|
void set_control(uint8_t);
|
||||||
uint8_t get_control();
|
uint8_t get_control();
|
||||||
void set_data(uint8_t);
|
void set_data(uint8_t);
|
||||||
@ -27,8 +30,35 @@ class GLU {
|
|||||||
void set_address_high(uint8_t);
|
void set_address_high(uint8_t);
|
||||||
uint8_t get_address_high();
|
uint8_t get_address_high();
|
||||||
|
|
||||||
|
void run_for(Cycles);
|
||||||
|
|
||||||
|
// SampleSource.
|
||||||
|
void get_samples(std::size_t number_of_samples, std::int16_t *target);
|
||||||
|
void set_sample_volume_range(std::int16_t range);
|
||||||
|
void skip_samples(const std::size_t number_of_samples);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Concurrency::DeferringAsyncTaskQueue &audio_queue_;
|
||||||
|
|
||||||
uint16_t address_ = 0;
|
uint16_t address_ = 0;
|
||||||
|
|
||||||
|
struct EnsoniqState {
|
||||||
|
uint8_t ram_[65536];
|
||||||
|
struct Oscillator {
|
||||||
|
uint32_t position;
|
||||||
|
|
||||||
|
// Programmer-set values.
|
||||||
|
uint16_t velocity;
|
||||||
|
uint8_t volume;
|
||||||
|
uint8_t address;
|
||||||
|
uint8_t control;
|
||||||
|
uint8_t table_size;
|
||||||
|
} oscillators_[32];
|
||||||
|
} local_, remote_;
|
||||||
|
uint8_t interrupt_state_;
|
||||||
|
uint8_t oscillator_enable_;
|
||||||
|
|
||||||
|
uint8_t control_ = 0x00;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user