Convert CD IO

This commit is contained in:
jaby 2024-09-29 17:10:41 +02:00
parent 60dec20a71
commit 8fcfa1e1fe
4 changed files with 180 additions and 146 deletions

View File

@ -0,0 +1,106 @@
#pragma once
#include "../ioport.hpp"
namespace JabyEngine {
namespace CD_IO_Values {
__declare_io_value(AudioVolumeApply, uint8_t) {
static constexpr auto Mute = Bit(0);
static constexpr auto ApplyChanges = Bit(5);
};
struct CDDAVolume {
using Type = uint8_t;
static constexpr uint8_t Off = 0x0;
static constexpr uint8_t Default = 0x80;
static constexpr uint8_t Max = 0xFF;
};
__declare_io_value(CommandFifo, uint8_t) {
};
__declare_io_value(DataFifo, uint8_t) {
};
__declare_io_value(DataFifo16, uint16_t) {
};
__declare_io_value(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);
};
using InterruptFlag = InterruptEnable;
__declare_io_value(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_value(LeftCD2LeftSPU, CDDAVolume::Type) {
};
__declare_io_value(LeftCD2RightSPU, CDDAVolume::Type) {
};
__declare_io_value(Mode, uint8_t) {
static constexpr auto DoubleSpeed = Bit(7);
static constexpr auto SingleSpeed = !DoubleSpeed;
static constexpr auto XADPCM = Bit(6);
static constexpr auto WholeSector = Bit(5);
static constexpr auto DataSector = !WholeSector;
static constexpr auto UseXAFilter = Bit(3);
static constexpr auto AudioPlayIRQ = Bit(2);
static constexpr auto AutoPauseTrack = Bit(1);
static constexpr auto CDDA = Bit(0);
operator uint8_t() const {
return this->raw;
}
};
__declare_io_value(ParameterFifo, uint8_t) {
};
__declare_io_value(Request, uint8_t) {
static constexpr auto WantCommandStartIRQ = Bit(5);
static constexpr auto WantData = Bit(7);
static Request want_data() {
return Request{static_cast<uint8_t>(Request::WantData)};
}
static Request reset() {
return Request{0};
}
};
__declare_io_value(ResponseFifo, uint8_t) {
};
__declare_io_value(RightCD2LeftSPU, CDDAVolume::Type) {
};
__declare_io_value(RightCD2RightSPU, CDDAVolume::Type) {
};
__declare_io_value(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_value(SoundMapDataOut, uint8_t) {
};
}
}

View File

@ -1,8 +1,25 @@
#pragma once #pragma once
#include "ioport.hpp" #include "IOValues/cd_io_values.hpp"
namespace JabyEngine { namespace JabyEngine {
namespace CD_IO { namespace CD_IO {
using AudioVolumeApply_IO = IOPort<CD_IO_Values::AudioVolumeApply>;
using CommandFifo_IO = IOPort<CD_IO_Values::CommandFifo>;
using DataFifo_IO = IOPort<CD_IO_Values::DataFifo>;
using DataFifo16_IO = IOPort<CD_IO_Values::DataFifo16>;
using IndexStatus_IO = IOPort<CD_IO_Values::IndexStatus>;
using InterruptEnable_IO = IOPort<CD_IO_Values::InterruptEnable>;
using InterruptFlag_IO = IOPort<CD_IO_Values::InterruptFlag>;
using LeftCD2LeftSPU_IO = IOPort<CD_IO_Values::LeftCD2LeftSPU>;
using LeftCD2RightSPU_IO = IOPort<CD_IO_Values::LeftCD2RightSPU>;
using ParameterFifo_IO = IOPort<CD_IO_Values::ParameterFifo>;
using Request_IO = IOPort<CD_IO_Values::Request>;
using ResponseFifo_IO = IOPort<CD_IO_Values::ResponseFifo>;
using RightCD2LeftSPU_IO = IOPort<CD_IO_Values::RightCD2LeftSPU>;
using RightCD2RightSPU_IO = IOPort<CD_IO_Values::RightCD2RightSPU>;
using SoundMapDataOut_IO = IOPort<CD_IO_Values::SoundMapDataOut>;
using SoundMapCoding_IO = IOPort<CD_IO_Values::SoundMapCoding>;
struct DataSector { struct DataSector {
static constexpr size_t SizeBytes = 2048; static constexpr size_t SizeBytes = 2048;
static constexpr size_t SizeWords = (SizeBytes/sizeof(uint32_t)); static constexpr size_t SizeWords = (SizeBytes/sizeof(uint32_t));
@ -31,99 +48,13 @@ namespace JabyEngine {
Index3 = 3, 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_value(Mode, uint8_t) {
static constexpr auto DoubleSpeed = Bit(7);
static constexpr auto SingleSpeed = !DoubleSpeed;
static constexpr auto XADPCM = Bit(6);
static constexpr auto WholeSector = Bit(5);
static constexpr auto DataSector = !WholeSector;
static constexpr auto UseXAFilter = Bit(3);
static constexpr auto AudioPlayIRQ = Bit(2);
static constexpr auto AutoPauseTrack = Bit(1);
static constexpr auto CDDA = Bit(0);
operator uint8_t() const {
return this->raw;
}
};
__declare_io_value(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_value(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 InterruptFlag;
__declare_io_value(Request, uint8_t) {
static constexpr auto WantCommandStartIRQ = Bit(5);
static constexpr auto WantData = Bit(7);
static Request want_data() {
return Request{static_cast<uint8_t>(Request::WantData)};
}
static Request reset() {
return Request{0};
}
};
__declare_io_value(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_value(AudioVolumeApply, uint8_t) {
static constexpr auto Mute = Bit(0);
static constexpr auto ApplyChanges = Bit(5);
};
__declare_io_value(ResponseFifo, uint8_t) {
};
__declare_io_value(CommandFifo, uint8_t) {
};
__declare_io_value(DataFifo, uint8_t) {
};
__declare_io_value(DataFifo16, uint16_t) {
};
__declare_io_value(ParameterFifo, uint8_t) {
};
__declare_io_value(SoundMapDataOut, uint8_t) {
};
__declare_io_value(LeftCD2LeftSPU, CDDAVolume::Type) {
};
__declare_io_value(LeftCD2RightSPU, CDDAVolume::Type) {
};
__declare_io_value(RightCD2RightSPU, CDDAVolume::Type) {
};
__declare_io_value(RightCD2LeftSPU, CDDAVolume::Type) {
};
struct Interrupt { struct Interrupt {
static constexpr auto ExtendedFlags = CD_IO_Values::InterruptEnable::from(
CD_IO_Values::InterruptEnable::InterruptTypValue.range_max<uint8_t>(),
CD_IO_Values::InterruptEnable::UnknownIRQ,
CD_IO_Values::InterruptEnable::CommandStartIRQ
);
enum Type : uint8_t { enum Type : uint8_t {
None = 0, None = 0,
DataReady = 1, DataReady = 1,
@ -133,28 +64,28 @@ namespace JabyEngine {
DiskError = 5 DiskError = 5
}; };
static void enable(IOPort<InterruptEnable>& port) { static void enable(InterruptEnable_IO& port) {
port.write(port.read().set(InterruptEnable::InterruptTypValue.range_max<uint8_t>())); port.write(port.read().set(CD_IO_Values::InterruptEnable::InterruptTypValue.range_max<uint8_t>()));
} }
static void enable_extended(IOPort<InterruptEnable>& port) { static void enable_extended(InterruptEnable_IO& port) {
port.write(InterruptEnable::from(InterruptEnable::InterruptTypValue.range_max<uint8_t>(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)); port.write(Interrupt::ExtendedFlags);
} }
static Type get_type(const IOPort<InterruptFlag>& port) { static Type get_type(const InterruptFlag_IO& port) {
return static_cast<Type>(port.read().get(InterruptFlag::InterruptTypValue)); return static_cast<Type>(port.read().get(CD_IO_Values::InterruptFlag::InterruptTypValue));
} }
static void ack(IOPort<InterruptFlag>& port) { static void ack(InterruptFlag_IO& port) {
port.write(port.read().set(InterruptFlag::InterruptTypValue.range_max<uint8_t>())); port.write(port.read().set(CD_IO_Values::InterruptFlag::InterruptTypValue.range_max<uint8_t>()));
} }
static void ack_extended(IOPort<InterruptFlag>& port) { static void ack_extended(InterruptFlag_IO& port) {
port.write(InterruptFlag::from(InterruptFlag::InterruptTypValue.range_max<uint8_t>(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)); port.write(Interrupt::ExtendedFlags);
} }
static void reset_parameter_fifo(IOPort<InterruptFlag>& port) { static void reset_parameter_fifo(InterruptFlag_IO& port) {
port.write(InterruptFlag{0x40}); port.write(CD_IO_Values::InterruptFlag{0x40});
} }
}; };
@ -185,18 +116,18 @@ namespace JabyEngine {
static constexpr auto IORegister2Adr = 0x1F801802; static constexpr auto IORegister2Adr = 0x1F801802;
static constexpr auto IORegister3Adr = 0x1F801803; static constexpr auto IORegister3Adr = 0x1F801803;
__declare_io_port(, IndexStatus, 0x1F801800); static auto& IndexStatus = __new_declare_io_port(IndexStatus_IO, 0x1F801800);
struct PortIndex0 { struct PortIndex0 {
__declare_io_port(inline const, ResponseFifo, IORegister1Adr); static inline const auto& ResponseFifo = __new_declare_io_port(ResponseFifo_IO, IORegister1Adr);
__declare_io_port(inline, CommandFifo, IORegister1Adr); static inline auto& CommandFifo = __new_declare_io_port(CommandFifo_IO, IORegister1Adr);
__declare_io_port(inline const, DataFifo, IORegister2Adr); static inline const auto& DataFifo = __new_declare_io_port(DataFifo_IO, IORegister2Adr);
__declare_io_port(inline const, DataFifo16, IORegister2Adr); static inline const auto& DataFifo16 = __new_declare_io_port(DataFifo16_IO, IORegister2Adr);
__declare_io_port(inline, ParameterFifo, IORegister2Adr); static inline auto& ParameterFifo = __new_declare_io_port(ParameterFifo_IO, IORegister2Adr);
__declare_io_port(inline const, InterruptEnable, IORegister3Adr); static inline const auto& InterruptEnable = __new_declare_io_port(InterruptEnable_IO, IORegister3Adr);
__declare_io_port(inline, Request, IORegister3Adr); static inline auto& Request = __new_declare_io_port(Request_IO, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus.write({Index::Index0}); IndexStatus.write({Index::Index0});
@ -204,14 +135,14 @@ namespace JabyEngine {
}; };
struct PortIndex1 { struct PortIndex1 {
__declare_io_port(inline const, ResponseFifo, IORegister1Adr); static inline const auto& ResponseFifo = __new_declare_io_port(ResponseFifo_IO, IORegister1Adr);
__declare_io_port(inline, SoundMapDataOut, IORegister1Adr); static inline auto& SoundMapDataOut = __new_declare_io_port(SoundMapDataOut_IO, IORegister1Adr);
__declare_io_port(inline const, DataFifo, IORegister2Adr); static inline const auto& DataFifo = __new_declare_io_port(DataFifo_IO, IORegister2Adr);
__declare_io_port(inline const, DataFifo16, IORegister2Adr); static inline const auto& DataFifo16 = __new_declare_io_port(DataFifo16_IO, IORegister2Adr);
__declare_io_port(inline, InterruptEnable, IORegister2Adr); static inline auto& InterruptEnable = __new_declare_io_port(InterruptEnable_IO, IORegister2Adr);
__declare_io_port_w_type(inline, struct InterruptEnable, InterruptFlag, IORegister3Adr); static inline auto& InterruptFlag = __new_declare_io_port(InterruptFlag_IO, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus.write({Index::Index1}); IndexStatus.write({Index::Index1});
@ -219,15 +150,15 @@ namespace JabyEngine {
}; };
struct PortIndex2 { struct PortIndex2 {
__declare_io_port(inline const, ResponseFifo, IORegister1Adr); static inline const auto& ResponseFifo = __new_declare_io_port(ResponseFifo_IO, IORegister1Adr);
__declare_io_port(inline, SoundMapCoding, IORegister1Adr); static inline auto& SoundMapCoding = __new_declare_io_port(SoundMapCoding_IO, IORegister1Adr);
__declare_io_port(inline const, DataFifo, IORegister2Adr); static inline const auto& DataFifo = __new_declare_io_port(DataFifo_IO, IORegister2Adr);
__declare_io_port(inline const, DataFifo16, IORegister2Adr); static inline const auto& DataFifo16 = __new_declare_io_port(DataFifo16_IO, IORegister2Adr);
__declare_io_port(inline, LeftCD2LeftSPU, IORegister2Adr); static inline auto& LeftCD2LeftSPU = __new_declare_io_port(LeftCD2LeftSPU_IO, IORegister2Adr);
__declare_io_port(inline const, InterruptEnable, IORegister3Adr); static inline const auto& InterruptEnable = __new_declare_io_port(InterruptEnable_IO, IORegister3Adr);
__declare_io_port(inline, LeftCD2RightSPU, IORegister3Adr); static inline auto& LeftCD2RightSPU = __new_declare_io_port(LeftCD2RightSPU_IO, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus.write({Index::Index2}); IndexStatus.write({Index::Index2});
@ -235,22 +166,19 @@ namespace JabyEngine {
}; };
struct PortIndex3 { struct PortIndex3 {
__declare_io_port(inline const, ResponseFifo, IORegister1Adr); static inline const auto& ResponseFifo = __new_declare_io_port(ResponseFifo_IO, IORegister1Adr);
__declare_io_port(inline, RightCD2RightSPU, IORegister1Adr); static inline auto& RightCD2RightSPU = __new_declare_io_port(RightCD2RightSPU_IO, IORegister1Adr);
__declare_io_port(inline const, DataFifo, IORegister2Adr); static inline const auto& DataFifo = __new_declare_io_port(DataFifo_IO, IORegister2Adr);
__declare_io_port(inline const, DataFifo16, IORegister2Adr); static inline const auto& DataFifo16 = __new_declare_io_port(DataFifo16_IO, IORegister2Adr);
__declare_io_port(inline, RightCD2LeftSPU, IORegister1Adr); static inline auto& RightCD2LeftSPU = __new_declare_io_port(RightCD2LeftSPU_IO, IORegister1Adr);
__declare_io_port_w_type(inline const, struct InterruptEnable, InterruptFlag, IORegister3Adr); static inline const auto& InterruptFlag = __new_declare_io_port(InterruptFlag_IO, IORegister3Adr);
__declare_io_port( inline, AudioVolumeApply, IORegister3Adr); static inline auto& AudioVolumeApply = __new_declare_io_port(AudioVolumeApply_IO, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus.write({Index::Index3}); IndexStatus.write({Index::Index3});
} }
}; };
#undef __declare_index_io_port
#undef __declare_index_io_port_const
} }
} }

View File

@ -29,12 +29,12 @@ namespace JabyEngine {
template<typename...ARGS> template<typename...ARGS>
static void send_no_wait(CD_IO::Command::Desc cmd, ARGS...args) { static void send_no_wait(CD_IO::Command::Desc cmd, ARGS...args) {
while(CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::IsTransmissionBusy)); while(CD_IO::IndexStatus.read().is_set(CD_IO_Values::IndexStatus::IsTransmissionBusy));
irq_bit_pending = bit::set(irq_bit_pending, cmd.complete_irq); irq_bit_pending = bit::set(irq_bit_pending, cmd.complete_irq);
CD_IO::PortIndex0::change_to(); CD_IO::PortIndex0::change_to();
((CD_IO::PortIndex0::ParameterFifo.write(CD_IO::ParameterFifo{args})),...); ((CD_IO::PortIndex0::ParameterFifo.write(CD_IO_Values::ParameterFifo{args})),...);
CD_IO::PortIndex0::CommandFifo.write(CD_IO::CommandFifo{cmd.id}); CD_IO::PortIndex0::CommandFifo.write(CD_IO_Values::CommandFifo{cmd.id});
} }
template<typename...ARGS> template<typename...ARGS>

View File

@ -36,9 +36,9 @@ namespace JabyEngine {
} }
}; };
static constexpr auto AudioSectorMode = CD_IO::Mode::from(CD_IO::Mode::SingleSpeed, CD_IO::Mode::AutoPauseTrack, CD_IO::Mode::CDDA); static constexpr auto AudioSectorMode = CD_IO_Values::Mode::from(CD_IO_Values::Mode::SingleSpeed, CD_IO_Values::Mode::AutoPauseTrack, CD_IO_Values::Mode::CDDA);
static constexpr auto DataSectorMode = CD_IO::Mode::from(CD_IO::Mode::DoubleSpeed, CD_IO::Mode::DataSector); static constexpr auto DataSectorMode = CD_IO_Values::Mode::from(CD_IO_Values::Mode::DoubleSpeed, CD_IO_Values::Mode::DataSector);
static constexpr auto XAAudioSectorMode = CD_IO::Mode::from(CD_IO::Mode::SingleSpeed, CD_IO::Mode::XADPCM, CD_IO::Mode::WholeSector, CD_IO::Mode::UseXAFilter); static constexpr auto XAAudioSectorMode = CD_IO_Values::Mode::from(CD_IO_Values::Mode::SingleSpeed, CD_IO_Values::Mode::XADPCM, CD_IO_Values::Mode::WholeSector, CD_IO_Values::Mode::UseXAFilter);
namespace IRQ { namespace IRQ {
static SysCall::InterruptVerifierResult verifier(); static SysCall::InterruptVerifierResult verifier();
@ -69,7 +69,7 @@ namespace JabyEngine {
namespace IRQ { namespace IRQ {
static void read_sector_dma0(uint32_t* dst, size_t bytes) { static void read_sector_dma0(uint32_t* dst, size_t bytes) {
static const auto WaitSectorReady = []() { static const auto WaitSectorReady = []() {
while(!CD_IO::IndexStatus.read().is_set(CD_IO::IndexStatus::HasDataFifoData)); while(!CD_IO::IndexStatus.read().is_set(CD_IO_Values::IndexStatus::HasDataFifoData));
}; };
static const auto ReadSector = [](uint32_t* dst, size_t bytes) { static const auto ReadSector = [](uint32_t* dst, size_t bytes) {
@ -80,7 +80,7 @@ namespace JabyEngine {
DMA_IO::CDROM.wait(); DMA_IO::CDROM.wait();
CD_IO::PortIndex0::change_to(); CD_IO::PortIndex0::change_to();
CD_IO::PortIndex0::Request.write(CD_IO::Request::reset()); CD_IO::PortIndex0::Request.write(CD_IO_Values::Request::reset());
}; };
WaitSectorReady(); WaitSectorReady();
@ -124,7 +124,7 @@ namespace JabyEngine {
CD_IO::PortIndex0::change_to(); CD_IO::PortIndex0::change_to();
if(cur_irq == CD_IO::Interrupt::DataReady) { if(cur_irq == CD_IO::Interrupt::DataReady) {
CD_IO::PortIndex0::Request.write(CD_IO::Request::want_data()); CD_IO::PortIndex0::Request.write(CD_IO_Values::Request::want_data());
} }
// No masking required because we can only write bit 0 - 2 // No masking required because we can only write bit 0 - 2
@ -228,7 +228,7 @@ namespace JabyEngine {
void enable_CDXA(bool double_speed) { void enable_CDXA(bool double_speed) {
static constexpr uint8_t SingleSpeedBit = 0x0; static constexpr uint8_t SingleSpeedBit = 0x0;
static constexpr uint8_t DoubleSpeedBit = static_cast<uint8_t>(CD_IO::Mode::DoubleSpeed); static constexpr uint8_t DoubleSpeedBit = static_cast<uint8_t>(CD_IO_Values::Mode::DoubleSpeed);
const uint8_t mode = XAAudioSectorMode.raw | (double_speed ? DoubleSpeedBit : SingleSpeedBit); const uint8_t mode = XAAudioSectorMode.raw | (double_speed ? DoubleSpeedBit : SingleSpeedBit);