Add new IOPort design
This commit is contained in:
parent
509c25dfec
commit
3da34d0686
|
@ -63,6 +63,7 @@ namespace JabyEngine {
|
|||
template<typename T>
|
||||
class ComplexBitMap {
|
||||
public:
|
||||
typedef T UnderlyingType;
|
||||
T raw;
|
||||
|
||||
private:
|
||||
|
|
|
@ -11,9 +11,7 @@ namespace JabyEngine {
|
|||
Index3 = 3,
|
||||
};
|
||||
|
||||
struct __no_align IndexStatus : public ComplexBitMap<uint8_t> {
|
||||
__io_port_inherit_complex_bit_map(IndexStatus);
|
||||
|
||||
typedef struct IndexStatus : public ComplexBitMap<uint8_t> {
|
||||
static constexpr auto PortIndex = BitRange<Index>::from_to(0, 1);
|
||||
static constexpr auto HasXAFifoData = Bit<uint8_t>(2);
|
||||
static constexpr auto IsParameterFifoEmpty = Bit<uint8_t>(3);
|
||||
|
@ -21,20 +19,16 @@ namespace JabyEngine {
|
|||
static constexpr auto HasResponseFifoData = Bit<uint8_t>(5);
|
||||
static constexpr auto HasDataFifoData = Bit<uint8_t>(6);
|
||||
static constexpr auto IsTransmissionBusy = Bit<uint8_t>(7);
|
||||
};
|
||||
|
||||
struct __no_align InterruptEnable : public ComplexBitMap<uint8_t> {
|
||||
__io_port_inherit_complex_bit_map(InterruptEnable);
|
||||
} IndexStatus_t;
|
||||
|
||||
struct InterruptEnable : public ComplexBitMap<uint8_t> {
|
||||
static constexpr auto InterruptTypValue = BitRange<uint8_t>::from_to(0, 2);
|
||||
static constexpr auto UnknownIRQ = Bit<uint8_t>(3);
|
||||
static constexpr auto CommandStartIRQ = Bit<uint8_t>(4);
|
||||
};
|
||||
typedef InterruptEnable InterruptFlag;
|
||||
|
||||
struct __no_align Request : public ComplexBitMap<uint8_t> {
|
||||
__io_port_inherit_complex_bit_map(Request);
|
||||
|
||||
struct Request : public ComplexBitMap<uint8_t> {
|
||||
static constexpr auto WantCommandStartIRQ = Bit<uint8_t>(5);
|
||||
static constexpr auto WantData = Bit<uint8_t>(7);
|
||||
};
|
||||
|
@ -63,34 +57,34 @@ namespace JabyEngine {
|
|||
struct __no_align IndexTriplet {
|
||||
// Replace with proper types later
|
||||
union __no_align {
|
||||
const IOPort<ResponseFifo> response_fifo;
|
||||
IOPort<CommandFifo> command;
|
||||
const IOPort<uint8_t, ResponseFifo> response_fifo;
|
||||
IOPort<uint8_t, CommandFifo> command;
|
||||
};
|
||||
|
||||
union __no_align {
|
||||
const IOPort<DataFifo> data_fifo;
|
||||
IOPort<ParameterFifo> parameter_fifo;
|
||||
const IOPort<uint8_t, DataFifo> data_fifo;
|
||||
IOPort<uint8_t, ParameterFifo> parameter_fifo;
|
||||
};
|
||||
|
||||
union __no_align {
|
||||
const IOPort<InterruptEnable> irq_enable;
|
||||
IOPort<Request> request;
|
||||
const IOPort<InterruptEnable::UnderlyingType, InterruptEnable> irq_enable;
|
||||
IOPort<Request::UnderlyingType, Request> request;
|
||||
};
|
||||
|
||||
const IOPort<uint16_t>& get_data_fifo_16() const {
|
||||
return *reinterpret_cast<const IOPort<uint16_t>*>(&this->data_fifo);
|
||||
const IOPort<uint16_t, DataFifo16>& get_data_fifo_16() const {
|
||||
return *reinterpret_cast<const IOPort<uint16_t, DataFifo16>*>(&this->data_fifo);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(IndexTriplet) == 3);
|
||||
}
|
||||
|
||||
__declare_io_port_global(struct IndexStatus, IndexStatus, 0x1F801800);
|
||||
__declare_io_port_global(IndexStatus_t, IndexStatus, 0x1F801800);
|
||||
|
||||
namespace Helper {
|
||||
template<typename S>
|
||||
static S& change_to(Index idx) {
|
||||
IndexStatus.write(ComplexBitMap(static_cast<uint8_t>(idx)));
|
||||
IndexStatus.write({static_cast<uint8_t>(idx)});
|
||||
return *reinterpret_cast<S*>(0x1F801801);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,34 +4,26 @@
|
|||
|
||||
namespace JabyEngine {
|
||||
namespace DMA_IO {
|
||||
struct __no_align MADR : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(MADR);
|
||||
|
||||
struct MADR : public ComplexBitMap<uint32_t> {
|
||||
static constexpr auto MemoryAdr = BitRange<uint32_t>::from_to(0, 23);
|
||||
};
|
||||
|
||||
struct __no_align BCR : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(BCR);
|
||||
|
||||
struct BCR : public ComplexBitMap<uint32_t> {
|
||||
struct __no_align SyncMode0 {
|
||||
static constexpr auto NumberOfWords = BitRange<uint16_t>::from_to(0, 15);
|
||||
static constexpr auto CD_OneBlock = Bit<uint16_t>(16);
|
||||
};
|
||||
|
||||
struct __no_align SyncMode1 : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(SyncMode1);
|
||||
|
||||
struct SyncMode1 : public ComplexBitMap<uint32_t> {
|
||||
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 {
|
||||
struct SyncMode2 {
|
||||
};
|
||||
};
|
||||
|
||||
struct __no_align CHCHR : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(CHCHR);
|
||||
|
||||
struct CHCHR : public ComplexBitMap<uint32_t> {
|
||||
enum _SyncMode {
|
||||
Sync0 = 0, //Start immediately,
|
||||
Sync1 = 1, //Sync blocks to DMA requests
|
||||
|
@ -60,34 +52,34 @@ namespace JabyEngine {
|
|||
static constexpr auto ToMainRAM = !FromMainRAM;
|
||||
|
||||
static constexpr CHCHR StartMDECin() {
|
||||
return ComplexBitMap{0x01000201};
|
||||
return CHCHR{0x01000201};
|
||||
}
|
||||
|
||||
static constexpr CHCHR StartMDECout() {
|
||||
return ComplexBitMap{0x01000200};
|
||||
return CHCHR{0x01000200};
|
||||
}
|
||||
|
||||
static constexpr CHCHR StartGPUReceive() {
|
||||
return ComplexBitMap{0x01000201};
|
||||
return CHCHR{0x01000201};
|
||||
}
|
||||
|
||||
static constexpr CHCHR StartCDROM() {
|
||||
return ComplexBitMap{0x11000000};
|
||||
return CHCHR{0x11000000};
|
||||
}
|
||||
|
||||
static constexpr CHCHR StartSPUReceive() {
|
||||
return ComplexBitMap{0x01000201};
|
||||
return CHCHR{0x01000201};
|
||||
}
|
||||
|
||||
static constexpr CHCHR StartOTC() {
|
||||
return ComplexBitMap{0x11000002};
|
||||
return CHCHR{0x11000002};
|
||||
}
|
||||
};
|
||||
|
||||
struct __no_align Registers {
|
||||
IOPort<MADR> adr;
|
||||
IOPort<BCR> block_ctrl;
|
||||
IOPort<CHCHR> channel_ctrl;
|
||||
IOPort<MADR::UnderlyingType, MADR> adr;
|
||||
IOPort<BCR::UnderlyingType, BCR> block_ctrl;
|
||||
IOPort<CHCHR::UnderlyingType, CHCHR> channel_ctrl;
|
||||
};
|
||||
|
||||
//0: Highest, 7: Lowest
|
||||
|
@ -95,9 +87,7 @@ namespace JabyEngine {
|
|||
static constexpr Priority HighestPriority = 0;
|
||||
static constexpr Priority LowestPriority = 7;
|
||||
|
||||
struct __no_align DMAControlRegister : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(DMAControlRegister);
|
||||
|
||||
struct DMAControlRegister : public ComplexBitMap<uint32_t> {
|
||||
static constexpr auto OTCEnable = Bit<uint32_t>(27);
|
||||
static constexpr auto OTCPriority = BitRange<Priority>::from_to(24, 26);
|
||||
|
||||
|
@ -120,9 +110,7 @@ namespace JabyEngine {
|
|||
static constexpr auto MDECinPriority = BitRange<Priority>::from_to(0, 2);
|
||||
};
|
||||
|
||||
struct __no_align DMAInterruptRegister : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(DMAInterruptRegister);
|
||||
|
||||
struct DMAInterruptRegister : public ComplexBitMap<uint32_t> {
|
||||
static constexpr auto MasterEnable = Bit<uint32_t>(31);
|
||||
static constexpr auto Flags = BitRange<uint32_t>::from_to(24, 30);
|
||||
static constexpr auto MasterEnableDPCR = Bit<uint32_t>(23);
|
||||
|
|
|
@ -48,15 +48,14 @@ namespace JabyEngine {
|
|||
};
|
||||
|
||||
struct Command {
|
||||
struct __no_align GP0 : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(GP0);
|
||||
struct GP0 : public ComplexBitMap<uint32_t> {
|
||||
|
||||
static constexpr GP0 QuickFill(GPU::Color24 color) {
|
||||
return ComplexBitMap{(0x02 << 24) | color.raw()};
|
||||
return {(0x02 << 24) | color.raw()};
|
||||
}
|
||||
|
||||
static constexpr GP0 CPU2VRAM_Blitting() {
|
||||
return ComplexBitMap{(0b101u << 29)};
|
||||
return {(0b101u << 29)};
|
||||
}
|
||||
|
||||
static constexpr GP0 DrawAreaTemplate(uint8_t code, uint16_t x, uint16_t y) {
|
||||
|
@ -64,7 +63,7 @@ namespace JabyEngine {
|
|||
constexpr auto Y = BitRange<uint32_t>::from_to(10, 18);
|
||||
constexpr auto X = BitRange<uint32_t>::from_to(0, 9);
|
||||
|
||||
return ComplexBitMap<uint32_t>::with(Command.with(code), Y.with(y), X.with(x));
|
||||
return {GP0::with(Command.with(code), Y.with(y), X.with(x))};
|
||||
}
|
||||
|
||||
static constexpr GP0 DrawAreaTopLeft(uint16_t x, uint16_t y) {
|
||||
|
@ -76,65 +75,63 @@ namespace JabyEngine {
|
|||
}
|
||||
|
||||
static constexpr GP0 TopLeftPosition(uint16_t x, uint16_t y) {
|
||||
return ComplexBitMap{static_cast<uint32_t>((y << 16u) | x)};
|
||||
return {static_cast<uint32_t>((y << 16u) | x)};
|
||||
}
|
||||
|
||||
static constexpr GP0 WidthHeight(uint16_t w, uint16_t h) {
|
||||
return ComplexBitMap{static_cast<uint32_t>((h << 16u) | w)};
|
||||
return {static_cast<uint32_t>((h << 16u) | w)};
|
||||
}
|
||||
};
|
||||
|
||||
struct __no_align GP1 : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(GP1);
|
||||
|
||||
struct GP1 : public ComplexBitMap<uint32_t> {
|
||||
static constexpr uint32_t construct_cmd(uint8_t cmd, uint32_t value) {
|
||||
return ((cmd << 24) | value);
|
||||
}
|
||||
|
||||
static constexpr GP1 Reset() {
|
||||
return ComplexBitMap{0};
|
||||
return {0};
|
||||
}
|
||||
|
||||
static constexpr GP1 ResetCMDBufer() {
|
||||
return ComplexBitMap{construct_cmd(0x01, 0)};
|
||||
return {construct_cmd(0x01, 0)};
|
||||
}
|
||||
|
||||
static constexpr GP1 SetDisplayState(DisplayState state) {
|
||||
return ComplexBitMap{construct_cmd(0x03, static_cast<uint32_t>(state))};
|
||||
return {construct_cmd(0x03, static_cast<uint32_t>(state))};
|
||||
}
|
||||
|
||||
static constexpr GP1 DMADirection(DMADirection dir) {
|
||||
return ComplexBitMap{construct_cmd(0x04, static_cast<uint32_t>(dir))};
|
||||
return {construct_cmd(0x04, static_cast<uint32_t>(dir))};
|
||||
}
|
||||
|
||||
static constexpr GP1 DisplayArea(uint16_t x, uint16_t y) {
|
||||
constexpr auto X = BitRange<uint32_t>::from_to(0, 9);
|
||||
constexpr auto Y = BitRange<uint32_t>::from_to(10, 18);
|
||||
|
||||
return ComplexBitMap{construct_cmd(0x05, ComplexBitMap<uint32_t>::with(X.with(x), Y.with(y)).raw)};
|
||||
return {construct_cmd(0x05, ComplexBitMap<uint32_t>::with(X.with(x), Y.with(y)).raw)};
|
||||
}
|
||||
|
||||
static constexpr GP1 HorizontalDisplayRange(uint32_t x1, uint32_t x2) {
|
||||
constexpr auto X1 = BitRange<uint32_t>::from_to(0, 11);
|
||||
constexpr auto X2 = BitRange<uint32_t>::from_to(12, 23);
|
||||
|
||||
return ComplexBitMap{construct_cmd(0x06, ComplexBitMap<uint32_t>::with(X1.with(x1), X2.with(x2)).raw)};
|
||||
return {construct_cmd(0x06, ComplexBitMap<uint32_t>::with(X1.with(x1), X2.with(x2)).raw)};
|
||||
}
|
||||
|
||||
static constexpr GP1 VerticalDisplayRange(uint32_t y1, uint32_t y2) {
|
||||
constexpr auto Y1 = BitRange<uint32_t>::from_to(0, 9);
|
||||
constexpr auto Y2 = BitRange<uint32_t>::from_to(10, 19);
|
||||
|
||||
return ComplexBitMap{construct_cmd(0x07, ComplexBitMap<uint32_t>::with(Y1.with(y1), Y2.with(y2)).raw)};
|
||||
return {construct_cmd(0x07, ComplexBitMap<uint32_t>::with(Y1.with(y1), Y2.with(y2)).raw)};
|
||||
}
|
||||
|
||||
static constexpr GP1 DisplayMode(uint32_t mode) {
|
||||
return ComplexBitMap{construct_cmd(0x08, mode)};
|
||||
return {construct_cmd(0x08, mode)};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct __no_align GPUStatusRegister : public ComplexBitMap<uint32_t> {
|
||||
struct GPUStatusRegister : public ComplexBitMap<uint32_t> {
|
||||
static constexpr auto DrawingOddLinesInterlaced = Bit<uint32_t>(31);
|
||||
static constexpr auto DMADirectionValue = BitRange<DMADirection>::from_to(29, 30);
|
||||
static constexpr auto DMAReady = Bit<uint32_t>(28);
|
||||
|
@ -166,7 +163,7 @@ namespace JabyEngine {
|
|||
__declare_io_port_global(Command::GP0, GP0, 0x1F801810);
|
||||
__declare_io_port_global(Command::GP1, GP1, 0x1F801814);
|
||||
|
||||
__declare_io_port_global_const(uint32_t, GPUREAD, 0x1F801810);
|
||||
__declare_io_port_global_const_simple(uint32_t, GPUREAD, 0x1F801810);
|
||||
__declare_io_port_global_const(GPUStatusRegister, GPUSTAT, 0x1F801814);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,31 +17,29 @@ namespace JabyEngine {
|
|||
static constexpr auto Controller = Bit<uint32_t>(10);
|
||||
static constexpr auto LightPen = Controller;
|
||||
|
||||
struct __no_align Status : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(Status);
|
||||
};
|
||||
typedef struct Status : public ComplexBitMap<uint32_t> {
|
||||
} Status_t;
|
||||
|
||||
struct __no_align Mask : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(Mask);
|
||||
};
|
||||
typedef struct Mask : public ComplexBitMap<uint32_t> {
|
||||
} Mask_t;
|
||||
|
||||
__declare_io_port_member(struct Status, Status, 0x1F801070);
|
||||
__declare_io_port_member(struct Mask, Mask, 0x1F801074);
|
||||
__declare_io_port_member(Status_t, Status, 0x1F801070);
|
||||
__declare_io_port_member(Mask_t, Mask, 0x1F801074);
|
||||
|
||||
static bool is_irq(Bit<uint32_t> irq) {
|
||||
return Status.read().is_bit_set(irq);
|
||||
}
|
||||
|
||||
static void ack_irq(Bit<uint32_t> irq) {
|
||||
Status.write(Status.read().clear_bit(irq));
|
||||
Status.write({Status.read().clear_bit(irq)});
|
||||
}
|
||||
|
||||
static void disable_irq(Bit<uint32_t> irq) {
|
||||
Mask.write(Mask.read().clear_bit(irq));
|
||||
Mask.write({Mask.read().clear_bit(irq)});
|
||||
}
|
||||
|
||||
static void enable_irq(Bit<uint32_t> irq) {
|
||||
Mask.write(Mask.read().set_bit(irq));
|
||||
Mask.write({Mask.read().set_bit(irq)});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,94 +3,82 @@
|
|||
#include "../../Auxiliary/complex_bitmap.hpp"
|
||||
|
||||
namespace JabyEngine {
|
||||
template<typename T>
|
||||
template<typename T, typename S/* = T*/>
|
||||
class __no_align IOPort {
|
||||
private:
|
||||
T value;
|
||||
volatile T value;
|
||||
|
||||
public:
|
||||
// decltype(this) instead of IOPort<T>* lead to wrong runtime behaviour somethow...
|
||||
constexpr T read() const {
|
||||
return const_cast<const volatile IOPort<T>*>(this)->value;
|
||||
constexpr T read_raw() const {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
constexpr S read(const BitRange<S>& range) const {
|
||||
constexpr S read() const {
|
||||
return S{this->value};
|
||||
}
|
||||
|
||||
constexpr T read_range_value(const BitRange<T>& range) const {
|
||||
return IOPort::read().get_value(range);
|
||||
}
|
||||
|
||||
template<typename...ARGS>
|
||||
constexpr void write_combined(const ARGS&... value) {
|
||||
IOPort::write(T::with(value...));
|
||||
constexpr void write_raw(T value) {
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
constexpr void write(const BitRangeValue<S>& value) {
|
||||
IOPort::write(T::with(value));
|
||||
constexpr void write(const S& value) {
|
||||
this->value = static_cast<T>(value);
|
||||
}
|
||||
|
||||
constexpr void write(const T& value) {
|
||||
const_cast<volatile IOPort<T>*>(this)->value = value;
|
||||
constexpr void write_range_value(const BitRangeValue<T>& value) {
|
||||
IOPort<T, S>::write(S{S::with(value)});
|
||||
}
|
||||
|
||||
// We keep this a POD so we will not add assignment operators anymore
|
||||
// We also removed ref() to be more percise
|
||||
};
|
||||
|
||||
struct __no_align ubus32_t {
|
||||
ComplexBitMap<uint16_t> low;
|
||||
ComplexBitMap<uint16_t> high;
|
||||
typedef ComplexBitMap<uint16_t> Base16;
|
||||
|
||||
IOPort<Base16::UnderlyingType, Base16> low;
|
||||
IOPort<Base16::UnderlyingType, Base16> high;
|
||||
|
||||
constexpr ubus32_t(uint32_t value) {
|
||||
*this = value;
|
||||
}
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return ((this->high.raw << 16) | this->low.raw);
|
||||
constexpr void write(uint32_t value) {
|
||||
*this = value;
|
||||
}
|
||||
|
||||
operator uint32_t() const volatile {
|
||||
return ((this->high.raw << 16) | this->low.raw);
|
||||
constexpr operator uint32_t() const {
|
||||
return ((this->high.read_raw() << 16) | this->low.read_raw());
|
||||
}
|
||||
|
||||
constexpr ubus32_t& operator=(uint32_t value) {
|
||||
this->low.raw = (value & 0xFFFF);
|
||||
this->high.raw = (value >> 16);
|
||||
this->low.write_raw(value & 0xFFFF);
|
||||
this->high.write_raw(value >> 16);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr void operator=(uint32_t value) volatile {
|
||||
this->low.raw = (value & 0xFFFF);
|
||||
this->high.raw = (value >> 16);
|
||||
}
|
||||
};
|
||||
static constexpr uintptr_t IO_Base_Mask = 0xF0000000;
|
||||
static constexpr uintptr_t IO_Base_Adr = 0x10000000;
|
||||
|
||||
#define __declare_global_raw(cv, type, name, adr) static __always_inline cv auto& name = *reinterpret_cast<type*>(__io_port_adr(adr))
|
||||
|
||||
#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_raw(cv, type, sub_type, name, adr) __declare_global_raw(cv, __collect(IOPort<type, sub_type>), name, adr)
|
||||
|
||||
#define __declare_io_port_member(type, name, adr) __declare_io_port_global_raw(inline, type, name, adr)
|
||||
#define __declare_io_port_member_const(type, name, adr) __declare_io_port_global_raw(const inline, type, name, adr)
|
||||
#define __declare_io_port_global(type, name, adr) __declare_io_port_global_raw(, type::UnderlyingType, type, name, adr)
|
||||
#define __declare_io_port_global_const(type, name, adr) __declare_io_port_global_raw(const, type::UnderlyingType, type, name, adr)
|
||||
#define __declare_io_port_global_simple(type, name, adr) __declare_io_port_global_raw(, type, type, name, adr)
|
||||
#define __declare_io_port_global_const_simple(type, name, adr) __declare_io_port_global_raw(const, type, type, name, adr)
|
||||
|
||||
#define __declare_io_port_member(type, name, adr) __declare_io_port_global_raw(inline, type::UnderlyingType, type, name, adr)
|
||||
#define __declare_io_port_member_const(type, name, adr) __declare_io_port_global_raw(const inline, type::UnderlyingType, type, name, adr)
|
||||
#define __declare_io_port_member_simple(type, name, adr) __declare_io_port_global_raw(inline, type, type, name, adr)
|
||||
#define __declare_io_port_member_const_simple(type, name, adr) __declare_io_port_global_raw(const inline, type, 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_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) { \
|
||||
} \
|
||||
template<typename...ARGS> \
|
||||
static constexpr __always_inline name with(ARGS...args) { \
|
||||
return {ComplexBitMap::with(args...)}; \
|
||||
}\
|
||||
template<typename T> \
|
||||
constexpr void __always_inline operator=(ComplexBitMap<T> value) volatile { \
|
||||
this->raw = value.raw; \
|
||||
}
|
||||
}
|
||||
#endif //!__JABYENGINE_IOPORT_HPP__
|
|
@ -27,20 +27,16 @@ namespace JabyEngine {
|
|||
|
||||
typedef int16_t SimpleVolume;
|
||||
|
||||
struct __no_align SampleRate : public ComplexBitMap<uint16_t> {
|
||||
__io_port_inherit_complex_bit_map(SampleRate);
|
||||
|
||||
struct SampleRate : public ComplexBitMap<uint16_t> {
|
||||
static constexpr SampleRate from_HZ(double freq) {
|
||||
//4096 == 44100Hz
|
||||
constexpr double Base = (4096.0 / 44100.0);
|
||||
|
||||
return ComplexBitMap<uint16_t>{static_cast<uint16_t>((freq*Base))};
|
||||
return {static_cast<uint16_t>((freq*Base))};
|
||||
}
|
||||
};
|
||||
|
||||
struct __no_align SweepVolume : public ComplexBitMap<int16_t> {
|
||||
__io_port_inherit_complex_bit_map(SweepVolume);
|
||||
|
||||
struct SweepVolume : public ComplexBitMap<int16_t> {
|
||||
// For Volume Mode
|
||||
static constexpr auto SweepEnable = Bit<int16_t>(15);
|
||||
static constexpr auto VolumeEnable = !SweepEnable;
|
||||
|
@ -54,9 +50,7 @@ namespace JabyEngine {
|
|||
static constexpr auto SweepStep = BitRange<Step>::from_to(0, 1);
|
||||
};
|
||||
|
||||
struct __no_align SR : public ComplexBitMap<uint16_t> {
|
||||
__io_port_inherit_complex_bit_map(SR);
|
||||
|
||||
struct SR : public ComplexBitMap<uint16_t> {
|
||||
static constexpr auto SustainMode = Bit<Mode>(31 - 16);
|
||||
static constexpr auto SustainDirection = Bit<Direction>(30 - 16);
|
||||
static constexpr auto SustainShift = BitRange<Shift>::from_to((24 - 16), (28 - 16));
|
||||
|
@ -65,9 +59,7 @@ namespace JabyEngine {
|
|||
static constexpr auto ReleaseShift = BitRange<Shift>::from_to((16 - 16), (20 - 16));
|
||||
};
|
||||
|
||||
struct __no_align AD : public ComplexBitMap<uint16_t> {
|
||||
__io_port_inherit_complex_bit_map(AD);
|
||||
|
||||
struct AD : public ComplexBitMap<uint16_t> {
|
||||
static constexpr auto AttackMode = Bit<Mode>(15);
|
||||
static constexpr auto AttackShift = BitRange<Shift>::from_to(10, 14);
|
||||
static constexpr auto AttackStep = BitRange<Step>::from_to(8, 9);
|
||||
|
@ -76,19 +68,17 @@ namespace JabyEngine {
|
|||
};
|
||||
|
||||
struct __no_align Voice {
|
||||
IOPort<SweepVolume> volumeLeft; //Offset: 0x0
|
||||
IOPort<SweepVolume> volumeRight; //Offset: 0x2
|
||||
IOPort<SampleRate> sampleRate; //Offset: 0x4;
|
||||
IOPort<uint16_t> adr; //Offset: 0x6
|
||||
IOPort<AD> ad; //Offset: 0x8
|
||||
IOPort<SR> sr; //Offset: 0xA
|
||||
IOPort<SimpleVolume> currentVolume; //Offset: 0xC
|
||||
IOPort<uint16_t> repeatAdr; //Offset: 0xE
|
||||
IOPort<SweepVolume::UnderlyingType, SweepVolume> volumeLeft; //Offset: 0x0
|
||||
IOPort<SweepVolume::UnderlyingType, SweepVolume> volumeRight; //Offset: 0x2
|
||||
IOPort<SampleRate::UnderlyingType, SampleRate> sampleRate; //Offset: 0x4;
|
||||
IOPort<uint16_t, uint16_t> adr; //Offset: 0x6
|
||||
IOPort<AD::UnderlyingType, AD> ad; //Offset: 0x8
|
||||
IOPort<SR::UnderlyingType, SR> sr; //Offset: 0xA
|
||||
IOPort<SimpleVolume, SimpleVolume> currentVolume; //Offset: 0xC
|
||||
IOPort<uint16_t, uint16_t> repeatAdr; //Offset: 0xE
|
||||
};
|
||||
|
||||
struct __no_align ControlRegister : public ComplexBitMap<uint16_t> {
|
||||
__io_port_inherit_complex_bit_map(ControlRegister);
|
||||
|
||||
struct ControlRegister : public ComplexBitMap<uint16_t> {
|
||||
enum RAMTransferMode {
|
||||
Stop = 0,
|
||||
ManualWrite = 1,
|
||||
|
@ -109,30 +99,24 @@ namespace JabyEngine {
|
|||
static constexpr auto CDAudioEnable = Bit<uint16_t>(0);
|
||||
};
|
||||
|
||||
struct __no_align PitchModFlags : public ComplexBitMap<uint16_t> {
|
||||
__io_port_inherit_complex_bit_map(PitchModFlags);
|
||||
|
||||
struct PitchModFlags : public ComplexBitMap<uint16_t> {
|
||||
static constexpr BitRange<uint16_t> EnableBits = BitRange<uint16_t>::from_to(1, 23);
|
||||
};
|
||||
|
||||
struct __no_align NoiseGenerator : public ComplexBitMap<uint16_t> {
|
||||
__io_port_inherit_complex_bit_map(NoiseGenerator);
|
||||
|
||||
struct NoiseGenerator : public ComplexBitMap<uint16_t> {
|
||||
static constexpr BitRange<uint16_t> NoiseBits = BitRange<uint16_t>::from_to(0, 23);
|
||||
};
|
||||
|
||||
struct __no_align EchoOn : public ComplexBitMap<uint16_t> {
|
||||
__io_port_inherit_complex_bit_map(EchoOn);
|
||||
|
||||
struct EchoOn : public ComplexBitMap<uint16_t> {
|
||||
static constexpr BitRange<uint16_t> EchoBits = BitRange<uint16_t>::from_to(0, 23);
|
||||
};
|
||||
|
||||
static constexpr size_t VoiceCount = 24;
|
||||
|
||||
struct Key {
|
||||
__declare_io_port_member(ubus32_t, On, 0x1F801D88);
|
||||
__declare_io_port_member(ubus32_t, Off, 0x1F801D8C);
|
||||
__declare_io_port_member(ubus32_t, Status, 0x1F801D9C);
|
||||
__declare_global_raw(inline, ubus32_t, On, 0x1F801D88);
|
||||
__declare_global_raw(inline, ubus32_t, Off, 0x1F801D8C);
|
||||
__declare_global_raw(inline, ubus32_t, Status, 0x1F801D9C);
|
||||
};
|
||||
|
||||
struct MainVolume {
|
||||
|
@ -141,28 +125,28 @@ namespace JabyEngine {
|
|||
};
|
||||
|
||||
struct CDVolume {
|
||||
__declare_io_port_member(SimpleVolume, Left, 0x1F801DB0);
|
||||
__declare_io_port_member(SimpleVolume, Right, 0x1F801DB2);
|
||||
__declare_io_port_member_simple(SimpleVolume, Left, 0x1F801DB0);
|
||||
__declare_io_port_member_simple(SimpleVolume, Right, 0x1F801DB2);
|
||||
};
|
||||
|
||||
struct ExternalAudioInputVolume {
|
||||
__declare_io_port_member(SimpleVolume, Left, 0x1F801DB4);
|
||||
__declare_io_port_member(SimpleVolume, Right, 0x1F801DB6);
|
||||
__declare_io_port_member_simple(SimpleVolume, Left, 0x1F801DB4);
|
||||
__declare_io_port_member_simple(SimpleVolume, Right, 0x1F801DB6);
|
||||
};
|
||||
|
||||
struct Reverb {
|
||||
struct Volume {
|
||||
__declare_io_port_member(SimpleVolume, Left, 0x1F801D84);
|
||||
__declare_io_port_member(SimpleVolume, Right, 0x1F801D86);
|
||||
__declare_io_port_member_simple(SimpleVolume, Left, 0x1F801D84);
|
||||
__declare_io_port_member_simple(SimpleVolume, Right, 0x1F801D86);
|
||||
};
|
||||
__declare_io_port_member(uint16_t, WorkAreaAdr, 0x1F801DA2);
|
||||
__declare_io_port_member_simple(uint16_t, WorkAreaAdr, 0x1F801DA2);
|
||||
};
|
||||
|
||||
__declare_io_port_global(ControlRegister, Control, 0x1F801DAA);
|
||||
__declare_io_port_global(uint16_t, DataTransferControl, 0x1F801DAC);
|
||||
__declare_io_port_global(PitchModFlags, PMON, 0x1F801D90);
|
||||
__declare_io_port_global(NoiseGenerator, NON, 0x1F801D94);
|
||||
__declare_io_port_global(EchoOn, EON, 0x1F801D98);
|
||||
__declare_io_port_global(ControlRegister, Control, 0x1F801DAA);
|
||||
__declare_io_port_global_simple(uint16_t, DataTransferControl, 0x1F801DAC);
|
||||
__declare_io_port_global(PitchModFlags, PMON, 0x1F801D90);
|
||||
__declare_io_port_global(NoiseGenerator, NON, 0x1F801D94);
|
||||
__declare_io_port_global(EchoOn, EON, 0x1F801D98);
|
||||
|
||||
__declare_io_port_global_array(struct Voice, Voice, 0x1F801C00, VoiceCount);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
namespace JabyEngine {
|
||||
namespace Timer_IO {
|
||||
struct __no_align CounterMode : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(CounterMode);
|
||||
|
||||
struct CounterMode : public ComplexBitMap<uint32_t> {
|
||||
static constexpr auto SyncEnable = Bit<uint32_t>(0);
|
||||
static constexpr auto FreeRun = !SyncEnable;
|
||||
static constexpr auto SyncMode = BitRange<uint32_t>::from_to(1, 2);
|
||||
|
@ -23,22 +21,18 @@ namespace JabyEngine {
|
|||
static constexpr auto IsMaxReached = Bit<uint32_t>(12);
|
||||
};
|
||||
|
||||
struct __no_align CounterTarget : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(CounterTarget);
|
||||
|
||||
struct CounterTarget : public ComplexBitMap<uint32_t> {
|
||||
static constexpr auto CounterTargetValue = BitRange<uint32_t>::from_to(0, 15);
|
||||
};
|
||||
|
||||
struct __no_align CounterValue : public ComplexBitMap<uint32_t> {
|
||||
__io_port_inherit_complex_bit_map(CounterValue);
|
||||
|
||||
struct CounterValue : public ComplexBitMap<uint32_t> {
|
||||
static constexpr auto Value = BitRange<uint32_t>::from_to(0, 15);
|
||||
};
|
||||
|
||||
struct __no_align Counter {
|
||||
IOPort<CounterValue> value;
|
||||
IOPort<CounterMode> mode;
|
||||
IOPort<CounterTarget> target;
|
||||
IOPort<CounterValue::UnderlyingType, CounterValue> value;
|
||||
IOPort<CounterMode::UnderlyingType, CounterMode> mode;
|
||||
IOPort<CounterTarget::UnderlyingType, CounterTarget> target;
|
||||
private:
|
||||
uint32_t _unused;
|
||||
};
|
||||
|
|
|
@ -66,10 +66,9 @@ namespace JabyEngine {
|
|||
~HighResTime() = delete;
|
||||
|
||||
static TimeStamp get_time_stamp() {
|
||||
return TimeStamp(HighResTime::global_counter_10ms, Timer_IO::Counter2.value.read(Timer_IO::CounterValue::Value));
|
||||
return TimeStamp(HighResTime::global_counter_10ms, Timer_IO::Counter2.value.read_range_value(Timer_IO::CounterValue::Value));
|
||||
}
|
||||
};
|
||||
#endif //JABYENGINE_USE_HIGH_PERCISION_TIMER
|
||||
}
|
||||
|
||||
#endif //!__JABYENGINE_HIGH_RES_TIMER_HPP__
|
|
@ -8,6 +8,7 @@
|
|||
#define __no_inline __attribute__((noinline))
|
||||
#define __always_inline __attribute__((always_inline))
|
||||
#define __section(name) __attribute__((section(name)))
|
||||
#define __collect(...) __VA_ARGS__
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define __constexpr constexpr
|
||||
|
|
|
@ -95,7 +95,7 @@ namespace JabyEngine {
|
|||
}
|
||||
|
||||
static void set_src(uintptr_t adr) {
|
||||
DMA_IO::GPU.adr.write(DMA_IO::MADR::MemoryAdr.with(static_cast<uint32_t>(adr)));
|
||||
DMA_IO::GPU.adr.write_range_value(DMA_IO::MADR::MemoryAdr.with(static_cast<uint32_t>(adr)));
|
||||
}
|
||||
|
||||
static void set_dst(const PositionU16& position, const SizeU16& size) {
|
||||
|
@ -108,7 +108,7 @@ namespace JabyEngine {
|
|||
static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) {
|
||||
typedef DMA_IO::BCR::SyncMode1 SyncMode1;
|
||||
|
||||
DMA_IO::GPU.block_ctrl.write(SyncMode1::with(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount)));
|
||||
DMA_IO::GPU.block_ctrl.write(DMA_IO::BCR{SyncMode1::with(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount))});
|
||||
DMA_IO::GPU.channel_ctrl.write(DMA_IO::CHCHR::StartGPUReceive());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ namespace JabyEngine {
|
|||
static void clear_main_volume() {
|
||||
static constexpr auto StartVol = SPU_IO::SweepVolume::with(SPU_IO::SweepVolume::VolumeEnable, SPU_IO::SweepVolume::Volume.with(I16_MAX >> 2));
|
||||
|
||||
SPU_IO::MainVolume::Left.write(StartVol);
|
||||
SPU_IO::MainVolume::Right.write(StartVol);
|
||||
SPU_IO::MainVolume::Left.write({StartVol});
|
||||
SPU_IO::MainVolume::Right.write({StartVol});
|
||||
}
|
||||
|
||||
static void clear_cd_and_ext_audio_volume() {
|
||||
|
@ -58,7 +58,7 @@ namespace JabyEngine {
|
|||
static void setup_control_register() {
|
||||
static constexpr auto SetupValue = SPU_IO::ControlRegister::with(SPU_IO::ControlRegister::Enable, SPU_IO::ControlRegister::Unmute, SPU_IO::ControlRegister::CDAudioEnable);
|
||||
|
||||
SPU_IO::Control.write(SetupValue);
|
||||
SPU_IO::Control.write({SetupValue});
|
||||
}
|
||||
|
||||
static void setup_data_transfer_control() {
|
||||
|
@ -79,7 +79,7 @@ namespace JabyEngine {
|
|||
}
|
||||
|
||||
void stop_voices() {
|
||||
SPU_IO::Key::Off.write(UI32_MAX);
|
||||
SPU_IO::Key::Off.write({UI32_MAX});
|
||||
}
|
||||
|
||||
void setup() {
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace JabyEngine {
|
|||
namespace boot {
|
||||
namespace Start {
|
||||
static void enable_DMA() {
|
||||
DMA_IO::DPCR.write(DMA_IO::DPCR.read() | DMA_IO::DMAControlRegister::SPUEnable | DMA_IO::DMAControlRegister::GPUEnable);
|
||||
DMA_IO::DPCR.write(DMA_IO::DMAControlRegister{DMA_IO::DPCR.read() | DMA_IO::DMAControlRegister::SPUEnable | DMA_IO::DMAControlRegister::GPUEnable});
|
||||
}
|
||||
|
||||
JabyEngine::NextRoutine setup() {
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
__syscall_SysEnqIntRP(Timer2Irq, &IRQCallback);
|
||||
__syscall_ExitCriticalSection();
|
||||
|
||||
Counter2.target.write(CounterTarget::CounterTargetValue.with(HighResTime::TicksFor10ms));
|
||||
Counter2.mode.write(Mode);
|
||||
Counter2.target.write_range_value(CounterTarget::CounterTargetValue.with(HighResTime::TicksFor10ms));
|
||||
Counter2.mode.write({Mode});
|
||||
|
||||
Interrupt::enable_irq(Interrupt::Timer2);
|
||||
}
|
||||
|
|
|
@ -1,49 +1,8 @@
|
|||
#include "../../include/CD/cd_internal.hpp"
|
||||
#include <PSX/Auxiliary/complex_bitmap.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace CD {
|
||||
template<typename T, typename S = T>
|
||||
class IOPortX {
|
||||
private:
|
||||
volatile T value;
|
||||
|
||||
public:
|
||||
constexpr T read_raw() const {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
constexpr S read() const {
|
||||
return S{this->value};
|
||||
}
|
||||
|
||||
constexpr void write_raw(T value) {
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
constexpr void write(const S& value) {
|
||||
this->value = static_cast<T>(value);
|
||||
}
|
||||
};
|
||||
|
||||
struct __no_align Wuff : public ComplexBitMap<uint32_t> {
|
||||
static constexpr auto Miau = Bit<uint32_t>(0);
|
||||
static constexpr auto Blubb = BitRange<uint32_t>::from_to(0, 5);
|
||||
};
|
||||
|
||||
static __always_inline auto& Wuff = *reinterpret_cast<IOPortX<uint32_t, struct Wuff>*>(0x1F80000);
|
||||
|
||||
static uint32_t read(const IOPortX<uint32_t, struct Wuff>& port) {
|
||||
return port.read().get_value(Wuff::Blubb);
|
||||
}
|
||||
|
||||
|
||||
namespace internal {
|
||||
void setup() {
|
||||
while(Wuff.read().is_bit_set(Wuff::Miau));
|
||||
|
||||
Wuff.write({Wuff::with(Wuff::Miau)});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue