~aleteoryx/muditaos

39718a08ea04ef45f50794117a7edfec6ddae023 — Piotr Tański 4 years ago f238160
[BH-903] Pre-wake up frontlight

Implemented a frontlight handling for the pre-wake up.
Major clean-up of the frontlight implementation.
34 files changed, 655 insertions(+), 306 deletions(-)

M module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp
M module-db/Interface/EventRecord.cpp
M module-db/Interface/EventRecord.hpp
M module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.cpp
M module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.hpp
M module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp
M module-services/service-evtmgr/screen-light-control/ControlFunctions.hpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp
M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp
M module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp
M module-services/service-time/AlarmOperations.cpp
M module-services/service-time/AlarmOperations.hpp
M products/BellHybrid/alarms/BellAlarmHandler.cpp
M products/BellHybrid/alarms/CMakeLists.txt
M products/BellHybrid/alarms/include/BellAlarmHandler.hpp
M products/BellHybrid/alarms/src/actions/FrontlightAction.cpp
M products/BellHybrid/alarms/src/actions/FrontlightAction.hpp
M products/BellHybrid/services/evtmgr/CMakeLists.txt
M products/BellHybrid/services/evtmgr/EventManager.cpp
M products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.cpp
D products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.hpp
M products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp
R products/BellHybrid/services/evtmgr/include/evtmgr/{ => backlight-handler}/BacklightHandler.hpp
M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp
A products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.hpp
M products/BellHybrid/services/time/AlarmOperations.cpp
M products/BellHybrid/services/time/include/time/AlarmOperations.hpp
M products/PurePhone/services/evtmgr/CMakeLists.txt
M products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.cpp
D products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.hpp
M products/PurePhone/services/evtmgr/include/evtmgr/BacklightHandler.hpp
M products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.cpp
A products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.hpp
M module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp => module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp +3 -1
@@ 42,7 42,9 @@ namespace bsp::eink_frontlight

    void setBrightness(BrightnessPercentage brightness)
    {
        pwm->SetDutyCycle(gammaCorrection(brightness));
        if (pwm) {
            pwm->SetDutyCycle(gammaCorrection(brightness));
        }
    }

    void turnOn()

M module-db/Interface/EventRecord.cpp => module-db/Interface/EventRecord.cpp +5 -0
@@ 93,3 93,8 @@ bool EventRecord::isValid() const
{
    return (EventInfo::isValid() && Record::isValid());
}

auto SingleEventRecord::isValid() const -> bool
{
    return EventInfo::isValid();
}

M module-db/Interface/EventRecord.hpp => module-db/Interface/EventRecord.hpp +2 -0
@@ 65,4 65,6 @@ struct SingleEventRecord : public Record, public EventInfo
    SingleEventRecord() = default;
    SingleEventRecord(std::shared_ptr<EventRecord> parent, TimePoint startDate, TimePoint endDate)
        : EventInfo{parent->name, startDate, endDate, parent->duration, parent->isAllDay}, parent{parent} {};

    auto isValid() const -> bool;
};

