2024-02-18 03:10 PM
Hi all,
Currently i am stuck so i will try it here.
Ive got custom board with 32L4R9 with LCD connected through FMC on bank 2, SRAM on bank 1 and QSPI.
The first problem is if i use any transition between screens i get a a new screen distorted by shifted every line from previous. This do not occur when transition effect is none.
Second and bigger problem is, that every time i click on button the picture on button is distorted same way.
The behavior:
https://youtu.be/E_HLBltoxFo?si=HB2uXv-tUfQ55lt8
Any ideas?
Btw ST, great idea to permit mp4 files on forum. Really "smart".
Solved! Go to Solution.
2024-09-22 10:33 AM
I have fixed it few months ago. It was really problem with driver of LCD and calculation of pixel width and height.
2024-02-20 09:56 AM
So neither ST emplyees? Great.
2024-09-19 08:52 AM
@Eiffel - came across your post yesterday when I was trying to solve the same, or a very similar problem. I realize you've probably found a solution by now or otherwise moved on to other things, but just in case it is helpful to you or someone else. Your statement "distorted by shifted every line from previous" made me look closer at my actual pixels on the display, which in turn lead me to look more closely at my redraw code (in my case TouchGFXHAL::flushFrameBuffer).
The short answer is that I was setting the address window for the redraw 1 pixel further in x and y than I should have been when I was redrawing a portion of the screen, but not on a full redraw.
The more complete explanation and how I got there follows:
On the initial draw of the entire screen, everything was displaying correctly, but as soon as an individual element (button, text box, etc) needed to be redrawn (“invalidated”), it would display distorted, or at a slant:
Before button was pressed:
After button was pressed:
If you were to look closely at the bottom right corner of the pressed button (I did it with a magnifier), you would be able to see some missing pixels (or really the wrong color). This made me think I was somehow missing or skipping pixels whenever I redrew anything smaller than the entire screen.
To test this, I drew a 5 pixel by 5 pixel box at the upper left hand corner of my screen initially colored red:
I then setup an interaction for that screen in TouchGFX designer to call a virtual function every 10 ticks (1 second in my application). On each tick, I toggled the screen between green and blue.
So as it turned out, redraws of areas smaller than the entire display were resulting in the image being drawing 1 pixel too far to the right, and subsequent rows were ending up with the image shifted one pixel to the left per row, resulting in the slanted display.
My “set window” function was developed to be given a start X & Y coordinate, and a stop X & Y coordinate, with the stop coordinate inclusive in the rectangular window that was to be modified on screen:
void TFT_setAddress_StartStop(uint16_t xStart, uint16_t yStart, uint16_t xStop, uint16_t yStop) {
// Protect inputs from attempting to write outside the boundaries of the screen
if (xStart > TFT_WIDTH-1) { xStart = TFT_WIDTH-1; }
if (xStop > TFT_WIDTH-1) { xStop = TFT_WIDTH-1; }
if (yStart > TFT_HEIGHT-1) { yStart = TFT_HEIGHT-1; }
if (yStop > TFT_HEIGHT-1) { yStop = TFT_HEIGHT-1; }
TFT_writeCommand(CASET); //X address set
TFT_writeData(xStart >> 8);
TFT_writeData(xStart & 0xFF);
TFT_writeData(xStop >> 8);
TFT_writeData(xStop & 0xFF);
TFT_writeCommand(RASET); //Y address set
TFT_writeData(yStart >> 8);
TFT_writeData(yStart & 0xFF);
TFT_writeData(yStop >> 8);
TFT_writeData(yStop & 0xFF);
TFT_writeCommand(RAMWR); // Memory Write
}
But the example code that I based my TouchGFXHAL::flushFrameBuffer implementation on assumed that the second set of XY coordinates were exclusive (1 pixel larger in both dimensions). This is because rect.right() returns x + window width, and rect.bottom() returns y + window height, which is (again) one pixel larger than the actual window.
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();
// Set the address window to the area that needs to be updated
TFT_setAddress_StartStop(rect.x, rect.y, rect.right(), rect.bottom()); // <<== RIGHT HERE
// Write the frame buffer data to the display
for (int32_t y = rect.y; y < rect.bottom(); y++)
{
for (int32_t x = rect.x; x < rect.right(); x++)
{
uint16_t color = frameBuffer[y * TFT_WIDTH + x];
TFT_writeData(color);
}
}
TouchGFXGeneratedHAL::flushFrameBuffer(rect);
}
Note this code should work just fine when using the STM’s SetWindow() function (found in some of their examples) instead of my TFT_setAddress_StartStop was because they remove that 1 pixel in their Xpos + Xwidth – 1 for the row and column stop positions:
void setWindow(uint32_t Xpos, uint32_t Ypos, uint32_t Xwidth, uint32_t Ywidth)
{
// set pixel x pos:
LCD_IO_WriteReg(ST7789H2_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] */ // <<== EXTRA PIXEL IS REMOVED
LCD_IO_WriteData((uint8_t)(Xpos + Xwidth - 1)); /* XE[7:0] */ // <<== EXTRA PIXEL IS REMOVED
// set pixel y pos:
LCD_IO_WriteReg(ST7789H2_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] */ // <<== EXTRA PIXEL IS REMOVED
LCD_IO_WriteData((uint8_t)(Ypos + Ywidth - 1)); /* YE[7:0] */ // <<== EXTRA PIXEL IS REMOVED
}
The reason it only worked in my code when the entire screen was being redrawn was because of my guard statements at the top of the TFT_setAddress_StartStop() function, which made sure that the end positions were 1 less than the display’s width and height.
So all I needed to do to fix this issue was to make my stopX and stopY paraemters 1 pixel smaller than the rect.right(), and rect.bottom():
TFT_setAddress_StartStop(rect.x, rect.y, rect.right()-1, rect.bottom()-1);
Although I just expanded it out to make it easier for me to read down the road:
TFT_setAddress_StartStop(rect.x, rect.y, rect.x + rect.width - 1, rect.y + rect.height - 1);
Thanks for helping me out, and I'm sorry no one helped you with this!
2024-09-22 10:33 AM
I have fixed it few months ago. It was really problem with driver of LCD and calculation of pixel width and height.