2025-08-07 10:32 AM
Hi all,
I'm trying to use the partial frame buffer feature and I get the first two partial frames (40 lines), but TouchGFX does not seem to update the screen into the partial buffer. Just using TouchGFX no DMA, and no ChromArt.
My home screen is :
But the LCD only displays
Looking at the partial frame buffer, the rest of the screen is not rendered.
Do I need to make some call in frame transfer to update to the next partial frame?
Thanks
Archer
2025-08-18 5:14 AM - edited 2025-08-18 5:15 AM
Hello,
You need to implement a few functions, it is described in TouchGFXGeneratedHAL.cpp:
/* ******************************************************
* Functions required by Partial Frame Buffer Strategy
* ******************************************************
*
* int touchgfxDisplayDriverTransmitActive() must return whether or not data is currently being transmitted, over e.g. SPI.
* void touchgfxDisplayDriverTransmitBlock(const uint8_t* pixels, uint16_t x, uint16_t y, uint16_t w, uint16_t h) will be called
* when the framework wants to send a block. The user must then transfer the data represented by the arguments.
*/
extern "C" int touchgfxDisplayDriverTransmitActive();
extern "C" int touchgfxDisplayDriverShouldTransferBlock(uint16_t bottom);
extern "C" void touchgfxDisplayDriverTransmitBlock(const uint8_t* pixels, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
extern "C" void touchgfxSignalVSync(void);
2025-08-28 5:56 PM
Hello,
I implemented the routines you mentioned, and ported to the Nucleo examples. Same results..
Below are my routines...
Always draw two partial buffers. Seems to be initiated from taskEntry()
Thanks
Archer
2025-09-03 9:56 AM
Hi all
Many thanks to Lina for the suggestion on reposting using the 'inseert code tool'.
----------------------------------------------------------------------------------------------------------------
Hello,
I implemented the routines you mentioned, and ported to the Nucleo examples. Same results..
Below are my routines...
/* auto generated in TouchGFXGeneratedHAL.c */
extern "C" void touchgfxSignalVSync(void)
{
/* VSync has occurred, increment TouchGFX engine vsync counter */
touchgfx::HAL::getInstance()->vSync();
/* VSync has occurred, signal TouchGFX engine */
touchgfx::OSWrappers::signalVSync();
}
/* written in TouchGFXHAL.c */
// The TouchGFX framework calls this function to check if a transmission is in progress
extern "C" int touchgfxDisplayDriverTransmitActive()
{
return isTransmittingBlock ? 1 : 0;
}
// The TouchGFX framework calls this function to check if the transfer of a block should be started
extern "C" int touchgfxDisplayDriverShouldTransferBlock(uint16_t bottom)
{
// Only allow block transfer if the display has drawn past the bottom of the requested block
// (plus a margin of two lines)
// A timer is used to estimate how many lines have been drawn by setting the prescaler
// so the tick rate matches the line draw rate
uint16_t lastLineDrawn = LL_TIM_GetCounter(LINE_TIMER);
int retVal = bottom + 2 < lastLineDrawn || tearingEffectCount > 0;
// return retVal;
return 10; // hard coded to retrun the number of lines
}
extern "C" void touchgfxDisplayDriverTransmitBlock(const uint8_t* pixels, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
uint8_t lo = 0, hi = 0;
uint32_t nPixels = w * h;
isTransmittingBlock = true;
SSD1963_SetDisplayWindow(x, y, x+w-1, y+h-1);
// LCD_IO_SendDataDMA((uint8_t*)pixels, w * h * 2); // DMA clears isTransmittingBlock at end of xfer
// Manual Xfer -- down and dirty, no DMA
//
while (nPixels)
{
lo = *pixels++;
hi = *pixels++;
FMC_BANK1_WriteData(((uint16_t)hi << 8) | lo);
nPixels--;
}
isTransmittingData = false; // not necessary with this implementation since
// DISP_TransmitData is blocking
isTransmittingBlock = false;
osSemaphoreRelease(xDisplayTransmitSemaphore); // release semaphore to mimic DMA
}
2025-09-03 10:04 AM
The two buffers tah are displayed happen with in the taskEntry() routine. The VSync()/LCD_Tear() routines are processed but do no draw any additional LCD buffers.
I've randomly tried many things. Re-read the app notes multiple times without progress.
At this point I am out of time. The project is stopped until I something new occurs.
I've been a big fan on STM, but I am stuck. I suppose I'll try another embedded graphic tool set.
Archer
2025-09-04 12:19 AM
Looking at this, there are a few things I am wondering about that you could check out if you get time and/or motivation.
First of all, is there anything that calls touchgfxSignalVSync() in your code?
You are expected to handle that yourself, preferably using an interrupt on a tearing effect output from the display, if available. Otherwise, a timer could be used, but that will probably result in tearing on the display.
Do you get calls to touchgfxDisplayDriverTransmitActive() and touchgfxDisplayDriverShouldTransferBlock()?
2025-09-09 2:52 PM
Hello,
toughgfxSignalVSync() is being called in HAL_GPIO_EXTI_Callback(). This is part of the VSync IRQ routines.
touchgfxDisplayDriverTransmitActive() is called often. Right now I have it hard coded to return 'false'. I'll change that when I get DMA and the rest working.
touchgfxDisplayDriverShouldTransferBlock() is not called at all.
The system seems to draw 1 block into the PartialBuffer, then diplays it to the LCD().
Then it stays in a loop as follows...
void TouchGFXHAL::taskEntry()
{
enableLCDControllerInterrupt();
enableInterrupts();
OSWrappers::waitForVSync(); // vsync
backPorchExited();
/* Enable the LCD, Send Display on DCS command to display LCDTear */
// HAL_DSI_ShortWrite(&hdsi, LCD_OTM8009A_ID, DSI_DCS_SHORT_PKT_WRITE_P1, OTM8009A_CMD_DISPON, 0x00);
for (;;)
{
if (!startRenderingImmediately)
// if TE high start render immediately,
// otherwise wait for next TE to synchronize with display
{
OSWrappers::waitForVSync();
}
startRenderingImmediately = true;
// only start one new frame inside each TE high
backPorchExited();
}
}
2025-09-10 12:02 AM
Hello,
I think I got it. You are not releasing the blocks after transfer. You need something like this, which you need to call manually when using blocking transfers, or from the DMA complete callback when using DMA
void DisplayDriver_TransferCompleteCallback()
{
// After completed transmission start new transfer if blocks are ready.
PartialFrameBufferManager::tryTransmitBlockFromIRQ();
}
Or, if you prefer, this:
// Mark a block transferred
FrameBufferAllocator* fba = HAL::getInstance()->getFrameBufferAllocator();
fba->freeBlockAfterTransfer();
2025-09-15 11:02 AM
Hello,
I tried your changes. got a little further but still stopped.
I'm looking into the touch IRQ. It may be interrupting continuously. Which of course will cause all kinds of trouble. I'll let you know what I find....
Thanks
Archer