M module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.cpp => module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.cpp +13 -23
@@ 15,17 15,17 @@ namespace backlight
        constexpr auto screenLightTimerTimeout = std::chrono::seconds(5);
    } // namespace timers

    HandlerCommon::HandlerCommon(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
        : settings{std::move(settings)}, screenLightControl{std::make_shared<screen_light_control::ScreenLightControl>(
                                             parent)},
    HandlerCommon::HandlerCommon(std::shared_ptr<settings::Settings> settings,
                                 std::shared_ptr<screen_light_control::ScreenLightController> screenLightController,
                                 sys::Service *parent)
        : settings{std::move(settings)}, screenLightController{std::move(screenLightController)},
          screenLightTimer{std::make_shared<sys::TimerHandle>(sys::TimerFactory::createSingleShotTimer(
              parent, timers::screenLightTimerName, timers::screenLightTimerTimeout, [this](sys::Timer &t) {
                  if (getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic &&
                      screenLightControl->isLightOn()) {
                      screenLightControl->processRequest(screen_light_control::Action::turnOff);
                      this->screenLightController->isLightOn()) {
                      this->screenLightController->processRequest(screen_light_control::Action::turnOff);
                  }
              }))}

    {}

    void HandlerCommon::init()


@@ 33,34 33,24 @@ namespace backlight
        using namespace screen_light_control;
        settings->registerValueChange(settings::Brightness::brightnessLevel, [&](const std::string &value) {
            ManualModeParameters params{utils::getNumericValue<float>(value)};
            screenLightControl->processRequest(Action::setManualModeBrightness, Parameters(params));
            screenLightController->processRequest(Action::setManualModeBrightness, Parameters(params));
        });

        settings->registerValueChange(settings::Brightness::autoMode, [&]([[maybe_unused]] const std::string &value) {
            const auto action = getScreenAutoModeState() == ScreenLightMode::Automatic ? Action::enableAutomaticMode
                                                                                       : Action::disableAutomaticMode;
            screenLightControl->processRequest(action);
            screenLightController->processRequest(action);
        });

        settings->registerValueChange(settings::Brightness::state, [&]([[maybe_unused]] const std::string &value) {
            const auto action = getScreenLightState() ? Action::turnOn : Action::turnOff;
            if (action == Action::turnOn) {
                screenLightTimer->start();
                onScreenLightTurnedOn();
            }
            screenLightControl->processRequest(action);
            screenLightController->processRequest(action);
        });
    }

    void HandlerCommon::processScreenRequest(screen_light_control::Action action,
                                             const screen_light_control::Parameters &params)
    {
        if (action == screen_light_control::Action::enableAutomaticMode) {
            startScreenLightTimer();
        }
        handleScreenLightSettings(action, params);
        screenLightControl->processRequest(action, params);
    }

    auto HandlerCommon::getValue(const std::string &path) const -> std::string
    {
        return settings->getValue(path);


@@ 95,8 85,8 @@ namespace backlight
    void HandlerCommon::handleScreenLightRefresh()
    {
        if (getScreenLightState() && getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic) {
            if (!screenLightControl->isLightOn()) {
                screenLightControl->processRequest(screen_light_control::Action::turnOn);
            if (!screenLightController->isLightOn()) {
                screenLightController->processRequest(screen_light_control::Action::turnOn);
            }
            startScreenLightTimer();
        }


@@ 119,7 109,7 @@ namespace backlight
            break;
        case screen_light_control::Action::turnOn:
            setValue(settings::Brightness::state, utils::to_string(true));
            screenLightTimer->start();
            onScreenLightTurnedOn();
            break;
        case screen_light_control::Action::setManualModeBrightness:
            if (params.hasManualModeParams()) {

M module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.hpp => module-services/service-evtmgr/backlight-handler/BacklightHandlerCommon.hpp +10 -5
@@ 19,7 19,9 @@ namespace backlight
    class HandlerCommon
    {
      public:
        HandlerCommon(std::shared_ptr<settings::Settings> settings, sys::Service *parent);
        HandlerCommon(std::shared_ptr<settings::Settings> settings,
                      std::shared_ptr<screen_light_control::ScreenLightController> screenLightController,
                      sys::Service *parent);

        /// initialise in InitHandler when Service is ready
        void init();


@@ 27,24 29,27 @@ namespace backlight
        /// Process request of the screen light control
        /// @screen_light_control::Action an action to perform
        /// @screen_light_control::Parameters parameters being set
        void processScreenRequest(screen_light_control::Action action, const screen_light_control::Parameters &params);
        virtual void processScreenRequest(screen_light_control::Action action,
                                          const screen_light_control::Parameters &params) = 0;

        [[nodiscard]] auto getScreenLightState() const noexcept -> bool;
        [[nodiscard]] auto getScreenAutoModeState() const noexcept -> screen_light_control::ScreenLightMode;
        [[nodiscard]] auto getScreenBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage;

      private:
        virtual void onScreenLightTurnedOn() = 0;

        std::shared_ptr<settings::Settings> settings;
        std::shared_ptr<screen_light_control::ScreenLightControl> screenLightControl;
        std::shared_ptr<screen_light_control::ScreenLightController> screenLightController;

      public:
        auto getScreenLightTimer() noexcept -> std::shared_ptr<sys::TimerHandle>
        {
            return screenLightTimer;
        }
        auto getScreenLightControl() noexcept -> std::shared_ptr<screen_light_control::ScreenLightControl>
        auto getScreenLightControl() noexcept -> std::shared_ptr<screen_light_control::ScreenLightController>
        {
            return screenLightControl;
            return screenLightController;
        }
        void handleScreenLightSettings(screen_light_control::Action action,
                                       const screen_light_control::Parameters &params);

M module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp => module-services/service-evtmgr/screen-light-control/ControlFunctions.cpp +14 -0
@@ 95,9 95,23 @@ namespace screen_light_control::functions
        }
    }

    void setRampState(float state)
    {
        rampState = state;
    }

    void setRampTarget(bsp::eink_frontlight::BrightnessPercentage value)
    {
        rampTarget = value;
    }

    bool isRampTargetReached()
    {
        return rampTargetReached;
    }

    bsp::eink_frontlight::BrightnessPercentage getRampState()
    {
        return rampState;
    }
} // namespace screen_light_control::functions

M module-services/service-evtmgr/screen-light-control/ControlFunctions.hpp => module-services/service-evtmgr/screen-light-control/ControlFunctions.hpp +13 -0
@@ 5,6 5,8 @@

#include <bsp/eink_frontlight/eink_frontlight.hpp>
#include <bsp/light_sensor/light_sensor.hpp>

#include <chrono>
#include <vector>
#include <utility>



@@ 13,10 15,18 @@ namespace screen_light_control::functions
    using BrightnessFunction =
        std::vector<std::pair<bsp::light_sensor::IlluminanceLux, bsp::eink_frontlight::BrightnessPercentage>>;

    struct LinearProgressFunction
    {
        float target                       = 100.0f;
        std::chrono::milliseconds duration = std::chrono::milliseconds::zero();
    };

    bsp::eink_frontlight::BrightnessPercentage brightnessRampOut();

    void calculateBrightness(bsp::light_sensor::IlluminanceLux measurement);

    void setRampState(float state);

    void setRampStep(float step);

    void setHysteresis(float hyst);


@@ 25,4 35,7 @@ namespace screen_light_control::functions

    void setRampTarget(bsp::eink_frontlight::BrightnessPercentage value);

    bool isRampTargetReached();

    bsp::eink_frontlight::BrightnessPercentage getRampState();
} // namespace screen_light_control::functions

M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp +9 -39
@@ 20,46 20,16 @@ namespace sys
/// Processing of ambient light sensor input to screen brightness output.
namespace screen_light_control
{
    /// Control screen light and keeps it's current state
    class ScreenLightControl
    class ScreenLightController
    {
      public:
        explicit ScreenLightControl(sys::Service *parent);
        ~ScreenLightControl();

        void processRequest(Action action);
        void processRequest(Action action, const Parameters &params);

        [[nodiscard]] auto isLightOn() const noexcept -> bool;
        [[nodiscard]] auto getAutoModeState() const noexcept -> ScreenLightMode;
        [[nodiscard]] auto getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage;

      private:
        void controlTimerCallback();
        void readoutTimerCallback();

        void enableTimers();
        void disableTimers();

        void setParameters(const AutomaticModeParameters &params);
        void setParameters(ManualModeParameters params);
        void setManualBrightnessLevel();

        void turnOff();
        void turnOn();

        void enableAutomaticMode();
        void disableAutomaticMode();

        static constexpr inline auto CONTROL_TIMER_MS = 25;
        static constexpr inline auto READOUT_TIMER_MS = 500;

        sys::TimerHandle controlTimer;
        sys::TimerHandle readoutTimer;

        bool lightOn                                               = false;
        screen_light_control::ScreenLightMode automaticMode        = ScreenLightMode::Manual;
        bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0;
        virtual ~ScreenLightController() noexcept = default;

        virtual void processRequest(Action action)                           = 0;
        virtual void processRequest(Action action, const Parameters &params) = 0;
        [[nodiscard]] virtual auto isLightOn() const noexcept -> bool        = 0;
        [[nodiscard]] virtual auto isAutoModeOn() const noexcept -> bool     = 0;
        [[nodiscard]] virtual auto getBrightnessValue() const noexcept
            -> bsp::eink_frontlight::BrightnessPercentage = 0;
    };

} // namespace screen_light_control

M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp => module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.cpp +6 -0
@@ 18,4 18,10 @@ namespace screen_light_control
        Expects(hasManualModeParams());
        return manualModeParams.value();
    }

    auto Parameters::getLinearProgressModeParams() const noexcept -> const LinearProgressModeParameters &
    {
        Expects(hasLinearProgressModeParams());
        return linearProgressModeParams.value();
    }
} // namespace screen_light_control

M module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp +28 -4
@@ 47,18 47,35 @@ namespace screen_light_control
        float gammaFactor = 2.5f;
    };

    struct LinearProgressModeParameters
    {
        using LinearFunctions = std::vector<functions::LinearProgressFunction>;

        /// Manually set starting value of the brightness
        float startBrightnessValue = 0.0f;
        /// Vector of linear functions of progressive screen brightness
        LinearFunctions functions{
            functions::LinearProgressFunction{.target = 100.0f, .duration = std::chrono::milliseconds{1500}}};
        /// Hysteresis value of screen brightness control
        float brightnessHysteresis = 0.0f;
    };

    class Parameters
    {
        std::optional<ManualModeParameters> manualModeParams;
        std::optional<AutomaticModeParameters> autoModeParams;
        std::optional<LinearProgressModeParameters> linearProgressModeParams;

      public:
        Parameters() = default;
        explicit Parameters(ManualModeParameters manualModeParams)
            : manualModeParams{std::make_optional(manualModeParams)}
        explicit Parameters(ManualModeParameters manualModeParams) : manualModeParams{manualModeParams}
        {}

        explicit Parameters(const AutomaticModeParameters &autoModeParams) : autoModeParams{autoModeParams}
        {}
        explicit Parameters(const AutomaticModeParameters &autoModeParams)
            : autoModeParams{std::make_optional(autoModeParams)}

        explicit Parameters(const LinearProgressModeParameters &autoModeParams)
            : linearProgressModeParams{autoModeParams}
        {}

        [[nodiscard]] bool hasManualModeParams() const noexcept


@@ 74,5 91,12 @@ namespace screen_light_control
        }

        [[nodiscard]] auto getAutoModeParams() const noexcept -> const AutomaticModeParameters &;

        [[nodiscard]] bool hasLinearProgressModeParams() const noexcept
        {
            return linearProgressModeParams.has_value();
        }

        [[nodiscard]] auto getLinearProgressModeParams() const noexcept -> const LinearProgressModeParameters &;
    };
} // namespace screen_light_control

M module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp => module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp +25 -2
@@ 14,16 14,23 @@ namespace sevm
    class ScreenLightControlMessage : public sys::DataMessage
    {
        const screen_light_control::Action action;
        std::optional<screen_light_control::Parameters> params;

      public:
        explicit ScreenLightControlMessage(screen_light_control::Action act)
            : sys::DataMessage(MessageType::ScreenLightControlAction), action(act)
        explicit ScreenLightControlMessage(screen_light_control::Action act,
                                           std::optional<screen_light_control::Parameters> params = std::nullopt)
            : sys::DataMessage(MessageType::ScreenLightControlAction), action(act), params{std::move(params)}
        {}

        [[nodiscard]] auto getAction() const noexcept -> screen_light_control::Action
        {
            return action;
        }

        [[nodiscard]] auto getParams() const noexcept -> const std::optional<screen_light_control::Parameters> &
        {
            return params;
        }
    };

    class ScreenLightSetAutoModeParams : public ScreenLightControlMessage


