~aleteoryx/muditaos

7f9bc6bf6f8ee58c58e4b476bb315ff0fa0ded68 — Maciej Gibowicz 4 years ago d8fc8f9
[EGD-7922] Added Permanent Frequency Setting

Added Permanent Frequency setting in Advanced Developer
Mode with simple set window.
50 files changed, 556 insertions(+), 139 deletions(-)

M module-apps/application-settings/ApplicationSettings.cpp
M module-apps/application-settings/CMakeLists.txt
M module-apps/application-settings/windows/WindowNames.hpp
M module-apps/application-settings/windows/advanced/AdvancedOptionsWindow.cpp
A module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp
A module-apps/application-settings/windows/advanced/CPUModeTestWindow.hpp
M module-bsp/board/linux/eink_frontlight/eink_frontlight.cpp
M module-bsp/board/linux/lpm/LinuxLPM.cpp
M module-bsp/board/linux/lpm/LinuxLPM.h
M module-bsp/board/linux/lpm/PowerProfile.cpp
M module-bsp/board/linux/vibrator/vibrator.cpp
M module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp
M module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp
M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp
M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp
M module-bsp/board/rt1051/bsp/vibrator/vibrator.cpp
M module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp
M module-bsp/bsp/common.hpp
M module-bsp/bsp/eink_frontlight/eink_frontlight.hpp
M module-bsp/bsp/lpm/PowerProfile.hpp
M module-bsp/bsp/lpm/bsp_lpm.cpp
M module-bsp/bsp/lpm/bsp_lpm.hpp
M module-bsp/bsp/vibrator/vibrator.hpp
M module-services/service-audio/ServiceAudio.cpp
M module-services/service-bluetooth/ServiceBluetooth.cpp
M module-services/service-cellular/CellularCall.cpp
M module-services/service-cellular/ServiceCellular.cpp
M module-services/service-cellular/connection-manager/ConnectionManagerCellularCommands.cpp
M module-services/service-desktop/WorkerDesktop.cpp
M module-services/service-evtmgr/EventManager.cpp
M module-services/service-evtmgr/WorkerEventCommon.cpp
M module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp
M module-services/service-evtmgr/service-evtmgr/WorkerEventCommon.hpp
M module-sys/SystemManager/CpuGovernor.cpp
M module-sys/SystemManager/CpuSentinel.cpp
M module-sys/SystemManager/PowerManager.cpp
M module-sys/SystemManager/SystemManagerCommon.cpp
M module-sys/SystemManager/include/SystemManager/CpuGovernor.hpp
M module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp
M module-sys/SystemManager/include/SystemManager/PowerManager.hpp
M module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp
M module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp
M module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp
M module-sys/common/include/system/messages/SentinelRegistrationMessage.hpp
M products/BellHybrid/EinkSentinelBell.cpp
M products/BellHybrid/services/audio/ServiceAudio.cpp
M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp
M products/BellHybrid/services/evtmgr/user-activity-handler/UserActivityHandler.cpp
M products/PurePhone/EinkSentinelPure.cpp
M source/MessageType.hpp
M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +4 -0
@@ 8,6 8,7 @@
#include <application-settings/windows/advanced/InformationWindow.hpp>
#include <application-settings/windows/advanced/TextImageColorWindow.hpp>
#include <application-settings/windows/advanced/UITestWindow.hpp>
#include <application-settings/windows/advanced/CPUModeTestWindow.hpp>
#include <application-settings/windows/advanced/ColorTestWindow.hpp>
#include <application-settings/windows/advanced/StatusBarImageTypeWindow.hpp>
#include <application-settings/windows/bluetooth/BluetoothWindow.hpp>


