Use DMA for GPU

This commit is contained in:
jaby 2022-09-11 15:44:45 +02:00
parent b9b01bd544
commit 30824748ea
8 changed files with 143 additions and 20 deletions

View File

@ -79,40 +79,79 @@ public:
//Accesssing bits
template<typename S>
constexpr __always_inline ComplexBitMap<T>& set_bit(S bit) {
constexpr ComplexBitMap<T>& set_bit(S bit) {
this->raw = bit::set(this->raw, static_cast<size_t>(bit));
return *this;
}
template<typename S>
constexpr __always_inline ComplexBitMap<T>& clear_bit(S bit) {
constexpr void set_bit(S bit) volatile {
this->raw = bit::set(this->raw, static_cast<size_t>(bit));
}
template<typename S>
constexpr ComplexBitMap<T>& clear_bit(S bit) {
this->raw = bit::clear(this->raw, static_cast<size_t>(bit));
return *this;
}
template<typename S>
constexpr __always_inline bool is_bit_set(S bit) {
constexpr void clear_bit(S bit) volatile {
this->raw = bit::clear(this->raw, static_cast<size_t>(bit));
}
template<typename S>
constexpr bool is_bit_set(S bit) {
return bit::is_set(this->raw, static_cast<size_t>(bit));
}
template<typename S>
constexpr bool is_bit_set(S bit) const volatile {
return bit::is_set(this->raw, static_cast<size_t>(bit));
}
//Accessing values
template<typename S>
constexpr __always_inline ComplexBitMap<T>& set_value(S value, const BitRange<S>& range) {
constexpr ComplexBitMap<T>& set_value(S value, const BitRange<S>& range) {
this->raw = bit::value::set_normalized(this->raw, static_cast<T>(value), range.begin, range.length);
return *this;
}
template<typename S>
constexpr __always_inline ComplexBitMap<T>& clear_value(const BitRange<S>& range) {
constexpr void set_value(S value, const BitRange<S>& range) volatile {
this->raw = bit::value::set_normalized(this->raw, static_cast<T>(value), range.begin, range.length);
}
template<typename S>
constexpr ComplexBitMap<T>& clear_value(const BitRange<S>& range) {
this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length);
return *this;
}
template<typename S>
constexpr __always_inline S get_value(const BitRange<S>& range) {
constexpr void clear_value(const BitRange<S>& range) volatile {
this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length);
}
template<typename S>
constexpr S get_value(const BitRange<S>& range) {
return static_cast<S>(bit::value::get_normalized(this->raw, range.begin, range.length));
}
template<typename S>
constexpr S get_value(const BitRange<S>& range) volatile {
return static_cast<S>(bit::value::get_normalized(this->raw, range.begin, range.length));
}
//For easier checking
constexpr bool is(Bit<T> bit) const {
return ComplexBitMap::is_bit_set(bit);
}
constexpr bool is(Bit<T> bit) const volatile {
return ComplexBitMap::is_bit_set(bit);
}
// For easier constructing
constexpr __always_inline ComplexBitMap<T>& set(const BitRange<T>& range, T value) {
this->set_value(value, range);

View File

@ -18,9 +18,11 @@ namespace DMA {
static constexpr auto CD_OneBlock = Bit<uint16_t>(16);
};
struct __no_align SyncMode1 {
static constexpr auto BlockSize = BitRange<uint16_t>::from_to(0, 15);
static constexpr auto BlockAmount = BitRange<uint16_t>::from_to(16, 31);
struct __no_align SyncMode1 : public ComplexBitMap<uint32_t> {
__io_port_inherit_complex_bit_map(SyncMode1);
static constexpr auto BlockSize = BitRange<uint32_t>::from_to(0, 15);
static constexpr auto BlockAmount = BitRange<uint32_t>::from_to(16, 31);
};
struct __no_align SyncMode2 {
@ -83,9 +85,9 @@ namespace DMA {
};
struct __no_align Registers {
MADR adr;
BCR block_ctrl;
CHCHR channel_ctrl;
IOPort<MADR> adr;
IOPort<BCR> block_ctrl;
IOPort<CHCHR> channel_ctrl;
};
//0: Highest, 7: Lowest
@ -130,7 +132,7 @@ namespace DMA {
__declare_io_port_global(Registers, MDECin, 0x1F801080);
__declare_io_port_global(Registers, MDECout, 0x1F801090);
__declare_io_port_global(Registers, GPU, 0x1F8010A0);
__declare_io_port_global_struct(Registers, GPU, 0x1F8010A0);
__declare_io_port_global(Registers, CDROM, 0x1F8010B0);
__declare_io_port_global(Registers, SPU, 0x1F8010C0);
__declare_io_port_global(Registers, PIO, 0x1F8010D0);

View File

@ -32,7 +32,7 @@ namespace GPU {
enum struct DMADirection {
Off = 0,
Unknown = 1,
Fifo = 1,
CPU2GPU = 2,
GPU2CPU = 3,
};
@ -50,6 +50,10 @@ namespace GPU {
return ComplexBitMap{(0x02 << 24) | color.raw()};
}
static constexpr GP0 CPU2VRAM_Blitting() {
return ComplexBitMap{(0b101u << 29)};
}
static constexpr GP0 TopLeftPosition(uint16_t x, uint16_t y) {
return ComplexBitMap{static_cast<uint32_t>((y << 16u) | x)};
}
@ -70,9 +74,17 @@ namespace GPU {
return ComplexBitMap{0};
}
static constexpr GP1 ResetCMDBufer() {
return ComplexBitMap{construct_cmd(0x01, 0)};
}
static constexpr GP1 SetDisplayState(DisplayState state) {
return ComplexBitMap{construct_cmd(0x03, static_cast<uint32_t>(state))};
}
static constexpr GP1 DMADirection(DMADirection dir) {
return ComplexBitMap{construct_cmd(0x04, static_cast<uint32_t>(dir))};
}
};
}

View File

@ -20,6 +20,10 @@ public:
constexpr volatile T& ref() {
return const_cast<volatile IOPort<T>*>(this)->value;
}
constexpr const volatile T& ref() const {
return const_cast<volatile IOPort<T>*>(this)->value;
}
};
struct __no_align ubus32_t {
@ -52,11 +56,15 @@ struct __no_align ubus32_t {
};
static constexpr uintptr_t IO_Base_Mask = 0xF0000000;
static constexpr uintptr_t IO_Base_Adr = 0x10000000;
#define __declare_io_port_global_raw(cv, type, name, adr) static __always_inline cv auto& name = *reinterpret_cast<IOPort<type>*>((IO_Base_Adr + (adr & ~IO_Base_Mask)))
#define __io_port_adr(adr) (IO_Base_Adr + (adr & ~IO_Base_Mask))
#define __declare_io_port_global_raw(cv, type, name, adr) static __always_inline cv auto& name = *reinterpret_cast<IOPort<type>*>(__io_port_adr(adr))
#define __declare_io_port_global(type, name, adr) __declare_io_port_global_raw(, type, name, adr)
#define __declare_io_port_global_const(type, name, adr) __declare_io_port_global_raw(const, type, name, adr)
#define __declare_io_port_global_array(type, name, adr, size) static __always_inline auto& name = reinterpret_cast<type(&)[size]>(*reinterpret_cast<type*>((IO_Base_Adr + (adr & ~IO_Base_Mask))));
#define __declare_io_port_global_array(type, name, adr, size) static __always_inline auto& name = reinterpret_cast<type(&)[size]>(*reinterpret_cast<type*>((IO_Base_Adr + (adr & ~IO_Base_Mask))))
#define __declare_io_port_global_struct(type, name, adr) static __always_inline auto& name = *reinterpret_cast<type*>(__io_port_adr(adr))
#define __io_port_inherit_complex_bit_map(name) \
constexpr __always_inline name() = default; \
constexpr __always_inline name(ComplexBitMap value) : ComplexBitMap(value) { \

View File

@ -1,6 +1,7 @@
#ifndef __JABYENGINE_INTERNAL_GPU_HPP__
#define __JABYENGINE_INTERNAL_GPU_HPP__
#include <PSX/GPU/GPU_Types.hpp>
#include <PSX/System/IOPorts/DMA_IO.hpp>
#include <PSX/System/IOPorts/GPU_IO.hpp>
namespace GPU {
@ -9,6 +10,51 @@ namespace GPU {
Port::GP0.write(Port::Command::GP0::TopLeftPosition(pos.x, pos.y));
Port::GP0.write(Port::Command::GP0::WidthHeight(size.width, size.height));
}
static void reset_cmd_buffer() {
Port::GP1.write(Port::Command::GP1::ResetCMDBufer());
}
static void wait_ready_for_CMD() {
while(!Port::GPUSTAT.ref().is(Port::GPUStatusRegister::GP0ReadyForCMD));
}
namespace DMA {
static void wait() {
while(::DMA::Port::GPU.channel_ctrl.ref().is(::DMA::Port::CHCHR::Busy));
}
static void end() {
reset_cmd_buffer();
}
namespace Receive {
static void prepare()
{
Port::GP1.write(Port::Command::GP1::DMADirection(Port::DMADirection::CPU2GPU));
reset_cmd_buffer();
}
static void set_src(uintptr_t adr) {
::DMA::Port::GPU.adr.ref().set_value(static_cast<uint32_t>(adr), ::DMA::Port::MADR::MemoryAdr);
}
static void set_dst(const PositionU16& position, const SizeU16& size) {
wait_ready_for_CMD();
Port::GP0.write(Port::Command::GP0::CPU2VRAM_Blitting());
Port::GP0.write(Port::Command::GP0::TopLeftPosition(position.x, position.y));
Port::GP0.write(Port::Command::GP0::WidthHeight(size.width, size.height));
}
static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) {
typedef ::DMA::Port::BCR::SyncMode1 SyncMode1;
::DMA::Port::GPU.block_ctrl.write(SyncMode1::with(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount)));
::DMA::Port::GPU.channel_ctrl.write(::DMA::Port::CHCHR::StartGPUReceive());
}
}
}
}
#endif //!__JABYENGINE_INTERNAL_GPU_HPP__

View File

@ -20,6 +20,18 @@ namespace GPU {
void display_logo() {
Display::disable();
quick_fill_fast(Color24(0x0, 0x80, 0x80), PositionU16(0, 0), SizeU16(640, 480));
//DMA Start
DMA::Receive::prepare();
DMA::Receive::set_dst(PositionU16(0, 0), SizeU16(12, 12));
DMA::Receive::set_src(reinterpret_cast<uintptr_t>(&TestSequence));
DMA::Receive::start(12, (12*sizeof(Color))/sizeof(uint32_t));
DMA::wait();
DMA::end();
//DMA End
Display::enable();
}

View File

@ -95,8 +95,5 @@ namespace SPU {
setup_data_transfer_control();
setup_control_register();
// Enable SPU DMA
DPCR.write(DPCR.read() | DMAControlRegister::SPUEnable);
}
}

View File

@ -1,12 +1,19 @@
#include "BootLoader/boot_loader.hpp"
#include <PSX/System/IOPorts/DMA_IO.hpp>
#include <stdio.h>
using namespace DMA::Port;
namespace JabyEngine {
static void enable_DMA() {
DPCR.write(DPCR.read() | DMAControlRegister::SPUEnable | DMAControlRegister::GPUEnable);
}
void start() {
printf("Hello Planschbecken\n");
enable_DMA();
SPU::stop_voices();
GPU::display_logo();
//Load picture here
//Pause??