diff --git a/src/Arduino_GigaDisplayTouch.h b/src/Arduino_GigaDisplayTouch.h index de7cf3c..97c4653 100644 --- a/src/Arduino_GigaDisplayTouch.h +++ b/src/Arduino_GigaDisplayTouch.h @@ -41,10 +41,15 @@ #define GT911_I2C_ADDR_28_29 (0x14 | 0x80) // 0x28/0x29 - 0x14 (7bit address) #define GT911_CONTACT_SIZE 8 +#if defined(__MBED__) #define GT911_MAX_CONTACTS 5 +#else +#define GT911_MAX_CONTACTS CONFIG_INPUT_GT911_MAX_TOUCH_POINTS +#endif /* Exported types ------------------------------------------------------------*/ typedef struct GDTpoint_s GDTpoint_t; +typedef void (*GDTTouchHandler_t)(uint8_t, GDTpoint_t *); /* Exported enumeration ------------------------------------------------------*/ @@ -59,7 +64,7 @@ struct GDTpoint_s { uint16_t x; uint16_t y; uint16_t area; - uint8_t reserved; + uint8_t pressed; }; /* Class @@ -123,24 +128,25 @@ class Arduino_GigaDisplayTouch { * @brief Attach an interrupt handler function for touch detection callbacks. * @param handler The pointer to the user-defined handler function. */ - void onDetect(void (*handler)(uint8_t, GDTpoint_t *)); + void onDetect(GDTTouchHandler_t handler); private: + GDTTouchHandler_t _gt911TouchHandler; + GDTpoint_t _points[GT911_MAX_CONTACTS]; #if defined(__MBED__) TwoWire &_wire; uint8_t _intPin; uint8_t _rstPin; uint8_t _addr; mbed::InterruptIn _irqInt; - GDTpoint_t _points[GT911_MAX_CONTACTS]; - void (*_gt911TouchHandler)(uint8_t, GDTpoint_t *); uint8_t _gt911WriteOp(uint16_t reg, uint8_t data); uint8_t _gt911WriteBytesOp(uint16_t reg, uint8_t *data, uint8_t len); uint8_t _gt911ReadOp(uint16_t reg, uint8_t *data, uint8_t len); void _gt911onIrq(); uint8_t _gt911ReadInputCoord(uint8_t *pointsbuf, uint8_t &contacts); - +#elif defined(__ZEPHYR__) + friend void touch_event_callback(struct input_event *evt, void *user_data); #endif }; diff --git a/src/Arduino_GigaDisplayTouchZephyr.cpp b/src/Arduino_GigaDisplayTouchZephyr.cpp index 0b8c54e..4e59328 100644 --- a/src/Arduino_GigaDisplayTouchZephyr.cpp +++ b/src/Arduino_GigaDisplayTouchZephyr.cpp @@ -24,80 +24,102 @@ #include #include -typedef struct { - size_t x; - size_t y; - bool pressed; -} touch_point_t; +static struct k_sem zephyr_touch_sem; -static uint8_t zephyr_touch_cb_slot_num; -static struct k_sem zephyr_touch_event_sync; -static touch_point_t zephyr_touch_points[CONFIG_INPUT_GT911_MAX_TOUCH_POINTS]; +typedef void (*zephyr_input_callback_t)(struct input_event *evt, void *user_data); +extern "C" void zephyr_input_register_callback(zephyr_input_callback_t cb, void *user_data); +void touch_event_callback(struct input_event *evt, void *user_data); -typedef void (*zephyr_input_callback_t)(struct input_event *evt, - void *user_data); -extern "C" void zephyr_input_register_callback(zephyr_input_callback_t cb); -static void touch_event_callback(struct input_event *evt, void *user_data); +Arduino_GigaDisplayTouch::Arduino_GigaDisplayTouch() { -Arduino_GigaDisplayTouch::Arduino_GigaDisplayTouch() {} +} + +Arduino_GigaDisplayTouch::~Arduino_GigaDisplayTouch() { -Arduino_GigaDisplayTouch::~Arduino_GigaDisplayTouch() {} +} bool Arduino_GigaDisplayTouch::begin() { - k_sem_init(&zephyr_touch_event_sync, 0, 1); - zephyr_input_register_callback(touch_event_callback); + _gt911TouchHandler = nullptr; + k_sem_init(&zephyr_touch_sem, 1, 1); + zephyr_input_register_callback(touch_event_callback, this); return true; } -void Arduino_GigaDisplayTouch::end() {} +void Arduino_GigaDisplayTouch::end() { + _gt911TouchHandler = nullptr; + zephyr_input_register_callback(NULL, NULL); +} uint8_t Arduino_GigaDisplayTouch::getTouchPoints(GDTpoint_t *points) { // First wait to see if we get any events. - if (k_sem_take(&zephyr_touch_event_sync, K_NO_WAIT) != 0) { + if (k_sem_take(&zephyr_touch_sem, K_NO_WAIT)) { return 0; } - uint8_t count_pressed = 0; - for (uint8_t i = 0; i <= zephyr_touch_cb_slot_num; i++) { - if (zephyr_touch_points[i].pressed) { - points[count_pressed].x = zephyr_touch_points[i].x; - points[count_pressed].y = zephyr_touch_points[i].y; + size_t count_pressed = 0; + for (int i = 0; i < GT911_MAX_CONTACTS; i++) { + if (_points[i].pressed) { + points[count_pressed].trackId = _points[i].trackId; + points[count_pressed].x = _points[i].x; + points[count_pressed].y = _points[i].y; count_pressed++; } } + + k_sem_give(&zephyr_touch_sem); return count_pressed; } -void Arduino_GigaDisplayTouch::onDetect(void (*handler)(uint8_t, - GDTpoint_t *)) { - UNUSED(handler); +void Arduino_GigaDisplayTouch::onDetect(GDTTouchHandler_t handler) { + _gt911TouchHandler = handler; } -static void touch_event_callback(struct input_event *evt, void *user_data) { - static const struct device *const touch_dev = - DEVICE_DT_GET(DT_CHOSEN(zephyr_touch)); +void touch_event_callback(struct input_event *evt, void *user_data) { + static int8_t tp_index = 0; + static bool sem_taken = false; + static const struct device *const touch_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_touch)); + Arduino_GigaDisplayTouch *touch = (Arduino_GigaDisplayTouch *) user_data; - if (evt->dev != touch_dev) { + if (!touch || evt->dev != touch_dev) { + return; + } + + // Take semaphore on first event. + if (evt->code == INPUT_ABS_MT_SLOT) { + // If the semaphore is already taken do Not try to take it again. + // This could only happen if the event queue dropped BTN_TOUCH. + if (!sem_taken && k_sem_take(&zephyr_touch_sem, K_NO_WAIT)) { + return; + } + sem_taken = true; + } else if (!sem_taken) { + // On subsequent events, return if we don't have the semaphore. return; } switch (evt->code) { case INPUT_ABS_MT_SLOT: - zephyr_touch_cb_slot_num = evt->value; + tp_index = evt->value; + touch->_points[tp_index].trackId = evt->value; break; case INPUT_ABS_X: - zephyr_touch_points[zephyr_touch_cb_slot_num].x = evt->value; + touch->_points[tp_index].x = evt->value; break; case INPUT_ABS_Y: - zephyr_touch_points[zephyr_touch_cb_slot_num].y = evt->value; + touch->_points[tp_index].y = evt->value; break; case INPUT_BTN_TOUCH: - zephyr_touch_points[zephyr_touch_cb_slot_num].pressed = evt->value; + touch->_points[tp_index].pressed = evt->value; break; } - if (evt->sync) { - k_sem_give(&zephyr_touch_event_sync); + // Release the semaphore only after updating all of the data. + if (evt->code == INPUT_BTN_TOUCH) { + sem_taken = false; + k_sem_give(&zephyr_touch_sem); + if (touch->_gt911TouchHandler) { + touch->_gt911TouchHandler(GT911_MAX_CONTACTS, touch->_points); + } } } #endif