@@ 368,6 369,9 @@ namespace app
        windowsFactory.attach(gui::window::name::ui_test, [](ApplicationCommon *app, const std::string &name) {
            return std::make_unique<gui::UiTestWindow>(app);
        });
        windowsFactory.attach(gui::window::name::cpu_test_window, [](ApplicationCommon *app, const std::string &name) {
            return std::make_unique<gui::CPUModeTestWindow>(app);
        });
        windowsFactory.attach(gui::window::name::color_test_window,
                              [](ApplicationCommon *app, const std::string &name) {
                                  return std::make_unique<gui::ColorTestWindow>(app);

M module-apps/application-settings/CMakeLists.txt => module-apps/application-settings/CMakeLists.txt +1 -0
@@ 47,6 47,7 @@ target_sources(application-settings
        windows/SettingsMainWindow.cpp
        windows/advanced/AdvancedOptionsWindow.cpp
        windows/advanced/ColorTestWindow.cpp
        windows/advanced/CPUModeTestWindow.cpp
        windows/advanced/InformationWindow.cpp
        windows/advanced/TextImageColorWindow.cpp
        windows/advanced/UITestWindow.cpp

M module-apps/application-settings/windows/WindowNames.hpp => module-apps/application-settings/windows/WindowNames.hpp +1 -0
@@ 9,6 9,7 @@ namespace gui::window::name
    inline constexpr auto information         = "Information";
    inline constexpr auto ui_test             = "UI Test";
    inline constexpr auto color_test_window   = "Color Test";
    inline constexpr auto cpu_test_window     = "CPUModeTest";
    inline constexpr auto status_bar_img_type = "StatusBarImgType";
    inline constexpr auto text_image_color    = "TextImageColor";


M module-apps/application-settings/windows/advanced/AdvancedOptionsWindow.cpp => module-apps/application-settings/windows/advanced/AdvancedOptionsWindow.cpp +1 -0
@@ 28,6 28,7 @@ std::list<gui::Option> advancedOptions(app::ApplicationCommon *app)
    addMenu("Color Test", gui::window::name::color_test_window);
    addMenu("Statusbar Image Test", gui::window::name::status_bar_img_type);
    addMenu("Text Image Color test", gui::window::name::text_image_color);
    addMenu("CPU Mode Test", gui::window::name::cpu_test_window);

    return l;
}

A module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp => module-apps/application-settings/windows/advanced/CPUModeTestWindow.cpp +193 -0
@@ 0,0 1,193 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CPUModeTestWindow.hpp"

#include <system/messages/SentinelRegistrationMessage.hpp>
#include <application-settings/windows/WindowNames.hpp>
#include <Application.hpp>
#include <TextFixedSize.hpp>
#include <BoxLayout.hpp>

#include <magic_enum.hpp>

namespace magic_enum
{
    template <> struct enum_range<bsp::CpuFrequencyMHz>
    {
        static constexpr int min = 0;
        static constexpr int max = 528;
    };
} // namespace magic_enum

namespace gui
{
    CPUModeTestWindow::CPUModeTestWindow(app::ApplicationCommon *app) : AppWindow(app, window::name::cpu_test_window)
    {
        cpuModeTester = std::make_shared<sys::CpuSentinel>(name, app, [&](bsp::CpuFrequencyMHz freq) {
            auto freqToPrint = std::to_string(magic_enum::enum_integer(freq));
            currentFreqValue->setMinimumWidthToFitText(freqToPrint);
            currentFreqValue->setMaximumWidth(currentFreqValue->widgetMinimumArea.w);
            currentFreqValue->informContentChanged();
            currentFreqValue->setText(freqToPrint);

            application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
        });

        auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuModeTester);
        application->bus.sendUnicastSync(sentinelRegistrationMsg, service::name::system_manager, 30);

        AppWindow::buildInterface();

        navBar->setText(nav_bar::Side::Right, utils::translate(style::strings::common::back));

        setTitle(name);

        body = new VBox(this,
                        style::window::default_left_margin,
                        style::window::default_vertical_pos,
                        style::window::default_body_width,
                        style::window::default_body_height);

        body->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        body->setEdges(RectangleEdge::None);

        createCurrentFreqBox();
        createPermanentFreqSettingBox();
        createNewFreqBox();

        body->resizeItems();
        setFocusItem(body);
    }

    void CPUModeTestWindow::onClose(Window::CloseReason reason)
    {
        if (reason != Window::CloseReason::Popup && reason != Window::CloseReason::PhoneLock) {
            auto sentinelRemovalMessage = std::make_shared<sys::SentinelRemovalMessage>(name);
            application->bus.sendUnicastSync(sentinelRemovalMessage, service::name::system_manager, 30);
        }
    }

    void CPUModeTestWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        auto freqToPrint = std::to_string(magic_enum::enum_integer(cpuModeTester->GetFrequency()));

        currentFreqValue->setMinimumWidthToFitText(freqToPrint);
        currentFreqValue->setMinimumHeightToFitText();
        currentFreqValue->setMaximumWidth(currentFreqValue->widgetMinimumArea.w);
        currentFreqValue->informContentChanged();
        currentFreqValue->setText(freqToPrint);
    }

    void CPUModeTestWindow::createCurrentFreqBox()
    {
        auto currentFreqBody = new VBox(body);
        currentFreqBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        currentFreqBody->setEdges(RectangleEdge::None);
        currentFreqBody->setMinimumSize(style::window::default_body_width, 80);
        currentFreqBody->setMargins({0, 60, 0, 30});
        currentFreqBody->activeItem = false;

        auto currentFreqLabel = new TextFixedSize(currentFreqBody);
        currentFreqLabel->setAlignment({Alignment::Horizontal::Center});
        currentFreqLabel->setFont(style::window::font::small);
        currentFreqLabel->setMinimumWidth(style::window::default_body_width);
        currentFreqLabel->setMinimumHeightToFitText();
        currentFreqLabel->setMargins({0, 0, 0, 15});
        currentFreqLabel->setText("Current CPU Frequency [MHz]:");
        currentFreqLabel->setEdges(RectangleEdge::None);
        currentFreqLabel->drawUnderline(false);

        currentFreqValue = new TextFixedSize(currentFreqBody);
        currentFreqValue->setAlignment({Alignment::Horizontal::Center});
        currentFreqValue->setFont(style::window::font::mediumbold);
        currentFreqValue->setPenWidth(style::window::default_border_focus_w);
        currentFreqValue->setEdges(RectangleEdge::Bottom);
        currentFreqValue->drawUnderline(false);
        currentFreqValue->setEditMode(EditMode::Browse);
        currentFreqValue->activeItem = false;
    }

    void CPUModeTestWindow::createPermanentFreqSettingBox()
    {
        auto permanentFreqBody = new VBox(body);
        permanentFreqBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        permanentFreqBody->setEdges(RectangleEdge::None);
        permanentFreqBody->setMinimumSize(style::window::default_body_width, 80);
        permanentFreqBody->setMargins({0, 0, 0, 30});

        auto permanentFreqLabel = new TextFixedSize(permanentFreqBody);
        permanentFreqLabel->setAlignment({Alignment::Horizontal::Center});
        permanentFreqLabel->setFont(style::window::font::small);
        permanentFreqLabel->setMinimumWidth(style::window::default_body_width);
        permanentFreqLabel->setMinimumHeightToFitText();
        permanentFreqLabel->setMargins({0, 0, 0, 15});
        permanentFreqLabel->setText("Set Permanent Frequency:");
        permanentFreqLabel->setEdges(RectangleEdge::None);
        permanentFreqLabel->drawUnderline(false);
        permanentFreqLabel->activeItem = false;

        permanentFreqSpinner = new gui::TextSpinnerBox(permanentFreqBody, {"OFF", "ON"}, Boundaries::Continuous);
        permanentFreqSpinner->setMinimumSize(100, 30);
        permanentFreqSpinner->setCurrentValue(cpuModeTester->isPermanentFrequencyActive() ? "ON" : "OFF");

        permanentFreqBody->inputCallback = [&](Item &item, const InputEvent &event) {
            auto ret = permanentFreqSpinner->onInput(event);
            if (ret) {
                if (permanentFreqSpinner->getCurrentValue() == "ON") {
                    cpuModeTester->HoldFrequencyPermanently(
                        magic_enum::enum_cast<bsp::CpuFrequencyMHz>(std::stoi(currentFreqSpinner->getCurrentValue()))
                            .value());
                }
                else {
                    cpuModeTester->ReleasePermanentFrequency();
                }
            }

            return ret;
        };
    }

    void CPUModeTestWindow::createNewFreqBox()
    {
        auto newFreqBody = new VBox(body);
        newFreqBody->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        newFreqBody->setEdges(RectangleEdge::None);
        newFreqBody->setMinimumSize(style::window::default_body_width, 80);

        auto newFreqLabel = new TextFixedSize(newFreqBody);
        newFreqLabel->setAlignment({Alignment::Horizontal::Center});
        newFreqLabel->setFont(style::window::font::small);
        newFreqLabel->setMinimumWidth(style::window::default_body_width);
        newFreqLabel->setMinimumHeightToFitText();
        newFreqLabel->setMargins({0, 0, 0, 15});
        newFreqLabel->setText("New Frequency to set [MHz]:");
        newFreqLabel->setEdges(RectangleEdge::None);
        newFreqLabel->drawUnderline(false);
        newFreqLabel->activeItem = false;

        std::vector<UTF8> freqOptions;
        for (auto val : magic_enum::enum_values<bsp::CpuFrequencyMHz>()) {
            if (val <= bsp::getPowerProfile().minimalFrequency) {
                continue;
            }

            freqOptions.push_back(std::to_string(static_cast<int>(val)));
        }

        currentFreqSpinner = new gui::TextSpinnerBox(newFreqBody, freqOptions, Boundaries::Continuous);
        currentFreqSpinner->setMinimumSize(100, 30);

        newFreqBody->inputCallback = [&](Item &item, const InputEvent &event) {
            auto ret = currentFreqSpinner->onInput(event);

            if (cpuModeTester->isPermanentFrequencyActive()) {
                cpuModeTester->HoldFrequencyPermanently(
                    magic_enum::enum_cast<bsp::CpuFrequencyMHz>(std::stoi(currentFreqSpinner->getCurrentValue()))
                        .value());
            }

            return ret;
        };
    }
} /* namespace gui */

A module-apps/application-settings/windows/advanced/CPUModeTestWindow.hpp => module-apps/application-settings/windows/advanced/CPUModeTestWindow.hpp +34 -0
@@ 0,0 1,34 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once

#include "AppWindow.hpp"

#include <TextFixedSize.hpp>
#include <widgets/TextSpinnerBox.hpp>
#include <SystemManager/CpuSentinel.hpp>

namespace gui
{
    class CPUModeTestWindow : public AppWindow
    {
      private:
        static inline auto name = "CPU Mode Tester";

        VBox *body                           = nullptr;
        TextFixedSize *currentFreqValue      = nullptr;
        TextSpinnerBox *currentFreqSpinner   = nullptr;
        TextSpinnerBox *permanentFreqSpinner = nullptr;

        std::shared_ptr<sys::CpuSentinel> cpuModeTester;

        void createCurrentFreqBox();
        void createPermanentFreqSettingBox();
        void createNewFreqBox();

      public:
        explicit CPUModeTestWindow(app::ApplicationCommon *app);
        void onClose(CloseReason reason) override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };
} /* namespace gui */

M module-bsp/board/linux/eink_frontlight/eink_frontlight.cpp => module-bsp/board/linux/eink_frontlight/eink_frontlight.cpp +1 -1
@@ 23,7 23,7 @@ namespace bsp::eink_frontlight
    void setGammaFactor(float)
    {}

    void updateClockFrequency(CpuFrequencyHz newFrequency)
    void updateClockFrequency(CpuFrequencyMHz newFrequency)
    {}

} // namespace bsp::eink_frontlight

M module-bsp/board/linux/lpm/LinuxLPM.cpp => module-bsp/board/linux/lpm/LinuxLPM.cpp +1 -1
@@ 20,7 20,7 @@ namespace bsp
        return 0;
    }

    void LinuxLPM::SetCpuFrequency(bsp::CpuFrequencyHz freq)
    void LinuxLPM::SetCpuFrequency(bsp::CpuFrequencyMHz freq)
    {
        currentFrequency = freq;
    }

M module-bsp/board/linux/lpm/LinuxLPM.h => module-bsp/board/linux/lpm/LinuxLPM.h +1 -1
@@ 14,7 14,7 @@ namespace bsp
      public:
        int32_t PowerOff() override final;
        int32_t Reboot(RebootType reason) override final;
        void SetCpuFrequency(CpuFrequencyHz freq) final;
        void SetCpuFrequency(CpuFrequencyMHz freq) final;
        void SetHighestCoreVoltage() final;
        [[nodiscard]] uint32_t GetCpuFrequency() const noexcept final;
        void SwitchOscillatorSource(OscillatorSource source) final;

M module-bsp/board/linux/lpm/PowerProfile.cpp => module-bsp/board/linux/lpm/PowerProfile.cpp +1 -1
@@ 14,7 14,7 @@ namespace bsp
        linuxPowerProfile.maxBelowThresholdCount            = 30;
        linuxPowerProfile.maxBelowThresholdInRowCount       = 10;
        linuxPowerProfile.maxAboveThresholdCount            = 3;
        linuxPowerProfile.minimalFrequency                  = CpuFrequencyHz::Level_1;
        linuxPowerProfile.minimalFrequency                  = CpuFrequencyMHz::Level_1;
        linuxPowerProfile.frequencyIncreaseIntermediateStep = false;

        return linuxPowerProfile;

