#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 { 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); } IndexStatus_t; struct InterruptEnable : public ComplexBitMap { static constexpr auto InterruptTypValue = BitRange::from_to(0, 2); static constexpr auto UnknownIRQ = Bit(3); static constexpr auto CommandStartIRQ = Bit(4); }; typedef InterruptEnable InterruptFlag; struct Request : public ComplexBitMap { static constexpr auto WantCommandStartIRQ = Bit(5); static constexpr auto WantData = Bit(7); }; struct SoundMapCoding : public ComplexBitMap { 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); }; struct AudioVolumeApply : public ComplexBitMap { static constexpr auto Mute = Bit(0); static constexpr auto ApplyChanges = Bit(5); }; struct Interrupt { static void enable_all(VolatileBitMapPOD& port) { port.write({InterruptEnable::with(InterruptEnable::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); } static uint8_t get_type(const VolatileBitMapPOD& port) { return port.read().get_value(InterruptFlag::InterruptTypValue); } static void ack(VolatileBitMapPOD& 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 ResponseFifo; typedef VolatilePOD CommandFifo; typedef VolatilePOD DataFifo; typedef VolatilePOD DataFifo16; typedef VolatilePOD ParameterFifo; typedef VolatilePOD SoundMapDataOut; typedef VolatilePOD VolumeRegister; typedef VolatileBitMapPOD InterruptEnableRegister; typedef VolatileBitMapPOD InterruptFlagRegister; typedef VolatileBitMapPOD RequestRegister; typedef VolatileBitMapPOD SoundMapCodingInfo; typedef VolatileBitMapPOD 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 static S& change_to(Index idx) { IndexStatus.write({static_cast(idx)}); return *reinterpret_cast(0x1F801801); } } static Index0Types::IndexTriplet& change_to_index0() { return Helper::change_to(Index::Index0); } static Index1Types::IndexTriplet& change_to_index1() { return Helper::change_to(Index::Index1); } static Index2Types::IndexTriplet& change_to_index2() { return Helper::change_to(Index::Index2); } static Index3Types::IndexTriplet& change_to_index3() { return Helper::change_to(Index::Index2); } } } #endif //!__JABYENGINE_CD_IO_HPP__