211 lines
7.9 KiB
C++
211 lines
7.9 KiB
C++
#ifndef __JABYENGINE_CD_IO_HPP__
|
|
#define __JABYENGINE_CD_IO_HPP__
|
|
#include "ioport.hpp"
|
|
|
|
namespace JabyEngine {
|
|
namespace CD_IO {
|
|
enum struct 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 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);
|
|
};
|
|
|
|
struct Interrupt {
|
|
static void enable_all(VolatileBitMapPOD<InterruptEnable>& port) {
|
|
port.write({InterruptEnable::with(InterruptEnable::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)});
|
|
}
|
|
|
|
static uint8_t get_type(const VolatileBitMapPOD<InterruptFlag>& port) {
|
|
return port.read().get_value(InterruptFlag::InterruptTypValue);
|
|
}
|
|
|
|
static void ack(VolatileBitMapPOD<InterruptFlag>& port) {
|
|
port.write(InterruptFlag::InterruptTypValue.max());
|
|
}
|
|
};
|
|
|
|
__declare_io_port_global(IndexStatus_t, IndexStatus, 0x1F801800);
|
|
|
|
static constexpr auto IORegister1Adr = 0x1F801801;
|
|
static constexpr auto IORegister2Adr = 0x1F801802;
|
|
static constexpr auto IORegister3Adr = 0x1F801803;
|
|
|
|
struct Index0 {
|
|
__declare_io_port_member_const_simple(uint8_t, ResponseFifo, IORegister1Adr);
|
|
__declare_io_port_member_simple(uint8_t, CommandFifo, IORegister1Adr);
|
|
|
|
__declare_io_port_member_const_simple(uint8_t, DataFifo, IORegister2Adr);
|
|
__declare_io_port_member_const_simple(uint16_t, DataFifo16, IORegister2Adr);
|
|
};
|
|
|
|
typedef VolatilePOD<uint8_t> ResponseFifo;
|
|
typedef VolatilePOD<uint8_t> CommandFifo;
|
|
typedef VolatilePOD<uint8_t> DataFifo;
|
|
typedef VolatilePOD<uint16_t> DataFifo16;
|
|
typedef VolatilePOD<uint8_t> ParameterFifo;
|
|
typedef VolatilePOD<uint8_t> SoundMapDataOut;
|
|
typedef VolatilePOD<CDDAVolume::Type> VolumeRegister;
|
|
typedef VolatileBitMapPOD<InterruptEnable> InterruptEnableRegister;
|
|
typedef VolatileBitMapPOD<InterruptFlag> InterruptFlagRegister;
|
|
typedef VolatileBitMapPOD<Request> RequestRegister;
|
|
typedef VolatileBitMapPOD<SoundMapCoding> SoundMapCodingInfo;
|
|
typedef VolatileBitMapPOD<AudioVolumeApply> AudioVolumeApplyChange;
|
|
|
|
namespace Index0Types {
|
|
struct __no_align IndexTriplet {
|
|
union __no_align {
|
|
const ResponseFifo response_fifo;
|
|
CommandFifo command;
|
|
};
|
|
|
|
union __no_align {
|
|
const DataFifo data_fifo;
|
|
ParameterFifo parameter_fifo;
|
|
};
|
|
|
|
union __no_align {
|
|
const InterruptEnableRegister irq_enable;
|
|
RequestRegister request;
|
|
};
|
|
};
|
|
|
|
static_assert(sizeof(IndexTriplet) == 3);
|
|
}
|
|
|
|
namespace Index1Types {
|
|
struct __no_align IndexTriplet {
|
|
union __no_align {
|
|
const ResponseFifo response_fifo;
|
|
SoundMapDataOut sound_map_data_out;
|
|
};
|
|
|
|
union __no_align {
|
|
const DataFifo data_fifo;
|
|
InterruptEnableRegister irq_enable;
|
|
};
|
|
|
|
union __no_align {
|
|
InterruptFlagRegister irq_flag;
|
|
};
|
|
};
|
|
|
|
static_assert(sizeof(IndexTriplet) == 3);
|
|
}
|
|
|
|
namespace Index2Types {
|
|
struct __no_align IndexTriplet {
|
|
union __no_align {
|
|
const ResponseFifo response_fifo;
|
|
SoundMapCodingInfo sound_map_coding_info;
|
|
};
|
|
|
|
union __no_align {
|
|
const DataFifo data_fifo;
|
|
VolumeRegister left_cd_2_left_spu;
|
|
};
|
|
|
|
union __no_align {
|
|
const InterruptEnableRegister irq_enable;
|
|
VolumeRegister left_cd_2_right_spu;
|
|
};
|
|
};
|
|
|
|
static_assert(sizeof(IndexTriplet) == 3);
|
|
}
|
|
|
|
namespace Index3Types {
|
|
struct __no_align IndexTriplet {
|
|
union __no_align {
|
|
const ResponseFifo response_fifo;
|
|
VolumeRegister right_cd_2_right_spu;
|
|
};
|
|
|
|
union __no_align {
|
|
const DataFifo data_fifo;
|
|
VolumeRegister right_cd_2_left_spu;
|
|
};
|
|
|
|
union __no_align {
|
|
const InterruptFlagRegister irq_flag;
|
|
AudioVolumeApplyChange audio_volume_change;
|
|
};
|
|
};
|
|
|
|
static_assert(sizeof(IndexTriplet) == 3);
|
|
}
|
|
|
|
|
|
|
|
namespace Helper {
|
|
template<typename S>
|
|
static S& change_to(Index idx) {
|
|
IndexStatus.write({static_cast<uint8_t>(idx)});
|
|
return *reinterpret_cast<S*>(0x1F801801);
|
|
}
|
|
}
|
|
|
|
static Index0Types::IndexTriplet& change_to_index0() {
|
|
return Helper::change_to<Index0Types::IndexTriplet>(Index::Index0);
|
|
}
|
|
|
|
static Index1Types::IndexTriplet& change_to_index1() {
|
|
return Helper::change_to<Index1Types::IndexTriplet>(Index::Index1);
|
|
}
|
|
|
|
static Index2Types::IndexTriplet& change_to_index2() {
|
|
return Helper::change_to<Index2Types::IndexTriplet>(Index::Index2);
|
|
}
|
|
|
|
static Index3Types::IndexTriplet& change_to_index3() {
|
|
return Helper::change_to<Index3Types::IndexTriplet>(Index::Index2);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif //!__JABYENGINE_CD_IO_HPP__
|