#ifndef __JABYENGINE_CD_IO_HPP__ #define __JABYENGINE_CD_IO_HPP__ #include "ioport.hpp" namespace JabyEngine { namespace CD_IO { 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); } }; enum Index { Index0 = 0, Index1 = 1, Index2 = 2, Index3 = 3, }; struct CDDAVolume { typedef uint8_t Type; static constexpr uint8_t Off = 0x0; static constexpr uint8_t Default = 0x80; static constexpr uint8_t Max = 0xFF; }; __declare_io_type(IndexStatus, uint8_t, static constexpr auto PortIndex = BitRange::from_to(0, 1); static constexpr auto HasXAFifoData = Bit(2); static constexpr auto IsParameterFifoEmpty = Bit(3); static constexpr auto HasParameterFifoSpace = Bit(4); static constexpr auto HasResponseFifoData = Bit(5); static constexpr auto HasDataFifoData = Bit(6); static constexpr auto IsTransmissionBusy = Bit(7); ); __declare_io_type(InterruptEnable, uint8_t, static constexpr auto InterruptTypValue = BitRange::from_to(0, 2); static constexpr auto InterruptExtended = BitRange::from_to(0, 4); static constexpr auto UnknownIRQ = Bit(3); static constexpr auto CommandStartIRQ = Bit(4); ); typedef InterruptEnable_v InterruptFlag_v; __declare_io_type(Request, uint8_t, static constexpr auto WantCommandStartIRQ = Bit(5); static constexpr auto WantData = Bit(7); ); __declare_io_type(SoundMapCoding, uint8_t, static constexpr auto Stereo = Bit(0); static constexpr auto Mono = !Stereo; static constexpr auto SampleRate_18900hz = Bit(2); static constexpr auto SampleRate_37800hz = !SampleRate_18900hz; static constexpr auto BitsPerSample8 = Bit(4); static constexpr auto BitsPerSample4 = !BitsPerSample8; static constexpr auto Emphasis = Bit(6); ); __declare_io_type(AudioVolumeApply, uint8_t, static constexpr auto Mute = Bit(0); static constexpr auto ApplyChanges = Bit(5); ); __declare_io_type(ResponseFifo, uint8_t,); __declare_io_type(CommandFifo, uint8_t,); __declare_io_type(DataFifo, uint8_t,); __declare_io_type(DataFifo16, uint16_t,); __declare_io_type(ParameterFifo, uint8_t,); __declare_io_type(SoundMapDataOut, uint8_t,); __declare_io_type(LeftCD2LeftSPU, CDDAVolume::Type,); __declare_io_type(LeftCD2RightSPU, CDDAVolume::Type,); __declare_io_type(RightCD2RightSPU,CDDAVolume::Type,); __declare_io_type(RightCD2LeftSPU, CDDAVolume::Type,); struct Interrupt { enum Type : uint8_t { None = 0, DataReady = 1, Complete = 2, Acknowledge = 3, DataEnd = 4, DiskError = 5 }; static void enable(InterruptEnable_v& port) { port.set(InterruptEnable_t::InterruptTypValue.range_max()); } static void enable_extended(InterruptEnable_v& port) { port = InterruptEnable_t::from(InterruptEnable_t::InterruptTypValue.range_max(), InterruptEnable_t::UnknownIRQ, InterruptEnable_t::CommandStartIRQ); } static Type get_type(const InterruptFlag_v& port) { return static_cast(port.get(InterruptFlag_v::InterruptTypValue)); } static void ack(InterruptFlag_v& port) { port.set(InterruptFlag_v::InterruptTypValue.range_max()); } static void ack_extended(InterruptFlag_v& port) { port = InterruptFlag_v::from(InterruptFlag_v::InterruptTypValue.range_max(), InterruptEnable_v::UnknownIRQ, InterruptEnable_v::CommandStartIRQ); } }; 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 ReadN{0x06, Interrupt::Type::DataReady}; static constexpr Desc Pause{0x09, Interrupt::Type::Complete}; static constexpr Desc Init{0x0A, Interrupt::Type::Complete}; static constexpr Desc SetMode{0x0E, Interrupt::Type::Acknowledge}; }; static constexpr auto IORegister1Adr = 0x1F801801; static constexpr auto IORegister2Adr = 0x1F801802; static constexpr auto IORegister3Adr = 0x1F801803; __declare_new_io_port(IndexStatus, 0x1F801800); #define __declare_index_io_port(type, name, adr) __cast_io_adr_with_type(inline, type, name, adr) #define __declare_index_io_port_const(type, name, adr) __cast_io_adr_with_type(const inline, type, name, adr) struct PortIndex0 { __declare_new_const_io_port(ResponseFifo, IORegister1Adr); __declare_new_io_port(CommandFifo, IORegister1Adr); __declare_new_const_io_port(DataFifo, IORegister2Adr); __declare_new_const_io_port(DataFifo16, IORegister2Adr); __declare_new_io_port(ParameterFifo, IORegister2Adr); __declare_new_const_io_port(InterruptEnable, IORegister3Adr); __declare_new_io_port(Request, IORegister3Adr); static void change_to() { IndexStatus = Index::Index0; } }; struct PortIndex1 { __declare_new_const_io_port(ResponseFifo, IORegister1Adr); __declare_new_io_port(SoundMapDataOut, IORegister1Adr); __declare_new_const_io_port(DataFifo, IORegister2Adr); __declare_new_const_io_port(DataFifo16, IORegister2Adr); __declare_new_io_port(InterruptEnable, IORegister2Adr); __declare_new_io_port(InterruptFlag, IORegister3Adr); static void change_to() { IndexStatus = Index::Index1; } }; struct PortIndex2 { __declare_new_const_io_port(ResponseFifo, IORegister1Adr); __declare_new_io_port(SoundMapCoding, IORegister1Adr); __declare_new_const_io_port(DataFifo, IORegister2Adr); __declare_new_const_io_port(DataFifo16, IORegister2Adr); __declare_new_io_port(LeftCD2LeftSPU, IORegister2Adr); __declare_new_const_io_port(InterruptEnable, IORegister3Adr); __declare_new_io_port(LeftCD2RightSPU, IORegister3Adr); static void change_to() { IndexStatus = Index::Index2; } }; struct PortIndex3 { __declare_new_const_io_port(ResponseFifo, IORegister1Adr); __declare_new_io_port(RightCD2RightSPU, IORegister1Adr); __declare_new_const_io_port(DataFifo, IORegister2Adr); __declare_new_const_io_port(DataFifo16, IORegister2Adr); __declare_new_io_port(RightCD2LeftSPU, IORegister1Adr); __declare_new_const_io_port(InterruptFlag, IORegister3Adr); __declare_new_io_port(AudioVolumeApply, IORegister3Adr); static void change_to() { IndexStatus = Index::Index3; } }; #undef __declare_index_io_port #undef __declare_index_io_port_const } } #endif //!__JABYENGINE_CD_IO_HPP__