Better DSP scheduling

This commit is contained in:
wheremyfoodat 2024-02-18 22:22:00 +02:00
parent f58354af06
commit 33eb096ef8
8 changed files with 44 additions and 27 deletions

View file

@ -7,20 +7,30 @@
#include "helpers.hpp"
#include "logger.hpp"
#include "memory.hpp"
#include "scheduler.hpp"
// The DSP core must have access to the DSP service to be able to trigger interrupts properly
class DSPService;
namespace Audio {
// There are 160 stereo samples in 1 audio frame, so 320 samples total
static constexpr u64 samplesInFrame = 160;
// 1 frame = 4096 DSP cycles = 8192 ARM11 cycles
static constexpr u64 cyclesPerFrame = samplesInFrame * 8192;
// For LLE DSP cores, we run the DSP for N cycles at a time, every N*2 arm11 cycles since the ARM11 runs twice as fast
static constexpr u64 lleSlice = 16384;
class DSPCore {
protected:
Memory& mem;
Scheduler& scheduler;
DSPService& dspService;
MAKE_LOG_FUNCTION(log, dspLogger)
public:
enum class Type { Null, Teakra };
DSPCore(Memory& mem, DSPService& dspService) : mem(mem), dspService(dspService) {}
DSPCore(Memory& mem, Scheduler& scheduler, DSPService& dspService) : mem(mem), scheduler(scheduler), dspService(dspService) {}
virtual void reset() = 0;
virtual void runAudioFrame() = 0;
@ -36,5 +46,5 @@ namespace Audio {
virtual void setSemaphoreMask(u16 value) = 0;
};
std::unique_ptr<DSPCore> makeDSPCore(DSPCore::Type type, Memory& mem, DSPService& dspService);
std::unique_ptr<DSPCore> makeDSPCore(DSPCore::Type type, Memory& mem, Scheduler& scheduler, DSPService& dspService);
} // namespace Audio

View file

@ -20,7 +20,7 @@ namespace Audio {
void resetAudioPipe();
public:
NullDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspService) {}
NullDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService) : DSPCore(mem, scheduler, dspService) {}
void reset() override;
void runAudioFrame() override {}

View file

@ -65,14 +65,22 @@ namespace Audio {
bool signalledData;
bool signalledSemaphore;
// Run 1 slice of DSP instructions
void runSlice() {
if (running) {
teakra.Run(Audio::lleSlice);
}
}
public:
TeakraDSP(Memory& mem, DSPService& dspService);
TeakraDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService);
void reset() override;
// Run 1 slice of DSP instructions and schedule the next audio frame
void runAudioFrame() override {
if (running) {
teakra.Run(16384);
}
runSlice();
scheduler.addEvent(Scheduler::EventType::RunDSP, scheduler.currentTimestamp + Audio::lleSlice * 2);
}
u8* getDspMemory() override { return teakra.GetDspMemory().data(); }