Files
edgetx-gx12/radio/src/targets/common/arm/stm32/dma2d.cpp
T

207 lines
6.8 KiB
C++

/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include "stm32_hal_ll.h"
#include "definitions.h"
#include "libopenui_defines.h"
#include "dma2d.h"
#if !LV_USE_GPU_STM32_DMA2D
/**
* Turn on the peripheral and set output color mode, this only needs to be done once
*
* Copied from LVGL code
*/
void DMAInit(void)
{
// Enable DMA2D clock
#if defined(STM32F4) || defined(STM32F7) || defined(STM32U5)
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN; // enable DMA2D
// wait for hardware access to complete
__asm volatile("DSB\n");
volatile uint32_t temp = RCC->AHB1ENR;
LV_UNUSED(temp);
#elif defined(STM32H7)
RCC->AHB3ENR |= RCC_AHB3ENR_DMA2DEN;
// wait for hardware access to complete
__asm volatile("DSB\n");
volatile uint32_t temp = RCC->AHB3ENR;
LV_UNUSED(temp);
#else
# warning "LVGL can't enable the clock of DMA2D"
#endif
// AHB master timer configuration
DMA2D->AMTCR = 0; // AHB bus guaranteed dead time disabled
}
#endif
void DMACopyBitmap(uint16_t *dest, uint16_t destw, uint16_t desth, uint16_t x,
uint16_t y, const uint16_t *src, uint16_t srcw,
uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w,
uint16_t h)
{
DMAWait();
#if __CORTEX_M >= 0x07
SCB_CleanInvalidateDCache();
#endif
LL_DMA2D_DeInit(DMA2D);
LL_DMA2D_InitTypeDef DMA2D_InitStruct;
LL_DMA2D_StructInit(&DMA2D_InitStruct);
DMA2D_InitStruct.Mode = LL_DMA2D_MODE_M2M;
DMA2D_InitStruct.ColorMode = LL_DMA2D_OUTPUT_MODE_RGB565;
DMA2D_InitStruct.OutputMemoryAddress = CONVERT_PTR_UINT(dest + y*destw + x);
DMA2D_InitStruct.LineOffset = destw - w;
DMA2D_InitStruct.NbrOfLines = h;
DMA2D_InitStruct.NbrOfPixelsPerLines = w;
LL_DMA2D_Init(DMA2D, &DMA2D_InitStruct);
LL_DMA2D_FGND_SetMemAddr(DMA2D, CONVERT_PTR_UINT(src + srcy*srcw + srcx));
LL_DMA2D_FGND_SetLineOffset(DMA2D, srcw - w);
LL_DMA2D_FGND_SetColorMode(DMA2D, LL_DMA2D_INPUT_MODE_RGB565);
LL_DMA2D_FGND_SetAlphaMode(DMA2D, LL_DMA2D_ALPHA_MODE_NO_MODIF);
LL_DMA2D_FGND_SetAlpha(DMA2D, 0);
/* Start Transfer */
LL_DMA2D_Start(DMA2D);
}
void DMACopyAlphaBitmap(uint16_t *dest, uint16_t destw, uint16_t desth,
uint16_t x, uint16_t y, const uint16_t *src,
uint16_t srcw, uint16_t srch, uint16_t srcx,
uint16_t srcy, uint16_t w, uint16_t h)
{
DMAWait();
#if __CORTEX_M >= 0x07
SCB_CleanInvalidateDCache();
#endif
LL_DMA2D_DeInit(DMA2D);
LL_DMA2D_InitTypeDef DMA2D_InitStruct;
LL_DMA2D_StructInit(&DMA2D_InitStruct);
DMA2D_InitStruct.Mode = LL_DMA2D_MODE_M2M_BLEND;
DMA2D_InitStruct.ColorMode = LL_DMA2D_OUTPUT_MODE_RGB565;
DMA2D_InitStruct.OutputMemoryAddress = CONVERT_PTR_UINT(dest + y*destw + x);
DMA2D_InitStruct.LineOffset = destw - w;
DMA2D_InitStruct.NbrOfLines = h;
DMA2D_InitStruct.NbrOfPixelsPerLines = w;
LL_DMA2D_Init(DMA2D, &DMA2D_InitStruct);
LL_DMA2D_FGND_SetMemAddr(DMA2D, CONVERT_PTR_UINT(src + srcy*srcw + srcx));
LL_DMA2D_FGND_SetLineOffset(DMA2D, srcw - w);
LL_DMA2D_FGND_SetColorMode(DMA2D, LL_DMA2D_INPUT_MODE_ARGB4444);
LL_DMA2D_FGND_SetAlphaMode(DMA2D, LL_DMA2D_ALPHA_MODE_NO_MODIF);
LL_DMA2D_FGND_SetAlpha(DMA2D, 0);
LL_DMA2D_BGND_SetMemAddr(DMA2D, CONVERT_PTR_UINT(dest + y*destw + x));
LL_DMA2D_BGND_SetLineOffset(DMA2D, destw - w);
LL_DMA2D_BGND_SetColorMode(DMA2D, LL_DMA2D_OUTPUT_MODE_RGB565);
LL_DMA2D_BGND_SetAlphaMode(DMA2D, LL_DMA2D_ALPHA_MODE_NO_MODIF);
LL_DMA2D_BGND_SetAlpha(DMA2D, 0);
/* Start Transfer */
LL_DMA2D_Start(DMA2D);
}
// same as DMACopyAlphaBitmap(), but with an 8 bit mask for each pixel (used by fonts)
void DMACopyAlphaMask(uint16_t *dest, uint16_t destw, uint16_t desth,
uint16_t x, uint16_t y, const uint8_t *src, uint16_t srcw,
uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w,
uint16_t h, uint16_t bg_color)
{
DMAWait();
#if __CORTEX_M >= 0x07
SCB_CleanInvalidateDCache();
#endif
LL_DMA2D_DeInit(DMA2D);
LL_DMA2D_InitTypeDef DMA2D_InitStruct;
LL_DMA2D_StructInit(&DMA2D_InitStruct);
DMA2D_InitStruct.Mode = LL_DMA2D_MODE_M2M_BLEND;
DMA2D_InitStruct.ColorMode = LL_DMA2D_OUTPUT_MODE_RGB565;
DMA2D_InitStruct.OutputMemoryAddress = CONVERT_PTR_UINT(dest + y*destw + x);
DMA2D_InitStruct.LineOffset = destw - w;
DMA2D_InitStruct.NbrOfLines = h;
DMA2D_InitStruct.NbrOfPixelsPerLines = w;
LL_DMA2D_Init(DMA2D, &DMA2D_InitStruct);
LL_DMA2D_FGND_SetMemAddr(DMA2D, CONVERT_PTR_UINT(src + srcy*srcw + srcx));
LL_DMA2D_FGND_SetLineOffset(DMA2D, srcw - w);
LL_DMA2D_FGND_SetColorMode(DMA2D, LL_DMA2D_INPUT_MODE_A8);
LL_DMA2D_FGND_SetAlphaMode(DMA2D, LL_DMA2D_ALPHA_MODE_NO_MODIF);
LL_DMA2D_FGND_SetAlpha(DMA2D, 0);
LL_DMA2D_FGND_SetRedColor(DMA2D, GET_RED(bg_color)); // 8 bit red
LL_DMA2D_FGND_SetGreenColor(DMA2D, GET_GREEN(bg_color)); // 8 bit green
LL_DMA2D_FGND_SetBlueColor(DMA2D, GET_BLUE(bg_color)); // 8 bit blue
LL_DMA2D_BGND_SetMemAddr(DMA2D, CONVERT_PTR_UINT(dest + y*destw + x));
LL_DMA2D_BGND_SetLineOffset(DMA2D, destw - w);
LL_DMA2D_BGND_SetColorMode(DMA2D, LL_DMA2D_OUTPUT_MODE_RGB565);
LL_DMA2D_BGND_SetAlphaMode(DMA2D, LL_DMA2D_ALPHA_MODE_NO_MODIF);
LL_DMA2D_BGND_SetAlpha(DMA2D, 0);
/* Start Transfer */
LL_DMA2D_Start(DMA2D);
}
void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format)
{
DMAWait();
#if __CORTEX_M >= 0x07
SCB_CleanInvalidateDCache();
#endif
LL_DMA2D_DeInit(DMA2D);
LL_DMA2D_InitTypeDef DMA2D_InitStruct;
LL_DMA2D_StructInit(&DMA2D_InitStruct);
DMA2D_InitStruct.Mode = LL_DMA2D_MODE_M2M_PFC;
DMA2D_InitStruct.ColorMode = format;
DMA2D_InitStruct.OutputMemoryAddress = CONVERT_PTR_UINT(dest);
DMA2D_InitStruct.NbrOfLines = h;
DMA2D_InitStruct.NbrOfPixelsPerLines = w;
LL_DMA2D_Init(DMA2D, &DMA2D_InitStruct);
LL_DMA2D_FGND_SetMemAddr(DMA2D, CONVERT_PTR_UINT(src));
LL_DMA2D_FGND_SetLineOffset(DMA2D, 0);
LL_DMA2D_FGND_SetColorMode(DMA2D, LL_DMA2D_INPUT_MODE_ARGB8888);
LL_DMA2D_FGND_SetAlphaMode(DMA2D, LL_DMA2D_ALPHA_MODE_REPLACE);
LL_DMA2D_FGND_SetAlpha(DMA2D, 0);
/* Start Transfer */
LL_DMA2D_Start(DMA2D);
}