mirror of
https://github.com/TomHarte/CLK.git
synced 2025-12-20 06:16:41 +00:00
Attempt some basic voice details.
This commit is contained in:
@@ -44,7 +44,7 @@ struct BBCMicroTarget: public ::Analyser::Static::Target, public Reflection::Str
|
|||||||
bool has_1770dfs = false;
|
bool has_1770dfs = false;
|
||||||
bool has_adfs = false;
|
bool has_adfs = false;
|
||||||
bool has_sideways_ram = true;
|
bool has_sideways_ram = true;
|
||||||
bool has_beebsid = true;
|
bool has_beebsid = true; // TODO: false is a much better default.
|
||||||
|
|
||||||
ReflectableEnum(TubeProcessor, None, WDC65C02, Z80);
|
ReflectableEnum(TubeProcessor, None, WDC65C02, Z80);
|
||||||
TubeProcessor tube_processor = TubeProcessor::None;
|
TubeProcessor tube_processor = TubeProcessor::None;
|
||||||
|
|||||||
@@ -12,6 +12,30 @@ using namespace MOS::SID;
|
|||||||
|
|
||||||
SID::SID(Concurrency::AsyncTaskQueue<false> &audio_queue) : audio_queue_(audio_queue) {}
|
SID::SID(Concurrency::AsyncTaskQueue<false> &audio_queue) : audio_queue_(audio_queue) {}
|
||||||
|
|
||||||
|
|
||||||
|
void SID::write(const Numeric::SizedInt<5> address, const uint8_t value) {
|
||||||
|
switch(address.get()) {
|
||||||
|
case 0x00: case 0x07: case 0x0e: voices_[address.get() / 7].frequency.load<0>(value); break;
|
||||||
|
case 0x01: case 0x08: case 0x0f: voices_[address.get() / 7].frequency.load<8>(value); break;
|
||||||
|
case 0x02: case 0x09: case 0x10: voices_[address.get() / 7].pulse_width.load<0>(value); break;
|
||||||
|
case 0x03: case 0x0a: case 0x11: voices_[address.get() / 7].pulse_width.load<8>(value); break;
|
||||||
|
case 0x04: case 0x0b: case 0x12: voices_[address.get() / 7].control = value; break;
|
||||||
|
case 0x05: case 0x0c: case 0x13:
|
||||||
|
voices_[address.get() / 7].attack = value >> 4;
|
||||||
|
voices_[address.get() / 7].decay = value;
|
||||||
|
break;
|
||||||
|
case 0x06: case 0x0d: case 0x14:
|
||||||
|
voices_[address.get() / 7].sustain = value >> 4;
|
||||||
|
voices_[address.get() / 7].release = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SID::read(const Numeric::SizedInt<5> address) {
|
||||||
|
(void)address;
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
void SID::set_sample_volume_range(const std::int16_t range) {
|
void SID::set_sample_volume_range(const std::int16_t range) {
|
||||||
(void)range;
|
(void)range;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Numeric/SizedInt.hpp"
|
||||||
|
|
||||||
#include "Concurrency/AsyncTaskQueue.hpp"
|
#include "Concurrency/AsyncTaskQueue.hpp"
|
||||||
#include "Outputs/Speaker/Implementation/BufferSource.hpp"
|
#include "Outputs/Speaker/Implementation/BufferSource.hpp"
|
||||||
|
|
||||||
@@ -17,6 +19,10 @@ class SID: public Outputs::Speaker::BufferSource<SID, false> {
|
|||||||
public:
|
public:
|
||||||
SID(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
SID(Concurrency::AsyncTaskQueue<false> &audio_queue);
|
||||||
|
|
||||||
|
void write(Numeric::SizedInt<5> address, uint8_t value);
|
||||||
|
uint8_t read(Numeric::SizedInt<5> address);
|
||||||
|
|
||||||
|
// Outputs::Speaker::BufferSource.
|
||||||
template <Outputs::Speaker::Action action>
|
template <Outputs::Speaker::Action action>
|
||||||
void apply_samples(std::size_t number_of_samples, Outputs::Speaker::MonoSample *target);
|
void apply_samples(std::size_t number_of_samples, Outputs::Speaker::MonoSample *target);
|
||||||
bool is_zero_level() const;
|
bool is_zero_level() const;
|
||||||
@@ -24,6 +30,18 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Concurrency::AsyncTaskQueue<false> &audio_queue_;
|
Concurrency::AsyncTaskQueue<false> &audio_queue_;
|
||||||
|
|
||||||
|
struct Voice {
|
||||||
|
Numeric::SizedInt<16> frequency;
|
||||||
|
Numeric::SizedInt<12> pulse_width;
|
||||||
|
Numeric::SizedInt<8> control;
|
||||||
|
Numeric::SizedInt<4> attack;
|
||||||
|
Numeric::SizedInt<4> decay;
|
||||||
|
Numeric::SizedInt<4> sustain;
|
||||||
|
Numeric::SizedInt<4> release;
|
||||||
|
};
|
||||||
|
|
||||||
|
Voice voices_[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ private:
|
|||||||
/*!
|
/*!
|
||||||
Combines an SN76489 with an appropriate asynchronous queue and filtering speaker.
|
Combines an SN76489 with an appropriate asynchronous queue and filtering speaker.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: generalise the below and clean up across the project.
|
||||||
template <bool has_beebsid>
|
template <bool has_beebsid>
|
||||||
struct Audio {
|
struct Audio {
|
||||||
private:
|
private:
|
||||||
@@ -147,7 +149,7 @@ public:
|
|||||||
return sn76489_;
|
return sn76489_;
|
||||||
}
|
}
|
||||||
if constexpr (std::is_same_v<TargetT, MOS::SID::SID>) {
|
if constexpr (std::is_same_v<TargetT, MOS::SID::SID>) {
|
||||||
return sn76489_;
|
return sid_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,6 +1029,12 @@ public:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if(has_beebsid && address >= 0xfc20 && address < 0xfc40) {
|
||||||
|
if constexpr (is_read(operation)) {
|
||||||
|
value = audio_.template get<MOS::SID::SID>().read(+address);
|
||||||
|
} else {
|
||||||
|
audio_.template get<MOS::SID::SID>().write(+address, value);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Logger::error()
|
Logger::error()
|
||||||
.append("Unhandled IO %s at %04x", is_read(operation) ? "read" : "write", address)
|
.append("Unhandled IO %s at %04x", is_read(operation) ? "read" : "write", address)
|
||||||
|
|||||||
Reference in New Issue
Block a user