M module-bsp/board/linux/vibrator/vibrator.cpp => module-bsp/board/linux/vibrator/vibrator.cpp +1 -1
@@ 21,7 21,7 @@ namespace bsp
        {}
        void deinit()
        {}
        void updateClockFrequency(CpuFrequencyHz newFrequency)
        void updateClockFrequency(CpuFrequencyMHz newFrequency)
        {}
        void setVibrationLevel(unsigned int vibrationLevel)
        {}

M module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp => module-bsp/board/rt1051/bellpx/bsp/lpm/PowerProfile.cpp +1 -1
@@ 14,7 14,7 @@ namespace bsp
        bellPowerProfile.maxBelowThresholdCount            = 5;
        bellPowerProfile.maxBelowThresholdInRowCount       = 1;
        bellPowerProfile.maxAboveThresholdCount            = 2;
        bellPowerProfile.minimalFrequency                  = CpuFrequencyHz::Level_0;
        bellPowerProfile.minimalFrequency                  = CpuFrequencyMHz::Level_0;
        bellPowerProfile.frequencyIncreaseIntermediateStep = true;

        return bellPowerProfile;

M module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp => module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp +1 -1
@@ 63,7 63,7 @@ namespace bsp::eink_frontlight
        gammaFactor = gamma;
    }

    void updateClockFrequency(CpuFrequencyHz newFrequency)
    void updateClockFrequency(CpuFrequencyMHz newFrequency)
    {
        pwm->UpdateClockFrequency(static_cast<std::uint32_t>(newFrequency));
    }

M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp +8 -8
@@ 68,29 68,29 @@ namespace bsp
        return 0;
    }

    void RT1051LPM::SetCpuFrequency(bsp::CpuFrequencyHz freq)
    void RT1051LPM::SetCpuFrequency(bsp::CpuFrequencyMHz freq)
    {
        currentFrequency = freq;
        switch (freq) {
        case bsp::CpuFrequencyHz::Level_0:
        case bsp::CpuFrequencyMHz::Level_0:
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_4_Mhz);
            break;
        case bsp::CpuFrequencyHz::Level_1:
        case bsp::CpuFrequencyMHz::Level_1:
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_12_Mhz);
            break;
        case bsp::CpuFrequencyHz::Level_2:
        case bsp::CpuFrequencyMHz::Level_2:
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Osc_24_Mhz);
            break;
        case bsp::CpuFrequencyHz::Level_3:
        case bsp::CpuFrequencyMHz::Level_3:
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_66_Mhz);
            break;
        case bsp::CpuFrequencyHz::Level_4:
        case bsp::CpuFrequencyMHz::Level_4:
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_132_Mhz);
            break;
        case bsp::CpuFrequencyHz::Level_5:
        case bsp::CpuFrequencyMHz::Level_5:
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_264_Mhz);
            break;
        case bsp::CpuFrequencyHz::Level_6:
        case bsp::CpuFrequencyMHz::Level_6:
            CpuFreq->SetCpuFrequency(CpuFreqLPM::CpuClock::CpuClock_Pll2_528_Mhz);
            break;
        }

M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.hpp +1 -1
@@ 16,7 16,7 @@ namespace bsp
        RT1051LPM();
        int32_t PowerOff() override final;
        int32_t Reboot(RebootType reason) override final;
        void SetCpuFrequency(CpuFrequencyHz freq) final;
        void SetCpuFrequency(CpuFrequencyMHz freq) final;
        void SetHighestCoreVoltage() final;
        [[nodiscard]] uint32_t GetCpuFrequency() const noexcept final;
        void SwitchOscillatorSource(OscillatorSource source) final;

M module-bsp/board/rt1051/bsp/vibrator/vibrator.cpp => module-bsp/board/rt1051/bsp/vibrator/vibrator.cpp +1 -1
@@ 46,7 46,7 @@ namespace bsp
            pwm->Stop(pwmChannel);
        }

        void updateClockFrequency(CpuFrequencyHz newFrequency)
        void updateClockFrequency(CpuFrequencyMHz newFrequency)
        {
            if (pwm) {
                pwm->UpdateClockFrequency(static_cast<std::uint32_t>(newFrequency));

M module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp => module-bsp/board/rt1051/puretx/bsp/lpm/PowerProfile.cpp +1 -1
@@ 14,7 14,7 @@ namespace bsp
        purePowerProfile.maxBelowThresholdCount            = 30;
        purePowerProfile.maxBelowThresholdInRowCount       = 10;
        purePowerProfile.maxAboveThresholdCount            = 3;
        purePowerProfile.minimalFrequency                  = CpuFrequencyHz::Level_1;
        purePowerProfile.minimalFrequency                  = CpuFrequencyMHz::Level_1;
        purePowerProfile.frequencyIncreaseIntermediateStep = false;

        return purePowerProfile;

M module-bsp/bsp/common.hpp => module-bsp/bsp/common.hpp +8 -8
@@ 13,15 13,15 @@ namespace bsp

    /// CPU frequency is dependent on the clock settings.
    /// Only a few thresholds are available in the current configuration
    enum class CpuFrequencyHz
    enum class CpuFrequencyMHz
    {
        Level_0 = 4000000,
        Level_1 = 12000000,
        Level_2 = 24000000,
        Level_3 = 66000000,
        Level_4 = 132000000,
        Level_5 = 264000000,
        Level_6 = 528000000
        Level_0 = 4,
        Level_1 = 12,
        Level_2 = 24,
        Level_3 = 66,
        Level_4 = 132,
        Level_5 = 264,
        Level_6 = 528
    };

    enum class Board{

M module-bsp/bsp/eink_frontlight/eink_frontlight.hpp => module-bsp/bsp/eink_frontlight/eink_frontlight.hpp +1 -1
@@ 30,5 30,5 @@ namespace bsp::eink_frontlight

    void setGammaFactor(float gamma);

    void updateClockFrequency(CpuFrequencyHz newFrequency);
    void updateClockFrequency(CpuFrequencyMHz newFrequency);
} // namespace bsp::eink_frontlight

M module-bsp/bsp/lpm/PowerProfile.hpp => module-bsp/bsp/lpm/PowerProfile.hpp +1 -1
@@ 15,7 15,7 @@ namespace bsp
        std::uint32_t maxBelowThresholdCount;
        std::uint32_t maxBelowThresholdInRowCount;
        std::uint32_t maxAboveThresholdCount;
        CpuFrequencyHz minimalFrequency;
        CpuFrequencyMHz minimalFrequency;
        bool frequencyIncreaseIntermediateStep;
    };


M module-bsp/bsp/lpm/bsp_lpm.cpp => module-bsp/bsp/lpm/bsp_lpm.cpp +1 -1
@@ 29,7 29,7 @@ namespace bsp{
        return inst;
    }

    CpuFrequencyHz LowPowerMode::GetCurrentFrequencyLevel() const noexcept
    CpuFrequencyMHz LowPowerMode::GetCurrentFrequencyLevel() const noexcept
    {
    	return currentFrequency;
    }

M module-bsp/bsp/lpm/bsp_lpm.hpp => module-bsp/bsp/lpm/bsp_lpm.hpp +3 -3
@@ 34,9 34,9 @@ namespace bsp
        virtual int32_t PowerOff()                = 0;
        virtual int32_t Reboot(RebootType reason) = 0;

        virtual void SetCpuFrequency(CpuFrequencyHz freq) = 0;
        virtual void SetCpuFrequency(CpuFrequencyMHz freq) = 0;
        virtual void SetHighestCoreVoltage() = 0;
        [[nodiscard]] CpuFrequencyHz GetCurrentFrequencyLevel() const noexcept;
        [[nodiscard]] CpuFrequencyMHz GetCurrentFrequencyLevel() const noexcept;
        [[nodiscard]] virtual uint32_t GetCpuFrequency() const noexcept = 0;

        virtual void SwitchOscillatorSource(OscillatorSource source) = 0;


@@ 52,6 52,6 @@ namespace bsp
        virtual void SwitchToLowPowerModeLDO() = 0;

      protected:
        CpuFrequencyHz currentFrequency = CpuFrequencyHz::Level_6;
        CpuFrequencyMHz currentFrequency = CpuFrequencyMHz::Level_6;
    };
} // namespace bsp

