From 8d9719e8b9d3aa0f99af6f7405e63154e46a8d16 Mon Sep 17 00:00:00 2001 From: Szymon Mroczek <63716532+SzMrMdt@users.noreply.github.com> Date: Fri, 13 Nov 2020 13:51:30 +0100 Subject: [PATCH] [EGD-3510] audio codec configuration for headset microphone (#1004) [EGD-3510] Audio stereo outputs fixed. Microphone bias handling for headset. Headset microphone gain adjusted. --- changelog.md | 1 + .../Audio/Operation/RouterOperation.cpp | 2 +- .../Profiles/ProfilePlaybackHeadphones.hpp | 1 - .../Profiles/ProfileRecordingHeadphones.hpp | 1 - .../Profiles/ProfileRecordingOnBoardMic.hpp | 1 - .../Profiles/ProfileRoutingEarspeaker.hpp | 1 - .../Profiles/ProfileRoutingHeadphones.hpp | 3 +- .../Profiles/ProfileRoutingLoudspeaker.hpp | 3 +- .../board/rt1051/bsp/audio/CodecMAX98090.cpp | 258 +++++++++--------- .../board/rt1051/bsp/audio/CodecMAX98090.hpp | 2 + .../board/rt1051/bsp/audio/max98090_regs.hpp | 94 ++----- .../board/rt1051/bsp/headset/headset.cpp | 38 ++- module-bsp/board/rt1051/common/board.h | 10 +- module-bsp/board/rt1051/common/pin_mux.c | 9 +- module-bsp/board/rt1051/common/pin_mux.h | 5 +- module-bsp/bsp/audio/bsp_audio.hpp | 1 + .../service-audio/ServiceAudio.cpp | 2 +- 17 files changed, 220 insertions(+), 212 deletions(-) diff --git a/changelog.md b/changelog.md index 7ca5352e91aa3c9968e5edd2d17ee0e77c7bd388..28e0f3bd239dd624f002e064f3d70c84a216ebc9 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,7 @@ * `[file indexer db]` Added messages for File Indexer db. * `[settings]` Added Torch window (front-end only). * `[audio]` Added support for Bluetooth audio profiles +* `[audio]` Added support for headset microphone. * `[filesystem]` Added support for standard file IO library. * [`[messages]`] Added fetching text messages at phone startup. diff --git a/module-audio/Audio/Operation/RouterOperation.cpp b/module-audio/Audio/Operation/RouterOperation.cpp index 8129827b86b79ebd6f27f5ae2433b112665e2de5..2d5a5822046162ae0c81ec46a86e7dd6575c9487 100644 --- a/module-audio/Audio/Operation/RouterOperation.cpp +++ b/module-audio/Audio/Operation/RouterOperation.cpp @@ -104,7 +104,7 @@ namespace audio constexpr audio::Volume defaultRoutingEarspeakerVolume = 10; constexpr audio::Gain defaultRoutingSpeakerphoneGain = 20; constexpr audio::Volume defaultRoutingSpeakerphoneVolume = 10; - constexpr audio::Gain defaultRoutingHeadphonesGain = 50; + constexpr audio::Gain defaultRoutingHeadphonesGain = 0; constexpr audio::Volume defaultRoutingHeadphonesVolume = 10; const auto dbRoutingEarspeakerGainPath = diff --git a/module-audio/Audio/Profiles/ProfilePlaybackHeadphones.hpp b/module-audio/Audio/Profiles/ProfilePlaybackHeadphones.hpp index 507a33ba4f0db9bd80a28a1188cf86ec4cb79209..24ba600ca8c08034b03a2256971f94bd486f7e07 100644 --- a/module-audio/Audio/Profiles/ProfilePlaybackHeadphones.hpp +++ b/module-audio/Audio/Profiles/ProfilePlaybackHeadphones.hpp @@ -1,6 +1,5 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - #pragma once #include "Profile.hpp" diff --git a/module-audio/Audio/Profiles/ProfileRecordingHeadphones.hpp b/module-audio/Audio/Profiles/ProfileRecordingHeadphones.hpp index 645207ac3a56c08dfea2f20a3e02ec8a4c3ebf9e..5d26d43b41e85e14b9948e275844f71c731cc1ca 100644 --- a/module-audio/Audio/Profiles/ProfileRecordingHeadphones.hpp +++ b/module-audio/Audio/Profiles/ProfileRecordingHeadphones.hpp @@ -1,6 +1,5 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - #pragma once #include "Profile.hpp" diff --git a/module-audio/Audio/Profiles/ProfileRecordingOnBoardMic.hpp b/module-audio/Audio/Profiles/ProfileRecordingOnBoardMic.hpp index 07f5e554870236f17fb0ad752f55fdc666a1a3ff..3f8bb6d031204414f302d75594e23b4482627463 100644 --- a/module-audio/Audio/Profiles/ProfileRecordingOnBoardMic.hpp +++ b/module-audio/Audio/Profiles/ProfileRecordingOnBoardMic.hpp @@ -1,6 +1,5 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - #pragma once #include "Profile.hpp" diff --git a/module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp b/module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp index e4fda48aa8584cfc022189611fe46e2a07b9f249..080a4c62f7b8cb72da5cdf64f32f1ade3bd8d146 100644 --- a/module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp +++ b/module-audio/Audio/Profiles/ProfileRoutingEarspeaker.hpp @@ -1,6 +1,5 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - #pragma once #include "Profile.hpp" diff --git a/module-audio/Audio/Profiles/ProfileRoutingHeadphones.hpp b/module-audio/Audio/Profiles/ProfileRoutingHeadphones.hpp index ee3b70362b4b00060a9ce90d6de76eed9dcc71c5..b00503e2ce3852f9627d463d60bf1e660fe1f8ea 100644 --- a/module-audio/Audio/Profiles/ProfileRoutingHeadphones.hpp +++ b/module-audio/Audio/Profiles/ProfileRoutingHeadphones.hpp @@ -1,6 +1,5 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - #pragma once #include "Profile.hpp" @@ -23,7 +22,7 @@ namespace audio .outputVolume = static_cast(volume), .inputGain = static_cast(gain), .inputPath = bsp::AudioDevice::InputPath::Headphones, - .outputPath = bsp::AudioDevice::OutputPath::Headphones}, + .outputPath = bsp::AudioDevice::OutputPath::HeadphonesMono}, bsp::AudioDevice::Type::Audiocodec, callback) {} diff --git a/module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp b/module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp index d76f31040d9a86e4d8815c3161c4b904692b52ce..815a5acb061ebfc014a0ec97eff09419377710ed 100644 --- a/module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp +++ b/module-audio/Audio/Profiles/ProfileRoutingLoudspeaker.hpp @@ -1,6 +1,5 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - #pragma once #include "Profile.hpp" @@ -23,7 +22,7 @@ namespace audio .outputVolume = static_cast(volume), .inputGain = static_cast(gain), .inputPath = bsp::AudioDevice::InputPath::Microphone, - .outputPath = bsp::AudioDevice::OutputPath::Loudspeaker}, + .outputPath = bsp::AudioDevice::OutputPath::LoudspeakerMono}, bsp::AudioDevice::Type::Audiocodec, callback) {} diff --git a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp index 26307132e2fc6879b9682a376aeb98266e75ba16..66a9fc0ea06a3e3091ca3302f1e0de35c031e06a 100644 --- a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp +++ b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.cpp @@ -80,31 +80,34 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m) // OUT configuration if (params.outputPath != bsp::AudioDevice::OutputPath::None) { - // Set output route - max98090_reg_playback_quick_setup_t q_playback_setup = {0}; // Control HP performance max98090_reg_dachp_perfmode_t dacperf = {0}; + dacperf.dachp = 1; + dacperf.perfmode = 0; + i2cAddr.subAddress = MAX98090_REG_DACHP_PERF_MODE; + i2c->Write(i2cAddr, (uint8_t *)&dacperf, 1); switch (params.outputPath) { case bsp::AudioDevice::OutputPath::HeadphonesMono: { + max98090_reg_playback_quick_setup_t q_playback_setup = {0}; + q_playback_setup.dig2hp = 1; + i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP; + i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1); // Mix left DAC channel to left&right HP output max98090_reg_lhp_mixer_t lmixconf = {0}; - max98090_reg_rhp_mixer_t rmixconf = {0}; lmixconf.mixhpl = 1; - rmixconf.mixhpr = 1; - i2cAddr.subAddress = MAX98090_REG_LHP_MIXER_CONF; i2c->Write(i2cAddr, (uint8_t *)&lmixconf, 1); + + max98090_reg_rhp_mixer_t rmixconf = {0}; + rmixconf.mixhpr = 1; i2cAddr.subAddress = MAX98090_REG_RHP_MIXER_CONF; i2c->Write(i2cAddr, (uint8_t *)&rmixconf, 1); - q_playback_setup.dig2hp = 1; - i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP; - i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1); - + // Use mixer outputs instead of direct DAC outputs max98090_reg_hpmix_conf_t mixconf = {0}; mixconf.mixhplsel = 1; mixconf.mixhprsel = 1; @@ -114,110 +117,58 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m) } break; case bsp::AudioDevice::OutputPath::Headphones: { - // Set DAC headphones output to high performance mode, increasing power consumption but providing the - // highest quality - dacperf.dachp = 1; - dacperf.perfmode = 1; - q_playback_setup.dig2hp = 1; - + max98090_reg_playback_quick_setup_t q_playback_setup = {0}; + q_playback_setup.dig2hp = 1; i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP; i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1); - i2cAddr.subAddress = MAX98090_REG_DACHP_PERF_MODE; - i2c->Write(i2cAddr, (uint8_t *)&dacperf, 1); } break; case bsp::AudioDevice::OutputPath::Earspeaker: { + max98090_reg_playback_quick_setup_t q_playback_setup = {0}; q_playback_setup.dig2ear = 1; i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP; i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1); - qfilter_coefficients_t band1_filter = {0}; - qfilter_coefficients_t band2_filter = {0}; - qfilter_coefficients_t band3_filter = {0}; - - // Highpass,lowpass & flat filters don't use Gain parameter - qfilter_CalculateCoeffs(FilterHighPass, 800, currentParams.GetSampleRateVal(), 0.707, 1, &band1_filter); - qfilter_CalculateCoeffs(FilterLowPass, 6000, currentParams.GetSampleRateVal(), 0.707, 1, &band2_filter); - qfilter_CalculateCoeffs(FilterFlat, 0, currentParams.GetSampleRateVal(), 0.707, 1, &band3_filter); - - // BAND1 - WriteFilterCoeff(band1_filter.b0, 0x46); - WriteFilterCoeff(band1_filter.b1, 0x49); - WriteFilterCoeff(band1_filter.b2, 0x4C); - WriteFilterCoeff(band1_filter.a1, 0x4F); - WriteFilterCoeff(band1_filter.a2, 0x52); - - // BAND2 - WriteFilterCoeff(band2_filter.b0, 0x55); - WriteFilterCoeff(band2_filter.b1, 0x58); - WriteFilterCoeff(band2_filter.b2, 0x5B); - WriteFilterCoeff(band2_filter.a1, 0x5E); - WriteFilterCoeff(band2_filter.a2, 0x61); - - // BAND3 - WriteFilterCoeff(band3_filter.b0, 0x64); - WriteFilterCoeff(band3_filter.b1, 0x67); - WriteFilterCoeff(band3_filter.b2, 0x6A); - WriteFilterCoeff(band3_filter.a1, 0x6D); - WriteFilterCoeff(band3_filter.a2, 0x70); - - // Enable 3-band filter - max98090_reg_dsp_biquadfilter_enable_t filter = {0}; - filter.eq3banden = 1; - i2cAddr.subAddress = MAX98090_REG_DSP_BIQUAD_FILTER_ENABLE; - i2c->Write(i2cAddr, (uint8_t *)&filter, 1); + SetupEarspeakerEqualizer(); } break; case bsp::AudioDevice::OutputPath::Loudspeaker: { + max98090_reg_playback_quick_setup_t q_playback_setup = {0}; q_playback_setup.dig2spk = 1; + i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP; + i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1); uint8_t mask = 0x08; // Set 3th bit (dmono on) i2cAddr.subAddress = MAX98090_REG_INOUT_PATH_CONF; i2c->Modify(i2cAddr, mask, true, 1); - // TODO: Turn off/mute right speaker + // Turn off right speaker path + max98090_reg_outputenable_t outputenable = {0}; + outputenable.dalen = 1; + outputenable.splen = 1; + i2cAddr.subAddress = MAX98090_REG_OUTPUT_ENABLE; + i2c->Write(i2cAddr, (uint8_t *)&outputenable, 1); + + SetupLoudspeakerEqualizer(); + } break; + + case bsp::AudioDevice::OutputPath::LoudspeakerMono: { + max98090_reg_playback_quick_setup_t q_playback_setup = {0}; + q_playback_setup.dig2spk = 1; i2cAddr.subAddress = MAX98090_REG_PLAYBACK_QUICK_SETUP; i2c->Write(i2cAddr, (uint8_t *)&q_playback_setup, 1); - qfilter_coefficients_t band1_filter = {0}; - qfilter_coefficients_t band2_filter = {0}; - qfilter_coefficients_t band3_filter = {0}; - - // Highpass,lowpass & flat filters don't use Gain parameter - qfilter_CalculateCoeffs(FilterHighPass, 500, currentParams.GetSampleRateVal(), 0.707, 1, &band1_filter); - qfilter_CalculateCoeffs(FilterFlat, 0, currentParams.GetSampleRateVal(), 0.707, 1, &band2_filter); - qfilter_CalculateCoeffs(FilterFlat, 0, currentParams.GetSampleRateVal(), 0.707, 1, &band3_filter); - - // BAND1 - WriteFilterCoeff(band1_filter.b0, 0x46); - WriteFilterCoeff(band1_filter.b1, 0x49); - WriteFilterCoeff(band1_filter.b2, 0x4C); - WriteFilterCoeff(band1_filter.a1, 0x4F); - WriteFilterCoeff(band1_filter.a2, 0x52); - - // BAND2 - WriteFilterCoeff(band2_filter.b0, 0x55); - WriteFilterCoeff(band2_filter.b1, 0x58); - WriteFilterCoeff(band2_filter.b2, 0x5B); - WriteFilterCoeff(band2_filter.a1, 0x5E); - WriteFilterCoeff(band2_filter.a2, 0x61); - - // BAND3 - WriteFilterCoeff(band3_filter.b0, 0x64); - WriteFilterCoeff(band3_filter.b1, 0x67); - WriteFilterCoeff(band3_filter.b2, 0x6A); - WriteFilterCoeff(band3_filter.a1, 0x6D); - WriteFilterCoeff(band3_filter.a2, 0x70); - - // Enable 3-band filter - max98090_reg_dsp_biquadfilter_enable_t filter = {0}; - filter.eq3banden = 1; - i2cAddr.subAddress = MAX98090_REG_DSP_BIQUAD_FILTER_ENABLE; - i2c->Write(i2cAddr, (uint8_t *)&filter, 1); + // Turn off right speaker path + max98090_reg_outputenable_t outputenable = {0}; + outputenable.dalen = 1; + outputenable.splen = 1; + i2cAddr.subAddress = MAX98090_REG_OUTPUT_ENABLE; + i2c->Write(i2cAddr, (uint8_t *)&outputenable, 1); + SetupLoudspeakerEqualizer(); } break; default: @@ -229,34 +180,16 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m) if (params.inputPath != bsp::AudioDevice::InputPath::None) { // Set input path switch (params.inputPath) { - case bsp::AudioDevice::InputPath::Headphones: { - /* max98090_reg_analog_to_record_quick_t q_analog_setup = {0}; - q_analog_setup.in34mic2 = 1; - bsp_i2c_Send(i2CInst,DeviceAddr, - MAX98090_REG_ANALOG_MIC_TO_RECORD_QUICK,(uint8_t*)&q_analog_setup,1); - - max98090_reg_radc_mix_input_t radcmix = {0}; - bsp_i2c_Send(i2CInst,DeviceAddr, MAX98090_REG_RADC_MIXER_INPUT,(uint8_t*)&radcmix); - - max98090_reg_ladc_mix_input_t ladcmix = {0}; - ladcmix.mixadl = 0x40; - bsp_i2c_Send(i2CInst,DeviceAddr, MAX98090_REG_LADC_MIXER_INPUT,(uint8_t*)&ladcmix); */ + case bsp::AudioDevice::InputPath::Headphones: { max98090_reg_input_to_record_quick_t q_input_setup = {0}; q_input_setup.in34dan = 1; i2cAddr.subAddress = MAX98090_REG_LINE_INPUT_TO_RECORD_QUICK; i2c->Write(i2cAddr, (uint8_t *)&q_input_setup, 1); - - uint8_t mask = 0x10; // Set 4th bit (mic bias enable) - i2cAddr.subAddress = MAX98090_REG_INPUT_ENABLE; - i2c->Modify(i2cAddr, mask, true, 1); - } break; case bsp::AudioDevice::InputPath::Microphone: { - max98090_reg_input_to_record_quick_t q_input_setup = {0}; - max98090_reg_analog_to_record_quick_t q_analog_setup = {0}; - max98090_reg_digmic_enable_t digena = {0}; + max98090_reg_digmic_enable_t digena = {0}; // Enable left and right digital mic interface digena.digmicl = 1; @@ -266,32 +199,18 @@ CodecRetCode CodecMAX98090::Start(const CodecParams ¶m) i2cAddr.subAddress = MAX98090_REG_DIG_MIC_ENABLE; i2c->Write(i2cAddr, (uint8_t *)&digena, 1); - - // It seems that for digital mics it doesn't matter if digitial or analog input is chosen - q_input_setup.in12sab = 1; - - i2cAddr.subAddress = MAX98090_REG_LINE_INPUT_TO_RECORD_QUICK; - i2c->Write(i2cAddr, (uint8_t *)&q_input_setup, 1); - - // q_analog_setup.in12mic1 = 1; - // bsp_i2c_Send(i2CInst,DeviceAddr, MAX98090_REG_ANALOG_MIC_TO_RECORD_QUICK,(uint8_t*)&q_analog_setup,1); - - uint8_t mask = 0x10; // Clr 4th bit (mic bias disable) - i2cAddr.subAddress = MAX98090_REG_INPUT_ENABLE; - i2c->Modify(i2cAddr, mask, false, 1); - } break; default: return CodecRetCode::InvalidInputPath; } - - // Turn on DC blocking filters - uint8_t mask = (1 << 6) | (1 << 5); // set 6th and 7th bit (AHPF and DHPF) - i2cAddr.subAddress = MAX98090_REG_PLAYBACK_DSP_FILTER_CONF; - i2c->Modify(i2cAddr, mask, true, 1); } + // Turn on DC blocking filters + uint8_t mask = (1 << 6) | (1 << 5); // set 6th and 7th bit (AHPF and DHPF) + i2cAddr.subAddress = MAX98090_REG_PLAYBACK_DSP_FILTER_CONF; + i2c->Modify(i2cAddr, mask, true, 1); + // Store param configuration currentParams = params; @@ -417,7 +336,8 @@ CodecRetCode CodecMAX98090::SetOutputVolume(const float vol) i2c->Write(i2cAddr, (uint8_t *)&vol, 1); } break; - case bsp::AudioDevice::OutputPath::Loudspeaker: { + case bsp::AudioDevice::OutputPath::Loudspeaker: + case bsp::AudioDevice::OutputPath::LoudspeakerMono: { // Scale input volume(range 0 - 100) to MAX98090 range(decibels hardcoded as specific hex values) constexpr float scale_factor = .39f * 10.f; uint8_t volume = static_cast(vol * scale_factor) + 0x18; @@ -515,6 +435,88 @@ CodecRetCode CodecMAX98090::MicBias(const bool enable) return CodecRetCode::Success; } +CodecRetCode CodecMAX98090::SetupEarspeakerEqualizer() +{ + qfilter_coefficients_t band1_filter = {0}; + qfilter_coefficients_t band2_filter = {0}; + qfilter_coefficients_t band3_filter = {0}; + + // Highpass,lowpass & flat filters don't use Gain parameter + qfilter_CalculateCoeffs(FilterHighPass, 800, currentParams.GetSampleRateVal(), 0.707, 1, &band1_filter); + qfilter_CalculateCoeffs(FilterLowPass, 6000, currentParams.GetSampleRateVal(), 0.707, 1, &band2_filter); + qfilter_CalculateCoeffs(FilterFlat, 0, currentParams.GetSampleRateVal(), 0.707, 1, &band3_filter); + + // BAND1 + WriteFilterCoeff(band1_filter.b0, 0x46); + WriteFilterCoeff(band1_filter.b1, 0x49); + WriteFilterCoeff(band1_filter.b2, 0x4C); + WriteFilterCoeff(band1_filter.a1, 0x4F); + WriteFilterCoeff(band1_filter.a2, 0x52); + + // BAND2 + WriteFilterCoeff(band2_filter.b0, 0x55); + WriteFilterCoeff(band2_filter.b1, 0x58); + WriteFilterCoeff(band2_filter.b2, 0x5B); + WriteFilterCoeff(band2_filter.a1, 0x5E); + WriteFilterCoeff(band2_filter.a2, 0x61); + + // BAND3 + WriteFilterCoeff(band3_filter.b0, 0x64); + WriteFilterCoeff(band3_filter.b1, 0x67); + WriteFilterCoeff(band3_filter.b2, 0x6A); + WriteFilterCoeff(band3_filter.a1, 0x6D); + WriteFilterCoeff(band3_filter.a2, 0x70); + + // Enable 3-band filter + max98090_reg_dsp_biquadfilter_enable_t filter = {0}; + filter.eq3banden = 1; + i2cAddr.subAddress = MAX98090_REG_DSP_BIQUAD_FILTER_ENABLE; + i2c->Write(i2cAddr, (uint8_t *)&filter, 1); + + return CodecRetCode::Success; +} + +CodecRetCode CodecMAX98090::SetupLoudspeakerEqualizer() +{ + qfilter_coefficients_t band1_filter = {0}; + qfilter_coefficients_t band2_filter = {0}; + qfilter_coefficients_t band3_filter = {0}; + + // Highpass,lowpass & flat filters don't use Gain parameter + qfilter_CalculateCoeffs(FilterHighPass, 500, currentParams.GetSampleRateVal(), 0.707, 1, &band1_filter); + qfilter_CalculateCoeffs(FilterFlat, 0, currentParams.GetSampleRateVal(), 0.707, 1, &band2_filter); + qfilter_CalculateCoeffs(FilterFlat, 0, currentParams.GetSampleRateVal(), 0.707, 1, &band3_filter); + + // BAND1 + WriteFilterCoeff(band1_filter.b0, 0x46); + WriteFilterCoeff(band1_filter.b1, 0x49); + WriteFilterCoeff(band1_filter.b2, 0x4C); + WriteFilterCoeff(band1_filter.a1, 0x4F); + WriteFilterCoeff(band1_filter.a2, 0x52); + + // BAND2 + WriteFilterCoeff(band2_filter.b0, 0x55); + WriteFilterCoeff(band2_filter.b1, 0x58); + WriteFilterCoeff(band2_filter.b2, 0x5B); + WriteFilterCoeff(band2_filter.a1, 0x5E); + WriteFilterCoeff(band2_filter.a2, 0x61); + + // BAND3 + WriteFilterCoeff(band3_filter.b0, 0x64); + WriteFilterCoeff(band3_filter.b1, 0x67); + WriteFilterCoeff(band3_filter.b2, 0x6A); + WriteFilterCoeff(band3_filter.a1, 0x6D); + WriteFilterCoeff(band3_filter.a2, 0x70); + + // Enable 3-band filter + max98090_reg_dsp_biquadfilter_enable_t filter = {0}; + filter.eq3banden = 1; + i2cAddr.subAddress = MAX98090_REG_DSP_BIQUAD_FILTER_ENABLE; + i2c->Write(i2cAddr, (uint8_t *)&filter, 1); + + return CodecRetCode::Success; +} + CodecRetCode CodecMAX98090::Reset() { diff --git a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp index fb078e623435f28ecfc6a7afef78738fe83dc365..cd3df45d8299b18d9b921846b0b1d9fe8ba3ca8d 100644 --- a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp +++ b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp @@ -120,6 +120,8 @@ class CodecMAX98090 : public Codec CodecRetCode SetInputPath(const bsp::AudioDevice::InputPath path); CodecRetCode SetOutputPath(const bsp::AudioDevice::OutputPath path); CodecRetCode MicBias(const bool enable); + CodecRetCode SetupEarspeakerEqualizer(); + CodecRetCode SetupLoudspeakerEqualizer(); CodecRetCode WriteFilterCoeff(const float coeff, const uint8_t basereg); CodecRetCode Reset(); }; diff --git a/module-bsp/board/rt1051/bsp/audio/max98090_regs.hpp b/module-bsp/board/rt1051/bsp/audio/max98090_regs.hpp index 9baa367cf63a7303603f5faff6e4513cc380378d..66e9878a4522ac230ab57cf041ece2117b0b6d06 100644 --- a/module-bsp/board/rt1051/bsp/audio/max98090_regs.hpp +++ b/module-bsp/board/rt1051/bsp/audio/max98090_regs.hpp @@ -37,7 +37,7 @@ typedef struct // Device Status Interrupt Mask Register // Check Table 86. for more info. -#define MAX98090_REG_DEVICE_STATUS_MASK 0x01 +#define MAX98090_REG_DEVICE_STATUS_MASK 0x03 typedef struct { uint8_t idrcclp : 1; @@ -74,24 +74,25 @@ typedef struct #define MAX98090_REG_OUTPUT_ENABLE 0x3F typedef struct { - uint8_t hpren : 1; - uint8_t hplen : 1; - uint8_t spren : 1; - uint8_t splen : 1; - uint8_t rcvlen : 1; - uint8_t rcvren : 1; - uint8_t daren : 1; uint8_t dalen : 1; + uint8_t daren : 1; + uint8_t rcvren : 1; + uint8_t rcvlen : 1; + uint8_t splen : 1; + uint8_t spren : 1; + uint8_t hplen : 1; + uint8_t hpren : 1; } max98090_reg_outputenable_t; -// Output enable register -#define MAX98090_REG_DAC_HP_PERF 0x43 +// Line Input Level Configuration Register +#define MAX98090_REG_LINE_INPUT_LEVEL_CONF 0x0E typedef struct { - uint8_t dachp : 1; - uint8_t perfmode : 1; - uint8_t unused : 6; -} max98090_reg_dac_hp_perf_t; + uint8_t linbpga : 3; + uint8_t linapga : 3; + uint8_t mixg246 : 1; + uint8_t mixg135 : 1; +} max98090_reg_line_inp_lvl_t; // Microphone 1 enable and level configuration register #define MAX98090_REG_MIC1_ENABLE_LEVEL_CONF 0x10 @@ -99,6 +100,7 @@ typedef struct { uint8_t pgam : 5; uint8_t pa1en : 2; + uint8_t unused : 1; } max98090_reg_mic1ena_lvlctl_t; // Microphone 2 enable and level configuration register @@ -107,6 +109,7 @@ typedef struct { uint8_t pgam : 5; uint8_t pa2en : 2; + uint8_t unused : 1; } max98090_reg_mic2ena_lvlctl_t; // Microphone Bias Level Configuration Register @@ -125,7 +128,7 @@ typedef struct uint8_t digmicl : 1; uint8_t digmicr : 1; uint8_t unused : 2; - uint8_t dmicclk : 2; + uint8_t dmicclk : 3; uint8_t unused2 : 1; } max98090_reg_digmic_enable_t; @@ -154,6 +157,7 @@ typedef struct typedef struct { uint8_t mixadl : 7; + uint8_t unused : 1; } max98090_reg_ladc_mix_input_t; /* Right ADC Mixer Input Configuration Register @@ -169,6 +173,7 @@ typedef struct typedef struct { uint8_t mixadr : 7; + uint8_t unused : 1; } max98090_reg_radc_mix_input_t; /* Left Record Path Digital Gain Configuration Register @@ -193,46 +198,6 @@ typedef struct uint8_t unused : 1; } max98090_reg_rrec_dig_gain_t; -// Record DSP Filter Configuration Register -#define MAX98090_REG_REC_DSP_FILTER_CONF 0x14 -typedef struct -{ - - uint8_t unused : 4; - - /* - Enables the DAC High Sample Rate Mode (LRCLK > 48kHz, FIR Only) - 0: LRCLK is less than 48kHz. 8x FIR interpolation filter used. - 1: LRCLK is greater than 48kHz. 4x FIR interpolation filter used. - */ - uint8_t dhf : 1; - - /* - Enables the Playback Path DC-Blocking Filter - 0: DC-blocking filter disabled. - 1: DC-blocking filter enabled - */ - uint8_t dhpf : 1; - - /* - Enables the Record Path DC-Blocking Filter - 0: DC-blocking filter disabled. - 1: DC-blocking filter enabled. - */ - uint8_t ahpf : 1; - - /* - Enables the Codec DSP FIR Music Filters (Default IIR Voice Filters) - 0: The codec DSP filters operate in IIR voice mode with stop band frequencies below - the fS/2 Nyquist rate. The voice mode filters are optimized for 8kHz or 16kHz voice - application use. - 1: The codec DSP filters operate in a linear phase FIR audio mode optimized to - maintain stereo imaging and operate at higher fS rates while utilizing lower power - */ - uint8_t mode : 1; - -} max98090_reg_rec_dspfilter_conf_t; - // System Master Clock (MCLK) Prescaler Configuration Register // Check MAX98090 datasheet Table 34 for available configurations #define MAX98090_REG_SYSTEM_MASTER_CLOCK 0x1B @@ -260,7 +225,7 @@ typedef struct #define MAX98090_REG_CLOCK_MODE 0x1C typedef struct { - uint8_t usemi : 4; + uint8_t usemi : 1; uint8_t unused : 3; uint8_t freq : 4; } max98090_reg_clock_mode_t; @@ -270,7 +235,8 @@ typedef struct #define MAX98090_REG_NI_MSB 0x1D typedef struct { - uint8_t ni; + uint8_t ni : 7; + uint8_t unused : 1; } max98090_reg_manual_clock_ratio_NI_MSB_t; // Manual Clock Ratio Configuration Register (NI LSB) @@ -405,7 +371,6 @@ typedef struct uint8_t dhpf : 1; uint8_t ahpf : 1; uint8_t mode : 1; - } max98090_reg_playback_dspfilter_conf_t; // Master Clock Quick Setup Register @@ -501,8 +466,8 @@ typedef struct #define MAX98090_REG_LHP_VOL_CTRL 0x2C typedef struct { - uint8_t hpvoll : 6; - uint8_t unused : 1; + uint8_t hpvoll : 5; + uint8_t unused : 2; uint8_t hplm : 1; } max98090_reg_lhp_vol_ctrl_t; @@ -512,8 +477,8 @@ typedef struct #define MAX98090_REG_RHP_VOL_CTRL 0x2D typedef struct { - uint8_t hpvolr : 6; - uint8_t unused : 1; + uint8_t hpvolr : 5; + uint8_t unused : 2; uint8_t hprm : 1; } max98090_reg_rhp_vol_ctrl_t; @@ -545,8 +510,8 @@ typedef struct #define MAX98090_REG_RECV_VOL_CTRL 0x39 typedef struct { - uint8_t rcvlvol : 6; - uint8_t unused : 1; + uint8_t rcvlvol : 5; + uint8_t unused : 2; uint8_t rcvlm : 1; } max98090_reg_recv_vol_ctrl_t; @@ -581,7 +546,6 @@ typedef struct uint8_t adcdither : 1; uint8_t osr128 : 1; uint8_t unused : 5; - } max98090_reg_adcperf_mode_t; #define MAX98090_I2C_ADDR 0x10 diff --git a/module-bsp/board/rt1051/bsp/headset/headset.cpp b/module-bsp/board/rt1051/bsp/headset/headset.cpp index 78b8e23a49a6de05305e04f1488afab0b2082dff..0808a470c830978162c92a5f97f4e6e2f5a5d5d0 100644 --- a/module-bsp/board/rt1051/bsp/headset/headset.cpp +++ b/module-bsp/board/rt1051/bsp/headset/headset.cpp @@ -5,6 +5,7 @@ #include "BoardDefinitions.hpp" #include "DriverI2C.hpp" +#include "DriverGPIO.hpp" #include "fsl_common.h" #include "timers.h" @@ -32,9 +33,10 @@ namespace bsp static constexpr uint8_t HEADSET_DEV_SET_DET_EN = 1 << 5; static constexpr uint8_t HEADSET_DEV_SET_DEB_1S = 0x06; - static constexpr uint16_t HEADSET_POLL_INTERVAL_MS = 500; + static constexpr uint16_t HEADSET_POLL_INTERVAL_MS = 2500; static std::shared_ptr i2c; + static std::shared_ptr gpio; static drivers::I2CAddress i2cAddr = {.deviceAddress = HEADSET_I2C_ADDR, .subAddressSize = 0x01}; static TimerHandle_t timerHandle; @@ -55,12 +57,27 @@ namespace bsp if (((reg & 0x08) == 0) && (HeadsetInserted == true)) { HeadsetInserted = false; LOG_INFO("Headset removed"); + gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0); + ret = true; } if (((reg & 0x08) != 0) && (HeadsetInserted == false)) { HeadsetInserted = true; LOG_INFO("Headset inserted"); + + if ((reg & 0x01) != 0) { + LOG_INFO("Headset 3-pole detected"); + gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0); + } + if ((reg & 0x02) != 0) { + LOG_INFO("Headset 4-pole OMTP detected"); + gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 1); + } + if ((reg & 0x04) != 0) { + LOG_INFO("Headset 4-pole Standard detected"); + gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 1); + } ret = true; } @@ -81,8 +98,20 @@ namespace bsp static_cast(BoardDefinitions::HEADSET_I2C), DriverI2CParams{.baudrate = static_cast(BoardDefinitions::HEADSET_I2C_BAUDRATE)}); + gpio = DriverGPIO::Create(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_GPIO), + DriverGPIOParams{}); + + gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, + .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, + .defLogic = 0, + .pin = static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN)}); + qHandleIrq = qHandle; + HeadsetInserted = false; + + gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0); + uint8_t reg = HEADSET_INT_DIS_INT_ENA | HEADSET_INT_DIS_ADC_ENA | HEADSET_INT_DIS_DC_ENA | HEADSET_INT_DIS_INS_ENA; i2cAddr.subAddress = HEADSET_INT_DIS_ADDR; @@ -101,7 +130,7 @@ namespace bsp } } - xTimerStart(timerHandle, 0); + xTimerStart(timerHandle, HEADSET_POLL_INTERVAL_MS); return kStatus_Success; } @@ -122,10 +151,13 @@ namespace bsp status_t Deinit() { - qHandleIrq = nullptr; + qHandleIrq = nullptr; + HeadsetInserted = false; i2c.reset(); + gpio->WritePin(static_cast(BoardDefinitions::MIC_BIAS_DRIVER_EN), 0); + return kStatus_Success; } } // namespace headset diff --git a/module-bsp/board/rt1051/common/board.h b/module-bsp/board/rt1051/common/board.h index d47d17c10fac0ece92d68bbb8aa78f1f2be8b427..044712e8e9f6ce9f9979d06a7073c5b4da5b81f3 100644 --- a/module-bsp/board/rt1051/common/board.h +++ b/module-bsp/board/rt1051/common/board.h @@ -189,8 +189,8 @@ #define BSP_CELLULAR_AP_RDY_PAD GPIO_B1_00 #define BSP_CELLULAR_WAKEUP_PORT GPIO2 -#define BSP_CELLULAR_WAKEUP_PIN 19 -#define BSP_CELLULAR_WAKEUP_PAD GPIO_B1_03 +#define BSP_CELLULAR_WAKEUP_PIN 22 +#define BSP_CELLULAR_WAKEUP_PAD GPIO_B1_06 #define BSP_CELLULAR_SIM_TRAY_INSERTED_PORT GPIO2 #define BSP_CELLULAR_SIM_TRAY_INSERTED_PIN 11 @@ -294,6 +294,12 @@ #define BOARD_JACKDET_IRQ_GPIO GPIO2 #define BOARD_JACKDET_IRQ_GPIO_PIN (30U) +/** + * MICROPHONE BIAS DEFINITIONS + */ +#define BOARD_MIC_LDO_EN_GPIO GPIO2 +#define BOARD_MIC_LDO_EN_PIN 19 + #define DMA_MAX_SINGLE_TRANSACTION_PAYLOAD 32767 /** diff --git a/module-bsp/board/rt1051/common/pin_mux.c b/module-bsp/board/rt1051/common/pin_mux.c index 0c7c891e4d311d4336a3cf416c02e28855d93de2..bae9bf424fcdde892966d9ad4b9a79982f8c80c7 100644 --- a/module-bsp/board/rt1051/common/pin_mux.c +++ b/module-bsp/board/rt1051/common/pin_mux.c @@ -305,7 +305,7 @@ void PINMUX_InitBootPins(void) PINMUX_InitBatteryCharger(); PINMUX_InitALS(); PINMUX_InitPowerSW(); - PINMUX_InitJACKDET(); + PINMUX_InitHeadset(); PINMUX_InitVibrator(); PINMUX_InitTorch(); PINMUX_InitMagnetometer(); @@ -1381,7 +1381,7 @@ void PINMUX_InitBluetoothPins(void) PAD_CONFIG_HYSTERESIS_DISABLED); } -void PINMUX_InitJACKDET(void) +void PINMUX_InitHeadset(void) { CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */ @@ -1390,6 +1390,11 @@ void PINMUX_InitJACKDET(void) IOMUXC_SetPinConfig(PINMUX_JACKDET_IRQ, /* GPIO_AD_B0_02 PAD functional properties : */ PAD_CONFIG_PULL_UP_100kOhm | PAD_CONFIG_SELECT_PULL | PAD_CONFIG_PULL_KEEPER_ENABLED); + + IOMUXC_SetPinMux(PINMUX_MIC_LDO_EN, 1); + IOMUXC_SetPinConfig(PINMUX_MIC_LDO_EN, + PAD_CONFIG_PULL_UP_22kOhm | PAD_CONFIG_SELECT_PULL | PAD_CONFIG_PULL_KEEPER_DISABLED | + PAD_CONFIG_DRIVER_STRENGTH_LVL_4 | PAD_CONFIG_SLEW_RATE_SLOW | PAD_CONFIG_SPEED_SLOW_50MHz); } void PINMUX_InitBatteryCharger(void) diff --git a/module-bsp/board/rt1051/common/pin_mux.h b/module-bsp/board/rt1051/common/pin_mux.h index 2cfe69f225748c0ad2922077687273de08d05fcd..50c5b59bb918f512182cd9a35ac532d83aa566d4 100644 --- a/module-bsp/board/rt1051/common/pin_mux.h +++ b/module-bsp/board/rt1051/common/pin_mux.h @@ -183,10 +183,11 @@ extern "C" void PINMUX_InitLEDDRIVER(void); /** - * JACK DETECTION PINMUX DEFINITIONS + * HEADSET (JACK DETECTION, MIC BIAS) PINMUX DEFINITIONS */ #define PINMUX_JACKDET_IRQ IOMUXC_GPIO_B1_14_GPIO2_IO30 - void PINMUX_InitJACKDET(void); +#define PINMUX_MIC_LDO_EN IOMUXC_GPIO_B1_03_GPIO2_IO19 + void PINMUX_InitHeadset(void); /** * BATTERY CHARGER PINMUX DEFINITIONS diff --git a/module-bsp/bsp/audio/bsp_audio.hpp b/module-bsp/bsp/audio/bsp_audio.hpp index 7bfe4c76d2d11c34f60c3d29b1e0f506f0a54011..9a35fe735264c1ceaf3a23fd04e03521b5cf23fc 100755 --- a/module-bsp/bsp/audio/bsp_audio.hpp +++ b/module-bsp/bsp/audio/bsp_audio.hpp @@ -33,6 +33,7 @@ namespace bsp { HeadphonesMono, Earspeaker, Loudspeaker, + LoudspeakerMono, BluetoothA2DP, BluetoothHSP, None diff --git a/module-services/service-audio/ServiceAudio.cpp b/module-services/service-audio/ServiceAudio.cpp index 9a293bfb8ad0822e6961bea1952b867126f9a841..297943ea1160919ec7b86aeb5abd552b618b3480 100644 --- a/module-services/service-audio/ServiceAudio.cpp +++ b/module-services/service-audio/ServiceAudio.cpp @@ -69,7 +69,7 @@ sys::ReturnCodes ServiceAudio::InitHandler() // ROUTING {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP), "20"}, {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker), "20"}, - {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "20"}, + {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "0"}, {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker), "20"}, {dbPath(Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones), "50"},