diff --git a/firmware/application/audio.cpp b/firmware/application/audio.cpp index c732fcbb..7858376f 100644 --- a/firmware/application/audio.cpp +++ b/firmware/application/audio.cpp @@ -22,11 +22,8 @@ #include "audio.hpp" #include "portapack.hpp" -using portapack::i2c0; using portapack::clock_manager; -#include "wm8731.hpp" -using wolfson::wm8731::WM8731; #include "portapack_hal.hpp" #include "i2s.hpp" @@ -98,9 +95,7 @@ constexpr i2s::ConfigDMA i2s0_config_dma { }, }; -constexpr uint8_t wm8731_i2c_address = 0x1a; - -WM8731 audio_codec { i2c0, wm8731_i2c_address }; +static audio::Codec* audio_codec = nullptr; } /* namespace */ @@ -118,12 +113,12 @@ void stop() { void mute() { i2s::i2s0::tx_mute(); - - audio_codec.headphone_mute(); + audio_codec->headphone_disable(); } void unmute() { i2s::i2s0::tx_unmute(); + audio_codec->headphone_enable(); } } /* namespace output */ @@ -131,30 +126,40 @@ void unmute() { namespace headphone { volume_range_t volume_range() { - return wolfson::wm8731::headphone_gain_range; + return audio_codec->headphone_gain_range(); } void set_volume(const volume_t volume) { - audio_codec.set_headphone_volume(volume); + audio_codec->set_headphone_volume(volume); } } /* namespace headphone */ namespace debug { -int reg_count() { - return wolfson::wm8731::reg_count; +size_t reg_count() { + return audio_codec->reg_count(); } -uint16_t reg_read(const int register_number) { - return audio_codec.read(register_number); +uint32_t reg_read(const size_t register_number) { + return audio_codec->reg_read(register_number); +} + +std::string codec_name() { + return audio_codec->name(); +} + +size_t reg_bits() { + return audio_codec->reg_bits(); } } /* namespace debug */ -void init() { +void init(audio::Codec* const codec) { + audio_codec = codec; + clock_manager.start_audio_pll(); - audio_codec.init(); + audio_codec->init(); i2s::i2s0::configure( i2s0_config_tx, @@ -167,7 +172,7 @@ void init() { } void shutdown() { - audio_codec.reset(); + audio_codec->reset(); output::stop(); } diff --git a/firmware/application/audio.hpp b/firmware/application/audio.hpp index 8ed545e4..94f193ce 100644 --- a/firmware/application/audio.hpp +++ b/firmware/application/audio.hpp @@ -73,12 +73,14 @@ void set_volume(const volume_t volume); namespace debug { -int reg_count(); -uint16_t reg_read(const int register_number); +size_t reg_count(); +uint32_t reg_read(const size_t register_number); +std::string codec_name(); +size_t reg_bits(); } /* namespace debug */ -void init(); +void init(audio::Codec* const codec); void shutdown(); enum class Rate { diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index d4d73cd3..60545ae9 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -33,6 +33,9 @@ using namespace hackrf::one; #include "touch_adc.hpp" #include "audio.hpp" +#include "wm8731.hpp" +using wolfson::wm8731::WM8731; + #include "cpld_update.hpp" namespace portapack { @@ -61,6 +64,8 @@ ClockManager clock_manager { i2c0, clock_generator }; +WM8731 audio_codec_wm8731 { i2c0, 0x1a }; + ReceiverModel receiver_model; TemperatureLogger temperature_logger; @@ -154,7 +159,7 @@ void init() { portapack::io.init(); - audio::init(); + audio::init(&audio_codec_wm8731); clock_manager.enable_first_if_clock(); clock_manager.enable_second_if_clock(); diff --git a/firmware/application/ui_debug.cpp b/firmware/application/ui_debug.cpp index 907e85b4..3e439367 100644 --- a/firmware/application/ui_debug.cpp +++ b/firmware/application/ui_debug.cpp @@ -260,8 +260,8 @@ DebugPeripheralsMenuView::DebugPeripheralsMenuView(NavigationView& nav) { "Si5351C", RegistersWidgetConfig { 96, 8 }, [](const size_t register_number) { return portapack::clock_generator.read_register(register_number); } ); } }, - { "WM8731", [&nav](){ nav.push( - "WM8731", RegistersWidgetConfig { audio::debug::reg_count(), 9 }, + { audio::debug::codec_name(), [&nav](){ nav.push( + audio::debug::codec_name(), RegistersWidgetConfig { audio::debug::reg_count(), audio::debug::reg_bits() }, [](const size_t register_number) { return audio::debug::reg_read(register_number); } ); } }, }); diff --git a/firmware/common/wm8731.cpp b/firmware/common/wm8731.cpp index e4c01b1b..68086d66 100644 --- a/firmware/common/wm8731.cpp +++ b/firmware/common/wm8731.cpp @@ -108,7 +108,7 @@ bool WM8731::write(const address_t reg_address, const reg_t value) { return bus.transmit(bus_address, values.data(), values.size()); } -reg_t WM8731::read(const address_t reg_address) { +uint32_t WM8731::reg_read(const size_t reg_address) { return map.w[reg_address]; } diff --git a/firmware/common/wm8731.hpp b/firmware/common/wm8731.hpp index bca090e9..b2c52778 100644 --- a/firmware/common/wm8731.hpp +++ b/firmware/common/wm8731.hpp @@ -27,14 +27,11 @@ #include "i2c_pp.hpp" -#include "volume.hpp" +#include "audio.hpp" namespace wolfson { namespace wm8731 { -constexpr volume_range_t headphone_gain_range { -121.0_dB, 6.0_dB }; -constexpr volume_range_t line_in_gain_range { -34.5_dB, 12.0_dB }; - enum class ADCSource { Line = 0, Microphone = 1, @@ -278,7 +275,7 @@ constexpr RegisterMap default_after_reset { Register_Type { }, } }; -class WM8731 { +class WM8731 : public audio::Codec { public: constexpr WM8731( I2C& bus, @@ -288,14 +285,18 @@ public: { } - void init(); + void init() override; + + bool reset() override; - bool reset(); + std::string name() const override { + return "WM8731"; + } bool detected(); void set_line_in_volume(const volume_t volume) { - const auto normalized = line_in_gain_range.normalize(volume); + const auto normalized = line_in_gain_range().normalize(volume); auto n = normalized.centibel() / 15; write(LeftLineIn { @@ -307,9 +308,9 @@ public: }); } - void set_headphone_volume(const volume_t volume) { - const auto normalized = headphone_gain_range.normalize(volume); + void set_headphone_volume(const volume_t volume) override { headphone_volume = volume; + const auto normalized = headphone_gain_range().normalize(volume); auto n = normalized.centibel() / 10; write(LeftHeadphoneOut { @@ -320,8 +321,32 @@ public: }); } + volume_range_t headphone_gain_range() const override { + return { -121.0_dB, 6.0_dB }; + } + + volume_range_t line_in_gain_range() const { + return { -34.5_dB, 12.0_dB }; + } + void headphone_mute() { - set_headphone_volume(headphone_gain_range.min); + set_headphone_volume(headphone_gain_range().min); + } + + void headphone_enable() override { + set_headphone_volume(headphone_volume); + } + + void headphone_disable() override { + headphone_mute(); + } + + void microphone_enable() override { + // TODO: Implement + } + + void microphone_disable() override { + // TODO: Implement } // void microphone_mute(const bool mute) { @@ -334,7 +359,15 @@ public: // write(Register::AnalogAudioPathControl); // } - reg_t read(const address_t reg_address); + size_t reg_count() const override { + return wolfson::wm8731::reg_count; + } + + size_t reg_bits() const override { + return 9; + } + + uint32_t reg_read(const size_t reg_address) override; private: I2C& bus;