@@ 42,6 49,22 @@ namespace sevm
        }
    };

    class ScreenLightSetAutoProgressiveModeParams : public ScreenLightControlMessage
    {
        screen_light_control::LinearProgressModeParameters params;

      public:
        explicit ScreenLightSetAutoProgressiveModeParams(screen_light_control::LinearProgressModeParameters params)
            : ScreenLightControlMessage(screen_light_control::Action::setAutomaticModeParameters), params{std::move(
                                                                                                       params)}
        {}

        [[nodiscard]] auto getParams() const noexcept -> const screen_light_control::LinearProgressModeParameters &
        {
            return params;
        }
    };

    class ScreenLightSetManualModeParams : public ScreenLightControlMessage
    {
        screen_light_control::ManualModeParameters params;

M module-services/service-time/AlarmOperations.cpp => module-services/service-time/AlarmOperations.cpp +5 -0
@@ 350,10 350,15 @@ namespace alarms
            }
            else {
                handler->handleOff(*event);
                onAlarmTurnedOff(event, alarmType);
            }
        }
    }

    void AlarmOperationsCommon::onAlarmTurnedOff(const std::shared_ptr<AlarmEventRecord> &event,
                                                 alarms::AlarmType alarmType)
    {}

    auto AlarmOperationsCommon::processNextEventsQueue(const TimePoint now) -> void
    {
        if (nextSingleEvents.front()->startDate <= now) {

M module-services/service-time/AlarmOperations.hpp => module-services/service-time/AlarmOperations.hpp +1 -0
@@ 153,6 153,7 @@ namespace alarms
        void processEvents(TimePoint now);
        void processNextEventsQueue(const TimePoint now);
        void processSnoozedEventsQueue(const TimePoint now);
        virtual void onAlarmTurnedOff(const std::shared_ptr<AlarmEventRecord> &event, alarms::AlarmType alarmType);

        TimePoint getCurrentTime();
        void handleSnoozedAlarmsCountChange();

M products/BellHybrid/alarms/BellAlarmHandler.cpp => products/BellHybrid/alarms/BellAlarmHandler.cpp +12 -1
@@ 40,7 40,7 @@ namespace alarms
        Actions actions;
        actions.emplace_back(std::make_unique<PlayToneAction>(*service));
        actions.emplace_back(std::make_unique<NotifyGUIAction>(*service));
        actions.emplace_back(std::make_unique<FrontlightAction>(*service));
        actions.emplace_back(std::make_unique<FrontlightAction>(*service, FrontlightAction::Mode::Manual));
        return actions;
    }



@@ 54,6 54,17 @@ namespace alarms
        return actions;
    }

    PreWakeUpFrontlightHandler::PreWakeUpFrontlightHandler(sys::Service *service)
        : BellAlarmHandler(getActions(service))
    {}

    auto PreWakeUpFrontlightHandler::getActions(sys::Service *service) -> Actions
    {
        Actions actions;
        actions.emplace_back(std::make_unique<FrontlightAction>(*service, FrontlightAction::Mode::LinearProgress));
        return actions;
    }

    SnoozeChimeHandler::SnoozeChimeHandler(sys::Service *service) : BellAlarmHandler{getActions(service)}
    {}


