From d3dc9e2f7104d32b217581b7ac1631c14dc418e9 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 17 Feb 2024 23:54:43 +0200 Subject: [PATCH] Forward interrupts properly in Teakra DSP core --- include/audio/teakra_core.hpp | 5 +++-- src/core/audio/teakra_core.cpp | 28 ++++++++++++++++------------ src/core/services/dsp.cpp | 1 - 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/audio/teakra_core.hpp b/include/audio/teakra_core.hpp index 96c86212..99ae8800 100644 --- a/include/audio/teakra_core.hpp +++ b/include/audio/teakra_core.hpp @@ -7,7 +7,8 @@ namespace Audio { class TeakraDSP : public DSPCore { Teakra::Teakra teakra; u32 pipeBaseAddr; - bool running; + bool running; // Is the DSP running? + bool loaded; // Have we finished loading a binary with LoadComponent? // Get a pointer to a data memory address u8* getDataPointer(u32 address) { return getDspMemory() + Memory::DSP_DATA_MEMORY_OFFSET + address; } @@ -17,7 +18,7 @@ namespace Audio { CPUtoDSP = 1, }; - // A lot of Teakra integration code, especially pipe stuff are based on Citra's integration here: + // A lot of Teakra integration code, especially pipe stuff is based on Citra's integration here: // https://github.com/citra-emu/citra/blob/master/src/audio_core/lle/lle.cpp struct PipeStatus { // All addresses and sizes here refer to byte values, NOT 16-bit values. diff --git a/src/core/audio/teakra_core.cpp b/src/core/audio/teakra_core.cpp index 23a3c3ce..7541185a 100644 --- a/src/core/audio/teakra_core.cpp +++ b/src/core/audio/teakra_core.cpp @@ -35,8 +35,6 @@ struct Dsp1 { }; TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspService), pipeBaseAddr(0), running(false) { - teakra.Reset(); - // Set up callbacks for Teakra Teakra::AHBMCallback ahbm; @@ -53,21 +51,23 @@ TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspServ // NOP for now }); - // Set up event handlers + // Set up event handlers. These handlers forward a hardware interrupt to the DSP service, which is responsible + // For triggering the appropriate DSP kernel events + // Note: It's important not to fire any events if "loaded" is false, ie if we haven't fully loaded a DSP component yet teakra.SetRecvDataHandler(0, [&]() { - if (running) { + if (loaded) { dspService.triggerInterrupt0(); } }); teakra.SetRecvDataHandler(1, [&]() { - if (running) { + if (loaded) { dspService.triggerInterrupt1(); } }); auto processPipeEvent = [&](bool dataEvent) { - if (!running) { + if (!loaded) { return; } @@ -85,7 +85,7 @@ TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspServ signalledSemaphore = signalledData = false; u16 slot = teakra.RecvData(2); - u16 side = slot % 2; + u16 side = slot & 1; u16 pipe = slot / 2; if (side != static_cast(PipeDirection::DSPtoCPU)) { @@ -107,6 +107,7 @@ TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspServ void TeakraDSP::reset() { teakra.Reset(); running = false; + loaded = false; signalledData = signalledSemaphore = false; } @@ -222,12 +223,13 @@ std::vector TeakraDSP::readPipe(u32 channel, u32 peer, u32 size, u32 buffer) void TeakraDSP::loadComponent(std::vector& data, u32 programMask, u32 dataMask) { // TODO: maybe move this to the DSP service - if (running) { + if (loaded) { Helpers::warn("Loading DSP component when already loaded"); return; } teakra.Reset(); + running = true; u8* dspCode = teakra.GetDspMemory().data(); u8* dspData = dspCode + 0x40000; @@ -239,7 +241,7 @@ void TeakraDSP::loadComponent(std::vector& data, u32 programMask, u32 dataMa // Load DSP segments to DSP RAM // TODO: verify hashes - for (unsigned int i = 0; i < dsp1.segmentCount; i++) { + for (uint i = 0; i < dsp1.segmentCount; i++) { auto& segment = dsp1.segments[i]; u32 addr = segment.dspAddr << 1; u8* src = data.data() + segment.offs; @@ -262,8 +264,6 @@ void TeakraDSP::loadComponent(std::vector& data, u32 programMask, u32 dataMa log("LoadComponent: special segment not supported"); } - running = true; - if (syncWithDsp) { // Wait for the DSP to reply with 1s in all RECV registers for (int i = 0; i < 3; i++) { @@ -275,19 +275,23 @@ void TeakraDSP::loadComponent(std::vector& data, u32 programMask, u32 dataMa } } + printf("DSP::LoadComponent: Semaphore value: %X\n", teakra.GetSemaphore()); + // Retrieve the pipe base address while (!teakra.RecvDataIsReady(2)) { runAudioFrame(); } pipeBaseAddr = teakra.RecvData(2); + loaded = true; } void TeakraDSP::unloadComponent() { - if (!running) { + if (!loaded) { Helpers::warn("Audio: unloadComponent called without a running program"); return; } + loaded = false; // Wait for SEND2 to be ready, then send the shutdown command to the DSP while (!teakra.SendDataIsEmpty(2)) { diff --git a/src/core/services/dsp.cpp b/src/core/services/dsp.cpp index f12e31f0..c768248c 100644 --- a/src/core/services/dsp.cpp +++ b/src/core/services/dsp.cpp @@ -124,7 +124,6 @@ void DSPService::recvData(u32 messagePointer) { log("DSP::RecvData (register = %d)\n", registerIndex); if (registerIndex != 0) Helpers::panic("Unknown register in DSP::RecvData"); - // Return 0 if the DSP is running, otherwise 1 const u16 data = dsp->recvData(registerIndex); mem.write32(messagePointer, IPC::responseHeader(0x01, 2, 0));