From 3246570dc8f5927d27ab7567d013a51538702672 Mon Sep 17 00:00:00 2001 From: Maciej Janicki Date: Fri, 3 Sep 2021 09:48:26 +0200 Subject: [PATCH] [BH-842] Add no screen rotation option for Bell This commit adds no screen rotation version of eink methods. It also separates pins initialization for eink per product. --- module-bsp/board/rt1051/bellpx/CMakeLists.txt | 3 +- .../bellpx/bsp/eink/eink_pin_config.cpp | 42 ++++ .../bellpx/bsp/eink/eink_pin_config.hpp | 15 ++ .../board/rt1051/bsp/BoardDefinitions.hpp | 2 + module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp | 223 ++++++++++-------- module-bsp/board/rt1051/bsp/eink/bsp_eink.cpp | 33 +-- module-bsp/board/rt1051/puretx/CMakeLists.txt | 5 +- .../puretx/bsp/eink/eink_pin_config.cpp | 34 +++ .../puretx/bsp/eink/eink_pin_config.hpp | 15 ++ module-bsp/board/rt1051/puretx/eink-config.h | 6 +- products/BellHybrid/BellHybridMain.cpp | 2 - 11 files changed, 245 insertions(+), 135 deletions(-) create mode 100644 module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.cpp create mode 100644 module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.hpp create mode 100644 module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.cpp create mode 100644 module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.hpp diff --git a/module-bsp/board/rt1051/bellpx/CMakeLists.txt b/module-bsp/board/rt1051/bellpx/CMakeLists.txt index 5b89eda80f115fc915b00d953a9b2bae1b2032de..90836eca4fbd6c2b99f9576dd1b489716a3bf5d1 100644 --- a/module-bsp/board/rt1051/bellpx/CMakeLists.txt +++ b/module-bsp/board/rt1051/bellpx/CMakeLists.txt @@ -12,7 +12,8 @@ target_sources( PRIVATE hal/temperature_source/TemperatureSource.cpp hal/battery_charger/BatteryCharger.cpp - hal/key_input/KeyInput.cpp + hal/key_input/KeyInput.cpp + bsp/eink/eink_pin_config.cpp pin_mux.c clock_config.cpp irq_gpio.cpp diff --git a/module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.cpp b/module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ec0710b0e427850b3b023062d06125d13e2e12c --- /dev/null +++ b/module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "drivers/gpio/DriverGPIO.hpp" +#include "bsp/BoardDefinitions.hpp" + +namespace bsp::eink +{ + + void eink_configure_gpio_pins() + { + using namespace drivers; + + auto gpio_pwren = + DriverGPIO::Create(static_cast(BoardDefinitions::EINK_BELL_PWR_GPIO), DriverGPIOParams{}); + + gpio_pwren->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, + .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, + .defLogic = 1, + .pin = static_cast(BoardDefinitions::EINK_BELL_PWR_PIN)}); + + auto gpio = DriverGPIO::Create(static_cast(BoardDefinitions::EINK_GPIO), DriverGPIOParams{}); + + gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, + .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, + .defLogic = 1, + .pin = static_cast(BoardDefinitions::EINK_CS_PIN)}); + + gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, + .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, + .defLogic = 0, + .pin = static_cast(BoardDefinitions::EINK_RESET_PIN)}); + + gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Input, + .irqMode = DriverGPIOPinParams::InterruptMode::IntRisingEdge, + .defLogic = 0, + .pin = static_cast(BoardDefinitions::EINK_BUSY_PIN)}); + + gpio->ClearPortInterrupts(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); + gpio->DisableInterrupt(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); + } +} // namespace bsp::eink diff --git a/module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.hpp b/module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c85a5e3396569764a4ac794b7d1b890eedb41fd5 --- /dev/null +++ b/module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +namespace bsp::eink +{ + /** + * eink_configure_gpio_pins + * + * This method initializes all GPIO pins needed for eInk handling. + */ + + void eink_configure_gpio_pins(); +} // namespace bsp::eink diff --git a/module-bsp/board/rt1051/bsp/BoardDefinitions.hpp b/module-bsp/board/rt1051/bsp/BoardDefinitions.hpp index 5a9d820f1c2abd4497e6b46036fa28618f50d9d9..54231408bb6300e2df935695c96586122467501b 100644 --- a/module-bsp/board/rt1051/bsp/BoardDefinitions.hpp +++ b/module-bsp/board/rt1051/bsp/BoardDefinitions.hpp @@ -95,6 +95,8 @@ enum class BoardDefinitions EINK_BUSY_PIN = 17, EINK_PLL = static_cast(drivers::PLLInstances::PLL2_PFD2), EINK_LPSPI_INSTANCE = static_cast(drivers::LPSPIInstances::LPSPI_1), + EINK_BELL_PWR_GPIO = static_cast(drivers::GPIOInstances ::GPIO_1), + EINK_BELL_PWR_PIN = 19, BLUETOOTH_DMA = static_cast(drivers::DMAInstances ::DMA_0), BLUETOOTH_DMAMUX = static_cast(drivers::DMAMuxInstances ::DMAMUX0), diff --git a/module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp b/module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp index f6f397cc64dd98c412843a4078e971ecb039b93a..8f77658f65cbf943354cd35ac4c739f44b218602 100644 --- a/module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp +++ b/module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "dma_config.h" @@ -56,6 +56,22 @@ #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 @@ -77,7 +93,7 @@ static std::shared_ptr dmamux; static uint8_t s_einkIsPoweredOn = false; // Variable which contains the state of the power of the EPD display static EinkWaveforms_e s_einkConfiguredWaveform = - EinkWaveformGC16; // This variable contains the current waveform set in the display + EinkWaveformGC16; // This variable contains the current waveform set in the display static CACHEABLE_SECTION_SDRAM(uint8_t s_einkServiceRotatedBuf[BOARD_EINK_DISPLAY_RES_X * BOARD_EINK_DISPLAY_RES_Y / 2 + 2]); // Plus 2 for the EPD command and BPP config @@ -482,11 +498,17 @@ static uint8_t *s_EinkTransformAnimationFrameCoordinateSystem_3Bpp(uint8_t *data * * @return */ -static uint8_t *s_EinkTransformAnimationFrameCoordinateSystem_4Bpp(uint8_t *dataIn, - uint16_t windowWidthPx, - uint16_t windowHeightPx, - uint8_t *dataOut, - EinkDisplayColorMode_e invertColors); + +/* + * Not rotating version of s_EinkTransformAnimationFrameCoordinateSystem_4Bpp. + * It is used when EINK_ROTATE_90_CLOCKWISE is not defined. + */ + +static uint8_t *s_EinkTransformFrameCoordinateSystemNoRotation_4Bpp(uint8_t *dataIn, + uint16_t windowWidthPx, + uint16_t windowHeightPx, + uint8_t *dataOut, + EinkDisplayColorMode_e invertColors); /* Function bodies */ @@ -808,17 +830,19 @@ EinkStatus_e EinkUpdateFrame( case Eink1Bpp: { s_EinkTransformAnimationFrameCoordinateSystem_1Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); } break; - case Eink2Bpp: { s_EinkTransformAnimationFrameCoordinateSystem_2Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); } break; - case Eink3Bpp: { s_EinkTransformAnimationFrameCoordinateSystem_3Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); } break; - case Eink4Bpp: { - s_EinkTransformAnimationFrameCoordinateSystem_4Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); +#if defined(EINK_ROTATE_90_CLOCKWISE) + s_EinkTransformFrameCoordinateSystem_4Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); +#else + s_EinkTransformFrameCoordinateSystemNoRotation_4Bpp( + buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); +#endif } break; } } @@ -827,40 +851,40 @@ EinkStatus_e EinkUpdateFrame( case Eink1Bpp: { s_EinkTransformFrameCoordinateSystem_1Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); } break; - case Eink2Bpp: { s_EinkTransformFrameCoordinateSystem_2Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); } break; - case Eink3Bpp: { s_EinkTransformFrameCoordinateSystem_3Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); } break; - case Eink4Bpp: { +#if defined(EINK_ROTATE_90_CLOCKWISE) s_EinkTransformFrameCoordinateSystem_4Bpp(buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); +#else + s_EinkTransformFrameCoordinateSystemNoRotation_4Bpp( + buffer, W, H, s_einkServiceRotatedBuf + 2, invertColors); +#endif } break; } } - buf[0] = EinkDataStartTransmissionWindow; // set display window - buf[1] = - (uint8_t)((BOARD_EINK_DISPLAY_RES_Y - Y - H) >> 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)BOARD_EINK_DISPLAY_RES_Y - Y - H; // LSB of the X axis in the EPD display. Value converted from + 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)((BOARD_EINK_DISPLAY_RES_X - X - W) >> 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)BOARD_EINK_DISPLAY_RES_X - X - W; // LSB of the Y axis in the EPD display. Value converted from + 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)(H >> 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)H; // 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)(W >> 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)W; // LSB of the window width 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 + // the standard GUI coords system to the ED028TC1 one if (BSP_EinkWriteData(buf, 9, SPI_AUTOMATIC_CS) != 0) { EinkResetAndInitialize(); @@ -889,10 +913,10 @@ EinkStatus_e EinkFillScreenWithColor(EinkDisplayColorFilling_e colorFill) buf[2] = 0x00; buf[3] = 0x00; buf[4] = 0x00; - buf[5] = (BOARD_EINK_DISPLAY_RES_Y & 0xFF00) >> 8; - buf[6] = BOARD_EINK_DISPLAY_RES_Y & 0x00FF; - buf[7] = (BOARD_EINK_DISPLAY_RES_X & 0xFF00) >> 8; - buf[8] = BOARD_EINK_DISPLAY_RES_X & 0x00FF; + buf[5] = (EINK_DISPLAY_RES_X & 0xFF00) >> 8; + buf[6] = EINK_DISPLAY_RES_X & 0x00FF; + buf[7] = (EINK_DISPLAY_RES_Y & 0xFF00) >> 8; + buf[8] = EINK_DISPLAY_RES_Y & 0x00FF; if (BSP_EinkWriteData(buf, 9, SPI_AUTOMATIC_CS) != 0) { EinkResetAndInitialize(); @@ -947,24 +971,22 @@ EinkStatus_e EinkRefreshImage( buf[0] = EinkDisplayRefresh; buf[1] = UPD_CPY_TO_PRE; - buf[2] = - (uint8_t)((BOARD_EINK_DISPLAY_RES_Y - Y - H) >> 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)BOARD_EINK_DISPLAY_RES_Y - Y - H; // LSB of the X axis in the EPD display. Value converted from + 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)((BOARD_EINK_DISPLAY_RES_X - X - W) >> 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)BOARD_EINK_DISPLAY_RES_X - X - W; // LSB of the Y axis in the EPD display. Value converted from + 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)(H >> 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)H; // 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)(W >> 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)W; // LSB of the window width 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 + // the standard GUI coords system to the ED028TC1 one if (BSP_EinkWriteData(buf, sizeof(buf), SPI_AUTOMATIC_CS) != 0) { EinkResetAndInitialize(); @@ -1117,54 +1139,6 @@ __attribute__((optimize("O1"))) static uint8_t *s_EinkTransformFrameCoordinateSy return s_EinkTransformFrameCoordinateSystem_4Bpp(dataIn, windowWidthPx, windowHeightPx, dataOut, invertColors); } -__attribute__((optimize("O1"))) static uint8_t *s_EinkTransformFrameCoordinateSystem_4Bpp( - uint8_t *dataIn, - uint16_t windowWidthPx, - uint16_t windowHeightPx, - uint8_t *dataOut, - EinkDisplayColorMode_e invertColors) -{ - // In 3bpp and 4bpp modes there are 2 pixels in the byte. Using 8bpp to process the whole uint32_t at once for - // faster execution - const uint8_t pixelsInByte = 8; - - uint32_t pixels = 0; - uint32_t *outArray = (uint32_t *)dataOut; - - for (int32_t inputCol = windowWidthPx - 1; inputCol >= 0; --inputCol) { - for (int32_t inputRow = windowHeightPx - 1; inputRow >= 7; inputRow -= pixelsInByte) { - // HACK: Did not create the loop for accessing pixels and merging them in the single byte for better - // performance. - // Wanted to avoid unneeded loop count increasing and jump operations which for large amount of data - // take considerable amount of time. Using 8 pixels at a time for better performance - uint32_t index = inputRow * BOARD_EINK_DISPLAY_RES_X + inputCol; - - // Get 4x 2 adjacent pixels to process them as uint32_t for better execution timings - uint8_t firstPixel = - (dataIn[index - 0 * BOARD_EINK_DISPLAY_RES_X] << 4) | dataIn[index - 1 * BOARD_EINK_DISPLAY_RES_X]; - uint8_t thirdPixel = - (dataIn[index - 2 * BOARD_EINK_DISPLAY_RES_X] << 4) | dataIn[index - 3 * BOARD_EINK_DISPLAY_RES_X]; - uint8_t fifthPixel = - (dataIn[index - 4 * BOARD_EINK_DISPLAY_RES_X] << 4) | dataIn[index - 5 * BOARD_EINK_DISPLAY_RES_X]; - uint8_t seventhPixel = - (dataIn[index - 6 * BOARD_EINK_DISPLAY_RES_X] << 4) | dataIn[index - 7 * BOARD_EINK_DISPLAY_RES_X]; - - // Put the pixels in the uint32_t for faster processing - pixels = firstPixel | (thirdPixel << 8) | (fifthPixel << 16) | (seventhPixel << 24); - - if (invertColors) { - pixels = ~pixels; - } - - // Put the pixels in order: Most left positioned pixel at the most significant side of byte - *outArray = pixels; - ++outArray; - } - } - - return dataOut; -} - __attribute__((optimize("O1"))) static uint8_t *s_EinkTransformAnimationFrameCoordinateSystem_1Bpp( uint8_t *dataIn, uint16_t windowWidthPx, @@ -1269,11 +1243,10 @@ __attribute__((optimize("O3"))) static uint8_t *s_EinkTransformAnimationFrameCoo EinkDisplayColorMode_e invertColors) { // The 4bpp is coded the same way as the 3bpp - return s_EinkTransformAnimationFrameCoordinateSystem_4Bpp( - dataIn, windowWidthPx, windowHeightPx, dataOut, invertColors); + return s_EinkTransformFrameCoordinateSystem_4Bpp(dataIn, windowWidthPx, windowHeightPx, dataOut, invertColors); } -__attribute__((optimize("O1"))) static uint8_t *s_EinkTransformAnimationFrameCoordinateSystem_4Bpp( +__attribute__((optimize("O1"))) static uint8_t *s_EinkTransformFrameCoordinateSystem_4Bpp( uint8_t *dataIn, uint16_t windowWidthPx, uint16_t windowHeightPx, @@ -1319,3 +1292,49 @@ __attribute__((optimize("O1"))) static uint8_t *s_EinkTransformAnimationFrameCoo return dataOut; } + +__attribute__((optimize("O1"))) static uint8_t *s_EinkTransformFrameCoordinateSystemNoRotation_4Bpp( + uint8_t *dataIn, + uint16_t windowWidthPx, + uint16_t windowHeightPx, + uint8_t *dataOut, + EinkDisplayColorMode_e invertColors) +{ + // In 3bpp and 4bpp modes there are 2 pixels in the byte. Using 8bpp to process the whole uint32_t at once for + // faster execution + const uint8_t pixelsInByte = 8; + + uint32_t pixels = 0; + uint32_t *outArray = (uint32_t *)dataOut; + int32_t inputRow = 0; + int32_t inputCol = 0; + + for (inputRow = windowHeightPx - 1; inputRow >= 0; --inputRow) { + for (inputCol = 0; inputCol < windowWidthPx - 7; inputCol += pixelsInByte) { + // HACK: Did not create the loop for accessing pixels and merging them in the single byte for better + // performance. + // Wanted to avoid unneeded loop count increasing and jump operations which for large amount of data + // take considerable amount of time. Using 8 pixels at a time for better performance + uint32_t index = inputRow * BOARD_EINK_DISPLAY_RES_X + inputCol; + + // Get 4x 2 adjacent pixels to process them as uint32_t for better execution timings + uint8_t firstPixelPair = (dataIn[index] << 4) | dataIn[index + 1]; + uint8_t secondPixelPair = (dataIn[index + 2] << 4) | dataIn[index + 3]; + uint8_t thirdPixelPair = (dataIn[index + 4] << 4) | dataIn[index + 5]; + uint8_t fourthPixelPair = (dataIn[index + 6] << 4) | dataIn[index + 7]; + + // Put the pixels in the uint32_t for faster processing + pixels = (firstPixelPair) | (secondPixelPair << 8) | (thirdPixelPair << 16) | (fourthPixelPair << 24); + + if (invertColors) { + pixels = ~pixels; + } + + // Put the pixels in order: Most left positioned pixel at the most significant side of byte + *outArray = pixels; + ++outArray; + } + } + + return dataOut; +} diff --git a/module-bsp/board/rt1051/bsp/eink/bsp_eink.cpp b/module-bsp/board/rt1051/bsp/eink/bsp_eink.cpp index d87fcddf07ba9dd904c0437ddfeddc9b50952d6d..5aadc17a4f975a9cca1ed30f6a9b52fd48cc2840 100644 --- a/module-bsp/board/rt1051/bsp/eink/bsp_eink.cpp +++ b/module-bsp/board/rt1051/bsp/eink/bsp_eink.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "bsp_eink.h" @@ -7,6 +7,7 @@ #include "fsl_lpspi_edma.h" #include "fsl_common.h" #include "dma_config.h" +#include "bsp/eink/eink_pin_config.hpp" #include "FreeRTOS.h" #include "semphr.h" @@ -145,7 +146,7 @@ static void s_LPSPI_MasterEdmaCallback(LPSPI_Type *base, status_t BSP_EinkInit(bsp_eink_BusyEvent event) { - bsp_eink_driver_t *lpspi = &BSP_EINK_LPSPI_EdmaDriverState; + bsp_eink_driver_t *lpspi = &BSP_EINK_LPSPI_EdmaDriverState; // lpspi_edma_resource_t *dmaResource = lpspi->dmaResource; // If was already created - free it @@ -175,29 +176,11 @@ status_t BSP_EinkInit(bsp_eink_BusyEvent event) return kStatus_Fail; } - // pll = DriverPLL::Create(static_cast(BoardDefinitions ::EINK_PLL),DriverPLLParams{}); - lpspi->eventRegister = EventWaitNotRegistered; gpio = DriverGPIO::Create(static_cast(BoardDefinitions::EINK_GPIO), DriverGPIOParams{}); - gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, - .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, - .defLogic = 1, - .pin = static_cast(BoardDefinitions::EINK_CS_PIN)}); - - gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, - .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, - .defLogic = 0, - .pin = static_cast(BoardDefinitions::EINK_RESET_PIN)}); - - gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Input, - .irqMode = DriverGPIOPinParams::InterruptMode::IntRisingEdge, - .defLogic = 0, - .pin = static_cast(BoardDefinitions::EINK_BUSY_PIN)}); - - gpio->ClearPortInterrupts(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); - gpio->DisableInterrupt(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); + bsp::eink::eink_configure_gpio_pins(); s_eink_lpspi_master_config.baudRate = BSP_EINK_TRANSFER_WRITE_CLOCK; s_eink_lpspi_master_config.bitsPerFrame = 8; @@ -320,8 +303,8 @@ status_t BSP_EinkWriteData(void *txBuffer, uint32_t len, eink_spi_cs_config_e cs gpio->ClearPortInterrupts(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); // Enable the BUSY Pin IRQ gpio->EnableInterrupt(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); - // Take the BUSY semaphore without timeout just in case the transmission makes the BUSY pin state change. It enables - // the driver to block then on the bsp_eink_busySemaphore until the BUSY pin is deasserted + // Take the BUSY semaphore without timeout just in case the transmission makes the BUSY pin state change. It + // enables the driver to block then on the bsp_eink_busySemaphore until the BUSY pin is deasserted xSemaphoreTake(bsp_eink_busySemaphore, 0); // The MAJOR loop of the DMA can be maximum of value 32767 @@ -402,8 +385,8 @@ status_t BSP_EinkReadData(void *rxBuffer, uint32_t len, eink_spi_cs_config_e cs) gpio->ClearPortInterrupts(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); // Enable the BUSY Pin IRQ gpio->EnableInterrupt(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); - // Take the BUSY semaphore without timeout just in case the transmission makes the BUSY pin state change. It enables - // the driver to block then on the bsp_eink_busySemaphore until the BUSY pin is deasserted + // Take the BUSY semaphore without timeout just in case the transmission makes the BUSY pin state change. It + // enables the driver to block then on the bsp_eink_busySemaphore until the BUSY pin is deasserted xSemaphoreTake(bsp_eink_busySemaphore, 0); status = LPSPI_MasterTransferEDMA( diff --git a/module-bsp/board/rt1051/puretx/CMakeLists.txt b/module-bsp/board/rt1051/puretx/CMakeLists.txt index 39b050ac0f3f996a44eadf60e53e19b6661ebac4..c9114b0b72630424b24c4d378484361c92c3d8e3 100644 --- a/module-bsp/board/rt1051/puretx/CMakeLists.txt +++ b/module-bsp/board/rt1051/puretx/CMakeLists.txt @@ -11,10 +11,11 @@ target_sources( PRIVATE hal/battery_charger/BatteryCharger.cpp + hal/key_input/KeyInput.cpp bsp/battery_charger/battery_charger.cpp - hal/key_input/KeyInput.cpp + bsp/eink/eink_pin_config.cpp bsp/keyboard/keyboard.cpp - pin_mux.c + pin_mux.c clock_config.cpp irq_gpio.cpp diff --git a/module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.cpp b/module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92ee0efc4bfcdb776cd77bb823810598882b4622 --- /dev/null +++ b/module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "drivers/gpio/DriverGPIO.hpp" +#include "bsp/BoardDefinitions.hpp" + +namespace bsp::eink +{ + + void eink_configure_gpio_pins() + { + using namespace drivers; + + auto gpio = DriverGPIO::Create(static_cast(BoardDefinitions::EINK_GPIO), DriverGPIOParams{}); + + gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, + .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, + .defLogic = 1, + .pin = static_cast(BoardDefinitions::EINK_CS_PIN)}); + + gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Output, + .irqMode = DriverGPIOPinParams::InterruptMode::NoIntmode, + .defLogic = 0, + .pin = static_cast(BoardDefinitions::EINK_RESET_PIN)}); + + gpio->ConfPin(DriverGPIOPinParams{.dir = DriverGPIOPinParams::Direction::Input, + .irqMode = DriverGPIOPinParams::InterruptMode::IntRisingEdge, + .defLogic = 0, + .pin = static_cast(BoardDefinitions::EINK_BUSY_PIN)}); + + gpio->ClearPortInterrupts(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); + gpio->DisableInterrupt(1 << static_cast(BoardDefinitions::EINK_BUSY_PIN)); + } +} // namespace bsp::eink diff --git a/module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.hpp b/module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c85a5e3396569764a4ac794b7d1b890eedb41fd5 --- /dev/null +++ b/module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +namespace bsp::eink +{ + /** + * eink_configure_gpio_pins + * + * This method initializes all GPIO pins needed for eInk handling. + */ + + void eink_configure_gpio_pins(); +} // namespace bsp::eink diff --git a/module-bsp/board/rt1051/puretx/eink-config.h b/module-bsp/board/rt1051/puretx/eink-config.h index 440eb31258ea9797644084170a24415c64f0c338..176ced5dcac09eac8e8a261d37285ab1aa123c5f 100644 --- a/module-bsp/board/rt1051/puretx/eink-config.h +++ b/module-bsp/board/rt1051/puretx/eink-config.h @@ -2,6 +2,6 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once -#define BOARD_EINK_DISPLAY_RES_X 480 -#define BOARD_EINK_DISPLAY_RES_Y 600 -#define BOARD_EINK_DISPLAY_ROTATE 1 +#define BOARD_EINK_DISPLAY_RES_X 480 +#define BOARD_EINK_DISPLAY_RES_Y 600 +#define EINK_ROTATE_90_CLOCKWISE 1 diff --git a/products/BellHybrid/BellHybridMain.cpp b/products/BellHybrid/BellHybridMain.cpp index 7693c32ab99b6ff1605d80c129a24dc412998ce0..5edddfdb9f631c3d171acd1d2a115c6c58850966 100644 --- a/products/BellHybrid/BellHybridMain.cpp +++ b/products/BellHybrid/BellHybridMain.cpp @@ -72,8 +72,6 @@ int main() #endif systemServices.emplace_back(sys::CreatorFor()); systemServices.emplace_back(sys::CreatorFor()); - systemServices.emplace_back(sys::CreatorFor()); - systemServices.emplace_back(sys::CreatorFor()); systemServices.emplace_back(sys::CreatorFor()); systemServices.emplace_back(sys::CreatorFor()); systemServices.emplace_back(sys::CreatorFor());