M products/BellHybrid/alarms/CMakeLists.txt => products/BellHybrid/alarms/CMakeLists.txt +1 -0
@@ 38,6 38,7 @@ target_link_libraries(alarms
        bell::db
        bell::appmgr
        bell::app-common
        bell::evtmgr
        apps-common
   PUBLIC
        module-db

M products/BellHybrid/alarms/include/BellAlarmHandler.hpp => products/BellHybrid/alarms/include/BellAlarmHandler.hpp +9 -0
@@ 41,6 41,15 @@ namespace alarms
        static auto getActions(sys::Service *service) -> Actions;
    };

    class PreWakeUpFrontlightHandler : public BellAlarmHandler
    {
      public:
        explicit PreWakeUpFrontlightHandler(sys::Service *service);

      private:
        static auto getActions(sys::Service *service) -> Actions;
    };

    class SnoozeChimeHandler : public BellAlarmHandler
    {
      public:

M products/BellHybrid/alarms/src/actions/FrontlightAction.cpp => products/BellHybrid/alarms/src/actions/FrontlightAction.cpp +115 -3
@@ 3,22 3,134 @@

#include "FrontlightAction.hpp"

#include <service-evtmgr/Constants.hpp>
#include <service-evtmgr/ScreenLightControlMessage.hpp>
#include <service-evtmgr/Constants.hpp>

#include <service-db/Settings.hpp>
#include <db/SystemSettings.hpp>
#include <module-utils/utility/Utils.hpp>

namespace alarms
{
    FrontlightAction::FrontlightAction(sys::Service &service) : service{service}
    namespace
    {
        class ManualFrontlightAction : public AbstractAlarmAction
        {
          public:
            explicit ManualFrontlightAction(sys::Service &service);
            bool execute() override;
            bool turnOff() override;

          private:
            screen_light_control::ManualModeParameters prepareParameters();

            sys::Service &service;
        };

        class LinearProgressFrontlightAction : public AbstractAlarmAction
        {
          public:
            explicit LinearProgressFrontlightAction(sys::Service &service);
            bool execute() override;
            bool turnOff() override;

          private:
            screen_light_control::LinearProgressModeParameters prepareParameters();

            sys::Service &service;
            settings::Settings settings;
        };

        std::unique_ptr<AbstractAlarmAction> createFrontlightImplementation(sys::Service &service,
                                                                            FrontlightAction::Mode mode)
        {
            switch (mode) {
            case FrontlightAction::Mode::Manual:
                return std::make_unique<ManualFrontlightAction>(service);
            case FrontlightAction::Mode::LinearProgress:
                return std::make_unique<LinearProgressFrontlightAction>(service);
            }
            return nullptr;
        }
    } // namespace

    FrontlightAction::FrontlightAction(sys::Service &service, Mode mode)
        : pimpl{createFrontlightImplementation(service, mode)}
    {}

    bool FrontlightAction::execute()
    {
        return pimpl->execute();
    }

    bool FrontlightAction::turnOff()
    {
        return pimpl->turnOff();
    }

    ManualFrontlightAction::ManualFrontlightAction(sys::Service &service) : service{service}
    {}

    bool ManualFrontlightAction::execute()
    {
        service.bus.sendUnicast(
            std::make_shared<sevm::ScreenLightControlMessage>(screen_light_control::Action::disableAutomaticMode),
            service::name::evt_manager);

        auto params = prepareParameters();
        service.bus.sendUnicast(std::make_shared<sevm::ScreenLightControlMessage>(
                                    screen_light_control::Action::turnOn, screen_light_control::Parameters{params}),
                                service::name::evt_manager);
        return true;
    }

    screen_light_control::ManualModeParameters ManualFrontlightAction::prepareParameters()
    {
        return screen_light_control::ManualModeParameters{.manualModeBrightness = 100.0f};
    }

    bool ManualFrontlightAction::turnOff()
    {
        service.bus.sendUnicast(
            std::make_shared<sevm::ScreenLightControlMessage>(screen_light_control::Action::turnOff),
            service::name::evt_manager);
        return true;
    }

    LinearProgressFrontlightAction::LinearProgressFrontlightAction(sys::Service &service) : service{service}
    {
        settings.init(service::ServiceProxy{service.weak_from_this()});
    }

    bool LinearProgressFrontlightAction::execute()
    {
        const auto params = prepareParameters();
        service.bus.sendUnicast(std::make_shared<sevm::ScreenLightSetAutoProgressiveModeParams>(params),
                                service::name::evt_manager);
        service.bus.sendUnicast(
            std::make_shared<sevm::ScreenLightControlMessage>(screen_light_control::Action::enableAutomaticMode),
            service::name::evt_manager);
        service.bus.sendUnicast(std::make_shared<sevm::ScreenLightControlMessage>(screen_light_control::Action::turnOn),
                                service::name::evt_manager);
        return true;
    }

    bool FrontlightAction::turnOff()
    screen_light_control::LinearProgressModeParameters LinearProgressFrontlightAction::prepareParameters()
    {
        constexpr auto firstTargetDuration = std::chrono::seconds{5};
        const auto value = settings.getValue(bell::settings::PrewakeUp::lightDuration, settings::SettingsScope::Global);
        const auto lightDuration        = std::chrono::minutes{utils::toNumeric(value)};
        const auto secondTargetDuration = lightDuration - std::chrono::minutes{1} - firstTargetDuration;
        return screen_light_control::LinearProgressModeParameters{
            .startBrightnessValue = 0.0f,
            .functions            = {screen_light_control::functions::LinearProgressFunction{.target   = 10.0f,
                                                                                  .duration = firstTargetDuration},
                          screen_light_control::functions::LinearProgressFunction{.target   = 100.0f,
                                                                                  .duration = secondTargetDuration}},
            .brightnessHysteresis = 0.0f};
    }

    bool LinearProgressFrontlightAction::turnOff()
    {
        service.bus.sendUnicast(
            std::make_shared<sevm::ScreenLightControlMessage>(screen_light_control::Action::turnOff),

M products/BellHybrid/alarms/src/actions/FrontlightAction.hpp => products/BellHybrid/alarms/src/actions/FrontlightAction.hpp +8 -3
@@ 12,12 12,17 @@ namespace alarms
    class FrontlightAction : public AbstractAlarmAction
    {
      public:
        explicit FrontlightAction(sys::Service &service);
        enum class Mode
        {
            Manual,
            LinearProgress
        };

        FrontlightAction(sys::Service &service, Mode mode);
        bool execute() override;
        bool turnOff() override;

      private:
        sys::Service &service;
        std::unique_ptr<AbstractAlarmAction> pimpl;
    };

} // namespace alarms

M products/BellHybrid/services/evtmgr/CMakeLists.txt => products/BellHybrid/services/evtmgr/CMakeLists.txt +1 -0
@@ 24,6 24,7 @@ target_sources(evtmgr
    PUBLIC
        include/evtmgr/EventManager.hpp
        include/evtmgr/api/TemperatureApi.hpp
        include/evtmgr/backlight-handler/BacklightHandler.hpp
)

target_include_directories(evtmgr

M products/BellHybrid/services/evtmgr/EventManager.cpp => products/BellHybrid/services/evtmgr/EventManager.cpp +8 -4
@@ 71,7 71,8 @@ void EventManager::initProductEvents()

    connect(typeid(sevm::ScreenLightControlMessage), [&](sys::Message *msgl) {
        auto *m = static_cast<sevm::ScreenLightControlMessage *>(msgl);
        backlightHandler.processScreenRequest(m->getAction(), screen_light_control::Parameters());
        const auto params = m->getParams();
        backlightHandler.processScreenRequest(m->getAction(), params.value_or(screen_light_control::Parameters()));
        return sys::msgHandled();
    });



@@ 81,6 82,12 @@ void EventManager::initProductEvents()
        return sys::msgHandled();
    });

    connect(typeid(sevm::ScreenLightSetAutoProgressiveModeParams), [&](sys::Message *msgl) {
        auto *m = static_cast<sevm::ScreenLightSetAutoProgressiveModeParams *>(msgl);
        backlightHandler.processScreenRequest(m->getAction(), screen_light_control::Parameters(m->getParams()));
        return sys::msgHandled();
    });

    connect(typeid(sevm::ScreenLightSetManualModeParams), [&](sys::Message *msgl) {
        auto *m = static_cast<sevm::ScreenLightSetManualModeParams *>(msgl);
        backlightHandler.processScreenRequest(m->getAction(), screen_light_control::Parameters(m->getParams()));


@@ 93,9 100,6 @@ void EventManager::initProductEvents()
            backlightHandler.getScreenLightState(), backlightHandler.getScreenAutoModeState(), params);
        return msg;
    });

    backlightHandler.processScreenRequest(screen_light_control::Action::enableAutomaticMode,
                                          screen_light_control::Parameters());
}

sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)

M products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.cpp => products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.cpp +35 -17
@@ 1,11 1,13 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <evtmgr/BacklightHandler.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
#include <evtmgr/backlight-handler/BacklightHandler.hpp>

#include <screen-light-control/ScreenLightControl.hpp>

#include <service-db/Settings.hpp>

#include <Timers/TimerFactory.hpp>
#include <Utils.hpp>
#include <keymap/KeyMap.hpp>

namespace backlight


@@ 17,29 19,45 @@ namespace backlight
    } // namespace timers

    Handler::Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
        : HandlerCommon(settings, parent), screenLightControl{getScreenLightControl()}, screenLightTimer{
                                                                                            getScreenLightTimer()}
        : HandlerCommon(
              std::move(settings), std::make_shared<bell::screen_light_control::ScreenLightController>(parent), parent)
    {}

    void Handler::handleKeyPressed([[maybe_unused]] const int key)
    void Handler::handleKeyPressed([[maybe_unused]] int key)
    {
        handleScreenLightRefresh(key);
    }

    void Handler::handleScreenLightRefresh([[maybe_unused]] const int key)
    void Handler::handleScreenLightRefresh([[maybe_unused]] int key)
    {
        if (getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic) {
            if (!screenLightControl->isLightOn() && (key == static_cast<int>(KeyMap::Frontlight))) {
                screenLightControl->processRequest(screen_light_control::Action::turnOn);
                screenLightTimer->restart(timers::screenLightTimerTimeout);
            }
            else if (screenLightControl->isLightOn() && (key != static_cast<int>(KeyMap::Frontlight))) {
                screenLightTimer->restart(timers::screenLightTimerHoldTimeout);
        auto controller = getScreenLightControl();
        auto timer      = getScreenLightTimer();
        if (!controller->isLightOn() && (key == static_cast<int>(KeyMap::Frontlight))) {
            controller->processRequest(screen_light_control::Action::turnOn);
            timer->restart(timers::screenLightTimerTimeout);
        }
        else if (controller->isLightOn()) {
            if (controller->isAutoModeOn() || key == static_cast<int>(KeyMap::Frontlight)) {
                controller->processRequest(screen_light_control::Action::turnOff);
                timer->stop();
            }
            else if (key == static_cast<int>(KeyMap::Frontlight)) {
                screenLightControl->processRequest(screen_light_control::Action::turnOff);
                screenLightTimer->stop();
            else {
                timer->restart(timers::screenLightTimerHoldTimeout);
            }
        }
    }

    void Handler::processScreenRequest(screen_light_control::Action action,
                                       const screen_light_control::Parameters &params)
    {
        handleScreenLightSettings(action, params);
        getScreenLightControl()->processRequest(action, params);
    }

    void Handler::onScreenLightTurnedOn()
    {
        if (!getScreenLightControl()->isAutoModeOn()) {
            startScreenLightTimer();
        }
    }
} // namespace backlight

D products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.hpp => products/BellHybrid/services/evtmgr/backlight-handler/BacklightHandler.hpp +0 -37
@@ 1,37 0,0 @@
// 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 <bsp/keypad_backlight/keypad_backlight.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <Timers/TimerHandle.hpp>
#include <Service/ServiceProxy.hpp>
#include <backlight-handler/BacklightHandlerCommon.hpp>

namespace settings
{
    class Settings;
} // namespace settings

namespace backlight
{
    /// @brief Backlight events handler
    class HandlerBell : public Handler
    {
      public:
        HandlerBell(std::shared_ptr<settings::Settings> settings, sys::Service *parent);

        void handleKeyPressed(const int key = 0);

      private:
        std::shared_ptr<settings::Settings> settings;
        std::unique_ptr<screen_light_control::ScreenLightControl> screenLightControl;
        /// Timer that keeps screen backlight on for a certain time if there was key pressed
        sys::TimerHandle screenLightTimer;
        void startScreenLightTimer();
        void handleScreenLightRefresh(const int key = 0);
        void handleScreenLightSettings(screen_light_control::Action action,
                                       const screen_light_control::Parameters &params);
    };
} // namespace backlight

M products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp => products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp +1 -1
@@ 5,7 5,7 @@

#include <service-evtmgr/EventManagerCommon.hpp>

#include "BacklightHandler.hpp"
#include "backlight-handler/BacklightHandler.hpp"

class KeySequenceMgr;


R products/BellHybrid/services/evtmgr/include/evtmgr/BacklightHandler.hpp => products/BellHybrid/services/evtmgr/include/evtmgr/backlight-handler/BacklightHandler.hpp +7 -5
@@ 22,12 22,14 @@ namespace backlight
      public:
        Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent);

        void handleKeyPressed([[maybe_unused]] const int key = 0);
        void handleKeyPressed(int key = 0);

        void processScreenRequest(screen_light_control::Action action,
                                  const screen_light_control::Parameters &params) override;

      private:
        std::shared_ptr<screen_light_control::ScreenLightControl> screenLightControl;
        /// Timer that keeps screen backlight on for a certain time if there was key pressed
        std::shared_ptr<sys::TimerHandle> screenLightTimer;
        void handleScreenLightRefresh([[maybe_unused]] const int key = 0);
        void handleScreenLightRefresh(int key = 0);

        void onScreenLightTurnedOn() override;
    };
} // namespace backlight

