|
|
|
/*
|
|
|
|
* EEZ Modular Firmware
|
|
|
|
* Copyright (C) 2021-present, Envox d.o.o.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <memory.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include <dma2d.h>
|
|
|
|
#include <i2c.h>
|
|
|
|
#include <ltdc.h>
|
|
|
|
|
|
|
|
#ifdef EEZ_PLATFORM_STM32F469I_DISCO
|
|
|
|
#include "stm32l496g_discovery_lcd.h"
|
|
|
|
extern "C" LTDC_HandleTypeDef hltdc_eval;
|
|
|
|
extern "C" DMA2D_HandleTypeDef hdma2d_eval;
|
|
|
|
#define hltdc hltdc_eval
|
|
|
|
#define hdma2d hdma2d_eval
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <eez/core/util.h>
|
|
|
|
#include <eez/core/memory.h>
|
|
|
|
#include <eez/core/os.h>
|
|
|
|
|
|
|
|
#include <eez/gui/gui.h>
|
|
|
|
#include <eez/gui/thread.h>
|
|
|
|
#include <eez/gui/display.h>
|
|
|
|
#include <eez/gui/display-private.h>
|
|
|
|
|
|
|
|
void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *phltdc) {
|
|
|
|
using namespace eez::gui;
|
|
|
|
using namespace eez::gui::display;
|
|
|
|
|
|
|
|
LTDC_LAYER(phltdc, 0)->CFBAR = (uint32_t)g_syncedBuffer;
|
|
|
|
__HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(phltdc);
|
|
|
|
|
|
|
|
sendMessageToGuiThread(GUI_QUEUE_MESSAGE_TYPE_DISPLAY_VSYNC, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace eez {
|
|
|
|
namespace gui {
|
|
|
|
namespace display {
|
|
|
|
|
|
|
|
#define DMA2D_WAIT if (g_waitDMA) { while (HAL_DMA2D_PollForTransfer(&hdma2d, 1000) != HAL_OK); g_waitDMA = false; }
|
|
|
|
|
|
|
|
static bool g_waitDMA;
|
|
|
|
|
|
|
|
void initDriver() {
|
|
|
|
__HAL_RCC_DMA2D_CLK_ENABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
void syncBuffer() {
|
|
|
|
DMA2D_WAIT;
|
|
|
|
static const uint32_t LINE_INTERRUPT_POSITION = (LTDC->AWCR & 0x7FF) - 1;
|
|
|
|
HAL_LTDC_ProgramLineEvent(&hltdc, LINE_INTERRUPT_POSITION);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bitBltRGB888(uint16_t *src, uint8_t *dst, int x, int y, int width, int height);
|
|
|
|
void copySyncedBufferToScreenshotBuffer() {
|
|
|
|
bitBltRGB888(g_syncedBuffer, SCREENSHOOT_BUFFER_START_ADDRESS, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
|
|
|
|
DMA2D_WAIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
inline uint32_t vramOffset(uint16_t *vram, int x, int y) {
|
|
|
|
return (uint32_t)(vram + y * DISPLAY_WIDTH + x);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uint32_t vramOffsetRGB888(uint8_t *vram, int x, int y) {
|
|
|
|
return (uint32_t)(vram + (y * DISPLAY_WIDTH + x) * 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uint32_t vramOffset(uint32_t *vram, int x, int y) {
|
|
|
|
return (uint32_t)(vram + y * DISPLAY_WIDTH + x);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillRect(uint16_t *dst, int x, int y, int width, int height, uint16_t color) {
|
|
|
|
if (g_opacity == 255) {
|
|
|
|
hdma2d.Init.Mode = DMA2D_R2M;
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
|
|
|
hdma2d.Init.OutputOffset = DISPLAY_WIDTH - width;
|
|
|
|
|
|
|
|
uint32_t colorBGRA;
|
|
|
|
uint8_t *pcolorBGRA = (uint8_t *)&colorBGRA;
|
|
|
|
pcolorBGRA[0] = COLOR_TO_B(color);
|
|
|
|
pcolorBGRA[1] = COLOR_TO_G(color);
|
|
|
|
pcolorBGRA[2] = COLOR_TO_R(color);
|
|
|
|
pcolorBGRA[3] = 255;
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_Start(&hdma2d, colorBGRA, vramOffset(dst, x, y), width, height);
|
|
|
|
g_waitDMA = true;
|
|
|
|
} else {
|
|
|
|
// fill aux. buffer with BGRA color
|
|
|
|
uint32_t colorBGRA;
|
|
|
|
uint8_t *pcolorBGRA = (uint8_t *)&colorBGRA;
|
|
|
|
pcolorBGRA[0] = COLOR_TO_B(color);
|
|
|
|
pcolorBGRA[1] = COLOR_TO_G(color);
|
|
|
|
pcolorBGRA[2] = COLOR_TO_R(color);
|
|
|
|
pcolorBGRA[3] = g_opacity;
|
|
|
|
|
|
|
|
// blend aux. buffer with dst buffer
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M_BLEND;
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
|
|
|
hdma2d.Init.OutputOffset = DISPLAY_WIDTH - width;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[0].InputOffset = DISPLAY_WIDTH - width;
|
|
|
|
hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[0].InputAlpha = 0;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = DISPLAY_WIDTH - width;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_A8;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = colorBGRA;
|
|
|
|
|
|
|
|
auto dstOffset = vramOffset(dst, x, y);
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
|
|
|
|
HAL_DMA2D_BlendingStart(&hdma2d, dstOffset, dstOffset, dstOffset, width, height);
|
|
|
|
g_waitDMA = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillRect(void *dst, int x1, int y1, int x2, int y2) {
|
|
|
|
fillRect((uint16_t *)dst, x1, y1, x2 - x1 + 1, y2 - y1 + 1, g_fc);
|
|
|
|
setDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void bitBlt(void *src, int srcBpp, uint32_t srcLineOffset, uint16_t *dst, int x, int y, int width, int height) {
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
|
|
|
hdma2d.Init.OutputOffset = DISPLAY_WIDTH - width;
|
|
|
|
|
|
|
|
if (srcBpp == 32) {
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M_BLEND;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[0].InputOffset = DISPLAY_WIDTH - width;
|
|
|
|
hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[0].InputAlpha = 0;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = srcLineOffset;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = 0;
|
|
|
|
} else if (srcBpp == 24) {
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M_PFC;
|
|
|
|
#ifndef EEZ_PLATFORM_STM32F469I_DISCO
|
|
|
|
hdma2d.Init.RedBlueSwap = DMA2D_RB_SWAP;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = srcLineOffset;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB888;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = 0;
|
|
|
|
} else {
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = srcLineOffset;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto dstOffset = vramOffset(dst, x, y);
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
|
|
|
|
if (srcBpp == 32) {
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
|
|
|
|
HAL_DMA2D_BlendingStart(&hdma2d, (uint32_t)src, dstOffset, dstOffset, width, height);
|
|
|
|
} else {
|
|
|
|
HAL_DMA2D_Start(&hdma2d, (uint32_t)src, dstOffset, width, height);
|
|
|
|
}
|
|
|
|
g_waitDMA = true;
|
|
|
|
|
|
|
|
if (srcBpp == 24) {
|
|
|
|
#ifndef EEZ_PLATFORM_STM32F469I_DISCO
|
|
|
|
hdma2d.Init.RedBlueSwap = DMA2D_RB_REGULAR;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void bitBlt(void *src, int x1, int y1, int x2, int y2) {
|
|
|
|
bitBlt(src, g_renderBuffer, x1, y1, x2, y2);
|
|
|
|
setDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void bitBlt(uint16_t *src, uint16_t *dst, int x, int y, int width, int height) {
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M;
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
|
|
|
hdma2d.Init.OutputOffset = DISPLAY_WIDTH - width;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = DISPLAY_WIDTH - width;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = 0;
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
|
|
|
|
HAL_DMA2D_Start(&hdma2d, vramOffset(src, x, y), vramOffset(dst, x, y), width, height);
|
|
|
|
g_waitDMA = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bitBltRGB888(uint16_t *src, uint8_t *dst, int x, int y, int width, int height) {
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M_PFC;
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB888;
|
|
|
|
hdma2d.Init.OutputOffset = DISPLAY_WIDTH - width;
|
|
|
|
#ifndef EEZ_PLATFORM_STM32F469I_DISCO
|
|
|
|
hdma2d.Init.RedBlueSwap = DMA2D_RB_SWAP;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = DISPLAY_WIDTH - width;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = 0;
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
|
|
|
|
HAL_DMA2D_Start(&hdma2d, vramOffset(src, x, y), vramOffsetRGB888(dst, x, y), width, height);
|
|
|
|
g_waitDMA = true;
|
|
|
|
|
|
|
|
#ifndef EEZ_PLATFORM_STM32F469I_DISCO
|
|
|
|
hdma2d.Init.RedBlueSwap = DMA2D_RB_REGULAR;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void bitBlt(void *src, void *dst, int x1, int y1, int x2, int y2) {
|
|
|
|
bitBlt((uint16_t *)src, (uint16_t *)dst, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
|
|
|
|
setDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void bitBlt(uint16_t *src, uint16_t *dst, int x, int y, int width, int height, int dstx, int dsty) {
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M;
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
|
|
|
hdma2d.Init.OutputOffset = DISPLAY_WIDTH - width;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = DISPLAY_WIDTH - width;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = 0;
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
|
|
|
|
HAL_DMA2D_Start(&hdma2d, vramOffset(src, x, y), vramOffset(dst, dstx, dsty), width, height);
|
|
|
|
g_waitDMA = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void bitBlt(void *src, void *dst, int sx, int sy, int sw, int sh, int dx, int dy, uint8_t opacity) {
|
|
|
|
if (dst == nullptr) {
|
|
|
|
dst = g_renderBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto srcOffset = vramOffset((uint16_t *)src, sx, sy);
|
|
|
|
auto dstOffset = vramOffset((uint16_t *)dst, dx, dy);
|
|
|
|
|
|
|
|
if (opacity == 255) {
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M;
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
|
|
|
hdma2d.Init.OutputOffset = DISPLAY_WIDTH - sw;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = DISPLAY_WIDTH - sw;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = 0;
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
|
|
|
|
HAL_DMA2D_Start(&hdma2d, srcOffset, dstOffset, sw, sh);
|
|
|
|
g_waitDMA = true;
|
|
|
|
} else {
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M_BLEND;
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
|
|
|
hdma2d.Init.OutputOffset = DISPLAY_WIDTH - sw;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[0].InputOffset = DISPLAY_WIDTH - sw;
|
|
|
|
hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[0].AlphaMode = DMA2D_COMBINE_ALPHA;
|
|
|
|
hdma2d.LayerCfg[0].InputAlpha = 0xFF;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = DISPLAY_WIDTH - sw;
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = opacity;
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
|
|
|
|
HAL_DMA2D_BlendingStart(&hdma2d, srcOffset, dstOffset, dstOffset, sw, sh);
|
|
|
|
g_waitDMA = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void startPixelsDraw() {
|
|
|
|
DMA2D_WAIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawPixel(int x, int y) {
|
|
|
|
*(g_renderBuffer + y * DISPLAY_WIDTH + x) = g_fc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawPixel(int x, int y, uint8_t opacity) {
|
|
|
|
auto dest = g_renderBuffer + y * DISPLAY_WIDTH + x;
|
|
|
|
*dest = color32to16(
|
|
|
|
blendColor(
|
|
|
|
color16to32(g_fc, opacity),
|
|
|
|
color16to32(*dest, 255 - opacity)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void endPixelsDraw() {
|
|
|
|
setDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillRect(int x1, int y1, int x2, int y2) {
|
|
|
|
fillRect(g_renderBuffer, x1, y1, x2 - x1 + 1, y2 - y1 + 1, g_fc);
|
|
|
|
|
|
|
|
setDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void bitBlt(int x1, int y1, int x2, int y2, int dstx, int dsty) {
|
|
|
|
bitBlt(g_renderBuffer, g_renderBuffer, x1, y1, x2-x1+1, y2-y1+1, dstx, dsty);
|
|
|
|
|
|
|
|
setDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawBitmap(Image *image, int x, int y) {
|
|
|
|
bitBlt(image->pixels, image->bpp, image->lineOffset, g_renderBuffer, x, y, image->width, image->height);
|
|
|
|
|
|
|
|
setDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawStrInit() {
|
|
|
|
auto color = g_fc;
|
|
|
|
|
|
|
|
// initialize everything except lineOffset
|
|
|
|
|
|
|
|
hdma2d.Init.Mode = DMA2D_M2M_BLEND;
|
|
|
|
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
|
|
|
|
hdma2d.Init.OutputOffset = 0;
|
|
|
|
|
|
|
|
// background
|
|
|
|
hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
|
|
|
|
hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[0].InputAlpha = 0;
|
|
|
|
hdma2d.LayerCfg[0].InputOffset = 0;
|
|
|
|
|
|
|
|
// foreground
|
|
|
|
uint32_t colorBGRA;
|
|
|
|
uint8_t *pcolorBGRA = (uint8_t *)&colorBGRA;
|
|
|
|
pcolorBGRA[0] = COLOR_TO_B(color);
|
|
|
|
pcolorBGRA[1] = COLOR_TO_G(color);
|
|
|
|
pcolorBGRA[2] = COLOR_TO_R(color);
|
|
|
|
pcolorBGRA[3] = 255;
|
|
|
|
|
|
|
|
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_A8;
|
|
|
|
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
|
|
|
hdma2d.LayerCfg[1].InputAlpha = colorBGRA;
|
|
|
|
hdma2d.LayerCfg[1].InputOffset = 0;
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
HAL_DMA2D_Init(&hdma2d);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
|
|
|
|
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
|
|
|
|
g_waitDMA = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawGlyph(const uint8_t *src, uint32_t srcLineOffset, int x, int y, int width, int height) {
|
|
|
|
uint32_t lineOffset = DISPLAY_WIDTH - width;
|
|
|
|
uint32_t dst = vramOffset(g_renderBuffer, x, y);
|
|
|
|
|
|
|
|
DMA2D_WAIT;
|
|
|
|
|
|
|
|
// initialize lineOffset
|
|
|
|
WRITE_REG(hdma2d.Instance->OOR, lineOffset);
|
|
|
|
WRITE_REG(hdma2d.Instance->BGOR, lineOffset);
|
|
|
|
WRITE_REG(hdma2d.Instance->FGOR, srcLineOffset);
|
|
|
|
|
|
|
|
HAL_DMA2D_BlendingStart(&hdma2d, (uint32_t)src, dst, dst, width, height);
|
|
|
|
g_waitDMA = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace display
|
|
|
|
} // namespace gui
|
|
|
|
} // namespace eez
|