之前写过一篇文章“arduino下使用LVGL的一些笔记(驱动CST816触摸屏、适配FFat内部文件系统)”,链接:arduino下使用LVGL的一些笔记(驱动CST816触摸屏、适配FFat内部文件系统)_littlefs lvgl-CSDN博客
其中简单提到了如何去适配触摸屏的驱动,这篇文件我们更加深入的去了解下如何把一个自己的触摸屏驱动(FT6336U为例)适配到LVGL中去。当然这里说的是LVGL中没有被集成的驱动。
一、LVGL触摸屏驱动API部分
首先,我们要了解LVGL是如何与触摸屏驱动之间进行API接口联系的。
1.设备注册
LVGL的初始化部分有如下注册输入设备驱动的代码,这里就是注册触摸屏的驱动了。
/*Initialize the (dummy) input device driver*/
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register(&indev_drv);
其中:
indev_drv.type = LV_INDEV_TYPE_POINTER;
代表指针型输入设备,比如触摸屏、鼠标等,意味着传给LVGL的最重要信息是坐标信息。
indev_drv.read_cb = my_touchpad_read;
这行是把读取坐标的函数作为回调函数注册给LVGL,my_touchpad_read是最重要的触摸屏坐标传输API接口。
驱动注册成功后,LVGL会后台不断调用回调函数my_touchpad_read(),然后根据回调函数返回结果来处理触摸事件。
2.触摸屏读取API
my_touchpad_read这个函数是LVGL提供的。注意到其有两个参数:indev_drv和data。
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
if (touch_6336.available())
{
data->state = LV_INDEV_STATE_PR;
data->point.x = touch_6336.touchPoint.tp[0].x;
data->point.y = touch_6336.touchPoint.tp[0].y;
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}
indev_drv实际可以不用,但是data是我们必须用的。
代码中:
data->state就是标识触摸屏状态了,LV_INDEV_STATE_PR代表有触摸动作发生,LV_INDEV_STATE_REL代表触摸屏释放。
data->point.x和data->point.y就是在有触摸动作发生的时候,把读取的坐标保存到这两个变量中。
要注意if (touch_6336.available())这行,它的返回结果代表着是否发生触摸动作,是需要触摸屏驱动在发生触摸时返回true的。同时也是说,触摸屏驱动中,必须要有available()这个方法。
此外其实我们还有些要了解:
(1)触摸屏对象的定义。FT6336U.h中是定义的类,那么定义一个对象就行了。
FT6336U touch_6336(5,4,7,&Wire);//Wire是0号总线
几个参数后面会讲到为什么这么写。
(2)触摸屏初始化。在setup部分调用一次即可。
touch_6336.begin();
函数定义后面会讲。
二、触摸屏驱动部分
了解了LVGL的触摸屏驱动API,那么我们就可以做驱动适配了。
这里我们在arduino库中找了一下FT6336U这个触摸屏的驱动,找到一个“RAK14014-FT6336U”的驱动版本,不用安装库,找到该驱动的github仓库,下载源文件即可:RAK14014_FT6336U.cpp和RAK14014_FT6336U.h。
在arduino的library中新建一个文件夹FT6336U,把这下载的两个文件拷贝到该文件夹中,重命名为FT6336U.cpp和FT6336U.h。
然后就可以开始改造了。
1.硬件底层方面
打开FT6336U.cpp,我们可以看到底层与触摸屏硬件层面交互数据的两个方法:
uint8_t FT6336U::readByte(uint8_t addr)
{
uint8_t rdData = 0;
uint8_t rdDataCount;
do {
_i2cPort->beginTransmission(_deviceAddress);
_i2cPort->write(addr);
_i2cPort->endTransmission(false); // Restart
delay(10);
rdDataCount = _i2cPort->requestFrom(_deviceAddress, 1);
} while(rdDataCount == 0);
if(_i2cPort->available())
{
rdData = _i2cPort->read();
}
return rdData;
}
void FT6336U::writeByte(uint8_t addr, uint8_t data)
{
_i2cPort->beginTransmission(_deviceAddress);
_i2cPort->write(addr);
_i2cPort->write(data);
_i2cPort->endTransmission();
}
具体的过程我们可以不去管它,但是我们必须关注它使用的是I2C总线。
具体使用的是哪个I2C总线,引脚怎么定义的呢?这个是我们必须要弄清楚的。
看FT6336U.cpp的代码:
FT6336U::FT6336U(byte addr)
{
_deviceAddress = addr;
}
bool FT6336U::begin(TwoWire &wirePort, uint8_t deviceAddress)
{
_deviceAddress = deviceAddress;
_i2cPort = &wirePort;
_i2cPort->begin();
if(read_device_type() == 0x02)
{
writeByte(0x02, 0x01);
return true;
}
return false;
}
第一个是构造函数,第二个是初始化函数。
(1)构造函数
为了方便我们指定触摸屏引脚和总线号,我们把构造函数改造一下,把总线号和引脚传给对象。
FT6336U::FT6336U(int SDAPin, int SCLPin, int INTPin, TwoWire * wirePort)
{
_deviceAddress = I2C_ADDR_FT6336U;
_SDAPin = uint8_t(SDAPin);
_SCLPin = uint8_t(SCLPin);
_INTPin = uint8_t(INTPin);
_i2cPort = wirePort;//Wire和wire1两个关键字是两条硬总线0/1,在wire.h中被固定定义了
}
(2)初始化函数
看FT6336U.h中函数原型定义:
bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = I2C_ADDR_FT6336U);
OK,如此的话,如果不指定参数,那么就是用的第一条(0#)I2C总线。具体见Wire.h末尾对Wire和Wire1两个符号的预定义。
等等,关于引脚的定义呢?
看bool FT6336U::begin(TwoWire &wirePort, uint8_t deviceAddress)中的一行:
_i2cPort->begin();
_i2cPort是一个I2C(TwoWire)对象,那么这个begin()函数的原型定义是就在Wire.h中了。
在Wire.h中,关于begin()函数定义了多种形式:
bool begin(int sda, int scl, uint32_t frequency=0); // returns true, if successful init of i2c bus
bool begin(uint8_t slaveAddr, int sda, int scl, uint32_t frequency);
// Explicit Overload for Arduino MainStream API compatibility
inline bool begin()
{
return begin(-1, -1, static_cast<uint32_t>(0));
}
inline bool begin(uint8_t addr)
{
return begin(addr, -1, -1, 0);
}
inline bool begin(int addr)
{
return begin(static_cast<uint8_t>(addr), -1, -1, 0);
}
OK,那么在这个begin中增加引脚即可:
_i2cPort->begin(SDAPin,SCLPin);
SDAPin和SCLPin是你实际的I2C总线引脚号。
2.对LVGL的接口方面
前面我们已经搞清楚了,LVGL是通过my_touchpad_read()这个函数读取触摸屏输入数据的。那触摸屏驱动就要对接这个接口,把触摸数据传给LVGL。
(1)首先,my_touchpad_read()中:
if (touch_6336.available())
这句是调用触摸屏驱动中的available()函数,让其返回是否有触摸事件发生。那么触摸屏驱动中必须要有这个available()方法才行。
然而,不幸的是,FT6336U.cpp中并没有这个函数,那么就需要我们自己添加了。
这里我们参考CST816触摸屏的驱动,采用注册中断的方式,来实现一个available()方法。
首先,FT6336U触摸屏是有INT引脚的,应该说绝大部分触摸屏都有这个引脚,作用是有触摸事件发生时通知CPU。
顺便提一句,触摸屏大都有两种工作模式:中断模式和扫描模式。中断模式是在有输入时通过中断引脚通知CPU,然后CPU读取触摸数据;扫描模式是CPU一直不停的读取触摸屏数据,有触摸时CPU自然会读取到。显而易见,中断模式更加节省CPU的开销。
用中断方式实现available()方法我们添加如下代码:
void IRAM_ATTR FT6336U::handleISR(void) {
_event_available = true;
}
bool FT6336U::available(void) {
if (_event_available) {
//read_touch();
_event_available = false;
return true;
}
return false;
}
并且把begin()函数给更改一下:
bool FT6336U::begin(void)
{//modifyied by fat0x
_i2cPort->begin(_SDAPin,_SCLPin);
if(read_device_type() == 0x02)
{
writeByte(0x02, 0x01);
attachInterrupt(_INTPin, std::bind(&FT6336U::handleISR, this), FALLING);
return true;
}
return false;
}
handleISR是一个中断服务函数,发生中断时把_event_available置位。
begin()函数中,我们增加attachInterrupt(),在硬件层面注册一个中断服务函数,其中_INTPin就是触摸屏的INT引脚连接到CPU的引脚号;handleISR是中断服务函数名;FALLING是定义有引脚上电平变化的哪种类型触发该中断,FALLING是电平下降沿。
最后available()函数就是在LVGL调用时,如果有中断就返回true给LVGL了。
(2)my_touchpad_read中读取触摸坐标数据
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
if (touch_6336.available())
{
data->state = LV_INDEV_STATE_PR;
data->point.x = touch_6336.touchPoint.tp[0].x;
data->point.y = touch_6336.touchPoint.tp[0].y;
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}
注意到my_touchpad_read中,一旦available()返回true,LVGL就会读取触摸屏对象中保存的坐标数据。这意味着,触摸屏驱动需要在中断发生的时候,就在硬件层面去读取数据,然后把数据提前保存到对象中,LVGL才能读取到。
那么available()函数中就需要增加读取坐标的代码了(下面代码中的scan()):
bool FT6336U::available(void) {
if (_event_available) {
scan();
_event_available = false;
return true;
}
return false;
}
scan()函数是驱动的作者写好的,作用是读取触摸坐标,并且保存到类中定义的两个对象数据touchPoint.tp[0].x和touchPoint.tp[0].y中。所以我们在my_touchpad_read()函数中是这两行代码:
data->point.x = touch_6336.touchPoint.tp[0].x;
data->point.y = touch_6336.touchPoint.tp[0].y;
OK,整个驱动的改造就基本结束了。
三、修改过的完整代码
1.FT6336U.h
/**************************************************************************/
/*!
@file FT6336U.h
Author: Atsushi Sasaki(https://github.com/aselectroworks)
License: MIT (see LICENSE)
*/
/**************************************************************************/
#ifndef _FT6336U_H__
#define _FT6336U_H__
#include <Arduino.h>
#include <Wire.h>
#define LIB_DEBUG 0
#if LIB_DEBUG > 0
#define LIB_LOG(tag, ...) \
do \
{ \
if (tag) \
Serial.printf("#Debug "); \
Serial.printf("<%s> ", tag); \
Serial.printf(__VA_ARGS__); \
Serial.printf("\n"); \
} while (0)
#else
#define LIB_LOG(...)
#endif
#define I2C_ADDR_FT6336U 0x38
#define FT6336U_PRES_DOWN 0x02
#define FT6336U_COORD_UD 0x01
#define FT6336U_ADDR_DEVICE_MODE 0x00
typedef enum
{
working_mode = 0b000,
factory_mode = 0b100,
} DEVICE_MODE_Enum;
#define FT6336U_ADDR_GESTURE_ID 0x01
#define FT6336U_ADDR_TD_STATUS 0x02
#define FT6336U_ADDR_TOUCH1_EVENT 0x03
#define FT6336U_ADDR_TOUCH1_ID 0x05
#define FT6336U_ADDR_TOUCH1_X 0x03
#define FT6336U_ADDR_TOUCH1_Y 0x05
#define FT6336U_ADDR_TOUCH1_WEIGHT 0x07
#define FT6336U_ADDR_TOUCH1_MISC 0x08
#define FT6336U_ADDR_TOUCH2_EVENT 0x09
#define FT6336U_ADDR_TOUCH2_ID 0x0B
#define FT6336U_ADDR_TOUCH2_X 0x09
#define FT6336U_ADDR_TOUCH2_Y 0x0B
#define FT6336U_ADDR_TOUCH2_WEIGHT 0x0D
#define FT6336U_ADDR_TOUCH2_MISC 0x0E
#define FT6336U_ADDR_THRESHOLD 0x80
#define FT6336U_ADDR_FILTER_COE 0x85
#define FT6336U_ADDR_CTRL 0x86
typedef enum
{
keep_active_mode = 0,
switch_to_monitor_mode = 1,
} CTRL_MODE_Enum;
#define FT6336U_ADDR_TIME_ENTER_MONITOR 0x87
#define FT6336U_ADDR_ACTIVE_MODE_RATE 0x88
#define FT6336U_ADDR_MONITOR_MODE_RATE 0x89
#define FT6336U_ADDR_RADIAN_VALUE 0x91
#define FT6336U_ADDR_OFFSET_LEFT_RIGHT 0x92
#define FT6336U_ADDR_OFFSET_UP_DOWN 0x93
#define FT6336U_ADDR_DISTANCE_LEFT_RIGHT 0x94
#define FT6336U_ADDR_DISTANCE_UP_DOWN 0x95
#define FT6336U_ADDR_DISTANCE_ZOOM 0x96
#define FT6336U_ADDR_CIPHER_LOW 0xA0
#define FT6336U_ADDR_LIBRARY_VERSION_H 0xA1
#define FT6336U_ADDR_LIBRARY_VERSION_L 0xA2
#define FT6336U_ADDR_CHIP_ID 0xA3
#define FT6336U_ADDR_G_MODE 0xA4
typedef enum {
pollingMode = 0,
triggerMode = 1,
} G_MODE_Enum;
#define FT6336U_ADDR_POWER_MODE 0xA5
#define FT6336U_ADDR_FIRMARE_ID 0xA6
#define FT6336U_ADDR_FOCALTECH_ID 0xA8
#define FT6336U_ADDR_RELEASE_CODE_ID 0xAF
#define FT6336U_ADDR_STATE 0xBC
// Function Specific Type
typedef enum
{
touch = 0,
stream,
release,
} TouchStatusEnum;
typedef struct
{
TouchStatusEnum status;
uint16_t x;
uint16_t y;
} TouchPointType;
typedef struct
{
uint8_t touch_count;
TouchPointType tp[2];
} FT6336U_TouchPointType;
/**************************************************************************/
/*!
@brief FT6336U I2C CTP controller driver
*/
/**************************************************************************/
class FT6336U
{
public:
FT6336U(int SDAPin, int SCLPin, int INTPin, TwoWire * wirePort);
//bool begin(TwoWire &wirePort = Wire, uint8_t deviceAddress = I2C_ADDR_FT6336U);
bool begin(void);
bool available(void);
void IRAM_ATTR handleISR(void);
uint8_t read_device_type(void);
uint8_t read_device_mode(void);
void write_device_mode(DEVICE_MODE_Enum);
uint8_t read_gesture_id(void);
uint8_t read_td_status(void);
uint8_t read_touch_number(void);
uint16_t read_touch1_x(void);
uint16_t read_touch1_y(void);
uint8_t read_touch1_event(void);
uint8_t read_touch1_id(void);
uint8_t read_touch1_weight(void);
uint8_t read_touch1_misc(void);
uint16_t read_touch2_x(void);
uint16_t read_touch2_y(void);
uint8_t read_touch2_event(void);
uint8_t read_touch2_id(void);
uint8_t read_touch2_weight(void);
uint8_t read_touch2_misc(void);
// Mode Parameter Register
void write_power_mode(uint8_t mode);
void write_monitor_mode_period(uint8_t mode);
void disable_face_dec_mode();
uint8_t read_touch_threshold(void);
uint8_t read_filter_coefficient(void);
uint8_t read_ctrl_mode(void);
void write_ctrl_mode(CTRL_MODE_Enum mode);
uint8_t read_time_period_enter_monitor(void);
void write_time_period_enter_monitor(uint8_t time);
uint8_t read_active_rate(void);
uint8_t read_monitor_rate(void);
// Gestrue Parameter Register
uint8_t read_radian_value(void);
void write_radian_value(uint8_t val);
uint8_t read_offset_left_right(void);
void write_offset_left_right(uint8_t val);
uint8_t read_offset_up_down(void);
void write_offset_up_down(uint8_t val);
uint8_t read_distance_left_right(void);
void write_distance_left_right(uint8_t val);
uint8_t read_distance_up_down(void);
void write_distance_up_down(uint8_t val);
uint8_t read_distance_zoom(void);
void write_distance_zoom(uint8_t val);
// System Information
uint16_t read_library_version(void);
uint8_t read_chip_id(void);
uint8_t read_g_mode(void);
void write_g_mode(G_MODE_Enum mode);
uint8_t read_pwrmode(void);
uint8_t read_firmware_id(void);
uint8_t read_focaltech_id(void);
uint8_t read_release_code_id(void);
uint8_t read_state(void);
// Scan Function
FT6336U_TouchPointType scan(void);
FT6336U_TouchPointType touchPoint;
private:
TwoWire *_i2cPort; // The generic connection to user's chosen I2C hardware
uint8_t _SDAPin;
uint8_t _SCLPin;
uint8_t _INTPin;
uint8_t _deviceAddress;
bool _event_available; //added by fat0x
uint8_t readByte(uint8_t addr);
void writeByte(uint8_t addr, uint8_t data);
};
#endif
2.FT6336U.cpp
/**************************************************************************/
/*!
@file FT6336U.cpp
Author: Atsushi Sasaki (https://github.com/aselectroworks)
License: MIT (see LICENSE)
*/
/**************************************************************************/
#include "FT6336U.h"
#include <FunctionalInterrupt.h>
FT6336U::FT6336U(int SDAPin, int SCLPin, int INTPin, TwoWire * wirePort)
{
_deviceAddress = I2C_ADDR_FT6336U;
_SDAPin = uint8_t(SDAPin);
_SCLPin = uint8_t(SCLPin);
_INTPin = uint8_t(INTPin);
_i2cPort = wirePort;//Wire和wire1两个关键字是两条硬总线0/1,在wire.h中被固定定义了
}
bool FT6336U::begin(void)
{//modifyied by fat0x
_i2cPort->begin(_SDAPin,_SCLPin);
if(read_device_type() == 0x02)
{
writeByte(0x02, 0x01);
attachInterrupt(_INTPin, std::bind(&FT6336U::handleISR, this), FALLING);
return true;
}
return false;
}
/*added by fat0x begin*/
void IRAM_ATTR FT6336U::handleISR(void) {
_event_available = true;
}
bool FT6336U::available(void) {
if (_event_available) {
scan();
_event_available = false;
return true;
}
return false;
}
/*added by fat0x end!*/
uint8_t FT6336U::read_device_type(void)
{
return readByte(FT6336U_ADDR_CIPHER_LOW);
}
uint8_t FT6336U::read_device_mode(void)
{
return (readByte(FT6336U_ADDR_DEVICE_MODE) & 0x70) >> 4;
}
void FT6336U::write_device_mode(DEVICE_MODE_Enum mode)
{
writeByte(FT6336U_ADDR_DEVICE_MODE, (mode & 0x07) << 4);
}
uint8_t FT6336U::read_gesture_id(void)
{
return readByte(FT6336U_ADDR_GESTURE_ID);
}
uint8_t FT6336U::read_td_status(void)
{
return readByte(FT6336U_ADDR_TD_STATUS);
}
uint8_t FT6336U::read_touch_number(void)
{
return readByte(FT6336U_ADDR_TD_STATUS) & 0x0F;
}
// Touch 1 functions
uint16_t FT6336U::read_touch1_x(void)
{
uint8_t read_buf[2];
read_buf[0] = readByte(FT6336U_ADDR_TOUCH1_X);
read_buf[1] = readByte(FT6336U_ADDR_TOUCH1_X + 1);
return ((read_buf[0] & 0x0f) << 8) | read_buf[1];
}
uint16_t FT6336U::read_touch1_y(void)
{
uint8_t read_buf[2];
read_buf[0] = readByte(FT6336U_ADDR_TOUCH1_Y);
read_buf[1] = readByte(FT6336U_ADDR_TOUCH1_Y + 1);
return ((read_buf[0] & 0x0f) << 8) | read_buf[1];
}
uint8_t FT6336U::read_touch1_event(void)
{
return readByte(FT6336U_ADDR_TOUCH1_EVENT) >> 6;
}
uint8_t FT6336U::read_touch1_id(void)
{
return readByte(FT6336U_ADDR_TOUCH1_ID) >> 4;
}
uint8_t FT6336U::read_touch1_weight(void)
{
return readByte(FT6336U_ADDR_TOUCH1_WEIGHT);
}
uint8_t FT6336U::read_touch1_misc(void)
{
return readByte(FT6336U_ADDR_TOUCH1_MISC) >> 4;
}
// Touch 2 functions
uint16_t FT6336U::read_touch2_x(void)
{
uint8_t read_buf[2];
read_buf[0] = readByte(FT6336U_ADDR_TOUCH2_X);
read_buf[1] = readByte(FT6336U_ADDR_TOUCH2_X + 1);
return ((read_buf[0] & 0x0f) << 8) | read_buf[1];
}
uint16_t FT6336U::read_touch2_y(void)
{
uint8_t read_buf[2];
read_buf[0] = readByte(FT6336U_ADDR_TOUCH2_Y);
read_buf[1] = readByte(FT6336U_ADDR_TOUCH2_Y + 1);
return ((read_buf[0] & 0x0f) << 8) | read_buf[1];
}
uint8_t FT6336U::read_touch2_event(void)
{
return readByte(FT6336U_ADDR_TOUCH2_EVENT) >> 6;
}
uint8_t FT6336U::read_touch2_id(void)
{
return readByte(FT6336U_ADDR_TOUCH2_ID) >> 4;
}
uint8_t FT6336U::read_touch2_weight(void)
{
return readByte(FT6336U_ADDR_TOUCH2_WEIGHT);
}
uint8_t FT6336U::read_touch2_misc(void)
{
return readByte(FT6336U_ADDR_TOUCH2_MISC) >> 4;
}
// Mode Parameter Register
void FT6336U::write_power_mode(uint8_t mode)
{
writeByte(FT6336U_ADDR_POWER_MODE, mode);
}
void FT6336U::write_monitor_mode_period(uint8_t mode)
{
writeByte(FT6336U_ADDR_MONITOR_MODE_RATE, mode);
}
void FT6336U::disable_face_dec_mode()
{
writeByte(0xB0, 0x00);
}
uint8_t FT6336U::read_touch_threshold(void)
{
return readByte(FT6336U_ADDR_THRESHOLD);
}
uint8_t FT6336U::read_filter_coefficient(void)
{
return readByte(FT6336U_ADDR_FILTER_COE);
}
uint8_t FT6336U::read_ctrl_mode(void)
{
return readByte(FT6336U_ADDR_CTRL);
}
void FT6336U::write_ctrl_mode(CTRL_MODE_Enum mode)
{
writeByte(FT6336U_ADDR_CTRL, mode);
}
uint8_t FT6336U::read_time_period_enter_monitor(void)
{
return readByte(FT6336U_ADDR_TIME_ENTER_MONITOR);
}
void FT6336U::write_time_period_enter_monitor(uint8_t time)
{
writeByte(FT6336U_ADDR_TIME_ENTER_MONITOR, time);
}
uint8_t FT6336U::read_active_rate(void)
{
return readByte(FT6336U_ADDR_ACTIVE_MODE_RATE);
}
uint8_t FT6336U::read_monitor_rate(void)
{
return readByte(FT6336U_ADDR_MONITOR_MODE_RATE);
}
// Gesture Parameters
uint8_t FT6336U::read_radian_value(void)
{
return readByte(FT6336U_ADDR_RADIAN_VALUE);
}
void FT6336U::write_radian_value(uint8_t val)
{
writeByte(FT6336U_ADDR_RADIAN_VALUE, val);
}
uint8_t FT6336U::read_offset_left_right(void)
{
return readByte(FT6336U_ADDR_OFFSET_LEFT_RIGHT);
}
void FT6336U::write_offset_left_right(uint8_t val)
{
writeByte(FT6336U_ADDR_OFFSET_LEFT_RIGHT, val);
}
uint8_t FT6336U::read_offset_up_down(void)
{
return readByte(FT6336U_ADDR_OFFSET_UP_DOWN);
}
void FT6336U::write_offset_up_down(uint8_t val)
{
writeByte(FT6336U_ADDR_OFFSET_UP_DOWN, val);
}
uint8_t FT6336U::read_distance_left_right(void)
{
return readByte(FT6336U_ADDR_DISTANCE_LEFT_RIGHT);
}
void FT6336U::write_distance_left_right(uint8_t val)
{
writeByte(FT6336U_ADDR_DISTANCE_LEFT_RIGHT, val);
}
uint8_t FT6336U::read_distance_up_down(void)
{
return readByte(FT6336U_ADDR_DISTANCE_UP_DOWN);
}
void FT6336U::write_distance_up_down(uint8_t val)
{
writeByte(FT6336U_ADDR_DISTANCE_UP_DOWN, val);
}
uint8_t FT6336U::read_distance_zoom(void)
{
return readByte(FT6336U_ADDR_DISTANCE_ZOOM);
}
void FT6336U::write_distance_zoom(uint8_t val)
{
writeByte(FT6336U_ADDR_DISTANCE_ZOOM, val);
}
// System Information
uint16_t FT6336U::read_library_version(void)
{
uint8_t read_buf[2];
read_buf[0] = readByte(FT6336U_ADDR_LIBRARY_VERSION_H);
read_buf[1] = readByte(FT6336U_ADDR_LIBRARY_VERSION_L);
return ((read_buf[0] & 0x0f) << 8) | read_buf[1];
}
uint8_t FT6336U::read_chip_id(void)
{
return readByte(FT6336U_ADDR_CHIP_ID);
}
uint8_t FT6336U::read_g_mode(void)
{
return readByte(FT6336U_ADDR_G_MODE);
}
void FT6336U::write_g_mode(G_MODE_Enum mode)
{
writeByte(FT6336U_ADDR_G_MODE, mode);
}
uint8_t FT6336U::read_pwrmode(void)
{
return readByte(FT6336U_ADDR_POWER_MODE);
}
uint8_t FT6336U::read_firmware_id(void)
{
return readByte(FT6336U_ADDR_FIRMARE_ID);
}
uint8_t FT6336U::read_focaltech_id(void)
{
return readByte(FT6336U_ADDR_FOCALTECH_ID);
}
uint8_t FT6336U::read_release_code_id(void)
{
return readByte(FT6336U_ADDR_RELEASE_CODE_ID);
}
uint8_t FT6336U::read_state(void)
{
return readByte(FT6336U_ADDR_STATE);
}
//coordinate diagram(FPC downwards)
y 264x176
//
//
//x
//
//
FT6336U_TouchPointType FT6336U::scan(void){
touchPoint.touch_count = read_td_status();
if(touchPoint.touch_count == 0) {
touchPoint.tp[0].status = release;
touchPoint.tp[1].status = release;
}
else if(touchPoint.touch_count == 1) {
uint8_t id1 = read_touch1_id(); // id1 = 0 or 1
touchPoint.tp[id1].status = (touchPoint.tp[id1].status == release) ? touch : stream;
touchPoint.tp[id1].x = read_touch1_x();
touchPoint.tp[id1].y = read_touch1_y();
touchPoint.tp[~id1 & 0x01].status = release;
}
else {
uint8_t id1 = read_touch1_id(); // id1 = 0 or 1
touchPoint.tp[id1].status = (touchPoint.tp[id1].status == release) ? touch : stream;
touchPoint.tp[id1].x = read_touch1_x();
touchPoint.tp[id1].y = read_touch1_y();
uint8_t id2 = read_touch2_id(); // id2 = 0 or 1(~id1 & 0x01)
touchPoint.tp[id2].status = (touchPoint.tp[id2].status == release) ? touch : stream;
touchPoint.tp[id2].x = read_touch2_x();
touchPoint.tp[id2].y = read_touch2_y();
}
return touchPoint;
}
// Private Function
uint8_t FT6336U::readByte(uint8_t addr)
{
uint8_t rdData = 0;
uint8_t rdDataCount;
do {
_i2cPort->beginTransmission(_deviceAddress);
_i2cPort->write(addr);
_i2cPort->endTransmission(false); // Restart
delay(10);
rdDataCount = _i2cPort->requestFrom(_deviceAddress, 1);
} while(rdDataCount == 0);
if(_i2cPort->available())
{
rdData = _i2cPort->read();
}
return rdData;
}
void FT6336U::writeByte(uint8_t addr, uint8_t data)
{
_i2cPort->beginTransmission(_deviceAddress);
_i2cPort->write(addr);
_i2cPort->write(data);
_i2cPort->endTransmission();
}
3.arduino中的调用代码
#include "FT6336U.h"
FT6336U touch_6336(5,4,7,&Wire);//Wire是0号总线,引脚号根据实际连线修改
/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
if (touch_6336.available())
{
data->state = LV_INDEV_STATE_PR;
data->point.x = touch_6336.touchPoint.tp[0].x;
data->point.y = touch_6336.touchPoint.tp[0].y;
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}
void setup()
{
touch_6336.begin();
/*Initialize the (dummy) input device driver*/
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register(&indev_drv);
}
arduino中其他LVGL代码我没有全部贴,因为和本驱动无关。
4.坐标的调整
最后,说一个点,屏幕旋转的问题。
触摸屏传回的坐标是根据屏幕的大小来的。比如240*320的屏幕,成品的触摸屏传回给你的x和y坐标一定是在0-239,0-319之间的。
但是x和y是需要根据你屏幕的旋转的改变的。比如屏幕出厂默认是竖屏,你使用时改成了横屏显示,那么你的触摸屏驱动里也要把x和y做相应的调整,LVGL中的触摸功能才能正常使用,否则触摸就是乱的。
全文完结。