From efd887268b186e0b77ff883867497fe9c3bda687 Mon Sep 17 00:00:00 2001 From: jaby Date: Mon, 16 Sep 2024 21:52:27 +0200 Subject: [PATCH] DMA SPU memory --- examples/PoolBox/application/src/menu.cpp | 2 ++ include/PSX/Auxiliary/word_helper.hpp | 15 +++++++++++ .../System/IOPorts/IOValues/spu_io_values.hpp | 16 ++++++++++++ include/PSX/System/IOPorts/spu_io.hpp | 3 +++ .../internal-include/SPU/spu_internal.hpp | 5 ++-- .../src/File/Processor/vag_processor.cpp | 25 +++++++++++-------- 6 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 include/PSX/Auxiliary/word_helper.hpp diff --git a/examples/PoolBox/application/src/menu.cpp b/examples/PoolBox/application/src/menu.cpp index 2eace68f..1dcbfd09 100644 --- a/examples/PoolBox/application/src/menu.cpp +++ b/examples/PoolBox/application/src/menu.cpp @@ -1,6 +1,7 @@ #include "../include/shared.hpp" #include "include/menu.hpp" #include +#include namespace Menu { using DigitalButton = Periphery::GenericController::Button; @@ -24,6 +25,7 @@ namespace Menu { } if(controller.button.went_down(DigitalButton::Cross)) { + SPU::voice[0].play(); this->selection_callback(this->cur_selection); } diff --git a/include/PSX/Auxiliary/word_helper.hpp b/include/PSX/Auxiliary/word_helper.hpp new file mode 100644 index 00000000..6675c8af --- /dev/null +++ b/include/PSX/Auxiliary/word_helper.hpp @@ -0,0 +1,15 @@ +#pragma once +#include + +namespace JabyEngine { + using word_t = uint32_t; + + static constexpr size_t bytes_to_words(size_t bytes) { + return bytes/sizeof(word_t); + } + + static constexpr size_t words_to_bytes(size_t words) { + return words*sizeof(word_t); + } +} + diff --git a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp index 1416fe0f..36dd32e2 100644 --- a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp +++ b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp @@ -24,6 +24,22 @@ namespace JabyEngine { static constexpr auto CDAudioEnable = Bit(0); }; + __declare_io_value(StatusRegister, uint16_t) { + static constexpr auto Unused = BitRange::from_to(12, 15); + static constexpr auto CaputreBufferHalf = Bit(11); // TODO: Turn into enum?; Writing to First/Second half of Capture Buffers (0=First, 1=Second) + static constexpr auto TransferBusy = Bit(10); + static constexpr auto IsDMARead = Bit(9); + static constexpr auto isDMAWrite = Bit(8); + static constexpr auto isDMA = Bit(7); + static constexpr auto isIRQ = Bit(6); + // Copies of ControlRegister + static constexpr auto TransferMode = BitRange::from_to(4, 5); + static constexpr auto ExternalAudioReverb = Bit(3); + static constexpr auto CDAudioReverb = Bit(2); + static constexpr auto ExternalAudioEnable = Bit(1); + static constexpr auto CDAudioEnable = Bit(0); + }; + __declare_io_value(SRAM_Adr, uint16_t) {}; } } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index f6eb9b07..9d6197ee 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -163,8 +163,11 @@ namespace JabyEngine { } }; + struct StatusRegisterIO : public IOPort {}; + // TODO: The new way? v Parse with a Macro? static auto& ControlRegister = *reinterpret_cast(0x1F801DAA); + static auto& StatusRegister = *reinterpret_cast(0x1F801DAE); static auto& SRAMTransferAdr = *reinterpret_cast(0x1F801DA6); //__declare_io_port(, ControlRegister, 0x1F801DAA); diff --git a/src/Library/internal-include/SPU/spu_internal.hpp b/src/Library/internal-include/SPU/spu_internal.hpp index 21726d8a..9cdf0805 100644 --- a/src/Library/internal-include/SPU/spu_internal.hpp +++ b/src/Library/internal-include/SPU/spu_internal.hpp @@ -8,6 +8,7 @@ namespace JabyEngine { struct DMA { static void wait() { DMA_IO::SPU.wait(); + while(SPU_IO::StatusRegister.read().is_set(SPU_IO_Values::StatusRegister::TransferBusy)); } static void end() { @@ -16,9 +17,9 @@ namespace JabyEngine { struct Receive { static void prepare() { + end(); SPU_IO::DataTransferControl.write(SPU_IO::DataTransferControl::NormalTransferMode()); SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::Stop); - SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::DMAWrite); } static void set_src(uintptr_t adr) { @@ -27,9 +28,9 @@ namespace JabyEngine { static void set_dst(SPU::SRAM_Adr adr) { SPU_IO::SRAMTransferAdr.write(adr); + SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::DMAWrite); } - // Not adjusted yet static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { using SyncMode1 = DMA_IO::BCR::SyncMode1; diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 5734538d..4468aca1 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -1,5 +1,6 @@ #include "../../../internal-include/SPU/spu_internal.hpp" #include +#include #include #include #include @@ -31,32 +32,36 @@ namespace JabyEngine { struct VAGState { uint32_t voice_id; - size_t bytes_left; + size_t words_left; SPU::SRAM_Adr adr; static constexpr VAGState create(uint32_t voice_id) { - return VAGState{.voice_id = voice_id, .bytes_left = 0, .adr = 0}; + return VAGState{.voice_id = voice_id, .words_left = 0, .adr = 0}; } }; static Progress parse_sample(State::Configuration& config, VAGState& state) { - // Load balancer? + const auto [words_to_use, is_last] = Helper::DMA::WordsReady::calculate(config, state.words_left); + const auto words_used = Helper::DMA::send_words(words_to_use, is_last); - - return Progress::Error; + state.words_left -= words_used; + config.processed(words_used*sizeof(uint32_t)); + return is_last ? Progress::Done : Progress::InProgress; } static Progress parse_header(State::Configuration& config, VAGState& state) { if(config.data_bytes >= sizeof(VAGHeader)) { const auto& header = *reinterpret_cast(config.data_adr); + const auto bytes = header.get_sample_size(); - state.bytes_left = header.get_sample_size(); - state.adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), state.bytes_left); - - SPU::internal::DMA::Receive::prepare(); - SPU::internal::DMA::Receive::set_dst(state.adr); + state.words_left = bytes_to_words(bytes); + state.adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), words_to_bytes(state.words_left)); config.processed(sizeof(VAGHeader)); + SPU::internal::DMA::Receive::prepare(); + SPU::internal::DMA::Receive::set_dst(state.adr); + SPU::internal::DMA::Receive::set_src(reinterpret_cast(config.data_adr)); + return Helper::exchange_and_execute_process_function(parse_sample, config, state); }