~aleteoryx/muditaos

3246570dc8f5927d27ab7567d013a51538702672 — Maciej Janicki 4 years ago 847957a
[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.
M module-bsp/board/rt1051/bellpx/CMakeLists.txt => module-bsp/board/rt1051/bellpx/CMakeLists.txt +2 -1
@@ 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

A module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.cpp => module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.cpp +42 -0
@@ 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<GPIOInstances>(BoardDefinitions::EINK_BELL_PWR_GPIO), DriverGPIOParams{});

        gpio_pwren->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Output,
                                                .irqMode  = DriverGPIOPinParams::InterruptMode::NoIntmode,
                                                .defLogic = 1,
                                                .pin = static_cast<uint32_t>(BoardDefinitions::EINK_BELL_PWR_PIN)});

        auto gpio = DriverGPIO::Create(static_cast<GPIOInstances>(BoardDefinitions::EINK_GPIO), DriverGPIOParams{});

        gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Output,
                                          .irqMode  = DriverGPIOPinParams::InterruptMode::NoIntmode,
                                          .defLogic = 1,
                                          .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_CS_PIN)});

        gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Output,
                                          .irqMode  = DriverGPIOPinParams::InterruptMode::NoIntmode,
                                          .defLogic = 0,
                                          .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_RESET_PIN)});

        gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Input,
                                          .irqMode  = DriverGPIOPinParams::InterruptMode::IntRisingEdge,
                                          .defLogic = 0,
                                          .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_BUSY_PIN)});

        gpio->ClearPortInterrupts(1 << static_cast<uint32_t>(BoardDefinitions::EINK_BUSY_PIN));
        gpio->DisableInterrupt(1 << static_cast<uint32_t>(BoardDefinitions::EINK_BUSY_PIN));
    }
} // namespace bsp::eink

A module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.hpp => module-bsp/board/rt1051/bellpx/bsp/eink/eink_pin_config.hpp +15 -0
@@ 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

M module-bsp/board/rt1051/bsp/BoardDefinitions.hpp => module-bsp/board/rt1051/bsp/BoardDefinitions.hpp +2 -0
@@ 95,6 95,8 @@ enum class BoardDefinitions
    EINK_BUSY_PIN       = 17,
    EINK_PLL            = static_cast<int>(drivers::PLLInstances::PLL2_PFD2),
    EINK_LPSPI_INSTANCE = static_cast<int>(drivers::LPSPIInstances::LPSPI_1),
    EINK_BELL_PWR_GPIO  = static_cast<int>(drivers::GPIOInstances ::GPIO_1),
    EINK_BELL_PWR_PIN   = 19,

    BLUETOOTH_DMA            = static_cast<int>(drivers::DMAInstances ::DMA_0),
    BLUETOOTH_DMAMUX         = static_cast<int>(drivers::DMAMuxInstances ::DMAMUX0),

M module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp => module-bsp/board/rt1051/bsp/eink/ED028TC1.cpp +121 -102
@@ 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<drivers::DriverDMAMux> 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;
}

M module-bsp/board/rt1051/bsp/eink/bsp_eink.cpp => module-bsp/board/rt1051/bsp/eink/bsp_eink.cpp +8 -25
@@ 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<PLLInstances >(BoardDefinitions ::EINK_PLL),DriverPLLParams{});

    lpspi->eventRegister = EventWaitNotRegistered;

    gpio = DriverGPIO::Create(static_cast<GPIOInstances>(BoardDefinitions::EINK_GPIO), DriverGPIOParams{});

    gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Output,
                                      .irqMode  = DriverGPIOPinParams::InterruptMode::NoIntmode,
                                      .defLogic = 1,
                                      .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_CS_PIN)});

    gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Output,
                                      .irqMode  = DriverGPIOPinParams::InterruptMode::NoIntmode,
                                      .defLogic = 0,
                                      .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_RESET_PIN)});

    gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Input,
                                      .irqMode  = DriverGPIOPinParams::InterruptMode::IntRisingEdge,
                                      .defLogic = 0,
                                      .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_BUSY_PIN)});

    gpio->ClearPortInterrupts(1 << static_cast<uint32_t>(BoardDefinitions::EINK_BUSY_PIN));
    gpio->DisableInterrupt(1 << static_cast<uint32_t>(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<uint32_t>(BoardDefinitions::EINK_BUSY_PIN));
    // Enable the BUSY Pin IRQ
    gpio->EnableInterrupt(1 << static_cast<uint32_t>(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<uint32_t>(BoardDefinitions::EINK_BUSY_PIN));
    // Enable the BUSY Pin IRQ
    gpio->EnableInterrupt(1 << static_cast<uint32_t>(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(

M module-bsp/board/rt1051/puretx/CMakeLists.txt => module-bsp/board/rt1051/puretx/CMakeLists.txt +3 -2
@@ 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
        

A module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.cpp => module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.cpp +34 -0
@@ 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<GPIOInstances>(BoardDefinitions::EINK_GPIO), DriverGPIOParams{});

        gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Output,
                                          .irqMode  = DriverGPIOPinParams::InterruptMode::NoIntmode,
                                          .defLogic = 1,
                                          .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_CS_PIN)});

        gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Output,
                                          .irqMode  = DriverGPIOPinParams::InterruptMode::NoIntmode,
                                          .defLogic = 0,
                                          .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_RESET_PIN)});

        gpio->ConfPin(DriverGPIOPinParams{.dir      = DriverGPIOPinParams::Direction::Input,
                                          .irqMode  = DriverGPIOPinParams::InterruptMode::IntRisingEdge,
                                          .defLogic = 0,
                                          .pin      = static_cast<uint32_t>(BoardDefinitions::EINK_BUSY_PIN)});

        gpio->ClearPortInterrupts(1 << static_cast<uint32_t>(BoardDefinitions::EINK_BUSY_PIN));
        gpio->DisableInterrupt(1 << static_cast<uint32_t>(BoardDefinitions::EINK_BUSY_PIN));
    }
} // namespace bsp::eink

A module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.hpp => module-bsp/board/rt1051/puretx/bsp/eink/eink_pin_config.hpp +15 -0
@@ 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

M module-bsp/board/rt1051/puretx/eink-config.h => module-bsp/board/rt1051/puretx/eink-config.h +3 -3
@@ 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

M products/BellHybrid/BellHybridMain.cpp => products/BellHybrid/BellHybridMain.cpp +0 -2
@@ 72,8 72,6 @@ int main()
#endif
    systemServices.emplace_back(sys::CreatorFor<ServiceDB>());
    systemServices.emplace_back(sys::CreatorFor<ServiceAudio>());
    systemServices.emplace_back(sys::CreatorFor<ServiceBluetooth>());
    systemServices.emplace_back(sys::CreatorFor<ServiceLwIP>());
    systemServices.emplace_back(sys::CreatorFor<ServiceDesktop>());
    systemServices.emplace_back(sys::CreatorFor<stm::ServiceTime>());
    systemServices.emplace_back(sys::CreatorFor<service::eink::ServiceEink>());