Use DMA for GPU
This commit is contained in:
parent
2a97f7fa68
commit
303ffbccc9
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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) { \
|
||||
|
|
|
@ -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__
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -95,8 +95,5 @@ namespace SPU {
|
|||
|
||||
setup_data_transfer_control();
|
||||
setup_control_register();
|
||||
|
||||
// Enable SPU DMA
|
||||
DPCR.write(DPCR.read() | DMAControlRegister::SPUEnable);
|
||||
}
|
||||
}
|
|
@ -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??
|
||||
|
|
Loading…
Reference in New Issue