#pragma once #include "ioport.hpp" namespace JabyEngine { namespace DMA_IO { __declare_io_value(MADR, uint32_t) { static constexpr auto MemoryAdr = BitRange::from_to(0, 23); }; __declare_io_value(BCR, uint32_t) { struct SyncMode0 { static constexpr auto NumberOfWords = BitRange::from_to(0, 15); static constexpr auto CD_OneBlock = Bit(16); static constexpr BCR for_cd(size_t words) { return BCR::from(SyncMode0::CD_OneBlock, SyncMode0::NumberOfWords.with(words)); } }; struct SyncMode1 { static constexpr auto BlockSize = BitRange::from_to(0, 15); static constexpr auto BlockAmount = BitRange::from_to(16, 31); }; struct SyncMode2 { static constexpr BCR for_gpu_cmd() { return {0}; } }; }; __declare_io_value(CHCHR, uint32_t) { enum SyncMode_t { Sync0 = 0, //Start immediately, Sync1 = 1, //Sync blocks to DMA requests Sync2 = 2, //Linked List }; static constexpr auto ManualStart = Bit(28); static constexpr auto Start = Bit(24); static constexpr auto Busy = Start; static constexpr auto ChoppingCPUWindowSize = BitRange::from_to(20, 22); static constexpr auto ChoppingDMAWindowSize = BitRange::from_to(16, 18); static constexpr auto SyncMode = BitRange::from_to(9, 10); static constexpr auto UseSyncMode0 = SyncMode.with(Sync0); static constexpr auto UseSyncMode1 = SyncMode.with(Sync1); static constexpr auto UseSyncMode2 = SyncMode.with(Sync2); static constexpr auto UseChopping = Bit(8); static constexpr auto MemoryAdrDecreaseBy4 = Bit(1); static constexpr auto MemoryAdrIncreaseBy4 = !MemoryAdrDecreaseBy4; static constexpr auto FromMainRAM = Bit(0); static constexpr auto ToMainRAM = !FromMainRAM; static constexpr CHCHR StartMDECin() { return CHCHR{0x01000201}; } static constexpr CHCHR StartMDECout() { return CHCHR{0x01000200}; } static constexpr CHCHR StartGPUReceive() { return CHCHR{0x01000201}; } static constexpr CHCHR StartGPULinked() { return CHCHR{0x01000401}; } static constexpr CHCHR StartCDROM() { return CHCHR{0x11000000}; } static constexpr CHCHR StartSPUReceive() { return CHCHR{0x01000201}; } static constexpr CHCHR StartOTC() { return CHCHR{0x11000002}; } }; #pragma pack(push, 1) struct Registers { IOPort adr; IOPort block_ctrl; IOPort channel_ctrl; inline void set_adr(uintptr_t adr) { this->adr.write({bit::value::set_normalized(0u, MADR::MemoryAdr.with(adr))}); } inline void wait() { while(this->channel_ctrl.read().is_set(CHCHR::Busy)); } }; #pragma pack(pop) //0: Highest, 7: Lowest typedef uint32_t Priority; static constexpr Priority HighestPriority = 0; static constexpr Priority LowestPriority = 7; __declare_io_value(DPCR, uint32_t) { struct DMASetting { uint16_t master_bit; static constexpr DMASetting create(uint16_t master_bit) { return DMASetting{master_bit}; } constexpr BitRange::RangeValuePair turn_on(uint8_t priority) const { return BitRange::from_to(this->master_bit - 3, this->master_bit).with(static_cast(0b1000 + (priority & 0b111))); } constexpr ClearBit turn_off() const { return ClearBit(this->master_bit); } }; static constexpr const auto OTC = DMASetting(27); static constexpr const auto PIO = DMASetting(23); static constexpr const auto SPU = DMASetting(19); static constexpr const auto CDROM = DMASetting(15); static constexpr const auto GPU = DMASetting(11); static constexpr const auto MDEC_Out = DMASetting(7); static constexpr const auto MDEC_In = DMASetting(3); static constexpr auto OTCEnabled = Bit(27); static constexpr auto OTCPriority = BitRange::from_to(24, 26); static constexpr auto PIOEnabled = Bit(23); static constexpr auto PIOPriority = BitRange::from_to(20, 22); static constexpr auto SPUEnabled = Bit(19); static constexpr auto SPUPriority = BitRange::from_to(16, 18); static constexpr auto CDROMEnabled = Bit(15); static constexpr auto CDROMPriority = BitRange::from_to(12, 14); static constexpr auto GPUEnabled = Bit(11); static constexpr auto GPUPriority = BitRange::from_to(8, 10); static constexpr auto MDECoutEnabled = Bit(7); static constexpr auto MDECoutPriority = BitRange::from_to(4, 6); static constexpr auto MDECinEnabled = Bit(3); static constexpr auto MDECinPriority = BitRange::from_to(0, 2); }; __declare_io_value(DICR, uint32_t) { static constexpr auto MasterEnable = Bit(31); static constexpr auto Flags = BitRange::from_to(24, 30); static constexpr auto MasterEnableDPCR = Bit(23); static constexpr auto EnableDPCR = BitRange::from_to(16, 22); static constexpr auto ForceIRQ = Bit(15); static constexpr DICR empty() { return DICR{0}; } }; __declare_value_at(, Registers, MDECin, 0x1F801080); __declare_value_at(, Registers, MDECout, 0x1F801090); __declare_value_at(, Registers, GPU, 0x1F8010A0); __declare_value_at(, Registers, CDROM, 0x1F8010B0); __declare_value_at(, Registers, SPU, 0x1F8010C0); __declare_value_at(, Registers, PIO, 0x1F8010D0); __declare_value_at(, Registers, OTC, 0x1F8010E0); __declare_io_port(, DPCR, 0x1F8010F0); __declare_io_port(, DICR, 0x1F8010F4); } }