M module-bsp/board/linux/eink_frontlight/eink_frontlight.cpp => module-bsp/board/linux/eink_frontlight/eink_frontlight.cpp +3 -0
@@ 20,4 20,7 @@ namespace bsp::eink_frontlight
void turnOff()
{}
+ void setGammaFactor(float)
+ {}
+
} // namespace bsp::eink_frontlight
M module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp => module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp +9 -4
@@ 13,12 13,12 @@ namespace bsp::eink_frontlight
{
std::shared_ptr<drivers::DriverPWM> pwm;
constexpr inline auto PWM_FREQUENCY_HZ = 20000;
- constexpr inline float gamma = 2.5f;
+ float gammaFactor = 2.5f;
- constexpr inline std::uint8_t gammaCorrection(BrightnessPercentage brightness)
+ std::uint8_t gammaCorrection(BrightnessPercentage brightness)
{
- std::clamp(brightness, static_cast<std::uint8_t>(0), static_cast<std::uint8_t>(100));
- return static_cast<std::uint8_t>(100 * std::pow((brightness / 100.0f), gamma));
+ std::clamp(brightness, 0.0f, 100.0f);
+ return static_cast<std::uint8_t>(100 * std::pow((brightness / 100.0f), gammaFactor));
}
} // namespace
@@ 55,4 55,9 @@ namespace bsp::eink_frontlight
pwm->Stop();
}
+ void setGammaFactor(float gamma)
+ {
+ gammaFactor = gamma;
+ }
+
} // namespace bsp::eink_frontlight
M module-bsp/board/rt1051/bsp/light_sensor/LTR303ALS.hpp => module-bsp/board/rt1051/bsp/light_sensor/LTR303ALS.hpp +16 -6
@@ 28,22 28,32 @@ namespace bsp::light_sensor
INTERRUPT_PERSIST = 0x9E
};
- constexpr inline auto ACTIVE_MODE = 0b00000001;
+ constexpr inline auto MEASUREMENT_GAIN_8 = 0b00001100;
+ constexpr inline auto ACTIVE_MODE = 0b00000001 | MEASUREMENT_GAIN_8;
constexpr inline auto SW_RESET = 0b00000010;
+ constexpr inline auto INTEGRATION_TIME_50MS = 0b00001000;
+ constexpr inline auto ALS_INT_50MS = 0.5f;
+ constexpr inline auto INTEGRATION_TIME_100MS = 0b00000000;
+ constexpr inline auto ALS_INT_100MS = 1;
constexpr inline auto INTEGRATION_TIME_200MS = 0b00010000;
constexpr inline auto ALS_INT_200MS = 2;
constexpr inline auto INTEGRATION_TIME_400MS = 0b00011000;
constexpr inline auto ALS_INT_400MS = 4;
- constexpr inline auto ALS_GAIN = 1.0f;
- // Factor of light resistance of window above the sensor - roughly estimated value
- constexpr inline auto PFACTOR = 0.8f;
- constexpr inline auto MEASUREMENT_COEFF = (ALS_INT_200MS * ALS_GAIN) / PFACTOR;
-
+ constexpr inline auto MEASUREMENT_RATE_50MS = 0b00000000;
+ constexpr inline auto MEASUREMENT_RATE_100MS = 0b00000001;
constexpr inline auto MEASUREMENT_RATE_500MS = 0b00000011;
+ constexpr inline auto MEASUREMENT_RATE_1000MS = 0b00000100;
constexpr inline auto MEASUREMENT_RATE_2000MS = 0b00000111;
+ constexpr inline auto MEAS_SETUP = INTEGRATION_TIME_400MS | MEASUREMENT_RATE_500MS;
+
+ constexpr inline auto ALS_GAIN = 8.0f;
+ // Factor of light resistance of window above the sensor - roughly estimated value
+ constexpr inline auto PFACTOR = 0.8f;
+ constexpr inline auto MEASUREMENT_COEFF = (ALS_INT_400MS * ALS_GAIN) / PFACTOR;
+
constexpr inline auto ENABLE_IRQ = 0x0A;
constexpr inline auto MANUFACTURER_ID = 0x05;
M module-bsp/board/rt1051/bsp/light_sensor/light_sensor.cpp => module-bsp/board/rt1051/bsp/light_sensor/light_sensor.cpp +1 -1
@@ 60,7 60,7 @@ namespace bsp::light_sensor
void configureMeasurement()
{
- std::uint8_t reg = MEASUREMENT_RATE_500MS | INTEGRATION_TIME_200MS;
+ std::uint8_t reg = MEAS_SETUP;
writeSingleRegister(static_cast<std::uint32_t>(LTR303ALS_Registers::ALS_MEAS_RATE), ®);
}
M module-bsp/bsp/eink_frontlight/eink_frontlight.hpp => module-bsp/bsp/eink_frontlight/eink_frontlight.hpp +3 -1
@@ 16,7 16,7 @@ namespace bsp::eink_frontlight
setBrightness,
};
- using BrightnessPercentage = uint8_t;
+ using BrightnessPercentage = float;
void init();
@@ 27,4 27,6 @@ namespace bsp::eink_frontlight
void turnOn();
void turnOff();
+
+ void setGammaFactor(float gamma);
} // namespace bsp::eink_frontlight
M module-services/service-evtmgr/CMakeLists.txt => module-services/service-evtmgr/CMakeLists.txt +1 -0
@@ 7,6 7,7 @@ set(SOURCES
alarm/EventManagerAlarm.cpp
api/EventManagerServiceAPI.cpp
messages/Message.cpp
+ ScreenLightControl.cpp
)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +6 -26
@@ 7,6 7,7 @@
#include "service-evtmgr/EventManager.hpp"
#include "service-evtmgr/KbdMessage.hpp"
#include "service-evtmgr/WorkerEvent.hpp"
+#include "service-evtmgr/ScreenLightControl.hpp"
#include <BaseInterface.hpp>
#include <MessageType.hpp>
@@ 19,7 20,6 @@
#include <bsp/magnetometer/magnetometer.hpp>
#include <bsp/rtc/rtc.hpp>
#include <bsp/torch/torch.hpp>
-#include <bsp/keypad_backlight/keypad_backlight.hpp>
#include <common_data/RawKey.hpp>
#include <log/log.hpp>
#include <module-utils/time/time_conversion.hpp>
@@ 30,7 30,6 @@
#include <service-db/DBNotificationMessage.hpp>
#include <service-desktop/Constants.hpp>
#include <service-desktop/DesktopMessages.hpp>
-#include <bsp/light_sensor/light_sensor.hpp>
#include <cassert>
#include <list>
#include <tuple>
@@ 280,17 279,12 @@ sys::ReturnCodes EventManager::InitHandler()
return response;
});
- connect(sevm::EinkFrontlightMessage(), [&](sys::Message *msgl) {
- auto msg = static_cast<sevm::EinkFrontlightMessage *>(msgl);
- processEinkFrontlightRequest(msg->action, msg->value);
+ connect(sevm::ScreenLightControlMessage(sevm::screen_light_control::Action::turnOff), [&](sys::Message *msgl) {
+ auto request = static_cast<sevm::ScreenLightControlMessage *>(msgl);
+ sevm::screen_light_control::processRequest(request->action, request->parameters);
return std::make_shared<sys::ResponseMessage>();
});
- connect(sevm::LightSensorMessage(), [&](sys::Message *msgl) {
- auto message = std::make_shared<sevm::LightSensorReadoutMessage>(bsp::light_sensor::readout());
- return message;
- });
-
// initialize keyboard worker
EventWorker = std::make_unique<WorkerEvent>(this);
@@ 325,12 319,14 @@ sys::ReturnCodes EventManager::InitHandler()
EventWorker->init(list);
EventWorker->run();
+ sevm::screen_light_control::init(this);
return sys::ReturnCodes::Success;
}
sys::ReturnCodes EventManager::DeinitHandler()
{
+ sevm::screen_light_control::deinit();
EventWorker->close();
EventWorker.reset();
EventWorker = nullptr;
@@ 379,19 375,3 @@ bool EventManager::processKeypadBacklightRequest(bsp::keypad_backlight::Action a
}
return response;
}
-
-void EventManager::processEinkFrontlightRequest(bsp::eink_frontlight::Action act,
- bsp::eink_frontlight::BrightnessPercentage val)
-{
- switch (act) {
- case bsp::eink_frontlight::Action::turnOn:
- bsp::eink_frontlight::turnOn();
- break;
- case bsp::eink_frontlight::Action::turnOff:
- bsp::eink_frontlight::turnOff();
- break;
- case bsp::eink_frontlight::Action::setBrightness:
- bsp::eink_frontlight::setBrightness(val);
- break;
- }
-}
A module-services/service-evtmgr/ScreenLightControl.cpp => module-services/service-evtmgr/ScreenLightControl.cpp +206 -0
@@ 0,0 1,206 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "service-evtmgr/ScreenLightControl.hpp"
+
+namespace sevm::screen_light_control
+{
+ namespace
+ {
+ constexpr inline auto CONTROL_TIMER_MS = 25;
+ constexpr inline auto READOUT_TIMER_MS = 500;
+ std::unique_ptr<sys::Timer> controlTimer;
+ std::unique_ptr<sys::Timer> readoutTimer;
+
+ bool automaticMode = false;
+ bool lightOn = false;
+ struct FunctionSection
+ {
+ float xBound;
+ float a;
+ float b;
+ };
+
+ std::vector<FunctionSection> brightnessFunction;
+ float rampStep;
+ float brightnessHysteresis;
+
+ bsp::eink_frontlight::BrightnessPercentage brightnessRampTarget;
+ bsp::eink_frontlight::BrightnessPercentage brightnessRampState;
+ bool rampTargetReached = false;
+
+ float calculateBrightness(bsp::light_sensor::IlluminanceLux measurement)
+ {
+ for (const auto §ion : brightnessFunction) {
+ if (measurement < section.xBound) {
+ return section.a * measurement + section.b;
+ }
+ }
+
+ if (brightnessFunction.empty()) {
+ return 0.0f;
+ }
+ return brightnessFunction.back().xBound * brightnessFunction.back().a + brightnessFunction.back().b;
+ }
+
+ bsp::eink_frontlight::BrightnessPercentage brightnessRampOut()
+ {
+ if (rampTargetReached && std::abs(brightnessRampTarget - brightnessRampState) > brightnessHysteresis) {
+ rampTargetReached = false;
+ }
+
+ if (!rampTargetReached) {
+ if (brightnessRampState < brightnessRampTarget) {
+ brightnessRampState += rampStep;
+ if (brightnessRampState > brightnessRampTarget) {
+ rampTargetReached = true;
+ }
+ }
+ else if (brightnessRampState > brightnessRampTarget) {
+ brightnessRampState -= rampStep;
+ if (brightnessRampState < brightnessRampTarget) {
+ brightnessRampState = brightnessRampTarget;
+ rampTargetReached = true;
+ }
+ }
+ }
+
+ return brightnessRampState;
+ }
+
+ void controlTimerCallback()
+ {
+ auto out = brightnessRampOut();
+ bsp::eink_frontlight::setBrightness(out);
+ }
+
+ void readoutTimerCallback()
+ {
+ float lightMeasurement = bsp::light_sensor::readout();
+ brightnessRampTarget = calculateBrightness(lightMeasurement);
+ }
+
+ void enableTimers()
+ {
+ controlTimer->connect([&](sys::Timer &) { controlTimerCallback(); });
+ readoutTimer->connect([&](sys::Timer &) { readoutTimerCallback(); });
+ controlTimer->start();
+ readoutTimer->start();
+ }
+
+ void disableTimers()
+ {
+ controlTimer->stop();
+ readoutTimer->stop();
+ }
+
+ void setAutomaticModeParameters(const Parameters ¶ms)
+ {
+ if (lightOn && automaticMode) {
+ disableTimers();
+ }
+
+ rampStep = 100.0f * (static_cast<float>(CONTROL_TIMER_MS) / static_cast<float>(params.rampTimeMS));
+ brightnessHysteresis = params.brightnessHysteresis;
+
+ if (!params.functionPoints.empty()) {
+ brightnessFunction.clear();
+ for (unsigned int i = 0; i < params.functionPoints.size(); ++i) {
+ FunctionSection section;
+ section.xBound = params.functionPoints[i].first;
+ if (i == 0) {
+ section.a = 0.0f;
+ section.b = params.functionPoints[i].second;
+ }
+ else {
+ section.a = (params.functionPoints[i - 1].second - params.functionPoints[i].second) /
+ (params.functionPoints[i - 1].first - params.functionPoints[i].first);
+ section.b =
+ params.functionPoints[i - 1].second - section.a * params.functionPoints[i - 1].first;
+ }
+ brightnessFunction.push_back(section);
+ }
+ }
+
+ if (lightOn && automaticMode) {
+ enableTimers();
+ }
+ }
+
+ void turnOff()
+ {
+ bsp::eink_frontlight::turnOff();
+ bsp::light_sensor::standby();
+ controlTimer->stop();
+ readoutTimer->stop();
+ lightOn = false;
+ }
+
+ void turnOn()
+ {
+ bsp::eink_frontlight::turnOn();
+ bsp::light_sensor::wakeup();
+ if (automaticMode) {
+ enableTimers();
+ }
+ lightOn = true;
+ }
+
+ void enableAutomaticMode()
+ {
+ if (lightOn) {
+ enableTimers();
+ }
+ automaticMode = true;
+ }
+
+ void disableAutomaticMode()
+ {
+ disableTimers();
+ automaticMode = false;
+ }
+
+ } // namespace
+
+ void init(sys::Service *parent)
+ {
+ controlTimer = std::make_unique<sys::Timer>("LightControlTimer", parent, CONTROL_TIMER_MS);
+ readoutTimer = std::make_unique<sys::Timer>("LightSensorReadoutTimer", parent, READOUT_TIMER_MS);
+
+ Parameters defaultParams;
+ setAutomaticModeParameters(defaultParams);
+ }
+
+ void deinit()
+ {
+ disableTimers();
+ }
+
+ void processRequest(Action action, const Parameters ¶ms)
+ {
+ switch (action) {
+ case Action::turnOff:
+ turnOff();
+ break;
+ case Action::turnOn:
+ turnOn();
+ break;
+ case Action::enableAutomaticMode:
+ enableAutomaticMode();
+ break;
+ case Action::disableAutomaticMode:
+ disableAutomaticMode();
+ break;
+ case Action::setManualModeBrightness:
+ bsp::eink_frontlight::setBrightness(params.manualModeBrightness);
+ break;
+ case Action::setGammaCorrectionFactor:
+ bsp::eink_frontlight::setGammaFactor(params.gammaFactor);
+ break;
+ case Action::setAutomaticModeParameters:
+ setAutomaticModeParameters(params);
+ break;
+ }
+ }
+
+} // namespace sevm::screen_light_control
A module-services/service-evtmgr/doc/gamma_correction.svg => module-services/service-evtmgr/doc/gamma_correction.svg +3 -0
@@ 0,0 1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="293px" height="213px" viewBox="-0.5 -0.5 293 213" content="<mxfile host="app.diagrams.net" modified="2020-12-08T13:23:26.829Z" agent="5.0 (X11)" version="13.10.9" etag="cIShF1NpU-w7JGPpKOUe" type="google"><diagram id="yTwYNGOTziU7TQcxtC_X">7VhNc5swEP01PjYjvvExttPm0M5kJoe2RxmtjaYycoXs4P76SiAMAkLs1Jl6JvHF6Gm1rN6+FQsTb74pvgi8Tb9xAmziIlJMvMXEdR0vctWfRg4VEiOvAtaCkgpCDfBI/4BZWaM7SiA3WAVJzpmkWxtMeJZBIi0MC8GfbLMVZ8QCtngNPeAxwayPfqdEpmYXbtTg90DXaX1nJ5xWMxtcGxsXeYoJf2pt2bubeHPBuayuNsUcmCbP5uXzM7PHwARk8pQFJhF7zHZmbyYueag3Cxm51ZypUcJwntNk4s1SuWEKcNRltQBIj7ImBue4MyUJ4BuQ4qBMnhruApPZtEVbjQlgWNK97R6bFK6P7o53eOBU3dhFRm6Bi25Q62d2aKQ3re9SO8z5TiRgfLSZO8ttFHfcSizWIHtu1UWLkgYq0zScMu8jZa9MWRSicUeXS5J/VpIynoGdoRXPpDn3VAV7s1wK/ut42LjGYs4ZF6U3T9M0n2ucMtbCCYZ4lRw9tGbCJIbl6h2rAdlqiJ03U0PwGjUQnKdAjB5a0hiWQlssHQms4gSSQQks48AP0IcEzpWAyhQ+tMy22iAfCT/qHDw+Go0r7MQ19V6w9zv26AX7TjxxaNmri2qHr9V72NP711ISyiKTkOV0T+WhVwISCmlLHTO6zvRDTKkQlGZnexCSqj7s1kxsKCF6+UxATv/gZelKC9pkRPkNZpNgoX3tJM+rIukcsE5TAdo/FOfWQK0mJ+jI0oxbNRIP1IjbEV27HKxDZ4TxaOCECZmmk9C9RXP4e6eby5KATxUht8rAcbdFSUM9r67W5p/V9v/kaFACqHa/FBeJUvFUBdqDSx5s9GqoYTQDrAlIUpypM/i8zVxLGbmXKaOg06VFU9QrIwcN1JF3gTqKx+uoovx+t8GZfl4e4ASBVdAW1BNpKynP2op/V4ntno+x30/s0Pl4ibxOz+rABl+a7L5riKPnWnIoqPyhib/xp74Z/9SLbhwnNuNFYTJTDg6twQMIqvar87sY6dWqnsd6GlxN+9btN6Jun3Vqw6Yao5E+MI7erIOvA/7vAnIdW0AoegsBxVcmoMi38+7Yee9+bDlZTsHoawW6lJzUsPmkV5k3H0a9u78=</diagram></mxfile>"><defs><style xmlns="http://www.w3.org/1999/xhtml" type="text/css">.MathJax_Preview {color: #888; display: contents}
#MathJax_Message {position: fixed; left: 1px; bottom: 2px; background-color: #E6E6E6; border: 1px solid #959595; margin: 0px; padding: 2px 8px; z-index: 102; color: black; font-size: 80%; width: auto; white-space: nowrap}
#MathJax_MSIE_Frame {position: absolute; top: 0; left: 0; width: 0px; z-index: 101; border: 0px; margin: 0px; padding: 0px}
.MathJax_Error {color: #CC0000; font-style: italic}
</style></defs><g><path d="M 10 180 L 10 16.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 10 11.12 L 13.5 18.12 L 10 16.37 L 6.5 18.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 10 180 L 243.63 180" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 248.88 180 L 241.88 183.5 L 243.63 180 L 241.88 176.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 10 180 L 190 40" fill="none" stroke="#6c8ebf" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 10 180 L 50.19 171.96 Q 60 170 69.49 166.84 L 80.51 163.16 Q 90 160 98 154 L 122 136 Q 130 130 136 122 L 154 98 Q 160 90 165.14 81.43 L 190 40" fill="none" stroke="#b85450" stroke-width="2" stroke-miterlimit="10" stroke-dasharray="6 6" pointer-events="stroke"/><rect x="205" y="185" width="80" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 195px; margin-left: 245px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; ">Light intensivity</div></div></div></foreignObject><text x="245" y="198" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle">Light intensivity</text></switch></g><rect x="50" y="20" width="100" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 35px; margin-left: 100px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><div style="font-size: 12px"><font style="font-size: 12px">Light intensivity <br style="font-size: 12px" /></font></div><div style="font-size: 12px"><font style="font-size: 12px">linear change</font></div></div></div></div></foreignObject><text x="100" y="39" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Light intensivit...</text></switch></g><rect x="205" y="70" width="80" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 85px; margin-left: 245px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><div>Human eye</div><div>perception<br /></div></div></div></div></foreignObject><text x="245" y="89" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Human eye...</text></switch></g><path d="M 99.4 53.54 L 91.26 93.76" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 90.22 98.9 L 88.18 91.35 L 91.26 93.76 L 95.04 92.74 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 238.68 103.21 L 146.15 128.33" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 141.08 129.71 L 146.92 124.5 L 146.15 128.33 L 148.75 131.25 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg><
\ No newline at end of file
A module-services/service-evtmgr/doc/light_control_algorithm.puml => module-services/service-evtmgr/doc/light_control_algorithm.puml +21 -0
@@ 0,0 1,21 @@
+@startuml
+
+hide footbox
+
+box "500ms" #LightBlue
+participant "Light Measurement" as lm
+participant "Brightness Function" as bc
+participant "Ramp target \nvalue update" as ru
+end box
+
+box "25ms" #LightGreen
+participant "Current ramp value \ncalculation with hysteresis" as rc
+participant "Light driver duty cycle \nupdate with Gamma Correction" as ld
+end box
+
+lm -> bc : measurement
+bc -> ru : brightness \nvalue
+ru -> rc : ramp target
+rc -> ld : current ramp \nvalue
+
+@enduml
A module-services/service-evtmgr/doc/light_control_algorithm.svg => module-services/service-evtmgr/doc/light_control_algorithm.svg +31 -0
@@ 0,0 1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="250px" preserveAspectRatio="none" style="width:900px;height:250px;" version="1.1" viewBox="0 0 900 250" width="900px" zoomAndPan="magnify"><defs><filter height="300%" id="f1mh8i95ojgk88" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#ADD8E6" height="231.5234" style="stroke:#A80036;stroke-width:1.0;" width="443" x="1" y="6"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="49" x="198" y="18.0669">500ms</text><rect fill="#90EE90" height="231.5234" style="stroke:#A80036;stroke-width:1.0;" width="448" x="446" y="6"/><text fill="#000000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="40" x="650" y="18.0669">25ms</text><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="80" x2="80" y1="76.7266" y2="243.5234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="244" x2="244" y1="76.7266" y2="243.5234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="386" x2="386" y1="76.7266" y2="243.5234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="549" x2="549" y1="76.7266" y2="243.5234"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="774" x2="774" y1="76.7266" y2="243.5234"/><rect fill="#FEFECE" filter="url(#f1mh8i95ojgk88)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="147" x="5" y="41.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="133" x="12" y="61.4248">Light Measurement</text><rect fill="#FEFECE" filter="url(#f1mh8i95ojgk88)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="153" x="166" y="41.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="139" x="173" y="61.4248">Brightness Function</text><rect fill="#FEFECE" filter="url(#f1mh8i95ojgk88)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="103" x="333" y="25.1328"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="85" x="340" y="45.1279">Ramp target</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="89" x="340" y="61.4248">value update</text><rect fill="#FEFECE" filter="url(#f1mh8i95ojgk88)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="194" x="450" y="25.1328"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="131" x="479.5" y="45.1279">Current ramp value</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="180" x="457" y="61.4248">calculation with hysteresis</text><rect fill="#FEFECE" filter="url(#f1mh8i95ojgk88)" height="46.5938" style="stroke:#A80036;stroke-width:1.5;" width="228" x="658" y="25.1328"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="148" x="696" y="45.1279">Light driver duty cycle</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="214" x="665" y="61.4248">update with Gamma Correction</text><polygon fill="#A80036" points="232.5,103.8594,242.5,107.8594,232.5,111.8594,236.5,107.8594" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="80.5" x2="238.5" y1="107.8594" y2="107.8594"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="91" x="87.5" y="102.7935">measurement</text><polygon fill="#A80036" points="374.5,148.125,384.5,152.125,374.5,156.125,378.5,152.125" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="244.5" x2="380.5" y1="152.125" y2="152.125"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="67" x="251.5" y="131.9263">brightness</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="34" x="251.5" y="147.0591">value</text><polygon fill="#A80036" points="537,177.2578,547,181.2578,537,185.2578,541,181.2578" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="386.5" x2="543" y1="181.2578" y2="181.2578"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="77" x="393.5" y="176.1919">ramp target</text><polygon fill="#A80036" points="762,221.5234,772,225.5234,762,229.5234,766,225.5234" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="549" x2="768" y1="225.5234" y2="225.5234"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="84" x="556" y="205.3247">current ramp</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="34" x="556" y="220.4575">value</text><!--MD5=[41ba1f1179bd1c783f736902b7001ce8]
+@startuml
+
+hide footbox
+
+box "500ms" #LightBlue
+participant "Light Measurement" as lm
+participant "Brightness Function" as bc
+participant "Ramp target \nvalue update" as ru
+end box
+
+box "25ms" #LightGreen
+participant "Current ramp value \ncalculation with hysteresis" as rc
+participant "Light driver duty cycle \nupdate with Gamma Correction" as ld
+end box
+
+lm -> bc : measurement
+bc -> ru : brightness \nvalue
+ru -> rc : ramp target
+rc -> ld : current ramp \nvalue
+
+@enduml
+
+PlantUML version 1.2020.22(Sun Dec 06 10:36:27 CET 2020)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Default Encoding: UTF-8
+Language: pl
+Country: PL
+--></g></svg><
\ No newline at end of file
A module-services/service-evtmgr/doc/light_control_function.svg => module-services/service-evtmgr/doc/light_control_function.svg +3 -0
@@ 0,0 1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="472px" height="256px" viewBox="-0.5 -0.5 472 256" content="<mxfile host="app.diagrams.net" modified="2020-12-08T13:24:39.119Z" agent="5.0 (X11)" version="13.10.9" etag="zb_maAve2Po3ZfvaQdIF" type="google"><diagram id="bYA3SPjRXRI9Chxooi9G">7VpLc9owEP41PjYjvzA+EkjbQzvTGQ5tjwIroIltUVkmpr++kiU/ZV7GpCEDF6zP8nq13+5qtWDY0yj7QuFm/Z0EKDQsEGSGPTMsy7Q9i38JZCeRMbAlsKI4kBCogDn+i9STBZriACUKkxAjJGR40wSXJI7RkjUwSCl5bU57JmHQADZwhTRgvoShjv7EAVurVVhehX9FeLUu3myOfHkngsVkJSJZw4C81pZsPxn2lBLC5FWUTVEojNe0y+c9d0vFKIrZKQ8oIrYwTNXalF5sVywWxcFE2IyPliFMErw07Mc1i0IOmPxSPoACzWSVDma5Mu4SiESI0R2f8lrZzlXMrmtmKzCKQsjwtikeKgpXpbjyDT8I5i+2QOluSo5yNtPxQVNGQlK6ROqxurGOSbLakhikK8Q0SfyitvAKysnoJsa+E3M6MY4LHkDtYx2ROxxNTgdNo5Db6THA2wZdoz+pCOrHZxKzT0me0iZ8ggk2Wc5VcZ9frcT3fEkRig0Rv1Lggl4krxDDV5Sr1kQv1XZBhXvEKEmExi7HXcOd3YTqV1ayFbQMZawZpjDEq1jEMI9KRDmwRZRhvtlM1I0IB4F4/JEirgdc5KIAH2+EA+cuzQ3Orc1lpYxIXXPRQne1e5qg1EbIR9m5OSFrxn6ZAscKqOWMcUfOcMD+9NCIvwPB5h4ONmnxSbTAKE8OYf72ZgCd7FASCtMIxzBeIunV39Ks5tUfnGnH1NKzq1Htd1BtD0D16KztLyYxapq62x7veC+0Wsa221bsXaRokvbsftyYcFebpnzufJUriqXIvnurp/mACcC7CTNvmCjz20a09CCzO/zOHCDIxgMGmRgnjJKX8kRkl8iUhITm8mwAfB/cREBqxWnvgPSOSRquHPXvjO5llO9nBw8Jbt/Dh32e3OHYLnLAne4OWvTM2pvgMx1nQILNO8H7CW7Xp70JfssMbVp3St+A0uPRPyCleq/uKYPRJpQtg/9ZrxqXF6iW1vTsOPF7HT5hDVChmkf6a/LoPYP0RTgfIZFhTU8+3C/QM6HiZJ+ECG1O7xLcOKFOO9n5Op9dHZwhjvXmSS2cAEcRCoyLOjew3Qb6kFxaoE2m+YZk6k2aeRorc9+4YZ2is1/uHx1RMrpW1tM7H4dqhJv88ae9PzvjvsWbls9s/2o7/Xkdk5skRuvwO6BvDaY1CEfXq8HO63x0MoMyzH6JHPPgeI4a/xb3HkzPV+NZppJQPtjVBj8QxVxhkcpmB2ptabxmAn033DujNvftdHbymdk5fGZu/xzU2xP4sPq3hJxe/efEfvoH</diagram></mxfile>"><defs><style xmlns="http://www.w3.org/1999/xhtml" type="text/css">.MathJax_Preview {color: #888; display: contents}
#MathJax_Message {position: fixed; left: 1px; bottom: 2px; background-color: #E6E6E6; border: 1px solid #959595; margin: 0px; padding: 2px 8px; z-index: 102; color: black; font-size: 80%; width: auto; white-space: nowrap}
#MathJax_MSIE_Frame {position: absolute; top: 0; left: 0; width: 0px; z-index: 101; border: 0px; margin: 0px; padding: 0px}
.MathJax_Error {color: #CC0000; font-style: italic}
</style></defs><g><path d="M 93 213 L 93 19.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 93 14.12 L 96.5 21.12 L 93 19.37 L 89.5 21.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 93 213 L 406.63 213" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 411.88 213 L 404.88 216.5 L 406.63 213 L 404.88 209.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="13" y="3" width="80" height="40" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 23px; margin-left: 53px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><div style="font-size: 10px">Screen <br style="font-size: 10px" /></div><div style="font-size: 10px">brightness [%]<br style="font-size: 10px" /></div><div style="font-size: 10px"><br style="font-size: 10px" /></div></div></div></div></foreignObject><text x="53" y="26" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle">Screen...</text></switch></g><rect x="373" y="218" width="90" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 233px; margin-left: 418px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><div>Ambient light <br /></div><div>luminance [Lux]</div></div></div></div></foreignObject><text x="418" y="236" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle">Ambient light...</text></switch></g><path d="M 83 53 L 83 53 L 93 53" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><rect x="53" y="48" width="30" height="10" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 53px; margin-left: 68px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 7px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; ">100</div></div></div></foreignObject><text x="68" y="55" fill="#000000" font-family="Helvetica" font-size="7px" text-anchor="middle">100</text></switch></g><path d="M 93 153 L 133 153" fill="none" stroke="#009900" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 373 173 L 393 173" fill="none" stroke="#009900" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 253 73 L 373 173" fill="none" stroke="#009900" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 173 73 L 133 153" fill="none" stroke="#009900" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 173 73 L 253 73" fill="none" stroke="#009900" stroke-width="3" stroke-miterlimit="10" pointer-events="stroke"/><rect x="193" y="3" width="70" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 13px; margin-left: 228px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; ">Example:</div></div></div></foreignObject><text x="228" y="17" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Example:</text></switch></g><rect x="3" y="213" width="80" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 228px; margin-left: 43px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><div>Dark room,</div><div>before sleep<br /></div></div></div></div></foreignObject><text x="43" y="232" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Dark room,...</text></switch></g><rect x="163" y="133" width="80" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 148px; margin-left: 203px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "><div>dimmed <br /></div><div>ambient light</div></div></div></div></foreignObject><text x="203" y="152" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">dimmed...</text></switch></g><rect x="387" y="113" width="60" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 123px; margin-left: 417px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; ">Sunlight</div></div></div></foreignObject><text x="417" y="127" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Sunlight</text></switch></g><path d="M 53 203 L 98.08 166.04" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 102.14 162.71 L 98.94 169.85 L 98.08 166.04 L 94.5 164.44 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 213 123 L 186.82 88.09" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 183.67 83.89 L 190.67 87.39 L 186.82 88.09 L 185.07 91.59 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 415.44 136.58 L 405.71 157.24" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 403.48 161.99 L 403.29 154.16 L 405.71 157.24 L 409.62 157.15 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg><
\ No newline at end of file
A module-services/service-evtmgr/doc/light_control_hysteresis.puml => module-services/service-evtmgr/doc/light_control_hysteresis.puml +11 -0
@@ 0,0 1,11 @@
+@startuml
+(*) --> If "Ramp target reached?" then
+ If "New target differs by \nhysteresis value from \nthe old one?" then
+ -> [Yes] "update ramp" as ur
+ else
+ ---> [No] "RampValue = \nRampTarget"
+ Endif
+else
+--> [No] ur
+Endif
+@enduml
A module-services/service-evtmgr/doc/light_control_hysteresis.svg => module-services/service-evtmgr/doc/light_control_hysteresis.svg +26 -0
@@ 0,0 1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="336px" preserveAspectRatio="none" style="width:324px;height:336px;" version="1.1" viewBox="0 0 324 336" width="324px" zoomAndPan="magnify"><defs><filter height="300%" id="f1t5fss58cooth" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><ellipse cx="207.363" cy="16" fill="#000000" filter="url(#f1t5fss58cooth)" rx="10" ry="10" style="stroke:none;stroke-width:1.0;"/><polygon fill="#FEFECE" filter="url(#f1t5fss58cooth)" points="207.363,67,219.363,79,207.363,91,195.363,79,207.363,67" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#f1t5fss58cooth)" points="155.363,150,167.363,162,155.363,174,143.363,162,155.363,150" style="stroke:#A80036;stroke-width:1.5;"/><rect fill="#FEFECE" filter="url(#f1t5fss58cooth)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="101" x="209.863" y="145"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="81" x="219.863" y="166.1387">update ramp</text><rect fill="#FEFECE" filter="url(#f1t5fss58cooth)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="108" x="101.363" y="275"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="84" x="111.363" y="296.1387">RampValue =</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="76" x="117.363" y="310.1074">RampTarget</text><!--MD5=[9e7bccaab94f33706b7c2613f3cc0026]
+link start to #3--><path d="M207.363,26 C207.363,35.34 207.363,50.16 207.363,61.59 " fill="none" id="start-to-#3" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="207.363,66.89,211.363,57.89,207.363,61.89,203.363,57.89,207.363,66.89" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="126" x="61.2817" y="59.4561">Ramp target reached?</text><!--MD5=[2773403863a502716c38047ac44135d7]
+link #3 to #6--><path d="M202.923,86.91 C193.943,100.89 173.533,132.69 162.603,149.72 " fill="none" id="#3-to-#6" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="159.783,154.11,168.0145,148.7024,162.4868,149.9041,161.2851,144.3764,159.783,154.11" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="120" x="8.5" y="115.3137">New target differs by</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="125" x="6" y="128.1184">hysteresis value from</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="70" x="35.5" y="140.9231">the old one?</text><!--MD5=[7cfa565d5a7a904cbabcd798f1ced685]
+link #6 to ur--><path d="M167.403,162 C176.713,162 190.323,162 204.273,162 " fill="none" id="#6-to-ur" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="209.423,162,200.423,158,204.423,162,200.423,166,209.423,162" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="21" x="178.113" y="156.2104">Yes</text><!--MD5=[52e4b7cb87ab58fb7e68b8a1b8520dc5]
+link #6 to RampValue = \nRampTarget--><path d="M155.363,174.05 C155.363,194.74 155.363,239.91 155.363,269.63 " fill="none" id="#6-to-RampValue = \nRampTarget" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="155.363,274.99,159.363,265.99,155.363,269.99,151.363,265.99,155.363,274.99" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="15" x="156.363" y="231.2104">No</text><!--MD5=[1fc0cef09484a68efdf13ae0dd1e584d]
+link #3 to ur--><path d="M211.883,86.91 C219.583,98.69 235.563,123.09 247.063,140.68 " fill="none" id="#3-to-ur" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="249.883,144.99,248.2958,135.2699,247.1425,140.8079,241.6045,139.6546,249.883,144.99" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="15" x="237.363" y="122.2104">No</text><!--MD5=[eb3de5f3e5b05e23159ab560e1b3b1b4]
+@startuml
+(*) - -> If "Ramp target reached?" then
+ If "New target differs by \nhysteresis value from \nthe old one?" then
+ -> [Yes] "update ramp" as ur
+ else
+ - - -> [No] "RampValue = \nRampTarget"
+ Endif
+else
+- -> [No] ur
+Endif
+@enduml
+
+PlantUML version 1.2020.22(Sun Dec 06 10:36:27 CET 2020)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Default Encoding: UTF-8
+Language: pl
+Country: PL
+--></g></svg><
\ No newline at end of file
A module-services/service-evtmgr/doc/light_control_message_flow.puml => module-services/service-evtmgr/doc/light_control_message_flow.puml +6 -0
@@ 0,0 1,6 @@
+@startuml
+Application -> "Event Manager" as evm : ScreenLightControlMessage
+evm -> "ScreenLightControl" as slc: processRequest()
+slc -> "Eink Frontlight" : request
+slc -> "Light Sensor" : request
+@enduml
A module-services/service-evtmgr/doc/light_control_message_flow.svg => module-services/service-evtmgr/doc/light_control_message_flow.svg +16 -0
@@ 0,0 1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="220px" preserveAspectRatio="none" style="width:725px;height:220px;" version="1.1" viewBox="0 0 725 220" width="725px" zoomAndPan="magnify"><defs><filter height="300%" id="fywa74pnlo8ex" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="51" x2="51" y1="40.2969" y2="176.8281"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="254" x2="254" y1="40.2969" y2="176.8281"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="400" x2="400" y1="40.2969" y2="176.8281"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="543" x2="543" y1="40.2969" y2="176.8281"/><line style="stroke:#A80036;stroke-width:1.0;stroke-dasharray:5.0,5.0;" x1="663" x2="663" y1="40.2969" y2="176.8281"/><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="89" x="5" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="75" x="12" y="24.9951">Application</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="89" x="5" y="175.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="75" x="12" y="195.8232">Application</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="117" x="194" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="103" x="201" y="24.9951">Event Manager</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="117" x="194" y="175.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="103" x="201" y="195.8232">Event Manager</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="146" x="325" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="132" x="332" y="24.9951">ScreenLightControl</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="146" x="325" y="175.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="132" x="332" y="195.8232">ScreenLightControl</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="112" x="485" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="98" x="492" y="24.9951">Eink Frontlight</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="112" x="485" y="175.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="98" x="492" y="195.8232">Eink Frontlight</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="100" x="611" y="5"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="86" x="618" y="24.9951">Light Sensor</text><rect fill="#FEFECE" filter="url(#fywa74pnlo8ex)" height="30.2969" style="stroke:#A80036;stroke-width:1.5;" width="100" x="611" y="175.8281"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="86" x="618" y="195.8232">Light Sensor</text><polygon fill="#A80036" points="242.5,67.4297,252.5,71.4297,242.5,75.4297,246.5,71.4297" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="51.5" x2="248.5" y1="71.4297" y2="71.4297"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="179" x="58.5" y="66.3638">ScreenLightControlMessage</text><polygon fill="#A80036" points="388,96.5625,398,100.5625,388,104.5625,392,100.5625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="254.5" x2="394" y1="100.5625" y2="100.5625"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="112" x="261.5" y="95.4966">processRequest()</text><polygon fill="#A80036" points="531,125.6953,541,129.6953,531,133.6953,535,129.6953" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="400" x2="537" y1="129.6953" y2="129.6953"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="49" x="407" y="124.6294">request</text><polygon fill="#A80036" points="651,154.8281,661,158.8281,651,162.8281,655,158.8281" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.0;" x1="400" x2="657" y1="158.8281" y2="158.8281"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="49" x="407" y="153.7622">request</text><!--MD5=[cffb76a7c8b7e9568ee4c32e1fb1e346]
+@startuml
+Application -> "Event Manager" as evm : ScreenLightControlMessage
+evm -> "ScreenLightControl" as slc: processRequest()
+slc -> "Eink Frontlight" : request
+slc -> "Light Sensor" : request
+@enduml
+
+PlantUML version 1.2020.22(Sun Dec 06 10:36:27 CET 2020)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Default Encoding: UTF-8
+Language: pl
+Country: PL
+--></g></svg><
\ No newline at end of file
A module-services/service-evtmgr/doc/screen_light_control.md => module-services/service-evtmgr/doc/screen_light_control.md +59 -0
@@ 0,0 1,59 @@
+# Screen frontlight control
+
+## Modes of operation
+
+Screen frontlight can be controlled in Manual and Standalone mode.
+
+### Manual mode
+
+Manual mode refers to constant level of the screen brightness passed to
+screen_light_control module via messages in field `sevm::screen_light_control::Parameters::manualModeBrightness` .
+
+### Automatic mode
+
+In the automatic mode screen light is controlled using data from the ambient light sensor. This data is
+then processed with brightness function mapping to obtain particular level of screen lighting. Control algoritm contains ramp, hysteresis and gamma correction calculation.
+
+
+
+## Brightness level function
+Brightness level [%] in relation to ambient light luminance level [Lux] is passed as
+a vector of points wchich are automatically interpolated with linear function. `sevm::screen_light_control::Parameters::functionPoints` field is used for parametrization. These
+points have to be in ascending order of luminance values. Example:
+
+```
+sevm::screen_light_control::BrightnessFunction({{50.0f, 30.0f}, {150.0f, 80.0f}, {400.0f, 80.0f}, {700.0f, 40.0f}});
+```
+Which could be translated as follows:
+
+
+
+NOTE: Values before first point and after last point are set to constant level of brightness described by this points. Values in between are interpolated.
+
+## Ramp
+Values of screen brightness are udpated in faster control loop with ramping to acheive smooth change of light. Ramp value could be parametrized in `sevm::screen_light_control::Parameters::rampTimeMS` and refers to 0-100% change of brightness in given number of miliseconds.
+
+## Hysteresis
+
+Hysteresis value is adjustable via API using `sevm::screen_light_control::Parameters::brightnessHysteresis`.
+
+
+
+## Gamma correction
+Gamma correction is an algorithm to adjust change of the light intesivity in the way that it is perceived as linear by human eye.
+
+
+
+Gamma correction is described by formula:
+
+y(x) = scale*(x/scale) <sup>γ</sup>
+
+Where γ is parametrizable correction factor in `sevm::screen_light_control::Parameters::gammaFactor`. Scale is used to normalize x value to 0-1 range.
+Default value of γ is 2.5 . For leds this factor could be in range 2.2-2.8.
+
+
+## Message API
+
+`sevm::ScreenLightControlMessage` is used to control the module. It takes action and data structure as parameters. Set of actions is described in `sevm::screen_light_control::Action`.
+
+<
\ No newline at end of file
M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp => module-services/service-evtmgr/service-evtmgr/EVMessages.hpp +8 -23
@@ 5,6 5,7 @@
#include "KbdMessage.hpp"
#include "BatteryMessages.hpp"
+#include "ScreenLightControl.hpp"
#include <MessageType.hpp>
#include <Service/Message.hpp>
@@ 15,8 16,6 @@
#include <bsp/keyboard/key_codes.hpp>
#include <bsp/torch/torch.hpp>
#include <bsp/keypad_backlight/keypad_backlight.hpp>
-#include <bsp/eink_frontlight/eink_frontlight.hpp>
-#include <bsp/light_sensor/light_sensor.hpp>
#include <string>
@@ 126,6 125,7 @@ namespace sevm
{}
bool success = false;
};
+
class KeypadBacklightMessage : public Message
{
public:
@@ 143,31 143,16 @@ namespace sevm
bool success;
};
- class EinkFrontlightMessage : public Message
+ class ScreenLightControlMessage : public Message
{
public:
- explicit EinkFrontlightMessage(bsp::eink_frontlight::Action act = bsp::eink_frontlight::Action::turnOff,
- std::uint8_t val = 0)
- : Message(MessageType::EVMEinkFrontlightMessage), action(act), value(val)
+ ScreenLightControlMessage(screen_light_control::Action act,
+ screen_light_control::Parameters params = screen_light_control::Parameters())
+ : Message(MessageType::EVMScreenLightControlMessage), action(act), parameters(params)
{}
- const bsp::eink_frontlight::Action action;
- const bsp::eink_frontlight::BrightnessPercentage value;
- };
-
- class LightSensorMessage : public Message
- {
- public:
- LightSensorMessage() : Message(MessageType::EVMLightSensorMessage)
- {}
- };
-
- class LightSensorReadoutMessage : public LightSensorMessage
- {
- public:
- explicit LightSensorReadoutMessage(bsp::light_sensor::IlluminanceLux val) : LightSensorMessage(), value(val)
- {}
- const bsp::light_sensor::IlluminanceLux value;
+ screen_light_control::Action action;
+ screen_light_control::Parameters parameters;
};
} /* namespace sevm*/
M module-services/service-evtmgr/service-evtmgr/EventManager.hpp => module-services/service-evtmgr/service-evtmgr/EventManager.hpp +1 -5
@@ 11,7 11,6 @@
#include <bsp/common.hpp>
#include <bsp/keyboard/key_codes.hpp>
#include <bsp/keypad_backlight/keypad_backlight.hpp>
-#include <bsp/eink_frontlight/eink_frontlight.hpp>
#include <cstdint>
#include <memory>
@@ 25,6 24,7 @@ class EventManager : public sys::Service
private:
void HandleAlarmTrigger(sys::DataMessage *msgl);
void GetNextAlarmTimestamp(time_t timestamp);
+ bool processKeypadBacklightRequest(bsp::keypad_backlight::Action act);
protected:
std::unique_ptr<WorkerEvent> EventWorker;
@@ 60,8 60,4 @@ class EventManager : public sys::Service
* with specified name .
*/
static bool messageSetApplication(sys::Service *sender, const std::string &applicationName);
-
- bool processKeypadBacklightRequest(bsp::keypad_backlight::Action act);
-
- void processEinkFrontlightRequest(bsp::eink_frontlight::Action act, bsp::eink_frontlight::BrightnessPercentage val);
};
A module-services/service-evtmgr/service-evtmgr/ScreenLightControl.hpp => module-services/service-evtmgr/service-evtmgr/ScreenLightControl.hpp +54 -0
@@ 0,0 1,54 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <bsp/eink_frontlight/eink_frontlight.hpp>
+#include <bsp/light_sensor/light_sensor.hpp>
+#include <Service/Timer.hpp>
+#include <memory>
+#include <vector>
+
+/// Screen light control algorithm. Automatic/Manual mode of operation.
+/// Processing of ambient light sensor input to screen brightness output.
+namespace sevm::screen_light_control
+{
+ /// Set of actions to control the screen light
+ enum class Action
+ {
+ turnOff, ///< Turn off screen frontlight
+ turnOn, ///< Turn on screen frontlight
+ enableAutomaticMode, ///< Enable automatic mode of screen frontlight
+ disableAutomaticMode, ///< Disable automatic mode of screen frontlight
+ setManualModeBrightness, ///< Set screen brightness in manual mode control
+ setGammaCorrectionFactor, ///< Set gamma factor for screen frontlight correction
+ setAutomaticModeParameters, ///< Set parameters for automatic mode of screen frontlight
+ };
+
+ using BrightnessFunction =
+ std::vector<std::pair<bsp::light_sensor::IlluminanceLux, bsp::eink_frontlight::BrightnessPercentage>>;
+
+ struct Parameters
+ {
+ /// Screen brightness 0-100% in manual mode
+ bsp::eink_frontlight::BrightnessPercentage manualModeBrightness = 50.0f;
+ /// Vector of points for screen brightness [%] in relation to ambient light [Lux] function. Points have to be in
+ /// ascending order of ambient light values.
+ BrightnessFunction functionPoints = BrightnessFunction({{0.0f, 50.0f}});
+ /// Ramp time of screen brightness in miliseconds per 0-100% change
+ unsigned int rampTimeMS = 1500;
+ /// Hysteresis value of screen brightness control
+ float brightnessHysteresis = 10.0f;
+ /// Gamma factor for screen brightness correction
+ float gammaFactor = 2.5f;
+ };
+
+ /// Initialization of screen light control
+ /// @param 'parent' - pointer to parent sys::Service class
+ void init(sys::Service *parent);
+
+ void deinit();
+
+ void processRequest(Action action, const Parameters ¶ms);
+
+} // namespace sevm::screen_light_control
M source/MessageType.hpp => source/MessageType.hpp +3 -5
@@ 171,12 171,10 @@ enum class MessageType
EVMTimeUpdated, ///< This message is send on every time update.
// Torch messages
EVMTorchStateMessage,
- // Keypad backlight messages
+ // Keypad backlight control messages
EVMKeypadBacklightMessage,
- // Eink frontlight messages
- EVMEinkFrontlightMessage,
- // Light sensor messages
- EVMLightSensorMessage,
+ // Screen frontlight control messages
+ EVMScreenLightControlMessage,
// cellular messages
EVMGetBoard,