Closed xqdd closed 5 years ago
How to init lv_display_drv_t 's buffer?
https://blog.littlevgl.com/2018-01-03/linux_fb is out of date
I'll update it soon.
Until that see https://docs.littlevgl.com/en/html/porting/display.html
ok, thanks for all your work!
And I found that the mouse movement is pretty slow, How to increase read frequency ( ) or just listen to the changes rather than roll polling
Lower LV_INDEV_DEF_READ_PERIOD
in lv_conf.h.
Let me know if the fb driver is not working.
ok, I will tell you when I figure out what the buffer is, now it's NULL then I got a segment fault
Have you initialized the driver as shown in the documentation?
lv_disp_drv_t disp_drv; /*A variable to hold the drivers. Can be local variable*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.buffer = &disp_buf; /*Set an initialized buffer*/
disp_drv.flush_cb = my_flush_cb; /*Set a flush callback to draw to the display*/
lv_disp_t * disp;
disp = lv_disp_drv_register(&disp_drv); /*Register the driver and save the created display objects*/
I'll update the Linux framebuffer project soon and get back to you.
I updated and tested the Linux frame buffer project: https://github.com/littlevgl/linux_frame_buffer
There was a bug in demo
example when "slide show" was enabled.
I've enabled the blog post too: https://blog.littlevgl.com/2018-01-03/linux_fb
it can't display with init mouse code, it work in v5.3
bool mouse_read(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data) {
return evdev_read(data);
}
void init_mouse() {
evdev_init();
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv); /*Basic initialization*/
indev_drv.type =LV_INDEV_TYPE_POINTER; /*See below.*/
indev_drv.read_cb =mouse_read; /*See below.*/
/*Register the driver in LittlevGL and save the created input device object*/
lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv);
lv_obj_t *cursor_obj = lv_img_create(lv_scr_act(), NULL);
lv_img_set_src(cursor_obj, LV_SYMBOL_GPS);
lv_indev_set_cursor(my_indev, cursor_obj);
}
# ./video_monitor
The framebuffer device was opened successfully.
1920x1080, 32bpp
The framebuffer device was mapped to memory successfully.
Does the display work properly now? I'll check the evdev soon.
no problem in the display, but it pretty slow when switching or in animation with lower CPU ( about 50% when animating ) and memory ( 13% )
1f4a58b72aaf19166c8a6615ab9784ca.zip
when I disable animation and preload, switch tab need to wait 2-3 seconds
Try to add lv_tick_inc(5)
into a pthread like:
while(1) {
lv_tick_inc(5);
usleep(5000);
}
Is that what you mean?Or use in somewhere else (create a pthread by myself then call it in while clause)?
Yes, I meant that!
Better, but it misses a feature call v-sync I think
void *my_thread(void*) {
while (1) {
lv_tick_inc(5);
lv_task_handler();
usleep(5000);
}
}
int main() {
lv_init();
init_fb();
init_mouse();
App app;
app.init_app();
pthread_t id1,id2,id3,id4,id5;
pthread_create(&id1, NULL, my_thread, NULL);
pthread_create(&id2, NULL, my_thread, NULL);
pthread_create(&id3, NULL, my_thread, NULL);
pthread_create(&id4, NULL, my_thread, NULL);
pthread_create(&id5, NULL, my_thread, NULL);
pthread_join(id1, NULL);
pthread_join(id2, NULL);
pthread_join(id3, NULL);
pthread_join(id4, NULL);
pthread_join(id5, NULL);
return 0;
}
lv_task_handler
should be in the main()
function. So the task should look like this:
while (1) {
lv_tick_inc(5);
usleep(5000);
}
You should create the task only once.
If it's still slow probably you need to measure the real "usleep time" and pass it in milliseconds to lv_tick_inc()
.
The refreshing seems very slow.
fbdev_flush
can be improved to use memcpy
for one line instead of continuously calculate the locationfbdev_flush
How fast is your MCU?
armv7 soft float without gpu
# cat /proc/cpuinfo Processor : ARMv7 Processor rev 0 (v7l) processor : 0 BogoMIPS : 1849.75
processor : 1 BogoMIPS : 1856.30
Features : swp half thumb fastmult vfp edsp vfpv3 vfpv3d16 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc09 CPU revision : 0
Hardware : godnet Revision : 0000 Serial : 0000000000000000
Processor : ARMv7 Processor rev 0 (v7l) processor : 0 BogoMIPS : 1849.75
processor : 1 BogoMIPS : 1856.30
Features : swp half thumb fastmult vfp edsp vfpv3 vfpv3d16 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc09 CPU revision : 0
Hardware : godnet Revision : 0000 Serial : 0000000000000000
A 1,8 GHz processor should be definitely faster. Try the other things I metioned above.
ok
Better with -O3 compile config and pthread
1c93370f00ee296defde93eaad1bece9.zip
void *my_thread(void *) {
while (1) {
lv_tick_inc(5);
usleep(5000);
}
}
int main() {
lv_init();
init_fb();
init_mouse();
App app;
app.init_app();
pthread_t pid1;
pthread_create(&pid1, NULL, my_thread, NULL);
while(1){
lv_tick_inc(5);
lv_task_handler();
usleep(5000);
}
return 0;
}
# cmake_minimum_required(VERSION <specify CMake version here>)
cmake_minimum_required(VERSION 3.14)
project(video_monitor)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
file(GLOB_RECURSE INCLUDES "lvgl/*.h" "lv_drivers/*.h" "lv_examples/*.h" "./*.h")
file(GLOB_RECURSE SOURCES "lvgl/*.c" "lv_drivers/*.c" "lv_examples/*.c")
file(GLOB_RECURSE SRC "src/*.h" "src/*.cpp")
file(GLOB_RECURSE COMMON "common/*.h" "common/*.c")
INCLUDE_DIRECTORIES(include)
link_directories(lib)
add_executable(video_monitor main.cpp ${COMMON} ${SOURCES} ${INCLUDES} ${SRC})
target_link_libraries(video_monitor dl pthread mpi libaec.a libanr.a libresampler.a libVoiceEngine.a libjpeg.a)
It should look like this. (now you call lv_tick_inc in both places)
void *my_thread(void *) {
while (1) {
lv_tick_inc(5);
usleep(5000);
}
}
int main() {
lv_init();
init_fb();
init_mouse();
App app;
app.init_app();
pthread_t pid1;
pthread_create(&pid1, NULL, my_thread, NULL);
while(1){
lv_task_handler();
usleep(5000);
}
return 0;
}
It seems my_thread
sleeps longer than 5 ms.
Try to measure the real time between two calls of lv_tick_inc()
https://stackoverflow.com/a/41449642/1999969
void *my_thread(void *) {
while (1) {
clock_t begin = clock();
lv_tick_inc(5);
usleep(5000);
clock_t end = clock();
printf("begin: %i end: %i spent: %i\n", begin, end, end - begin);
}
}
int main() {
lv_init();
init_fb();
init_mouse();
App app;
app.init_app();
pthread_t pid1;
pthread_create(&pid1, NULL, my_thread, NULL);
while (1) {
lv_task_handler();
usleep(5000);
}
return 0;
}
more test
# chmod +x video_monitor ;./video_monitor
fuction time(usec) realtime reduce
----------------------------------------------------
usleep 500000 502037 2037
nanosleep 500000 509860 9860
select 500000 510408 10408
pselect 500000 509859 9859
--------------------------------
usleep 100000 109669 9669
nanosleep 100000 110126 10126
select 100000 109582 9582
pselect 100000 109938 9938
--------------------------------
usleep 50000 59847 9847
nanosleep 50000 59934 9934
select 50000 60007 10007
pselect 50000 59993 9993
--------------------------------
usleep 10000 19799 9799
nanosleep 10000 20013 10013
select 10000 19901 9901
pselect 10000 19823 9823
--------------------------------
usleep 1000 10028 9028
nanosleep 1000 9946 8946
select 1000 9943 8943
pselect 1000 9894 8894
--------------------------------
usleep 900 9925 9025
nanosleep 900 9983 9083
select 900 9747 8847
pselect 900 10082 9182
--------------------------------
usleep 500 9954 9454
nanosleep 500 9788 9288
select 500 9990 9490
pselect 500 9991 9491
--------------------------------
usleep 100 10011 9911
nanosleep 100 9830 9730
select 100 9911 9811
pselect 100 10122 10022
--------------------------------
usleep 10 9658 9648
nanosleep 10 10009 9999
select 10 10011 10001
pselect 10 9733 9723
--------------------------------
usleep 1 9945 9944
nanosleep 1 9994 9993
select 1 10045 10044
pselect 1 9815 9814
--------------------------------
int test_delay() {
unsigned int nTimeTestSec = 0;
unsigned int nTimeTest = 0;
struct timeval tvBegin;
struct timeval tvNow;
int ret = 0;
unsigned int nDelay = 0;
struct timeval tv;
int fd = 1;
int i = 0;
struct timespec req;
unsigned int delay[20] =
{500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0};
int nReduce = 0; //误差
fprintf(stderr, "%19s%12s%12s%12s\n", "fuction", "time(usec)", "realtime", "reduce");
fprintf(stderr, "----------------------------------------------------\n");
for (i = 0; i < 20; i++) {
if (delay[i] <= 0)
break;
nDelay = delay[i];
//test sleep
gettimeofday(&tvBegin, NULL);
ret = usleep(nDelay);
if (ret == -1) {
fprintf(stderr, "usleep error, errno=%d [%s]\n", errno, strerror(errno));
}
gettimeofday(&tvNow, NULL);
nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;
nReduce = nTimeTest - nDelay;
fprintf(stderr, "\t usleep %8u %8u %8d\n", nDelay, nTimeTest, nReduce);
//test nanosleep
req.tv_sec = nDelay / 1000000;
req.tv_nsec = (nDelay % 1000000) * 1000;
gettimeofday(&tvBegin, NULL);
ret = nanosleep(&req, NULL);
if (-1 == ret) {
fprintf(stderr, "\t nanousleep %8u not support\n", nDelay);
}
gettimeofday(&tvNow, NULL);
nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;
nReduce = nTimeTest - nDelay;
fprintf(stderr, "\t nanosleep %8u %8u %8d\n", nDelay, nTimeTest, nReduce);
//test select
tv.tv_sec = 0;
tv.tv_usec = nDelay;
gettimeofday(&tvBegin, NULL);
ret = select(0, NULL, NULL, NULL, &tv);
if (-1 == ret) {
fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno));
}
gettimeofday(&tvNow, NULL);
nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;
nReduce = nTimeTest - nDelay;
fprintf(stderr, "\t select %8u %8u %8d\n", nDelay, nTimeTest, nReduce);
//pselcet
req.tv_sec = nDelay / 1000000;
req.tv_nsec = (nDelay % 1000000) * 1000;
gettimeofday(&tvBegin, NULL);
ret = pselect(0, NULL, NULL, NULL, &req, NULL);
if (-1 == ret) {
fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno));
}
gettimeofday(&tvNow, NULL);
nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;
nReduce = nTimeTest - nDelay;
fprintf(stderr, "\t pselect %8u %8u %8d\n", nDelay, nTimeTest, nReduce);
fprintf(stderr, "--------------------------------\n");
}
return 0;
}
I've just also realized clock()
isn't working well here.
I've update the main.c
to correctly measure the time and optimized fbdev.c
I will test it when I can use my mouse in v6.0 ^^
I will test it when I can use my mouse in v6.0 ^^
It would be good the get feedback from the display part too.
The tick handling is improved again: cc02e15
How to use it? Like this?
void *my_thread(void *) {
while (1) {
lv_tick_inc(custom_tick_get());
}
}
int main(void) {
/*LittlevGL init*/
lv_init();
/*Linux frame buffer device init*/
fbdev_init();
/*A small buffer for LittlevGL to draw the screen's content*/
static lv_color_t buf[DISP_BUF_SIZE];
/*Initialize a descriptor for the buffer*/
static lv_disp_buf_t disp_buf;
lv_disp_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);
/*Initialize and register a display driver*/
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.buffer = &disp_buf;
disp_drv.flush_cb = fbdev_flush;
lv_disp_drv_register(&disp_drv);
/*Create a Demo*/
demo_create();
pthread_t pid1;
pthread_create(&pid1, NULL, my_thread, NULL);
/*Handle LitlevGL tasks (tickless mode)*/
while (1) {
lv_task_handler();
usleep(5000);
}
return 0;
}
It's already configured for you. Just git pull
the latest version and use it. No changes should be necessary.
Are you sure not need lv_tick_inc()? https://github.com/littlevgl/lv_linux_frame_buffer/blob/master/main.c#L37
@XQDD Please read lv_conf.h
carefully.
@kisvegabor enabled LV_TICK_CUSTOM
on this project, so calling lv_tick_inc
is not necessary.
Please ignore the noise... It seems the same
It's not the same because now the duration of the animation is correct. You just have a few FPS. In the previous version the tab switching was much slower (~2sec instead of ~500ms).
This issue or pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I've just updated the driver but haven't tested yet: f07f7a3
Is it working well?