M module-apps/application-meditation/CMakeLists.txt => module-apps/application-meditation/CMakeLists.txt +1 -0
@@ 47,6 47,7 @@ target_link_libraries(application-meditation
module-vfs
service-audio
utils-time
+ Microsoft.GSL::GSL
PUBLIC
apps-common
module-gui
M module-apps/application-onboarding/CMakeLists.txt => module-apps/application-onboarding/CMakeLists.txt +1 -0
@@ 51,6 51,7 @@ target_link_libraries(application-onboarding
i18n
log
module-gui
+ Microsoft.GSL::GSL
PUBLIC
apps-common
)
M module-bsp/board/linux/CMakeLists.txt => module-bsp/board/linux/CMakeLists.txt +1 -0
@@ 11,6 11,7 @@ target_sources(module-bsp
eeprom/eeprom.cpp
eink_frontlight/eink_frontlight.cpp
eink/ED028TC1.c
+ eink/LinuxEinkDisplay.cpp
headset/headset.cpp
keypad_backlight/keypad_backlight.cpp
light_sensor/light_sensor.cpp
M module-bsp/board/linux/eink/ED028TC1.c => module-bsp/board/linux/eink/ED028TC1.c +6 -32
@@ 49,10 49,6 @@ int shared_fd = 0;
static uint8_t s_einkIsPoweredOn = false; // Variable which contains the state of the power of the EPD display
-/* Function bodies */
-void EinkChangeDisplayUpdateTimings(EinkDisplayTimingsMode_e timingsMode)
-{}
-
uint8_t EinkIsPoweredOn()
{
return s_einkIsPoweredOn;
@@ 73,11 69,6 @@ void EinkPowerDown(void)
EinkPowerOff();
}
-int16_t EinkGetTemperatureInternal()
-{
- return 25;
-}
-
static shared_memory_header *createSHMBuffer(const char *name)
{
if (shared_header != NULL)
@@ 128,30 119,14 @@ EinkStatus_e EinkResetAndInitialize()
return EinkOK;
}
-EinkStatus_e EinkUpdateWaveform(const EinkWaveformSettings_t *settings)
-{
- return EinkOK;
-}
-
-EinkStatus_e EinkWaitTillPipelineBusy()
-{
- return EinkOK;
-}
-
-EinkStatus_e EinkDitherDisplay()
-{
- return EinkOK;
-}
-
-EinkStatus_e EinkUpdateFrame(
- uint16_t X, uint16_t Y, uint16_t W, uint16_t H, uint8_t *buffer, EinkBpp_e bpp, EinkDisplayColorMode_e invertColors)
+EinkStatus_e EinkUpdateFrame(EinkFrame_t frame, uint8_t *buffer)
{
- uint32_t offset_eink = Y * BOARD_EINK_DISPLAY_RES_X + X;
+ uint32_t offset_eink = frame.pos_y * BOARD_EINK_DISPLAY_RES_X + frame.pos_x;
uint32_t offset_buffer = 0;
- for (uint32_t h = 0; h < H; ++h) {
- memcpy(shared_buffer + offset_eink, buffer + offset_buffer, W);
+ for (uint32_t h = 0; h < frame.height; ++h) {
+ memcpy(shared_buffer + offset_eink, buffer + offset_buffer, frame.width);
offset_eink += BOARD_EINK_DISPLAY_RES_X;
- offset_buffer += W;
+ offset_buffer += frame.width;
}
shared_header->frameCount++;
@@ 168,8 143,7 @@ EinkStatus_e EinkFillScreenWithColor(EinkDisplayColorFilling_e colorFill)
return EinkError;
}
-EinkStatus_e EinkRefreshImage(
- uint16_t X, uint16_t Y, uint16_t W, uint16_t H, EinkDisplayTimingsMode_e refreshTimingsMode)
+EinkStatus_e EinkRefreshImage(EinkFrame_t frame)
{
return EinkOK;
}
M module-bsp/board/linux/eink/ED028TC1.h => module-bsp/board/linux/eink/ED028TC1.h +9 -314
@@ 22,218 22,6 @@ extern "C"
{
#endif /* __cplusplus */
-/* Exported macro ------------------------------------------------------------*/
-/**
- * @brief ED028TC1 register definitions
- */
-#define EinkPanelSetting (0x00U)
-#define EinkPowerSetting (0x01U)
-#define EinkPowerOFF (0x02U)
-#define EinkPowerOFFSequenceSetting (0x03U)
-#define EinkPowerON (0x04U)
-#define EinkDPC (0x05U)
-#define EinkDSLP (0x06U)
-#define EinkBoosterSoftStart (0x07U)
-
-#define EinkDataStartTransmission1 (0x10U)
-#define EinkDisplayRefresh (0x12U)
-#define EinkDTM2 (0x13U)
-#define EinkAWM1 (0x15U)
-#define EinkAWM2 (0x16U)
-
-#define EinkLUTC (0x20U)
-#define EinkLUTD (0x21U)
-#define EinkLUTR (0x22U)
-#define EinkPowerSaving (0x26U)
-#define EinkMISCS (0x27U)
-
-#define EinkPLLControl (0x30U)
-
-#define EinkTemperatureSensorCalibration (0x40U)
-#define EinkTemperatureSensorSelection (0x41U)
-
-#define EinkVcomAndDataIntervalSetting (0x50U)
-#define EinkLPD (0x51U)
-
-#define EinkTCONSetting (0x60U)
-#define EinkResolutionSetting (0x61U)
-#define EinkDAM (0x65U)
-
-#define EinkREV (0x70U)
-#define EinkFLG (0x71U)
-#define EinkLUT_COL_FLG (0x72U)
-#define EinkLUT_BUSY_FLG (0x73U)
-
-#define EinkAutoMeasurementVcom (0x80U)
-#define EinkReadVcomValue (0x81U)
-#define EinkVCM_DCSetting (0x82U)
-#define EinkDataStartTransmissionWindow (0x83U)
-#define EinkEDS (0x84U)
-#define EinkXONS (0x85U)
-
-#define EinkLEDDS (0x90U)
-#define EinkPBC (0x91U)
-#define EinkPBCS (0x92U)
-#define EinkEXTRS (0x93U)
-#define EinkNTRS (0x94U)
-
-#define EinkGDOrderSetting (0xE0U)
-
-/**
- * @brief ED028TC1 register bit definitions
- */
-// PanelSetting
-#define XON (1 << 7)
-#define RES0 (1 << 6)
-#define LUT_SEL (1 << 5)
-#define DM (1 << 4)
-#define SHL (1 << 2)
-#define SPIWM (1 << 1)
-#define RST_N (1 << 0)
-#define SFT1PX (0 << 0)
-#define SFT2PX (1 << 0)
-#define SFT3PX (2 << 0)
-#define SFT4PX (3 << 0)
-
-// PowerSetting
-#define VSource_EN (1 << 0)
-#define VGate_EN (1 << 1)
-#define VG_LVL17V (0 << 0)
-#define VG_LVL18V (1 << 0)
-#define VG_LVL19V (2 << 0)
-#define VG_LVL20V (3 << 0)
-#define VG_LVL21V (4 << 0)
-#define VSLV_LVL (0) // this is: 7-bit 00h=2.4V, 7Fh=15.0V
-#define VSL_LVL15V (0 << 2)
-#define VSL_LVL14V (1 << 2)
-#define VSL_LVL13V (2 << 2)
-#define VSL_LVL12V (3 << 2)
-#define VSH_LVL15V (0 << 0)
-#define VSH_LVL14V (1 << 0)
-#define VSH_LVL13V (2 << 0)
-#define VSH_LVL12V (3 << 0)
-
-// PowerOFFSequenceSetting
-#define T_VDS_OFF_1F (0 << 4)
-#define T_VDS_OFF_2F (1 << 4)
-#define T_VDS_OFF_3F (2 << 4)
-#define T_VDS_OFF_4F (3 << 4)
-
-// BoosterSoftStart
-#define BTPHx_SSP_10ms (0 << 6) // soft start period of phase A,B
-#define BTPHx_SSP_20ms (1 << 6)
-#define BTPHx_SSP_30ms (2 << 6)
-#define BTPHx_SSP_40ms (3 << 6)
-#define BTPHx_DS_1 (0 << 3) // driving strength of phase A,B,C
-#define BTPHx_DS_2 (1 << 3)
-#define BTPHx_DS_3 (2 << 3)
-#define BTPHx_DS_4 (3 << 3)
-#define BTPHx_DS_5 (4 << 3)
-#define BTPHx_DS_6 (5 << 3)
-#define BTPHx_DS_7 (6 << 3)
-#define BTPHx_DS_8 (7 << 3)
-#define BTPHx_OT_027 (0 << 0) // minimum OFF time setting of phase A,B,C
-#define BTPHx_OT_034 (1 << 0)
-#define BTPHx_OT_040 (2 << 0)
-#define BTPHx_OT_054 (3 << 0)
-#define BTPHx_OT_080 (4 << 0)
-#define BTPHx_OT_154 (5 << 0)
-#define BTPHx_OT_334 (6 << 0)
-#define BTPHx_OT_658 (7 << 0)
-
-#define EINK_TEMPERATURE_SENSOR_USE_INTERNAL (0 << 6)
-#define EINK_TEMPERATURE_SENSOR_USE_EXTERNAL (2 << 6)
-
-// DataStartTransmission1
-#define Cur_BPP1 (0 << 0)
-#define Cur_BPP2 (1 << 0)
-#define Cur_BPP3 (2 << 0)
-#define Cur_BPP4 (3 << 0)
-
-// DisplayRefresh
-#define AC_DCVCOM (1 << 7)
-#define WFMode0 (0 << 4)
-#define WFMode1 (1 << 4)
-#define WFMode2 (2 << 4)
-#define WFMode3 (3 << 4)
-#define WFMode4 (4 << 4)
-#define UPD_CPY_TO_PRE (1 << 3)
-#define DN_EN (1 << 2)
-#define Regal_EN_DIS (0 << 0)
-#define Regal_EN_K (1 << 0)
-#define Regal_EN_W (2 << 0)
-#define Regal_EN_KW (3 << 0)
-
-// PLLControl
-#define OSC_RATE_SEL2_5 (0 << 1)
-#define OSC_RATE_SEL5 (1 << 1)
-#define OSC_RATE_SEL8 (2 << 1)
-#define OSC_RATE_SEL10 (3 << 1)
-#define OSC_RATE_SEL16 (4 << 1)
-#define OSC_RATE_SEL18 (5 << 1)
-#define OSC_RATE_SEL19 (6 << 1)
-#define OSC_RATE_SEL20 (7 << 1)
-
-// VcomAndDataIntervalSetting
-#define VBD_CON (1 << 3)
-#define VBD_OT_G0_G0 (0 << 1)
-#define VBD_OT_G0_G15 (2 << 1)
-#define VBD_OT_G15_G0 (3 << 1)
-#define VBD_OT_G15_G15 (4 << 1)
-#define DDX (1 << 0)
-#define CDI (4) // Vcom data interval: 0h=2hsync -> Fh=32hsync, step=2
-#define DCI (0) // Data to Vcom interval: 0h=1hsync -> Fh=16hsync, step=1
-
-// AutoMeasurementVcom
-#define VCM_EN (1 << 6)
-#define AMVT3s (0 << 4)
-#define AMVT5s (1 << 4)
-#define AMVT6s (2 << 4)
-#define AMVT10s (3 << 4)
-#define AMVX (1 << 3)
-#define AMVS (1 << 2)
-#define AMV (1 << 1)
-#define AMVE (1 << 0)
-
-// GDOrderSetting
-#define VBD_EN_SEL (1 << 3)
-#define GDOS_M0 (0 << 0)
-#define GDOS_M1 (1 << 0)
-#define GDOS_M2 (2 << 0)
-#define GDOS_M3 (3 << 0)
-#define GDOS_M4 (4 << 0)
-#define GDOS_M5 (5 << 0)
-#define GDOS_M6 (6 << 0)
-#define GDOS_M7 (7 << 0)
-#define VBD_FN (0) // VBorder frame number seting: 0-VBD disabled, 1-VBD=8, ... 1Fh-VBD=248
-
-// Dither
-#define EINK_DITHER_START 0x01
-#define EINK_DITHER_4BPP_MODE (0 << 1)
-#define EINK_DITHER_2BPP_MODE (1 << 1)
-
-#define EINK_FLAG_BUSY_N 0x0001 ///< This flag informs that the driver is busy. 0 - busy, 1 - idle
-#define EINK_FLAG_POWER_OFF_IN_PROGRESS \
- 0x0002 ///< This flag informs that the Power Off sequence is in progress. 1 - in progress
-#define EINK_FLAG_POWER_ON_IN_PROGRESS \
- 0x0004 ///< This flag informs that the Power On sequence is in progress. 1 - in progress
-#define EINK_FLAG_ENTIRE_FRAME_RECEIVED \
- 0x0008 ///< This flag informs that the driver received data for entire frame defined in the \ref
- ///< EinkDataStartTransmissionWindow command
-#define EINK_FLAG_I2C_BUSY 0x0010 ///< This flag informs that the I2C master periph is busy. Active low
-#define EINK_FLAG_I2C_ERROR 0x0020 ///< This flag informs that the I2C master acquired an error
-#define EINK_FLAG_PIPELINE_COLLISION 0x0040 ///< This flag informs that two frames sent in the pipelin overlap
-#define EINK_FLAG_PIPELINE_BUSY 0x0080 ///< This flag informs that pipeline insertion is in progress
-#define EINK_FLAG_REAGL_BUSY 0x0100 ///< This flag informs that the REAGLS function processing is in progress
-#define EINK_FLAG_DITHER_IN_PROGRESS 0x0200 ///< This flag informs that the Dither process is in progress
-#define EINK_FLAG_DISP_REFRESH_IN_PROGRESS \
- 0x0400 ///< This flag informs that the Display Refreshing process is in progress
-#define EINK_FLAG_AUTO_MEASURE_VCOM_IN_PROGRESS \
- 0x0800 ///< This flag informs that the auto measurement of the VCOM is in progress
-#define EINK_FLAG_EPD_DISCHARGE_IN_PROGRESS 0x1000 ///< This flag informs that the EPD display discharge is in progress
-#define EINK_FLAG_BOOST_VOLTAGE_READY 0x4000 ///< This flag informs that the Boost voltage is ready
-#define EINK_FLAG_RAM_TEST_FLAG 0x8000 ///< This flag is for internal SRAM memory testing
-
/* Exported types ------------------------------------------------------------*/
/**
* @enum EinkStatus_e
@@ 251,64 39,19 @@ extern "C"
EinkWaveformsFileOpenFail, //!< Could not open the file with the waveforms for EPD display
} EinkStatus_e;
- /**
- * @enum EinkBpp_e
- */
- typedef enum
- {
- Eink1Bpp = 1, //!< Eink1Bpp
- Eink2Bpp, //!< Eink2Bpp
- Eink3Bpp, //!< Eink3Bpp
- Eink4Bpp //!< Eink4Bpp
- } EinkBpp_e;
-
- typedef enum
- {
- EinkWaveformINIT, ///< Clears deeply the display
- EinkWaveformA2, ///< Fastest, direct update, no flashing. Severe ghosting effect
- EinkWaveformDU2, ///< Fast, direct update, no flashing. Medium ghosting effect
- EinkWaveformGLD16, ///< Slow, little flashing. Light ghosting mode
- EinkWaveformGC16, ///< Slow, strong flashing. Next to none ghosting
- } EinkWaveforms_e;
-
- typedef enum
- {
- EinkDisplayTimingsDeepCleanMode,
- EinkDisplayTimingsHighContrastMode,
- EinkDisplayTimingsFastRefreshMode
- } EinkDisplayTimingsMode_e;
-
typedef enum
{
EinkDisplayColorBlack = 0,
EinkDisplayColorWhite = 0xFF
} EinkDisplayColorFilling_e;
- typedef enum
- {
- EinkDisplayColorModeStandard,
- EinkDisplayColorModeInverted
- } EinkDisplayColorMode_e;
-
typedef struct
{
- // type of eink's waveform
- EinkWaveforms_e mode;
- // temperature of surrounding
- int32_t temperature;
- // use counter to keep track if need to change
- uint32_t useCounter;
- // pointer to lookup table for lut c
- uint8_t *LUTCData;
- // sizeo of lutc data
- uint32_t LUTCSize;
- // pointer to lookup table for lut d
- uint8_t *LUTDData;
- // size of lutd data
- uint32_t LUTDSize;
- } EinkWaveformSettings_t;
-
- /* Exported constants --------------------------------------------------------*/
+ uint16_t pos_x;
+ uint16_t pos_y;
+ uint16_t width;
+ uint16_t height;
+ } EinkFrame_t;
/* Exported functions ------------------------------------------------------- */
@@ 334,51 77,20 @@ extern "C"
void EinkPowerDown(void);
/**
- * This function measures the ambient temperature using the ED028TC1 display internal temperature sensor.
- * @note The display needs to be powered on
- *
- * @return Ambient temperature in the degrees of Celsius
- */
- int16_t EinkGetTemperatureInternal();
-
- /**
* @brief This function resets the eink display and setups the initial configuration
*/
EinkStatus_e EinkResetAndInitialize();
/**
- * TODO: Fill The doxy when got info what does it do
- * @return
- */
- EinkStatus_e EinkWaitTillPipelineBusy();
-
- /**
- * TODO: Fill The doxy when got info what does it do
- * @return
- */
- EinkStatus_e EinkDitherDisplay();
-
- /**
* @brief This function sends the part of image from the given buffer to the internal memory of the display. It
* makes not screen to update.
- * @param X [in] - image start position X in pixels
- * @param Y [in] - image start position Y in pixels
- * @param W [in] - image width in pixels
- * @param H [in] - image height in pixels
+ * @param frame [in] - draw buffer on specified part of screen
* @param buffer [in] - pointer to image encoded according to \ref bpp set in initialization
- * @param bpp [in] - The format of the \ref buffer (number of the bits per pixel)
- * @param invertColors[in] - true if colors of the image are to be inverted, false otherwise
*
* @return EinkNoMem - Could not allocate the temporary buffer
* EinkOK - Part of image send successfully
*/
- EinkStatus_e EinkUpdateFrame(uint16_t X,
- uint16_t Y,
- uint16_t W,
- uint16_t H,
- uint8_t *buffer,
- EinkBpp_e bpp,
- EinkDisplayColorMode_e invertColors);
+ EinkStatus_e EinkUpdateFrame(EinkFrame_t frame, uint8_t *buffer);
/**
* @brief This function sets the waveform to the \ref EinkWaveformINIT to make the display clearing more deep and
@@ 399,28 111,11 @@ extern "C"
/**
* @brief Refresh window on the screen. E-paper display tends to loose contrast over time. To Keep the image sharp
* refresh is needed.
- * @param X refresh window position X in pixels
- * @param Y refresh window position Y in pixels
- * @param W refresh window width in pixels
- * @param H refresh window height in pixels
- * @param refreshTimingsMode [in] - EinkDisplayTimingsDeepCleanMode - if image is to be cleared precisely
- * EinkDisplayTimingsHighContrastMode - if image is displayed in the high contrast
- * mode EinkDisplayTimingsFastRefreshMode - if image is to be displayed fast
+ * @param frame refresh specified part of screen
*
* @return EinkOK
*/
- EinkStatus_e EinkRefreshImage(
- uint16_t X, uint16_t Y, uint16_t W, uint16_t H, EinkDisplayTimingsMode_e refreshTimingsMode);
-
- /**
- * @brief This function sends the proper waveform consisting from the LUTC and LUTD data,
- * based on the requested waveform (see \ref Mode) and the given temperature (see \ref temperature)
- * @param Mode [in] - type of the waveform
- * @param temperature [in] - current ambient temperature in Celsius degrees
- * @param LUTCData [in] - Data
- * @return
- */
- EinkStatus_e EinkUpdateWaveform(const EinkWaveformSettings_t *settings);
+ EinkStatus_e EinkRefreshImage(EinkFrame_t frame);
/**
* This function converts the ARGB image to the L4 format
A module-bsp/board/linux/eink/LinuxEinkDisplay.cpp => module-bsp/board/linux/eink/LinuxEinkDisplay.cpp +95 -0
@@ 0,0 1,95 @@
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <board.h>
+
+#include <log/log.hpp>
+
+#include <cstring>
+#include <memory>
+
+#include "LinuxEinkDisplay.hpp"
+#include "ED028TC1.h"
+
+namespace hal::eink
+{
+ EinkStatus translateStatus(const EinkStatus_e status_e)
+ {
+ switch (status_e) {
+ case EinkOK:
+ return EinkStatus::EinkOK;
+ case EinkError:
+ return EinkStatus::EinkError;
+ case EinkSPIErr:
+ return EinkStatus::EinkSPIErr;
+ case EinkSPINotInitializedErr:
+ return EinkStatus::EinkSPINotInitializedErr;
+ case EinkDMAErr:
+ return EinkStatus::EinkDMAErr;
+ case EinkInitErr:
+ return EinkStatus::EinkInitErr;
+ case EinkTimeout:
+ return EinkStatus::EinkTimeout;
+ case EinkNoMem:
+ return EinkStatus::EinkNoMem;
+ case EinkWaveformsFileOpenFail:
+ return EinkStatus::EinkWaveformsFileOpenFail;
+ default:
+ return EinkStatus::EinkUnknown;
+ }
+ }
+
+ LinuxEinkDisplay::LinuxEinkDisplay(FrameSize size) : size{size}
+ {}
+
+ void LinuxEinkDisplay::setMode(const EinkDisplayColorMode mode) noexcept
+ {
+ displayColorMode = mode;
+ }
+
+ EinkStatus LinuxEinkDisplay::showImage(std::uint8_t *frameBuffer, const EinkRefreshMode refreshMode)
+ {
+ return translateStatus(EinkUpdateFrame(EinkFrame_t{0, 0, size.width, size.height}, frameBuffer));
+ }
+
+ void LinuxEinkDisplay::prepareEarlyRequest([[maybe_unused]] const EinkRefreshMode refreshMode,
+ [[maybe_unused]] const WaveformTemperature behaviour)
+ {}
+
+ void LinuxEinkDisplay::dither()
+ {}
+
+ void LinuxEinkDisplay::powerOn()
+ {
+ EinkPowerOn();
+ }
+
+ void LinuxEinkDisplay::powerOff()
+ {
+ EinkPowerOff();
+ }
+
+ void LinuxEinkDisplay::shutdown()
+ {}
+
+ void LinuxEinkDisplay::wipeOut()
+ {
+ EinkFillScreenWithColor(EinkDisplayColorFilling_e::EinkDisplayColorWhite);
+ }
+
+ EinkStatus LinuxEinkDisplay::resetAndInit()
+ {
+ EinkResetAndInitialize();
+ return EinkStatus::EinkOK;
+ }
+
+ [[nodiscard]] auto LinuxEinkDisplay::getDevice() const noexcept -> std::shared_ptr<devices::Device>
+ {
+ return {};
+ }
+
+ std::unique_ptr<AbstractEinkDisplay> AbstractEinkDisplay::Factory::create(FrameSize size)
+ {
+ return std::make_unique<LinuxEinkDisplay>(size);
+ }
+} // namespace hal::eink
A module-bsp/board/linux/eink/LinuxEinkDisplay.hpp => module-bsp/board/linux/eink/LinuxEinkDisplay.hpp +32 -0
@@ 0,0 1,32 @@
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <hal/eink/AbstractEinkDisplay.hpp>
+
+namespace hal::eink
+{
+
+ class LinuxEinkDisplay : public AbstractEinkDisplay
+ {
+ public:
+ explicit LinuxEinkDisplay(FrameSize size);
+
+ private:
+ void setMode(const EinkDisplayColorMode mode) noexcept override;
+ EinkStatus showImage(std::uint8_t *frameBuffer, const EinkRefreshMode refreshMode) override;
+ void prepareEarlyRequest(const EinkRefreshMode refreshMode, const WaveformTemperature behaviour) override;
+
+ void dither() override;
+ void powerOn() override;
+ void powerOff() override;
+ void shutdown() override;
+ void wipeOut() override;
+ EinkStatus resetAndInit() override;
+ [[nodiscard]] std::shared_ptr<devices::Device> getDevice() const noexcept override;
+
+ FrameSize size;
+ EinkDisplayColorMode displayColorMode{EinkDisplayColorMode::EinkDisplayColorModeStandard};
+ };
+} // namespace hal::eink
M module-bsp/board/rt1051/CMakeLists.txt => module-bsp/board/rt1051/CMakeLists.txt +3 -1
@@ 13,7 13,9 @@ target_sources(module-bsp
bsp/eink_frontlight/eink_frontlight.cpp
bsp/eink/bsp_eink.cpp
bsp/eink/ED028TC1.cpp
+ bsp/eink/EinkDisplay.cpp
bsp/eink/eink_binarization_luts.c
+ bsp/eink/eink_dimensions.cpp
bsp/eMMC/fsl_mmc.c
bsp/eMMC/fsl_sdmmc_common.c
bsp/eMMC/fsl_sdmmc_event.c
@@ 75,7 77,7 @@ add_subdirectory(common/fsl_drivers)
add_subdirectory(os)
add_subdirectory(${BOARD})
-target_link_libraries(module-bsp PUBLIC cmsis fsl)
+target_link_libraries(module-bsp PUBLIC cmsis fsl Microsoft.GSL::GSL)
add_library(system-stats-sink-board)
target_sources(system-stats-sink-board
M module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp => module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp +70 -62
@@ 21,6 21,7 @@
#include "board.h"
#include "eink_binarization_luts.h"
#include "macros.h"
+#include "eink_dimensions.hpp"
#include <magic_enum.hpp>
#include "drivers/pll/DriverPLL.hpp"
@@ 54,22 55,6 @@
#define EPD_BOOSTER_OFF_TIME_GDR_6_58uS 7
#define EPD_BOOSTER_OFF_TIME_GDR_POS 0
-#if defined(EINK_ROTATE_90_CLOCKWISE)
-#define EINK_DISPLAY_RES_X (BOARD_EINK_DISPLAY_RES_Y)
-#define EINK_DISPLAY_RES_Y (BOARD_EINK_DISPLAY_RES_X)
-#define EINK_DISPLAY_X_AXIS (BOARD_EINK_DISPLAY_RES_Y - Y - H)
-#define EINK_DISPLAY_Y_AXIS (BOARD_EINK_DISPLAY_RES_X - X - W)
-#define EINK_DISPLAY_WINDOW_WIDTH (H)
-#define EINK_DISPLAY_WINDOW_HEIGHT (W)
-#else
-#define EINK_DISPLAY_RES_X (BOARD_EINK_DISPLAY_RES_X)
-#define EINK_DISPLAY_RES_Y (BOARD_EINK_DISPLAY_RES_Y)
-#define EINK_DISPLAY_X_AXIS (BOARD_EINK_DISPLAY_RES_X - X - W)
-#define EINK_DISPLAY_Y_AXIS (BOARD_EINK_DISPLAY_RES_Y - Y - H)
-#define EINK_DISPLAY_WINDOW_WIDTH (W)
-#define EINK_DISPLAY_WINDOW_HEIGHT (H)
-#endif
-
#define EINK_BLACK_PIXEL_MASK 0x00 // This is the mask for the black pixel value
#define EINK_1BPP_WHITE_PIXEL_MASK 0x01 // This is the mask for the white pixel in 1bpp mode
#define EINK_2BPP_WHITE_PIXEL_MASK 0x03 // This is the mask for the white pixel in 2bpp mode
@@ 814,8 799,7 @@ EinkStatus_e EinkDitherDisplay()
return EinkOK;
}
-EinkStatus_e EinkUpdateFrame(
- uint16_t X, uint16_t Y, uint16_t W, uint16_t H, uint8_t *buffer, EinkBpp_e bpp, EinkDisplayColorMode_e invertColors)
+EinkStatus_e EinkUpdateFrame(EinkFrame_t frame, uint8_t *buffer, EinkBpp_e bpp, EinkDisplayColorMode_e invertColors)
{
uint8_t buf[10];
uint8_t pixelsInByte = 8 / bpp;
@@ 826,20 810,24 @@ EinkStatus_e EinkUpdateFrame(
if ((s_einkConfiguredWaveform == EinkWaveformA2) || (s_einkConfiguredWaveform == EinkWaveformDU2)) {
switch (bpp) {
case Eink1Bpp: {
- s_EinkTransformAnimationFrameCoordinateSystem_1Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ s_EinkTransformAnimationFrameCoordinateSystem_1Bpp(
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
} break;
case Eink2Bpp: {
- s_EinkTransformAnimationFrameCoordinateSystem_2Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ s_EinkTransformAnimationFrameCoordinateSystem_2Bpp(
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
} break;
case Eink3Bpp: {
- s_EinkTransformAnimationFrameCoordinateSystem_3Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ s_EinkTransformAnimationFrameCoordinateSystem_3Bpp(
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
} break;
case Eink4Bpp: {
#if defined(EINK_ROTATE_90_CLOCKWISE)
- s_EinkTransformFrameCoordinateSystem_4Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ s_EinkTransformFrameCoordinateSystem_4Bpp(
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
#else
s_EinkTransformFrameCoordinateSystemNoRotation_4Bpp(
- buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
#endif
} break;
}
@@ 847,49 835,61 @@ EinkStatus_e EinkUpdateFrame(
else {
switch (bpp) {
case Eink1Bpp: {
- s_EinkTransformFrameCoordinateSystem_1Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ s_EinkTransformFrameCoordinateSystem_1Bpp(
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
} break;
case Eink2Bpp: {
- s_EinkTransformFrameCoordinateSystem_2Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ s_EinkTransformFrameCoordinateSystem_2Bpp(
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
} break;
case Eink3Bpp: {
- s_EinkTransformFrameCoordinateSystem_3Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ s_EinkTransformFrameCoordinateSystem_3Bpp(
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
} break;
case Eink4Bpp: {
#if defined(EINK_ROTATE_90_CLOCKWISE)
- s_EinkTransformFrameCoordinateSystem_4Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ s_EinkTransformFrameCoordinateSystem_4Bpp(
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
#else
s_EinkTransformFrameCoordinateSystemNoRotation_4Bpp(
- buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors);
+ buffer, frame.width, frame.height, s_einkServiceRotatedBuf + 2, invertColors);
#endif
} break;
}
}
buf[0] = EinkDataStartTransmissionWindow; // set display window
- buf[1] = (uint8_t)(EINK_DISPLAY_X_AXIS >> 8); // MSB of the X axis in the EPD display. Value converted
- // from the standard GUI coords system to the ED028TC1 one
- buf[2] = (uint8_t)EINK_DISPLAY_X_AXIS; // LSB of the X axis in the EPD display. Value converted from
- // the standard GUI coords system to the ED028TC1 one
- buf[3] = (uint8_t)(EINK_DISPLAY_Y_AXIS >> 8); // MSB of the Y axis in the EPD display. Value converted
- // from the standard GUI coords system to the ED028TC1 one
- buf[4] = (uint8_t)EINK_DISPLAY_Y_AXIS; // LSB of the Y axis in the EPD display. Value converted from
- // the standard GUI coords system to the ED028TC1 one
- buf[5] = (uint8_t)(EINK_DISPLAY_WINDOW_WIDTH >> 8); // MSB of the window height in the EPD display. Value converted
- // from the standard GUI coords system to the ED028TC1 one
- buf[6] = (uint8_t)EINK_DISPLAY_WINDOW_WIDTH; // LSB of the window height in the EPD display. Value converted from
- // the standard GUI coords system to the ED028TC1 one
- buf[7] = (uint8_t)(EINK_DISPLAY_WINDOW_HEIGHT >> 8); // MSB of the window width in the EPD display. Value converted
- // from the standard GUI coords system to the ED028TC1 one
- buf[8] = (uint8_t)EINK_DISPLAY_WINDOW_HEIGHT; // LSB of the window width in the EPD display. Value converted from
+ buf[1] = static_cast<uint8_t>(hal::eink::getDisplayXAxis(frame) >>
+ 8); // MSB of the X axis in the EPD display. Value converted
+ // from the standard GUI coords system to the ED028TC1 one
+ buf[2] = static_cast<uint8_t>(
+ hal::eink::getDisplayXAxis(frame)); // LSB of the X axis in the EPD display. Value converted from
+ // the standard GUI coords system to the ED028TC1 one
+ buf[3] = static_cast<uint8_t>(hal::eink::getDisplayYAxis(frame) >>
+ 8); // MSB of the Y axis in the EPD display. Value converted
+ // from the standard GUI coords system to the ED028TC1 one
+ buf[4] = static_cast<uint8_t>(
+ hal::eink::getDisplayYAxis(frame)); // LSB of the Y axis in the EPD display. Value converted from
+ // the standard GUI coords system to the ED028TC1 one
+ buf[5] = static_cast<uint8_t>(hal::eink::getDisplayWindowWidth(frame) >>
+ 8); // MSB of the window height in the EPD display. Value converted
+ // from the standard GUI coords system to the ED028TC1 one
+ buf[6] = static_cast<uint8_t>(
+ hal::eink::getDisplayWindowWidth(frame)); // LSB of the window height in the EPD display. Value converted from
// the standard GUI coords system to the ED028TC1 one
+ buf[7] = static_cast<uint8_t>(hal::eink::getDisplayWindowHeight(frame) >>
+ 8); // MSB of the window width in the EPD display. Value converted
+ // from the standard GUI coords system to the ED028TC1 one
+ buf[8] = static_cast<uint8_t>(
+ hal::eink::getDisplayWindowHeight(frame)); // LSB of the window width in the EPD display. Value converted from
+ // the standard GUI coords system to the ED028TC1 one
if (BSP_EinkWriteData(buf, 9, SPI_AUTOMATIC_CS) != 0) {
EinkResetAndInitialize();
return EinkSPIErr;
}
- uint32_t msgSize = 2 + ((uint32_t)W * (uint32_t)H /
+ uint32_t msgSize = 2 + (static_cast<uint32_t>(frame.width) * static_cast<uint32_t>(frame.height) /
pixelsInByte); // command (1 byte) + bpp (1 byte) + dataSize(W*H/pixelsInByte bytes)
// Send the part of the image to the display memory
@@ 952,13 952,13 @@ EinkStatus_e EinkFillScreenWithColor(EinkDisplayColorFilling_e colorFill)
BSP_EinkWriteCS(BSP_Eink_CS_Set);
- EinkRefreshImage(0, 0, BOARD_EINK_DISPLAY_RES_X, BOARD_EINK_DISPLAY_RES_Y, EinkDisplayTimingsDeepCleanMode);
+ EinkRefreshImage(EinkFrame_t{0, 0, BOARD_EINK_DISPLAY_RES_X, BOARD_EINK_DISPLAY_RES_Y},
+ EinkDisplayTimingsDeepCleanMode);
return EinkOK;
}
-EinkStatus_e EinkRefreshImage(
- uint16_t X, uint16_t Y, uint16_t W, uint16_t H, EinkDisplayTimingsMode_e refreshTimingsMode)
+EinkStatus_e EinkRefreshImage(EinkFrame_t frame, EinkDisplayTimingsMode_e refreshTimingsMode)
{
EinkChangeDisplayUpdateTimings(refreshTimingsMode);
@@ 969,22 969,30 @@ EinkStatus_e EinkRefreshImage(
buf[0] = EinkDisplayRefresh;
buf[1] = UPD_CPY_TO_PRE;
- buf[2] = (uint8_t)(EINK_DISPLAY_X_AXIS >> 8); // MSB of the X axis in the EPD display. Value converted
- // from the standard GUI coords system to the ED028TC1 one
- buf[3] = (uint8_t)EINK_DISPLAY_X_AXIS; // LSB of the X axis in the EPD display. Value converted from
- // the standard GUI coords system to the ED028TC1 one
- buf[4] = (uint8_t)(EINK_DISPLAY_Y_AXIS >> 8); // MSB of the Y axis in the EPD display. Value converted
- // from the standard GUI coords system to the ED028TC1 one
- buf[5] = (uint8_t)EINK_DISPLAY_Y_AXIS; // LSB of the Y axis in the EPD display. Value converted from
- // the standard GUI coords system to the ED028TC1 one
- buf[6] = (uint8_t)(EINK_DISPLAY_WINDOW_WIDTH >> 8); // MSB of the window height in the EPD display. Value converted
- // from the standard GUI coords system to the ED028TC1 one
- buf[7] = (uint8_t)EINK_DISPLAY_WINDOW_WIDTH; // LSB of the window height in the EPD display. Value converted from
- // the standard GUI coords system to the ED028TC1 one
- buf[8] = (uint8_t)(EINK_DISPLAY_WINDOW_HEIGHT >> 8); // MSB of the window width in the EPD display. Value converted
- // from the standard GUI coords system to the ED028TC1 one
- buf[9] = (uint8_t)EINK_DISPLAY_WINDOW_HEIGHT; // LSB of the window width in the EPD display. Value converted from
+ buf[2] = static_cast<uint8_t>(hal::eink::getDisplayXAxis(frame) >>
+ 8); // MSB of the X axis in the EPD display. Value converted
+ // from the standard GUI coords system to the ED028TC1 one
+ buf[3] = static_cast<uint8_t>(
+ hal::eink::getDisplayXAxis(frame)); // LSB of the X axis in the EPD display. Value converted from
+ // the standard GUI coords system to the ED028TC1 one
+ buf[4] = static_cast<uint8_t>(hal::eink::getDisplayYAxis(frame) >>
+ 8); // MSB of the Y axis in the EPD display. Value converted
+ // from the standard GUI coords system to the ED028TC1 one
+ buf[5] = static_cast<uint8_t>(
+ hal::eink::getDisplayYAxis(frame)); // LSB of the Y axis in the EPD display. Value converted from
+ // the standard GUI coords system to the ED028TC1 one
+ buf[6] = static_cast<uint8_t>(hal::eink::getDisplayWindowWidth(frame) >>
+ 8); // MSB of the window height in the EPD display. Value converted
+ // from the standard GUI coords system to the ED028TC1 one
+ buf[7] = static_cast<uint8_t>(
+ hal::eink::getDisplayWindowWidth(frame)); // LSB of the window height in the EPD display. Value converted from
// the standard GUI coords system to the ED028TC1 one
+ buf[8] = static_cast<uint8_t>(hal::eink::getDisplayWindowHeight(frame) >>
+ 8); // MSB of the window width in the EPD display. Value converted
+ // from the standard GUI coords system to the ED028TC1 one
+ buf[9] = static_cast<uint8_t>(
+ hal::eink::getDisplayWindowHeight(frame)); // LSB of the window width in the EPD display. Value converted from
+ // the standard GUI coords system to the ED028TC1 one
if (BSP_EinkWriteData(buf, sizeof(buf), SPI_AUTOMATIC_CS) != 0) {
EinkResetAndInitialize();
M module-bsp/board/rt1051/bsp/eink/ED028TC1.h => module-bsp/board/rt1051/bsp/eink/ED028TC1.h +13 -15
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
/**
@@ 312,6 312,14 @@ extern "C"
uint32_t LUTDSize;
} EinkWaveformSettings_t;
+ typedef struct
+ {
+ uint16_t pos_x;
+ uint16_t pos_y;
+ uint16_t width;
+ uint16_t height;
+ } EinkFrame_t;
+
/* Exported constants --------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
@@ 365,10 373,7 @@ extern "C"
/**
* @brief This function sends the part of image from the given buffer to the internal memory of the display. It
* makes not screen to update.
- * @param X [in] - image start position X in pixels
- * @param Y [in] - image start position Y in pixels
- * @param W [in] - image width in pixels
- * @param H [in] - image height in pixels
+ * @param frame [in] - part of screen on which the image will be written
* @param buffer [in] - pointer to image encoded according to \ref bpp set in initialization
* @param bpp [in] - The format of the \ref buffer (number of the bits per pixel)
* @param invertColors[in] - true if colors of the image are to be inverted, false otherwise
@@ 376,10 381,7 @@ extern "C"
* @return EinkNoMem - Could not allocate the temporary buffer
* EinkOK - Part of image send successfully
*/
- EinkStatus_e EinkUpdateFrame(uint16_t X,
- uint16_t Y,
- uint16_t W,
- uint16_t H,
+ EinkStatus_e EinkUpdateFrame(EinkFrame_t frame,
uint8_t *buffer,
EinkBpp_e bpp,
EinkDisplayColorMode_e invertColors);
@@ 403,18 405,14 @@ extern "C"
/**
* @brief Refresh window on the screen. E-paper display tends to loose contrast over time. To Keep the image sharp
* refresh is needed.
- * @param X refresh window position X in pixels
- * @param Y refresh window position Y in pixels
- * @param W refresh window width in pixels
- * @param H refresh window height in pixels
+ * @param frame - part of screen on which image will be written
* @param refreshTimingsMode [in] - EinkDisplayTimingsDeepCleanMode - if image is to be cleared precisely
* EinkDisplayTimingsHighContrastMode - if image is displayed in the high contrast
* mode EinkDisplayTimingsFastRefreshMode - if image is to be displayed fast
*
* @return EinkOK
*/
- EinkStatus_e EinkRefreshImage(
- uint16_t X, uint16_t Y, uint16_t W, uint16_t H, EinkDisplayTimingsMode_e refreshTimingsMode);
+ EinkStatus_e EinkRefreshImage(EinkFrame_t frame, EinkDisplayTimingsMode_e refreshTimingsMode);
/**
* @brief This function sends the proper waveform consisting from the LUTC and LUTD data,
R module-services/service-eink/EinkDisplay.cpp => module-bsp/board/rt1051/bsp/eink/EinkDisplay.cpp +145 -75
@@ 3,17 3,16 @@
#include "EinkDisplay.hpp"
-#if defined(TARGET_RT1051)
#include <board/BoardDefinitions.hpp>
-#endif
#include <log/log.hpp>
-#include <gui/core/Color.hpp>
+
#include <gsl/util>
+#include <stdexcept>
#include <cstdio>
#include <cstring>
-namespace service::eink
+namespace hal::eink
{
namespace
{
@@ 44,10 43,81 @@ namespace service::eink
settings.LUTDSize = 0;
return settings;
}
+
+ unsigned int toWaveformTemperatureOffset(std::int32_t temperature) noexcept
+ {
+ if (temperature >= LUTTemperatureCritical) {
+ return LUTTemperatureOffsetCritical;
+ }
+ if (temperature >= LUTTemperatureSubcritical) {
+ return LUTTemperatureOffsetSubcritical;
+ }
+ if (temperature < LUTTemperatureMinimal) {
+ temperature = LUTTemperatureMinimal;
+ }
+ return temperature / LUTTemperatureOffsetInterval;
+ }
+
+ unsigned int toWaveformOffset(unsigned short LUTbank, unsigned int temperatureOffset) noexcept
+ {
+ constexpr auto singleLUTOffset = (LUTTemperatureOffsetCritical + 1);
+ return LUTSTotalSize * (singleLUTOffset * LUTbank + temperatureOffset);
+ }
+
+ unsigned int toWaveformOffset(EinkWaveforms_e mode, unsigned int temperatureOffset)
+ {
+ switch (mode) {
+ case EinkWaveformINIT:
+ return toWaveformOffset(0, temperatureOffset);
+ case EinkWaveformA2:
+ return toWaveformOffset(1, temperatureOffset);
+ case EinkWaveformDU2:
+ return toWaveformOffset(2, temperatureOffset);
+ case EinkWaveformGLD16:
+ return toWaveformOffset(3, temperatureOffset);
+ case EinkWaveformGC16:
+ return toWaveformOffset(4, temperatureOffset);
+ default:
+ throw std::invalid_argument{"Invalid waveform mode."};
+ }
+ }
} // namespace
- EinkDisplay::EinkDisplay(::gui::Size screenSize)
- : size{screenSize}, currentWaveform{createDefaultWaveFormSettings(EinkWaveformGC16)},
+ EinkDisplayColorMode_e translateDisplayColorMode(const EinkDisplayColorMode mode)
+ {
+ return mode == EinkDisplayColorMode::EinkDisplayColorModeStandard
+ ? EinkDisplayColorMode_e::EinkDisplayColorModeStandard
+ : EinkDisplayColorMode_e::EinkDisplayColorModeInverted;
+ }
+
+ EinkStatus translateStatus(const EinkStatus_e status_e)
+ {
+ switch (status_e) {
+ case EinkOK:
+ return EinkStatus::EinkOK;
+ case EinkError:
+ return EinkStatus::EinkError;
+ case EinkSPIErr:
+ return EinkStatus::EinkSPIErr;
+ case EinkSPINotInitializedErr:
+ return EinkStatus::EinkSPINotInitializedErr;
+ case EinkDMAErr:
+ return EinkStatus::EinkDMAErr;
+ case EinkInitErr:
+ return EinkStatus::EinkInitErr;
+ case EinkTimeout:
+ return EinkStatus::EinkTimeout;
+ case EinkNoMem:
+ return EinkStatus::EinkNoMem;
+ case EinkWaveformsFileOpenFail:
+ return EinkStatus::EinkWaveformsFileOpenFail;
+ default:
+ return EinkStatus::EinkUnknown;
+ }
+ }
+
+ EinkDisplay::EinkDisplay(FrameSize size)
+ : size{size}, currentWaveform{createDefaultWaveFormSettings(EinkWaveformGC16)},
displayMode{EinkDisplayColorMode_e::EinkDisplayColorModeStandard}
{
#if defined(TARGET_RT1051)
@@ 62,9 132,59 @@ namespace service::eink
delete[] currentWaveform.LUTDData;
}
- EinkStatus_e EinkDisplay::resetAndInit()
+ EinkStatus EinkDisplay::updateDisplay(std::uint8_t *frameBuffer, [[maybe_unused]] const EinkRefreshMode refreshMode)
+ {
+ return update(frameBuffer);
+ }
+
+ EinkStatus EinkDisplay::refreshDisplay(const EinkRefreshMode refreshMode)
+ {
+ const auto isDeepRefresh = refreshMode == EinkRefreshMode::REFRESH_DEEP;
+ return refresh(isDeepRefresh ? EinkDisplayTimingsDeepCleanMode : EinkDisplayTimingsFastRefreshMode);
+ }
+
+ EinkStatus EinkDisplay::prepareDisplay(const EinkRefreshMode refreshMode, const WaveformTemperature behaviour)
{
- return EinkResetAndInitialize();
+ powerOn();
+
+ const auto temperature =
+ behaviour == WaveformTemperature::KEEP_CURRENT ? getLastTemperature() : EinkGetTemperatureInternal();
+
+ if (refreshMode == EinkRefreshMode::REFRESH_DEEP) {
+ auto status = setWaveform(EinkWaveforms_e::EinkWaveformGC16, temperature);
+ if (status == EinkStatus::EinkOK) {
+ dither();
+ }
+ return status;
+ }
+ return setWaveform(EinkWaveforms_e::EinkWaveformDU2, temperature);
+ }
+
+ EinkStatus EinkDisplay::showImage(std::uint8_t *frameBuffer, const EinkRefreshMode refreshMode)
+ {
+ if (const auto status = prepareDisplay(refreshMode, WaveformTemperature::KEEP_CURRENT);
+ status != EinkStatus::EinkOK) {
+ return status;
+ }
+
+ if (const auto status = updateDisplay(frameBuffer, refreshMode); status != EinkStatus::EinkOK) {
+ return status;
+ }
+
+ if (const auto status = refreshDisplay(refreshMode); status != EinkStatus::EinkOK) {
+ return status;
+ }
+ return EinkStatus::EinkOK;
+ }
+
+ void EinkDisplay::prepareEarlyRequest(const EinkRefreshMode refreshMode, const WaveformTemperature behaviour)
+ {
+ prepareDisplay(refreshMode, behaviour);
+ }
+
+ EinkStatus EinkDisplay::resetAndInit()
+ {
+ return translateStatus(EinkResetAndInitialize());
}
void EinkDisplay::dither()
@@ 77,9 197,6 @@ namespace service::eink
if (driverLPSPI) {
driverLPSPI->Enable();
}
- if (eInkSentinel) {
- eInkSentinel->HoldMinimumFrequency();
- }
EinkPowerOn();
}
@@ 89,9 206,6 @@ namespace service::eink
if (driverLPSPI) {
driverLPSPI->Disable();
}
- if (eInkSentinel) {
- eInkSentinel->ReleaseMinimumFrequency();
- }
}
void EinkDisplay::shutdown()
@@ 104,15 218,12 @@ namespace service::eink
EinkFillScreenWithColor(EinkDisplayColorFilling_e::EinkDisplayColorWhite);
}
- EinkStatus_e EinkDisplay::update(std::uint8_t *displayBuffer)
+ EinkStatus EinkDisplay::update(std::uint8_t *displayBuffer)
{
- return EinkUpdateFrame(pointTopLeft.x,
- pointTopLeft.y,
- size.width,
- size.height,
- displayBuffer,
- getCurrentBitsPerPixelFormat(),
- displayMode);
+ return translateStatus(EinkUpdateFrame(EinkFrame_t{0, 0, size.width, size.height},
+ displayBuffer,
+ getCurrentBitsPerPixelFormat(),
+ translateDisplayColorMode(displayMode)));
}
EinkBpp_e EinkDisplay::getCurrentBitsPerPixelFormat() const noexcept
@@ 123,13 234,13 @@ namespace service::eink
return Eink4Bpp;
}
- EinkStatus_e EinkDisplay::refresh(EinkDisplayTimingsMode_e refreshMode)
+ EinkStatus EinkDisplay::refresh(const EinkDisplayTimingsMode_e refreshMode)
{
currentWaveform.useCounter += 1;
- return EinkRefreshImage(pointTopLeft.x, pointTopLeft.y, size.width, size.height, refreshMode);
+ return translateStatus(EinkRefreshImage(EinkFrame_t{0, 0, size.width, size.height}, refreshMode));
}
- bool EinkDisplay::isNewWaveformNeeded(EinkWaveforms_e newMode, std::int32_t newTemperature) const
+ bool EinkDisplay::isNewWaveformNeeded(const EinkWaveforms_e newMode, const std::int32_t newTemperature) const
{
constexpr auto lenientTemperatureUseCounter = 50; // arbitrary. not documented
auto alloweLenientTemperature = currentWaveform.useCounter < lenientTemperatureUseCounter;
@@ 160,10 271,10 @@ namespace service::eink
return true;
}
- EinkStatus_e EinkDisplay::setWaveform(EinkWaveforms_e mode, std::int32_t temperature)
+ EinkStatus EinkDisplay::setWaveform(const EinkWaveforms_e mode, const std::int32_t temperature)
{
if (!isNewWaveformNeeded(mode, temperature)) {
- return EinkOK;
+ return EinkStatus::EinkOK;
}
auto currentOffset =
@@ 177,13 288,13 @@ namespace service::eink
if (offset == currentOffset) {
// current waveform is still the best fit
- return EinkOK;
+ return EinkStatus::EinkOK;
}
auto file = std::fopen(LutsFileName, "rb");
if (file == nullptr) {
LOG_FATAL("Could not find the LUTS.bin file. Returning");
- return EinkWaveformsFileOpenFail;
+ return EinkStatus::EinkWaveformsFileOpenFail;
}
auto fileHandlerCleanup = gsl::finally([&file]() { std::fclose(file); });
@@ 201,43 312,7 @@ namespace service::eink
std::fread(¤tWaveform.LUTCData[1], 1, LUTCSize, file);
EinkUpdateWaveform(¤tWaveform);
- return EinkOK;
- }
-
- unsigned int EinkDisplay::toWaveformTemperatureOffset(std::int32_t temperature) noexcept
- {
- if (temperature >= LUTTemperatureCritical)
- return LUTTemperatureOffsetCritical;
- if (temperature >= LUTTemperatureSubcritical)
- return LUTTemperatureOffsetSubcritical;
- if (temperature < LUTTemperatureMinimal) {
- temperature = LUTTemperatureMinimal;
- }
- return temperature / LUTTemperatureOffsetInterval;
- }
-
- unsigned int EinkDisplay::toWaveformOffset(unsigned short LUTbank, unsigned int temperatureOffset) noexcept
- {
- constexpr auto singleLUTOffset = (LUTTemperatureOffsetCritical + 1);
- return LUTSTotalSize * (singleLUTOffset * LUTbank + temperatureOffset);
- }
-
- unsigned int EinkDisplay::toWaveformOffset(EinkWaveforms_e mode, unsigned int temperatureOffset)
- {
- switch (mode) {
- case EinkWaveformINIT:
- return toWaveformOffset(0, temperatureOffset);
- case EinkWaveformA2:
- return toWaveformOffset(1, temperatureOffset);
- case EinkWaveformDU2:
- return toWaveformOffset(2, temperatureOffset);
- case EinkWaveformGLD16:
- return toWaveformOffset(3, temperatureOffset);
- case EinkWaveformGC16:
- return toWaveformOffset(4, temperatureOffset);
- default:
- throw std::invalid_argument{"Invalid waveform mode."};
- }
+ return EinkStatus::EinkOK;
}
void EinkDisplay::resetWaveformSettings()
@@ 253,7 328,7 @@ namespace service::eink
currentWaveform.LUTCData[0] = EinkLUTC;
}
- void EinkDisplay::setMode(EinkDisplayColorMode_e mode) noexcept
+ void EinkDisplay::setMode(const EinkDisplayColorMode mode) noexcept
{
displayMode = mode;
}
@@ 263,19 338,14 @@ namespace service::eink
return currentWaveform.temperature;
}
- ::gui::Size EinkDisplay::getSize() const noexcept
- {
- return size;
- }
-
[[nodiscard]] auto EinkDisplay::getDevice() const noexcept -> std::shared_ptr<devices::Device>
{
return driverLPSPI;
}
- void EinkDisplay::setEinkSentinel(std::shared_ptr<EinkSentinel> sentinel)
+ std::unique_ptr<AbstractEinkDisplay> AbstractEinkDisplay::Factory::create(FrameSize size)
{
- eInkSentinel = std::move(sentinel);
+ return std::make_unique<EinkDisplay>(size);
}
-} // namespace service::eink
+} // namespace hal::eink
A module-bsp/board/rt1051/bsp/eink/EinkDisplay.hpp => module-bsp/board/rt1051/bsp/eink/EinkDisplay.hpp +65 -0
@@ 0,0 1,65 @@
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include <hal/eink/AbstractEinkDisplay.hpp>
+
+#include "drivers/lpspi/DriverLPSPI.hpp"
+#include "ED028TC1.h"
+
+namespace hal::eink
+{
+ /**
+ * Specifies the Eink display.
+ * Responsible for handling low-level Eink display operations, e.g. switching power modes, updating, refreshing,
+ * etc.
+ */
+ class EinkDisplay : public AbstractEinkDisplay
+ {
+ public:
+ EinkDisplay(FrameSize size);
+
+ ~EinkDisplay() noexcept;
+
+ void setMode(EinkDisplayColorMode mode) noexcept override;
+ EinkStatus showImage(std::uint8_t *frameBuffer, const EinkRefreshMode refreshMode) override;
+ void prepareEarlyRequest(EinkRefreshMode refreshMode, const WaveformTemperature behaviour) override;
+
+ EinkStatus resetAndInit() override;
+ void dither() override;
+ void powerOn() override;
+ void powerOff() override;
+ void shutdown() override;
+ void wipeOut() override;
+
+ [[nodiscard]] auto getDevice() const noexcept -> std::shared_ptr<devices::Device> override;
+
+ private:
+ bool isNewWaveformNeeded(const EinkWaveforms_e newMode, const int32_t newTemperature) const;
+ void resetWaveformSettings();
+
+ EinkBpp_e getCurrentBitsPerPixelFormat() const noexcept;
+
+ EinkStatus setWaveform(const EinkWaveforms_e mode, const std::int32_t temperature);
+
+ std::int32_t getLastTemperature() const noexcept;
+
+ EinkStatus update(std::uint8_t *displayBuffer);
+ EinkStatus refresh(const EinkDisplayTimingsMode_e refreshMode);
+
+ EinkStatus updateDisplay(std::uint8_t *frameBuffer, const EinkRefreshMode refreshMode);
+ EinkStatus refreshDisplay(const EinkRefreshMode refreshMode);
+ EinkStatus prepareDisplay(const EinkRefreshMode refreshMode, const WaveformTemperature behaviour);
+
+ FrameSize size;
+
+ EinkWaveformSettings_t currentWaveform;
+ EinkDisplayColorMode displayMode;
+
+ std::shared_ptr<drivers::DriverLPSPI> driverLPSPI;
+ };
+} // namespace hal::eink
A module-bsp/board/rt1051/bsp/eink/eink_dimensions.cpp => module-bsp/board/rt1051/bsp/eink/eink_dimensions.cpp +47 -0
@@ 0,0 1,47 @@
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "eink_dimensions.hpp"
+
+#include <eink-config.h>
+
+namespace hal::eink
+{
+
+ std::uint32_t getDisplayXAxis(EinkFrame_t frame)
+ {
+#if defined(EINK_ROTATE_90_CLOCKWISE)
+ return BOARD_EINK_DISPLAY_RES_Y - frame.pos_y - frame.height;
+#else
+ return BOARD_EINK_DISPLAY_RES_X - frame.pos_x - frame.width;
+#endif
+ }
+
+ std::uint32_t getDisplayYAxis(EinkFrame_t frame)
+ {
+#if defined(EINK_ROTATE_90_CLOCKWISE)
+ return BOARD_EINK_DISPLAY_RES_X - frame.pos_x - frame.width;
+#else
+ return BOARD_EINK_DISPLAY_RES_Y - frame.pos_y - frame.height;
+#endif
+ }
+
+ std::uint32_t getDisplayWindowWidth(EinkFrame_t frame)
+ {
+#if defined(EINK_ROTATE_90_CLOCKWISE)
+ return frame.height;
+#else
+ return frame.width;
+#endif
+ }
+
+ std::uint32_t getDisplayWindowHeight(EinkFrame_t frame)
+ {
+#if defined(EINK_ROTATE_90_CLOCKWISE)
+ return frame.width;
+#else
+ return frame.height;
+#endif
+ }
+
+} // namespace hal::eink
A module-bsp/board/rt1051/bsp/eink/eink_dimensions.hpp => module-bsp/board/rt1051/bsp/eink/eink_dimensions.hpp +25 -0
@@ 0,0 1,25 @@
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <cstdint>
+
+#include <eink-config.h>
+#include "ED028TC1.h"
+
+#if defined(EINK_ROTATE_90_CLOCKWISE)
+#define EINK_DISPLAY_RES_X (BOARD_EINK_DISPLAY_RES_Y)
+#define EINK_DISPLAY_RES_Y (BOARD_EINK_DISPLAY_RES_X)
+#else
+#define EINK_DISPLAY_RES_X (BOARD_EINK_DISPLAY_RES_X)
+#define EINK_DISPLAY_RES_Y (BOARD_EINK_DISPLAY_RES_Y)
+#endif
+
+namespace hal::eink
+{
+ std::uint32_t getDisplayXAxis(EinkFrame_t frame);
+ std::uint32_t getDisplayYAxis(EinkFrame_t frame);
+ std::uint32_t getDisplayWindowWidth(EinkFrame_t frame);
+ std::uint32_t getDisplayWindowHeight(EinkFrame_t frame);
+} // namespace hal::eink
M module-bsp/hal/CMakeLists.txt => module-bsp/hal/CMakeLists.txt +1 -0
@@ 11,6 11,7 @@ target_sources(hal
include/hal/GenericFactory.hpp
include/hal/battery_charger/AbstractBatteryCharger.hpp
include/hal/cellular/SIM.hpp
+ include/hal/eink/AbstractEinkDisplay.hpp
include/hal/key_input/RawKey.hpp
include/hal/key_input/KeyEventDefinitions.hpp
include/hal/key_input/AbstractKeyInput.hpp
A module-bsp/hal/include/hal/eink/AbstractEinkDisplay.hpp => module-bsp/hal/include/hal/eink/AbstractEinkDisplay.hpp +80 -0
@@ 0,0 1,80 @@
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <memory>
+
+#include <devices/Device.hpp>
+
+namespace hal::eink
+{
+
+ enum class EinkDisplayColorMode
+ {
+ EinkDisplayColorModeStandard,
+ EinkDisplayColorModeInverted
+ };
+
+ enum class WaveformTemperature
+ {
+ KEEP_CURRENT,
+ MEASURE_NEW,
+ };
+
+ enum class EinkRefreshMode
+ {
+ REFRESH_NONE,
+ REFRESH_FAST = 1,
+ REFRESH_DEEP
+ };
+
+ enum class EinkStatus
+ {
+ EinkOK, //!< EinkOK
+ EinkError,
+ EinkSPIErr, //!< EinkSPIErr
+ EinkSPINotInitializedErr, //!< EinkSPINotInitializedErr
+ EinkDMAErr, //!< EinkDMAErr
+ EinkInitErr, //!< EinkInitErr
+ EinkTimeout, //!< Timeout occured while waiting for not busy signal from EINK
+ EinkNoMem, //!< Could not allocate memory
+ EinkWaveformsFileOpenFail, //!< Could not open the file with the waveforms for EPD display
+
+ EinkUnknown,
+ };
+
+ struct FrameSize
+ {
+ uint16_t width;
+ uint16_t height;
+ };
+
+ struct EinkFrame
+ {
+ uint16_t pos_x;
+ uint16_t pos_y;
+ FrameSize size;
+ };
+
+ class AbstractEinkDisplay
+ {
+ public:
+ struct Factory
+ {
+ static std::unique_ptr<AbstractEinkDisplay> create(FrameSize size);
+ };
+
+ virtual ~AbstractEinkDisplay() = default;
+
+ virtual void setMode(const EinkDisplayColorMode mode) noexcept = 0;
+ virtual EinkStatus showImage(std::uint8_t *frameBuffer, const EinkRefreshMode refreshMode) = 0;
+ virtual void prepareEarlyRequest(EinkRefreshMode refreshMode, const WaveformTemperature behaviour) = 0;
+
+ virtual void dither() = 0;
+ virtual void powerOn() = 0;
+ virtual void powerOff() = 0;
+ virtual void shutdown() = 0;
+ virtual void wipeOut() = 0;
+ virtual EinkStatus resetAndInit() = 0;
+ virtual std::shared_ptr<devices::Device> getDevice() const noexcept = 0;
+ };
+} // namespace hal::eink
M module-gui/CMakeLists.txt => module-gui/CMakeLists.txt +1 -0
@@ 27,6 27,7 @@ target_link_libraries(${PROJECT_NAME}
json::json
pugixml::pugixml
utils-time
+ Microsoft.GSL::GSL
)
# Board specific compilation definitions,options,include directories and features
M module-services/service-cellular/call/CMakeLists.txt => module-services/service-cellular/call/CMakeLists.txt +1 -0
@@ 25,6 25,7 @@ target_include_directories(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME}
PRIVATE
+ Microsoft.GSL::GSL
module-sys
sml::utils::logger
PUBLIC
M module-services/service-eink/CMakeLists.txt => module-services/service-eink/CMakeLists.txt +4 -3
@@ 3,7 3,6 @@ message( "${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}" )
set(SOURCES
ServiceEink.cpp
- EinkDisplay.cpp
api/ServiceEinkApi.cpp
internal/StaticData.cpp
messages/ImageMessage.cpp
@@ 14,11 13,13 @@ add_library(${PROJECT_NAME} STATIC ${SOURCES})
add_board_subdirectory(board)
target_link_libraries( ${PROJECT_NAME}
- module-utils
+ PUBLIC
module-bsp
- Microsoft.GSL::GSL
messagetype
module-sys
+ PRIVATE
+ Microsoft.GSL::GSL
+ module-utils
)
target_include_directories(${PROJECT_NAME}
D module-services/service-eink/EinkDisplay.hpp => module-services/service-eink/EinkDisplay.hpp +0 -62
@@ 1,62 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 <EinkIncludes.hpp>
-#include <gui/Common.hpp>
-#include "Common.hpp"
-
-#include <cstdint>
-#include <memory>
-#include "drivers/lpspi/DriverLPSPI.hpp"
-#include "EinkSentinel.hpp"
-
-namespace service::eink
-{
- /**
- * Specifies the Eink display.
- * Responsible for handling low-level Eink display operations, e.g. switching power modes, updating, refreshing,
- * etc.
- */
- class EinkDisplay
- {
- public:
- explicit EinkDisplay(::gui::Size screenSize);
- ~EinkDisplay() noexcept;
-
- EinkStatus_e resetAndInit();
- EinkStatus_e update(std::uint8_t *displayBuffer);
- EinkStatus_e refresh(EinkDisplayTimingsMode_e refreshMode);
- void dither();
- void powerOn();
- void powerOff();
- void shutdown();
- void wipeOut();
-
- EinkStatus_e setWaveform(EinkWaveforms_e mode, std::int32_t temperature);
- void setMode(EinkDisplayColorMode_e mode) noexcept;
-
- std::int32_t getLastTemperature() const noexcept;
- ::gui::Size getSize() const noexcept;
-
- [[nodiscard]] auto getDevice() const noexcept -> std::shared_ptr<devices::Device>;
- void setEinkSentinel(std::shared_ptr<EinkSentinel> sentinel);
-
- private:
- static unsigned int toWaveformTemperatureOffset(std::int32_t temperature) noexcept;
- static unsigned int toWaveformOffset(unsigned short LUTbank, unsigned int temperatureOffset) noexcept;
- static unsigned int toWaveformOffset(EinkWaveforms_e mode, unsigned int temperatureOffset);
- bool isNewWaveformNeeded(EinkWaveforms_e newMode, int32_t newTemperature) const;
- void resetWaveformSettings();
-
- EinkBpp_e getCurrentBitsPerPixelFormat() const noexcept;
- static constexpr ::gui::Point pointTopLeft{0, 0};
- const ::gui::Size size;
- EinkWaveformSettings_t currentWaveform;
- EinkDisplayColorMode_e displayMode;
-
- std::shared_ptr<drivers::DriverLPSPI> driverLPSPI;
- std::shared_ptr<EinkSentinel> eInkSentinel;
- };
-} // namespace service::eink
M module-services/service-eink/ServiceEink.cpp => module-services/service-eink/ServiceEink.cpp +42 -72
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <board.h>
@@ 29,22 29,38 @@ namespace service::eink
constexpr auto ServceEinkStackDepth = 4096U;
constexpr std::chrono::milliseconds displayPowerOffTimeout{2000};
- std::string toSettingString(EinkModeMessage::Mode mode)
+ std::string toSettingString(const EinkModeMessage::Mode mode)
{
if (mode == EinkModeMessage::Mode::Normal) {
return "0";
}
return "1";
}
+
+ hal::eink::EinkRefreshMode translateToEinkRefreshMode(const gui::RefreshModes guiRefreshMode)
+ {
+ switch (guiRefreshMode) {
+ case gui::RefreshModes::GUI_REFRESH_DEEP:
+ return hal::eink::EinkRefreshMode::REFRESH_DEEP;
+ case gui::RefreshModes::GUI_REFRESH_FAST:
+ return hal::eink::EinkRefreshMode::REFRESH_FAST;
+ default:
+ return hal::eink::EinkRefreshMode::REFRESH_NONE;
+ }
+ }
} // namespace
ServiceEink::ServiceEink(ExitAction exitAction, const std::string &name, std::string parent)
- : sys::Service(name, std::move(parent), ServceEinkStackDepth),
- exitAction{exitAction}, display{{BOARD_EINK_DISPLAY_RES_X, BOARD_EINK_DISPLAY_RES_Y}},
- currentState{State::Running}, settings{std::make_unique<settings::Settings>()}
+ : sys::Service(name, std::move(parent), ServceEinkStackDepth), exitAction{exitAction},
+ currentState{State::Running}, display{hal::eink::AbstractEinkDisplay::Factory::create(
+ hal::eink::FrameSize{BOARD_EINK_DISPLAY_RES_X, BOARD_EINK_DISPLAY_RES_Y})},
+ settings{std::make_unique<settings::Settings>()}
{
displayPowerOffTimer = sys::TimerFactory::createSingleShotTimer(
- this, "einkDisplayPowerOff", displayPowerOffTimeout, [this](sys::Timer &) { display.powerOff(); });
+ this, "einkDisplayPowerOff", displayPowerOffTimeout, [this](sys::Timer &) {
+ display->powerOff();
+ eInkSentinel->ReleaseMinimumFrequency();
+ });
connect(typeid(EinkModeMessage),
[this](sys::Message *message) -> sys::MessagePointer { return handleEinkModeChangedMessage(message); });
@@ 55,7 71,6 @@ namespace service::eink
[this](sys::Message *request) -> sys::MessagePointer { return handlePrepareEarlyRequest(request); });
eInkSentinel = std::make_shared<EinkSentinel>(name::eink, this);
- display.setEinkSentinel(eInkSentinel);
}
sys::MessagePointer ServiceEink::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *response)
@@ 66,7 81,7 @@ namespace service::eink
sys::ReturnCodes ServiceEink::InitHandler()
{
LOG_INFO("Initializing");
- if (const auto status = display.resetAndInit(); status != EinkOK) {
+ if (const auto status = display->resetAndInit(); status != hal::eink::EinkStatus::EinkOK) {
LOG_FATAL("Error: Could not initialize Eink display!");
return sys::ReturnCodes::Failure;
}
@@ 74,13 89,14 @@ namespace service::eink
settings->init(service::ServiceProxy(shared_from_this()));
initStaticData();
- auto deviceRegistrationMsg = std::make_shared<sys::DeviceRegistrationMessage>(display.getDevice());
+ auto deviceRegistrationMsg = std::make_shared<sys::DeviceRegistrationMessage>(display->getDevice());
bus.sendUnicast(deviceRegistrationMsg, service::name::system_manager);
auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(eInkSentinel);
bus.sendUnicast(sentinelRegistrationMsg, service::name::system_manager);
- display.powerOn();
+ display->powerOn();
+ eInkSentinel->HoldMinimumFrequency();
return sys::ReturnCodes::Success;
}
@@ 96,9 112,9 @@ namespace service::eink
sys::ReturnCodes ServiceEink::DeinitHandler()
{
if (exitAction == ExitAction::WipeOut) {
- display.wipeOut();
+ display->wipeOut();
}
- display.shutdown();
+ display->shutdown();
settings->deinit();
return sys::ReturnCodes::Success;
}
@@ 123,17 139,19 @@ namespace service::eink
{
setState(State::Running);
- if (const auto status = display.resetAndInit(); status != EinkOK) {
+ if (const auto status = display->resetAndInit(); status != hal::eink::EinkStatus::EinkOK) {
LOG_FATAL("Error: Could not initialize Eink display!");
}
- display.powerOn();
- display.powerOff();
+ eInkSentinel->HoldMinimumFrequency();
+ display->powerOn();
+ display->powerOff();
+ eInkSentinel->ReleaseMinimumFrequency();
}
void ServiceEink::suspend()
{
setState(State::Suspended);
- display.shutdown();
+ display->shutdown();
}
sys::MessagePointer ServiceEink::handleEinkModeChangedMessage(sys::Message *message)
@@ 149,10 167,10 @@ namespace service::eink
{
auto invertedModeRequested = mode == EinkModeMessage::Mode::Invert;
if (invertedModeRequested) {
- display.setMode(EinkDisplayColorMode_e::EinkDisplayColorModeInverted);
+ display->setMode(hal::eink::EinkDisplayColorMode::EinkDisplayColorModeInverted);
}
else {
- display.setMode(EinkDisplayColorMode_e::EinkDisplayColorModeStandard);
+ display->setMode(hal::eink::EinkDisplayColorMode::EinkDisplayColorModeStandard);
}
internal::StaticData::get().setInvertedMode(invertedModeRequested);
}
@@ 166,70 184,22 @@ namespace service::eink
}
utils::time::Scoped measurement("ImageMessage");
- showImage(message->getData(), message->getRefreshMode());
- return std::make_shared<service::eink::ImageDisplayedNotification>(message->getContextId());
- }
-
- void ServiceEink::showImage(std::uint8_t *frameBuffer, ::gui::RefreshModes refreshMode)
- {
displayPowerOffTimer.stop();
-
auto displayPowerOffTimerReload = gsl::finally([this]() { displayPowerOffTimer.start(); });
- if (const auto status = prepareDisplay(refreshMode, WaveformTemperature::KEEP_CURRENT);
- status != EinkStatus_e::EinkOK) {
- LOG_FATAL("Failed to prepare frame");
- return;
- }
-
- if (const auto status = updateDisplay(frameBuffer, refreshMode); status != EinkStatus_e::EinkOK) {
- LOG_FATAL("Failed to update frame");
- return;
+ auto status = display->showImage(message->getData(), translateToEinkRefreshMode(message->getRefreshMode()));
+ if (status != hal::eink::EinkStatus::EinkOK) {
+ LOG_ERROR("Error during drawing image on eink: %s", magic_enum::enum_name(status).data());
}
- if (const auto status = refreshDisplay(refreshMode); status != EinkStatus_e::EinkOK) {
- LOG_FATAL("Failed to refresh frame");
- return;
- }
- }
-
- EinkStatus_e ServiceEink::updateDisplay(std::uint8_t *frameBuffer, ::gui::RefreshModes refreshMode)
- {
- return display.update(frameBuffer);
- }
-
- EinkStatus_e ServiceEink::refreshDisplay(::gui::RefreshModes refreshMode)
- {
- const auto isDeepRefresh = refreshMode == ::gui::RefreshModes::GUI_REFRESH_DEEP;
- return display.refresh(isDeepRefresh ? EinkDisplayTimingsDeepCleanMode : EinkDisplayTimingsFastRefreshMode);
- }
-
- EinkStatus_e ServiceEink::prepareDisplay(::gui::RefreshModes refreshMode, WaveformTemperature behaviour)
- {
- EinkStatus_e status;
-
- displayPowerOffTimer.stop();
- display.powerOn();
-
- const auto temperature = behaviour == WaveformTemperature::KEEP_CURRENT ? display.getLastTemperature()
- : EinkGetTemperatureInternal();
-
- if (refreshMode == ::gui::RefreshModes::GUI_REFRESH_DEEP) {
- status = display.setWaveform(EinkWaveforms_e::EinkWaveformGC16, temperature);
- if (status == EinkOK) {
- display.dither();
- }
- }
- else {
- status = display.setWaveform(EinkWaveforms_e::EinkWaveformDU2, temperature);
- }
- return status;
+ return std::make_shared<service::eink::ImageDisplayedNotification>(message->getContextId());
}
sys::MessagePointer ServiceEink::handlePrepareEarlyRequest(sys::Message *message)
{
const auto waveformUpdateMsg = static_cast<service::eink::PrepareDisplayEarlyRequest *>(message);
- prepareDisplay(waveformUpdateMsg->getRefreshMode(), WaveformTemperature::MEASURE_NEW);
+ display->prepareEarlyRequest(translateToEinkRefreshMode(waveformUpdateMsg->getRefreshMode()),
+ hal::eink::WaveformTemperature::MEASURE_NEW);
return sys::MessageNone{};
}
M module-services/service-eink/ServiceEink.hpp => module-services/service-eink/ServiceEink.hpp +5 -14
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 9,7 9,6 @@
#include <Timers/TimerHandle.hpp>
#include "EinkSentinel.hpp"
-#include "EinkDisplay.hpp"
#include <service-db/DBServiceName.hpp>
#include <service-db/Settings.hpp>
@@ 18,6 17,9 @@
#include <cstdint>
#include <string>
#include <module-services/service-eink/messages/EinkModeMessage.hpp>
+#include <hal/eink/AbstractEinkDisplay.hpp>
+
+#include "Common.hpp"
namespace service::eink
{
@@ 46,23 48,12 @@ namespace service::eink
Suspended
};
- /// It takes 25ms to get a new measurement
- enum class WaveformTemperature
- {
- KEEP_CURRENT,
- MEASURE_NEW,
- };
-
void setState(State state) noexcept;
bool isInState(State state) const noexcept;
void enterActiveMode();
void suspend();
- void showImage(std::uint8_t *frameBuffer, ::gui::RefreshModes refreshMode);
- EinkStatus_e prepareDisplay(::gui::RefreshModes refreshMode, WaveformTemperature behaviour);
- EinkStatus_e refreshDisplay(::gui::RefreshModes refreshMode);
- EinkStatus_e updateDisplay(uint8_t *frameBuffer, ::gui::RefreshModes refreshMode);
void setDisplayMode(EinkModeMessage::Mode mode);
sys::MessagePointer handleEinkModeChangedMessage(sys::Message *message);
@@ 72,8 63,8 @@ namespace service::eink
void initStaticData();
ExitAction exitAction;
- EinkDisplay display;
State currentState;
+ std::unique_ptr<hal::eink::AbstractEinkDisplay> display;
sys::TimerHandle displayPowerOffTimer;
std::shared_ptr<EinkSentinel> eInkSentinel;
std::unique_ptr<settings::Settings> settings;
M module-services/service-gui/CMakeLists.txt => module-services/service-gui/CMakeLists.txt +7 -3
@@ 26,9 26,13 @@ target_sources(service-gui
target_link_libraries(service-gui
- service-eink
- module-gui
- module-apps
+ PUBLIC
+ service-eink
+ module-gui
+ module-apps
+ PRIVATE
+ Microsoft.GSL::GSL
+
)
target_include_directories(service-gui
M module-sys/SystemManager/CMakeLists.txt => module-sys/SystemManager/CMakeLists.txt +1 -0
@@ 47,6 47,7 @@ target_link_libraries(sys-manager
service-desktop
msgpack11
system-stats-sink
+ Microsoft.GSL::GSL
)
if (${ENABLE_TESTS})
M products/BellHybrid/apps/application-bell-background-sounds/CMakeLists.txt => products/BellHybrid/apps/application-bell-background-sounds/CMakeLists.txt +1 -0
@@ 48,6 48,7 @@ target_link_libraries(application-bell-background-sounds
apps-common
bell::audio
bell::alarms
+ Microsoft.GSL::GSL
PUBLIC
module-gui
M products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt => products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt +1 -0
@@ 48,6 48,7 @@ target_link_libraries(application-bell-powernap
bell::keymap
bell::alarms
bell::db
+ Microsoft.GSL::GSL
PUBLIC
module-gui
M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +1 -0
@@ 127,6 127,7 @@ target_link_libraries(application-bell-common
bell::audio
module-gui
bell::db
+ Microsoft.GSL::GSL
)
if (${ENABLE_TESTS})
M products/PurePhone/test/test-settings/CMakeLists.txt => products/PurePhone/test/test-settings/CMakeLists.txt +1 -0
@@ 13,6 13,7 @@ add_catch2_executable(
module-vfs
service-audio
service-cellular
+ Microsoft.GSL::GSL
DEPS
module-sys
)