/* * 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); }