M module-bsp/bsp/vibrator/vibrator.hpp => module-bsp/bsp/vibrator/vibrator.hpp +1 -1
@@ 25,7 25,7 @@ namespace bsp
        void deinit();
        void enable();
        void disable();
        void updateClockFrequency(CpuFrequencyHz newFrequency);
        void updateClockFrequency(CpuFrequencyMHz newFrequency);
        void setVibrationLevel(unsigned int vibrationLevel);

    } // namespace vibrator

M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +1 -1
@@ 683,7 683,7 @@ sys::MessagePointer ServiceAudio::DataReceivedHandler(sys::DataMessage *msgl, sy
    }

    if (const auto curIsBusy = IsBusy(); isBusy != curIsBusy) {
        curIsBusy ? cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_6)
        curIsBusy ? cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_6)
                  : cpuSentinel->ReleaseMinimumFrequency();
    }


M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +1 -1
@@ 185,7 185,7 @@ auto ServiceBluetooth::handle(message::bluetooth::SetStatus *msg) -> std::shared
    switch (newBtStatus.state) {
    case BluetoothStatus::State::On:

        cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_3);
        cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_3);
        sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::PowerOn));
        bus.sendMulticast(
            std::make_shared<sys::bluetooth::BluetoothModeChanged>(sys::bluetooth::BluetoothMode::Enabled),

M module-services/service-cellular/CellularCall.cpp => module-services/service-cellular/CellularCall.cpp +1 -1
@@ 28,7 28,7 @@ namespace CellularCall
        }

        if (cpuSentinel) {
            cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_6);
            cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_6);
        }

        clear();

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +1 -1
@@ 2116,7 2116,7 @@ auto ServiceCellular::handleNetworkStatusUpdateNotification(sys::Message *msg) -
auto ServiceCellular::handleUrcIncomingNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
    // when handling URC, the CPU frequency does not go below a certain level
    cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_4);
    cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_4);
    cmux->exitSleepMode();
    return std::make_shared<CellularResponseMessage>(true);
}

M module-services/service-cellular/connection-manager/ConnectionManagerCellularCommands.cpp => module-services/service-cellular/connection-manager/ConnectionManagerCellularCommands.cpp +1 -1
@@ 102,7 102,7 @@ void ConnectionManagerCellularCommands::holdMinimumCpuFrequency()
{
    auto handle = cellular.getTaskHandle();
    if (cellular.cpuSentinel) {
        cellular.cpuSentinel->HoldMinimumFrequencyAndWait(bsp::CpuFrequencyHz::Level_4, handle, 2000);
        cellular.cpuSentinel->HoldMinimumFrequencyAndWait(bsp::CpuFrequencyMHz::Level_4, handle, 2000);
    }
    return;
}

M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +1 -1
@@ 151,7 151,7 @@ bool WorkerDesktop::handleMessage(uint32_t queueID)
            usbStatus = bsp::USBDeviceStatus::Connected;
        }
        else if (notification == bsp::USBDeviceStatus::Configured) {
            cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_4);
            cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_4);
            if (usbStatus == bsp::USBDeviceStatus::Connected) {
                ownerService->bus.sendUnicast(std::make_shared<sdesktop::usb::USBConfigured>(
                                                  sdesktop::usb::USBConfigurationType::firstConfiguration),

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +1 -1
@@ 51,7 51,7 @@ namespace
} // namespace

EventManagerSentinel::EventManagerSentinel(std::shared_ptr<sys::CpuSentinel> cpuSentinel,
                                           bsp::CpuFrequencyHz frequencyToHold)
                                           bsp::CpuFrequencyMHz frequencyToHold)
    : cpuSentinel(cpuSentinel)
{
    cpuSentinel->HoldMinimumFrequency(frequencyToHold);

M module-services/service-evtmgr/WorkerEventCommon.cpp => module-services/service-evtmgr/WorkerEventCommon.cpp +2 -2
@@ 147,7 147,7 @@ bool WorkerEventCommon::initCommonHardwareComponents()
    bsp::rtc::getCurrentTimestamp(&timestamp);
    bsp::rtc::setMinuteAlarm(timestamp);

    cpuSentinel = std::make_shared<sys::CpuSentinel>("WorkerEvent", service, [this](bsp::CpuFrequencyHz newFrequency) {
    cpuSentinel = std::make_shared<sys::CpuSentinel>("WorkerEvent", service, [this](bsp::CpuFrequencyMHz newFrequency) {
        updateResourcesAfterCpuFrequencyChange(newFrequency);
    });



@@ 215,7 215,7 @@ void WorkerEventCommon::processKeyEvent(bsp::KeyEvents event, bsp::KeyCodes code
    service->bus.sendUnicast(message, service::name::evt_manager);
}

void WorkerEventCommon::updateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency)
void WorkerEventCommon::updateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency)
{
    bsp::eink_frontlight::updateClockFrequency(newFrequency);
    bsp::vibrator::updateClockFrequency(newFrequency);

M module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp => module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp +1 -1
@@ 26,7 26,7 @@ class WorkerEventCommon;
class EventManagerSentinel
{
  public:
    explicit EventManagerSentinel(std::shared_ptr<sys::CpuSentinel> cpuSentinel, bsp::CpuFrequencyHz frequencyToHold);
    explicit EventManagerSentinel(std::shared_ptr<sys::CpuSentinel> cpuSentinel, bsp::CpuFrequencyMHz frequencyToHold);
    ~EventManagerSentinel();

  private:

M module-services/service-evtmgr/service-evtmgr/WorkerEventCommon.hpp => module-services/service-evtmgr/service-evtmgr/WorkerEventCommon.hpp +1 -1
@@ 69,7 69,7 @@ class WorkerEventCommon : public sys::Worker
     * @param code key code
     * @note It sends message to service if event is processed successfully.
     */
    void updateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency);
    void updateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency);
    bool initEventQueues();
    bool initCommonHardwareComponents();


M module-sys/SystemManager/CpuGovernor.cpp => module-sys/SystemManager/CpuGovernor.cpp +48 -10
@@ 9,7 9,7 @@ namespace sys
{

    GovernorSentinel::GovernorSentinel(std::shared_ptr<CpuSentinel> newSentinel)
        : sentinelPtr(newSentinel), requestedFrequency(bsp::CpuFrequencyHz::Level_0)
        : sentinelPtr(newSentinel), requestedFrequency(bsp::CpuFrequencyMHz::Level_0)
    {}

    [[nodiscard]] auto GovernorSentinel::GetSentinel() const noexcept -> SentinelPointer


@@ 17,17 17,17 @@ namespace sys
        return sentinelPtr;
    }

    [[nodiscard]] auto GovernorSentinel::GetRequestedFrequency() const noexcept -> bsp::CpuFrequencyHz
    [[nodiscard]] auto GovernorSentinel::GetRequestedFrequency() const noexcept -> bsp::CpuFrequencyMHz
    {
        return requestedFrequency;
    }

    void GovernorSentinel::SetRequestedFrequency(bsp::CpuFrequencyHz newFrequency)
    void GovernorSentinel::SetRequestedFrequency(bsp::CpuFrequencyMHz newFrequency)
    {
        requestedFrequency = newFrequency;
    }

    void CpuGovernor::RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel)
    bool CpuGovernor::RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel)
    {
        if (newSentinel) {
            auto isNewSentinelAlreadyRegistered = false;


@@ 45,11 45,32 @@ namespace sys

            if (!isNewSentinelAlreadyRegistered) {
                sentinels.push_back(std::make_unique<GovernorSentinel>(newSentinel));
                return true;
            }
            else {
                return false;
                LOG_WARN("New sentinel %s is already registered", newSentinel->GetName().c_str());
            }
        }
        return false;
    }

    void CpuGovernor::RemoveSentinel(std::string sentinelName)
    {
        if (!sentinelName.empty()) {
            sentinels.erase(std::remove_if(sentinels.begin(),
                                           sentinels.end(),
                                           [sentinelName](auto const &sentinel) {
                                               auto sentinelWeakPointer = sentinel->GetSentinel();
                                               if (!sentinelWeakPointer.expired()) {
                                                   std::shared_ptr<CpuSentinel> sharedResource =
                                                       sentinelWeakPointer.lock();
                                                   return sharedResource->GetName() == sentinelName;
                                               }
                                               return false;
                                           }),
                            sentinels.end());
        }
    }

    [[nodiscard]] auto CpuGovernor::GetNumberOfRegisteredSentinels() const noexcept -> uint32_t