M products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp => products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.cpp +86 -48
@@ 1,44 1,42 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp>
#include <Timers/TimerFactory.hpp>
#include "ScreenLightControl.hpp"

#include <Service/Service.hpp>
#include <Timers/TimerFactory.hpp>

namespace screen_light_control
namespace bell::screen_light_control
{
    ScreenLightControl::ScreenLightControl(sys::Service *parent)
    ScreenLightController::ScreenLightController(sys::Service *parent)
    {
        controlTimer = sys::TimerFactory::createPeriodicTimer(parent,
                                                              "LightControlTimer",
                                                              std::chrono::milliseconds{CONTROL_TIMER_MS},
                                                              [this](sys::Timer &) { controlTimerCallback(); });
        readoutTimer = sys::TimerFactory::createPeriodicTimer(parent,
                                                              "LightSensorReadoutTimer",
                                                              std::chrono::milliseconds{READOUT_TIMER_MS},
                                                              [this](sys::Timer &) { readoutTimerCallback(); });

        setParameters(screen_light_control::AutomaticModeParameters());
        setParameters(ManualModeParameters{});
    }

    ScreenLightControl::~ScreenLightControl()
    ScreenLightController::~ScreenLightController()
    {
        disableTimers();
    }

    void ScreenLightControl::processRequest(Action action)
    void ScreenLightController::processRequest(Action action)
    {
        processRequest(action, Parameters());
        processRequest(action, Parameters{});
    }
    void ScreenLightControl::processRequest(Action action, const Parameters &params)

    void ScreenLightController::processRequest(Action action, const Parameters &params)
    {
        switch (action) {
        case Action::turnOff:
            turnOff();
            break;
        case Action::turnOn:
            turnOn();
            turnOn(params.hasManualModeParams() ? std::optional<ManualModeParameters>(params.getManualModeParams())
                                                : std::nullopt);
            break;
        case Action::enableAutomaticMode:
            enableAutomaticMode();


@@ 52,73 50,106 @@ namespace screen_light_control
            }
            break;
        case Action::setAutomaticModeParameters:
            if (params.hasAutoModeParams()) {
                setParameters(params.getAutoModeParams());
            if (params.hasLinearProgressModeParams()) {
                setParameters(params.getLinearProgressModeParams());
            }
            break;
        }
    }

    void ScreenLightControl::controlTimerCallback()
    void ScreenLightController::controlTimerCallback()
    {
        bsp::eink_frontlight::setBrightness(functions::brightnessRampOut());
    }
        auto currentBrightness = ::screen_light_control::functions::brightnessRampOut();

    void ScreenLightControl::readoutTimerCallback()
    {
        // functions::calculateBrightness(brightnessValue);
        bsp::eink_frontlight::setBrightness(currentBrightness);
        if (::screen_light_control::functions::isRampTargetReached()) {
            if (!automaticModeFunctions.empty()) {
                setUpAutomaticFunction(getNextAutomaticFunction(), currentBrightness);
            }
            else {
                disableAutomaticMode();
            }
        }
    }

    auto ScreenLightControl::getAutoModeState() const noexcept -> ScreenLightMode
    auto ScreenLightController::isLightOn() const noexcept -> bool
    {
        return automaticMode;
        return lightOn;
    }

    auto ScreenLightControl::isLightOn() const noexcept -> bool
    bool ScreenLightController::isAutoModeOn() const noexcept
    {
        return lightOn;
        return automaticMode == ScreenLightMode::Automatic;
    }

    auto ScreenLightControl::getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage
    auto ScreenLightController::getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage
    {
        return brightnessValue;
    }

    void ScreenLightControl::enableTimers()
    void ScreenLightController::enableTimers()
    {
        controlTimer.start();
        readoutTimer.start();
    }

    void ScreenLightControl::disableTimers()
    void ScreenLightController::disableTimers()
    {
        controlTimer.stop();
        readoutTimer.stop();
    }

    void ScreenLightControl::setParameters(const AutomaticModeParameters &params)
    void ScreenLightController::setParameters(const LinearProgressModeParameters &params)
    {
        if (params.functions.empty()) {
            LOG_ERROR("Functions are not defined. Cannot proceed with automatic mode.");
            disableTimers();
            return;
        }
        setAutomaticModeFunctions(params.functions);

        if (lightOn && automaticMode == ScreenLightMode::Automatic) {
            disableTimers();
        }

        functions::setRampStep(100.0f * (static_cast<float>(CONTROL_TIMER_MS) / static_cast<float>(params.rampTimeMS)));
        functions::setHysteresis(params.brightnessHysteresis);
        functions::setFunctionFromPoints(params.functionPoints);
        ::screen_light_control::functions::setHysteresis(params.brightnessHysteresis);
        setUpAutomaticFunction(getNextAutomaticFunction(), ::screen_light_control::functions::getRampState());
        setManualBrightnessLevel(params.startBrightnessValue);

        if (lightOn && automaticMode == ScreenLightMode::Automatic) {
            enableTimers();
        }
    }

    void ScreenLightControl::setParameters(ManualModeParameters params)
    void ScreenLightController::setAutomaticModeFunctions(
        const LinearProgressModeParameters::LinearFunctions &functions)
    {
        automaticModeFunctions = LinearProgressModeParameters::LinearFunctions{functions.rbegin(), functions.rend()};
    }

    ::screen_light_control::functions::LinearProgressFunction ScreenLightController::getNextAutomaticFunction()
    {
        auto function = automaticModeFunctions.back();
        automaticModeFunctions.pop_back();
        return function;
    }

