From f1c49a60e5912c07d741d71194d6223783e22303 Mon Sep 17 00:00:00 2001 From: Lefucjusz Date: Mon, 14 Aug 2023 13:58:11 +0200 Subject: [PATCH] [MOS-1018] ServiceAudio power management optimizations Optimized power management strategy used by ServiceAudio: * changed minimum CPU frequency from 528MHz to 264MHz; * added switching to 24MHz when operation active, but paused; * minor cleanup in several places. --- module-bsp/board/rt1051/CMakeLists.txt | 1 + module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp | 35 +++ module-bsp/board/rt1051/bsp/lpm/Bandgap.hpp | 10 + .../board/rt1051/drivers/RT1051DriverPLL.cpp | 84 +++--- .../board/rt1051/drivers/RT1051DriverPLL.hpp | 9 +- .../board/rt1051/drivers/RT1051DriverPLL2.cpp | 28 +- .../service-audio/ServiceAudio.cpp | 269 ++++++++++-------- .../include/service-audio/ServiceAudio.hpp | 10 +- pure_changelog.md | 1 + 9 files changed, 254 insertions(+), 193 deletions(-) create mode 100644 module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp create mode 100644 module-bsp/board/rt1051/bsp/lpm/Bandgap.hpp diff --git a/module-bsp/board/rt1051/CMakeLists.txt b/module-bsp/board/rt1051/CMakeLists.txt index e88f43e122ab0b7fd30f5236c705134eec954b34..2b62c5597f5a1b2c73e1da92b0c08401d7fc0977 100644 --- a/module-bsp/board/rt1051/CMakeLists.txt +++ b/module-bsp/board/rt1051/CMakeLists.txt @@ -27,6 +27,7 @@ target_sources(module-bsp bsp/lpm/CpuFreqLPM.cpp bsp/lpm/Oscillator.cpp bsp/lpm/RT1051LPMCommon.cpp + bsp/lpm/Bandgap.cpp bsp/magnetometer/ALS31300.cpp bsp/pit/pit.cpp bsp/trng/trng.cpp diff --git a/module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp b/module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6c465a2c8548c386a99f1b92f49b7afb7201278 --- /dev/null +++ b/module-bsp/board/rt1051/bsp/lpm/Bandgap.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "Bandgap.hpp" +#include +#include + +namespace +{ + constexpr std::uint32_t REFTOP_LOWPOWER_MASK = (1U << 2); +} + +namespace bsp::bandgap +{ + void SwitchToRegularMode() + { + /* Enable regular bandgap and wait for it to stabilize */ + CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_REFTOP_PWD_MASK; + while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_REFTOP_VBGUP_MASK) == 0) {} + + /* Disable low power bandgap */ + XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; + PMU->MISC0_CLR = REFTOP_LOWPOWER_MASK; + } + + void SwitchToLowPowerMode() + { + /* Enable low power bandgap */ + PMU->MISC0_SET = REFTOP_LOWPOWER_MASK; + + /* Disable regular bandgap */ + XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; + PMU->MISC0_SET = CCM_ANALOG_MISC0_REFTOP_PWD_MASK; + } +} // namespace bsp::bandgap diff --git a/module-bsp/board/rt1051/bsp/lpm/Bandgap.hpp b/module-bsp/board/rt1051/bsp/lpm/Bandgap.hpp new file mode 100644 index 0000000000000000000000000000000000000000..73652e807fd4e0e51acceab0a2bce3f78101f78b --- /dev/null +++ b/module-bsp/board/rt1051/bsp/lpm/Bandgap.hpp @@ -0,0 +1,10 @@ +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +namespace bsp::bandgap +{ + void SwitchToRegularMode(); + void SwitchToLowPowerMode(); +} // namespace bsp::bandgap diff --git a/module-bsp/board/rt1051/drivers/RT1051DriverPLL.cpp b/module-bsp/board/rt1051/drivers/RT1051DriverPLL.cpp index 5e2ecdc8221ec05df9d2f1a028dc89ec104c0c0b..a298e4c517a5eb2cc5e1b72398f948429f3b9ff7 100644 --- a/module-bsp/board/rt1051/drivers/RT1051DriverPLL.cpp +++ b/module-bsp/board/rt1051/drivers/RT1051DriverPLL.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "RT1051DriverPLL.hpp" @@ -7,86 +7,100 @@ namespace drivers { - RT1051DriverPLL::RT1051DriverPLL(const drivers::PLLInstances &inst, const drivers::DriverPLLParams ¶ms) : DriverPLL(params), instance(inst) { - switch (instance) { - case PLLInstances::PLL4_Audio: { + case PLLInstances::PLL4_Audio: clkPLL4setup(CLK_ENABLE, - clock_audio_pll_config_t{.loopDivider = static_cast(params.loopDivider), - .postDivider = static_cast(params.postDivider), + clock_audio_pll_config_t{.loopDivider = static_cast(params.loopDivider), + .postDivider = static_cast(params.postDivider), .numerator = params.numerator, .denominator = params.denominator, - .src = static_cast(params.src)}); + .src = static_cast(params.src)}); name = "PLL4_Audio"; - } break; - case PLLInstances::PLL3: { + break; + + case PLLInstances::PLL3: clkPLL3setup(CLK_ENABLE); name = "PLL3"; - } break; - case PLLInstances::PLL3_PFD0: { + break; + + case PLLInstances::PLL3_PFD0: clkPLL3_PFD0setup(CLK_ENABLE); name = "PLL3_PFD0"; - } break; - case PLLInstances::PLL3_PFD1: { + break; + + case PLLInstances::PLL3_PFD1: clkPLL3_PFD1setup(CLK_ENABLE); name = "PLL3_PFD1"; - } break; - case PLLInstances::PLL3_PFD2: { + break; + + case PLLInstances::PLL3_PFD2: clkPLL3_PFD2setup(CLK_ENABLE); name = "PLL3_PFD2"; - } break; + break; + case PLLInstances::PLL2_PFD2: clkPLL2_PFD2setup(CLK_ENABLE); name = "PLL2_PFD2"; break; - case PLLInstances::PLL1_ARM: { + + case PLLInstances::PLL1_ARM: clkPLL1setup(CLK_ENABLE); name = "PLL1_ARM"; - } break; - case PLLInstances::OSC_24M: { + break; + + case PLLInstances::OSC_24M: // not used - } break; + break; + default: break; } + LOG_DEBUG("Init: %s", name.c_str()); } RT1051DriverPLL::~RT1051DriverPLL() { switch (instance) { - case PLLInstances::PLL4_Audio: { + case PLLInstances::PLL4_Audio: clkPLL4setup(CLK_DISABLE, {}); - } break; - case PLLInstances::PLL3: { + break; + + case PLLInstances::PLL3: clkPLL3setup(CLK_DISABLE); - } break; - case PLLInstances::PLL3_PFD0: { + break; + + case PLLInstances::PLL3_PFD0: clkPLL3_PFD0setup(CLK_DISABLE); - } break; - case PLLInstances::PLL3_PFD1: { + break; + + case PLLInstances::PLL3_PFD1: clkPLL3_PFD1setup(CLK_DISABLE); - } break; - case PLLInstances::PLL3_PFD2: { + break; + + case PLLInstances::PLL3_PFD2: clkPLL3_PFD2setup(CLK_DISABLE); - } break; + break; + case PLLInstances::PLL2_PFD2: clkPLL2_PFD2setup(CLK_DISABLE); break; - case PLLInstances::PLL1_ARM: { + + case PLLInstances::PLL1_ARM: clkPLL1setup(CLK_DISABLE); - } break; - case PLLInstances::OSC_24M: { + break; + + case PLLInstances::OSC_24M: // not used - } break; + break; + default: break; } LOG_DEBUG("Deinit: %s", name.c_str()); } - } // namespace drivers diff --git a/module-bsp/board/rt1051/drivers/RT1051DriverPLL.hpp b/module-bsp/board/rt1051/drivers/RT1051DriverPLL.hpp index 1689e1bf8dc4117f0f25ae2aca7148c8e487177c..85dc1abacdd12893343ca43a9c4dbdd4fadc6c57 100644 --- a/module-bsp/board/rt1051/drivers/RT1051DriverPLL.hpp +++ b/module-bsp/board/rt1051/drivers/RT1051DriverPLL.hpp @@ -1,15 +1,13 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#ifndef PUREPHONE_RT1051DRIVERPLL_HPP -#define PUREPHONE_RT1051DRIVERPLL_HPP +#pragma once #include "drivers/pll/DriverPLL.hpp" #include namespace drivers { - class RT1051DriverPLL : public DriverPLL { public: @@ -20,7 +18,4 @@ namespace drivers PLLInstances instance; std::string name; }; - } // namespace drivers - -#endif // PUREPHONE_RT1051DRIVERPLL_HPP diff --git a/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp b/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp index e3aede3e94027dc3f4aba7c81c9df9c6d5567e3d..df6df93d1a74e4b55cda3f0e2105effe2d5ebc89 100644 --- a/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp +++ b/module-bsp/board/rt1051/drivers/RT1051DriverPLL2.cpp @@ -3,29 +3,22 @@ #include "RT1051DriverPLL2.hpp" #include "board/rt1051/bsp/lpm/ClockState.hpp" +#include "board/rt1051/bsp/lpm/Bandgap.hpp" #include "board/rt1051/bsp/lpm/CpuFreqLPM.hpp" -#include "fsl_dcdc.h" +#include namespace drivers { - namespace constants - { - inline constexpr auto REFTOP_LOWPOWER_FLAG{0x00000004}; - } // namespace constants - RT1051DriverPLL2::RT1051DriverPLL2() noexcept { if (!IsPLL2Enabled()) { // Set VDD_SOC_IN to 1.15V required to safely start PLL2 DCDC_AdjustTargetVoltage(DCDC, bsp::VDDRun_1150_mV, bsp::VDDStandby_925_mV); - // Turn on regular band gap and wait for stable - CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_REFTOP_PWD_MASK; - // It is recommended to wait for stabilization (documentation Low Power AN12085) - while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_REFTOP_VBGUP_MASK) == 0) {} - // Low power band gap disable - XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; - PMU->MISC0_CLR = constants::REFTOP_LOWPOWER_FLAG; + // Switch to regular bandgap + bsp::bandgap::SwitchToRegularMode(); + + // Enable PLL2 clkPLL2setup(CLK_ENABLE); } } @@ -37,12 +30,11 @@ namespace drivers !bsp::IsClockEnabled(kCLOCK_Lpspi4) && !bsp::IsClockEnabled(kCLOCK_Usdhc1) && !bsp::IsClockEnabled(kCLOCK_Usdhc2)) { + // Disable PLL2 clkPLL2setup(CLK_DISABLE); - // disable regular band gap and enable low power band gap - PMU->MISC0_SET = constants::REFTOP_LOWPOWER_FLAG; - XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_LPBG_SEL_MASK; - PMU->MISC0_SET = CCM_ANALOG_MISC0_REFTOP_PWD_MASK; + // Switch to low power bandgap + bsp::bandgap::SwitchToLowPowerMode(); // After turning off PLL2 and with CPU @4MHZ VDD_SOC_IN can be set to 950mV DCDC_AdjustTargetVoltage(DCDC, bsp::VDDRun_950_mV, bsp::VDDStandby_925_mV); @@ -51,7 +43,7 @@ namespace drivers bool RT1051DriverPLL2::IsPLL2Enabled() const noexcept { - return !(CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_POWERDOWN_MASK); + return not static_cast(CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_POWERDOWN_MASK); } } // namespace drivers diff --git a/module-services/service-audio/ServiceAudio.cpp b/module-services/service-audio/ServiceAudio.cpp index db023b34148b67cada73c81f9f9c12eb7432ef6c..71cc9f751d72a3cce31489104732f7cbed4db8aa 100644 --- a/module-services/service-audio/ServiceAudio.cpp +++ b/module-services/service-audio/ServiceAudio.cpp @@ -22,87 +22,91 @@ using namespace audio; -static constexpr auto audioServiceStackSize = 1024 * 8; - -static constexpr auto defaultVolumeHigh = "10"; -static constexpr auto defaultVolumeMid = "7"; -static constexpr auto defaultVolumeLow = "5"; -static constexpr auto defaultVolumeMuted = "0"; -static constexpr auto defaultTrue = "1"; -static constexpr auto defaultFalse = "0"; -static constexpr auto defaultVibrationLevel = "5"; -static constexpr auto defaultCallRingtonePath = "assets/audio/ringtone/ringtone_drum_2.mp3"; -static constexpr auto defaultTextMessageRingtonePath = "assets/audio/sms/sms_drum_2.mp3"; -static constexpr auto defaultNotificationsPath = "assets/audio/alarm/alarm_hang_drum.mp3"; -static constexpr auto defaultKeypadSoundPath = "assets/audio/sms/sms_drum_2.mp3"; - -static constexpr std::initializer_list> cacheInitializer{ - - // PLAYBACK - {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones}, defaultVolumeLow}, - {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBluetoothA2DP}, defaultVolumeLow}, - {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker}, defaultVolumeHigh}, - - {DbPathElement{Setting::Volume, PlaybackType::System, Profile::Type::PlaybackHeadphones}, defaultVolumeLow}, - {DbPathElement{Setting::Volume, PlaybackType::System, Profile::Type::PlaybackBluetoothA2DP}, defaultVolumeLow}, - {DbPathElement{Setting::Volume, PlaybackType::System, Profile::Type::PlaybackLoudspeaker}, defaultVolumeHigh}, - - {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::Idle}, defaultVolumeLow}, - - {DbPathElement{Setting::IsSystemSound, PlaybackType::Notifications, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::IsSystemSound, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::IsSystemSound, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::IsSystemSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::IsSystemSound, PlaybackType::Meditation, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::IsSystemSound, PlaybackType::Alarm, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::IsSystemSound, PlaybackType::None, Profile::Type::Idle}, defaultFalse}, - {DbPathElement{Setting::IsSystemSound, PlaybackType::Multimedia, Profile::Type::Idle}, defaultFalse}, - - // ROUTING - {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP}, "20"}, - {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHFP}, "20"}, - - {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker}, "3"}, - {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker}, "10"}, - {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones}, "5"}, - - {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHSP}, defaultVolumeHigh}, - {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHFP}, defaultVolumeHigh}, - - {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingEarspeaker}, defaultVolumeMid}, - {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones}, defaultVolumeMid}, - {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingLoudspeaker}, defaultVolumeMid}, - - // RECORDING - {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RecordingBuiltInMic}, "200"}, - {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RecordingHeadphones}, "100"}, - {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RecordingBluetoothHSP}, "100"}, - - // MISC - {DbPathElement{Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle}, defaultFalse}, - {DbPathElement{Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultFalse}, - {DbPathElement{Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle}, defaultFalse}, - {DbPathElement{Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle}, defaultTrue}, - - {DbPathElement{Setting::VibrationLevel, PlaybackType::System, Profile::Type::Idle}, defaultVibrationLevel}, - - {DbPathElement{Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle}, defaultTrue}, - {DbPathElement{Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle}, defaultTrue}, - - {DbPathElement{Setting::Sound, PlaybackType::Notifications, Profile::Type::Idle}, defaultNotificationsPath}, - {DbPathElement{Setting::Sound, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultKeypadSoundPath}, - {DbPathElement{Setting::Sound, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultCallRingtonePath}, - {DbPathElement{Setting::Sound, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, - defaultTextMessageRingtonePath}, -}; +namespace +{ + constexpr auto audioServiceStackSize = 1024 * 8; + + constexpr auto defaultVolumeHigh = "10"; + constexpr auto defaultVolumeMid = "7"; + constexpr auto defaultVolumeLow = "5"; + constexpr auto defaultTrue = "1"; + constexpr auto defaultFalse = "0"; + constexpr auto defaultVibrationLevel = "5"; + constexpr auto defaultCallRingtonePath = "assets/audio/ringtone/ringtone_drum_2.mp3"; + constexpr auto defaultTextMessageRingtonePath = "assets/audio/sms/sms_drum_2.mp3"; + constexpr auto defaultNotificationsPath = "assets/audio/alarm/alarm_hang_drum.mp3"; + constexpr auto defaultKeypadSoundPath = "assets/audio/sms/sms_drum_2.mp3"; + + constexpr std::initializer_list> cacheInitializer{ + + // PLAYBACK + {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackHeadphones}, defaultVolumeLow}, + {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackBluetoothA2DP}, + defaultVolumeLow}, + {DbPathElement{Setting::Volume, PlaybackType::Multimedia, Profile::Type::PlaybackLoudspeaker}, + defaultVolumeHigh}, + + {DbPathElement{Setting::Volume, PlaybackType::System, Profile::Type::PlaybackHeadphones}, defaultVolumeLow}, + {DbPathElement{Setting::Volume, PlaybackType::System, Profile::Type::PlaybackBluetoothA2DP}, defaultVolumeLow}, + {DbPathElement{Setting::Volume, PlaybackType::System, Profile::Type::PlaybackLoudspeaker}, defaultVolumeHigh}, + + {DbPathElement{Setting::Volume, PlaybackType::Alarm, Profile::Type::Idle}, defaultVolumeLow}, + + {DbPathElement{Setting::IsSystemSound, PlaybackType::Notifications, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::IsSystemSound, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::IsSystemSound, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::IsSystemSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::IsSystemSound, PlaybackType::Meditation, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::IsSystemSound, PlaybackType::Alarm, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::IsSystemSound, PlaybackType::None, Profile::Type::Idle}, defaultFalse}, + {DbPathElement{Setting::IsSystemSound, PlaybackType::Multimedia, Profile::Type::Idle}, defaultFalse}, + + // ROUTING + {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHSP}, "20"}, + {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingBluetoothHFP}, "20"}, + + {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker}, "3"}, + {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker}, "10"}, + {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones}, "5"}, + + {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHSP}, defaultVolumeHigh}, + {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHFP}, defaultVolumeHigh}, + + {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingEarspeaker}, defaultVolumeMid}, + {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingHeadphones}, defaultVolumeMid}, + {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingLoudspeaker}, defaultVolumeMid}, + + // RECORDING + {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RecordingBuiltInMic}, "200"}, + {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RecordingHeadphones}, "100"}, + {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RecordingBluetoothHSP}, "100"}, + + // MISC + {DbPathElement{Setting::EnableVibration, PlaybackType::Multimedia, Profile::Type::Idle}, defaultFalse}, + {DbPathElement{Setting::EnableVibration, PlaybackType::Notifications, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableVibration, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultFalse}, + {DbPathElement{Setting::EnableVibration, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableVibration, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableVibration, PlaybackType::Meditation, Profile::Type::Idle}, defaultFalse}, + {DbPathElement{Setting::EnableVibration, PlaybackType::Alarm, Profile::Type::Idle}, defaultTrue}, + + {DbPathElement{Setting::VibrationLevel, PlaybackType::System, Profile::Type::Idle}, defaultVibrationLevel}, + + {DbPathElement{Setting::EnableSound, PlaybackType::Multimedia, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableSound, PlaybackType::Notifications, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableSound, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableSound, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableSound, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableSound, PlaybackType::Meditation, Profile::Type::Idle}, defaultTrue}, + {DbPathElement{Setting::EnableSound, PlaybackType::Alarm, Profile::Type::Idle}, defaultTrue}, + + {DbPathElement{Setting::Sound, PlaybackType::Notifications, Profile::Type::Idle}, defaultNotificationsPath}, + {DbPathElement{Setting::Sound, PlaybackType::KeypadSound, Profile::Type::Idle}, defaultKeypadSoundPath}, + {DbPathElement{Setting::Sound, PlaybackType::CallRingtone, Profile::Type::Idle}, defaultCallRingtonePath}, + {DbPathElement{Setting::Sound, PlaybackType::TextMessageRingtone, Profile::Type::Idle}, + defaultTextMessageRingtonePath}, + }; +} // namespace ServiceAudio::ServiceAudio() : sys::Service(service::name::audio, "", audioServiceStackSize, sys::ServicePriority::Idle), @@ -145,7 +149,7 @@ sys::ReturnCodes ServiceAudio::InitHandler() for (const auto &setting : settingsCache) { settingsProvider->registerValueChange( - setting.first, [this](const std::string &name, std::string value) { settingsChanged(name, value); }); + setting.first, [this](const std::string &name, const std::string &value) { settingsChanged(name, value); }); } return sys::ReturnCodes::Success; @@ -172,12 +176,12 @@ std::optional ServiceAudio::AudioServicesCallback(const sys::Messag } else if (const auto *dbReq = dynamic_cast(msg); dbReq) { - auto selectedPlayback = generatePlayback(dbReq->playback, dbReq->setting); - auto selectedProfile = generateProfile(dbReq->profile, dbReq->playback); + const auto selectedPlayback = generatePlayback(dbReq->playback, dbReq->setting); + const auto selectedProfile = generateProfile(dbReq->profile, dbReq->playback); - std::string path = dbPath(dbReq->setting, selectedPlayback, selectedProfile); + const auto &path = dbPath(dbReq->setting, selectedPlayback, selectedProfile); LOG_DEBUG("ServiceAudio::DBbCallback(%s)", path.c_str()); - auto settings_it = settingsCache.find(path); + const auto settings_it = settingsCache.find(path); if (settingsCache.end() == settings_it) { LOG_DEBUG("%s does not exist in cache", path.c_str()); @@ -232,14 +236,14 @@ constexpr bool ServiceAudio::ShouldLoop(const std::optional bool ServiceAudio::IsVibrationEnabled(const audio::PlaybackType &type) { - auto isEnabled = + const auto isEnabled = utils::getNumericValue(getSetting(Setting::EnableVibration, Profile::Type::Idle, type)); return isEnabled; } bool ServiceAudio::IsSystemSound(const audio::PlaybackType &type) { - auto isSystemSound = + const auto isSystemSound = utils::getNumericValue(getSetting(Setting::IsSystemSound, Profile::Type::Idle, type)); return isSystemSound; } @@ -266,7 +270,8 @@ bool ServiceAudio::IsOperationEnabled(const audio::PlaybackType &plType, const O if (opType == Operation::Type::Router || opType == Operation::Type::Recorder) { return true; } - auto isEnabled = + + const auto isEnabled = utils::getNumericValue(getSetting(Setting::EnableSound, Profile::Type::Idle, plType)); return isEnabled; } @@ -279,7 +284,7 @@ std::string ServiceAudio::GetSound(const audio::PlaybackType &plType) ServiceAudio::VibrationType ServiceAudio::GetVibrationType(const audio::PlaybackType &type) { auto isOnVibrationMap = [&](auto vibrationType, auto playbackType) { - auto continuousVibrations = vibrationMap[vibrationType]; + const auto &continuousVibrations = vibrationMap[vibrationType]; return std::any_of(continuousVibrations.begin(), continuousVibrations.end(), [type](const auto &playBackType) { return playBackType == type; @@ -289,11 +294,10 @@ ServiceAudio::VibrationType ServiceAudio::GetVibrationType(const audio::Playback if (!IsVibrationEnabled(type)) { return VibrationType::None; } - if (isOnVibrationMap(VibrationType::Continuous, type)) { return VibrationType::Continuous; } - else if (isOnVibrationMap(VibrationType::OneShot, type)) { + if (isOnVibrationMap(VibrationType::OneShot, type)) { return VibrationType::OneShot; } return VibrationType::None; @@ -301,11 +305,11 @@ ServiceAudio::VibrationType ServiceAudio::GetVibrationType(const audio::Playback void ServiceAudio::VibrationUpdate(const audio::PlaybackType &type, std::optional input) { - auto vibrationLevel = utils::getNumericValue( + const auto vibrationLevel = utils::getNumericValue( getSetting(Setting::VibrationLevel, Profile::Type::Idle, PlaybackType::System)); EventManagerServiceAPI::setVibrationLevel(this, vibrationLevel); - auto curVibrationType = GetVibrationType(type); + const auto curVibrationType = GetVibrationType(type); LOG_DEBUG("Current vibration type: %s", magic_enum::enum_name(curVibrationType).data()); switch (curVibrationType) { case VibrationType::None: @@ -344,8 +348,8 @@ void ServiceAudio::EnableContinuousVibration(std::optionalEnableVibration(); } - auto &inputs = audioMux.GetAllInputs(); - auto anyOfInputsOn = std::any_of(inputs.cbegin(), inputs.cend(), [](auto &i) { + const auto &inputs = audioMux.GetAllInputs(); + const auto anyOfInputsOn = std::any_of(inputs.cbegin(), inputs.cend(), [](auto &i) { return i.GetVibrationStatus() == AudioMux::VibrationStatus::On; }); if (anyOfInputsOn && !IsVibrationMotorOn()) { @@ -356,7 +360,7 @@ void ServiceAudio::EnableContinuousVibration(std::optional ServiceAudio::HandlePause(const Token &token) { - auto input = audioMux.GetInput(token); + const auto input = audioMux.GetInput(token); return HandlePause(input); } @@ -438,13 +442,13 @@ std::unique_ptr ServiceAudio::HandleStart(const Operation: AudioStart(input); return std::make_unique(retCode, retToken); } - else if (opType == Operation::Type::Recorder) { - auto input = audioMux.GetIdleInput(); + if (opType == Operation::Type::Recorder) { + const auto input = audioMux.GetIdleInput(); AudioStart(input); return std::make_unique(retCode, retToken); } - else if (opType == Operation::Type::Router) { - auto input = audioMux.GetRoutingInput(true); + if (opType == Operation::Type::Router) { + const auto input = audioMux.GetRoutingInput(true); AudioStart(input); return std::make_unique(retCode, retToken); } @@ -464,10 +468,10 @@ std::unique_ptr ServiceAudio::HandleSendEvent(std::shared_ handleMultimediaAudioPause(); } - const auto playbacksToBeStopped = std::vector{audio::PlaybackType::Alarm, - audio::PlaybackType::Meditation, - audio::PlaybackType::Notifications, - audio::PlaybackType::TextMessageRingtone}; + const auto &playbacksToBeStopped = std::vector{audio::PlaybackType::Alarm, + audio::PlaybackType::Meditation, + audio::PlaybackType::Notifications, + audio::PlaybackType::TextMessageRingtone}; HandleStop(playbacksToBeStopped, audio::Token()); } break; @@ -505,7 +509,7 @@ std::unique_ptr ServiceAudio::HandleStop(const std::vector std::vector> retCodes; // stop by token - if (auto tokenInput = audioMux.GetInput(token); token.IsValid() && tokenInput) { + if (const auto tokenInput = audioMux.GetInput(token); token.IsValid() && tokenInput) { retCodes.emplace_back(std::make_pair(token, StopInput(tokenInput.value()))); } else if (token.IsValid()) { @@ -535,7 +539,7 @@ std::unique_ptr ServiceAudio::HandleStop(const std::vector } // on failure return first false code - auto it = + const auto it = std::find_if_not(retCodes.begin(), retCodes.end(), [](auto p) { return p.second == audio::RetCode::Success; }); if (it != retCodes.end()) { return std::make_unique(it->second, it->first); @@ -590,9 +594,7 @@ auto ServiceAudio::HandleKeyPressed(const int step) -> sys::MessagePointer MuteCurrentOperation(); return sys::msgHandled(); } - else { - return sys::msgHandled(); - } + return sys::msgHandled(); } const auto currentVolume = @@ -621,21 +623,21 @@ void ServiceAudio::MuteCurrentOperation() } } -bool ServiceAudio::IsBusy() +Operation::State ServiceAudio::GetOperationState() { - for (auto &input : audioMux.GetAllInputs()) { + for (const auto &input : audioMux.GetAllInputs()) { if (input.audio->GetCurrentState() != Audio::State::Idle) { - return true; + return input.audio->GetCurrentOperation().GetState(); } } - return false; + return Operation::State::Idle; } sys::MessagePointer ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) { sys::MessagePointer responseMsg; - const auto isBusy = IsBusy(); - auto &msgType = typeid(*msgl); + const auto operationState = GetOperationState(); + const auto &msgType = typeid(*msgl); if (msgType == typeid(AudioInternalEOFNotificationMessage)) { auto *msg = static_cast(msgl); @@ -683,17 +685,14 @@ sys::MessagePointer ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sy responseMsg = HandleKeyPressed(msg->step); } - if (const auto curIsBusy = IsBusy(); isBusy != curIsBusy) { - curIsBusy ? cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_6) - : cpuSentinel->ReleaseMinimumFrequency(); + if (const auto currentOperationState = GetOperationState(); currentOperationState != operationState) { + updateMinimumCpuFrequency(currentOperationState); } if (responseMsg) { return responseMsg; } - else { - return std::make_shared(RetCode::Failed); - } + return std::make_shared(RetCode::Failed); } std::string ServiceAudio::getSetting(const Setting &setting, @@ -742,7 +741,7 @@ std::string ServiceAudio::getSetting(const Setting &setting, break; } - const auto path = dbPath(setting, targetPlayback, targetProfile); + const auto &path = dbPath(setting, targetPlayback, targetProfile); if (const auto set_it = settingsCache.find(path); settingsCache.end() != set_it) { LOG_INFO("Get audio setting %s = %s", path.c_str(), set_it->second.c_str()); return set_it->second; @@ -791,6 +790,7 @@ void ServiceAudio::setSetting(const Setting &setting, updatedPlayback = generatePlayback(updatedPlayback); break; } break; + case Setting::Gain: { const auto clampedValue = std::clamp(utils::getNumericValue(value), minGain, maxGain); valueToSet = std::to_string(clampedValue); @@ -798,6 +798,7 @@ void ServiceAudio::setSetting(const Setting &setting, retCode = activeInput.value()->audio->SetInputGain(clampedValue); } } break; + case Setting::EnableVibration: case Setting::VibrationLevel: case Setting::EnableSound: @@ -833,7 +834,7 @@ void ServiceAudio::settingsChanged(const std::string &name, std::string value) if (value.empty()) { return; } - if (auto s_it = settingsCache.find(name); settingsCache.end() != s_it) { + if (const auto s_it = settingsCache.find(name); settingsCache.end() != s_it) { s_it->second = value; return; } @@ -842,7 +843,7 @@ void ServiceAudio::settingsChanged(const std::string &name, std::string value) void ServiceAudio::onVolumeChanged(const Volume volume, const VolumeChangeRequestSource source) { - const auto [profileType, playbackType] = getCurrentContext(); + const auto &[profileType, playbackType] = getCurrentContext(); settingsProvider->setValue(dbPath(Setting::Volume, playbackType, profileType), std::to_string(volume)); settingsCache[dbPath(Setting::Volume, playbackType, profileType)] = std::to_string(volume); bus.sendMulticast(std::make_shared(volume, std::make_pair(profileType, playbackType), source), @@ -854,7 +855,7 @@ auto ServiceAudio::handleA2DPVolumeChangedOnBluetoothDevice(sys::Message *msgl) const auto a2dpMsg = dynamic_cast(msgl); assert(a2dpMsg != nullptr); - const auto context = getCurrentContext(); + const auto &context = getCurrentContext(); const auto volume = volume::scaler::a2dp::toSystemVolume(a2dpMsg->getVolume()); bus.sendMulticast(std::make_shared(volume, context, VolumeChangeRequestSource::A2DP), sys::BusChannel::ServiceAudioNotifications); @@ -916,3 +917,19 @@ void ServiceAudio::notifyAboutNewRoutingIfRouterAvailable() } } } + +void ServiceAudio::updateMinimumCpuFrequency(Operation::State operationState) +{ + switch (operationState) { + case audio::Operation::State::Idle: + cpuSentinel->ReleaseMinimumFrequency(); + break; + case audio::Operation::State::Paused: + cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_2); // Required to keep PLL2 running, so that + // bandgap used also by PLL4 remains turned on + break; + case audio::Operation::State::Active: + cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_5); + break; + } +} diff --git a/module-services/service-audio/include/service-audio/ServiceAudio.hpp b/module-services/service-audio/include/service-audio/ServiceAudio.hpp index d5afefa8196380484dd364f4ba61170e81f00333..b9225fd51d3ba2eedc54273ab85f6468d6e10460 100644 --- a/module-services/service-audio/include/service-audio/ServiceAudio.hpp +++ b/module-services/service-audio/include/service-audio/ServiceAudio.hpp @@ -23,18 +23,13 @@ class ServiceAudio : public sys::Service { public: ServiceAudio(); - ~ServiceAudio(); sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp = nullptr) override; - sys::ReturnCodes InitHandler() override; - sys::ReturnCodes DeinitHandler() override; - void ProcessCloseReason(sys::CloseReason closeReason) override; - - sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final; + sys::ReturnCodes SwitchPowerModeHandler(sys::ServicePowerMode mode) override final; private: enum class VibrationType @@ -101,7 +96,7 @@ class ServiceAudio : public sys::Service std::string GetSound(const audio::PlaybackType &plType); constexpr auto IsResumable(const audio::PlaybackType &type) const -> bool; constexpr auto ShouldLoop(const std::optional &type) const -> bool; - auto IsBusy() -> bool; + auto GetOperationState() -> audio::Operation::State; auto IsSystemSound(const audio::PlaybackType &type) -> bool; audio::PlaybackType generatePlayback(const audio::PlaybackType &type, const audio::Setting &setting = audio::Setting::Volume); @@ -133,6 +128,7 @@ class ServiceAudio : public sys::Service auto handleSingleVibrationStart() -> sys::MessagePointer; void notifyAboutNewRoutingIfRouterAvailable(); + void updateMinimumCpuFrequency(audio::Operation::State operationState); }; namespace sys diff --git a/pure_changelog.md b/pure_changelog.md index 5e08950529216284af5337fd6fa8c16b87022b11..4e44535df76cb0f5db48b9ad5d905f638066e543 100644 --- a/pure_changelog.md +++ b/pure_changelog.md @@ -13,6 +13,7 @@ * General improvement in Eink display and error handling * Change roaming indicator to show domestic roaming as home network +* Optimized ServiceAudio power management ### Fixed