jabyengine/include/PSX/System/IOPorts/cd_io.hpp

213 lines
8.4 KiB
C++

#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<typename T>
static constexpr T words_to_sectors(T size) {
return (size + static_cast<T>(DataSector::SizeWords - 1))/static_cast<T>(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);
void want_data() {
this->raw_value = static_cast<uint8_t>(Self::WantData);
}
void reset() {
this->raw_value = 0;
}
);
__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<uint8_t>());
}
static void enable_extended(InterruptEnable_v& port) {
port = InterruptEnable_t::from(InterruptEnable_t::InterruptTypValue.range_max<uint8_t>(), InterruptEnable_t::UnknownIRQ, InterruptEnable_t::CommandStartIRQ);
}
static Type get_type(const InterruptFlag_v& port) {
return static_cast<Type>(port.get(InterruptFlag_v::InterruptTypValue));
}
static void ack(InterruptFlag_v& port) {
port.set(InterruptFlag_v::InterruptTypValue.range_max<uint8_t>());
}
static void ack_extended(InterruptFlag_v& port) {
port = InterruptFlag_v::from(InterruptFlag_v::InterruptTypValue.range_max<uint8_t>(), 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__