M module-gui/gui/Common.hpp => module-gui/gui/Common.hpp +6 -3
@@ 30,13 30,16 @@ namespace gui
struct Point
{
Position x = 0, y = 0;
- Point(Position x = 0, Position y = 0) : x(x), y(y)
+
+ constexpr Point(Position x = 0, Position y = 0) : x(x), y(y)
{}
- [[nodiscard]] auto get(Axis axis) const -> Length
+
+ [[nodiscard]] constexpr auto get(Axis axis) -> Length
{
return Axis::X == axis ? x : y;
}
- [[nodiscard]] auto isZero() const -> bool
+
+ [[nodiscard]] constexpr auto isZero() -> bool
{
return 0 == x && 0 == y;
}
M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +2 -2
@@ 139,8 139,8 @@ namespace app::manager
!ret) {
LOG_ERROR("Failed to initialize GUI service");
}
- if (bool ret =
- sys::SystemManager::CreateService(std::make_shared<ServiceEink>(service::name::eink, GetName()), this);
+ if (bool ret = sys::SystemManager::CreateService(
+ std::make_shared<eink::ServiceEink>(service::name::eink, GetName()), this);
!ret) {
LOG_ERROR("Failed to initialize EInk service");
}
M module-services/service-eink/CMakeLists.txt => module-services/service-eink/CMakeLists.txt +1 -0
@@ 14,6 14,7 @@ message( "EINK BOARD PATH: ${CMAKE_CURRENT_LIST_DIR}/${EINK_BOARD_PATH}" )
set(SOURCES
ServiceEink.cpp
+ EinkScreen.cpp
messages/ImageMessage.cpp
)
A module-services/service-eink/EinkScreen.cpp => module-services/service-eink/EinkScreen.cpp +210 -0
@@ 0,0 1,210 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "EinkScreen.hpp"
+
+#include <gui/core/Color.hpp>
+#include <gsl/gsl_util>
+
+#include <cstdio>
+#include <cstring>
+
+namespace eink
+{
+ namespace
+ {
+ constexpr auto DefaultSurroundingTemperature = -1000;
+ constexpr auto LutsFileName = "Luts.bin";
+ constexpr auto LUTDSize = 16385;
+ constexpr auto LUTCSize = 64;
+ constexpr auto LUTRSize = 256; ///< Needed due to \ref EINK_LUTS_FILE_PATH structure
+ constexpr auto LUTSTotalSize = LUTDSize + LUTCSize + LUTRSize;
+
+ EinkWaveFormSettings_t createDefaultWaveFormSettings(EinkWaveforms_e waveformMode)
+ {
+ EinkWaveFormSettings_t settings{};
+ settings.mode = waveformMode;
+ settings.temperature = DefaultSurroundingTemperature;
+ settings.LUTCData = nullptr;
+ settings.LUTCSize = 0;
+ settings.LUTDData = nullptr;
+ settings.LUTDSize = 0;
+ return settings;
+ }
+
+ std::unique_ptr<std::uint8_t[]> allocateScreenBuffer(gui::Size screenSize)
+ {
+ return std::make_unique<std::uint8_t[]>(screenSize.width * screenSize.height);
+ }
+ } // namespace
+
+ EinkScreen::EinkScreen(gui::Size screenSize)
+ : size{screenSize}, screenBuffer{allocateScreenBuffer(screenSize)},
+ waveformSettings{createDefaultWaveFormSettings(EinkWaveformGC16)},
+ displayMode{EinkDisplayColorMode_e::EinkDisplayColorModeStandard}
+ {}
+
+ EinkScreen::~EinkScreen() noexcept
+ {
+ delete[] waveformSettings.LUTCData;
+ delete[] waveformSettings.LUTDData;
+ }
+
+ EinkStatus_e EinkScreen::resetAndInit()
+ {
+ return EinkResetAndInitialize();
+ }
+
+ void EinkScreen::dither()
+ {
+ EinkDitherDisplay();
+ }
+
+ void EinkScreen::powerOn()
+ {
+ EinkPowerOn();
+ }
+
+ void EinkScreen::powerOff()
+ {
+ EinkPowerOff();
+ }
+
+ void EinkScreen::shutdown()
+ {
+ EinkPowerDown();
+ }
+
+ void EinkScreen::setScreenBuffer(const std::uint8_t *buffer, std::uint32_t bufferSize)
+ {
+ std::memcpy(screenBuffer.get(), buffer, bufferSize);
+ }
+
+ void EinkScreen::setScreenBuffer(std::uint8_t value, std::uint32_t bufferSize)
+ {
+ std::memset(screenBuffer.get(), value, bufferSize);
+ }
+
+ EinkStatus_e EinkScreen::update()
+ {
+ return EinkUpdateFrame(
+ pointTopLeft.x, pointTopLeft.y, size.width, size.height, screenBuffer.get(), Eink4Bpp, displayMode);
+ }
+
+ EinkStatus_e EinkScreen::refresh(EinkDisplayTimingsMode_e refreshMode)
+ {
+ return EinkRefreshImage(pointTopLeft.x, pointTopLeft.y, size.width, size.height, refreshMode);
+ }
+
+ bool EinkScreen::deepClear(std::int32_t temperature)
+ {
+ const auto waveformMode = waveformSettings.mode;
+
+ powerOn();
+ changeWaveform(EinkWaveforms_e::EinkWaveformA2, temperature);
+
+ fillScreen(gui::Color::White);
+ for (auto i = 0; i < 2; ++i) {
+ fillScreen(gui::Color::Black);
+ fillScreen(gui::Color::White);
+ }
+
+ changeWaveform(waveformMode, temperature);
+ powerOff();
+ return true;
+ }
+
+ void EinkScreen::fillScreen(std::uint8_t colorIntensity)
+ {
+ const auto screenBufferSize = size.width * size.height;
+ setScreenBuffer(colorIntensity, screenBufferSize);
+ if (const auto status = update(); status != EinkOK) {
+ LOG_FATAL("Failed to update frame");
+ }
+ if (const auto status = refresh(EinkDisplayTimingsFastRefreshMode); status != EinkOK) {
+ LOG_FATAL("Failed to refresh frame");
+ }
+ }
+
+ bool EinkScreen::changeWaveform(EinkWaveforms_e mode, std::int32_t temperature)
+ {
+ if (temperature == waveformSettings.temperature && mode == waveformSettings.mode) {
+ return EinkOK;
+ }
+ waveformSettings.temperature = temperature;
+ waveformSettings.mode = mode;
+
+ const auto segment = calculateWaveFormSegment(temperature);
+ auto offset = calculateWaveFormOffset(mode, segment);
+
+ auto file = std::fopen(LutsFileName, "rb");
+ if (file == nullptr) {
+ LOG_FATAL("Could not find the LUTS.bin file. Returning");
+ return false;
+ }
+ auto fileHandlerCleanup = gsl::finally([&file]() { std::fclose(file); });
+
+ resetWaveFormSettings();
+ std::fseek(file, offset, SEEK_SET);
+ std::fread(&waveformSettings.LUTDData[1], 1, LUTDSize, file);
+
+ // 0x00 - 1 frame, ... , 0x0F - 16 frames
+ const uint8_t frameCount = waveformSettings.LUTDData[1] + 1;
+ // (frameCount * 64) - size of actual LUT; (+1) - the byte containing frameCount; (+1) - EinkLUTD command
+ waveformSettings.LUTDSize = (frameCount * 64) + 1 + 1;
+
+ offset += LUTDSize;
+ std::fseek(file, offset, SEEK_SET);
+ std::fread(&waveformSettings.LUTCData[1], 1, LUTCSize, file);
+
+ EinkUpdateWaveform(&waveformSettings);
+ return true;
+ }
+
+ unsigned int EinkScreen::calculateWaveFormSegment(std::int32_t temperature) const
+ {
+ if (temperature < 38) {
+ return temperature / 3;
+ }
+ if (temperature < 43) {
+ return 12;
+ }
+ return 13;
+ }
+
+ unsigned int EinkScreen::calculateWaveFormOffset(EinkWaveforms_e mode, unsigned int segment) const
+ {
+ switch (mode) {
+ case EinkWaveformINIT:
+ return LUTSTotalSize * segment;
+ case EinkWaveformA2:
+ return LUTSTotalSize * (14 + segment);
+ case EinkWaveformDU2:
+ return LUTSTotalSize * (28 + segment);
+ case EinkWaveformGLD16:
+ return LUTSTotalSize * (42 + segment);
+ case EinkWaveformGC16:
+ [[fallthrough]];
+ default:
+ return LUTSTotalSize * (56 + segment);
+ }
+ }
+
+ void EinkScreen::resetWaveFormSettings()
+ {
+ delete[] waveformSettings.LUTDData;
+ waveformSettings.LUTDSize = 0;
+ waveformSettings.LUTDData = new uint8_t[LUTDSize + 1];
+ waveformSettings.LUTDData[0] = EinkLUTD;
+
+ delete[] waveformSettings.LUTCData;
+ waveformSettings.LUTCSize = LUTCSize;
+ waveformSettings.LUTCData = new uint8_t[LUTCSize + 1];
+ waveformSettings.LUTCData[0] = EinkLUTC;
+ }
+
+ void EinkScreen::setDisplayMode(EinkDisplayColorMode_e mode) noexcept
+ {
+ displayMode = mode;
+ }
+} // namespace eink
A module-services/service-eink/EinkScreen.hpp => module-services/service-eink/EinkScreen.hpp +49 -0
@@ 0,0 1,49 @@
+// 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 <gui/Common.hpp>
+
+#include <EinkIncludes.hpp>
+
+#include <cstdint>
+#include <memory>
+
+namespace eink
+{
+ class EinkScreen
+ {
+ public:
+ explicit EinkScreen(gui::Size screenSize = {480, 600});
+ ~EinkScreen() noexcept;
+
+ EinkStatus_e resetAndInit();
+ EinkStatus_e update();
+ EinkStatus_e refresh(EinkDisplayTimingsMode_e refreshMode);
+ void dither();
+ void powerOn();
+ void powerOff();
+ void shutdown();
+
+ bool deepClear(std::int32_t temperature);
+ bool changeWaveform(EinkWaveforms_e mode, std::int32_t temperature);
+
+ void setScreenBuffer(const std::uint8_t *buffer, std::uint32_t bufferSize);
+ void setDisplayMode(EinkDisplayColorMode_e mode) noexcept;
+
+ private:
+ void fillScreen(std::uint8_t colorIntensity);
+ void setScreenBuffer(std::uint8_t value, std::uint32_t bufferSize);
+ unsigned int calculateWaveFormSegment(std::int32_t temperature) const;
+ unsigned int calculateWaveFormOffset(EinkWaveforms_e mode, unsigned int segment) const;
+ void resetWaveFormSettings();
+
+ static constexpr gui::Point pointTopLeft{0, 0};
+
+ const gui::Size size;
+ std::unique_ptr<std::uint8_t[]> screenBuffer;
+ EinkWaveFormSettings_t waveformSettings;
+ EinkDisplayColorMode_e displayMode;
+ };
+} // namespace eink
M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +126 -299
@@ 13,316 13,140 @@
#include <log/log.hpp>
#include <messages/EinkMessage.hpp>
#include <messages/ImageMessage.hpp>
-#include <MessageType.hpp>
#include <Service/Bus.hpp>
-#include <service-gui/messages/GUIMessage.hpp>
-#include <cstdio>
#include <cstring>
#include <memory>
-enum class EinkWorkerCommands
+namespace eink
{
- Initialize,
- Initialized,
- Destroy,
- CopyImage,
- CopyCompleteCallback,
- CopyComplete
-};
-
-ServiceEink::ServiceEink(const std::string &name, std::string parent)
- : sys::Service(name, parent, 4096 + 1024),
- einkRenderBuffer(std::make_unique<uint8_t[]>(screen.height * screen.width)), selfRefereshTriggerCount{0},
- temperatureMeasurementTriggerCount{0}, powerOffTriggerCount{0},
- powerOffTimer("PwrOffTimer", this, 3000, sys::Timer::Type::SingleShot)
-{
- memset(&waveformSettings, 0, sizeof(EinkWaveFormSettings_t));
- waveformSettings.mode = EinkWaveformGC16;
- waveformSettings.temperature = -1000;
-
- connect(typeid(service::eink::EinkModeMessage), [this](sys::Message *message) -> sys::MessagePointer {
- auto msg = static_cast<service::eink::EinkModeMessage *>(message);
- this->displayMode = msg->getMode() == service::eink::EinkModeMessage::Mode::Normal
- ? EinkDisplayColorMode_e::EinkDisplayColorModeStandard
- : EinkDisplayColorMode_e::EinkDisplayColorModeInverted;
- return sys::MessageNone{};
- });
-
- connect(typeid(service::eink::EinkDMATransfer),
- [&](sys::Message *request) -> sys::MessagePointer { return handleEinkDMATransfer(request); });
-
- connect(typeid(service::eink::ImageMessage),
- [&](sys::Message *request) -> sys::MessagePointer { return handleImageMessage(request); });
-
- connect(typeid(service::eink::StateRequest),
- [&](sys::Message *request) -> sys::MessagePointer { return handleStateRequest(request); });
-
- connect(typeid(service::eink::TemperatureUpdate),
- [&](sys::Message *request) -> sys::MessagePointer { return handleTemperatureUpdate(request); });
-}
-
-ServiceEink::~ServiceEink()
-{
- if (waveformSettings.LUTCData != nullptr)
- delete[] waveformSettings.LUTCData;
- if (waveformSettings.LUTDData != nullptr)
- delete[] waveformSettings.LUTDData;
- waveformSettings.temperature = -1000;
-}
-
-sys::MessagePointer ServiceEink::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
-{
- return std::make_shared<sys::ResponseMessage>();
-}
-
-sys::ReturnCodes ServiceEink::InitHandler()
-{
-
- LOG_INFO("[ServiceEink] Initializing");
-
- EinkStatus_e einkStatus = EinkResetAndInitialize();
-
- if (einkStatus != EinkOK) {
- LOG_FATAL("Error: Could not initialize Eink display!\n");
+ namespace
+ {
+ constexpr auto ServceEinkStackDepth = 4096 + 1024;
+ } // namespace
+
+ ServiceEink::ServiceEink(const std::string &name, std::string parent)
+ : sys::Service(name, parent, ServceEinkStackDepth), selfRefereshTriggerCount{0},
+ temperatureMeasurementTriggerCount{0}, powerOffTriggerCount{0},
+ powerOffTimer("PwrOffTimer", this, 3000, sys::Timer::Type::SingleShot)
+ {
+ connect(typeid(service::eink::EinkModeMessage),
+ [this](sys::Message *message) -> sys::MessagePointer { return handleEinkModeChangedMessage(message); });
+
+ connect(typeid(service::eink::EinkDMATransfer),
+ [this](sys::Message *request) -> sys::MessagePointer { return handleEinkDMATransfer(request); });
+
+ connect(typeid(service::eink::ImageMessage),
+ [this](sys::Message *request) -> sys::MessagePointer { return handleImageMessage(request); });
+
+ connect(typeid(service::eink::StateRequest),
+ [this](sys::Message *request) -> sys::MessagePointer { return handleStateRequest(request); });
+
+ connect(typeid(service::eink::TemperatureUpdate),
+ [this](sys::Message *request) -> sys::MessagePointer { return handleTemperatureUpdate(request); });
}
- EinkPowerOn();
-
- auto msg = std::make_shared<service::gui::GUIDisplayReady>(suspendInProgress, shutdownInProgress);
- sys::Bus::SendUnicast(msg, service::name::gui, this);
-
- return sys::ReturnCodes::Success;
-}
-
-sys::ReturnCodes ServiceEink::DeinitHandler()
-{
- EinkPowerDown();
- return sys::ReturnCodes::Success;
-}
-
-sys::ReturnCodes ServiceEink::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
-{
- LOG_FATAL("[ServiceEink] PowerModeHandler: %s", c_str(mode));
-
- switch (mode) {
- case sys::ServicePowerMode ::Active: {
- suspended = false;
- EinkStatus_e einkStatus = EinkResetAndInitialize();
+ sys::MessagePointer ServiceEink::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
+ {
+ return std::make_shared<sys::ResponseMessage>();
+ }
- if (einkStatus != EinkOK) {
+ sys::ReturnCodes ServiceEink::InitHandler()
+ {
+ LOG_INFO("[ServiceEink] Initializing");
+ if (const auto status = screen.resetAndInit(); status != EinkOK) {
LOG_FATAL("Error: Could not initialize Eink display!\n");
+ return sys::ReturnCodes::Failure;
}
+ screen.powerOn();
- EinkPowerOn();
- EinkPowerOff();
- } break;
- case sys::ServicePowerMode ::SuspendToRAM:
- case sys::ServicePowerMode ::SuspendToNVM:
- suspended = true;
- powerOffTimer.stop();
- EinkPowerDown();
- break;
+ auto msg = std::make_shared<service::gui::GUIDisplayReady>(suspendInProgress, shutdownInProgress);
+ sys::Bus::SendUnicast(msg, service::name::gui, this);
+ return sys::ReturnCodes::Success;
}
- return sys::ReturnCodes::Success;
-}
-
-bool ServiceEink::changeWaveform(EinkWaveforms_e mode, const int32_t temperature)
-{
-
- if ((temperature == waveformSettings.temperature) && (mode == waveformSettings.mode)) {
- return EinkOK;
+ sys::ReturnCodes ServiceEink::DeinitHandler()
+ {
+ screen.shutdown();
+ return sys::ReturnCodes::Success;
}
- const uint32_t LUTD_SIZE = 16385;
- const uint32_t LUTC_SIZE = 64;
- const uint32_t LUTR_SIZE = 256; ///< Needed due to \ref EINK_LUTS_FILE_PATH structure
-
- const uint32_t LUTS_TOTAL_SIZE = LUTD_SIZE + LUTC_SIZE + LUTR_SIZE;
-
- waveformSettings.temperature = temperature;
- waveformSettings.mode = mode;
-
- unsigned int segment = 0;
-
- if (temperature < 38) {
- segment = temperature / 3;
- }
- else {
- if (temperature < 43) {
- segment = 12;
- }
- else {
- segment = 13;
+ sys::ReturnCodes ServiceEink::SwitchPowerModeHandler(const sys::ServicePowerMode mode)
+ {
+ LOG_FATAL("[ServiceEink] PowerModeHandler: %s", c_str(mode));
+
+ switch (mode) {
+ case sys::ServicePowerMode::Active:
+ enterActiveMode();
+ break;
+ case sys::ServicePowerMode::SuspendToRAM:
+ [[fallthrough]];
+ case sys::ServicePowerMode::SuspendToNVM:
+ suspend();
+ break;
}
+ return sys::ReturnCodes::Success;
}
- uint32_t offset = 0;
-
- switch (mode) {
- case EinkWaveformINIT:
- offset = LUTS_TOTAL_SIZE * segment;
- break;
-
- case EinkWaveformA2:
- offset = LUTS_TOTAL_SIZE * (14 + segment);
- break;
-
- case EinkWaveformDU2:
- offset = LUTS_TOTAL_SIZE * (28 + segment);
- break;
-
- case EinkWaveformGLD16:
- offset = LUTS_TOTAL_SIZE * (42 + segment);
- break;
-
- case EinkWaveformGC16:
- default:
- offset = LUTS_TOTAL_SIZE * (56 + segment);
- break;
- }
-
- auto file = std::fopen("Luts.bin", "rb");
- if (file == nullptr) {
- LOG_FATAL("Could not find the LUTS.bin file. Returning");
- return false;
- }
-
- if (waveformSettings.LUTDData != nullptr)
- delete[] waveformSettings.LUTDData;
-
- waveformSettings.LUTDSize = 0;
- waveformSettings.LUTDData = new uint8_t[LUTD_SIZE + 1];
+ void ServiceEink::enterActiveMode()
+ {
+ suspended = false;
- if (waveformSettings.LUTDData == nullptr) {
- LOG_ERROR("Could not allocate memory for the LUTD array");
- std::fclose(file);
- return false;
+ if (const auto status = screen.resetAndInit(); status != EinkOK) {
+ LOG_FATAL("Error: Could not initialize Eink display!\n");
+ }
+ screen.powerOn();
+ screen.powerOff();
}
- if (waveformSettings.LUTCData != nullptr)
- delete[] waveformSettings.LUTCData;
+ void ServiceEink::suspend()
+ {
+ suspended = true;
- waveformSettings.LUTCSize = LUTC_SIZE;
- waveformSettings.LUTCData = new uint8_t[LUTC_SIZE + 1];
- if (waveformSettings.LUTCData == nullptr) {
- LOG_ERROR("Could not allocate memory for the LUTC array");
- std::fclose(file);
- return false;
+ powerOffTimer.stop();
+ screen.shutdown();
}
- waveformSettings.LUTDData[0] = EinkLUTD;
- waveformSettings.LUTCData[0] = EinkLUTC;
-
- std::fseek(file, offset, SEEK_SET);
- std::fread(&waveformSettings.LUTDData[1], 1, LUTD_SIZE, file);
-
- uint8_t frameCount = waveformSettings.LUTDData[1] + 1; // 0x00 - 1 frame, ... , 0x0F - 16 frames
- waveformSettings.LUTDSize =
- frameCount * 64 + 1 +
- 1; // (frameCount * 64) - size of actual LUT; (+1) - the byte containing frameCount; (+1) - EinkLUTD command
-
- offset += LUTD_SIZE;
- std::fseek(file, offset, SEEK_SET);
- std::fread(&waveformSettings.LUTCData[1], 1, LUTC_SIZE, file);
-
- std::fclose(file);
-
- EinkUpdateWaveform(&waveformSettings);
-
- return true;
-}
-
-bool ServiceEink::deepClearScreen(int8_t temperature)
-{
- EinkWaveforms_e wv = waveformSettings.mode;
-
- EinkPowerOn();
- changeWaveform(EinkWaveforms_e::EinkWaveformA2, temperature);
-
- EinkStatus_e ret;
- memset(einkRenderBuffer.get(), 15, screen.width * screen.height);
- ret = EinkUpdateFrame(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, einkRenderBuffer.get(), Eink4Bpp, displayMode);
- if (ret != EinkOK)
- LOG_FATAL("Failed to update frame");
- ret = EinkRefreshImage(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, EinkDisplayTimingsFastRefreshMode);
- if (ret != EinkOK)
- LOG_FATAL("Failed to refresh frame");
-
- for (uint32_t i = 0; i < 2; i++) {
- memset(einkRenderBuffer.get(), 0, screen.width * screen.height);
- ret = EinkUpdateFrame(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, einkRenderBuffer.get(), Eink4Bpp, displayMode);
- if (ret != EinkOK)
- LOG_FATAL("Failed to update frame");
- ret = EinkRefreshImage(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, EinkDisplayTimingsFastRefreshMode);
- if (ret != EinkOK)
- LOG_FATAL("Failed to refresh frame");
-
- memset(einkRenderBuffer.get(), 15, screen.width * screen.height);
- ret = EinkUpdateFrame(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, einkRenderBuffer.get(), Eink4Bpp, displayMode);
- if (ret != EinkOK)
- LOG_FATAL("Failed to update frame");
- ret = EinkRefreshImage(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, EinkDisplayTimingsFastRefreshMode);
- if (ret != EinkOK)
- LOG_FATAL("Failed to refresh frame");
+ sys::MessagePointer ServiceEink::handleEinkModeChangedMessage(sys::Message *message)
+ {
+ const auto msg = static_cast<service::eink::EinkModeMessage *>(message);
+ const auto displayMode = msg->getMode() == service::eink::EinkModeMessage::Mode::Normal
+ ? EinkDisplayColorMode_e::EinkDisplayColorModeStandard
+ : EinkDisplayColorMode_e::EinkDisplayColorModeInverted;
+ screen.setDisplayMode(displayMode);
+ return sys::MessageNone{};
}
- changeWaveform(wv, temperature);
-
- EinkPowerOff();
-
- return true;
-}
-
-sys::MessagePointer ServiceEink::handleEinkDMATransfer(sys::Message *message)
-{
- utils::time::Scoped scopedtimming("EinkDMATransfer");
-
- if (suspended) {
- if (suspendInProgress) {
- LOG_ERROR("drawing before suspend failed");
- suspendInProgress = false;
+ sys::MessagePointer ServiceEink::handleEinkDMATransfer(sys::Message *message)
+ {
+ utils::time::Scoped measurement("EinkDMATransfer");
+
+ if (suspended) {
+ if (suspendInProgress) {
+ LOG_ERROR("drawing before suspend failed");
+ suspendInProgress = false;
+ }
+ LOG_INFO("[ServiceEink] Received image while suspended, ignoring");
+ return sys::MessageNone{};
}
- LOG_INFO("[ServiceEink] Received image while suspended, ignoring");
- }
- else {
- EinkPowerOn();
-
- int32_t temperature = EinkGetTemperatureInternal();
-
- EinkStatus_e ret;
- if (deepRefresh) {
- changeWaveform(EinkWaveforms_e::EinkWaveformGC16, temperature);
- EinkDitherDisplay();
+ screen.powerOn();
+ if (const auto temperature = EinkGetTemperatureInternal(); deepRefresh) {
+ screen.changeWaveform(EinkWaveforms_e::EinkWaveformGC16, temperature);
+ screen.dither();
}
else {
- changeWaveform(EinkWaveforms_e::EinkWaveformDU2, temperature);
+ screen.changeWaveform(EinkWaveforms_e::EinkWaveformDU2, temperature);
}
- ret = EinkUpdateFrame(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, einkRenderBuffer.get(), Eink4Bpp, displayMode);
- if (ret != EinkOK)
+ if (const auto status = screen.update(); status != EinkOK) {
LOG_FATAL("Failed to update frame");
-
- if (deepRefresh) {
- ret = EinkRefreshImage(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, EinkDisplayTimingsDeepCleanMode);
}
- else {
- ret = EinkRefreshImage(
- pointTopLeft.x, pointTopLeft.y, screen.width, screen.height, EinkDisplayTimingsFastRefreshMode);
- }
-
- if (ret != EinkOK)
+ if (const auto status =
+ screen.refresh(deepRefresh ? EinkDisplayTimingsDeepCleanMode : EinkDisplayTimingsFastRefreshMode);
+ status != EinkOK) {
LOG_FATAL("Failed to refresh frame");
+ }
powerOffTimer.reload();
@@ 330,35 154,38 @@ sys::MessagePointer ServiceEink::handleEinkDMATransfer(sys::Message *message)
suspendInProgress = false;
shutdownInProgress = false;
sys::Bus::SendUnicast(msg, service::name::gui, this);
+
+ return sys::MessageNone{};
}
- return nullptr;
-}
-sys::MessagePointer ServiceEink::handleImageMessage(sys::Message *request)
-{
- auto message = static_cast<service::eink::ImageMessage *>(request);
+ sys::MessagePointer ServiceEink::handleImageMessage(sys::Message *request)
+ {
+ auto message = static_cast<service::eink::ImageMessage *>(request);
- powerOffTimer.stop();
- memcpy(einkRenderBuffer.get(), message->getData(), message->getSize());
- deepRefresh = message->getDeepRefresh();
+ powerOffTimer.stop();
+ screen.setScreenBuffer(message->getData(), message->getSize());
+ deepRefresh = message->getDeepRefresh();
- shutdownInProgress = message->getShutdown();
- if (shutdownInProgress)
- LOG_DEBUG("Shutdown In Progress");
+ shutdownInProgress = message->getShutdown();
+ if (shutdownInProgress) {
+ LOG_DEBUG("Shutdown In Progress");
+ }
+ suspendInProgress = message->getSuspend();
+ if (suspendInProgress) {
+ LOG_DEBUG("Suspend In Progress");
+ }
- suspendInProgress = message->getSuspend();
- if (suspendInProgress)
- LOG_DEBUG("Suspend In Progress");
- sys::Bus::SendUnicast(std::make_shared<service::eink::EinkDMATransfer>(), GetName(), this);
- return std::make_shared<sys::ResponseMessage>();
-}
+ sys::Bus::SendUnicast(std::make_shared<service::eink::EinkDMATransfer>(), GetName(), this);
+ return std::make_shared<sys::ResponseMessage>();
+ }
-sys::MessagePointer ServiceEink::handleStateRequest(sys::Message *)
-{
- return std::make_shared<service::gui::GUIDisplayReady>(suspendInProgress, shutdownInProgress);
-}
+ sys::MessagePointer ServiceEink::handleStateRequest(sys::Message *)
+ {
+ return std::make_shared<service::gui::GUIDisplayReady>(suspendInProgress, shutdownInProgress);
+ }
-sys::MessagePointer ServiceEink::handleTemperatureUpdate(sys::Message *)
-{
- return nullptr;
-}
+ sys::MessagePointer ServiceEink::handleTemperatureUpdate(sys::Message *)
+ {
+ return nullptr;
+ }
+} // namespace eink
M module-services/service-eink/ServiceEink.hpp => module-services/service-eink/ServiceEink.hpp +50 -54
@@ 13,58 13,54 @@
#include <cstdint>
#include <string>
-class ServiceEink : public sys::Service
-{
- gui::Size screen = {480, 600};
- gui::Point pointTopLeft = {0, 0};
- std::unique_ptr<uint8_t[]> einkRenderBuffer;
-
- protected:
- // counts timer triggers from last self refresh
- uint32_t selfRefereshTriggerCount;
- // counts timer events from last temperature measurement
- uint32_t temperatureMeasurementTriggerCount;
- // counts trigger counts from last action that required eink to be powered on
- uint32_t powerOffTriggerCount;
-
- // number of timer triggers required to execute self refresh handler
- const uint32_t selfRefereshTriggerValue = 60;
- // number of timer triggers required to execute temperature measurement handler
- const uint32_t temperatureMeasurementTriggerValue = 5 * 60;
- // number of timer triggers from last action requiring power on eink to power down eink.
- const uint32_t powerOffTriggerValue = 3;
-
- // structure with recently loaded waveformdata
- EinkWaveFormSettings_t waveformSettings;
-
- EinkDisplayColorMode_e displayMode = EinkDisplayColorMode_e::EinkDisplayColorModeStandard;
-
- bool suspended = false;
-
- bool suspendInProgress = false;
- bool shutdownInProgress = false;
+#include "EinkScreen.hpp"
- bool changeWaveform(EinkWaveforms_e Mode, const int32_t temperature);
-
- bool deepClearScreen(int8_t temperature);
-
- bool deepRefresh = false;
-
- sys::ms powerOffTime = 3000;
- sys::Timer powerOffTimer;
-
- public:
- ServiceEink(const std::string &name, std::string parent = "");
- ~ServiceEink() override;
-
- sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
- sys::ReturnCodes InitHandler() override;
- sys::ReturnCodes DeinitHandler() override;
- sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;
-
- private:
- sys::MessagePointer handleEinkDMATransfer(sys::Message *message);
- sys::MessagePointer handleImageMessage(sys::Message *message);
- sys::MessagePointer handleStateRequest(sys::Message *messge);
- sys::MessagePointer handleTemperatureUpdate(sys::Message *);
-};
+namespace eink
+{
+ class ServiceEink : public sys::Service
+ {
+ protected:
+ EinkScreen screen;
+
+ // counts timer triggers from last self refresh
+ uint32_t selfRefereshTriggerCount;
+ // counts timer events from last temperature measurement
+ uint32_t temperatureMeasurementTriggerCount;
+ // counts trigger counts from last action that required eink to be powered on
+ uint32_t powerOffTriggerCount;
+
+ // number of timer triggers required to execute self refresh handler
+ const uint32_t selfRefereshTriggerValue = 60;
+ // number of timer triggers required to execute temperature measurement handler
+ const uint32_t temperatureMeasurementTriggerValue = 5 * 60;
+ // number of timer triggers from last action requiring power on eink to power down eink.
+ const uint32_t powerOffTriggerValue = 3;
+
+ bool suspended = false;
+
+ bool suspendInProgress = false;
+ bool shutdownInProgress = false;
+ bool deepRefresh = false;
+
+ sys::ms powerOffTime = 3000;
+ sys::Timer powerOffTimer;
+
+ public:
+ explicit ServiceEink(const std::string &name, std::string parent = {});
+
+ sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
+ sys::ReturnCodes InitHandler() override;
+ sys::ReturnCodes DeinitHandler() override;
+ sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;
+
+ private:
+ void enterActiveMode();
+ void suspend();
+
+ sys::MessagePointer handleEinkModeChangedMessage(sys::Message *message);
+ sys::MessagePointer handleEinkDMATransfer(sys::Message *message);
+ sys::MessagePointer handleImageMessage(sys::Message *message);
+ sys::MessagePointer handleStateRequest(sys::Message *messge);
+ sys::MessagePointer handleTemperatureUpdate(sys::Message *);
+ };
+} // namespace eink