Event based indev (input device) data processing

Hi,

I’m still working (trying to improve, understand lvgl better) with the esp32 demo project. So far the indev (touch sensor) is polled every LV_INDEV_READ_PERIOD ms. The XPT2046 touch controller have an interrupt pin available, which have a low pulse when a touch is detected and i would like to know if is possible to process the indev data only when the touch sensor detects a touch and not periodically?

Kind of a event based indev data processing and not polling.

1 Like

As far as I know, event based input handling is not supported in the current design.

Is it possible feature to support on the future?

I’m not as familiar with the lvgl code as you, do you think the support for it require a modification on the architecture of lvgl?

Yes. LittlevGL does not have a queue for processing event-based input. So it would require significant changes to the input logic. I’m not sure that @kisvegabor thinks that is necessary at this time.

Well, it’s not a requirement that needs to be addressed on the near future, maybe it’s impractical to implement after all.

I don’t know what is the approach on other graphic libraries for embedded, i will try to take a look at them and see if it’s possible to adapt something in here.

MBED OS have a event queue implementation, it’s discussed here:
Office Hours - Event Queue - Chris Haster

OT: Changed the topic title, i think now it’s better.

Hi,

What you can do is to use the interrupt PIN as you want, e.g. queue the touched points and read that queue in the read function. You can return true to indicate that there is more data to read.

If the queue is empty you need to only set the data to the last value.

Thanks, my end goal is to use only one SPI Master for both TFT controller and touch controller and i think using the touch interrupt can help me with that.

Note that the display related SPI transfer is started from lv_task_handler (main while(1) probably.) It can cause problems if you use the same SPI in an interrupt.

I am struggling with this a bit as well. All of my GUI updates are event driven (interrupts from touch, encoders, clocks, etc). The events trigger many GUI changes: locations of GUI objects, text strings, etc.

I have an lv refresh task that is blocked by a semaphore that is unblocked by an event, but this task could be pre-empted by another event task that ends up changing the GUI in the middle of the lv refresh and causes problems with the refresh. The lv refresh task does not execute on it’s own periodically and I am not using things like animation.

With so many event types, I’m not sure how to use a queue for the lv refresh task, but I’m also not sure how to make sure that interrupts don’t corrupt the VDB during lv refresh.

You either have to disable interrupts while lv_task_handler is running, or, better yet, avoid calling LittlevGL from an interrupt handler.

In a multitasking system, the simplest method to use is to guard all calls to LittlevGL with a mutex.

The general rule with LittlevGL is that only one thread can ever be using it at a time.

The interrupts are timing critical, so they can’t be disabled during a refresh. The lv task semaphore is given by a task that is unblocked by the interrupt. Context is switched when the interrupt handler completes. LVGL isn’t called directly by the handler.

Would using a double VDB solve this situation? The refresh would be running from one VDB, while updates to objects would be hitting the other VDB?

Then you have to avoid using LittlevGL directly inside these interrupts.

I’m a bit confused now. What is the exact issue?

The issue is that various events (clocks, buttons, etc) all update lvgl objects directly. This may happen while an lv refresh is currently executing.

example:

  • a timer interrupt results in an lvgl object location being directly updated
  • after the lv object location update, the lv refresh is unblocked, a refresh takes ~3mS
  • while the lv refresh is still executing, a second event occurs (physical button is pressed)
  • the button handler results in an lvgl object (text string) being directly updated.
  • because the lv refresh is still executing when we return from the button handler, it misses some of the updated VDB caused by the button handler, causing corruption of the display

Okay. I think I understand your problem now.

You can’t be calling LittlevGL APIs from inside your interrupt handlers, unless you can guarantee that lv_task_handler isn’t running at the same time (which can only be done by disabling those interrupts).

If you can find a way of moving LittlevGL calls out of timing-critical interrupts, you could leave those enabled and disable all other interrupts.

I was hoping that using doublevdb would eliminate the contention between object updates and a running lv refresh.

The problem here is that you are making concurrent calls to LittlevGL APIs. The only way to solve that is to not do it :wink: .

As far as I can tell the refresh corruption is merely a symptom of the problem.

Hi,

Has the touch interrupt (as Carlos_Diaz asked) already been implemented in the littlevgl library ?

I would like to use interrupt of FT6236 touch controller to wake up only the display or wake up all the system or to make lib littlevgl read the touch only when the display controller sends an interrupt signal.

Thank’s.

Hi,

In dev-7.0 @embeddedt implemented that the display refresh, the indev read and the animation tasks shuts down themself when they have nothing to do. So from LittlevGL’s side no task will be executed if you UI does nothing.

lv_task_handler returns the time to the next task to execute, i.e. you can sleep this long. LV_NO_TASK_READY will be returned if there are no tasks to run.

It allows you to sleep until any external event (e.g. touch interrupt) happens.

Actually, the indev task does not shut itself down yet. I haven’t gotten to the input system yet. So, if you have an input device registered, lv_task_handler will still run every 30ms.

Sorry for the confusion.

However, you can stop it manually e.g. if there are no interrupts for 300 ms.