Files
arcs/arcs-sdk/modules/lvgl8/porting/lv_port_indev.c
2026-08-13 16:50:52 +08:00

200 lines
4.9 KiB
C

/**
* @file lv_port_indev.c
*
*/
#if 1
/*********************
* INCLUDES
*********************/
#include "lv_port_indev.h"
#include "lisa_touch.h"
#include "lisa_device.h"
#include "lisa_display.h"
#include <FreeRTOS.h>
#include <semphr.h>
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
struct touch_msg {
uint16_t x;
uint16_t y;
bool pressed;
};
/**********************
* STATIC PROTOTYPES
**********************/
static void touchpad_init(lisa_device_t *touch_dev);
static void touchpad_read(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data);
static void touchpad_transform_coordinates(lv_coord_t *x, lv_coord_t *y);
/**********************
* STATIC VARIABLES
**********************/
static lisa_device_t *touch_device = NULL;
static lv_indev_drv_t indev_drv;
static uint16_t last_x = 0;
static uint16_t last_y = 0;
static uint8_t last_state = 0;
static SemaphoreHandle_t touchpad_sem = NULL;
static QueueHandle_t touchpad_queue = NULL;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* @brief Touch interrupt callback function
*
* This callback is called from interrupt context when touch event occurs.
* It should be kept as short as possible.
*/
static void touch_int_callback(const lisa_touch_event_t *event, void *user_data)
{
struct touch_msg msg;
static bool last_pressed = false;
if (event->type == LISA_TOUCH_EVENT_PRESS && event->point_count > 0) {
msg.x = event->points[0].x;
msg.y = event->points[0].y;
msg.pressed = true;
last_pressed = true;
} else if (event->type == LISA_TOUCH_EVENT_RELEASE) {
if (last_pressed) {
msg.pressed = false;
last_pressed = false;
}
}
xQueueSend(touchpad_queue, &msg, portMAX_DELAY);
}
void lv_port_indev_init(lisa_device_t *touch_dev)
{
/*Initialize your touchpad*/
touchpad_init(touch_dev);
if (touch_device == NULL) {
return;
}
/*Register a touchpad input device*/
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = touchpad_read;
lv_indev_drv_register(&indev_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/*Initialize your touchpad*/
static void touchpad_init(lisa_device_t *touch_dev)
{
touch_device = touch_dev;
if (touch_device == NULL) {
return;
}
int ret = lisa_touch_set_callback(touch_dev, touch_int_callback, NULL);
if (ret != 0) {
printf("Error: Touch callback set failed (code: %d)\n", ret);
return;
}
ret = lisa_touch_set_int_mode(touch_dev, LISA_TOUCH_INT_MODE_INTERRUPT);
if (ret != 0) {
printf("Error: Touch interrupt mode set failed (code: %d)\n", ret);
return;
}
ret = lisa_touch_enable(touch_dev);
if (ret != 0) {
printf("Error: Touch enable failed (code: %d)\n", ret);
return;
}
touchpad_sem = xSemaphoreCreateBinary();
touchpad_queue = xQueueCreate(CONFIG_LS_LV_INDEV_TASK_QUEUE_SIZE, sizeof(struct touch_msg));
}
/* Will be called by the library to read the touchpad */
static void touchpad_read(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
{
struct touch_msg msg;
if (xQueueReceive(touchpad_queue, &msg, 0) == pdPASS) {
data->point.x = (lv_coord_t)msg.x;
data->point.y = (lv_coord_t)msg.y;
data->state = msg.pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
data->continue_reading = (uxQueueMessagesWaiting(touchpad_queue) > 0 ? 1 : 0);
touchpad_transform_coordinates(&data->point.x, &data->point.y);
last_x = data->point.x;
last_y = data->point.y;
last_state = data->state;
return;
}
data->point.x = (lv_coord_t)last_x;
data->point.y = (lv_coord_t)last_y;
data->state = last_state;
data->continue_reading = 0;
}
/**
* @brief 触摸坐标系转换
* @param x 输入/输出 X 坐标
* @param y 输入/输出 Y 坐标
*
* @note 该函数处理硬件坐标系校正(触摸屏与显示屏坐标系不一致)
*/
static void touchpad_transform_coordinates(lv_coord_t *x, lv_coord_t *y)
{
if (!x || !y) {
return;
}
extern lisa_device_t *lv_display_device;
lisa_display_capabilities_t caps = {0};
lisa_display_get_capabilities(lv_display_device, &caps);
#if CONFIG_LV_POINTER_SWAP_XY
lv_coord_t cur_x = *y;
lv_coord_t cur_y = *x;
#else
lv_coord_t cur_x = *x;
lv_coord_t cur_y = *y;
#endif
#if CONFIG_LV_POINTER_INVERT_X
cur_x = caps.x_resolution - cur_x;
#endif
#if CONFIG_LV_POINTER_INVERT_Y
cur_y = caps.y_resolution - cur_y;
#endif
*x = cur_x;
*y = cur_y;
}
#else /* Enable this file at the top */
/* This dummy typedef exists purely to silence -Wpedantic. */
typedef int keep_pedantic_happy;
#endif