@krembed
LVGL isn’t going to render anything that is beyond the bounds of the widget. It does this by default. There is nothing that you would need to do to get that functionality. So yes it does improve the performance in those cases as well.
Where you really can notice an improvement is in the scrolling and how responsive it is to the dragging. It’s smoother…
One of the things that needs to be remembered is that this will loop until input stops so any user code that is in the main loop is not going to run until the user input stops. It places user input at the highest priority. Most actions that get performed are going to happen as the result of the user interaction with the UI. So any event callbacks that are attached to buttons and such will run like they normally do. If there is an animation that is running that will stop running because the animations rely on lvgl timers and those get run when task handler gets called and that gets called in the main loop. Iterating over the active timers and having the callbacks called is not hard to add.
The most important thing is setting up an ISR to increment the tick in LVGL. By having it in an ISR it will interrupt the code even if it is looping the input to make sure the time keeping in LVGL gets updated. If that doesn’t get updated like it should you will have things that don’t act properly.
1 Like
I need to clarify on the term “performance”. It’s not going to make it do the work any faster. It is always going to take the same amount of time to do the work that needs to be done. What the indev modification does is it eliminates the 33 milliseconds that LVGL waits between collecting user input. This is beneficial when scrolling because you get a higher precision scroll instead of it jumping.
As you drag your finger across the screen a 33 millisecond wait between collecting the coordinates is an eternity. You will cross a bunch of pixels before LVGL collects another input sample. So as an example. say LVGL collects 100, 0 from an input sample and it registers that touch and 33 milliseconds later it ends up collecting 100, 10 as the touch location. It is going to scroll 10 pixels. Where as using the way above might only have a 2 pixel difference. It improves the response time for user input only after the first input has been detected. We don’t want to add extra work by decreasing the polling time for input as a whole, we only want to decrease that time IF there is input.
If we take Microsoft Windows as an example. The most common polling rate for a mouse is 125hz, That’s once every 8 milliseconds. Most gaming mice have polling rates of 1000hz or once every millisecond. High end gaming mice can have polling rates of 8000hz which is every 125μs (0.125ms). so 33 milliseconds is a long time but setting that polling time lower than that is going to cause a lot of additional work to be done to check if there is input. It doesn’t really need to be done. so using a dynamic approach like what the example above does is it will poll the input and update the display as fast as possible only when there is input.
Hi @kdschlosser ,
Thanks again for your suggestion…
With the indev events I believe I have solved this in a slightly different way… I am using a USB touch screen(You can also attach a normal USB mouse to another port and the two devices work independently) the USB driver delivers the touch events to a FreeRTOS queue. The indev call-back queues a new entry if it is waiting and then checks the touch event queue count again to see if anymore messages remain if so it sets the indev ‘continue_reading’ flag which will force the timer routine to read again in LVGL as far as I am aware… I believe this will achieve the same outcome.
My indev call-back function is like this…
static void mouse_read(lv_indev_t *indev_drv, lv_indev_data_t *data) {
static lv_indev_data_t event_d_q; // This is used to keep the previous state
if( xQueueReceive( cpu0_globals->gui.mse_dat.state_q, data, 0 ) ) {
memcpy( &event_d_q, data, sizeof(lv_indev_data_t) );
} else {
memcpy( data, &event_d_q, sizeof(lv_indev_data_t) ); // No new points so we assume nothing changed so send last point
}
data->continue_reading = (uxQueueMessagesWaiting( cpu0_globals->gui.mse_dat.state_q ) ? pdTRUE : pdFALSE);
}
I have always implemented indevs this way.
I hope that makes sense…
Kind Regards,
Pete
That’s exactly what I had thought the purpose of that continue flag was as well. As it turns out it’s not. The continue reading flag is to take another sample it doesn’t update the display when each new sample is taken so that sample never gets realized onto the display. I had to go and look at the code to see what it is doing in order to determine what is happening.
You can test this by creating a slider and then dragging the slider. It doesn’t move as your finger slides across the display. It only updates the slider once you remove your finger from the display. Scrolling will do the same thing as well. If you want to have it move as your finger moves across the display you cannot use the continue flag. You have to do it the way I explained in my previous post. There is a specific use case for the continue flag which I don’t remember exactly what is is off hand. I believe it has something to do with how fast an indev device is able to be polled. Some devices are only able to be polled at a rate of something along the lines of 10 milliseconds and I am sure there are devices that have a longer wait duration between polls.
Hi @kdschlosser ,
I am not sure what is different but I have not experienced the issue you mention, here is a quick video of a slider on my system.
As you can see it is very smooth and responsive.
Kind Regards,
Pete