acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

indev.md (8224B)

      1 ```eval_rst
      2 .. include:: /header.rst
      3 :github_url: |github_link_base|/porting/indev.md
      4 ```
      5 # Input device interface
      6 
      7 ## Types of input devices
      8 
      9 To register an input device an `lv_indev_drv_t` variable has to be initialized. **Be sure to register at least one display before you register any input devices.**
     10 
     11 ```c
     12 lv_disp_drv_register(&disp_drv);
     13 
     14 static lv_indev_drv_t indev_drv;
     15 lv_indev_drv_init(&indev_drv);      /*Basic initialization*/
     16 indev_drv.type =...                 /*See below.*/
     17 indev_drv.read_cb =...              /*See below.*/
     18 /*Register the driver in LVGL and save the created input device object*/
     19 lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv);
     20 ```
     21 
     22 The `type` member can be:
     23 - `LV_INDEV_TYPE_POINTER` touchpad or mouse
     24 - `LV_INDEV_TYPE_KEYPAD` keyboard or keypad
     25 - `LV_INDEV_TYPE_ENCODER` encoder with left/right turn and push options
     26 - `LV_INDEV_TYPE_BUTTON` external buttons virtually pressing the screen
     27 
     28 `read_cb` is a function pointer which will be called periodically to report the current state of an input device.
     29 
     30 Visit [Input devices](/overview/indev) to learn more about input devices in general.
     31 
     32 ###  Touchpad, mouse or any pointer
     33 Input devices that can click points on the screen belong to this category.
     34 
     35 ```c
     36 indev_drv.type = LV_INDEV_TYPE_POINTER;
     37 indev_drv.read_cb = my_input_read;
     38 
     39 ...
     40 
     41 void my_input_read(lv_indev_drv_t * drv, lv_indev_data_t*data)
     42 {
     43   if(touchpad_pressed) {
     44     data->point.x = touchpad_x;
     45     data->point.y = touchpad_y;
     46     data->state = LV_INDEV_STATE_PRESSED;
     47   } else {
     48     data->state = LV_INDEV_STATE_RELEASED;
     49   }
     50 }
     51 ```
     52 
     53 To set a mouse cursor use `lv_indev_set_cursor(my_indev, &img_cursor)`. (`my_indev` is the return value of `lv_indev_drv_register`)
     54 
     55 ### Keypad or keyboard
     56 
     57 Full keyboards with all the letters or simple keypads with a few navigation buttons belong here.
     58 
     59 To use a keyboard/keypad:
     60 - Register a `read_cb` function with `LV_INDEV_TYPE_KEYPAD` type.
     61 - An object group has to be created: `lv_group_t * g = lv_group_create()` and objects have to be added to it with `lv_group_add_obj(g, obj)`
     62 - The created group has to be assigned to an input device: `lv_indev_set_group(my_indev, g)` (`my_indev` is the return value of `lv_indev_drv_register`)
     63 - Use `LV_KEY_...` to navigate among the objects in the group. See `lv_core/lv_group.h` for the available keys.
     64 
     65 ```c
     66 indev_drv.type = LV_INDEV_TYPE_KEYPAD;
     67 indev_drv.read_cb = keyboard_read;
     68 
     69 ...
     70 
     71 void keyboard_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
     72   data->key = last_key();            /*Get the last pressed or released key*/
     73 
     74   if(key_pressed()) data->state = LV_INDEV_STATE_PRESSED;
     75   else data->state = LV_INDEV_STATE_RELEASED;
     76 }
     77 ```
     78 
     79 ### Encoder
     80 With an encoder you can do the following:
     81 1. Press its button
     82 2. Long-press its button
     83 3. Turn left
     84 4. Turn right
     85 
     86 In short, the Encoder input devices work like this:
     87 - By turning the encoder you can focus on the next/previous object.
     88 - When you press the encoder on a simple object (like a button), it will be clicked.
     89 - If you press the encoder on a complex object (like a list, message box, etc.) the object will go to edit mode whereby you can navigate inside the object by turning the encoder.
     90 - To leave edit mode, long press the button.
     91 
     92 
     93 To use an *Encoder* (similarly to the *Keypads*) the objects should be added to groups.
     94 
     95 
     96 ```c
     97 indev_drv.type = LV_INDEV_TYPE_ENCODER;
     98 indev_drv.read_cb = encoder_read;
     99 
    100 ...
    101 
    102 void encoder_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    103   data->enc_diff = enc_get_new_moves();
    104 
    105   if(enc_pressed()) data->state = LV_INDEV_STATE_PRESSED;
    106   else data->state = LV_INDEV_STATE_RELEASED;
    107 }
    108 ```
    109 
    110 #### Using buttons with Encoder logic
    111 In addition to standard encoder behavior, you can also utilize its logic to navigate(focus) and edit widgets using buttons.
    112 This is especially handy if you have only few buttons available, or you want to use other buttons in addition to encoder wheel.
    113 
    114 You need to have 3 buttons available:
    115 - `LV_KEY_ENTER` will simulate press or pushing of the encoder button
    116 - `LV_KEY_LEFT` will simulate turning encoder left
    117 - `LV_KEY_RIGHT` will simulate turning encoder right
    118 - other keys will be passed to the focused widget
    119 
    120 If you hold the keys it will simulate an encoder advance with period specified in `indev_drv.long_press_rep_time`.
    121 
    122 ```c
    123 indev_drv.type = LV_INDEV_TYPE_ENCODER;
    124 indev_drv.read_cb = encoder_with_keys_read;
    125 
    126 ...
    127 
    128 void encoder_with_keys_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    129   data->key = last_key();            /*Get the last pressed or released key*/
    130                                      /* use LV_KEY_ENTER for encoder press */
    131   if(key_pressed()) data->state = LV_INDEV_STATE_PRESSED;
    132   else {
    133       data->state = LV_INDEV_STATE_RELEASED;
    134       /* Optionally you can also use enc_diff, if you have encoder*/
    135       data->enc_diff = enc_get_new_moves();
    136   }
    137 }
    138 ```
    139 
    140 ### Button
    141 *Buttons* mean external "hardware" buttons next to the screen which are assigned to specific coordinates of the screen.
    142 If a button is pressed it will simulate the pressing on the assigned coordinate. (Similarly to a touchpad)
    143 
    144 To assign buttons to coordinates use `lv_indev_set_button_points(my_indev, points_array)`.
    145 `points_array` should look like `const lv_point_t points_array[] = { {12,30},{60,90}, ...}`
    146 
    147 ``` important::  The points_array can't go out of scope. Either declare it as a global variable or as a static variable inside a function.
    148 ```
    149 
    150 ```c
    151 indev_drv.type = LV_INDEV_TYPE_BUTTON;
    152 indev_drv.read_cb = button_read;
    153 
    154 ...
    155 
    156 void button_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    157     static uint32_t last_btn = 0;   /*Store the last pressed button*/
    158     int btn_pr = my_btn_read();     /*Get the ID (0,1,2...) of the pressed button*/
    159     if(btn_pr >= 0) {               /*Is there a button press? (E.g. -1 indicated no button was pressed)*/
    160        last_btn = btn_pr;           /*Save the ID of the pressed button*/
    161        data->state = LV_INDEV_STATE_PRESSED;  /*Set the pressed state*/
    162     } else {
    163        data->state = LV_INDEV_STATE_RELEASED; /*Set the released state*/
    164     }
    165 
    166     data->btn = last_btn;            /*Save the last button*/
    167 }
    168 ```
    169 
    170 ## Other features
    171 
    172 ### Parameters
    173 
    174 The default value of the following parameters can be changed in `lv_indev_drv_t`:
    175 - `scroll_limit` Number of pixels to slide before actually scrolling the object.
    176 - `scroll_throw`  Scroll throw (momentum) slow-down in [%]. Greater value means faster slow-down.
    177 - `long_press_time` Press time to send `LV_EVENT_LONG_PRESSED` (in milliseconds)
    178 - `long_press_rep_time` Interval of sending `LV_EVENT_LONG_PRESSED_REPEAT` (in milliseconds)
    179 - `read_timer` pointer to the `lv_timer` which reads the input device. Its parameters can be changed by `lv_timer_...()` functions. `LV_INDEV_DEF_READ_PERIOD` in `lv_conf.h` sets the default read period.
    180 
    181 ### Feedback
    182 
    183 Besides `read_cb` a `feedback_cb` callback can be also specified in `lv_indev_drv_t`.
    184 `feedback_cb` is called when any type of event is sent by the input devices (independently of its type). This allows generating feedback for the user, e.g. to play a sound on `LV_EVENT_CLICKED`.
    185 
    186 
    187 ### Associating with a display
    188 Every input device is associated with a display. By default, a new input device is added to the last display created or explicitly selected (using `lv_disp_set_default()`).
    189 The associated display is stored and can be changed in `disp` field of the driver.
    190 
    191 ### Buffered reading
    192 By default, LVGL calls `read_cb` periodically. Because of this intermittent polling there is a chance that some user gestures are missed.
    193 
    194 To solve this you can write an event driven driver for your input device that buffers measured data. In `read_cb` you can report the buffered data instead of directly reading the input device.
    195 Setting the `data->continue_reading` flag will tell LVGL there is more data to read and it should call `read_cb` again.
    196 
    197 ## Further reading
    198 
    199 - [lv_port_indev_template.c](https://github.com/lvgl/lvgl/blob/master/examples/porting/lv_port_indev_template.c) for a template for your own driver.
    200 - [INdev features](/overview/display) to learn more about higher level input device features.
    201 
    202 ## API
    203 
    204 ```eval_rst
    205 
    206 .. doxygenfile:: lv_hal_indev.h
    207   :project: lvgl
    208 
    209 ```