2025-03-21 09:59:09 +01:00

389 lines
10 KiB
C++

/**
*
* @license MIT License
*
* Copyright (c) 2022 lewis he
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @file TouchDrvFT6X36.hpp
* @author Lewis He (lewishe@outlook.com)
* @date 2023-04-01
*
*/
#pragma once
#include "REG/FT6X36Constants.h"
#include "TouchDrvInterface.hpp"
class TouchDrvFT6X36 : public TouchDrvInterface
{
public:
enum GesTrue {
NO_GESTURE,
MOVE_UP,
MOVE_LEFT,
MOVE_DOWN,
MOVE_RIGHT,
ZOOM_IN,
ZOOM_OUT,
} ;
enum EventFlag {
EVENT_PUT_DOWN,
EVENT_PUT_UP,
EVENT_CONTACT,
EVENT_NONE,
} ;
enum PowerMode {
PMODE_ACTIVE = 0, // ~4mA
PMODE_MONITOR = 1, // ~3mA
PMODE_DEEP_SLEEP = 3, // ~100uA The reset pin must be pulled down to wake up
} ;
EventFlag event;
TouchDrvFT6X36() : comm(nullptr), hal(nullptr) {}
~TouchDrvFT6X36()
{
if (comm) {
comm->deinit();
}
}
#if defined(ARDUINO)
bool begin(TwoWire &wire, uint8_t addr = FT6X36_SLAVE_ADDRESS, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalArduino>(comm, hal, wire, addr, sda, scl)) {
return false;
}
return initImpl();
}
#elif defined(ESP_PLATFORM)
#if defined(USEING_I2C_LEGACY)
bool begin(i2c_port_t port_num, uint8_t addr = FT6X36_SLAVE_ADDRESS, int sda = -1, int scl = -1)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, port_num, addr, sda, scl)) {
return false;
}
return initImpl();
}
#else
bool begin(i2c_master_bus_handle_t handle, uint8_t addr = FT6X36_SLAVE_ADDRESS)
{
if (!beginCommon<SensorCommI2C, HalEspIDF>(comm, hal, handle, addr)) {
return false;
}
return initImpl();
}
#endif //ESP_PLATFORM
#endif //ARDUINO
bool begin(SensorCommCustom::CustomCallback callback,
SensorCommCustomHal::CustomHalCallback hal_callback,
uint8_t addr)
{
if (!beginCommCustomCallback<SensorCommCustom, SensorCommCustomHal>(COMM_CUSTOM,
callback, hal_callback, addr, comm, hal)) {
return false;
}
return initImpl();
}
uint8_t getDeviceMode(void)
{
return comm->readRegister(FT6X36_REG_MODE) & 0x03;
}
// Obtaining gestures depends on whether the built-in firmware of the chip has this function
uint8_t getGesture()
{
int val = comm->readRegister(FT6X36_REG_GEST);
switch (val) {
case 0x10:
return MOVE_UP;
case 0x14:
return MOVE_RIGHT;
case 0x18:
return MOVE_DOWN;
case 0x1C:
return MOVE_LEFT;
case 0x48:
return ZOOM_IN;
case 0x49:
return ZOOM_OUT;
default:
break;
}
return NO_GESTURE;
}
void setThreshold(uint8_t value)
{
comm->writeRegister(FT6X36_REG_THRESHOLD, value);
}
uint8_t getThreshold(void)
{
return comm->readRegister(FT6X36_REG_THRESHOLD);
}
uint8_t getMonitorTime(void)
{
return comm->readRegister(FT6X36_REG_MONITOR_TIME);
}
void setMonitorTime(uint8_t sec)
{
comm->writeRegister(FT6X36_REG_MONITOR_TIME, sec);
}
// Calibration useless actually,
// any value set will not be valid,
// depending on the internal firmware of the chip.
/*
void enableAutoCalibration(void)
{
comm->writeRegister(FT6X36_REG_AUTO_CLB_MODE, 0x00);
}
void disableAutoCalibration(void)
{
comm->writeRegister(FT6X36_REG_AUTO_CLB_MODE, 0xFF);
}
*/
uint16_t getLibraryVersion()
{
uint8_t buffer[2];
comm->readRegister(FT6X36_REG_LIB_VERSION_H, buffer, 2);
return (buffer[0] << 8) | buffer[1];
}
// The interrupt is triggered only if a touch is detected during the scan cycle
void interruptPolling(void)
{
//datasheet this bit is 0,Actually, it's wrong
comm->writeRegister(FT6X36_REG_INT_STATUS, 1);
}
// Triggers an interrupt whenever a touch is detected
void interruptTrigger(void)
{
//datasheet this bit is 1,Actually, it's wrong
comm->writeRegister(FT6X36_REG_INT_STATUS, (uint8_t)0);
}
uint8_t getPoint(int16_t *x_array, int16_t *y_array, uint8_t size = 1)
{
uint8_t buffer[16];
if (!x_array || !y_array || !size)
return 0;
if (comm->readRegister(FT6X36_REG_MODE, buffer, 16) == -1) {
return 0;
}
// uint8_t mode = buffer[0];
//REG 0x01
// uint8_t gesture = buffer[1];
//REG 0x02
uint8_t numPoints = buffer[2] & 0x0F;
if (numPoints == 0 || numPoints == 0x0F) {
return 0;
}
//REG 0x03 ~ 0x04
// uint8_t eventFlag = (buffer[3] & 0xC0) >> 6;
uint16_t posX = ((buffer[3] & 0x0F) << 8) | buffer[4];
//REG 0x05 ~ 0x06
uint16_t posY = ((buffer[5] & 0x0F) << 8) | buffer[6] ;
x_array[0] = posX;
y_array[0] = posY;
if (numPoints == 2) {
//REG 0x09 ~ 0x0A
posX = ((buffer[9] & 0x0F) << 8) | buffer[10];
//REG 0x0B ~ 0x0C
posY = ((buffer[11] & 0x0F) << 8) | buffer[12] ;
if (size == 2) {
x_array[1] = posX;
y_array[1] = posY;
}
}
updateXY(numPoints, x_array, y_array);
return numPoints;
}
bool isPressed()
{
if (_irq != -1) {
return hal->digitalRead(_irq) == LOW;
}
return comm->readRegister(FT6X36_REG_STATUS) & 0x0F;
}
void setPowerMode(PowerMode mode)
{
comm->writeRegister(FT6X36_REG_POWER_MODE, mode);
}
void sleep()
{
comm->writeRegister(FT6X36_REG_POWER_MODE, PMODE_DEEP_SLEEP);
}
void wakeup()
{
reset();
}
void idle()
{
}
uint8_t getSupportTouchPoint()
{
return 1;
}
uint32_t getChipID(void)
{
return comm->readRegister(FT6X36_REG_CHIP_ID);
}
uint8_t getVendorID(void)
{
return comm->readRegister(FT6X36_REG_VENDOR1_ID);
}
uint8_t getErrorCode(void)
{
return comm->readRegister(FT6X36_REG_ERROR_STATUS);
}
const char *getModelName()
{
switch (_chipID) {
case FT6206_CHIP_ID: return "FT6206";
case FT6236_CHIP_ID: return "FT6236";
case FT6236U_CHIP_ID: return "FT6236U";
case FT3267_CHIP_ID: return "FT3267";
default: return "UNKNOWN";
}
}
bool getResolution(int16_t *x, int16_t *y)
{
return false;
}
void reset()
{
if (_rst != -1) {
hal->pinMode(_rst, OUTPUT);
hal->digitalWrite(_rst, HIGH);
hal->delay(10);
hal->digitalWrite(_rst, LOW);
hal->delay(30);
hal->digitalWrite(_rst, HIGH);
// For the variant of GPIO extended RST,
// communication and hal->delay are carried out simultaneously, and 160ms is measured in T-RGB esp-idf new api
hal->delay(160);
}
}
void setGpioCallback(CustomMode mode_cb,
CustomWrite write_cb,
CustomRead read_cb)
{
SensorHalCustom::setCustomMode(mode_cb);
SensorHalCustom::setCustomWrite(write_cb);
SensorHalCustom::setCustomRead(read_cb);
}
private:
bool initImpl()
{
if (_irq != -1) {
hal->pinMode(_irq, INPUT);
}
reset();
uint8_t vendId = comm->readRegister(FT6X36_REG_VENDOR1_ID);
if (vendId != FT6X36_VEND_ID) {
log_e("Vendor id is 0x%X not match!", vendId);
return false;
}
_chipID = comm->readRegister(FT6X36_REG_CHIP_ID);
if ((_chipID != FT6206_CHIP_ID) &&
(_chipID != FT6236_CHIP_ID) &&
(_chipID != FT6236U_CHIP_ID) &&
(_chipID != FT3267_CHIP_ID)
) {
log_e("Vendor id is not match!");
log_e("ChipID:0x%lx should be 0x06 or 0x36 or 0x64", _chipID);
return false;
}
log_i("Vend ID: 0x%X", vendId);
log_i("Chip ID: 0x%lx", _chipID);
log_i("Firm Version: 0x%X", comm->readRegister(FT6X36_REG_FIRM_VERS));
log_i("Point Rate Hz: %u", comm->readRegister(FT6X36_REG_PERIOD_ACTIVE));
log_i("Thresh : %u", comm->readRegister(FT6X36_REG_THRESHOLD));
// change threshold to be higher/lower
comm->writeRegister(FT6X36_REG_THRESHOLD, 60);
log_i("Chip library version : 0x%x", getLibraryVersion());
// This register describes period of monitor status, it should not less than 30.
log_i("Chip period of monitor status : 0x%x", comm->readRegister(FT6X36_REG_PERIOD_MONITOR));
// This register describes the period of active status, it should not less than 12
return true;
}
protected:
std::unique_ptr<SensorCommBase> comm;
std::unique_ptr<SensorHal> hal;
};