/** ****************************************************************************** * File Name : STM32DMA.cpp ****************************************************************************** * This file is generated by TouchGFX Generator 4.21.2. Please, do not edit! ****************************************************************************** * @attention * * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_dma2d.h" #include #include #include #include #include #include /* Makes touchgfx specific types and variables visible to this file */ using namespace touchgfx; typedef struct { const uint16_t format; const uint16_t size; const uint32_t* const data; } clutData_t; extern "C" void DMA2D_IRQHandler() { /* Transfer Complete Interrupt management ************************************/ if ((READ_REG(DMA2D->ISR) & DMA2D_FLAG_TC) != RESET) { /* Verify Transfer Complete Interrupt */ if ((READ_REG(DMA2D->CR) & DMA2D_IT_TC) != RESET) { /* Disable the transfer complete interrupt */ DMA2D->CR &= ~(DMA2D_IT_TC); /* Clear the transfer complete flag */ DMA2D->IFCR = (DMA2D_FLAG_TC); /* Signal DMA queue of execution complete */ touchgfx::HAL::getInstance()->signalDMAInterrupt(); } } } STM32DMA::STM32DMA() : DMA_Interface(dma_queue), dma_queue(queue_storage, sizeof(queue_storage) / sizeof(queue_storage[0])) { } STM32DMA::~STM32DMA() { /* Disable DMA2D global Interrupt */ NVIC_DisableIRQ(DMA2D_IRQn); } void STM32DMA::initialize() { /* Ensure DMA2D Clock is enabled */ __HAL_RCC_DMA2D_CLK_ENABLE(); __HAL_RCC_DMA2D_FORCE_RESET(); __HAL_RCC_DMA2D_RELEASE_RESET(); /* Enable DMA2D global Interrupt */ HAL_NVIC_SetPriority(DMA2D_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA2D_IRQn); } inline uint32_t STM32DMA::getChromARTInputFormat(Bitmap::BitmapFormat format) { // Default color mode set to ARGB8888 uint32_t dma2dColorMode = DMA2D_INPUT_ARGB8888; switch (format) { case Bitmap::ARGB8888: /* DMA2D input mode set to 32bit ARGB */ dma2dColorMode = DMA2D_INPUT_ARGB8888; break; case Bitmap::RGB888: /* DMA2D input mode set to 24bit RGB */ dma2dColorMode = DMA2D_INPUT_RGB888; break; case Bitmap::RGB565: /* DMA2D input mode set to 16bit RGB */ dma2dColorMode = DMA2D_INPUT_RGB565; break; case Bitmap::ARGB2222: /* Fall through */ case Bitmap::ABGR2222: /* Fall through */ case Bitmap::RGBA2222: /* Fall through */ case Bitmap::BGRA2222: /* Fall through */ case Bitmap::L8: /* DMA2D input mode set to 8bit Color Look up table*/ dma2dColorMode = DMA2D_INPUT_L8; break; case Bitmap::BW: /* Fall through */ case Bitmap::BW_RLE: /* Fall through */ case Bitmap::GRAY4: /* Fall through */ case Bitmap::GRAY2: /* Fall through */ default: /* Unsupported input format for DMA2D */ assert(0 && "Unsupported Format!"); break; } return dma2dColorMode; } inline uint32_t STM32DMA::getChromARTOutputFormat(Bitmap::BitmapFormat format) { // Default color mode set to ARGB8888 uint32_t dma2dColorMode = DMA2D_OUTPUT_ARGB8888; switch (format) { case Bitmap::ARGB8888: /* DMA2D output mode set to 32bit ARGB */ dma2dColorMode = DMA2D_OUTPUT_ARGB8888; break; case Bitmap::RGB888: /* Fall through */ case Bitmap::ARGB2222: /* Fall through */ case Bitmap::ABGR2222: /* Fall through */ case Bitmap::RGBA2222: /* Fall through */ case Bitmap::BGRA2222: /* DMA2D output mode set to 24bit RGB */ dma2dColorMode = DMA2D_OUTPUT_RGB888; break; case Bitmap::RGB565: /* DMA2D output mode set to 16bit RGB */ dma2dColorMode = DMA2D_OUTPUT_RGB565; break; case Bitmap::L8: /* Fall through */ case Bitmap::BW: /* Fall through */ case Bitmap::BW_RLE: /* Fall through */ case Bitmap::GRAY4: /* Fall through */ case Bitmap::GRAY2: /* Fall through */ default: /* Unsupported output format for DMA2D */ assert(0 && "Unsupported Format!"); break; } return dma2dColorMode; } BlitOperations STM32DMA::getBlitCaps() { return static_cast(BLIT_OP_FILL | BLIT_OP_FILL_WITH_ALPHA | BLIT_OP_COPY | BLIT_OP_COPY_L8 | BLIT_OP_COPY_WITH_ALPHA | BLIT_OP_COPY_ARGB8888 | BLIT_OP_COPY_ARGB8888_WITH_ALPHA | BLIT_OP_COPY_A4 | BLIT_OP_COPY_A8); } /* * void STM32DMA::setupDataCopy(const BlitOp& blitOp) handles blit operation of * BLIT_OP_COPY * BLIT_OP_COPY_L8 * BLIT_OP_COPY_WITH_ALPHA * BLIT_OP_COPY_ARGB8888 * BLIT_OP_COPY_ARGB8888_WITH_ALPHA * BLIT_OP_COPY_A4 * BLIT_OP_COPY_A8 */ void STM32DMA::setupDataCopy(const BlitOp& blitOp) { uint32_t dma2dForegroundColorMode = getChromARTInputFormat(static_cast(blitOp.srcFormat)); uint32_t dma2dBackgroundColorMode = getChromARTInputFormat(static_cast(blitOp.dstFormat)); uint32_t dma2dOutputColorMode = getChromARTOutputFormat(static_cast(blitOp.dstFormat)); /* DMA2D OOR register configuration */ WRITE_REG(DMA2D->OOR, blitOp.dstLoopStride - blitOp.nSteps); /* DMA2D BGOR register configuration */ WRITE_REG(DMA2D->BGOR, blitOp.dstLoopStride - blitOp.nSteps); /* DMA2D FGOR register configuration */ WRITE_REG(DMA2D->FGOR, blitOp.srcLoopStride - blitOp.nSteps); /* DMA2D OPFCCR register configuration */ WRITE_REG(DMA2D->OPFCCR, dma2dOutputColorMode); /* Configure DMA2D data size */ WRITE_REG(DMA2D->NLR, (blitOp.nLoops | (blitOp.nSteps << DMA2D_NLR_PL_Pos))); /* Configure DMA2D destination address */ WRITE_REG(DMA2D->OMAR, reinterpret_cast(blitOp.pDst)); /* Configure DMA2D source address */ WRITE_REG(DMA2D->FGMAR, reinterpret_cast(blitOp.pSrc)); switch (blitOp.operation) { case BLIT_OP_COPY_A4: /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_A4 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24)); /* set DMA2D foreground color */ WRITE_REG(DMA2D->FGCOLR, blitOp.color); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(blitOp.pDst)); /* Set DMA2D mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START); break; case BLIT_OP_COPY_A8: /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_A8 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24)); /* set DMA2D foreground color */ WRITE_REG(DMA2D->FGCOLR, blitOp.color); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(blitOp.pDst)); /* Set DMA2D mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START); break; case BLIT_OP_COPY_WITH_ALPHA: /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, dma2dForegroundColorMode | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24)); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(blitOp.pDst)); /* Set DMA2D mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START); break; case BLIT_OP_COPY_L8: { bool blend = true; const clutData_t* const palette = reinterpret_cast(blitOp.pClut); /* Write foreground CLUT memory address */ WRITE_REG(DMA2D->FGCMAR, reinterpret_cast(&palette->data)); /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, dma2dForegroundColorMode | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24)); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(blitOp.pDst)); /* Configure CLUT */ switch ((Bitmap::ClutFormat)palette->format) { case Bitmap::CLUT_FORMAT_L8_ARGB8888: /* Write foreground CLUT size and CLUT color mode */ MODIFY_REG(DMA2D->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), (((palette->size - 1) << DMA2D_FGPFCCR_CS_Pos) | (DMA2D_CCM_ARGB8888 << DMA2D_FGPFCCR_CCM_Pos))); break; case Bitmap::CLUT_FORMAT_L8_RGB888: if(blitOp.alpha == 255) { blend = false; } MODIFY_REG(DMA2D->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), (((palette->size - 1) << DMA2D_FGPFCCR_CS_Pos) | (DMA2D_CCM_RGB888 << DMA2D_FGPFCCR_CCM_Pos))); break; case Bitmap::CLUT_FORMAT_L8_RGB565: default: assert(0 && "Unsupported format"); break; } /* Enable the CLUT loading for the foreground */ SET_BIT(DMA2D->FGPFCCR, DMA2D_FGPFCCR_START); while ((READ_REG(DMA2D->FGPFCCR) & DMA2D_FGPFCCR_START) != 0U) { } DMA2D->IFCR = (DMA2D_FLAG_CTC); /* Set DMA2D mode */ if(blend) { WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START); } else { WRITE_REG(DMA2D->CR, DMA2D_M2M_PFC | DMA2D_IT_TC | DMA2D_CR_START); } } break; case BLIT_OP_COPY_ARGB8888: case BLIT_OP_COPY_ARGB8888_WITH_ALPHA: /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, dma2dForegroundColorMode | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24)); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, dma2dBackgroundColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(blitOp.pDst)); /* Set DMA2D mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_IT_TC | DMA2D_CR_START); break; default: /* BLIT_OP_COPY */ /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, dma2dForegroundColorMode | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (blitOp.alpha << 24)); /* Perform pixel-format-conversion (PFC) If Bitmap format is not same format as framebuffer format */ if (blitOp.srcFormat != blitOp.dstFormat) { /* Start DMA2D : PFC Mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_PFC | DMA2D_IT_TC | DMA2D_CR_START); } else { /* Start DMA2D : M2M Mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M | DMA2D_IT_TC | DMA2D_CR_START); } break; } } /* * void STM32DMA::setupDataFill(const BlitOp& blitOp) handles blit operation of * BLIT_OP_FILL * BLIT_OP_FILL_WITH_ALPHA */ void STM32DMA::setupDataFill(const BlitOp& blitOp) { uint32_t dma2dOutputColorMode = getChromARTOutputFormat(static_cast(blitOp.dstFormat)); /* DMA2D OPFCCR register configuration */ WRITE_REG(DMA2D->OPFCCR, dma2dOutputColorMode); /* Configure DMA2D data size */ WRITE_REG(DMA2D->NLR, (blitOp.nLoops | (blitOp.nSteps << DMA2D_NLR_PL_Pos))); /* Configure DMA2D destination address */ WRITE_REG(DMA2D->OMAR, reinterpret_cast(blitOp.pDst)); /* DMA2D OOR register configuration */ WRITE_REG(DMA2D->OOR, blitOp.dstLoopStride - blitOp.nSteps); if (blitOp.operation == BLIT_OP_FILL_WITH_ALPHA) { /* DMA2D BGOR register configuration */ WRITE_REG(DMA2D->BGOR, blitOp.dstLoopStride - blitOp.nSteps); /* DMA2D FGOR register configuration */ WRITE_REG(DMA2D->FGOR, blitOp.dstLoopStride - blitOp.nSteps); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, dma2dOutputColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Write DMA2D FGPFCCR register */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_A8 | (DMA2D_REPLACE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | ((blitOp.alpha << 24) & DMA2D_FGPFCCR_ALPHA)); /* DMA2D FGCOLR register configuration */ WRITE_REG(DMA2D->FGCOLR, blitOp.color); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(blitOp.pDst)); /* Configure DMA2D source address */ WRITE_REG(DMA2D->FGMAR, reinterpret_cast(blitOp.pDst)); /* Enable the Peripheral and Enable the transfer complete interrupt */ WRITE_REG(DMA2D->CR, (DMA2D_IT_TC | DMA2D_CR_START | DMA2D_M2M_BLEND)); } else { /* Write DMA2D FGPFCCR register */ WRITE_REG(DMA2D->FGPFCCR, dma2dOutputColorMode | (DMA2D_NO_MODIF_ALPHA << DMA2D_FGPFCCR_AM_Pos)); /* DMA2D FGOR register configuration */ WRITE_REG(DMA2D->FGOR, 0); /* Set color */ WRITE_REG(DMA2D->OCOLR, ((blitOp.color >> 8) & 0xF800) | ((blitOp.color >> 5) & 0x07E0) | ((blitOp.color >> 3) & 0x001F)); /* Enable the Peripheral and Enable the transfer complete interrupt */ WRITE_REG(DMA2D->CR, (DMA2D_IT_TC | DMA2D_CR_START | DMA2D_R2M)); } } namespace touchgfx { namespace paint { namespace { const clutData_t* L8CLUT = 0; uint32_t L8ClutLoaded = 0; } // namespace void setL8Pallette(const uint8_t* const data) { L8CLUT = reinterpret_cast(data - offsetof(clutData_t, data)); L8ClutLoaded = 0; } /** * @fn void tearDown(); * * @brief Waits until previous DMA drawing operation has finished */ void tearDown() { /* Wait for DMA2D to finish last run */ while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U); /* Clear transfer flags */ WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC | DMA2D_FLAG_CE | DMA2D_FLAG_TE); } namespace rgb565 { /** * @fn void lineFromColor(); * * @brief Renders Canvas Widget chunks using DMA. * This functions will not generate an interrupt, and will not affect the DMA queue. */ void lineFromColor(uint16_t* const ptr, const unsigned count, const uint32_t color, const uint8_t alpha, const uint32_t color565) { /* Wait for DMA2D to finish last run */ while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U); /* Clear transfer flags */ WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC | DMA2D_FLAG_CE | DMA2D_FLAG_TE); /* DMA2D OPFCCR register configuration */ WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565); /* Configure DMA2D data size */ WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos))); /* Configure DMA2D destination address */ WRITE_REG(DMA2D->OMAR, reinterpret_cast(ptr)); if (alpha < 0xFF) { /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, DMA2D_OUTPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Write DMA2D FGPFCCR register */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_A8 | (DMA2D_REPLACE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | ((alpha << 24) & DMA2D_FGPFCCR_ALPHA)); /* DMA2D FGCOLR register configuration */ WRITE_REG(DMA2D->FGCOLR, color); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, (uint32_t)ptr); /* Configure DMA2D source address */ WRITE_REG(DMA2D->FGMAR, (uint32_t)ptr); /* Enable the Peripheral and Enable the transfer complete interrupt */ WRITE_REG(DMA2D->CR, (DMA2D_CR_START | DMA2D_M2M_BLEND)); } else { /* Write DMA2D FGPFCCR register */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_OUTPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_FGPFCCR_AM_Pos)); /* Set color */ WRITE_REG(DMA2D->OCOLR, color565); /* Enable the Peripheral and Enable the transfer complete interrupt */ WRITE_REG(DMA2D->CR, (DMA2D_CR_START | DMA2D_R2M)); } } void lineFromRGB565(uint16_t* const ptr, const uint16_t* const data, const unsigned count, const uint8_t alpha) { /* Wait for DMA2D to finish last run */ while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U); /* Clear transfer flags */ WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC | DMA2D_FLAG_CE | DMA2D_FLAG_TE); /* DMA2D OPFCCR register configuration */ WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565); /* Configure DMA2D data size */ WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos))); /* Configure DMA2D destination address */ WRITE_REG(DMA2D->OMAR, reinterpret_cast(ptr)); /* Configure DMA2D source address */ WRITE_REG(DMA2D->FGMAR, reinterpret_cast(data)); if (alpha < 0xFF) { /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (alpha << 24)); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(ptr)); /* Set DMA2D mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_CR_START); } else { /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_COMBINE_ALPHA << DMA2D_FGPFCCR_AM_Pos) | (alpha << 24)); /* Start DMA2D : M2M Mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M | DMA2D_CR_START); } } void lineFromARGB8888(uint16_t* const ptr, const uint32_t* const data, const unsigned count, const uint8_t alpha) { /* Wait for DMA2D to finish last run */ while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U); /* Clear transfer flags */ WRITE_REG(DMA2D->IFCR, DMA2D_FLAG_TC | DMA2D_FLAG_CE | DMA2D_FLAG_TE); /* DMA2D OPFCCR register configuration */ WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565); /* Configure DMA2D data size */ WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos))); /* Configure DMA2D destination address */ WRITE_REG(DMA2D->OMAR, reinterpret_cast(ptr)); /* Configure DMA2D source address */ WRITE_REG(DMA2D->FGMAR, reinterpret_cast(data)); /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_ARGB8888 | (DMA2D_COMBINE_ALPHA << DMA2D_BGPFCCR_AM_Pos) | (alpha << 24)); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(ptr)); /* Set DMA2D mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_CR_START); } void lineFromL8RGB888(uint16_t* const ptr, const uint8_t* const data, const unsigned count, const uint8_t alpha) { /* wait for DMA2D to finish last run */ while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U); /* DMA2D OPFCCR register configuration */ WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565); /* Configure DMA2D data size */ WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos))); /* Configure DMA2D destination address */ WRITE_REG(DMA2D->OMAR, reinterpret_cast(ptr)); /* Configure DMA2D source address */ WRITE_REG(DMA2D->FGMAR, reinterpret_cast(data)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(ptr)); /* Load CLUT if not already loaded */ if (L8ClutLoaded == 0) { /* Write foreground CLUT memory address */ WRITE_REG(DMA2D->FGCMAR, reinterpret_cast(&L8CLUT->data)); /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_L8 | (DMA2D_COMBINE_ALPHA << DMA2D_BGPFCCR_AM_Pos) | (alpha << 24)); MODIFY_REG(DMA2D->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), (((L8CLUT->size - 1) << DMA2D_FGPFCCR_CS_Pos) | (DMA2D_CCM_RGB888 << DMA2D_FGPFCCR_CCM_Pos))); /* Enable the CLUT loading for the foreground */ SET_BIT(DMA2D->FGPFCCR, DMA2D_FGPFCCR_START); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Mark CLUT loaded */ L8ClutLoaded = 1; /* Wait for load to finish */ while ((READ_REG(DMA2D->FGPFCCR) & DMA2D_FGPFCCR_START) != 0U); /* Clear CLUT Transfer Complete flag */ DMA2D->IFCR = (DMA2D_FLAG_CTC); } else { /* Set correct alpha for these pixels */ MODIFY_REG(DMA2D->FGPFCCR, DMA2D_BGPFCCR_ALPHA_Msk, alpha << 24); } /* Start pixel transfer in correct mode */ if (alpha < 0xFF) { /* Set DMA2D mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_CR_START); } else { /* Set DMA2D mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_PFC | DMA2D_CR_START); } } void lineFromL8ARGB8888(uint16_t* const ptr, const uint8_t* const data, const unsigned count, const uint8_t alpha) { /* wait for DMA2D to finish last run */ while ((READ_REG(DMA2D->CR) & DMA2D_CR_START) != 0U); /* DMA2D OPFCCR register configuration */ WRITE_REG(DMA2D->OPFCCR, DMA2D_OUTPUT_RGB565); /* Configure DMA2D data size */ WRITE_REG(DMA2D->NLR, (1 | (count << DMA2D_NLR_PL_Pos))); /* Configure DMA2D destination address */ WRITE_REG(DMA2D->OMAR, reinterpret_cast(ptr)); /* Configure DMA2D source address */ WRITE_REG(DMA2D->FGMAR, reinterpret_cast(data)); /* Configure DMA2D Stream source2 address */ WRITE_REG(DMA2D->BGMAR, reinterpret_cast(ptr)); /* Load CLUT if not already loaded */ if (L8ClutLoaded == 0) { /* Write foreground CLUT memory address */ WRITE_REG(DMA2D->FGCMAR, reinterpret_cast(&L8CLUT->data)); /* Set DMA2D color mode and alpha mode */ WRITE_REG(DMA2D->FGPFCCR, DMA2D_INPUT_L8 | (DMA2D_COMBINE_ALPHA << DMA2D_BGPFCCR_AM_Pos) | (alpha << 24)); MODIFY_REG(DMA2D->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), (((L8CLUT->size - 1) << DMA2D_FGPFCCR_CS_Pos) | (DMA2D_CCM_ARGB8888 << DMA2D_FGPFCCR_CCM_Pos))); /* Enable the CLUT loading for the foreground */ SET_BIT(DMA2D->FGPFCCR, DMA2D_FGPFCCR_START); /* Write DMA2D BGPFCCR register */ WRITE_REG(DMA2D->BGPFCCR, DMA2D_INPUT_RGB565 | (DMA2D_NO_MODIF_ALPHA << DMA2D_BGPFCCR_AM_Pos)); /* Mark CLUT loaded */ L8ClutLoaded = 1; /* Wait for load to finish */ while ((READ_REG(DMA2D->FGPFCCR) & DMA2D_FGPFCCR_START) != 0U); /* Clear CLUT Transfer Complete flag */ DMA2D->IFCR = (DMA2D_FLAG_CTC); } else { /* Set correct alpha for these pixels */ MODIFY_REG(DMA2D->FGPFCCR, DMA2D_BGPFCCR_ALPHA_Msk, alpha << 24); } /* Start pixel transfer in blending mode */ WRITE_REG(DMA2D->CR, DMA2D_M2M_BLEND | DMA2D_CR_START); } } // namespace rgb565 } // namespace paint } // namespace touchgfx /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/