commit 2892b0f44571f8cb83b404875c96a337e894b5ed
parent 0caae856225131947316c649e292cdd9becef97e
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Sat, 27 Jul 2024 22:35:56 +0200
change DSP/UC sync & audio processing, now DSP A writes its out to the DSP B input again
Diffstat:
4 files changed, 39 insertions(+), 136 deletions(-)
diff --git a/source/nord/n2x/n2xLib/n2xdsp.cpp b/source/nord/n2x/n2xLib/n2xdsp.cpp
@@ -96,11 +96,6 @@ namespace n2x
clock.setEsaiDivider(&esai, 1, 0);
clock.setEsaiCounter(&esai, -1, 0);
}
-
- esai.setCallback([this](dsp56k::Audio*)
- {
- onEsaiCallback();
- }, 0);
}
auto config = m_dsp.getJit().getConfig();
@@ -144,7 +139,7 @@ namespace n2x
hdi08().setRXRateLimit(0);
// hdi08().setTransmitDataAlwaysEmpty(false);
- m_periphX.getEsai().writeEmptyAudioIn(2048);
+ m_periphX.getEsai().writeEmptyAudioIn(2);
m_hdiUC.setRxEmptyCallback([&](const bool _needMoreData)
{
@@ -184,17 +179,7 @@ namespace n2x
});
}
- void DSP::advanceSamples(const uint32_t _samples, const uint32_t _latency)
- {
- {
- std::lock_guard uLockHalt(m_haltDSPmutex);
- m_maxEsaiCallbacks += _samples;
- m_esaiLatency = _latency;
- }
- m_haltDSPcv.notify_one();
- }
-
- void DSP::onUCRxEmpty(bool _needMoreData)
+ void DSP::onUCRxEmpty(const bool _needMoreData)
{
if(_needMoreData)
{
@@ -203,8 +188,7 @@ namespace n2x
return dsp().hasPendingInterrupts();
});
}
- const bool res = hdiTransferDSPtoUC();
-// assert(!_needMoreData || res);
+ hdiTransferDSPtoUC();
}
void DSP::hdiTransferUCtoDSP(const uint32_t _word)
@@ -216,31 +200,11 @@ namespace n2x
void DSP::hdiSendIrqToDSP(const uint8_t _irq)
{
- // If applicable, we wait for the halt on our DSP after resuming it
- /*if(m_haltDSP.halted())
- {
- bool done = false;
- std::mutex mutex;
- std::condition_variable wait;
- m_haltDSP.wakeUp([this, _irq, &mutex, &done, &wait]
- {
- dsp().execInterrupt(_irq);
- {
- std::unique_lock lock(mutex);
- done = true;
- }
- wait.notify_one();
- });
- std::unique_lock lock(mutex);
- wait.wait(lock, [&done]{return done;});
- assert(done);
- }
- else*/
{
dsp().injectExternalInterrupt(_irq);
dsp().injectExternalInterrupt(m_irqInterruptDone);
- hwLib::ScopedResumeDSP r(m_hardware.getDSPB().getHaltDSP());
+ hwLib::ScopedResumeDSP rB(m_hardware.getDSPB().getHaltDSP());
m_triggerInterruptDone.wait();
}
@@ -262,21 +226,6 @@ namespace n2x
return _isr;
}
- void DSP::onEsaiCallback()
- {
- ++m_numEsaiCallbacks;
-
- if(m_numEsaiCallbacks >= m_maxEsaiCallbacks + m_esaiLatency)
- {
- std::unique_lock uLock(m_haltDSPmutex);
- m_haltDSPcv.wait(uLock, [&]
- {
- return (m_maxEsaiCallbacks + m_esaiLatency) > m_numEsaiCallbacks;
- });
- }
- m_esaiCallback();
- }
-
bool DSP::hdiTransferDSPtoUC()
{
if (m_hdiUC.canReceiveData() && hdi08().hasTX())
diff --git a/source/nord/n2x/n2xLib/n2xdsp.h b/source/nord/n2x/n2xLib/n2xdsp.h
@@ -38,13 +38,6 @@ namespace n2x
return m_periphX;
}
- void setEsaiCallback(std::function<void()>&& _func)
- {
- m_esaiCallback = std::move(_func);
- }
-
- void advanceSamples(uint32_t _samples, uint32_t _latency);
-
dsp56k::DSPThread& getDSPThread() const { return *m_thread; }
auto& getHaltDSP() { return m_haltDSP; }
@@ -53,7 +46,6 @@ namespace n2x
void hdiTransferUCtoDSP(uint32_t _word);
void hdiSendIrqToDSP(uint8_t _irq);
uint8_t hdiUcReadIsr(uint8_t _isr);
- void onEsaiCallback();
bool hdiTransferDSPtoUC();
Hardware& m_hardware;
@@ -69,18 +61,6 @@ namespace n2x
std::unique_ptr<dsp56k::DSPThread> m_thread;
- bool m_receivedMagicEsaiPacket = false;
- uint32_t m_hdiHF01 = 0;
-
- uint64_t m_numEsaiCallbacks = 0;
- uint64_t m_maxEsaiCallbacks = 0;
- uint64_t m_esaiLatency = 0;
-
- std::function<void()> m_esaiCallback = [] {};
-
- std::condition_variable m_haltDSPcv;
- std::mutex m_haltDSPmutex;
-
baseLib::Semaphore m_triggerInterruptDone;
uint32_t m_irqInterruptDone = 0;
diff --git a/source/nord/n2x/n2xLib/n2xhardware.cpp b/source/nord/n2x/n2xLib/n2xhardware.cpp
@@ -13,14 +13,13 @@ namespace n2x
, m_dspA(*this, m_uc.getHdi08A(), 0)
, m_dspB(*this, m_uc.getHdi08B(), 1)
, m_samplerateInv(1.0 / g_samplerate)
+ , m_semDspAtoB(1)
{
if(!m_rom.isValid())
return;
- m_dspB.setEsaiCallback([this]()
- {
- onEsaiCallback();
- });
+ m_dspA.getPeriph().getEsai().setCallback([this](dsp56k::Audio*){ onEsaiCallbackA(); }, 0);
+ m_dspB.getPeriph().getEsai().setCallback([this](dsp56k::Audio*) { onEsaiCallbackB(); }, 0);
}
bool Hardware::isValid() const
@@ -40,7 +39,6 @@ namespace n2x
void Hardware::ucYieldLoop(const std::function<bool()>& _continue)
{
- hwLib::ScopedResumeDSP rA(m_dspA.getHaltDSP());
hwLib::ScopedResumeDSP rB(m_dspB.getHaltDSP());
while(_continue())
@@ -79,7 +77,6 @@ namespace n2x
outputs[10] = m_dummyOutput.data();
outputs[11] = m_dummyOutput.data();
- auto& esaiA = m_dspA.getPeriph().getEsai();
auto& esaiB = m_dspB.getPeriph().getEsai();
// LOG("B out " << esaiB.getAudioOutputs().size() << ", A out " << esaiA.getAudioOutputs().size() << ", B in " << esaiB.getAudioInputs().size());
@@ -89,35 +86,6 @@ namespace n2x
const auto processCount = std::min(_frames, static_cast<uint32_t>(64));
_frames -= processCount;
- m_dspA.advanceSamples(processCount, _latency);
- m_dspB.advanceSamples(processCount, _latency);
-
- auto* buf = m_dspAtoBBuffer.data();
-
- // read data from DSP A...
- esaiA.processAudioOutput<dsp56k::TWord>(processCount, [&](size_t _index, dsp56k::Audio::TxFrame& _frame)
- {
- *buf++ = _frame[0][0];
- *buf++ = _frame[1][0];
- *buf++ = _frame[2][0];
- *buf++ = _frame[3][0];
- });
-
- buf = m_dspAtoBBuffer.data();
-
- // ...and forward it to DSP B
- esaiB.processAudioInput<dsp56k::TWord>(processCount, 0, [&](size_t _s, dsp56k::Audio::RxFrame& _f)
- {
- _f.resize(4);
- _f[0] = dsp56k::Audio::RxSlot{0};
- _f[1] = dsp56k::Audio::RxSlot{0};
- _f[2] = dsp56k::Audio::RxSlot{0};
- _f[3] = dsp56k::Audio::RxSlot{0};
- buf += 4;
- });
-
-// esaiB.processAudioInput(m_dspAtoBBuffer.data(), processCount * 2, 4, 0);
-
const auto requiredSize = processCount > 8 ? processCount - 8 : 0;
if(esaiB.getAudioOutputs().size() < requiredSize)
@@ -138,15 +106,6 @@ namespace n2x
// read output of DSP B to regular audio output
esaiB.processAudioOutputInterleaved(outputs, processCount);
- for(uint32_t i=0; i<processCount; ++i)
- {
- const auto i4 = i<<2;
- outputs[0][i] += m_dspAtoBBuffer[i4+2];
- outputs[1][i] += m_dspAtoBBuffer[i4+3];
- outputs[2][i] += m_dspAtoBBuffer[i4+0];
- outputs[3][i] += m_dspAtoBBuffer[i4+1];
- }
-
outputs[0] += processCount;
outputs[1] += processCount;
outputs[2] += processCount;
@@ -168,8 +127,28 @@ namespace n2x
m_dspAtoBBuffer.resize(_frames * 4);
}
- void Hardware::onEsaiCallback()
+ void Hardware::onEsaiCallbackA()
{
+ // forward DSP A output to DSP B input
+ const auto out = m_dspA.getPeriph().getEsai().getAudioOutputs().pop_front();
+
+ dsp56k::Audio::RxFrame in;
+ in.resize(out.size());
+
+ in[0] = dsp56k::Audio::RxSlot{out[0][0]};
+ in[1] = dsp56k::Audio::RxSlot{out[1][0]};
+ in[2] = dsp56k::Audio::RxSlot{out[2][0]};
+ in[3] = dsp56k::Audio::RxSlot{out[3][0]};
+
+ m_dspB.getPeriph().getEsai().getAudioInputs().push_back(in);
+
+ m_semDspAtoB.wait();
+ }
+
+ void Hardware::onEsaiCallbackB()
+ {
+ m_semDspAtoB.notify();
+
++m_esaiFrameIndex;
// processMidiInput();
@@ -201,7 +180,6 @@ namespace n2x
if(m_esaiFrameIndex == m_lastEsaiFrameIndex)
{
- m_dspHalted = false;
resumeDSPs();
std::unique_lock uLock(m_esaiFrameAddedMutex);
m_esaiFrameAddedCv.wait(uLock, [this]{return m_esaiFrameIndex > m_lastEsaiFrameIndex;});
@@ -226,31 +204,24 @@ namespace n2x
m_remainingUcCyclesD -= static_cast<double>(m_remainingUcCycles);
if(esaiDelta > g_syncHaltDspEsaiThreshold)
- {
- if(!m_dspHalted)
- {
- m_dspHalted = true;
- haltDSPs();
- }
- }
- else if(m_dspHalted)
- {
- m_dspHalted = false;
- resumeDSPs();
- }
+ haltDSPs();
m_lastEsaiFrameIndex = esaiFrameIndex;
}
void Hardware::haltDSPs()
{
-// m_dspA.getHaltDSP().haltDSP();
+ if(m_dspHalted)
+ return;
+ m_dspHalted = true;
m_dspB.getHaltDSP().haltDSP();
}
void Hardware::resumeDSPs()
{
-// m_dspA.getHaltDSP().resumeDSP();
+ if(!m_dspHalted)
+ return;
+ m_dspHalted = false;
m_dspB.getHaltDSP().resumeDSP();
}
}
diff --git a/source/nord/n2x/n2xLib/n2xhardware.h b/source/nord/n2x/n2xLib/n2xhardware.h
@@ -31,7 +31,8 @@ namespace n2x
private:
void ensureBufferSize(uint32_t _frames);
- void onEsaiCallback();
+ void onEsaiCallbackA();
+ void onEsaiCallbackB();
void syncUCtoDSP();
Rom m_rom;
@@ -57,5 +58,7 @@ namespace n2x
std::condition_variable m_requestedFramesAvailableCv;
size_t m_requestedFrames = 0;
bool m_dspHalted = false;
+ dsp56k::SpscSemaphore m_semDspAtoB;
+ dsp56k::RingBuffer<dsp56k::Audio::RxFrame, 4, true> m_dspAtoBbuf;
};
}