commit cae54d750224b623ce515c9325f5067ee2b7e0ea
parent 774c14c323c1d901a26aa7399c3bc1377079491b
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Tue, 30 Apr 2024 23:15:28 +0200
refactor xt/mq hardware classes, remove duplicated code by moving to base class
Diffstat:
6 files changed, 269 insertions(+), 420 deletions(-)
diff --git a/source/mqLib/mqhardware.cpp b/source/mqLib/mqhardware.cpp
@@ -18,15 +18,9 @@ namespace mqLib
static_assert(ROM_DATA_SIZE == ROM::g_romSize);
#endif
- constexpr uint32_t g_syncEsaiFrameRate = 8;
- constexpr uint32_t g_syncHaltDspEsaiThreshold = 16;
-
- static_assert((g_syncEsaiFrameRate & (g_syncEsaiFrameRate - 1)) == 0, "esai frame sync rate must be power of two");
- static_assert(g_syncHaltDspEsaiThreshold >= g_syncEsaiFrameRate * 2, "esai DSP halt threshold must be greater than two times the sync rate");
-
- Hardware::Hardware(std::string _romFilename)
- : m_romFileName(std::move(_romFilename))
- , m_rom(m_romFileName, ROM_DATA)
+ Hardware::Hardware(const std::string& _romFilename)
+ : wLib::Hardware(44100)
+ , m_rom(_romFilename, ROM_DATA)
, m_uc(m_rom)
#if MQ_VOICE_EXPANSION
, m_dsps{MqDsp(*this, m_uc.getHdi08A().getHdi08(), 0), MqDsp(*this, m_uc.getHdi08B().getHdi08(), 1) , MqDsp(*this, m_uc.getHdi08C().getHdi08(), 2)}
@@ -54,16 +48,6 @@ namespace mqLib
{
processUcCycle();
}
-
- void Hardware::sendMidi(const synthLib::SMidiEvent& _ev)
- {
- m_midiIn.push_back(_ev);
- }
-
- void Hardware::receiveMidi(std::vector<uint8_t>& _data)
- {
- m_midi.readTransmitBuffer(_data);
- }
void Hardware::setBootMode(const BootMode _mode)
{
@@ -138,29 +122,6 @@ namespace mqLib
#endif
}
- void Hardware::ucYieldLoop(const std::function<bool()>& _continue)
- {
- const auto dspHalted = m_haltDSP;
-
- resumeDSP();
-
- while(_continue())
- {
- if(m_processAudio)
- {
- std::this_thread::yield();
- }
- else
- {
- std::unique_lock uLock(m_esaiFrameAddedMutex);
- m_esaiFrameAddedCv.wait(uLock);
- }
- }
-
- if(dspHalted)
- haltDSP();
- }
-
void Hardware::initVoiceExpansion()
{
if (m_dsps.size() < 3)
@@ -221,27 +182,7 @@ namespace mqLib
esaiA.setCallback([&](dsp56k::Audio*)
{
- ++m_esaiFrameIndex;
-
- processMidiInput();
-
- if((m_esaiFrameIndex & (g_syncEsaiFrameRate-1)) == 0)
- m_esaiFrameAddedCv.notify_one();
-
- m_requestedFramesAvailableMutex.lock();
-
- if(m_requestedFrames && esaiA.getAudioOutputs().size() >= m_requestedFrames)
- {
- m_requestedFramesAvailableMutex.unlock();
- m_requestedFramesAvailableCv.notify_one();
- }
- else
- {
- m_requestedFramesAvailableMutex.unlock();
- }
-
- std::unique_lock uLock(m_haltDSPmutex);
- m_haltDSPcv.wait(uLock, [&]{ return m_haltDSP == false; });
+ onEsaiCallback(esaiA);
}, 0);
}
@@ -275,27 +216,6 @@ namespace mqLib
}
}
- void Hardware::haltDSP()
- {
- if(m_haltDSP)
- return;
-
- std::lock_guard uLockHalt(m_haltDSPmutex);
- m_haltDSP = true;
- }
-
- void Hardware::resumeDSP()
- {
- if(!m_haltDSP)
- return;
-
- {
- std::lock_guard uLockHalt(m_haltDSPmutex);
- m_haltDSP = false;
- }
- m_haltDSPcv.notify_one();
- }
-
void Hardware::setGlobalDefaultParameters()
{
m_midi.writeMidi({0xf0,0x3e,0x10,0x7f,0x24,0x00,0x07,0x02,0xf7}); // Control Send = SysEx
@@ -303,76 +223,6 @@ namespace mqLib
m_bootCompleted = true;
}
- void Hardware::syncUcToDSP()
- {
- if(m_remainingUcCycles > 0)
- return;
-
- // we can only use ESAI to clock the uc once it has been enabled
- if(m_esaiFrameIndex <= 0)
- return;
-
- if(m_esaiFrameIndex == m_lastEsaiFrameIndex)
- {
- resumeDSP();
- std::unique_lock uLock(m_esaiFrameAddedMutex);
- m_esaiFrameAddedCv.wait(uLock, [this]{return m_esaiFrameIndex > m_lastEsaiFrameIndex;});
- }
-
- const auto esaiFrameIndex = m_esaiFrameIndex;
-
- const auto ucClock = m_uc.getSim().getSystemClockHz();
-
- constexpr double divInv = 1.0 / 44100.0; // stereo interleaved
- const double ucCyclesPerFrame = static_cast<double>(ucClock) * divInv;
-
- const auto esaiDelta = esaiFrameIndex - m_lastEsaiFrameIndex;
-
- m_remainingUcCyclesD += ucCyclesPerFrame * static_cast<double>(esaiDelta);
- m_remainingUcCycles = static_cast<int64_t>(m_remainingUcCyclesD);
- m_remainingUcCyclesD -= static_cast<double>(m_remainingUcCycles);
-
- if(esaiDelta > g_syncHaltDspEsaiThreshold)
- {
- haltDSP();
- }
- else
- {
- resumeDSP();
- }
-
- m_lastEsaiFrameIndex = esaiFrameIndex;
- }
-
- void Hardware::processMidiInput()
- {
- ++m_midiOffsetCounter;
-
- while(!m_midiIn.empty())
- {
- const auto& e = m_midiIn.front();
-
- if(e.offset > m_midiOffsetCounter)
- break;
-
- if(!e.sysex.empty())
- {
- m_midi.writeMidi(e.sysex);
- }
- else
- {
- m_midi.writeMidi(e.a);
- const auto len = synthLib::MidiBufferParser::lengthFromStatusByte(e.a);
- if (len > 1)
- m_midi.writeMidi(e.b);
- if (len > 2)
- m_midi.writeMidi(e.c);
- }
-
- m_midiIn.pop_front();
- }
- }
-
void Hardware::processAudio(uint32_t _frames, uint32_t _latency)
{
ensureBufferSize(_frames);
diff --git a/source/mqLib/mqhardware.h b/source/mqLib/mqhardware.h
@@ -22,7 +22,7 @@ namespace mqLib
static constexpr uint32_t g_dspCount = g_useVoiceExpansion ? 3 : 1;
public:
- explicit Hardware(std::string _romFilename);
+ explicit Hardware(const std::string& _romFilename);
~Hardware();
void process();
@@ -34,9 +34,6 @@ namespace mqLib
auto& getAudioInputs() { return m_audioInputs; }
auto& getAudioOutputs() { return m_audioOutputs; }
- void sendMidi(const synthLib::SMidiEvent& _ev);
- void receiveMidi(std::vector<uint8_t>& _data);
-
dsp56k::DSPThread& getDspThread(uint32_t _index = 0) { return m_dsps[_index].thread(); }
void processAudio(uint32_t _frames, uint32_t _latency = 0);
@@ -55,57 +52,33 @@ namespace mqLib
bool isBootCompleted() const { return m_bootCompleted; }
void resetMidiCounter();
- void ucYieldLoop(const std::function<bool()>& _continue);
void initVoiceExpansion();
+ wLib::Midi& getMidi() override
+ {
+ return m_midi;
+ }
+
+ mc68k::Mc68k& getUc() override
+ {
+ return m_uc;
+ }
+
private:
void setupEsaiListener();
void hdiProcessUCtoDSPNMIIrq();
void processUcCycle();
- void haltDSP();
- void resumeDSP();
void setGlobalDefaultParameters();
- void syncUcToDSP();
- void processMidiInput();
-
- const std::string m_romFileName;
const ROM m_rom;
bool m_requestNMI = false;
- // timing
- uint32_t m_esaiFrameIndex = 0;
- uint32_t m_lastEsaiFrameIndex = 0;
- int64_t m_remainingUcCycles = 0;
- double m_remainingUcCyclesD = 0;
-
MqMc m_uc;
- std::array<MqDsp,g_dspCount> m_dsps;
-
- wLib::Midi m_midi;
- dsp56k::RingBuffer<synthLib::SMidiEvent, 16384, true> m_midiIn;
- uint32_t m_midiOffsetCounter = 0;
-
- std::vector<dsp56k::TWord> m_delayedAudioIn;
-
- std::vector<dsp56k::TWord> m_dummyInput;
- std::vector<dsp56k::TWord> m_dummyOutput;
-
TAudioInputs m_audioInputs;
TAudioOutputs m_audioOutputs;
+ std::array<MqDsp,g_dspCount> m_dsps;
- std::mutex m_esaiFrameAddedMutex;
- std::condition_variable m_esaiFrameAddedCv;
-
- std::mutex m_requestedFramesAvailableMutex;
- std::condition_variable m_requestedFramesAvailableCv;
- size_t m_requestedFrames = 0;
-
- bool m_haltDSP = false;
- std::condition_variable m_haltDSPcv;
- std::mutex m_haltDSPmutex;
- bool m_processAudio = false;
- bool m_bootCompleted = false;
+ wLib::Midi m_midi;
};
}
diff --git a/source/wLib/wHardware.cpp b/source/wLib/wHardware.cpp
@@ -1,5 +1,170 @@
#include "wHardware.h"
+#include "wMidi.h"
+#include "dsp56kEmu/audio.h"
+
+#include "../synthLib/midiBufferParser.h"
+
+#include "../mc68k/mc68k.h"
+
namespace wLib
{
+ constexpr uint32_t g_syncEsaiFrameRate = 8;
+ constexpr uint32_t g_syncHaltDspEsaiThreshold = 16;
+
+ static_assert((g_syncEsaiFrameRate & (g_syncEsaiFrameRate - 1)) == 0, "esai frame sync rate must be power of two");
+ static_assert(g_syncHaltDspEsaiThreshold >= g_syncEsaiFrameRate * 2, "esai DSP halt threshold must be greater than two times the sync rate");
+
+ Hardware::Hardware(const double& _samplerate) : m_samplerateInv(1.0 / _samplerate)
+ {
+ }
+
+ void Hardware::haltDSP()
+ {
+ if(m_haltDSP)
+ return;
+
+ std::lock_guard uLockHalt(m_haltDSPmutex);
+ m_haltDSP = true;
+ }
+
+ void Hardware::resumeDSP()
+ {
+ if(!m_haltDSP)
+ return;
+
+ {
+ std::lock_guard uLockHalt(m_haltDSPmutex);
+ m_haltDSP = false;
+ }
+ m_haltDSPcv.notify_one();
+ }
+
+ void Hardware::ucYieldLoop(const std::function<bool()>& _continue)
+ {
+ const auto dspHalted = m_haltDSP;
+
+ resumeDSP();
+
+ while(_continue())
+ {
+ if(m_processAudio)
+ {
+ std::this_thread::yield();
+ }
+ else
+ {
+ std::unique_lock uLock(m_esaiFrameAddedMutex);
+ m_esaiFrameAddedCv.wait(uLock);
+ }
+ }
+
+ if(dspHalted)
+ haltDSP();
+ }
+
+ void Hardware::sendMidi(const synthLib::SMidiEvent& _ev)
+ {
+ m_midiIn.push_back(_ev);
+ }
+
+ void Hardware::receiveMidi(std::vector<uint8_t>& _data)
+ {
+ getMidi().readTransmitBuffer(_data);
+ }
+
+ void Hardware::onEsaiCallback(dsp56k::Audio& _audio)
+ {
+ ++m_esaiFrameIndex;
+
+ processMidiInput();
+
+ if((m_esaiFrameIndex & (g_syncEsaiFrameRate-1)) == 0)
+ m_esaiFrameAddedCv.notify_one();
+
+ m_requestedFramesAvailableMutex.lock();
+
+ if(m_requestedFrames && _audio.getAudioOutputs().size() >= m_requestedFrames)
+ {
+ m_requestedFramesAvailableMutex.unlock();
+ m_requestedFramesAvailableCv.notify_one();
+ }
+ else
+ {
+ m_requestedFramesAvailableMutex.unlock();
+ }
+
+ std::unique_lock uLock(m_haltDSPmutex);
+ m_haltDSPcv.wait(uLock, [&]{ return m_haltDSP == false; });
+ }
+
+ void Hardware::syncUcToDSP()
+ {
+ if(m_remainingUcCycles > 0)
+ return;
+
+ // we can only use ESAI to clock the uc once it has been enabled
+ if(m_esaiFrameIndex <= 0)
+ return;
+
+ if(m_esaiFrameIndex == m_lastEsaiFrameIndex)
+ {
+ resumeDSP();
+ std::unique_lock uLock(m_esaiFrameAddedMutex);
+ m_esaiFrameAddedCv.wait(uLock, [this]{return m_esaiFrameIndex > m_lastEsaiFrameIndex;});
+ }
+
+ const auto esaiFrameIndex = m_esaiFrameIndex;
+
+ const auto ucClock = getUc().getSim().getSystemClockHz();
+
+ constexpr double divInv = 1.0 / 44100.0; // stereo interleaved
+ const double ucCyclesPerFrame = static_cast<double>(ucClock) * divInv;
+
+ const auto esaiDelta = esaiFrameIndex - m_lastEsaiFrameIndex;
+
+ m_remainingUcCyclesD += ucCyclesPerFrame * static_cast<double>(esaiDelta);
+ m_remainingUcCycles = static_cast<int64_t>(m_remainingUcCyclesD);
+ m_remainingUcCyclesD -= static_cast<double>(m_remainingUcCycles);
+
+ if(esaiDelta > g_syncHaltDspEsaiThreshold)
+ {
+ haltDSP();
+ }
+ else
+ {
+ resumeDSP();
+ }
+
+ m_lastEsaiFrameIndex = esaiFrameIndex;
+ }
+
+ void Hardware::processMidiInput()
+ {
+ ++m_midiOffsetCounter;
+
+ while(!m_midiIn.empty())
+ {
+ const auto& e = m_midiIn.front();
+
+ if(e.offset > m_midiOffsetCounter)
+ break;
+
+ if(!e.sysex.empty())
+ {
+ getMidi().writeMidi(e.sysex);
+ }
+ else
+ {
+ getMidi().writeMidi(e.a);
+ const auto len = synthLib::MidiBufferParser::lengthFromStatusByte(e.a);
+ if (len > 1)
+ getMidi().writeMidi(e.b);
+ if (len > 2)
+ getMidi().writeMidi(e.c);
+ }
+
+ m_midiIn.pop_front();
+ }
+ }
}
diff --git a/source/wLib/wHardware.h b/source/wLib/wHardware.h
@@ -1,8 +1,75 @@
#pragma once
+#include <cstdint>
+#include <functional>
+
+#include "dsp56kEmu/ringbuffer.h"
+#include "dsp56kEmu/types.h"
+
+#include "../synthLib/midiTypes.h"
+
+namespace mc68k
+{
+ class Mc68k;
+}
+
+namespace dsp56k
+{
+ class Audio;
+}
+
namespace wLib
{
+ class Midi;
+
class Hardware
{
+ public:
+ Hardware(const double& _samplerate);
+ virtual ~Hardware() = default;
+
+ virtual Midi& getMidi() = 0;
+ virtual mc68k::Mc68k& getUc() = 0;
+
+ void haltDSP();
+ void resumeDSP();
+
+ void ucYieldLoop(const std::function<bool()>& _continue);
+
+ void sendMidi(const synthLib::SMidiEvent& _ev);
+ void receiveMidi(std::vector<uint8_t>& _data);
+
+ protected:
+ void onEsaiCallback(dsp56k::Audio& _audio);
+ void syncUcToDSP();
+ void processMidiInput();
+
+ // timing
+ const double m_samplerateInv;
+ uint32_t m_esaiFrameIndex = 0;
+ uint32_t m_lastEsaiFrameIndex = 0;
+ int64_t m_remainingUcCycles = 0;
+ double m_remainingUcCyclesD = 0;
+
+ dsp56k::RingBuffer<synthLib::SMidiEvent, 16384, true> m_midiIn;
+ uint32_t m_midiOffsetCounter = 0;
+
+ std::vector<dsp56k::TWord> m_delayedAudioIn;
+
+ std::vector<dsp56k::TWord> m_dummyInput;
+ std::vector<dsp56k::TWord> m_dummyOutput;
+
+ std::mutex m_esaiFrameAddedMutex;
+ std::condition_variable m_esaiFrameAddedCv;
+
+ std::mutex m_requestedFramesAvailableMutex;
+ std::condition_variable m_requestedFramesAvailableCv;
+ size_t m_requestedFrames = 0;
+
+ bool m_haltDSP = false;
+ std::condition_variable m_haltDSPcv;
+ std::mutex m_haltDSPmutex;
+ bool m_processAudio = false;
+ bool m_bootCompleted = false;
};
}
diff --git a/source/xtLib/xtHardware.cpp b/source/xtLib/xtHardware.cpp
@@ -1,6 +1,5 @@
#include "xtHardware.h"
-#include "../synthLib/midiTypes.h"
#include "../synthLib/midiBufferParser.h"
#include "../synthLib/deviceException.h"
@@ -8,15 +7,9 @@
namespace xt
{
- constexpr uint32_t g_syncEsaiFrameRate = 8;
- constexpr uint32_t g_syncHaltDspEsaiThreshold = 16;
-
- static_assert((g_syncEsaiFrameRate & (g_syncEsaiFrameRate - 1)) == 0, "esai frame sync rate must be power of two");
- static_assert(g_syncHaltDspEsaiThreshold >= g_syncEsaiFrameRate * 2, "esai DSP halt threshold must be greater than two times the sync rate");
-
- Hardware::Hardware(std::string _romFilename)
- : m_romFileName(std::move(_romFilename))
- , m_rom(m_romFileName, nullptr)
+ Hardware::Hardware(const std::string& _romFilename)
+ : wLib::Hardware(40000)
+ , m_rom(_romFilename, nullptr)
, m_uc(m_rom)
, m_dsps{DSP(*this, m_uc.getHdi08A().getHdi08(), 0)}
, m_midi(m_uc.getQSM())
@@ -35,16 +28,6 @@ namespace xt
processUcCycle();
}
- void Hardware::sendMidi(const synthLib::SMidiEvent& _ev)
- {
- m_midiIn.push_back(_ev);
- }
-
- void Hardware::receiveMidi(std::vector<uint8_t>& _data)
- {
- m_midi.readTransmitBuffer(_data);
- }
-
void Hardware::resetMidiCounter()
{
// wait for DSP to enter blocking state
@@ -60,45 +43,6 @@ namespace xt
m_midiOffsetCounter = 0;
}
- void Hardware::hdiProcessUCtoDSPNMIIrq()
- {
- // QS6 is connected to DSP NMI pin but I've never seen this being triggered
-#if SUPPORT_NMI_INTERRUPT
- const uint8_t requestNMI = m_uc.requestDSPinjectNMI();
-
- if(m_requestNMI && !requestNMI)
- {
-// LOG("uc request DSP NMI");
- m_dsps.front().hdiSendIrqToDSP(dsp56k::Vba_NMI);
-
- m_requestNMI = requestNMI;
- }
-#endif
- }
-
- void Hardware::ucYieldLoop(const std::function<bool()>& _continue)
- {
- const auto dspHalted = m_haltDSP;
-
- resumeDSP();
-
- while(_continue())
- {
- if(m_processAudio)
- {
- std::this_thread::yield();
- }
- else
- {
- std::unique_lock uLock(m_esaiFrameAddedMutex);
- m_esaiFrameAddedCv.wait(uLock);
- }
- }
-
- if(dspHalted)
- haltDSP();
- }
-
void Hardware::initVoiceExpansion()
{
if (m_dsps.size() < 3)
@@ -114,32 +58,9 @@ namespace xt
esaiA.setCallback([&](dsp56k::Audio*)
{
-/* auto& dsp = m_dsps.front().dsp();
- auto& mem = dsp.memory();
- mem.saveAssembly("xt_dspA.asm", 0, mem.sizeP(), true, false, dsp.getPeriph(0), dsp.getPeriph(1));
-*/
m_bootCompleted = true;
- ++m_esaiFrameIndex;
-
- processMidiInput();
-
- if((m_esaiFrameIndex & (g_syncEsaiFrameRate-1)) == 0)
- m_esaiFrameAddedCv.notify_one();
- m_requestedFramesAvailableMutex.lock();
-
- if(m_requestedFrames && esaiA.getAudioOutputs().size() >= m_requestedFrames)
- {
- m_requestedFramesAvailableMutex.unlock();
- m_requestedFramesAvailableCv.notify_one();
- }
- else
- {
- m_requestedFramesAvailableMutex.unlock();
- }
-
- std::unique_lock uLock(m_haltDSPmutex);
- m_haltDSPcv.wait(uLock, [&]{ return m_haltDSP == false; });
+ onEsaiCallback(esaiA);
}, 0);
}
@@ -154,8 +75,6 @@ namespace xt
for (auto& dsp : m_dsps)
dsp.transferHostFlagsUc2Dsdp();
- hdiProcessUCtoDSPNMIIrq();
-
for (auto& dsp : m_dsps)
dsp.hdiTransferDSPtoUC();
@@ -173,97 +92,6 @@ namespace xt
}
}
- void Hardware::haltDSP()
- {
- if(m_haltDSP)
- return;
-
- std::lock_guard uLockHalt(m_haltDSPmutex);
- m_haltDSP = true;
- }
-
- void Hardware::resumeDSP()
- {
- if(!m_haltDSP)
- return;
-
- {
- std::lock_guard uLockHalt(m_haltDSPmutex);
- m_haltDSP = false;
- }
- m_haltDSPcv.notify_one();
- }
-
- void Hardware::syncUcToDSP()
- {
- if(m_remainingUcCycles > 0)
- return;
-
- // we can only use ESAI to clock the uc once it has been enabled
- if(m_esaiFrameIndex <= 0)
- return;
-
- if(m_esaiFrameIndex == m_lastEsaiFrameIndex)
- {
- resumeDSP();
- std::unique_lock uLock(m_esaiFrameAddedMutex);
- m_esaiFrameAddedCv.wait(uLock, [this]{return m_esaiFrameIndex > m_lastEsaiFrameIndex;});
- }
-
- const auto esaiFrameIndex = m_esaiFrameIndex;
-
- const auto ucClock = m_uc.getSim().getSystemClockHz();
-
- constexpr double divInv = 1.0 / 40000.0;
- const double ucCyclesPerFrame = static_cast<double>(ucClock) * divInv;
-
- const auto esaiDelta = esaiFrameIndex - m_lastEsaiFrameIndex;
-
- m_remainingUcCyclesD += ucCyclesPerFrame * static_cast<double>(esaiDelta);
- m_remainingUcCycles += static_cast<int64_t>(m_remainingUcCyclesD);
- m_remainingUcCyclesD -= static_cast<double>(m_remainingUcCycles);
-
- if(esaiDelta > g_syncHaltDspEsaiThreshold)
- {
- haltDSP();
- }
- else
- {
- resumeDSP();
- }
-
- m_lastEsaiFrameIndex = esaiFrameIndex;
- }
-
- void Hardware::processMidiInput()
- {
- ++m_midiOffsetCounter;
-
- while(!m_midiIn.empty())
- {
- const auto& e = m_midiIn.front();
-
- if(e.offset > m_midiOffsetCounter)
- break;
-
- if(!e.sysex.empty())
- {
- m_midi.writeMidi(e.sysex);
- }
- else
- {
- m_midi.writeMidi(e.a);
- const auto len = synthLib::MidiBufferParser::lengthFromStatusByte(e.a);
- if (len > 1)
- m_midi.writeMidi(e.b);
- if (len > 2)
- m_midi.writeMidi(e.c);
- }
-
- m_midiIn.pop_front();
- }
- }
-
void Hardware::processAudio(uint32_t _frames, uint32_t _latency)
{
ensureBufferSize(_frames);
diff --git a/source/xtLib/xtHardware.h b/source/xtLib/xtHardware.h
@@ -8,23 +8,20 @@
#include "dsp56kEmu/dspthread.h"
-#include "../synthLib/midiTypes.h"
-
-#include "dsp56kEmu/ringbuffer.h"
-
#include "../wLib/wMidi.h"
+#include "../wLib/wHardware.h"
namespace xt
{
class XtUc;
- class Hardware
+ class Hardware : public wLib::Hardware
{
static constexpr uint32_t g_dspCount = 1;
public:
- explicit Hardware(std::string _romFilename);
- ~Hardware();
+ explicit Hardware(const std::string& _romFilename);
+ virtual ~Hardware();
void process();
@@ -35,9 +32,6 @@ namespace xt
auto& getAudioInputs() { return m_audioInputs; }
auto& getAudioOutputs() { return m_audioOutputs; }
- void sendMidi(const synthLib::SMidiEvent& _ev);
- void receiveMidi(std::vector<uint8_t>& _data);
-
dsp56k::DSPThread& getDspThread(uint32_t _index = 0) { return m_dsps[_index].thread(); }
void processAudio(uint32_t _frames, uint32_t _latency = 0);
@@ -54,56 +48,28 @@ namespace xt
bool isBootCompleted() const { return m_bootCompleted; }
void resetMidiCounter();
- void ucYieldLoop(const std::function<bool()>& _continue);
void initVoiceExpansion();
+ wLib::Midi& getMidi() override
+ {
+ return m_midi;
+ }
+
+ mc68k::Mc68k& getUc() override
+ {
+ return m_uc;
+ }
+
private:
void setupEsaiListener();
- void hdiProcessUCtoDSPNMIIrq();
void processUcCycle();
- void haltDSP();
- void resumeDSP();
- void syncUcToDSP();
- void processMidiInput();
-
- const std::string m_romFileName;
const Rom m_rom;
- bool m_requestNMI = false;
-
- // timing
- uint32_t m_esaiFrameIndex = 0;
- uint32_t m_lastEsaiFrameIndex = 0;
- int64_t m_remainingUcCycles = 0;
- double m_remainingUcCyclesD = 0;
-
XtUc m_uc;
- std::array<DSP,g_dspCount> m_dsps;
-
- wLib::Midi m_midi;
- dsp56k::RingBuffer<synthLib::SMidiEvent, 1024, true> m_midiIn;
- uint32_t m_midiOffsetCounter = 0;
-
- std::vector<dsp56k::TWord> m_delayedAudioIn;
-
- std::vector<dsp56k::TWord> m_dummyInput;
- std::vector<dsp56k::TWord> m_dummyOutput;
-
TAudioInputs m_audioInputs;
TAudioOutputs m_audioOutputs;
-
- std::mutex m_esaiFrameAddedMutex;
- std::condition_variable m_esaiFrameAddedCv;
-
- std::mutex m_requestedFramesAvailableMutex;
- std::condition_variable m_requestedFramesAvailableCv;
- size_t m_requestedFrames = 0;
-
- bool m_haltDSP = false;
- std::condition_variable m_haltDSPcv;
- std::mutex m_haltDSPmutex;
- bool m_processAudio = false;
- bool m_bootCompleted = false;
+ std::array<DSP,g_dspCount> m_dsps;
+ wLib::Midi m_midi;
};
}