2024-07-26 04:04 AM - edited 2024-07-26 04:09 AM
So I'm using an ST7789VI display connected to a STM32L4R9I-DISCO board. I've made some test projects in CubeIDE without using TouchGFX to ensure that the driver file and everything else was correct. However, when I try to integrate TouchGFX designs, I get misalignment and a bit of distortion. At first, I thought it was an issue with how I'm transmitting the data, but I did some debugging and I noticed that the Framebuf was being populated incorrectly i.e. the pixel "values" were incorrect in the areas I'm getting distortion- so not a transmission error. I'm still unsure what's causing the misalignment. Could someone help me out? I'll attach the flushframebuffer function, where i defined FrameBuf in TouchGFXGeneratedHAL and the dedicated memory spot in the linker files for the framebuffer.
EDIT: I've also tested with solid colors using the flushframebuffer function and I do get the correct output.
//How frameBuf is defined in TouchGFXGeneratedHAL.cpp
LOCATION_PRAGMA_NOLOAD(".TouchGFX_Framebuffer")
__attribute__((aligned(8))) uint16_t frameBuf[(320 * 240)] LOCATION_ATTRIBUTE_NOLOAD(".TouchGFX_Framebuffer");
//FrameBuffer in linker (memory)
/* TouchGFX Framebuffer section */
.TouchGFX_Framebuffer (NOLOAD):
{
. = ALIGN(8);
*(.TouchGFX_Framebuffer)
. = ALIGN(8);
} >RAM
//TouchGFXBridge.cpp
// TouchGFXBridge.cpp
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32l4xx_hal.h"
#include "stm32l4xx_hal_gpio.h"
#include "ST7789VI.h"
#include "main.h"
#ifdef __cplusplus
}
#endif
#include <touchgfx/hal/HAL.hpp> // Include TouchGFX HAL header
#include <touchgfx/hal/Types.hpp> // Include TouchGFX Types header
#include "TouchGFXHAL.hpp"
extern "C" void flushFrameBufferFromISR()
{
touchgfx::Rect rect(0, 0, 320, 240); // Define the rectangle to flush; adjust as needed
touchgfx::HAL::getInstance()->flushFrameBuffer(rect);
// HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
// Example code to draw a string on the display, adjust as needed
// static int count = 0;
// count++;
// ST7789_DrawString(count, 1, ".", COLOR_WHITE, COLOR_BLACK, 1);
}
//Flushframebuffer in TouchGFXHAL.cpp
void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect &rect)
{
// Use the TouchGFX framebuffer
uint16_t* frameBuf = touchgfx::HAL::getInstance()->getTFTFrameBuffer();
uint16_t displayWidth = touchgfx::HAL::DISPLAY_WIDTH;
uint16_t* src=frameBuf + (rect.y * displayWidth) + rect.x;
uint16_t x0 = rect.x;
uint16_t y0 = rect.y;
uint16_t x1 = rect.x + rect.width - 1;
uint16_t y1 = rect.y + rect.height - 1;
printf("Framebuffer Content Before Flush:\n");
for (uint16_t y = rect.y; y < rect.y + rect.height; ++y)
{
for (uint16_t x = rect.x; x < rect.x + rect.width; ++x)
{
uint16_t pixel = frameBuf[y * displayWidth + x];
printf("Pixel[%d, %d] = %04x ", x, y, pixel);
}
printf("\n");
}
// Set the correct address window for the entire display
ST7789_SetAddressWindow(x0, y0, x1, y1);
ST7789_WriteCommand(ST7789_RAMWR);
// Calculate the total size in bytes for the framebuffer
uint32_t totalDataSize = rect.width * rect.height * 2; // Each pixel is 2 bytes
// Define a reasonable chunk size in bytes
uint16_t chunkSize = 2048;
uint8_t buffer[chunkSize];
HAL_GPIO_WritePin(SPI2_CS_GPIO_Port, SPI2_CS_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOG, LCD_WR_Pin, GPIO_PIN_SET);
for (uint32_t i = 0; i < totalDataSize; i += chunkSize)
{
uint16_t currentChunkSize = (totalDataSize - i) < chunkSize ? (uint16_t)(totalDataSize - i) : chunkSize;
uint32_t pixelIndex = i / 2;
// Copy the 16-bit pixel data into the 8-bit buffer
for (uint16_t j = 0; j < currentChunkSize / 2; ++j)
{
uint16_t pixel = src[pixelIndex + j];
buffer[2 * j] = pixel >> 8; // High byte
buffer[2 * j + 1] = pixel & 0xFF; // Low byte
// Debugging output
// printf("Buffer[%d] = %02x, Buffer[%d] = %02x, Pixel[%d] = %04x\n",
// 2 * j, buffer[2 * j], 2 * j + 1, buffer[2 * j + 1], pixelIndex + j, pixel);
}
HAL_SPI_Transmit(&hspi2, buffer, currentChunkSize, HAL_MAX_DELAY);
}
HAL_GPIO_WritePin(SPI2_CS_GPIO_Port, SPI2_CS_Pin, GPIO_PIN_SET);
// printf("Framebuffer flush complete, terminating.\n");
printf("Framebuffer flush complete, terminating.\n");
while (1)
{
// Optional: Toggle an LED to indicate termination
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_Delay(500); // Adjust delay as needed
}
}