@@ 62,8 83,15 @@ namespace sys
        std::for_each(std::begin(sentinels), std::end(sentinels), PrintName);
    }

    void CpuGovernor::SetCpuFrequencyRequest(std::string sentinelName, bsp::CpuFrequencyHz request)
    void CpuGovernor::SetCpuFrequencyRequest(std::string sentinelName,
                                             bsp::CpuFrequencyMHz request,
                                             bool permanentBlock)
    {
        if (permanentBlock) {
            permanentFrequencyToHold.isActive        = true;
            permanentFrequencyToHold.frequencyToHold = request;
            return;
        }
        for (auto &sentinel : sentinels) {
            auto sentinelWeakPointer = sentinel->GetSentinel();
            if (!sentinelWeakPointer.expired()) {


@@ 75,14 103,19 @@ namespace sys
        }
    }

    void CpuGovernor::ResetCpuFrequencyRequest(std::string sentinelName)
    void CpuGovernor::ResetCpuFrequencyRequest(std::string sentinelName, bool permanentBlock)
    {
        SetCpuFrequencyRequest(sentinelName, bsp::CpuFrequencyHz::Level_0);
        if (permanentBlock) {
            permanentFrequencyToHold.isActive        = false;
            permanentFrequencyToHold.frequencyToHold = bsp::CpuFrequencyMHz::Level_0;
            return;
        }
        SetCpuFrequencyRequest(sentinelName, bsp::CpuFrequencyMHz::Level_0);
    }

    [[nodiscard]] auto CpuGovernor::GetMinimumFrequencyRequested() const noexcept -> bsp::CpuFrequencyHz
    [[nodiscard]] auto CpuGovernor::GetMinimumFrequencyRequested() const noexcept -> bsp::CpuFrequencyMHz
    {
        bsp::CpuFrequencyHz minFrequency = bsp::CpuFrequencyHz::Level_0;
        bsp::CpuFrequencyMHz minFrequency = bsp::CpuFrequencyMHz::Level_0;

        for (auto &sentinel : sentinels) {
            const auto sentinelFrequency = sentinel->GetRequestedFrequency();


@@ 95,7 128,7 @@ namespace sys
        return minFrequency;
    }

    void CpuGovernor::InformSentinelsAboutCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency) const noexcept
    void CpuGovernor::InformSentinelsAboutCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency) const noexcept
    {
        for (auto &sentinel : sentinels) {
            auto sentinelWeakPointer = sentinel->GetSentinel();


@@ 115,4 148,9 @@ namespace sys
        }
    }

    [[nodiscard]] auto CpuGovernor::GetPermanentFrequencyRequested() const noexcept -> PermanentFrequencyToHold
    {
        return permanentFrequencyToHold;
    }

} // namespace sys

M module-sys/SystemManager/CpuSentinel.cpp => module-sys/SystemManager/CpuSentinel.cpp +51 -6
@@ 9,7 9,9 @@
namespace sys
{

