mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-10 05:36:15 +00:00

This fixes bug #2880. Zephyr 3.2 made changes to how headers are reference (see [release notes](https://docs.zephyrproject.org/latest/releases/release-notes-3.2.html)). Work item [49578](https://github.com/zephyrproject-rtos/zephyr/issues/49578) deprecated the old headers names. The current WAMR codebase references these old headers, thus causing compile errors with current versions of Zephyr. This update adds #ifdefs around the header names. With this change, compiling with Zephyr 3.2.0 and above will use the new header files. Prior versions will use the existing code.
349 lines
8.5 KiB
C
349 lines
8.5 KiB
C
/**
|
|
* @file XPT2046.c
|
|
*/
|
|
/*********************
|
|
* INCLUDES
|
|
*********************/
|
|
#include "XPT2046.h"
|
|
#include "board_config.h"
|
|
#include "stdio.h"
|
|
#include <string.h>
|
|
#include "drivers/spi.h"
|
|
|
|
#if KERNEL_VERSION_NUMBER < 0x030200 /* version 3.2.0 */
|
|
#include <zephyr.h>
|
|
#include <kernel.h>
|
|
#else
|
|
#include <zephyr/kernel.h>
|
|
#endif
|
|
|
|
#if USE_XPT2046
|
|
|
|
#include <stddef.h>
|
|
|
|
#define abs(x) ((x) < 0 ? -(x) : (x))
|
|
|
|
/*********************
|
|
* DEFINES
|
|
*********************/
|
|
|
|
/**********************
|
|
* TYPEDEFS
|
|
**********************/
|
|
|
|
/**********************
|
|
* STATIC PROTOTYPES
|
|
**********************/
|
|
static void
|
|
xpt2046_corr(int16_t *x, int16_t *y);
|
|
#if 0
|
|
static void xpt2046_avg(int16_t * x, int16_t * y);
|
|
#endif
|
|
|
|
/**********************
|
|
* STATIC VARIABLES
|
|
**********************/
|
|
int16_t avg_buf_x[XPT2046_AVG];
|
|
int16_t avg_buf_y[XPT2046_AVG];
|
|
uint8_t avg_last;
|
|
|
|
/**********************
|
|
* MACROS
|
|
**********************/
|
|
|
|
/**********************
|
|
* GLOBAL FUNCTIONS
|
|
**********************/
|
|
|
|
/**
|
|
* Initialize the XPT2046
|
|
*/
|
|
struct device *input_dev;
|
|
|
|
struct spi_config spi_conf_xpt2046;
|
|
struct spi_cs_control xpt2046_cs_ctrl;
|
|
struct device *xpt2046_pen_gpio_dev;
|
|
static struct gpio_callback gpio_cb;
|
|
lv_indev_data_t touch_point;
|
|
lv_indev_data_t last_touch_point;
|
|
|
|
#define TOUCH_READ_THREAD_STACK_SIZE 4096
|
|
static K_THREAD_STACK_DEFINE(touch_read_thread_stack,
|
|
TOUCH_READ_THREAD_STACK_SIZE);
|
|
static struct k_thread touch_thread_data;
|
|
static struct k_sem sem_touch_read;
|
|
|
|
K_MUTEX_DEFINE(spi_display_touch_mutex);
|
|
|
|
int cnt = 0;
|
|
int touch_read_times = 0;
|
|
int last_pen_interrupt_time = 0;
|
|
void
|
|
xpt2046_pen_gpio_callback(struct device *port, struct gpio_callback *cb,
|
|
u32_t pins)
|
|
{
|
|
cnt++;
|
|
if ((k_uptime_get_32() - last_pen_interrupt_time) > 500) {
|
|
k_sem_give(&sem_touch_read);
|
|
touch_read_times++;
|
|
last_pen_interrupt_time = k_uptime_get_32();
|
|
}
|
|
}
|
|
|
|
void
|
|
disable_pen_interrupt()
|
|
{
|
|
int ret = 0;
|
|
ret = gpio_disable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN);
|
|
if (ret != 0) {
|
|
printf("gpio_pin_configure GPIO_INPUT failed\n");
|
|
}
|
|
}
|
|
void
|
|
enable_pen_interrupt()
|
|
{
|
|
int ret = 0;
|
|
ret = gpio_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN);
|
|
if (ret != 0) {
|
|
printf("gpio_pin_configure failed\n");
|
|
}
|
|
}
|
|
|
|
void
|
|
touch_screen_read_thread()
|
|
{
|
|
int i;
|
|
bool ret = false;
|
|
|
|
for (;;) {
|
|
k_sem_take(&sem_touch_read, K_FOREVER);
|
|
memset(&last_touch_point, 0, sizeof(lv_indev_data_t));
|
|
memset(&touch_point, 0, sizeof(lv_indev_data_t));
|
|
memset(avg_buf_x, 0, sizeof(avg_buf_x));
|
|
memset(avg_buf_y, 0, sizeof(avg_buf_y));
|
|
k_mutex_lock(&spi_display_touch_mutex, K_FOREVER);
|
|
disable_pen_interrupt();
|
|
for (i = 0; i < 100; i++) {
|
|
ret = xpt2046_read(&touch_point);
|
|
if (ret) {
|
|
if ((abs(last_touch_point.point.x - touch_point.point.x) < 4)
|
|
&& (abs(last_touch_point.point.y - touch_point.point.y)
|
|
< 4)) {
|
|
break;
|
|
}
|
|
last_touch_point = touch_point;
|
|
}
|
|
}
|
|
enable_pen_interrupt();
|
|
k_mutex_unlock(&spi_display_touch_mutex);
|
|
}
|
|
}
|
|
|
|
void
|
|
xpt2046_init(void)
|
|
{
|
|
int ret;
|
|
input_dev = device_get_binding(XPT2046_SPI_DEVICE_NAME);
|
|
|
|
if (input_dev == NULL) {
|
|
printf("device not found. Aborting test.");
|
|
return;
|
|
}
|
|
memset((void *)&touch_point, 0, sizeof(lv_indev_data_t));
|
|
|
|
spi_conf_xpt2046.frequency = XPT2046_SPI_MAX_FREQUENCY;
|
|
spi_conf_xpt2046.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
|
|
spi_conf_xpt2046.slave = 0;
|
|
spi_conf_xpt2046.cs = NULL;
|
|
#ifdef XPT2046_CS_GPIO_CONTROLLER
|
|
xpt2046_cs_ctrl.gpio_dev = device_get_binding(XPT2046_CS_GPIO_CONTROLLER);
|
|
if (xpt2046_cs_ctrl.gpio_dev == NULL) {
|
|
printk("Cannot find %s!\n", XPT2046_CS_GPIO_CONTROLLER);
|
|
return;
|
|
}
|
|
gpio_pin_configure(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN,
|
|
GPIO_OUTPUT);
|
|
gpio_pin_set(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN, 1);
|
|
xpt2046_cs_ctrl.gpio_pin = XPT2046_CS_GPIO_PIN;
|
|
xpt2046_cs_ctrl.delay = 0;
|
|
spi_conf_xpt2046.cs = &xpt2046_cs_ctrl;
|
|
|
|
#endif
|
|
|
|
#ifdef XPT2046_PEN_GPIO_CONTROLLER
|
|
|
|
xpt2046_pen_gpio_dev = device_get_binding(XPT2046_PEN_GPIO_CONTROLLER);
|
|
if (!xpt2046_pen_gpio_dev) {
|
|
printk("Cannot find %s!\n", XPT2046_PEN_GPIO_CONTROLLER);
|
|
return;
|
|
}
|
|
/* Setup GPIO input */
|
|
ret = gpio_pin_configure(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN,
|
|
(GPIO_INPUT | GPIO_INT_ENABLE | GPIO_INT_EDGE
|
|
| GPIO_INT_LOW_0 | GPIO_INT_DEBOUNCE));
|
|
if (ret) {
|
|
printk("Error configuring pin %d!\n", XPT2046_PEN_GPIO_PIN);
|
|
}
|
|
|
|
gpio_init_callback(&gpio_cb, xpt2046_pen_gpio_callback,
|
|
BIT(XPT2046_PEN_GPIO_PIN));
|
|
|
|
ret = gpio_add_callback(xpt2046_pen_gpio_dev, &gpio_cb);
|
|
if (ret) {
|
|
printk("gpio_add_callback error\n");
|
|
}
|
|
ret = gpio_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN);
|
|
if (ret) {
|
|
printk("gpio_enable_callback error\n");
|
|
}
|
|
#endif
|
|
|
|
k_sem_init(&sem_touch_read, 0, 1);
|
|
|
|
k_thread_create(&touch_thread_data, touch_read_thread_stack,
|
|
TOUCH_READ_THREAD_STACK_SIZE, touch_screen_read_thread,
|
|
NULL, NULL, NULL, 5, 0, K_NO_WAIT);
|
|
printf("xpt2046_init ok \n");
|
|
}
|
|
|
|
/**
|
|
* Get the current position and state of the touchpad
|
|
* @param data store the read data here
|
|
* @return false: because no ore data to be read
|
|
*/
|
|
bool
|
|
xpt2046_read(lv_indev_data_t *data)
|
|
{
|
|
static int16_t last_x = 0;
|
|
static int16_t last_y = 0;
|
|
bool valid = true;
|
|
int s32_ret = 0;
|
|
|
|
int16_t x = 0;
|
|
int16_t y = 0;
|
|
|
|
char tx1[16] = { 0 };
|
|
char rx1[16] = { 0 };
|
|
|
|
struct spi_buf tx_buf = { .buf = &tx1, .len = 3 };
|
|
struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 };
|
|
struct spi_buf rx_buf = { .buf = &rx1, .len = 3 };
|
|
struct spi_buf_set rx_bufs = { .buffers = &rx_buf, .count = 1 };
|
|
|
|
tx1[0] = CMD_X_READ;
|
|
s32_ret = spi_transceive(input_dev, &spi_conf_xpt2046, &tx_bufs, &rx_bufs);
|
|
if (s32_ret != 0) {
|
|
printf("spi_transceive return failed:%d\n", s32_ret);
|
|
}
|
|
x = rx1[1] << 8;
|
|
x += rx1[2];
|
|
|
|
tx1[0] = CMD_Y_READ;
|
|
s32_ret = spi_transceive(input_dev, &spi_conf_xpt2046, &tx_bufs, &rx_bufs);
|
|
if (s32_ret != 0) {
|
|
printf("spi_transceive return failed:%d\n", s32_ret);
|
|
}
|
|
y = rx1[1] << 8;
|
|
y += rx1[2];
|
|
x = x >> 3;
|
|
y = y >> 3;
|
|
|
|
xpt2046_corr(&x, &y);
|
|
if (y <= 0 || (x > 320)) {
|
|
valid = false;
|
|
}
|
|
|
|
last_x = x;
|
|
last_y = y;
|
|
|
|
data->point.x = x;
|
|
data->point.y = y;
|
|
data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**********************
|
|
* STATIC FUNCTIONS
|
|
**********************/
|
|
static void
|
|
xpt2046_corr(int16_t *x, int16_t *y)
|
|
{
|
|
#if XPT2046_XY_SWAP != 0
|
|
int16_t swap_tmp;
|
|
swap_tmp = *x;
|
|
*x = *y;
|
|
*y = swap_tmp;
|
|
#endif
|
|
|
|
if ((*x) > XPT2046_X_MIN)
|
|
(*x) -= XPT2046_X_MIN;
|
|
else
|
|
(*x) = 0;
|
|
|
|
if ((*y) > XPT2046_Y_MIN)
|
|
(*y) -= XPT2046_Y_MIN;
|
|
else
|
|
(*y) = 0;
|
|
|
|
(*x) = (uint32_t)((uint32_t)(*x) * XPT2046_HOR_RES)
|
|
/ (XPT2046_X_MAX - XPT2046_X_MIN);
|
|
|
|
(*y) = (uint32_t)((uint32_t)(*y) * XPT2046_VER_RES)
|
|
/ (XPT2046_Y_MAX - XPT2046_Y_MIN);
|
|
|
|
#if XPT2046_X_INV != 0
|
|
(*x) = XPT2046_HOR_RES - (*x);
|
|
#endif
|
|
|
|
#if XPT2046_Y_INV != 0
|
|
(*y) = XPT2046_VER_RES - (*y);
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
static void xpt2046_avg(int16_t * x, int16_t * y)
|
|
{
|
|
/*Shift out the oldest data*/
|
|
uint8_t i;
|
|
for (i = XPT2046_AVG - 1; i > 0; i--) {
|
|
avg_buf_x[i] = avg_buf_x[i - 1];
|
|
avg_buf_y[i] = avg_buf_y[i - 1];
|
|
}
|
|
|
|
/*Insert the new point*/
|
|
avg_buf_x[0] = *x;
|
|
avg_buf_y[0] = *y;
|
|
if (avg_last < XPT2046_AVG)
|
|
avg_last++;
|
|
|
|
/*Sum the x and y coordinates*/
|
|
int32_t x_sum = 0;
|
|
int32_t y_sum = 0;
|
|
for (i = 0; i < avg_last; i++) {
|
|
x_sum += avg_buf_x[i];
|
|
y_sum += avg_buf_y[i];
|
|
}
|
|
|
|
/*Normalize the sums*/
|
|
(*x) = (int32_t) x_sum / avg_last;
|
|
(*y) = (int32_t) y_sum / avg_last;
|
|
}
|
|
#endif
|
|
|
|
bool
|
|
touchscreen_read(lv_indev_data_t *data)
|
|
{
|
|
/*Store the collected data*/
|
|
data->point.x = last_touch_point.point.x;
|
|
data->point.y = last_touch_point.point.y;
|
|
data->state = last_touch_point.state;
|
|
|
|
if (last_touch_point.state == LV_INDEV_STATE_PR) {
|
|
last_touch_point.state = LV_INDEV_STATE_REL;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endif
|