    void ScreenLightController::setUpAutomaticFunction(
        ::screen_light_control::functions::LinearProgressFunction function,
        bsp::eink_frontlight::BrightnessPercentage currentBrightness)
    {
        ::screen_light_control::functions::setRampStep(
            std::abs(function.target - currentBrightness) /
            (static_cast<float>(function.duration.count()) / CONTROL_TIMER_MS));
        ::screen_light_control::functions::setRampTarget(function.target);
    }

    void ScreenLightController::setParameters(ManualModeParameters params)
    {
        brightnessValue = params.manualModeBrightness;
        functions::setRampTarget(brightnessValue);
        setManualBrightnessLevel();
        ::screen_light_control::functions::setRampTarget(brightnessValue);
        setManualBrightnessLevel(brightnessValue);
    }

    void ScreenLightControl::enableAutomaticMode()
    void ScreenLightController::enableAutomaticMode()
    {
        if (lightOn) {
            enableTimers();


@@ 126,15 157,22 @@ namespace screen_light_control
        automaticMode = ScreenLightMode::Automatic;
    }

    void ScreenLightControl::disableAutomaticMode()
    void ScreenLightController::disableAutomaticMode()
    {
        disableTimers();
        automaticMode = ScreenLightMode::Manual;
        setManualBrightnessLevel();
        automaticModeFunctions.clear();
        setManualBrightnessLevel(brightnessValue);
    }

    void ScreenLightControl::turnOn()
    void ScreenLightController::turnOn(const std::optional<ManualModeParameters> &params)
    {
        if (params.has_value()) {
            const auto brightness = params->manualModeBrightness;
            ::screen_light_control::functions::setRampTarget(brightness);
            setManualBrightnessLevel(brightness);
        }

        bsp::eink_frontlight::turnOn();
        if (automaticMode == ScreenLightMode::Automatic) {
            enableTimers();


@@ 142,16 180,16 @@ namespace screen_light_control
        lightOn = true;
    }

    void ScreenLightControl::setManualBrightnessLevel()
    void ScreenLightController::setManualBrightnessLevel(bsp::eink_frontlight::BrightnessPercentage brightness)
    {
        bsp::eink_frontlight::setBrightness(brightnessValue);
        bsp::eink_frontlight::setBrightness(brightness);
        ::screen_light_control::functions::setRampState(brightness);
    }

    void ScreenLightControl::turnOff()
    void ScreenLightController::turnOff()
    {
        bsp::eink_frontlight::turnOff();
        disableTimers();
        disableAutomaticMode();
        lightOn = false;
    }

} // namespace screen_light_control

A products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.hpp => products/BellHybrid/services/evtmgr/screen-light-control/ScreenLightControl.hpp +71 -0
@@ 0,0 1,71 @@
// 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 <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp>

#include <Timers/TimerHandle.hpp>

#include <memory>

namespace sys
{
    class Service;
} // namespace sys

/// Screen light control algorithm. Automatic/Manual mode of operation.
/// Processing of ambient light sensor input to screen brightness output.
namespace bell::screen_light_control
{
    /// Control screen light and keeps it's current state
    class ScreenLightController : public ::screen_light_control::ScreenLightController
    {
      public:
        using Action                       = ::screen_light_control::Action;
        using Parameters                   = ::screen_light_control::Parameters;
        using ScreenLightMode              = ::screen_light_control::ScreenLightMode;
        using ManualModeParameters         = ::screen_light_control::ManualModeParameters;
        using LinearProgressModeParameters = ::screen_light_control::LinearProgressModeParameters;

        explicit ScreenLightController(sys::Service *parent);
        ~ScreenLightController() override;

        void processRequest(Action action) override;
        void processRequest(Action action, const Parameters &params) override;

        [[nodiscard]] auto isLightOn() const noexcept -> bool override;
        [[nodiscard]] bool isAutoModeOn() const noexcept override;
        [[nodiscard]] auto getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage override;

      private:
        void controlTimerCallback();

        void enableTimers();
        void disableTimers();

        void setParameters(const LinearProgressModeParameters &params);
        void setParameters(ManualModeParameters params);
        void setManualBrightnessLevel(bsp::eink_frontlight::BrightnessPercentage brightness);

        void setAutomaticModeFunctions(const LinearProgressModeParameters::LinearFunctions &functions);
        ::screen_light_control::functions::LinearProgressFunction getNextAutomaticFunction();
        void setUpAutomaticFunction(::screen_light_control::functions::LinearProgressFunction function,
                                    bsp::eink_frontlight::BrightnessPercentage currentBrightness);

        void turnOff();
        void turnOn(const std::optional<ManualModeParameters> &params = std::nullopt);

        void enableAutomaticMode();
        void disableAutomaticMode();

        static constexpr inline auto CONTROL_TIMER_MS = 25;

        sys::TimerHandle controlTimer;
        bool lightOn                                               = false;
        ScreenLightMode automaticMode                              = ScreenLightMode::Manual;
        bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0;
        LinearProgressModeParameters::LinearFunctions automaticModeFunctions;
    };
} // namespace bell::screen_light_control

M products/BellHybrid/services/time/AlarmOperations.cpp => products/BellHybrid/services/time/AlarmOperations.cpp +32 -2
@@ 119,6 119,8 @@ namespace alarms
                                                  std::make_shared<alarms::BellAlarmClockHandler>(service));
        alarmOperations->addAlarmExecutionHandler(alarms::AlarmType::PreWakeUpChime,
                                                  std::make_shared<alarms::PreWakeUpChimeHandler>(service));
        alarmOperations->addAlarmExecutionHandler(alarms::AlarmType::PreWakeUpFrontlight,
                                                  std::make_shared<alarms::PreWakeUpFrontlightHandler>(service));
        alarmOperations->addAlarmExecutionHandler(alarms::AlarmType::SnoozeChime,
                                                  std::make_shared<alarms::SnoozeChimeHandler>(service));
        alarmOperations->addAlarmExecutionHandler(alarms::AlarmType::BedtimeReminder,


@@ 157,8 159,8 @@ namespace alarms
            return;
        }

        auto nextEvent = *(nextSingleEvents.front());
        if (getAlarmEventType(nextEvent) != alarms::AlarmType::Clock) {
        auto nextEvent = getNextPreWakeUpEvent();
        if (!nextEvent.isValid()) {
            return;
        }



@@ 178,6 180,23 @@ namespace alarms
        }
    }

    SingleEventRecord AlarmOperations::getNextPreWakeUpEvent()
    {
        const auto event = *(nextSingleEvents.front());
        if (getAlarmEventType(event) != alarms::AlarmType::Clock) {
            return {};
        }

        auto found = std::find_if(snoozedSingleEvents.begin(), snoozedSingleEvents.end(), [ev = event](auto &event) {
            return ev.parent->ID == event->parent->ID;
        });
        if (found != snoozedSingleEvents.end()) {
            return {};
        }

        return event;
    }

    void AlarmOperations::handlePreWakeUp(const SingleEventRecord &event, PreWakeUp::Decision decision)
    {
        if (auto alarmEventPtr = std::dynamic_pointer_cast<AlarmEventRecord>(event.parent); alarmEventPtr) {


@@ 225,6 244,17 @@ namespace alarms
        }
    }

    void AlarmOperations::onAlarmTurnedOff([[maybe_unused]] const std::shared_ptr<AlarmEventRecord> &event,
                                           alarms::AlarmType alarmType)
    {
        if (alarmType != alarms::AlarmType::Clock) {
            return;
        }

        handleAlarmEvent(event, alarms::AlarmType::PreWakeUpChime, false);
        handleAlarmEvent(event, alarms::AlarmType::PreWakeUpFrontlight, false);
    }

    PreWakeUp::PreWakeUp(std::unique_ptr<PreWakeUpSettingsProvider> &&settingsProvider)
        : settingsProvider{std::move(settingsProvider)}
    {}

