207 lines
9.5 KiB
C++
207 lines
9.5 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;
|
|
};
|
|
|
|
typedef struct IndexStatus : public ComplexBitMap<uint8_t> {
|
|
static constexpr auto PortIndex = BitRange<Index>::from_to(0, 1);
|
|
static constexpr auto HasXAFifoData = Bit<uint8_t>(2);
|
|
static constexpr auto IsParameterFifoEmpty = Bit<uint8_t>(3);
|
|
static constexpr auto HasParameterFifoSpace = Bit<uint8_t>(4);
|
|
static constexpr auto HasResponseFifoData = Bit<uint8_t>(5);
|
|
static constexpr auto HasDataFifoData = Bit<uint8_t>(6);
|
|
static constexpr auto IsTransmissionBusy = Bit<uint8_t>(7);
|
|
} IndexStatus_t;
|
|
|
|
struct InterruptEnable : public ComplexBitMap<uint8_t> {
|
|
static constexpr auto InterruptTypValue = BitRange<uint8_t>::from_to(0, 2);
|
|
static constexpr auto InterruptExtended = BitRange<uint8_t>::from_to(0, 4);
|
|
static constexpr auto UnknownIRQ = Bit<uint8_t>(3);
|
|
static constexpr auto CommandStartIRQ = Bit<uint8_t>(4);
|
|
};
|
|
typedef InterruptEnable InterruptFlag;
|
|
|
|
struct Request : public ComplexBitMap<uint8_t> {
|
|
static constexpr auto WantCommandStartIRQ = Bit<uint8_t>(5);
|
|
static constexpr auto WantData = Bit<uint8_t>(7);
|
|
};
|
|
|
|
struct SoundMapCoding : public ComplexBitMap<uint8_t> {
|
|
static constexpr auto Stereo = Bit<uint8_t>(0);
|
|
static constexpr auto Mono = !Stereo;
|
|
static constexpr auto SampleRate_18900hz = Bit<uint8_t>(2);
|
|
static constexpr auto SampleRate_37800hz = !SampleRate_18900hz;
|
|
static constexpr auto BitsPerSample8 = Bit<uint8_t>(4);
|
|
static constexpr auto BitsPerSample4 = !BitsPerSample8;
|
|
static constexpr auto Emphasis = Bit<uint8_t>(6);
|
|
};
|
|
|
|
struct AudioVolumeApply : public ComplexBitMap<uint8_t> {
|
|
static constexpr auto Mute = Bit<uint8_t>(0);
|
|
static constexpr auto ApplyChanges = Bit<uint8_t>(5);
|
|
};
|
|
|
|
typedef VolatilePOD<uint8_t> ResponseFifo_t;
|
|
typedef VolatilePOD<uint8_t> CommandFifo_t;
|
|
typedef VolatilePOD<uint8_t> DataFifo_t;
|
|
typedef VolatilePOD<uint16_t> DataFifo16_t;
|
|
typedef VolatilePOD<uint8_t> ParameterFifo_t;
|
|
typedef VolatilePOD<uint8_t> SoundMapDataOut_t;
|
|
typedef VolatilePOD<CDDAVolume::Type> VolumeRegister_t;
|
|
typedef VolatileBitMapPOD<InterruptEnable> InterruptEnableRegister_t;
|
|
typedef VolatileBitMapPOD<InterruptFlag> InterruptFlagRegister_t;
|
|
typedef VolatileBitMapPOD<Request> RequestRegister_t;
|
|
typedef VolatileBitMapPOD<SoundMapCoding> SoundMapCodingInfo_t;
|
|
typedef VolatileBitMapPOD<AudioVolumeApply> AudioVolumeApplyChange_t;
|
|
|
|
struct Interrupt {
|
|
enum Type : uint8_t {
|
|
None = 0,
|
|
DataReady = 1,
|
|
Complete = 2,
|
|
Acknowledge = 3,
|
|
DataEnd = 4,
|
|
DiskError = 5
|
|
};
|
|
|
|
static void enable(InterruptEnableRegister_t& port) {
|
|
port.write(InterruptEnable::InterruptTypValue.max());
|
|
}
|
|
|
|
static void enable_extended(InterruptEnableRegister_t& port) {
|
|
port.write({InterruptEnable::with(InterruptEnable::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)});
|
|
}
|
|
|
|
static Type get_type(const InterruptFlagRegister_t& port) {
|
|
return static_cast<Type>(port.read().get_value(InterruptFlag::InterruptTypValue));
|
|
}
|
|
|
|
static void ack(InterruptFlagRegister_t& port) {
|
|
port.write(InterruptFlag::InterruptTypValue.max());
|
|
}
|
|
|
|
static void ack_extended(InterruptFlagRegister_t& port) {
|
|
port.write({InterruptFlag::with(InterruptFlag::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)});
|
|
}
|
|
};
|
|
|
|
struct Command {
|
|
struct Info {
|
|
uint8_t id;
|
|
Interrupt::Type complete_irq;
|
|
};
|
|
|
|
static constexpr Info GetStat{0x01, Interrupt::Type::Acknowledge};
|
|
static constexpr Info SetLoc{0x02, Interrupt::Type::Acknowledge};
|
|
static constexpr Info ReadN{0x06, Interrupt::Type::DataReady};
|
|
static constexpr Info Pause{0x09, Interrupt::Type::Complete};
|
|
static constexpr Info Init{0x0A, Interrupt::Type::Complete};
|
|
static constexpr Info SetMode{0x0E, Interrupt::Type::Acknowledge};
|
|
};
|
|
|
|
static constexpr auto IORegister1Adr = 0x1F801801;
|
|
static constexpr auto IORegister2Adr = 0x1F801802;
|
|
static constexpr auto IORegister3Adr = 0x1F801803;
|
|
|
|
__declare_io_port_global(IndexStatus_t, 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_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr);
|
|
__declare_index_io_port( CommandFifo_t, CommandFifo, IORegister1Adr);
|
|
|
|
__declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr);
|
|
__declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr);
|
|
__declare_index_io_port( ParameterFifo_t, ParameterFifo, IORegister2Adr);
|
|
|
|
__declare_index_io_port_const(InterruptEnableRegister_t, InterruptEnableRegister, IORegister3Adr);
|
|
__declare_index_io_port( RequestRegister_t, RequestRegister, IORegister3Adr);
|
|
|
|
static void change_to() {
|
|
IndexStatus.write({static_cast<uint8_t>(Index::Index0)});
|
|
}
|
|
};
|
|
|
|
struct PortIndex1 {
|
|
__declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr);
|
|
__declare_index_io_port( SoundMapDataOut_t, SoundMapDataOut, IORegister1Adr);
|
|
|
|
__declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr);
|
|
__declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr);
|
|
__declare_index_io_port( InterruptEnableRegister_t, InterruptEnableRegister, IORegister2Adr);
|
|
|
|
__declare_index_io_port(InterruptFlagRegister_t, InterruptFlagRegister, IORegister3Adr);
|
|
|
|
static void change_to() {
|
|
IndexStatus.write({static_cast<uint8_t>(Index::Index1)});
|
|
}
|
|
};
|
|
|
|
struct PortIndex2 {
|
|
__declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr);
|
|
__declare_index_io_port( SoundMapCodingInfo_t, SoundMapCodingInfo, IORegister1Adr);
|
|
|
|
__declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr);
|
|
__declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr);
|
|
__declare_index_io_port( VolumeRegister_t, LeftCD2LeftSPU, IORegister2Adr);
|
|
|
|
__declare_index_io_port_const(InterruptEnableRegister_t, InterruptEnableRegister, IORegister3Adr);
|
|
__declare_index_io_port( VolumeRegister_t, LeftCD2RightSPU, IORegister3Adr);
|
|
|
|
static void change_to() {
|
|
IndexStatus.write({static_cast<uint8_t>(Index::Index2)});
|
|
}
|
|
};
|
|
|
|
struct PortIndex3 {
|
|
__declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr);
|
|
__declare_index_io_port( VolumeRegister_t, RightCD2RightSPU, IORegister1Adr);
|
|
|
|
__declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr);
|
|
__declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr);
|
|
__declare_index_io_port( VolumeRegister_t, RightCD2LeftSPU, IORegister1Adr);
|
|
|
|
__declare_index_io_port_const(InterruptFlagRegister_t, InterruptFlagRegister, IORegister3Adr);
|
|
__declare_index_io_port( AudioVolumeApplyChange_t, AudioVolumeApplyChange, IORegister3Adr);
|
|
|
|
static void change_to() {
|
|
IndexStatus.write({static_cast<uint8_t>(Index::Index3)});
|
|
}
|
|
};
|
|
|
|
#undef __declare_index_io_port
|
|
#undef __declare_index_io_port_const
|
|
}
|
|
}
|
|
|
|
#endif //!__JABYENGINE_CD_IO_HPP__
|