Merge pull request #1937 from yangfasheng/master

add touch driver; update lcd driver;
This commit is contained in:
Bernard Xiong 2018-10-31 10:38:13 +08:00 committed by GitHub
commit 62c3e74e3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 826 additions and 351 deletions

View File

@ -38,8 +38,6 @@ if GetDepend('RT_USING_I2C'):
# add lcd driver code
if GetDepend('RT_USING_LCD'):
src += ['drv_lcd.c']
if GetDepend('BOARD_RT1050_EVK') and GetDepend('PKG_USING_GUIENGINE'):
src += ['drv_ft5406.c']
# add sdio driver code
if GetDepend('RT_USING_SDIO'):
@ -68,6 +66,9 @@ if GetDepend('BOARD_RT1050_ATK') and GetDepend('RT_USING_LWIP'):
if GetDepend('RT_USING_AUDIO'):
src += ['drv_codec.c', 'fsl_wm8960.c']
if GetDepend('PKG_USING_GUIENGINE'):
src += Glob('touch/*.c')
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES=CPPDEFINES)
Return('group')

View File

@ -1,340 +0,0 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-08-08 Yang the first version
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <finsh.h>
#include <rtgui/event.h>
#include <rtgui/rtgui_server.h>
#include "board.h"
#include "fsl_gpio.h"
#include "fsl_lpi2c.h"
#define BSP_TOUCH_SAMPLE_HZ 30
#define I2CBUS_NAME "i2c1"
#if 0
#define FTDEBUG rt_kprintf
#else
#define FTDEBUG(...)
#endif
#define TOUCH_SLP_TIME (RT_TICK_PER_SECOND * 5)
#define FT5206_TS_ADDR 0x38
#define TP_MAX_TOUCH_POINT 2
enum ft5x0x_ts_regs
{
FT5X0X_REG_THGROUP = 0x80,
FT5X0X_REG_THPEAK = 0x81,
FT5X0X_REG_THCAL = 0x82,
FT5X0X_REG_THWATER = 0x83,
FT5X0X_REG_THTEMP = 0x84,
FT5X0X_REG_THDIFF = 0x85,
FT5X0X_REG_CTRL = 0x86,
FT5X0X_REG_TIMEENTERMONITOR = 0x87,
FT5X0X_REG_PERIODACTIVE = 0x88,
FT5X0X_REG_PERIODMONITOR = 0x89,
FT5X0X_REG_HEIGHT_B = 0x8a,
FT5X0X_REG_MAX_FRAME = 0x8b,
FT5X0X_REG_DIST_MOVE = 0x8c,
FT5X0X_REG_DIST_POINT = 0x8d,
FT5X0X_REG_FEG_FRAME = 0x8e,
FT5X0X_REG_SINGLE_CLICK_OFFSET = 0x8f,
FT5X0X_REG_DOUBLE_CLICK_TIME_MIN = 0x90,
FT5X0X_REG_SINGLE_CLICK_TIME = 0x91,
FT5X0X_REG_LEFT_RIGHT_OFFSET = 0x92,
FT5X0X_REG_UP_DOWN_OFFSET = 0x93,
FT5X0X_REG_DISTANCE_LEFT_RIGHT = 0x94,
FT5X0X_REG_DISTANCE_UP_DOWN = 0x95,
FT5X0X_REG_ZOOM_DIS_SQR = 0x96,
FT5X0X_REG_RADIAN_VALUE = 0x97,
FT5X0X_REG_MAX_X_HIGH = 0x98,
FT5X0X_REG_MAX_X_LOW = 0x99,
FT5X0X_REG_MAX_Y_HIGH = 0x9a,
FT5X0X_REG_MAX_Y_LOW = 0x9b,
FT5X0X_REG_K_X_HIGH = 0x9c,
FT5X0X_REG_K_X_LOW = 0x9d,
FT5X0X_REG_K_Y_HIGH = 0x9e,
FT5X0X_REG_K_Y_LOW = 0x9f,
FT5X0X_REG_AUTO_CLB_MODE = 0xa0,
FT5X0X_REG_LIB_VERSION_H = 0xa1,
FT5X0X_REG_LIB_VERSION_L = 0xa2,
FT5X0X_REG_CIPHER = 0xa3,
FT5X0X_REG_G_MODE = 0xa4,
FT5X0X_REG_PMODE = 0xa5, /* Power Consume Mode */
FT5X0X_REG_FIRMID = 0xa6,
FT5X0X_REG_STATE = 0xa7,
FT5X0X_REG_VENDID = 0xa8,
FT5X0X_REG_ERR = 0xa9,
FT5X0X_REG_CLB = 0xaa,
};
#define CTRL_NOAUTO_MONITOR 0x00
#define CTRL_AUTO_MONITOR 0x01
#define PMODE_ACTIVE 0x00
#define PMODE_MONITOR 0x01
#define PMODE_STANDBY 0x02
#define PMODE_HIBERNATE 0x03
#define G_MODE_POLLING 0x00
#define G_MODE_TRIGGER 0x01
typedef enum _touch_event
{
kTouch_Down = 0, /*!< The state changed to touched. */
kTouch_Up = 1, /*!< The state changed to not touched. */
kTouch_Contact = 2, /*!< There is a continuous touch being detected. */
kTouch_Reserved = 3 /*!< No touch information available. */
} touch_event_t;
typedef struct _touch_point
{
touch_event_t TOUCH_EVENT; /*!< Indicates the state or event of the touch point. */
uint8_t TOUCH_ID; /*!< Id of the touch point. This numeric value stays constant between down and up event. */
uint16_t TOUCH_X; /*!< X coordinate of the touch point */
uint16_t TOUCH_Y; /*!< Y coordinate of the touch point */
} touch_point_t;
typedef struct _ft5406_touch_point
{
uint8_t XH;
uint8_t XL;
uint8_t YH;
uint8_t YL;
uint8_t RESERVED[2];
} ft5406_touch_point_t;
typedef struct _ft5406_touch_data
{
uint8_t DEVIDE_MODE;
uint8_t GEST_ID;
uint8_t TD_STATUS;
ft5406_touch_point_t TOUCH;
} ft5406_touch_data_t;
#define TOUCH_POINT_GET_EVENT(T) ((touch_event_t)((T).XH >> 6))
#define TOUCH_POINT_GET_ID(T) ((T).YH >> 4)
#define TOUCH_POINT_GET_X(T) ((((T).XH & 0x0f) << 8) | (T).XL)
#define TOUCH_POINT_GET_Y(T) ((((T).YH & 0x0f) << 8) | (T).YL)
static struct rt_i2c_bus_device *_i2c_bus;
static struct rt_semaphore _tp_sem;
static int _ft5406_read(unsigned char cmd,
void *buf,
size_t len)
{
struct rt_i2c_msg msgs[2];
msgs[0].addr = FT5206_TS_ADDR;
msgs[0].flags = RT_I2C_WR;
msgs[0].buf = &cmd;
msgs[0].len = sizeof(cmd);
msgs[1].addr = FT5206_TS_ADDR;
msgs[1].flags = RT_I2C_RD;
msgs[1].buf = buf;
msgs[1].len = len;
if (rt_i2c_transfer(_i2c_bus, msgs, 2) == 2)
return len;
else
return -1;
}
static int ft5406_read_touch(touch_point_t *dp)
{
ft5406_touch_data_t touch_data;
_ft5406_read(0, &touch_data, sizeof(ft5406_touch_data_t));
FTDEBUG("GEST_ID: %02x, TD_STATUS: %02x\n", touch_data.GEST_ID, touch_data.TD_STATUS);
FTDEBUG("XH: %02x, XL: %02x, XH: %02x, XH: %02x, XH: %02x, RESERVED[0]: %02x, RESERVED[1]: %02x\n",
touch_data.TOUCH.XH, touch_data.TOUCH.XL,
touch_data.TOUCH.YH, touch_data.TOUCH.YL,
touch_data.TOUCH.RESERVED[0], touch_data.TOUCH.RESERVED[1]);
dp->TOUCH_X = TOUCH_POINT_GET_Y(touch_data.TOUCH);
dp->TOUCH_Y = TOUCH_POINT_GET_X(touch_data.TOUCH);
FTDEBUG(" ==> status : %d (%d, %d)\n", touch_data.TD_STATUS, dp->TOUCH_X, dp->TOUCH_Y);
if (touch_data.TD_STATUS != 0)
return 0;
else
return -1;
}
static void _touch_session()
{
touch_point_t tpd;
#ifdef RT_USING_RTGUI
struct rtgui_event_mouse emouse;
#endif
ft5406_read_touch(&tpd);
#ifdef RT_USING_RTGUI
emouse.parent.sender = RT_NULL;
emouse.wid = RT_NULL;
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
emouse.x = tpd.TOUCH_X;
emouse.y = tpd.TOUCH_Y;
emouse.ts = rt_tick_get();
emouse.id = emouse.ts;
if (emouse.id == 0) emouse.id = 1;
rtgui_server_post_event(&emouse.parent, sizeof(emouse));
#endif
do
{
rt_thread_delay(RT_TICK_PER_SECOND / BSP_TOUCH_SAMPLE_HZ);
if (ft5406_read_touch(&tpd) != 0)
break;
#ifdef RT_USING_RTGUI
emouse.parent.type = RTGUI_EVENT_MOUSE_MOTION;
emouse.x = tpd.TOUCH_X;
emouse.y = tpd.TOUCH_Y;
emouse.ts = rt_tick_get();
rtgui_server_post_event(&emouse.parent, sizeof(emouse));
#endif
}
while (1);
#ifdef RT_USING_RTGUI
/* Always send touch up event. */
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP;
emouse.x = tpd.TOUCH_X;
emouse.y = tpd.TOUCH_Y;
emouse.ts = rt_tick_get();
rtgui_server_post_event(&emouse.parent, sizeof(emouse));
#endif
//} while (rt_sem_take(&_tp_sem, TOUCH_SLP_TIME) == RT_EOK);
}
void touch_down(void)
{
rt_sem_release(&_tp_sem);
}
static void _touch(void *p)
{
int io_s;
gpio_pin_config_t pin_config =
{
kGPIO_DigitalInput, 0,
};
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_11_GPIO1_IO11, 0U);
/* Enable touch panel controller */
GPIO_PinInit(GPIO1, 11, &pin_config);
while(1)
{
rt_thread_delay(RT_TICK_PER_SECOND / 60);
io_s = GPIO_ReadPinInput(GPIO1, 11);
if (io_s == 0)
{
_touch_session();
}
else
continue;
}
}
static rt_device_t _i2c_find(const char *name)
{
rt_device_t dev;
dev = rt_device_find(name);
if (!dev)
{
rt_kprintf("search device failed: %s\n", name);
return RT_NULL;
}
if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
{
rt_kprintf("open device failed: %s\n", name);
return RT_NULL;
}
rt_kprintf("open i2c bus: %s\n", name);
return dev;
}
static void ft5406_hw_reset(void)
{
gpio_pin_config_t pin_config =
{
kGPIO_DigitalOutput, 0,
};
CLOCK_EnableClock(kCLOCK_Gpio1);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_02_GPIO1_IO02, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_02_GPIO1_IO02, 0x10B0u);
/* Enable touch panel controller */
GPIO_PinInit(GPIO1, 2, &pin_config);
GPIO_WritePinOutput(GPIO1, 2, 1);
rt_thread_delay(RT_TICK_PER_SECOND / 20);
GPIO_WritePinOutput(GPIO1, 2, 0);
rt_thread_delay(RT_TICK_PER_SECOND / 20);
GPIO_WritePinOutput(GPIO1, 2, 1);
}
int ft5406_hw_init(void)
{
rt_thread_t tid;
rt_device_t dev = _i2c_find(I2CBUS_NAME);
if (dev == RT_NULL)
{
FTDEBUG("search i2c device faild: %s\n", I2CBUS_NAME);
return -1;
}
else
{
FTDEBUG("ft5406 set i2c bus to %s\n", I2CBUS_NAME);
_i2c_bus = (struct rt_i2c_bus_device *)dev;
}
ft5406_hw_reset();
rt_sem_init(&_tp_sem, "touch", 0, RT_IPC_FLAG_FIFO);
tid = rt_thread_create("touch", _touch, RT_NULL, 2048, 10, 20);
if (!tid)
{
rt_device_close(dev);
return -1;
}
rt_thread_startup(tid);
return 0;
}
INIT_APP_EXPORT(ft5406_hw_init);

