#pragma once #include "IOValues/cd_io_values.hpp" namespace JabyEngine { namespace CD_IO { using AudioVolumeApply_IO = IOPort; using CommandFifo_IO = IOPort; using DataFifo_IO = IOPort; using DataFifo16_IO = IOPort; using IndexStatus_IO = IOPort; using InterruptEnable_IO = IOPort; using InterruptFlag_IO = IOPort; using LeftCD2LeftSPU_IO = IOPort; using LeftCD2RightSPU_IO = IOPort; using ParameterFifo_IO = IOPort; using Request_IO = IOPort; using ResponseFifo_IO = IOPort; using RightCD2LeftSPU_IO = IOPort; using RightCD2RightSPU_IO = IOPort; using SoundMapDataOut_IO = IOPort; using SoundMapCoding_IO = IOPort; struct DataSector { static constexpr size_t SizeBytes = 2048; static constexpr size_t SizeWords = (SizeBytes/sizeof(uint32_t)); uint32_t data[SizeWords]; template static constexpr T words_to_sectors(T size) { return (size + static_cast(DataSector::SizeWords - 1))/static_cast(DataSector::SizeWords); } constexpr size_t hash() const { uint32_t value = 0; for(const auto word : this->data) { value += word; } return value; } }; enum Index { Index0 = 0, Index1 = 1, Index2 = 2, Index3 = 3, }; struct Interrupt { static constexpr auto ExtendedFlags = CD_IO_Values::InterruptEnable::from( CD_IO_Values::InterruptEnable::InterruptTypValue.range_max(), CD_IO_Values::InterruptEnable::UnknownIRQ, CD_IO_Values::InterruptEnable::CommandStartIRQ ); enum Type : uint8_t { None = 0, DataReady = 1, Complete = 2, Acknowledge = 3, DataEnd = 4, DiskError = 5 }; static void enable(InterruptEnable_IO& port) { port.write(port.read().set(CD_IO_Values::InterruptEnable::InterruptTypValue.range_max())); } static void enable_extended(InterruptEnable_IO& port) { port.write(Interrupt::ExtendedFlags); } static Type get_type(const InterruptFlag_IO& port) { return static_cast(port.read().get(CD_IO_Values::InterruptFlag::InterruptTypValue)); } static void ack(InterruptFlag_IO& port) { port.write(port.read().set(CD_IO_Values::InterruptFlag::InterruptTypValue.range_max())); } static void ack_extended(InterruptFlag_IO& port) { port.write(Interrupt::ExtendedFlags); } static void reset_parameter_fifo(InterruptFlag_IO& port) { port.write(CD_IO_Values::InterruptFlag{0x40}); } }; struct Command { struct Desc { uint8_t id; Interrupt::Type complete_irq; }; static constexpr Desc GetStat{0x01, Interrupt::Type::Acknowledge}; static constexpr Desc SetLoc{0x02, Interrupt::Type::Acknowledge}; static constexpr Desc Play{0x03, Interrupt::Type::Acknowledge}; static constexpr Desc ReadN{0x06, Interrupt::Type::DataReady}; static constexpr Desc Pause{0x09, Interrupt::Type::Complete}; static constexpr Desc Init{0x0A, Interrupt::Type::Complete}; static constexpr Desc Demute{0x0C, Interrupt::Type::Acknowledge}; static constexpr Desc Filter{0x0D, Interrupt::Type::Acknowledge}; static constexpr Desc SetMode{0x0E, Interrupt::Type::Acknowledge}; static constexpr Desc GetLocL{0x10, Interrupt::Type::Acknowledge}; static constexpr Desc GetLocP{0x11, Interrupt::Type::Acknowledge}; static constexpr Desc GetTN{0x13, Interrupt::Type::Acknowledge}; static constexpr Desc GetTD{0x14, Interrupt::Type::Acknowledge}; static constexpr Desc SeekL{0x15, Interrupt::Type::Complete}; static constexpr Desc ReadS{0x1B, Interrupt::Type::DataReady}; }; static constexpr auto IORegister1Adr = 0x1F801801; static constexpr auto IORegister2Adr = 0x1F801802; static constexpr auto IORegister3Adr = 0x1F801803; static auto& IndexStatus = __declare_io_port(IndexStatus_IO, 0x1F801800); struct PortIndex0 { static inline const auto& ResponseFifo = __declare_io_port(ResponseFifo_IO, IORegister1Adr); static inline auto& CommandFifo = __declare_io_port(CommandFifo_IO, IORegister1Adr); static inline const auto& DataFifo = __declare_io_port(DataFifo_IO, IORegister2Adr); static inline const auto& DataFifo16 = __declare_io_port(DataFifo16_IO, IORegister2Adr); static inline auto& ParameterFifo = __declare_io_port(ParameterFifo_IO, IORegister2Adr); static inline const auto& InterruptEnable = __declare_io_port(InterruptEnable_IO, IORegister3Adr); static inline auto& Request = __declare_io_port(Request_IO, IORegister3Adr); static void change_to() { IndexStatus.write({Index::Index0}); } }; struct PortIndex1 { static inline const auto& ResponseFifo = __declare_io_port(ResponseFifo_IO, IORegister1Adr); static inline auto& SoundMapDataOut = __declare_io_port(SoundMapDataOut_IO, IORegister1Adr); static inline const auto& DataFifo = __declare_io_port(DataFifo_IO, IORegister2Adr); static inline const auto& DataFifo16 = __declare_io_port(DataFifo16_IO, IORegister2Adr); static inline auto& InterruptEnable = __declare_io_port(InterruptEnable_IO, IORegister2Adr); static inline auto& InterruptFlag = __declare_io_port(InterruptFlag_IO, IORegister3Adr); static void change_to() { IndexStatus.write({Index::Index1}); } }; struct PortIndex2 { static inline const auto& ResponseFifo = __declare_io_port(ResponseFifo_IO, IORegister1Adr); static inline auto& SoundMapCoding = __declare_io_port(SoundMapCoding_IO, IORegister1Adr); static inline const auto& DataFifo = __declare_io_port(DataFifo_IO, IORegister2Adr); static inline const auto& DataFifo16 = __declare_io_port(DataFifo16_IO, IORegister2Adr); static inline auto& LeftCD2LeftSPU = __declare_io_port(LeftCD2LeftSPU_IO, IORegister2Adr); static inline const auto& InterruptEnable = __declare_io_port(InterruptEnable_IO, IORegister3Adr); static inline auto& LeftCD2RightSPU = __declare_io_port(LeftCD2RightSPU_IO, IORegister3Adr); static void change_to() { IndexStatus.write({Index::Index2}); } }; struct PortIndex3 { static inline const auto& ResponseFifo = __declare_io_port(ResponseFifo_IO, IORegister1Adr); static inline auto& RightCD2RightSPU = __declare_io_port(RightCD2RightSPU_IO, IORegister1Adr); static inline const auto& DataFifo = __declare_io_port(DataFifo_IO, IORegister2Adr); static inline const auto& DataFifo16 = __declare_io_port(DataFifo16_IO, IORegister2Adr); static inline auto& RightCD2LeftSPU = __declare_io_port(RightCD2LeftSPU_IO, IORegister1Adr); static inline const auto& InterruptFlag = __declare_io_port(InterruptFlag_IO, IORegister3Adr); static inline auto& AudioVolumeApply = __declare_io_port(AudioVolumeApply_IO, IORegister3Adr); static void change_to() { IndexStatus.write({Index::Index3}); } }; } }