    CpuSentinel::CpuSentinel(std::string name, sys::Service *service, std::function<void(bsp::CpuFrequencyHz)> callback)
    CpuSentinel::CpuSentinel(std::string name,
                             sys::Service *service,
                             std::function<void(bsp::CpuFrequencyMHz)> callback)
        : name(name), owner(service), callback(callback)
    {}



@@ 18,7 20,7 @@ namespace sys
        return name;
    }

    void CpuSentinel::HoldMinimumFrequency(bsp::CpuFrequencyHz frequencyToHold)
    void CpuSentinel::HoldMinimumFrequency(bsp::CpuFrequencyMHz frequencyToHold)
    {
        if (currentFrequencyToHold != frequencyToHold) {
            auto msg = std::make_shared<sys::HoldCpuFrequencyMessage>(GetName(), frequencyToHold);


@@ 29,14 31,47 @@ namespace sys

    void CpuSentinel::ReleaseMinimumFrequency()
    {
        if (currentFrequencyToHold != bsp::CpuFrequencyHz::Level_0) {
        if (currentFrequencyToHold != bsp::CpuFrequencyMHz::Level_0) {
            auto msg = std::make_shared<sys::ReleaseCpuFrequencyMessage>(GetName());
            owner->bus.sendUnicast(std::move(msg), service::name::system_manager);
            currentFrequencyToHold = bsp::CpuFrequencyHz::Level_0;
            currentFrequencyToHold = bsp::CpuFrequencyMHz::Level_0;
        }
    }

    void CpuSentinel::CpuFrequencyHasChanged(bsp::CpuFrequencyHz newFrequency)
    void CpuSentinel::HoldFrequencyPermanently(bsp::CpuFrequencyMHz frequencyToHold)
    {
        permanentFrequencyToHold.isActive        = true;
        permanentFrequencyToHold.frequencyToHold = frequencyToHold;
        auto msg = std::make_shared<sys::HoldCpuFrequencyPermanentlyMessage>(GetName(), frequencyToHold);
        owner->bus.sendUnicast(std::move(msg), service::name::system_manager);
    }

    [[nodiscard]] auto CpuSentinel::GetFrequency() const noexcept -> bsp::CpuFrequencyMHz
    {
        if (permanentFrequencyToHold.isActive) {
            return permanentFrequencyToHold.frequencyToHold;
        }
        else {
            return currentFrequency;
        }
    }

    void CpuSentinel::ReleasePermanentFrequency()
    {
        if (permanentFrequencyToHold.isActive) {
            auto msg = std::make_shared<sys::ReleaseCpuPermanentFrequencyMessage>(GetName());
            owner->bus.sendUnicast(std::move(msg), service::name::system_manager);
            permanentFrequencyToHold.isActive        = false;
            permanentFrequencyToHold.frequencyToHold = bsp::CpuFrequencyMHz::Level_0;
        }
    }

    bool CpuSentinel::isPermanentFrequencyActive()
    {
        return permanentFrequencyToHold.isActive;
    }

    void CpuSentinel::CpuFrequencyHasChanged(bsp::CpuFrequencyMHz newFrequency)
    {
        currentFrequency = newFrequency;
        if (callback) {


@@ 48,7 83,7 @@ namespace sys
        }
    }

    bool CpuSentinel::HoldMinimumFrequencyAndWait(bsp::CpuFrequencyHz frequencyToHold,
    bool CpuSentinel::HoldMinimumFrequencyAndWait(bsp::CpuFrequencyMHz frequencyToHold,
                                                  TaskHandle_t taskToNotify,
                                                  uint32_t timeout)
    {


@@ 61,4 96,14 @@ namespace sys

        return true;
    }

    void CpuSentinel::ReadRegistrationData(bsp::CpuFrequencyMHz frequencyHz, bool permanentFrequency)
    {
        currentFrequency                  = frequencyHz;
        permanentFrequencyToHold.isActive = permanentFrequency;

        if (permanentFrequencyToHold.isActive) {
            permanentFrequencyToHold.frequencyToHold = currentFrequency;
        }
    }
} // namespace sys

M module-sys/SystemManager/PowerManager.cpp => module-sys/SystemManager/PowerManager.cpp +56 -31
@@ 73,10 73,26 @@ namespace sys

    void PowerManager::UpdateCpuFrequency(uint32_t cpuLoad)
    {
        const auto currentCpuFreq        = lowPowerControl->GetCurrentFrequencyLevel();
        const auto minFrequencyRequested = cpuGovernor->GetMinimumFrequencyRequested();
        const auto currentCpuFreq           = lowPowerControl->GetCurrentFrequencyLevel();
        const auto minFrequencyRequested    = cpuGovernor->GetMinimumFrequencyRequested();
        const auto permanentFrequencyToHold = cpuGovernor->GetPermanentFrequencyRequested();

        if (cpuLoad > powerProfile.frequencyShiftUpperThreshold && currentCpuFreq < bsp::CpuFrequencyHz::Level_6) {
        if (permanentFrequencyToHold.isActive) {
            auto frequencyToHold = std::max(permanentFrequencyToHold.frequencyToHold, powerProfile.minimalFrequency);

            if (currentCpuFreq < frequencyToHold) {
                IncreaseCpuFrequency(frequencyToHold);
            }
            else if (currentCpuFreq > frequencyToHold) {
                do {
                    DecreaseCpuFrequency();
                } while (lowPowerControl->GetCurrentFrequencyLevel() > frequencyToHold);
            }
            ResetFrequencyShiftCounter();
            return;
        }

        if (cpuLoad > powerProfile.frequencyShiftUpperThreshold && currentCpuFreq < bsp::CpuFrequencyMHz::Level_6) {
            aboveThresholdCounter++;
            belowThresholdCounter = 0;
        }


@@ 98,13 114,13 @@ namespace sys
            IncreaseCpuFrequency(minFrequencyRequested);
        }
        else if (aboveThresholdCounter >= powerProfile.maxAboveThresholdCount) {
            if (powerProfile.frequencyIncreaseIntermediateStep && currentCpuFreq < bsp::CpuFrequencyHz::Level_4) {
            if (powerProfile.frequencyIncreaseIntermediateStep && currentCpuFreq < bsp::CpuFrequencyMHz::Level_4) {
                ResetFrequencyShiftCounter();
                IncreaseCpuFrequency(bsp::CpuFrequencyHz::Level_4);
                IncreaseCpuFrequency(bsp::CpuFrequencyMHz::Level_4);
            }
            else {
                ResetFrequencyShiftCounter();
                IncreaseCpuFrequency(bsp::CpuFrequencyHz::Level_6);
                IncreaseCpuFrequency(bsp::CpuFrequencyMHz::Level_6);
            }
        }
        else {


@@ 117,11 133,11 @@ namespace sys
        }
    }

    void PowerManager::IncreaseCpuFrequency(bsp::CpuFrequencyHz newFrequency)
    void PowerManager::IncreaseCpuFrequency(bsp::CpuFrequencyMHz newFrequency)
    {
        const auto freq = lowPowerControl->GetCurrentFrequencyLevel();

        if ((freq <= bsp::CpuFrequencyHz::Level_1) && (newFrequency > bsp::CpuFrequencyHz::Level_1)) {
        if ((freq <= bsp::CpuFrequencyMHz::Level_1) && (newFrequency > bsp::CpuFrequencyMHz::Level_1)) {
            // connect internal the load resistor
            lowPowerControl->ConnectInternalLoadResistor();
            // turn off power save mode for DCDC inverter


@@ 137,8 153,8 @@ namespace sys
                driverSEMC->SwitchToPLL2ClockSource();
            }
            // Add intermediate step in frequency
            if (newFrequency > bsp::CpuFrequencyHz::Level_4)
                SetCpuFrequency(bsp::CpuFrequencyHz::Level_4);
            if (newFrequency > bsp::CpuFrequencyMHz::Level_4)
                SetCpuFrequency(bsp::CpuFrequencyMHz::Level_4);
        }

        // and increase frequency


@@ 153,24 169,24 @@ namespace sys
        auto level      = powerProfile.minimalFrequency;

        switch (freq) {
        case bsp::CpuFrequencyHz::Level_6:
            level = bsp::CpuFrequencyHz::Level_5;
        case bsp::CpuFrequencyMHz::Level_6:
            level = bsp::CpuFrequencyMHz::Level_5;
            break;
        case bsp::CpuFrequencyHz::Level_5:
            level = bsp::CpuFrequencyHz::Level_4;
        case bsp::CpuFrequencyMHz::Level_5:
            level = bsp::CpuFrequencyMHz::Level_4;
            break;
        case bsp::CpuFrequencyHz::Level_4:
            level = bsp::CpuFrequencyHz::Level_3;
        case bsp::CpuFrequencyMHz::Level_4:
            level = bsp::CpuFrequencyMHz::Level_3;
            break;
        case bsp::CpuFrequencyHz::Level_3:
            level = bsp::CpuFrequencyHz::Level_2;
        case bsp::CpuFrequencyMHz::Level_3:
            level = bsp::CpuFrequencyMHz::Level_2;
            break;
        case bsp::CpuFrequencyHz::Level_2:
        case bsp::CpuFrequencyMHz::Level_2:
            level = powerProfile.minimalFrequency;
            break;
        case bsp::CpuFrequencyHz::Level_1:
        case bsp::CpuFrequencyMHz::Level_1:
            [[fallthrough]];
        case bsp::CpuFrequencyHz::Level_0:
        case bsp::CpuFrequencyMHz::Level_0:
            break;
        }



@@ 179,7 195,7 @@ namespace sys
            SetCpuFrequency(level);
        }

        if (level <= bsp::CpuFrequencyHz::Level_1) {
        if (level <= bsp::CpuFrequencyMHz::Level_1) {
            // Enable weak 2P5 and 1P1 LDO and Turn off regular 2P5 and 1P1 LDO
            lowPowerControl->SwitchToLowPowerModeLDO();



@@ 203,20 219,30 @@ namespace sys

    void PowerManager::RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel) const
    {
        cpuGovernor->RegisterNewSentinel(newSentinel);
        if (cpuGovernor->RegisterNewSentinel(newSentinel)) {
            newSentinel->ReadRegistrationData(lowPowerControl->GetCurrentFrequencyLevel(),
                                              cpuGovernor->GetPermanentFrequencyRequested().isActive);
        }
    }

    void PowerManager::SetCpuFrequencyRequest(std::string sentinelName, bsp::CpuFrequencyHz request)
    void PowerManager::RemoveSentinel(std::string sentinelName) const
    {
        cpuGovernor->SetCpuFrequencyRequest(std::move(sentinelName), request);
        cpuGovernor->RemoveSentinel(sentinelName);
    }

    void PowerManager::ResetCpuFrequencyRequest(std::string sentinelName)
    void PowerManager::SetCpuFrequencyRequest(std::string sentinelName,
                                              bsp::CpuFrequencyMHz request,
                                              bool permanentBlock)
    {
        cpuGovernor->ResetCpuFrequencyRequest(std::move(sentinelName));
        cpuGovernor->SetCpuFrequencyRequest(std::move(sentinelName), request, permanentBlock);
    }

    void PowerManager::SetCpuFrequency(bsp::CpuFrequencyHz freq)
    void PowerManager::ResetCpuFrequencyRequest(std::string sentinelName, bool permanentBlock)
    {
        cpuGovernor->ResetCpuFrequencyRequest(std::move(sentinelName), permanentBlock);
    }

    void PowerManager::SetCpuFrequency(bsp::CpuFrequencyMHz freq)
    {
        UpdateCpuFrequencyMonitor(lowPowerControl->GetCurrentFrequencyLevel());
        lowPowerControl->SetCpuFrequency(freq);


@@ 234,12 260,12 @@ namespace sys
        return driverSEMC;
    }

    void PowerManager::UpdateCpuFrequencyMonitor(bsp::CpuFrequencyHz currentFreq)
    void PowerManager::UpdateCpuFrequencyMonitor(bsp::CpuFrequencyMHz currentFreq)
    {
        auto ticks     = xTaskGetTickCount();
        auto levelName = currentFreq == powerProfile.minimalFrequency
                             ? lowestLevelName
                             : (currentFreq == bsp::CpuFrequencyHz::Level_6 ? highestLevelName : middleLevelName);
                             : (currentFreq == bsp::CpuFrequencyMHz::Level_6 ? highestLevelName : middleLevelName);

        for (auto &level : cpuFrequencyMonitor) {
            if (level.GetName() == levelName) {


@@ 266,5 292,4 @@ namespace sys
    {
        lowPowerControl->SetBootSuccess();
    }

} // namespace sys

M module-sys/SystemManager/SystemManagerCommon.cpp => module-sys/SystemManager/SystemManagerCommon.cpp +23 -3
@@ 570,6 570,13 @@ namespace sys
            return sys::MessageNone{};
        });

        connect(typeid(sys::SentinelRemovalMessage), [this](sys::Message *message) -> sys::MessagePointer {
            auto msg = static_cast<sys::SentinelRemovalMessage *>(message);
            powerManager->RemoveSentinel(msg->getSentinelName());

            return sys::MessageNone{};
        });

        connect(typeid(sys::HoldCpuFrequencyMessage), [this](sys::Message *message) -> sys::MessagePointer {
            auto msg = static_cast<sys::HoldCpuFrequencyMessage *>(message);
            powerManager->SetCpuFrequencyRequest(msg->getName(), msg->getRequest());


@@ 584,6 591,19 @@ namespace sys
            return sys::MessageNone{};
        });

        connect(typeid(sys::HoldCpuFrequencyPermanentlyMessage), [this](sys::Message *message) -> sys::MessagePointer {
            auto msg = static_cast<sys::HoldCpuFrequencyPermanentlyMessage *>(message);
            powerManager->SetCpuFrequencyRequest(msg->getName(), msg->getRequest(), true);

            return sys::MessageNone{};
        });

        connect(typeid(sys::ReleaseCpuPermanentFrequencyMessage), [this](sys::Message *message) -> sys::MessagePointer {
            auto msg = static_cast<sys::ReleaseCpuPermanentFrequencyMessage *>(message);
            powerManager->ResetCpuFrequencyRequest(msg->getName(), true);
            return sys::MessageNone{};
        });

        connect(typeid(app::manager::CheckIfStartAllowedMessage), [this](sys::Message *) -> sys::MessagePointer {
            switch (Store::Battery::get().levelState) {
            case Store::Battery::LevelState::Normal:


@@ 612,7 632,7 @@ namespace sys
        deviceManager->RegisterNewDevice(powerManager->getExternalRamDevice());

        cpuSentinel = std::make_shared<sys::CpuSentinel>(
            service::name::system_manager, this, [this](bsp::CpuFrequencyHz newFrequency) {
            service::name::system_manager, this, [this](bsp::CpuFrequencyMHz newFrequency) {
                UpdateResourcesAfterCpuFrequencyChange(newFrequency);
            });
        powerManager->RegisterNewSentinel(cpuSentinel);


@@ 699,9 719,9 @@ namespace sys
        powerManager->UpdateCpuFrequency(cpuStatistics->GetPercentageCpuLoad());
    }

    void SystemManagerCommon::UpdateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency)
    void SystemManagerCommon::UpdateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency)
    {
        if (newFrequency <= bsp::CpuFrequencyHz::Level_1) {
        if (newFrequency <= bsp::CpuFrequencyMHz::Level_1) {
            purefs::subsystem::disk_mgr()->pm_control(purefs::blkdev::pm_state::suspend);
        }
        else {

M module-sys/SystemManager/include/SystemManager/CpuGovernor.hpp => module-sys/SystemManager/include/SystemManager/CpuGovernor.hpp +14 -8
@@ 16,12 16,12 @@ namespace sys
      public:
        explicit GovernorSentinel(std::shared_ptr<CpuSentinel> newSentinel);
        [[nodiscard]] auto GetSentinel() const noexcept -> SentinelPointer;
        [[nodiscard]] auto GetRequestedFrequency() const noexcept -> bsp::CpuFrequencyHz;
        void SetRequestedFrequency(bsp::CpuFrequencyHz newFrequency);
        [[nodiscard]] auto GetRequestedFrequency() const noexcept -> bsp::CpuFrequencyMHz;
        void SetRequestedFrequency(bsp::CpuFrequencyMHz newFrequency);

      private:
        SentinelPointer sentinelPtr;
        bsp::CpuFrequencyHz requestedFrequency;
        bsp::CpuFrequencyMHz requestedFrequency;
    };

    using GovernorSentinelPointer = std::unique_ptr<GovernorSentinel>;


@@ 33,20 33,26 @@ namespace sys
    {

      public:
        void RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel);
        auto RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel) -> bool;
        auto RemoveSentinel(std::string sentinelName) -> void;
        [[nodiscard]] auto GetNumberOfRegisteredSentinels() const noexcept -> uint32_t;
        void PrintAllSentinels() const noexcept;

        void SetCpuFrequencyRequest(std::string sentinelName, bsp::CpuFrequencyHz request);
        void ResetCpuFrequencyRequest(std::string sentinelName);
        void SetCpuFrequencyRequest(std::string sentinelName,
                                    bsp::CpuFrequencyMHz request,
                                    bool permanentBlock = false);
        void ResetCpuFrequencyRequest(std::string sentinelName, bool permanentBlock = false);

        [[nodiscard]] auto GetMinimumFrequencyRequested() const noexcept -> bsp::CpuFrequencyHz;
        void InformSentinelsAboutCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency) const noexcept;
        [[nodiscard]] auto GetMinimumFrequencyRequested() const noexcept -> bsp::CpuFrequencyMHz;
        void InformSentinelsAboutCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency) const noexcept;

        [[nodiscard]] auto GetPermanentFrequencyRequested() const noexcept -> PermanentFrequencyToHold;

      private:
        static void PrintName(const GovernorSentinelPointer &element);

        GovernorSentinelsVector sentinels;
        PermanentFrequencyToHold permanentFrequencyToHold{false, bsp::CpuFrequencyMHz::Level_0};
    };

} // namespace sys

M module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp => module-sys/SystemManager/include/SystemManager/CpuSentinel.hpp +21 -7
@@ 12,6 12,12 @@

namespace sys
{
    struct PermanentFrequencyToHold
    {
        bool isActive;
        bsp::CpuFrequencyMHz frequencyToHold;
    };

    /// Each sentinel manages the requests, i.e. when it is needed it sends messages to CpuGovernor with the required
    /// minimum CPU frequency to perform the task (e.g. screen redraw). Furthermore, every sentinel is informed
    /// immediately after changing the frequency. This allows it to invoke a callback to the service to update their


@@ 22,27 28,35 @@ namespace sys
      public:
        explicit CpuSentinel(std::string name,
                             sys::Service *service,
                             std::function<void(bsp::CpuFrequencyHz)> callback = nullptr);
                             std::function<void(bsp::CpuFrequencyMHz)> callback = nullptr);
        ~CpuSentinel() = default;

        [[nodiscard]] auto GetName() const noexcept -> std::string;
        void HoldMinimumFrequency(bsp::CpuFrequencyHz frequencyToHold);
        bool HoldMinimumFrequencyAndWait(bsp::CpuFrequencyHz frequencyToHold,
        void HoldMinimumFrequency(bsp::CpuFrequencyMHz frequencyToHold);
        bool HoldMinimumFrequencyAndWait(bsp::CpuFrequencyMHz frequencyToHold,
                                         TaskHandle_t taskToNotify,
                                         uint32_t timeout);
        void ReleaseMinimumFrequency();
        void CpuFrequencyHasChanged(bsp::CpuFrequencyHz newFrequency);

        void HoldFrequencyPermanently(bsp::CpuFrequencyMHz frequencyToHold);
        [[nodiscard]] auto GetFrequency() const noexcept -> bsp::CpuFrequencyMHz;
        void ReleasePermanentFrequency();
        [[nodiscard]] bool isPermanentFrequencyActive();

        void CpuFrequencyHasChanged(bsp::CpuFrequencyMHz newFrequency);
        void ReadRegistrationData(bsp::CpuFrequencyMHz frequencyHz, bool permanentFrequency);

      protected:
        const std::string name;
        bsp::CpuFrequencyHz currentFrequencyToHold{bsp::CpuFrequencyHz::Level_0};
        std::atomic<bsp::CpuFrequencyHz> currentFrequency{bsp::CpuFrequencyHz::Level_0};
        bsp::CpuFrequencyMHz currentFrequencyToHold{bsp::CpuFrequencyMHz::Level_0};
        PermanentFrequencyToHold permanentFrequencyToHold{false, bsp::CpuFrequencyMHz::Level_0};
        std::atomic<bsp::CpuFrequencyMHz> currentFrequency{bsp::CpuFrequencyMHz::Level_0};
        sys::Service *owner{nullptr};

        /// function called from the PowerManager context
        /// to update resources immediately
        /// critical section or mutex support necessary
        std::function<void(bsp::CpuFrequencyHz)> callback;
        std::function<void(bsp::CpuFrequencyMHz)> callback;

        TaskHandle_t taskHandle = nullptr;
    };

M module-sys/SystemManager/include/SystemManager/PowerManager.hpp => module-sys/SystemManager/include/SystemManager/PowerManager.hpp +8 -5
@@ 51,23 51,26 @@ namespace sys
        [[nodiscard]] auto getExternalRamDevice() const noexcept -> std::shared_ptr<devices::Device>;

        void RegisterNewSentinel(std::shared_ptr<CpuSentinel> newSentinel) const;
        void SetCpuFrequencyRequest(std::string sentinelName, bsp::CpuFrequencyHz request);
        void ResetCpuFrequencyRequest(std::string sentinelName);
        void RemoveSentinel(std::string sentinelName) const;
        void SetCpuFrequencyRequest(std::string sentinelName,
                                    bsp::CpuFrequencyMHz request,
                                    bool permanentBlock = false);
        void ResetCpuFrequencyRequest(std::string sentinelName, bool permanentBlock = false);
        void LogPowerManagerEfficiency();
        void SetBootSuccess();

      private:
        /// called when the CPU frequency needs to be increased
        void IncreaseCpuFrequency(bsp::CpuFrequencyHz newFrequency);
        void IncreaseCpuFrequency(bsp::CpuFrequencyMHz newFrequency);

        /// called when the CPU frequency needs to be reduced
        /// @note the frequency is always reduced by one step
        void DecreaseCpuFrequency();

        void ResetFrequencyShiftCounter();
        void SetCpuFrequency(bsp::CpuFrequencyHz freq);
        void SetCpuFrequency(bsp::CpuFrequencyMHz freq);

        void UpdateCpuFrequencyMonitor(bsp::CpuFrequencyHz currentFreq);
        void UpdateCpuFrequencyMonitor(bsp::CpuFrequencyMHz currentFreq);

        uint32_t belowThresholdCounter{0};
        uint32_t aboveThresholdCounter{0};

M module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp => module-sys/SystemManager/include/SystemManager/SystemManagerCommon.hpp +1 -1
@@ 183,7 183,7 @@ namespace sys
        void CpuStatisticsTimerHandler();

        /// used for power management control for the filesystem
        void UpdateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency);
        void UpdateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyMHz newFrequency);

        bool cpuStatisticsTimerInit{false};


M module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp => module-sys/SystemManager/tests/unittest_CpuSentinelsGovernor.cpp +13 -13
@@ 39,27 39,27 @@ TEST_CASE("Power Manager CPU sentinels governor test")
        governor->RegisterNewSentinel(testSentinel_1);
        governor->RegisterNewSentinel(testSentinel_2);

        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_0);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyMHz::Level_0);

        governor->SetCpuFrequencyRequest("testSentinel_1", bsp::CpuFrequencyHz::Level_4);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_4);
        governor->SetCpuFrequencyRequest("testSentinel_1", bsp::CpuFrequencyMHz::Level_4);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyMHz::Level_4);

        governor->SetCpuFrequencyRequest("testSentinel_2", bsp::CpuFrequencyHz::Level_6);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_6);
        governor->SetCpuFrequencyRequest("testSentinel_2", bsp::CpuFrequencyMHz::Level_6);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyMHz::Level_6);

        governor->SetCpuFrequencyRequest("testSentinel_1", bsp::CpuFrequencyHz::Level_2);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_6);
        governor->SetCpuFrequencyRequest("testSentinel_1", bsp::CpuFrequencyMHz::Level_2);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyMHz::Level_6);

        governor->ResetCpuFrequencyRequest("testSentinel_2");
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_2);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyMHz::Level_2);

        governor->SetCpuFrequencyRequest("bedNameSentinel", bsp::CpuFrequencyHz::Level_6);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_2);
        governor->SetCpuFrequencyRequest("bedNameSentinel", bsp::CpuFrequencyMHz::Level_6);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyMHz::Level_2);

        governor->SetCpuFrequencyRequest("testSentinel_1", bsp::CpuFrequencyHz::Level_1);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_1);
        governor->SetCpuFrequencyRequest("testSentinel_1", bsp::CpuFrequencyMHz::Level_1);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyMHz::Level_1);

        governor->ResetCpuFrequencyRequest("testSentinel_1");
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyHz::Level_0);
        REQUIRE(governor->GetMinimumFrequencyRequested() == bsp::CpuFrequencyMHz::Level_0);
    }
}