View File

@ -35,13 +35,19 @@ struct rt1050_lcd
};
static struct rt1050_lcd lcd;
ALIGN(64) static uint16_t frame_buffer[LCD_HEIGHT][LCD_WIDTH] SECTION("NonCacheable");
static volatile int fb_index = 0;
static volatile rt_bool_t fb_modified = RT_TRUE;
ALIGN(64) static uint16_t frame_buffer0[LCD_HEIGHT][LCD_WIDTH] SECTION("NonCacheable");
ALIGN(64) static uint16_t frame_buffer1[LCD_HEIGHT][LCD_WIDTH] SECTION("NonCacheable");
static rt_err_t rt1050_lcd_init(rt_device_t device)
{
RT_ASSERT(device != RT_NULL);
rt_memset(frame_buffer, 0x00, sizeof(frame_buffer));
memset(frame_buffer0, 0x00, sizeof(frame_buffer0));
memset(frame_buffer1, 0x00, sizeof(frame_buffer1));
/* DeInit Video PLL. */
CLOCK_DeinitVideoPll();
@ -145,7 +151,7 @@ static rt_err_t rt1050_lcd_init(rt_device_t device)
lcd_config.panelHeight = LCD_HEIGHT;
lcd_config.pixelFormat = kELCDIF_PixelFormatRGB565;
lcd_config.dataBus = kELCDIF_DataBus16Bit;
lcd_config.bufferAddr = (uint32_t)frame_buffer;
lcd_config.bufferAddr = (uint32_t)frame_buffer0;
ELCDIF_RgbModeInit(LCDIF, &lcd_config);
ELCDIF_RgbModeStart(LCDIF);
@ -155,16 +161,58 @@ static rt_err_t rt1050_lcd_init(rt_device_t device)
lcd.info.height = LCD_HEIGHT;
lcd.info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565;
lcd.info.bits_per_pixel = 16;
lcd.info.framebuffer = (void *)frame_buffer;
lcd.info.framebuffer = (void *)rt_malloc_align(LCD_WIDTH * LCD_HEIGHT * 2, 32);
return RT_EOK;
}
void LCDIF_IRQHandler(void)
{
uint32_t intStatus;
intStatus = ELCDIF_GetInterruptStatus(LCDIF);
ELCDIF_ClearInterruptStatus(LCDIF, intStatus);
if (intStatus & kELCDIF_CurFrameDone)
{
fb_modified = RT_TRUE;
}
}
static rt_err_t rt1050_lcd_control(rt_device_t device, int cmd, void *args)
{
switch (cmd)
{
case RTGRAPHIC_CTRL_RECT_UPDATE:
{
uint8_t *ptr;
if (fb_index == 0)
{
ptr = (uint8_t *)&frame_buffer1[0];
}
else
{
ptr = (uint8_t *)&frame_buffer0[0];
}
while(LCDIF->CUR_BUF != LCDIF->NEXT_BUF);
memcpy(ptr, lcd.info.framebuffer, LCD_WIDTH * LCD_HEIGHT * 2);
if (fb_index == 0)
{
/* use fb1 */
ELCDIF_SetNextBufferAddr(LCDIF, (uint32_t)&frame_buffer1[0]);
fb_index = 1;
}
else
{
/* use fb0 */
ELCDIF_SetNextBufferAddr(LCDIF, (uint32_t)&frame_buffer0[0]);
fb_index = 0;
}
}
break;
case RTGRAPHIC_CTRL_POWERON:
@ -176,7 +224,7 @@ static rt_err_t rt1050_lcd_control(rt_device_t device, int cmd, void *args)
break;
case RTGRAPHIC_CTRL_GET_INFO:
rt_memcpy(args, &lcd.info, sizeof(lcd.info));
memcpy(args, &lcd.info, sizeof(lcd.info));
break;
case RTGRAPHIC_CTRL_SET_MODE:

View File

@ -0,0 +1,253 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-02-08 Zhangyihong the first version
* 2018-10-29 XY
*/
#include "drv_touch.h"
#define TOUCH_I2C_NAME "i2c1"
#ifndef TOUCH_SAMPLE_HZ
#define TOUCH_SAMPLE_HZ (50)
#endif
#ifndef TOUCH_I2C_NAME
#error "Please define touch i2c name!"
#endif
#ifdef PKG_USING_GUIENGINE
#include <rtgui/event.h>
#include <rtgui/rtgui_server.h>
#endif
#if 0
#define TPDEBUG rt_kprintf
#else
#define TPDEBUG(...)
#endif
static rt_slist_t _driver_list;
static struct rt_i2c_bus_device *i2c_bus = RT_NULL;
static void post_down_event(rt_uint16_t x, rt_uint16_t y, rt_uint32_t id)
{
#ifdef PKG_USING_GUIENGINE
rt_err_t result;
struct rtgui_event_mouse emouse;
emouse.parent.sender = RT_NULL;
emouse.wid = RT_NULL;
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
emouse.x = x;
emouse.y = y;
emouse.ts = rt_tick_get();
emouse.id = id;
do
{
result = rtgui_server_post_event(&emouse.parent, sizeof(emouse));
if (result != RT_EOK)
{
rt_thread_delay(RT_TICK_PER_SECOND / TOUCH_SAMPLE_HZ);
}
}
while (result != RT_EOK);
TPDEBUG("[TP] touch down [%d, %d]\n", emouse.x, emouse.y);
#endif
}
static void post_motion_event(rt_uint16_t x, rt_uint16_t y, rt_uint32_t id)
{
#ifdef PKG_USING_GUIENGINE
struct rtgui_event_mouse emouse;
emouse.parent.sender = RT_NULL;
emouse.wid = RT_NULL;
emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN;
emouse.parent.type = RTGUI_EVENT_MOUSE_MOTION;
emouse.x = x;
emouse.y = y;
emouse.ts = rt_tick_get();
emouse.id = id;
rtgui_server_post_event(&emouse.parent, sizeof(emouse));
TPDEBUG("[TP] touch motion [%d, %d]\n", emouse.x, emouse.y);
#endif
}
static void post_up_event(rt_uint16_t x, rt_uint16_t y, rt_uint32_t id)
{
#ifdef PKG_USING_GUIENGINE
rt_err_t result;
struct rtgui_event_mouse emouse;
emouse.parent.sender = RT_NULL;
emouse.wid = RT_NULL;
emouse.parent.type = RTGUI_EVENT_MOUSE_BUTTON;
emouse.button = RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP;
emouse.x = x;
emouse.y = y;
emouse.ts = rt_tick_get();
emouse.id = id;
do
{
result = rtgui_server_post_event(&emouse.parent, sizeof(emouse));
if (result != RT_EOK)
{
rt_thread_delay(RT_TICK_PER_SECOND / TOUCH_SAMPLE_HZ);
}
}
while (result != RT_EOK);
TPDEBUG("[TP] touch up [%d, %d]\n", emouse.x, emouse.y);
#endif
}
static void touch_run(void* parameter)
{
rt_tick_t emouse_id = 0;
struct touch_message msg;
rt_slist_t *driver_list = NULL;
struct touch_driver *current_driver = RT_NULL;
i2c_bus = rt_i2c_bus_device_find(TOUCH_I2C_NAME);
RT_ASSERT(i2c_bus);
if(rt_device_open(&i2c_bus->parent, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
{
return;
}
rt_slist_for_each(driver_list, &_driver_list)
{
current_driver = (struct touch_driver *)driver_list;
if(current_driver->probe(i2c_bus) == RT_TRUE)
{
break;
}
current_driver = RT_NULL;
}
if(current_driver == RT_NULL)
{
rt_kprintf("[TP] No touch pad or driver.\n");
rt_device_close((rt_device_t)i2c_bus);
return;
}
current_driver->ops->init(i2c_bus);
while (1)
{
if (rt_sem_take(current_driver->isr_sem, RT_WAITING_FOREVER) != RT_EOK)
{
continue;
}
if (current_driver->ops->read_point(&msg) != RT_EOK)
{
continue;
}
switch (msg.event)
{
case TOUCH_EVENT_MOVE:
post_motion_event(msg.x, msg.y, emouse_id);
break;
case TOUCH_EVENT_DOWN:
emouse_id = rt_tick_get();
post_down_event(msg.x, msg.y, emouse_id);
break;
case TOUCH_EVENT_UP:
post_up_event(msg.x, msg.y, emouse_id);
break;
default:
break;
}
rt_thread_delay(RT_TICK_PER_SECOND / TOUCH_SAMPLE_HZ);
}
}
rt_err_t rt_touch_drivers_register(touch_driver_t drv)
{
RT_ASSERT(drv != RT_NULL);
RT_ASSERT(drv->ops != RT_NULL);
RT_ASSERT(drv->probe != RT_NULL);
rt_slist_append(&_driver_list, &drv->list);
return RT_EOK;
}
static int rt_touch_list_init(void)
{
rt_slist_init(&_driver_list);
return RT_EOK;
}
INIT_BOARD_EXPORT(rt_touch_list_init);
static int rt_touch_init(void)
{
rt_thread_t thread = RT_NULL;
thread = rt_thread_create("touch", touch_run, RT_NULL, 2048, 28, 20);
if(thread)
{
return rt_thread_startup(thread);
}
return RT_ERROR;
}
INIT_APP_EXPORT(rt_touch_init);
int rt_touch_read(rt_uint16_t addr, void *cmd_buf, size_t cmd_len, void *data_buf, size_t data_len)
{
struct rt_i2c_msg msgs[2];
msgs[0].addr = addr;
msgs[0].flags = RT_I2C_WR;
msgs[0].buf = cmd_buf;
msgs[0].len = cmd_len;
msgs[1].addr = addr;
msgs[1].flags = RT_I2C_RD;
msgs[1].buf = data_buf;
msgs[1].len = data_len;
if (rt_i2c_transfer(i2c_bus, msgs, 2) == 2)
return 0;
else
return -1;
}
int rt_touch_write(rt_uint16_t addr, void *data_buf, size_t data_len)
{
struct rt_i2c_msg msgs[1];
msgs[0].addr = addr;
msgs[0].flags = RT_I2C_WR;
msgs[0].buf = data_buf;
msgs[0].len = data_len;
if (rt_i2c_transfer(i2c_bus, msgs, 1) == 1)
return 0;
else
return -1;
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-02-08 Zhangyihong the first version
* 2018-10-29 XY
*/
#ifndef __DRV_TOUCH_H__
#define __DRV_TOUCH_H__
#include "rtthread.h"
#include "rtdevice.h"
#define TOUCH_EVENT_UP (0x01)
#define TOUCH_EVENT_DOWN (0x02)
#define TOUCH_EVENT_MOVE (0x03)
#define TOUCH_EVENT_NONE (0x80)
struct touch_message
{
rt_uint16_t x;
rt_uint16_t y;
rt_uint8_t event;
};
typedef struct touch_message *touch_message_t;
struct touch_ops
{
void (*init)(struct rt_i2c_bus_device *);
void (*deinit)(void);
rt_err_t (*read_point)(touch_message_t);
};
typedef struct touch_ops *touch_ops_t;
struct touch_driver
{
rt_slist_t list;
rt_bool_t (*probe)(struct rt_i2c_bus_device *i2c_bus);
rt_sem_t isr_sem;
touch_ops_t ops;
void *user_data;
};
typedef struct touch_driver *touch_driver_t;
rt_err_t rt_touch_drivers_register(touch_driver_t drv);
int rt_touch_read(rt_uint16_t addr, void *cmd_buf, size_t cmd_len, void *data_buf, size_t data_len);
int rt_touch_write(rt_uint16_t addr, void *data_buf, size_t data_len);
#endif

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-08-08 Yang the first version
* 2018-10-29 XY
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_touch.h"
#include "fsl_iomuxc.h"
#include "fsl_gpio.h"
#define TP_INT_PIN 54 /* GPIO_AD_B0_11 */
#define TP_RST_PIN 45 /* GPIO_AD_B0_02 */
#define FT5x06_TS_ADDR (0x38)
#if 0
#define TPDEBUG rt_kprintf
#else
#define TPDEBUG(...)
#endif
static struct touch_driver ft5x06_driver;
typedef enum _touch_event
{
kTouch_Down = 0, /*!< The state changed to touched. */
kTouch_Up = 1, /*!< The state changed to not touched. */
kTouch_Contact = 2, /*!< There is a continuous touch being detected. */
kTouch_Reserved = 3 /*!< No touch information available. */
} touch_event_t;
typedef struct _touch_point
{
touch_event_t TOUCH_EVENT; /*!< Indicates the state or event of the touch point. */
uint8_t TOUCH_ID; /*!< Id of the touch point. This numeric value stays constant between down and up event. */
uint16_t TOUCH_X; /*!< X coordinate of the touch point */
uint16_t TOUCH_Y; /*!< Y coordinate of the touch point */
} touch_point_t;
typedef struct _ft5406_touch_point
{
uint8_t XH;
uint8_t XL;
uint8_t YH;
uint8_t YL;
uint8_t RESERVED[2];
} ft5406_touch_point_t;
typedef struct _ft5406_touch_data
{
uint8_t DEVIDE_MODE;
uint8_t GEST_ID;
uint8_t TD_STATUS;
ft5406_touch_point_t TOUCH;
} ft5406_touch_data_t;
#define TOUCH_POINT_GET_EVENT(T) ((touch_event_t)((T).XH >> 6))
#define TOUCH_POINT_GET_ID(T) ((T).YH >> 4)
#define TOUCH_POINT_GET_X(T) ((((T).XH & 0x0f) << 8) | (T).XL)
#define TOUCH_POINT_GET_Y(T) ((((T).YH & 0x0f) << 8) | (T).YL)
static int ft5406_read_touch(touch_point_t *dp)
{
rt_uint8_t cmd = 0;
ft5406_touch_data_t touch_data;
if (rt_touch_read(FT5x06_TS_ADDR, &cmd, 1, &touch_data, sizeof(ft5406_touch_data_t)) != 0)
return -1;
dp->TOUCH_X = TOUCH_POINT_GET_Y(touch_data.TOUCH);
dp->TOUCH_Y = TOUCH_POINT_GET_X(touch_data.TOUCH);
dp->TOUCH_EVENT = TOUCH_POINT_GET_EVENT(touch_data.TOUCH);
dp->TOUCH_ID = TOUCH_POINT_GET_ID(touch_data.TOUCH);
if (dp->TOUCH_EVENT == 3) return -1;
if (touch_data.TD_STATUS != 0)
return 0;
else
return -1;
}
static void ft5x06_isr_enable(rt_bool_t enable)
{
if(enable == RT_TRUE)
{
rt_pin_irq_enable(TP_INT_PIN, PIN_IRQ_ENABLE);
}
else
{
rt_pin_irq_enable(TP_INT_PIN, PIN_IRQ_DISABLE);
}
}
static void ft5x06_touch_isr(void *parameter)
{
TPDEBUG("[TP] ft5x06_touch_isr\n");
ft5x06_isr_enable(RT_FALSE);
rt_sem_release(ft5x06_driver.isr_sem);
}
static rt_err_t ft5x06_read_point(touch_message_t msg)
{
touch_point_t dp;
if (ft5406_read_touch(&dp) != 0)
{
msg->event = TOUCH_EVENT_UP;
}
else
{
if (dp.TOUCH_EVENT == kTouch_Up)
{
msg->event = TOUCH_EVENT_UP;
}
else if (dp.TOUCH_EVENT == kTouch_Down)
{
msg->event = TOUCH_EVENT_DOWN;
}
else if (dp.TOUCH_EVENT == kTouch_Contact)
{
msg->event = TOUCH_EVENT_MOVE;
}
else
{
msg->event = TOUCH_EVENT_UP;
}
}
msg->x = dp.TOUCH_X;
msg->y = dp.TOUCH_Y;
TPDEBUG("[TP] [%d, %d] %s\n", msg->x, msg->y,
msg->event == TOUCH_EVENT_DOWN ? "DOWN" : (msg->event == TOUCH_EVENT_MOVE ? "MOVE" : (msg->event == TOUCH_EVENT_UP ? "UP" : "NONE")));
if (msg->event != TOUCH_EVENT_UP)
{
rt_sem_release(ft5x06_driver.isr_sem);
}
else
{
ft5x06_isr_enable(RT_TRUE);
}
return RT_EOK;
}
static void ft5x06_init(struct rt_i2c_bus_device *i2c_bus)
{
ft5x06_driver.isr_sem = rt_sem_create("ft5x06", 0, RT_IPC_FLAG_FIFO);
RT_ASSERT(ft5x06_driver.isr_sem);
rt_pin_attach_irq(TP_INT_PIN, PIN_IRQ_MODE_LOW_LEVEL, ft5x06_touch_isr, &ft5x06_driver);
rt_pin_irq_enable(TP_INT_PIN, PIN_IRQ_ENABLE);
rt_thread_delay(RT_TICK_PER_SECOND / 5);
}
static void ft5x06_deinit(void)
{
if (ft5x06_driver.isr_sem)
{
rt_sem_delete(ft5x06_driver.isr_sem);
ft5x06_driver.isr_sem = RT_NULL;
}
}
struct touch_ops ft5x06_ops =
{
ft5x06_init,
ft5x06_deinit,
ft5x06_read_point,
};
static void ft5406_hw_reset(void)
{
gpio_pin_config_t pin_config =
{
kGPIO_DigitalOutput, 0,
};
CLOCK_EnableClock(kCLOCK_Gpio1);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_02_GPIO1_IO02, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_02_GPIO1_IO02, 0x10B0u);
/* Enable touch panel controller */
GPIO_PinInit(GPIO1, 2, &pin_config);
GPIO_WritePinOutput(GPIO1, 2, 1);
rt_thread_delay(RT_TICK_PER_SECOND / 20);
GPIO_WritePinOutput(GPIO1, 2, 0);
rt_thread_delay(RT_TICK_PER_SECOND / 20);
GPIO_WritePinOutput(GPIO1, 2, 1);
}
static rt_bool_t ft5x06_probe(struct rt_i2c_bus_device *i2c_bus)
{
rt_uint16_t cmd = 0x000c;
rt_uint16_t tmp[2];
rt_uint16_t CurVersion;
ft5406_hw_reset();
if (rt_touch_read(FT5x06_TS_ADDR, &cmd, 2, tmp, 2) != 0)
{
TPDEBUG("[TP] %s failed!\n", __func__);
return RT_FALSE;
}
CurVersion = (tmp[0]<<8) | tmp[1];
rt_kprintf("[TP] FT5X06 Touch Version : %d\n", CurVersion);
return RT_TRUE;
}
int ft5x06_driver_register(void)
{
ft5x06_driver.probe = ft5x06_probe;
ft5x06_driver.ops = &ft5x06_ops;
ft5x06_driver.user_data = RT_NULL;
rt_touch_drivers_register(&ft5x06_driver);
return 0;
}
INIT_ENV_EXPORT(ft5x06_driver_register);

View File

@ -0,0 +1,225 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-02-08 Zhangyihong the first version
* 2018-04-03 XY gt9xx for 1024 * 600
* 2018-04-14 liu2guang optimize int and rst to pin framework
* 2018-10-29 XY
*/
#include "drv_touch.h"
#include "string.h"
#include "drv_pin.h"
#define TP_INT_PIN 54 /* GPIO_AD_B0_11 */
#define TP_RST_PIN 45 /* GPIO_AD_B0_02 */
#ifndef TP_INT_PIN
#error "Please config touch panel INT pin."
#endif
#ifndef TP_RST_PIN
#error "Please config touch panel RST pin."
#endif
#ifndef IIC_RETRY_NUM
#define IIC_RETRY_NUM 2
#endif
#define GT9xx_TS_ADDR (0x5D)
#define gt9xx_READ_XY_REG (0x814E) /* 坐标寄存器 */
#define gt9xx_CLEARBUF_REG (0x814E) /* 清除坐标寄存器 */
#define gt9xx_CONFIG_REG (0x8047) /* 配置参数寄存器 */
#define gt9xx_COMMAND_REG (0x8040) /* 实时命令 */
#define gt9xx_PRODUCT_ID_REG (0x8140) /* 产品ID */
#define gt9xx_VENDOR_ID_REG (0x814A) /* 当前模组选项信息 */
#define gt9xx_CONFIG_VERSION_REG (0x8047) /* 配置文件版本号 */
#define gt9xx_CONFIG_CHECKSUM_REG (0x80FF) /* 配置文件校验码 */
#define gt9xx_FIRMWARE_VERSION_REG (0x8144) /* 固件版本号 */
#if 0
#define TPDEBUG rt_kprintf
#else
#define TPDEBUG(...)
#endif
static struct touch_driver gt9xx_driver;
static void gt9xx_hw_reset(rt_uint8_t address)
{
rt_pin_mode(TP_INT_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(TP_RST_PIN, PIN_MODE_OUTPUT);
if(address == 0x5D)
{
rt_pin_write(TP_INT_PIN, PIN_LOW);
rt_pin_write(TP_RST_PIN, PIN_LOW);
rt_thread_delay(RT_TICK_PER_SECOND / 50);
rt_pin_write(TP_RST_PIN, PIN_HIGH);
rt_pin_write(TP_INT_PIN, PIN_LOW);
rt_thread_delay(RT_TICK_PER_SECOND / 50);
}
else
{
rt_pin_write(TP_INT_PIN, PIN_LOW);
rt_pin_write(TP_RST_PIN, PIN_LOW);
rt_thread_delay(RT_TICK_PER_SECOND / 50);
rt_pin_write(TP_RST_PIN, PIN_LOW);
rt_pin_write(TP_INT_PIN, PIN_HIGH);
rt_thread_delay(RT_TICK_PER_SECOND / 50);
rt_pin_write(TP_RST_PIN, PIN_HIGH);
rt_thread_delay(RT_TICK_PER_SECOND / 50);
}
}
static void gt9xx_soft_reset(struct rt_i2c_bus_device *i2c_bus)
{
rt_uint8_t buf[3];
buf[0] = (rt_uint8_t)((gt9xx_COMMAND_REG >> 8) & 0xFF);
buf[1] = (rt_uint8_t)(gt9xx_COMMAND_REG & 0xFF);
buf[2] = 0x02;
rt_touch_write(GT9xx_TS_ADDR, buf, 3);
}
static rt_bool_t gt9xx_probe(struct rt_i2c_bus_device *i2c_bus)
{
rt_uint8_t cmd[2];
rt_uint8_t buffer[5] = {0};
gt9xx_hw_reset(GT9xx_TS_ADDR);
//gt9xx_soft_reset(i2c_bus);
rt_thread_delay(RT_TICK_PER_SECOND / 5);
cmd[0] = (rt_uint8_t)((gt9xx_PRODUCT_ID_REG >> 8) & 0xFF);
cmd[1] = (rt_uint8_t)(gt9xx_PRODUCT_ID_REG & 0xFF);
if (rt_touch_read(GT9xx_TS_ADDR, &cmd, 2, buffer, 4) != 0)
return RT_FALSE;
buffer[4] = '\0';
TPDEBUG("%#X %#X %#X %#X %#X\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]);
if(!rt_strcmp((const char*)buffer, "911"))
{
rt_kprintf("[TP] Found chip gt911\r\n");
return RT_TRUE;
}
else if(!rt_strcmp((const char*)buffer, "9147"))
{
rt_kprintf("[TP] Found chip gt9147\r\n");
return RT_TRUE;
}
else if(!rt_strcmp((const char*)buffer, "9157"))
{
rt_kprintf("[TP] Found chip gt9157\r\n");
return RT_TRUE;
}
else
{
TPDEBUG("[TP] Uknow chip gt9xx device: [%s]\r\n", buffer);
}
return RT_FALSE;
}
static void gt9xx_init(struct rt_i2c_bus_device *i2c_bus)
{
rt_uint8_t buf = 0;
rt_uint8_t cmd[2];
gt9xx_driver.isr_sem = rt_sem_create("gt9xx", 0, RT_IPC_FLAG_FIFO);
RT_ASSERT(gt9xx_driver.isr_sem);
cmd[0] = (rt_uint8_t)((gt9xx_CONFIG_VERSION_REG >> 8) & 0xFF);
cmd[1] = (rt_uint8_t)(gt9xx_CONFIG_VERSION_REG & 0xFF);
rt_touch_read(GT9xx_TS_ADDR, &cmd, 2, &buf, 1);
rt_kprintf("[TP] GT9xx Config version: 0x%02X\n", buf);
cmd[0] = (rt_uint8_t)((gt9xx_VENDOR_ID_REG >> 8) & 0xFF);
cmd[1] = (rt_uint8_t)(gt9xx_VENDOR_ID_REG & 0xFF);
rt_touch_read(GT9xx_TS_ADDR, &cmd, 2, &buf, 1);
rt_kprintf("[TP] GT9xx Sensor id: 0x%02X\n", buf);
rt_sem_release(gt9xx_driver.isr_sem);
}
static void gt9xx_deinit(void)
{
rt_sem_delete(gt9xx_driver.isr_sem);
}
static rt_err_t gt9xx_read_point(touch_message_t msg)
{
rt_uint8_t cmd[2];
rt_uint8_t buf[8] = {0};
static rt_uint8_t s_tp_down = 0;
cmd[0] = (rt_uint8_t)((gt9xx_READ_XY_REG >> 8) & 0xFF);
cmd[1] = (rt_uint8_t)(gt9xx_READ_XY_REG & 0xFF);
rt_touch_read(GT9xx_TS_ADDR, &cmd, 2, buf, 8);
if((buf[0] & 0x01) == 0)
{
if(s_tp_down)
{
s_tp_down = 0;
msg->event = TOUCH_EVENT_UP;
}
else
{
msg->event = TOUCH_EVENT_NONE;
}
}
else
{
msg->x = ((rt_uint16_t)buf[3] << 8) | buf[2];
msg->y = ((rt_uint16_t)buf[5] << 8) | buf[4];
if(s_tp_down)
{
msg->event = TOUCH_EVENT_MOVE;
}
else
{
msg->event = TOUCH_EVENT_DOWN;
s_tp_down = 1;
}
}
buf[0] = ((gt9xx_CLEARBUF_REG >> 8) & 0xFF);
buf[1] = (gt9xx_CLEARBUF_REG & 0xFF);
buf[2] = 0x00;
rt_touch_write(GT9xx_TS_ADDR, buf, 3);
rt_sem_release(gt9xx_driver.isr_sem);
return RT_EOK;
}
struct touch_ops gt9xx_ops =
{
.init = gt9xx_init,
.deinit = gt9xx_deinit,
.read_point = gt9xx_read_point,
};
static int gt9xx_driver_register(void)
{
gt9xx_driver.probe = gt9xx_probe;
gt9xx_driver.ops = &gt9xx_ops;
gt9xx_driver.user_data = RT_NULL;
rt_touch_drivers_register(&gt9xx_driver);
return RT_EOK;
}
INIT_ENV_EXPORT(gt9xx_driver_register);