This post is related to wait_cb and frame sync issue at Performance ideas
I am trying to use wait_cb
to synchronize data update with a FR pin that is similar to the TE pin on most small-middle size TFTs. On every frame there is a high pulse of FR signal available from my OLED (64*128 monochrome). Users may poll the pin for a 0->1
edge to update the LCD to avoid tearing effect. Traces captured by a DSO below show the FR pulse coupling with the SPI clock. Without any synchronization measure, screen update is performed in a random manner that leads to tearing effect.
To make sure data write sync with FR 0->1 edge, a wait_cb()
function is developed with snippet below:
//local variable for FR event
static bool FR_Event_Flag=false;
//IRQ function
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin==OLED_FR_Pin)
{
FR_Event_Flag=true;
}
}
void my_wait_cb(lv_disp_drv_t * disp_drv)
{
//wait until a valid FR low->high transition
HAL_NVIC_EnableIRQ(OLED_FR_EXTI_IRQn); //enable EXTI interrupt
while(FR_Event_Flag==false) //infinite loop to wait for FR event flag==true
;
HAL_NVIC_DisableIRQ(OLED_FR_EXTI_IRQn); //disable EXTI for next frame update
FR_Event_Flag=false; //reset the FR event flag
}
Registration of wait_cb()
is :
void my_hal_init(void)
{
my_init();
static lv_disp_buf_t lv_disp_buf;
lv_disp_drv_t disp_drv;
/* Flushing freq for the full frame is a variable of the buffer size of lv_buf_array[]
* */
lv_disp_buf_init(&lv_disp_buf, lv_buf_array, NULL, LV_HOR_RES_MAX*LV_VER_RES_MAX);
disp_drv.rotated = (uint32_t)lv_disp_get_orientation();
lv_disp_drv_init(&disp_drv);
disp_drv.buffer = &lv_disp_buf;
disp_drv.flush_cb = my_flush_cb;
disp_drv.wait_cb = my_wait_cb;
disp_drv.set_px_cb = my_set_px_cb;
lv_disp_drv_register(&disp_drv);
//...
}
Issue: wait_cb()
is never called. I set breakpoints at any of the lines in wait_cb()
but the program is not halted. At the end there is still tearing effect. SPI data write is not synchronized with FR edge.
Ideally, on every FR pulse SPI data write should be tightly synchronized like what is shown in waveform below. I got the trace with an non-LVGL demo, synchronizing data update with each FR rising edge.
Any idea why wait_cb() is never called?