From 5c15b66873504749513a8cb858c850c1db78f755 Mon Sep 17 00:00:00 2001 From: jaby Date: Fri, 2 Sep 2022 10:23:32 +0200 Subject: [PATCH] Clear Voice Keys --- include/PSX/System/IOPorts/IOPort.hpp | 83 ++++++-- include/PSX/System/IOPorts/SPU_IO.hpp | 257 ++++++------------------ src/Library/src/BootLoader/boot_spu.cpp | 42 +--- 3 files changed, 132 insertions(+), 250 deletions(-) diff --git a/include/PSX/System/IOPorts/IOPort.hpp b/include/PSX/System/IOPorts/IOPort.hpp index 82ee1ed8..38ee92e0 100644 --- a/include/PSX/System/IOPorts/IOPort.hpp +++ b/include/PSX/System/IOPorts/IOPort.hpp @@ -2,11 +2,28 @@ #define __JABYENGINE_IOPORT_HPP__ #include "../../Auxiliary/bits.hpp" +template +struct Bit { + typedef T ValueType; + + size_t value; + + constexpr Bit(size_t value) : value(value) { + } + + constexpr operator size_t() const { + return this->value; + } +}; + +template struct BitRange { + typedef T ValueType; + size_t begin; size_t length; - static constexpr BitRange from_to(size_t start, size_t end) { + static constexpr BitRange from_to(size_t start, size_t end) { return {start, (end - start + 1)}; } }; @@ -29,9 +46,8 @@ public: } template - constexpr volatile IOPort& set_bit(S bit) volatile { + constexpr void set_bit(S bit) volatile { this->value = bit::set(this->value, static_cast(bit)); - return *this; } template @@ -41,9 +57,8 @@ public: } template - constexpr volatile IOPort& clear_bit(S bit) volatile { + constexpr void clear_bit(S bit) volatile { this->value = bit::set(this->value, static_cast(bit)); - return *this; } template @@ -58,39 +73,46 @@ public: //Accessing values template - constexpr IOPort& set_value(S value, const BitRange& range) { + constexpr IOPort& set_value(S value, const BitRange& range) { this->value = bit::value::set_normalized(this->value, static_cast(value), range.begin, range.length); return *this; } template - constexpr volatile IOPort& set_value(S value, const BitRange& range) volatile { + constexpr void set_value(S value, const BitRange& range) volatile { this->value = bit::value::set_normalized(this->value, static_cast(value), range.begin, range.length); - return *this; } template - constexpr IOPort& clear_value(const BitRange& range) { + constexpr IOPort& clear_value(const BitRange& range) { this->value = bit::value::clear_normalized(this->value, range.begin, range.length); return *this; } template - constexpr volatile IOPort& clear_value(const BitRange& range) volatile { + constexpr void clear_value(const BitRange& range) volatile { this->value = bit::value::clear_normalized(this->value, range.begin, range.length); - return *this; } template - constexpr S get_value(const BitRange& range) { + constexpr S get_value(const BitRange& range) { return static_cast(bit::value::get_normalized(this->value, range.begin, range.length)); } template - constexpr S get_value(const BitRange& range) volatile { + constexpr S get_value(const BitRange& range) volatile { return static_cast(bit::value::get_normalized(this->value, range.begin, range.length)); } + //For easy access + constexpr T read() const { + return const_cast*>(this)->value; + } + + constexpr void write(T value) { + const_cast*>(this)->value = value; + } + //For raw access constexpr operator T() const { return this->value; @@ -100,8 +122,9 @@ public: return this->value; } - constexpr void operator=(T value) { + constexpr IOPort& operator=(T value) { this->value = value; + return *this; } constexpr void operator=(T value) volatile { @@ -109,4 +132,36 @@ public: } }; +struct __no_align ubus32_t { + IOPort low; + IOPort high; + + constexpr ubus32_t(uint32_t value) { + *this = value; + } + + constexpr operator uint32_t() const { + return ((this->high << 16) | this->low); + } + + constexpr operator uint32_t() const volatile { + return ((this->high << 16) | this->low); + } + + constexpr ubus32_t& operator=(uint32_t value) { + this->low = (value & 0xFFFF); + this->high = (value >> 16); + + return *this; + } + + constexpr void operator=(uint32_t value) volatile { + this->low = (value & 0xFFFF); + this->high = (value >> 16); + } +}; +static constexpr uintptr_t IO_Base_Mask = 0xF0000000; +static constexpr uintptr_t IO_Base_Adr = 0x10000000; + +#define __declare_io_port_global(type, name, adr) static __always_inline auto& name = *reinterpret_cast*>((IO_Base_Adr + (adr & ~IO_Base_Mask))) #endif //!__JABYENGINE_IOPORT_HPP__ \ No newline at end of file diff --git a/include/PSX/System/IOPorts/SPU_IO.hpp b/include/PSX/System/IOPorts/SPU_IO.hpp index 94711dd3..6768e8b9 100644 --- a/include/PSX/System/IOPorts/SPU_IO.hpp +++ b/include/PSX/System/IOPorts/SPU_IO.hpp @@ -3,222 +3,85 @@ #include "IOPort.hpp" #include -#include "../../Auxiliary/io_class_helper.hpp" - namespace SPU { - struct __no_align ubus32_t - { - uint16_t low; - uint16_t high; - - constexpr ubus32_t() : low(0), high(0) { - } - - constexpr operator uint32_t() const { - return ((this->high << 16) | this->low); - } - - constexpr void operator=(uint32_t value) { - this->low = (value & 0xFFFF); - this->high = (value >> 16); - } - - constexpr void operator=(ubus32_t value) volatile { - this->low = value.low; - this->high = value.high; - } - }; - - enum Mode { + enum struct SweepMode { Linear = 0, Exponential = 1, }; - - struct __no_align SampleRate { - uint16_t raw_value = 0; - static constexpr SampleRate from_HZ(long double freq) - { - //SampleRate is defined as 4096 == 44100Hz - constexpr long double Base = (4096.0 / 44100.0); + enum struct SweepDirection { + Increase = 0, + Decrease = 1, + }; - return static_cast(((freq*4096.0)/44100.0)); + enum struct SweepPhase { + Posititve = 0, + Negative = 1, + }; + + //0..0x1F = Fast..Slow + typedef uint8_t SweepShift; + + //0..3 = +7, +6, +5, +4 or -6, -7, -6, -5 + typedef uint8_t SweepStep; + + struct __no_align SampleRate : public IOPort { + using IOPort::IOPort; + + static constexpr SampleRate from_HZ(double freq) { + //4096 == 44100Hz + constexpr double Base = (4096.0 / 44100.0); + + return static_cast((freq*Base)); } }; - struct __no_align SweepVolume { - typedef int16_t VolumeStep; + struct __no_align SweepVolume : public IOPort { + // For Volume Mode + static constexpr Bit ModeBit = 15; // 0 Volume Mode; 1 Sweep Mode + static constexpr BitRange VolumeRange = BitRange::from_to(0, 14); - static constexpr VolumeStep VolumeMax = 1000; - static constexpr VolumeStep SingleVolumeStep = (I16_MAX >> 1)/VolumeMax; - - enum Direction { - Increase = 0, - Decrease = 1, - }; - - enum Phase { - Positive = 0, - Negative = 1, - }; - - int16_t raw_value = 0; - - constexpr SweepVolume() = default; - - constexpr auto& set_volume_percent(double percent) { - this->raw_value = bit::value::set_normalized(this->raw_value, static_cast((I16_MAX/100.0)*percent), __start_end_bit2_start_length(0, 14)); - return *this; - } - - constexpr auto& set_volume(int16_t volume) { - this->raw_value = bit::value::set_normalized(this->raw_value, static_cast((volume >> 1)), __start_end_bit2_start_length(0, 14)); - return *this; - } - - constexpr int16_t get_volume_step() const { - return bit::value::get_normalized(this->raw_value, __start_end_bit2_start_length(0, 14)); - } - - io_class__2option_map(volume_mode, sweep_mode, 15); - io_class__2option_map_getter(Mode, linear_sweep_mode, exponential_sweep_mode, sweep_mode_type, 14); - io_class__2option_map_getter(Direction, increase_sweep_mode, decrease_sweep_mode, sweep_mode_direction, 13); - io_class__2option_map_getter(Phase, positive_sweep_phase, negative_sweep_phase, sweep_phase, 12); - - //Uses only 5bit of shift (0..1F (slow..fast)) - constexpr auto& set_sweep_shift(uint8_5b shift) { - const int16_t crop_value = static_cast(shift); //(bit::value::crop_value(shift, 5)); - this->raw_value = bit::value::set_normalized(this->raw_value, crop_value, __start_end_bit2_start_length(2, 6)); - return *this; - } - - constexpr uint8_5b get_sweep_shift() const { - return bit::value::get_normalized(this->raw_value, __start_end_bit2_start_length(2, 6)); - } - - //0..3 maps to => +7, +6, +5, +4 or -8, -7, -6, -5 - constexpr auto& set_sweep_step(uint8_2b step) { - this->raw_value = bit::value::set_normalized(this->raw_value, static_cast(step), __start_end_bit2_start_length(0, 1)); - return *this; - } - - constexpr uint8_2b get_sweep_step() const { - return bit::value::get_normalized(this->raw_value, __start_end_bit2_start_length(0, 1)); - } + // For Sweep Mode + static constexpr Bit SweepModeBit = 14; + static constexpr Bit SweepDirectionBit = 13; + static constexpr Bit SweepPhaseBit = 12; + static constexpr BitRange SweepShiftRange = BitRange::from_to(2, 6); + static constexpr BitRange SweepStepRange = BitRange::from_to(0, 1); }; - struct __no_align ADSR { - ubus32_t raw_value; + struct __no_align SR : public IOPort { + static constexpr Bit SustainModeBit = (31 - 16); + static constexpr Bit SustainDirectionBit = (30 - 16); + static constexpr BitRange SustainShiftRange = BitRange::from_to((24 - 16), (28 - 16)); + static constexpr BitRange SustainStepRange = BitRange::from_to((22 - 16), (23 - 16)); + static constexpr Bit ReleaseModeBit = (21 - 16); + static constexpr BitRange ReleaseShiftRange = BitRange::from_to((16 - 16), (20 - 16)); }; - struct __no_align KeyW { - ubus32_t raw_value; - - constexpr KeyW() = default; - - static constexpr KeyW All1() { - KeyW value; - - value.raw_value = static_cast(0xFFFFFFFF); - return value; - } - - constexpr KeyW& set(size_t id) { - this->raw_value = bit::set(this->raw_value, id); - return *this; - } - }; - - struct __no_align KeyR { - ubus32_t raw_value; - - constexpr bool is_set(size_t id) const { - return bit::is_set(this->raw_value, id); - } - }; - - struct __no_align Key { - static inline __always_inline auto& on = *reinterpret_cast(0x1F801D88); - static inline __always_inline auto& off = *reinterpret_cast(0x1F801D8C); - static inline __always_inline auto& state = *reinterpret_cast(0x1F801D9C); + struct __no_align AD : public IOPort { + static constexpr Bit AttackModeBit = 15; + static constexpr BitRange AttackShiftRange = BitRange::from_to(10, 14); + static constexpr BitRange AttackStepRange = BitRange::from_to(8, 9); + static constexpr BitRange DecayShiftRange = BitRange::from_to(4, 7); + static constexpr BitRange SustainLevelRange = BitRange::from_to(0, 3); }; struct __no_align Voice { - static constexpr size_t Count = 24; - static inline __always_inline auto& Channel = reinterpret_cast(*reinterpret_cast(0x1f801c00)); - - SweepVolume volumeLeft; - SweepVolume volumeRight; - SampleRate sampleRate; - uint16_t adr; - ADSR adsr; - SweepVolume currentVolume; //Not used - uint16_t repeatAdr; + SweepVolume volumeLeft; + SweepVolume volumeRight; + SampleRate sampleRate; + IOPort adr; + IOPort ad; + IOPort sr; + IOPort currentVolume; //Not used + IOPort repeatAdr; }; - struct MainVolume { - static inline __always_inline auto& Left = *reinterpret_cast(0x1F801D80); - static inline __always_inline auto& Right = *reinterpret_cast(0x1F801D82); - }; - - struct __no_align Control { - static inline __always_inline auto& Register = *reinterpret_cast(0x1F801DAA); - - enum TransferMode - { - Stop = 0, - ManualWrite = (1 << 4), - DMAWrite = (2 << 4), - DMARead = (3 << 4), - }; - - uint16_t raw_value = 0; - - constexpr Control() = default; - - io_class__2option_map(off, on, 15); - io_class__2option_map_getter_is(bool, mute, unmute, 14); - - constexpr Control& set_noise_shift(uint8_4b shift) { - this->raw_value = bit::value::set_normalized(this->raw_value, static_cast(shift), __start_end_bit2_start_length(10, 13)); - return *this; - } - - constexpr uint8_4b get_noise_shift() const { - return bit::value::get_normalized(this->raw_value, __start_end_bit2_start_length(10, 13)); - } - - constexpr Control& set_noise_step(uint8_2b step) { - this->raw_value = bit::value::set_normalized(this->raw_value, static_cast(step), __start_end_bit2_start_length(8, 9)); - return *this; - } - - constexpr uint8_2b get_noise_step() const { - return bit::value::get_normalized(this->raw_value, __start_end_bit2_start_length(8, 9)); - } - - io_class__2option_map_getter_is(bool, reverb_disabled, reverb_enabled, 7); - io_class__2option_map(irq9_ack, irq9_enable, 6); - - constexpr Control& set_transfer_mode(TransferMode mode) { - this->raw_value = bit::value::set_normalized(this->raw_value, static_cast(mode), __start_end_bit2_start_length(4, 5)); - return *this; - } - - constexpr TransferMode get_transfer_mode() const { - return static_cast(bit::value::get_normalized(this->raw_value, __start_end_bit2_start_length(4, 5))); - } - - io_class__2option_map_getter_is(bool, external_reverb_off, external_reverb_on, 3); - io_class__2option_map_getter_is(bool, cd_reverb_off, cd_reverb_on, 2); - io_class__2option_map_getter_is(bool, external_audio_off, external_audio_on, 1); - io_class__2option_map_getter_is(bool, cd_audio_disable, cd_audio_enable, 0); - }; - - struct DataTransferControl { - static inline __always_inline auto& Register = *reinterpret_cast*>(0x1F801DAC); - static inline __always_inline volatile auto& vRegister = *reinterpret_cast*>(0x1F801DAC); - }; + namespace Key { + __declare_io_port_global(ubus32_t, on, 0x1F801D88); + __declare_io_port_global(ubus32_t, off, 0x1F801D8C); + __declare_io_port_global(ubus32_t, status, 0x1F801D9C); + } } #endif //!__JABYENGINE_SPU_IO_HPP__ \ No newline at end of file diff --git a/src/Library/src/BootLoader/boot_spu.cpp b/src/Library/src/BootLoader/boot_spu.cpp index 15870d31..082a2a5b 100644 --- a/src/Library/src/BootLoader/boot_spu.cpp +++ b/src/Library/src/BootLoader/boot_spu.cpp @@ -2,47 +2,11 @@ #include namespace SPU { - static void clear_main_volume() { - static constexpr auto StartVol = SweepVolume().set_volume_mode().set_volume_percent(50.0); - - io_class__update_with(MainVolume::Left, StartVol); - io_class__update_with(MainVolume::Right, StartVol); - } - - static void clear_keys() { - io_class__update_with(Key::off, KeyW::All1()); - } - - static void clear_voice(Voice& voice) { - io_class__update_with(voice.volumeLeft, SweepVolume()); - io_class__update_with(voice.volumeRight, SweepVolume()); - - io_class__update_with(voice.sampleRate, SampleRate::from_HZ(0.0)); - io_class__update_with(voice.adsr, ADSR()); - io_class__update_with(voice.currentVolume, SweepVolume()); - - voice.adr = 0x200; - voice.repeatAdr = 0x200; - } - - static void enable_control() { - io_class__update_with(Control::Register, Control().set_on().set_unmute().set_cd_audio_enable()); - } - - static void disable_control() { - io_class__update_with(Control::Register, Control()); + static void clear_key() { + Key::off.write(UI32_MAX); } void setup() { - clear_main_volume(); - clear_keys(); - disable_control(); - - for(auto& voice : Voice::Channel) { - clear_voice(voice); - } - - DataTransferControl::Register = (2 << 1); - enable_control(); + clear_key(); } } \ No newline at end of file