M products/BellHybrid/services/time/include/time/AlarmOperations.hpp => products/BellHybrid/services/time/include/time/AlarmOperations.hpp +2 -0
@@ 101,10 101,12 @@ namespace alarms
        void stopAllSnoozeChimes();

      private:
        SingleEventRecord getNextPreWakeUpEvent();
        void handlePreWakeUp(const SingleEventRecord &event, PreWakeUp::Decision decision);
        void handleSnoozeChime(const SingleEventRecord &event, bool newStateOn);
        void handleBedtime(const SingleEventRecord &event, bool decision);
        void processBedtime(TimePoint now);
        void onAlarmTurnedOff(const std::shared_ptr<AlarmEventRecord> &event, alarms::AlarmType alarmType) override;

        PreWakeUp preWakeUp;
        std::unique_ptr<SnoozeChimeSettingsProvider> snoozeChimeSettings;

M products/PurePhone/services/evtmgr/CMakeLists.txt => products/PurePhone/services/evtmgr/CMakeLists.txt +1 -1
@@ 14,7 14,7 @@ target_sources(evtmgr

target_include_directories(evtmgr
    PRIVATE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)

M products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.cpp => products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.cpp +22 -6
@@ 2,6 2,8 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <evtmgr/BacklightHandler.hpp>
#include <screen-light-control/ScreenLightControl.hpp>

#include <service-db/agents/settings/SystemSettings.hpp>
#include <service-db/Settings.hpp>
#include <Timers/TimerFactory.hpp>


@@ 16,21 18,30 @@ namespace backlight
    } // namespace timers

    Handler::Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
        : HandlerCommon(settings, parent), screenLightControl{getScreenLightControl()},
          screenLightTimer{getScreenLightTimer()},

        : HandlerCommon(
              std::move(settings), std::make_shared<pure::screen_light_control::ScreenLightController>(parent), parent),
          keypadLightTimer{sys::TimerFactory::createSingleShotTimer(
              parent, timers::keypadLightTimerName, timers::keypadLightTimerTimeout, [this](sys::Timer &) {
                  bsp::keypad_backlight::shutdown();
              })}
    {}

    void Handler::handleKeyPressed()
    void Handler::handleKeyPressed([[maybe_unused]] int key)
    {
        handleKeypadLightRefresh();
        handleScreenLightRefresh();
    }

    void Handler::processScreenRequest(screen_light_control::Action action,
                                       const screen_light_control::Parameters &params)
    {
        if (action == screen_light_control::Action::enableAutomaticMode) {
            startScreenLightTimer();
        }
        handleScreenLightSettings(action, params);
        getScreenLightControl()->processRequest(action, params);
    }

    void Handler::stopKeypadTimer()
    {
        if (keypadLightState == bsp::keypad_backlight::State::activeMode) {


@@ 116,10 127,15 @@ namespace backlight
    void Handler::handleScreenLightRefresh([[maybe_unused]] const int key)
    {
        if (getScreenLightState() && getScreenAutoModeState() == screen_light_control::ScreenLightMode::Automatic) {
            if (!screenLightControl->isLightOn()) {
                screenLightControl->processRequest(screen_light_control::Action::turnOn);
            if (!getScreenLightControl()->isLightOn()) {
                getScreenLightControl()->processRequest(screen_light_control::Action::turnOn);
            }
            startScreenLightTimer();
        }
    }

    void Handler::onScreenLightTurnedOn()
    {
        startScreenLightTimer();
    }
} // namespace backlight

D products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.hpp => products/PurePhone/services/evtmgr/backlight-handler/BacklightHandler.hpp +0 -67
@@ 1,67 0,0 @@
// 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 <bsp/keypad_backlight/keypad_backlight.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <Timers/TimerHandle.hpp>
#include <Service/ServiceProxy.hpp>

namespace settings
{
    class Settings;
} // namespace settings

namespace backlight
{
    /// @brief Backlight events handler
    class Handler
    {
      public:
        Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent);

        /// initialise in InitHandler when Service is ready
        void init();

        /// Process request of the screen light control
        /// @screen_light_control::Action an action to perform
        /// @screen_light_control::Parameters parameters being set
        void processScreenRequest(screen_light_control::Action action, const screen_light_control::Parameters &params);

        void handleKeyPressed(const int key = 0);
        /// Process request of the keypad light control
        /// @keypad_backlight::action an action to perform
        /// @return True if request was processed successfully, false otherwise
        auto processKeypadRequest(bsp::keypad_backlight::Action action) -> bool;

        [[nodiscard]] auto getScreenLightState() const noexcept -> bool;
        [[nodiscard]] auto getScreenAutoModeState() const noexcept -> screen_light_control::ScreenLightMode;
        [[nodiscard]] auto getScreenBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage;

      protected:
        [[nodiscard]] auto getValue(const std::string &path) const -> std::string;
        void setValue(const std::string &path, const std::string &value);

      private:
        std::shared_ptr<settings::Settings> settings;
        std::unique_ptr<screen_light_control::ScreenLightControl> screenLightControl;
        /// Timer that keeps key backlight on for a certain time if there was key pressed
        sys::TimerHandle keypadLightTimer;
        /// Timer that keeps screen backlight on for a certain time if there was key pressed
        sys::TimerHandle screenLightTimer;
        bsp::keypad_backlight::State keypadLightState = bsp::keypad_backlight::State::off;
        bool isKeypadLightInCallMode                  = false;

        void startKeypadLightTimer();
        void startScreenLightTimer();
        void stopKeypadTimer();
        void setKeypadLightInCallMode(bool value) noexcept;
        void setKeypadLightState(bsp::keypad_backlight::State value) noexcept;
        void restoreKeypadLightState();
        void handleKeypadLightRefresh();
        void handleScreenLightRefresh(const int key = 0);
        void handleScreenLightSettings(screen_light_control::Action action,
                                       const screen_light_control::Parameters &params);
    };
} // namespace backlight

M products/PurePhone/services/evtmgr/include/evtmgr/BacklightHandler.hpp => products/PurePhone/services/evtmgr/include/evtmgr/BacklightHandler.hpp +9 -8
@@ 22,19 22,21 @@ namespace backlight
      public:
        Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent);

        void handleKeyPressed();
        void handleKeyPressed(int key = 0);
        /// Process request of the keypad light control
        /// @keypad_backlight::action an action to perform
        /// @return True if request was processed successfully, false otherwise
        auto processKeypadRequest(bsp::keypad_backlight::Action action) -> bool;

        void processScreenRequest(screen_light_control::Action action,
                                  const screen_light_control::Parameters &params) override;

      private:
        std::shared_ptr<screen_light_control::ScreenLightControl> screenLightControl;
        /// Timer that keeps screen backlight on for a certain time if there was key pressed
        std::shared_ptr<sys::TimerHandle> screenLightTimer;
        std::shared_ptr<settings::Settings> settings;
        /// Timer that keeps key backlight on for a certain time if there was key pressed
        sys::TimerHandle keypadLightTimer;

        /// Timer that keeps screen backlight on for a certain time if there was key pressed
        sys::TimerHandle screenLightTimer;
        bsp::keypad_backlight::State keypadLightState = bsp::keypad_backlight::State::off;
        bool isKeypadLightInCallMode                  = false;