M module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp => module-sys/common/include/system/messages/RequestCpuFrequencyMessage.hpp +17 -2
@@ 12,7 12,7 @@ namespace sys
    class HoldCpuFrequencyMessage : public sys::DataMessage
    {
      public:
        HoldCpuFrequencyMessage(std::string sentinelName, bsp::CpuFrequencyHz request)
        HoldCpuFrequencyMessage(std::string sentinelName, bsp::CpuFrequencyMHz request)
            : sys::DataMessage(MessageType::SystemManagerCpuFrequency), sentinelName(std::move(sentinelName)),
              frequencyRequested(request)
        {}


@@ 29,7 29,7 @@ namespace sys

      private:
        std::string sentinelName;
        bsp::CpuFrequencyHz frequencyRequested = bsp::CpuFrequencyHz::Level_0;
        bsp::CpuFrequencyMHz frequencyRequested = bsp::CpuFrequencyMHz::Level_0;
    };

    class ReleaseCpuFrequencyMessage : public sys::DataMessage


@@ 48,4 48,19 @@ namespace sys
        std::string sentinelName;
    };

    class HoldCpuFrequencyPermanentlyMessage : public HoldCpuFrequencyMessage
    {
      public:
        HoldCpuFrequencyPermanentlyMessage(std::string sentinelName, bsp::CpuFrequencyMHz request)
            : HoldCpuFrequencyMessage(sentinelName, request)
        {}
    };

    class ReleaseCpuPermanentFrequencyMessage : public ReleaseCpuFrequencyMessage
    {
      public:
        ReleaseCpuPermanentFrequencyMessage(std::string sentinelName) : ReleaseCpuFrequencyMessage(sentinelName)
        {}
    };

} // namespace sys

