Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions src/Arduino_GigaDisplayTouch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ------------------------------------------------------*/

Expand All @@ -59,7 +64,7 @@ struct GDTpoint_s {
uint16_t x;
uint16_t y;
uint16_t area;
uint8_t reserved;
uint8_t pressed;
};

/* Class
Expand Down Expand Up @@ -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
};

Expand Down
90 changes: 58 additions & 32 deletions src/Arduino_GigaDisplayTouchZephyr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,80 +24,106 @@
#include <zephyr/kernel.h>
#include <zephyr/sys/util.h>

typedef struct {
size_t x;
size_t y;
bool pressed;
} touch_point_t;

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];
static struct k_sem touch_sem;

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);
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);

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;
// Initialize to 1 to prevent deadlock by ensuring that
// at least one function can always proceed initially.
k_sem_init(&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);
memset(_points, 0, sizeof(_points));
}

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(&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[i].pressed = 0;
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(&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 =
void touch_event_callback(struct input_event *evt, void *user_data) {
static int8_t index = 0;
static bool sem_taken = false;

static const struct device *const dev =
DEVICE_DT_GET(DT_CHOSEN(zephyr_touch));
Arduino_GigaDisplayTouch *touch = (Arduino_GigaDisplayTouch *)user_data;

if (evt->dev != touch_dev) {
if (!touch || evt->dev != dev) {
return;
}

// Take semaphore on first event.
if (evt->code == INPUT_ABS_MT_SLOT) {
// Check if the semaphore is already taken by this callback.
// This could only happen if the event queue dropped BTN_TOUCH.
if (!sem_taken && k_sem_take(&touch_sem, K_NO_WAIT) != 0) {
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;
index = evt->value;
touch->_points[index].trackId = evt->value;
break;
case INPUT_ABS_X:
zephyr_touch_points[zephyr_touch_cb_slot_num].x = evt->value;
touch->_points[index].x = evt->value;
break;
case INPUT_ABS_Y:
zephyr_touch_points[zephyr_touch_cb_slot_num].y = evt->value;
touch->_points[index].y = evt->value;
break;
case INPUT_BTN_TOUCH:
zephyr_touch_points[zephyr_touch_cb_slot_num].pressed = evt->value;
touch->_points[index].pressed = evt->value;
break;
}

if (evt->sync) {
k_sem_give(&zephyr_touch_event_sync);
// Release the semaphore on the last event (BTN_TOUCH pressed).
if (evt->code == INPUT_BTN_TOUCH && evt->value) {
sem_taken = false;
k_sem_give(&touch_sem);
if (touch->_gt911TouchHandler) {
touch->_gt911TouchHandler(GT911_MAX_CONTACTS, touch->_points);
}
}
}
#endif