@@ 44,8 46,7 @@ namespace backlight
        void setKeypadLightState(bsp::keypad_backlight::State value) noexcept;
        void restoreKeypadLightState();
        void handleKeypadLightRefresh();
        void handleScreenLightRefresh([[maybe_unused]] const int key = 0);
        void handleScreenLightSettings(screen_light_control::Action action,
                                       const screen_light_control::Parameters &params);
        void handleScreenLightRefresh(int key = 0);
        void onScreenLightTurnedOn() override;
    };
} // namespace backlight

M products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.cpp => products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.cpp +31 -29
@@ 1,15 1,15 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp>
#include "ScreenLightControl.hpp"

#include <Timers/TimerFactory.hpp>
#include <Service/Service.hpp>

namespace screen_light_control
namespace pure::screen_light_control
{

    ScreenLightControl::ScreenLightControl(sys::Service *parent)
    ScreenLightController::ScreenLightController(sys::Service *parent)
    {
        controlTimer = sys::TimerFactory::createPeriodicTimer(parent,
                                                              "LightControlTimer",


@@ 20,19 20,20 @@ namespace screen_light_control
                                                              std::chrono::milliseconds{READOUT_TIMER_MS},
                                                              [this](sys::Timer &) { readoutTimerCallback(); });

        setParameters(screen_light_control::AutomaticModeParameters());
        setParameters(AutomaticModeParameters());
    }

    ScreenLightControl::~ScreenLightControl()
    ScreenLightController::~ScreenLightController()
    {
        disableTimers();
    }

    void ScreenLightControl::processRequest(Action action)
    void ScreenLightController::processRequest(Action action)
    {
        processRequest(action, Parameters());
    }
    void ScreenLightControl::processRequest(Action action, const Parameters &params)

    void ScreenLightController::processRequest(Action action, const Parameters &params)
    {
        switch (action) {
        case Action::turnOff:


@@ 60,65 61,66 @@ namespace screen_light_control
        }
    }

    void ScreenLightControl::controlTimerCallback()
    void ScreenLightController::controlTimerCallback()
    {
        bsp::eink_frontlight::setBrightness(functions::brightnessRampOut());
        bsp::eink_frontlight::setBrightness(::screen_light_control::functions::brightnessRampOut());
    }

    void ScreenLightControl::readoutTimerCallback()
    void ScreenLightController::readoutTimerCallback()
    {
        functions::calculateBrightness(bsp::light_sensor::readout());
        ::screen_light_control::functions::calculateBrightness(bsp::light_sensor::readout());
    }

    auto ScreenLightControl::getAutoModeState() const noexcept -> ScreenLightMode
    auto ScreenLightController::isLightOn() const noexcept -> bool
    {
        return automaticMode;
        return lightOn;
    }

    auto ScreenLightControl::isLightOn() const noexcept -> bool
    bool ScreenLightController::isAutoModeOn() const noexcept
    {
        return lightOn;
        return automaticMode == ScreenLightMode::Automatic;
    }

    auto ScreenLightControl::getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage
    auto ScreenLightController::getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage
    {
        return brightnessValue;
    }

    void ScreenLightControl::enableTimers()
    void ScreenLightController::enableTimers()
    {
        controlTimer.start();
        readoutTimer.start();
    }

    void ScreenLightControl::disableTimers()
    void ScreenLightController::disableTimers()
    {
        controlTimer.stop();
        readoutTimer.stop();
    }

    void ScreenLightControl::setParameters(const AutomaticModeParameters &params)
    void ScreenLightController::setParameters(const AutomaticModeParameters &params)
    {
        if (lightOn && automaticMode == ScreenLightMode::Automatic) {
            disableTimers();
        }

        functions::setRampStep(100.0f * (static_cast<float>(CONTROL_TIMER_MS) / static_cast<float>(params.rampTimeMS)));
        functions::setHysteresis(params.brightnessHysteresis);
        functions::setFunctionFromPoints(params.functionPoints);
        ::screen_light_control::functions::setRampStep(
            100.0f * (static_cast<float>(CONTROL_TIMER_MS) / static_cast<float>(params.rampTimeMS)));
        ::screen_light_control::functions::setHysteresis(params.brightnessHysteresis);
        ::screen_light_control::functions::setFunctionFromPoints(params.functionPoints);

        if (lightOn && automaticMode == ScreenLightMode::Automatic) {
            enableTimers();
        }
    }

    void ScreenLightControl::setParameters(ManualModeParameters params)
    void ScreenLightController::setParameters(ManualModeParameters params)
    {
        brightnessValue = params.manualModeBrightness;
        setManualBrightnessLevel();
    }

    void ScreenLightControl::enableAutomaticMode()
    void ScreenLightController::enableAutomaticMode()
    {
        if (lightOn) {
            enableTimers();


@@ 126,14 128,14 @@ namespace screen_light_control
        automaticMode = ScreenLightMode::Automatic;
    }

    void ScreenLightControl::disableAutomaticMode()
    void ScreenLightController::disableAutomaticMode()
    {
        disableTimers();
        automaticMode = ScreenLightMode::Manual;
        setManualBrightnessLevel();
    }

    void ScreenLightControl::turnOn()
    void ScreenLightController::turnOn()
    {
        bsp::eink_frontlight::turnOn();
        bsp::light_sensor::wakeup();


@@ 143,12 145,12 @@ namespace screen_light_control
        lightOn = true;
    }

    void ScreenLightControl::setManualBrightnessLevel()
    void ScreenLightController::setManualBrightnessLevel()
    {
        bsp::eink_frontlight::setBrightness(brightnessValue);
    }

    void ScreenLightControl::turnOff()
    void ScreenLightController::turnOff()
    {
        bsp::eink_frontlight::turnOff();
        bsp::light_sensor::standby();

A products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.hpp => products/PurePhone/services/evtmgr/screen-light-control/ScreenLightControl.hpp +70 -0
@@ 0,0 1,70 @@
// 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 <service-evtmgr/screen-light-control/ScreenLightControl.hpp>
#include <service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp>

#include <Timers/TimerHandle.hpp>

#include <memory>

namespace sys
{
    class Service;
} // namespace sys

/// Screen light control algorithm. Automatic/Manual mode of operation.
/// Processing of ambient light sensor input to screen brightness output.
namespace pure::screen_light_control
{
    /// Control screen light and keeps it's current state
    class ScreenLightController : public ::screen_light_control::ScreenLightController
    {
      public:
        using Action                       = ::screen_light_control::Action;
        using Parameters                   = ::screen_light_control::Parameters;
        using ScreenLightMode              = ::screen_light_control::ScreenLightMode;
        using ManualModeParameters         = ::screen_light_control::ManualModeParameters;
        using AutomaticModeParameters      = ::screen_light_control::AutomaticModeParameters;
        using LinearProgressModeParameters = ::screen_light_control::LinearProgressModeParameters;

        explicit ScreenLightController(sys::Service *parent);
        ~ScreenLightController() override;

        void processRequest(Action action) override;
        void processRequest(Action action, const Parameters &params) override;

        [[nodiscard]] auto isLightOn() const noexcept -> bool override;
        [[nodiscard]] bool isAutoModeOn() const noexcept override;
        [[nodiscard]] auto getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage override;

      private:
        void controlTimerCallback();
        void readoutTimerCallback();

        void enableTimers();
        void disableTimers();

        void setParameters(const AutomaticModeParameters &params);
        void setParameters(ManualModeParameters params);
        void setManualBrightnessLevel();

        void turnOff();
        void turnOn();

        void enableAutomaticMode();
        void disableAutomaticMode();

        static constexpr inline auto CONTROL_TIMER_MS = 25;
        static constexpr inline auto READOUT_TIMER_MS = 500;

        sys::TimerHandle controlTimer;
        sys::TimerHandle readoutTimer;

        bool lightOn                                               = false;
        ScreenLightMode automaticMode                              = ScreenLightMode::Manual;
        bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0;
    };
} // namespace pure::screen_light_control