mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 14:45:41 +12:00
Forward interrupts properly in Teakra DSP core
This commit is contained in:
parent
5dd3c02ffb
commit
d3dc9e2f71
3 changed files with 19 additions and 15 deletions
|
@ -7,7 +7,8 @@ namespace Audio {
|
||||||
class TeakraDSP : public DSPCore {
|
class TeakraDSP : public DSPCore {
|
||||||
Teakra::Teakra teakra;
|
Teakra::Teakra teakra;
|
||||||
u32 pipeBaseAddr;
|
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
|
// Get a pointer to a data memory address
|
||||||
u8* getDataPointer(u32 address) { return getDspMemory() + Memory::DSP_DATA_MEMORY_OFFSET + address; }
|
u8* getDataPointer(u32 address) { return getDspMemory() + Memory::DSP_DATA_MEMORY_OFFSET + address; }
|
||||||
|
@ -17,7 +18,7 @@ namespace Audio {
|
||||||
CPUtoDSP = 1,
|
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
|
// https://github.com/citra-emu/citra/blob/master/src/audio_core/lle/lle.cpp
|
||||||
struct PipeStatus {
|
struct PipeStatus {
|
||||||
// All addresses and sizes here refer to byte values, NOT 16-bit values.
|
// All addresses and sizes here refer to byte values, NOT 16-bit values.
|
||||||
|
|
|
@ -35,8 +35,6 @@ struct Dsp1 {
|
||||||
};
|
};
|
||||||
|
|
||||||
TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspService), pipeBaseAddr(0), running(false) {
|
TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspService), pipeBaseAddr(0), running(false) {
|
||||||
teakra.Reset();
|
|
||||||
|
|
||||||
// Set up callbacks for Teakra
|
// Set up callbacks for Teakra
|
||||||
Teakra::AHBMCallback ahbm;
|
Teakra::AHBMCallback ahbm;
|
||||||
|
|
||||||
|
@ -53,21 +51,23 @@ TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspServ
|
||||||
// NOP for now
|
// 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, [&]() {
|
teakra.SetRecvDataHandler(0, [&]() {
|
||||||
if (running) {
|
if (loaded) {
|
||||||
dspService.triggerInterrupt0();
|
dspService.triggerInterrupt0();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
teakra.SetRecvDataHandler(1, [&]() {
|
teakra.SetRecvDataHandler(1, [&]() {
|
||||||
if (running) {
|
if (loaded) {
|
||||||
dspService.triggerInterrupt1();
|
dspService.triggerInterrupt1();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
auto processPipeEvent = [&](bool dataEvent) {
|
auto processPipeEvent = [&](bool dataEvent) {
|
||||||
if (!running) {
|
if (!loaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspServ
|
||||||
signalledSemaphore = signalledData = false;
|
signalledSemaphore = signalledData = false;
|
||||||
|
|
||||||
u16 slot = teakra.RecvData(2);
|
u16 slot = teakra.RecvData(2);
|
||||||
u16 side = slot % 2;
|
u16 side = slot & 1;
|
||||||
u16 pipe = slot / 2;
|
u16 pipe = slot / 2;
|
||||||
|
|
||||||
if (side != static_cast<u16>(PipeDirection::DSPtoCPU)) {
|
if (side != static_cast<u16>(PipeDirection::DSPtoCPU)) {
|
||||||
|
@ -107,6 +107,7 @@ TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspServ
|
||||||
void TeakraDSP::reset() {
|
void TeakraDSP::reset() {
|
||||||
teakra.Reset();
|
teakra.Reset();
|
||||||
running = false;
|
running = false;
|
||||||
|
loaded = false;
|
||||||
signalledData = signalledSemaphore = false;
|
signalledData = signalledSemaphore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,12 +223,13 @@ std::vector<u8> TeakraDSP::readPipe(u32 channel, u32 peer, u32 size, u32 buffer)
|
||||||
|
|
||||||
void TeakraDSP::loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) {
|
void TeakraDSP::loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) {
|
||||||
// TODO: maybe move this to the DSP service
|
// TODO: maybe move this to the DSP service
|
||||||
if (running) {
|
if (loaded) {
|
||||||
Helpers::warn("Loading DSP component when already loaded");
|
Helpers::warn("Loading DSP component when already loaded");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
teakra.Reset();
|
teakra.Reset();
|
||||||
|
running = true;
|
||||||
|
|
||||||
u8* dspCode = teakra.GetDspMemory().data();
|
u8* dspCode = teakra.GetDspMemory().data();
|
||||||
u8* dspData = dspCode + 0x40000;
|
u8* dspData = dspCode + 0x40000;
|
||||||
|
@ -239,7 +241,7 @@ void TeakraDSP::loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMa
|
||||||
|
|
||||||
// Load DSP segments to DSP RAM
|
// Load DSP segments to DSP RAM
|
||||||
// TODO: verify hashes
|
// 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];
|
auto& segment = dsp1.segments[i];
|
||||||
u32 addr = segment.dspAddr << 1;
|
u32 addr = segment.dspAddr << 1;
|
||||||
u8* src = data.data() + segment.offs;
|
u8* src = data.data() + segment.offs;
|
||||||
|
@ -262,8 +264,6 @@ void TeakraDSP::loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMa
|
||||||
log("LoadComponent: special segment not supported");
|
log("LoadComponent: special segment not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
running = true;
|
|
||||||
|
|
||||||
if (syncWithDsp) {
|
if (syncWithDsp) {
|
||||||
// Wait for the DSP to reply with 1s in all RECV registers
|
// Wait for the DSP to reply with 1s in all RECV registers
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
|
@ -275,19 +275,23 @@ void TeakraDSP::loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("DSP::LoadComponent: Semaphore value: %X\n", teakra.GetSemaphore());
|
||||||
|
|
||||||
// Retrieve the pipe base address
|
// Retrieve the pipe base address
|
||||||
while (!teakra.RecvDataIsReady(2)) {
|
while (!teakra.RecvDataIsReady(2)) {
|
||||||
runAudioFrame();
|
runAudioFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeBaseAddr = teakra.RecvData(2);
|
pipeBaseAddr = teakra.RecvData(2);
|
||||||
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeakraDSP::unloadComponent() {
|
void TeakraDSP::unloadComponent() {
|
||||||
if (!running) {
|
if (!loaded) {
|
||||||
Helpers::warn("Audio: unloadComponent called without a running program");
|
Helpers::warn("Audio: unloadComponent called without a running program");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
loaded = false;
|
||||||
|
|
||||||
// Wait for SEND2 to be ready, then send the shutdown command to the DSP
|
// Wait for SEND2 to be ready, then send the shutdown command to the DSP
|
||||||
while (!teakra.SendDataIsEmpty(2)) {
|
while (!teakra.SendDataIsEmpty(2)) {
|
||||||
|
|
|
@ -124,7 +124,6 @@ void DSPService::recvData(u32 messagePointer) {
|
||||||
log("DSP::RecvData (register = %d)\n", registerIndex);
|
log("DSP::RecvData (register = %d)\n", registerIndex);
|
||||||
if (registerIndex != 0) Helpers::panic("Unknown register in DSP::RecvData");
|
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);
|
const u16 data = dsp->recvData(registerIndex);
|
||||||
|
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x01, 2, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x01, 2, 0));
|
||||||
|
|
Loading…
Add table
Reference in a new issue