M module-sys/common/include/system/messages/SentinelRegistrationMessage.hpp => module-sys/common/include/system/messages/SentinelRegistrationMessage.hpp +18 -2
@@ 11,8 11,8 @@ namespace sys
    class SentinelRegistrationMessage : public sys::DataMessage
    {
      public:
        SentinelRegistrationMessage(std::shared_ptr<CpuSentinel> sentinelPtr)
            : sys::DataMessage(MessageType::SystemManagerRegistration), sentinel(sentinelPtr)
        explicit SentinelRegistrationMessage(std::shared_ptr<CpuSentinel> sentinelPtr)
            : sys::DataMessage(MessageType::SystemManagerSentinelRegistration), sentinel(sentinelPtr)
        {}

        [[nodiscard]] auto getSentinel() const noexcept -> std::shared_ptr<CpuSentinel>


@@ 23,4 23,20 @@ namespace sys
      private:
        std::shared_ptr<CpuSentinel> sentinel;
    };

    class SentinelRemovalMessage : public sys::DataMessage
    {
      public:
        explicit SentinelRemovalMessage(std::string sentinelName)
            : sys::DataMessage(MessageType::SystemManagerSentinelRemoval), sentinelName(std::move(sentinelName))
        {}

        [[nodiscard]] auto getSentinelName() const noexcept -> std::string
        {
            return sentinelName;
        };

      private:
        std::string sentinelName;
    };
} // namespace sys

M products/BellHybrid/EinkSentinelBell.cpp => products/BellHybrid/EinkSentinelBell.cpp +1 -1
@@ 9,7 9,7 @@ namespace service::eink
{
    namespace
    {
        constexpr auto RedrawEinkCpuFrequency = bsp::CpuFrequencyHz::Level_4;
        constexpr auto RedrawEinkCpuFrequency = bsp::CpuFrequencyMHz::Level_4;
    } // namespace

    EinkSentinel::EinkSentinel(std::string name, sys::Service *service) : sys::CpuSentinel(name, service)

M products/BellHybrid/services/audio/ServiceAudio.cpp => products/BellHybrid/services/audio/ServiceAudio.cpp +1 -1
@@ 303,7 303,7 @@ namespace service
    }
    void Audio::manageCpuSentinel()
    {
        isBusy() ? cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_6)
        isBusy() ? cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_6)
                 : cpuSentinel->ReleaseMinimumFrequency();
    }
    void Audio::initializeDatabase()

M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp => products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp +1 -1
@@ 183,7 183,7 @@ namespace bell::screen_light_control

    void ScreenLightController::cpuSentinelKeepOn()
    {
        cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyHz::Level_6);
        cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_6);
    }

    void ScreenLightController::cpuSentinelRelease()

M products/BellHybrid/services/evtmgr/user-activity-handler/UserActivityHandler.cpp => products/BellHybrid/services/evtmgr/user-activity-handler/UserActivityHandler.cpp +1 -1
@@ 9,7 9,7 @@ namespace evm
    namespace
    {
        constexpr auto userActivityTimerTime = std::chrono::seconds(10);
        constexpr auto userActivityCPULevel  = bsp::CpuFrequencyHz::Level_5;
        constexpr auto userActivityCPULevel  = bsp::CpuFrequencyMHz::Level_5;
    } // namespace

    UserActivityHandler::UserActivityHandler(std::shared_ptr<sys::CpuSentinel> cpuSentinel, sys::Service *parent)

M products/PurePhone/EinkSentinelPure.cpp => products/PurePhone/EinkSentinelPure.cpp +2 -2
@@ 10,8 10,8 @@ namespace service::eink
{
    namespace
    {
        constexpr auto RedrawLockedEinkCpuFrequency   = bsp::CpuFrequencyHz::Level_4;
        constexpr auto RedrawUnlockedEinkCpuFrequency = bsp::CpuFrequencyHz::Level_6;
        constexpr auto RedrawLockedEinkCpuFrequency   = bsp::CpuFrequencyMHz::Level_4;
        constexpr auto RedrawUnlockedEinkCpuFrequency = bsp::CpuFrequencyMHz::Level_6;
    } // namespace

    EinkSentinel::EinkSentinel(std::string name, sys::Service *service) : sys::CpuSentinel(name, service)

M source/MessageType.hpp => source/MessageType.hpp +2 -1
@@ 91,7 91,8 @@ enum class MessageType

    // System manager
    SystemManagerCpuFrequency,
    SystemManagerRegistration,
    SystemManagerSentinelRegistration,
    SystemManagerSentinelRemoval,

    // rtc messages
    EVMMinuteUpdated, ///< This message is send to current focused application on every minute time change.