در قسمت هفتم از آموزش LVGL به نحوه کار با Simulator و دانلود فایلهای موردنیاز برای آن پرداختیم. در این قسمت قصد داریم که ورودیهای سیستم گرافیکی LVGL یعنی inputها، انواع interfaceهای مختلف، بخش تیک سیستم گرافیکی (tick interface)، بخش task handler و بخش LOG را آموزش دهیم. پس تا پایان این قسمت همراه سیسوگ باشید.
ابتدا میخواهیم بررسی کنیم که inputها چی هستند و برای سیستم گرافیکی چه فایدهای دارند. بهطورکلی، Inputها دیوایسهای جانبی هستند که به سیستم گرافیکی متصل میشوند و ما توسط این Inputها، میتوانیم به سیستم گرافیکی فرمان دهیم، یک گزینه را جابهجا کنیم و یا میتوانیم یک سری اطلاعات به سیستم خود بدهیم؛ به عبارت بهتر میتوان گفت: inputها واسطه بین کاربر و سیستم گرافیکی هستند.
در سیستم گرافیکی LVGL ،inputها در چهار دسته تقسیم میشوند:
inputها با استراکچر lv_indev_drv_t مشخص میشوند. به عبارتی، این استراکچر برای معرفی یک دیوایس ورودی به سیستم گرافیکی میباشد. این استراکچر حاوی نوع دیوایس، توابع خواندن دیوایس ورودی و اطلاعات تایمر خواندن دادهها و درایور صفحهنمایش میباشد. کلاً استراکچر بزرگی هست؛ چون شامل چهارتا مورد موس و صفحه تاچ، کیبورد و کی پد، انکودر و کلیدها میباشد.
بهعنوانمثال، برای معرفی این ورودی باید به صورت کد زیر عمل کنیم:
1 2 3 4 5 6 7 8 9 | static lv_indev_drv_t indev_drv_1; lv_indev_drv_init(&indev_drv_1); indev_drv_1.type = LV_INDEV_TYPE_POINTER; indev_drv_1.read_cb = my_input_read; lv_indev_t *touch_indev = lv_indev_drv_register(&indev_drv_1); |
ما میتوانیم همزمان، چند تا دیوایس ورودی برای سیستم خود تعریف کنیم و سیستم گرافیکی هیچ محدودیتی در این زمینه ندارد.
اگر شما بخواهید یک سری دیتا (اطلاعات) از طریق تابع call back به سیستم گرافیکی خود بدهید، به یک استراکچر به نام lv_indev_data_t احتیاج دارید که این استراکچر عمومی هست؛ یعنی هم مربوط به همهی ورودیها میباشد.
بهطورکلی، این استراکچر نگهدارنده اطلاعات مربوط به دیواس ورودی میباشد. به مثال زیر توجه کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | typedef struct { lv_point_t point; uint32_t key; uint32_t btn_id; int16_t enc_diff; lv_indev_state_t state; bool continue_reading; } lv_indev_data_t; |
lv_point_t نیز خودش یک استراکچر است که در ادامه درباره آن توضیح می دهیم.
این استراکچر حاوی مختصات X و Y است؛ یعنی اگر شما بخواهید به سسیتم گرافیکیتان، یک مختصات را معرفی کنید، باید از استراکچر lv_point_t استفاده کنید.
بهطورکلی، این استراکچر حاوی اطلاعات مربوط به مکان لمس شده است. به مثال زیر توجه کنید:
1 2 3 4 5 6 7 | typedef struct { lv_coord_t x; lv_coord_t y; } lv_point_t; |
نحوه درایور کردن همه موسها و کیبوردها به این شکل هست که یا Polling هستند یا بهصورت اینتراپتی (Interrupt). عیبی که Polling دارد، این است که برای سیستم، سربار دارد، درصورتیکه در حالت اینتراپتی، این سربار وجود ندارد و دلیل آن هم خواندن پشت سر هم آن ورودی هستش.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | void my_input_read(lv_indev_drv_t * drv, lv_indev_data_t * data) { if(touchpad_pressed) { data->point.x = touchpad_x; data->point.y = touchpad_y; data->state = LV_INDEV_STATE_PRESSED; } else { data->state = LV_INDEV_STATE_RELEASED; } } |
در Keypad و keyboard شما باید آبجکتهایی که قرار است با Keypad یا keyboard تغییر کنند یا جابه جا شوند را داخل group قرار دهید.
دراینخصوص، شما باید ابتدا یک group از جنس lv_group_t تعریف کنید که lv_group_t خودش یک استراکچر هست. مانند کد زیر شما باید ابتدا یک group تشکیل دهید و آن را بزارید رو حالت default. (وقتی رو حالت default بزارید، هر چی که تو صفحتون هست جز این گروه قرار میگیرد.) سپس دیوایس ورودی خود را تعریف کنید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | lv_group_t * g = lv_group_create(); lv_group_set_default(g); static lv_indev_drv_t indev_drv_2; lv_indev_drv_init(&indev_drv_2); indev_drv_2.type = LV_INDEV_TYPE_KEYPAD; indev_drv_2.read_cb = keyboard_read; lv_indev_t *kb_indev = lv_indev_drv_register(&indev_drv_2); lv_indev_set_group(kb_indev, g); |
توجه: تابع خواندن KEYPAD و keyboard یکسان هستند.
1 2 3 4 5 6 7 8 9 | void keyboard_read(lv_indev_drv_t * drv, lv_indev_data_t * data){ data->key = last_key(); /*Get the last pressed or released key*/ if(key_pressed()) data->state = LV_INDEV_STATE_PRESSED; else data->state = LV_INDEV_STATE_RELEASED; } |
انکودر نیز مانند KEYPAD و keyboard به این صورت است که شما نیاز دارید که یک group ایجاد کنید و آن را روی group خود، ست کنید.
تنها تفاوتی که انکودر با KEYPAD و keyboard دارد این است که ورودی از نوع انکودر میشود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | lv_group_t * g = lv_group_create(); lv_group_set_default(g); static lv_indev_drv_t indev_drv_3; lv_indev_drv_init(&indev_drv_3); indev_drv_3.type = LV_INDEV_TYPE_ENCODER; indev_drv_3.read_cb = encoder_read; lv_indev_t * enc_indev = lv_indev_drv_register(&indev_drv_3); lv_indev_set_group(enc_indev, g); |
تابع خواندن انکودر مانند تابعهای قبلی است. فقط در اینجا شما باید خروجی تفاضل کانتر انکودرتون به ورودی دیتا بدهید.
1 2 3 4 5 6 7 8 9 | void encoder_read(lv_indev_drv_t * drv, lv_indev_data_t*data){ data->enc_diff = enc_get_new_moves(); if(enc_pressed()) data->state = LV_INDEV_STATE_PRESSED; else data->state = LV_INDEV_STATE_RELEASED; } |
تایمر کانترها قابلیت اتصال انکودر را دارند؛ یعنی وقتی که شما تایمر کانتر خود را داخل stm فعال میکنید، هر step ای که داخل انکودرتان بدید مقدار این تایمر کانتر افزایش یا کاهش مییابد و در صورت فعال سازی وقفه، با هر تغییر یک وقفه به وجود می آید.
Tick interface یک بخش عمومی در تمام سختافزارها و سیستمهای گرافیکی است. کار Tick interface در سیستم گرافیکی LVGL، این است که زمانسنجی کند و این فرایند را توسط وقفههای یک میلی ثانیهای انجام میدهد.
ویژگیهای این تابع عبارتاند از:
1: super Loop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | void system_Tick(void) { lv_tick_inc(1); } 2: Free Rtos void * tick_thread (void *args) { while(1) { usleep(5*1000); lv_tick_inc(5); } } |
ویژگیهای این تابع عبارتاند از:
این تابع بررسی و نمایش وضعیت و اخطارها و خطاهای سیستم میباشد.
LV_LOG_LEVEL_TRACE
LV_LOG_LEVEL_WARN
LV_LOG_LEVEL_ERROR
LV_LOG_LEVEL_USER
LV_LOG_LEVEL_NONE
به عنوان مثال توسط در کد وقفهی زیر وقتی کلید شما لمس میشود سیستم عبارت “Clicked” را LOG می کند و در صورت تغییر وضعیت کلید عبارت “Toggled” LOG میشود.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | static void event_handler(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); if(code == LV_EVENT_CLICKED) { LV_LOG_USER("Clicked"); } else if(code == LV_EVENT_VALUE_CHANGED) { LV_LOG_USER("Toggled"); } } |
از ویژگی LOG برای بررسی و مانیتوریگ و اشکال یابی سیستم استفاده میشود.
نویسنده شو !
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.