/* USER CODE BEGIN Header */ /** ****************************************************************************** * File Name : TouchGFXHAL.cpp ****************************************************************************** * This file was created by TouchGFX Generator 4.24.0. This file is only * generated once! Delete this file from your project and re-generate code * using STM32CubeMX or change this file manually to update it. ****************************************************************************** * @attention * * Copyright (c) 2024 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. * ****************************************************************************** */ /* USER CODE END Header */ #include /* USER CODE BEGIN TouchGFXHAL.cpp */ #include #include "gui/touchgfx_config.h" #include "main.h" void initLCD(void); void setLCDwindow(uint32_t Xpos, uint32_t Ypos, uint32_t Xwidth, uint32_t Ywidth); extern "C" { void LCD_IO_WriteReg(uint8_t Reg); //defined in TouchGFXGeneratedHAL.cpp void LCD_IO_WriteData(uint16_t RegValue); //defined in TouchGFXGeneratedHAL.cpp } using namespace touchgfx; void TOUCHGFXHAL_signalVSync() { // Wrapper for triggering VSync OSWrappers::signalVSync(); // Trigger vSync } void TouchGFXHAL::initialize() { // Calling parent implementation of initialize(). // // To overwrite the generated implementation, omit the call to the parent function // and implement the needed functionality here. // Please note, HAL::initialize() must be called to initialize the framework. initLCD(); TouchGFXGeneratedHAL::initialize(); } /** * Gets the frame buffer address used by the TFT controller. * * @return The address of the frame buffer currently being displayed on the TFT. */ uint16_t* TouchGFXHAL::getTFTFrameBuffer() const { // Calling parent implementation of getTFTFrameBuffer(). // // To overwrite the generated implementation, omit the call to the parent function // and implement the needed functionality here. return TouchGFXGeneratedHAL::getTFTFrameBuffer(); } /** * Sets the frame buffer address used by the TFT controller. * * @param [in] address New frame buffer address. */ void TouchGFXHAL::setTFTFrameBuffer(uint16_t* address) { // Calling parent implementation of setTFTFrameBuffer(uint16_t* address). // // To overwrite the generated implementation, omit the call to the parent function // and implement the needed functionality here. TouchGFXGeneratedHAL::setTFTFrameBuffer(address); } /** * This function is called whenever the framework has performed a partial draw. * * @param rect The area of the screen that has been drawn, expressed in absolute coordinates. * * @see flushFrameBuffer(). */ void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect) { // Calling parent implementation of flushFrameBuffer(const touchgfx::Rect& rect). // // To overwrite the generated implementation, omit the call to the parent function // and implement the needed functionality here. // Please note, HAL::flushFrameBuffer(const touchgfx::Rect& rect) must // be called to notify the touchgfx framework that flush has been performed. // To calculate the start address of rect, // use advanceFrameBufferToRect(uint8_t* fbPtr, const touchgfx::Rect& rect) // defined in TouchGFXGeneratedHAL.cpp uint16_t* frameBuffer = getTFTFrameBuffer(); setLCDwindow(rect.x, rect.y, rect.width, rect.height); LCD_IO_WriteReg(RAMWR); int32_t YxWIDTH; for (int32_t y = rect.y; y < rect.bottom(); y++) { YxWIDTH = y * TFT_WIDTH; for (int32_t x = rect.x; x < rect.right(); x++) { LCD_IO_WriteData(frameBuffer[YxWIDTH + x]); } } TouchGFXGeneratedHAL::flushFrameBuffer(rect); } bool TouchGFXHAL::blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes) { return TouchGFXGeneratedHAL::blockCopy(dest, src, numBytes); } /** * Configures the interrupts relevant for TouchGFX. This primarily entails setting * the interrupt priorities for the DMA and LCD interrupts. */ void TouchGFXHAL::configureInterrupts() { // Calling parent implementation of configureInterrupts(). // // To overwrite the generated implementation, omit the call to the parent function // and implement the needed functionality here. TouchGFXGeneratedHAL::configureInterrupts(); } /** * Used for enabling interrupts set in configureInterrupts() */ void TouchGFXHAL::enableInterrupts() { // Calling parent implementation of enableInterrupts(). // // To overwrite the generated implementation, omit the call to the parent function // and implement the needed functionality here. TouchGFXGeneratedHAL::enableInterrupts(); } /** * Used for disabling interrupts set in configureInterrupts() */ void TouchGFXHAL::disableInterrupts() { // Calling parent implementation of disableInterrupts(). // // To overwrite the generated implementation, omit the call to the parent function // and implement the needed functionality here. TouchGFXGeneratedHAL::disableInterrupts(); } /** * Configure the LCD controller to fire interrupts at VSYNC. Called automatically * once TouchGFX initialization has completed. */ void TouchGFXHAL::enableLCDControllerInterrupt() { // Calling parent implementation of enableLCDControllerInterrupt(). // // To overwrite the generated implementation, omit the call to the parent function // and implement the needed functionality here. TouchGFXGeneratedHAL::enableLCDControllerInterrupt(); } bool TouchGFXHAL::beginFrame() { return TouchGFXGeneratedHAL::beginFrame(); } void TouchGFXHAL::endFrame() { TouchGFXGeneratedHAL::endFrame(); } // ========================== ST7789 DRIVER HELPER FUNCTIONS ======================================= void setLCDwindow(uint32_t Xpos, uint32_t Ypos, uint32_t Xwidth, uint32_t Ywidth) { // set pixel x pos: LCD_IO_WriteReg(CASET); LCD_IO_WriteData(Xpos >> 8); /* XS[15:8] */ LCD_IO_WriteData((uint8_t)Xpos); /* XS[7:0] */ LCD_IO_WriteData((Xpos + Xwidth - 1) >> 8); /* XE[15:8] */ LCD_IO_WriteData((uint8_t)(Xpos + Xwidth - 1)); /* XE[7:0] */ // set pixel y pos: LCD_IO_WriteReg(RASET); LCD_IO_WriteData(Ypos >> 8); /* YS[15:8] */ LCD_IO_WriteData((uint8_t)Ypos); /* YS[7:0] */ LCD_IO_WriteData((Ypos + Ywidth - 1) >> 8); /* YE[15:8] */ LCD_IO_WriteData((uint8_t)(Ypos + Ywidth - 1)); /* YE[7:0] */ } void initLCD(void) { /* Reset ST7789H2 */ HAL_GPIO_WritePin(DISP_RST_GPIO_Port, DISP_RST_Pin, GPIO_PIN_RESET); HAL_Delay(100); /* wait at least 10us according ST7789H2 datasheet */ HAL_GPIO_WritePin(DISP_RST_GPIO_Port, DISP_RST_Pin, GPIO_PIN_SET); HAL_Delay(100); /* wait maximum 120ms according ST7789H2 datasheet */ LCD_IO_WriteReg(SLPOUT); HAL_Delay(100); //MADCTL: memory data access control LCD_IO_WriteReg(MADCTL); LCD_IO_WriteData(MX+MV); //COLMOD: Interface Pixel format *** I use 262K-colors in 16bit/pixel (RGB565) format when using 16-bit parallel interface to allow 2-bytes per pixel LCD_IO_WriteReg(COLMOD); LCD_IO_WriteData(RGB_COL_FORMAT_65K + RGB_INTF_16BIT); //INVON: Display Inversion ON (setting for IPS) LCD_IO_WriteReg(INVON); //PORCTRK: Porch setting LCD_IO_WriteReg(PORCTRL); LCD_IO_WriteData(0x0C); LCD_IO_WriteData(0x0C); LCD_IO_WriteData(0x00); LCD_IO_WriteData(0x33); LCD_IO_WriteData(0x33); //GCTRL: Gate Control LCD_IO_WriteReg(GCTRL); LCD_IO_WriteData(0x35); //VCOMS: VCOM setting LCD_IO_WriteReg(VCOMS); LCD_IO_WriteData(0x2B); //LCMCTRL: LCM Control LCD_IO_WriteReg(LCMCTRL); LCD_IO_WriteData(0x2C); //VDVVRHEN: VDV and VRH Command Enable LCD_IO_WriteReg(VDVVRHEN); LCD_IO_WriteData(0x01); LCD_IO_WriteData(0xFF); //VRHS: VRH Set LCD_IO_WriteReg(VRHS); LCD_IO_WriteData(0x11); //VDVS: VDV Set LCD_IO_WriteReg(VDVS); LCD_IO_WriteData(0x20); //FRCTRL2: Frame Rate control in normal mode LCD_IO_WriteReg(FRCTRL2); LCD_IO_WriteData(0x0F); //PWCTRL1: Power Control 1 LCD_IO_WriteReg(PWRCTRL1); LCD_IO_WriteData(0xA4); LCD_IO_WriteData(0xA1); //PVGAMCTRL: Positive Voltage Gamma control LCD_IO_WriteReg(PVGAMCTRL); LCD_IO_WriteData(0xD0); LCD_IO_WriteData(0x00); LCD_IO_WriteData(0x05); LCD_IO_WriteData(0x0E); LCD_IO_WriteData(0x15); LCD_IO_WriteData(0x0D); LCD_IO_WriteData(0x37); LCD_IO_WriteData(0x43); LCD_IO_WriteData(0x47); LCD_IO_WriteData(0x09); LCD_IO_WriteData(0x15); LCD_IO_WriteData(0x12); LCD_IO_WriteData(0x16); LCD_IO_WriteData(0x19); //NVGAMCTRL: Negative Voltage Gamma control LCD_IO_WriteReg(NVGAMCTRL); LCD_IO_WriteData(0xD0); LCD_IO_WriteData(0x00); LCD_IO_WriteData(0x05); LCD_IO_WriteData(0x0D); LCD_IO_WriteData(0x0C); LCD_IO_WriteData(0x06); LCD_IO_WriteData(0x2D); LCD_IO_WriteData(0x44); LCD_IO_WriteData(0x40); LCD_IO_WriteData(0x0E); LCD_IO_WriteData(0x1C); LCD_IO_WriteData(0x18); LCD_IO_WriteData(0x16); LCD_IO_WriteData(0x19); //X address set LCD_IO_WriteReg(CASET); LCD_IO_WriteData(0x00); LCD_IO_WriteData(0x00); LCD_IO_WriteData(0x01); LCD_IO_WriteData(0x3F); //Y address set LCD_IO_WriteReg(RASET); LCD_IO_WriteData(0x00); LCD_IO_WriteData(0x00); LCD_IO_WriteData(0x00); LCD_IO_WriteData(0xEF); // Write to display ram LCD_IO_WriteReg(RAMWR); // // Set all pixels to black // for (int32_t y = 0; y < TFT_HEIGHT; y++) { // for (int32_t x = 0; x < TFT_WIDTH; x++) { // // LCD_IO_WriteData(0xF800); // } // } /* Display on */ LCD_IO_WriteReg(DISPON); /* Display on */ LCD_IO_WriteReg(DISPON); // DMA2D setup hdma2d.Init.Mode = DMA2D_R2M; // Register-to-Memory mode hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565; // Output format is RGB565 hdma2d.Init.OutputOffset = 0; // No offset for a full screen fill if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) { // Handle initialization error Error_Handler(); } uint32_t outputAddress = (uint32_t)FMC_BANK1_MEM; uint32_t color = 0x07E0; // Green in RGB565 format // Start the DMA2D transfer if (HAL_DMA2D_Start(&hdma2d, color, outputAddress, TFT_WIDTH, TFT_HEIGHT) != HAL_OK) { // Handle transfer start error Error_Handler(); } // Wait for the transfer to complete if (HAL_DMA2D_PollForTransfer(&hdma2d, 1000) != HAL_OK) { // Handle timeout or error Error_Handler(); } } /* USER CODE END TouchGFXHAL.cpp */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/