cyttsp MCU裸机触摸驱动

cyttsp6_ts.h

/*
 * cyttsp5_ts.h
 * Parade TrueTouch(TM) Standard Product V5 Core Module.
 *
 * Copyright (C) 2017 Hwtc Co,.Ltd
 *
 */
#ifndef _CYTTSP6_REGS_H
#define _CYTTSP6_REGS_H

#include "type.h"

#define IS_BOOTLOADER(hst_mode, reset_detect) \
		((hst_mode) & 0x01 || (reset_detect) != 0)
#define IS_BOOTLOADER_IDLE(hst_mode, reset_detect) \
		((hst_mode) & 0x01 && (reset_detect) & 0x01)

/* helpers */
#define GET_NUM_TOUCH_RECORDS(x)	((x) & 0x1F)
#define IS_LARGE_AREA(x)		((x) & 0x20)
#define IS_BAD_PKT(x)			((x) & 0x20)

#define IS_BOOTLOADER(hst_mode, reset_detect) \
		((hst_mode) & 0x01 || (reset_detect) != 0)
#define IS_BOOTLOADER_IDLE(hst_mode, reset_detect) \
		((hst_mode) & 0x01 && (reset_detect) & 0x01)

#define GET_HSTMODE(reg)		((reg & 0x70) >> 4)
#define GET_TOGGLE(reg)			((reg & 0x80) >> 7)

#define IS_LITTLEENDIAN(reg)		((reg & 0x01) == 1)
#define GET_PANELID(reg)		(reg & 0x07)

#define HI_BYTE(x)			(u8)(((x) >> 8) & 0xFF)
#define LO_BYTE(x)			(u8)((x) & 0xFF)

#define IS_DEEP_SLEEP_CONFIGURED(x)	((x) == 0 || (x) == 0xFF)

#define IS_TMO(t)			((t) == 0)

#define IS_GEST_EXTD(gest_id)		(((u8)gest_id) >> 7)

#define CY_BL_MAX_STATUS_SIZE		32
/* Communication bus values */
#define CY_DEFAULT_ADAP_MAX_XFER	512
#define CY_ADAP_MIN_XFER		64

/* DEVICE REGISTERS */
/* OP MODE REGISTERS */
#define CY_REG_BASE			0x00

/* DRIVER STATES */
enum cyttsp6_mode {
	CY_MODE_UNKNOWN      = 0,
	CY_MODE_BOOTLOADER   = (1 << 0),
	CY_MODE_OPERATIONAL  = (1 << 1),
	CY_MODE_SYSINFO      = (1 << 2),
	CY_MODE_CAT          = (1 << 3),
	CY_MODE_STARTUP      = (1 << 4),
	CY_MODE_LOADER       = (1 << 5),
	CY_MODE_CHANGE_MODE  = (1 << 6),
	CY_MODE_CHANGED      = (1 << 7),
	CY_MODE_CMD_COMPLETE = (1 << 8),
};

enum cyttsp6_core_platform_flags {
	CY_CORE_FLAG_NONE		= 0,
	CY_CORE_FLAG_WAKE_ON_GESTURE	= (1 << 0),
	CY_CORE_FLAG_POWEROFF_ON_SLEEP	= (1 << 1),
	CY_CORE_FLAG_BOOTLOADER_FAST_EXIT = (1 << 2),
	/* choose SCAN_TYPE or TOUCH_MODE RAM ID to alter scan type */
	CY_CORE_FLAG_SCAN_MODE_USES_RAM_ID_SCAN_TYPE = (1 << 3),
};

enum cyttsp6_int_state {
	CY_INT_NONE,
	CY_INT_IGNORE      = (1 << 0),
	CY_INT_MODE_CHANGE = (1 << 1),
	CY_INT_EXEC_CMD    = (1 << 2),
	CY_INT_AWAKE       = (1 << 3),
};

/* DRIVER STATES */
//enum cyttsp6_mode {
//	CY_MODE_UNKNOWN      = 0,
//	CY_MODE_BOOTLOADER   = (1 << 0),
//	CY_MODE_OPERATIONAL  = (1 << 1),
//	CY_MODE_SYSINFO      = (1 << 2),
//	CY_MODE_CAT          = (1 << 3),
//	CY_MODE_STARTUP      = (1 << 4),
//	CY_MODE_LOADER       = (1 << 5),
//	CY_MODE_CHANGE_MODE  = (1 << 6),
//	CY_MODE_CHANGED      = (1 << 7),
//	CY_MODE_CMD_COMPLETE = (1 << 8),
//};

enum cyttsp6_hst_mode_bits {
	CY_HST_TOGGLE      = (1 << 7),
	CY_HST_MODE_CHANGE = (1 << 3),
	CY_HST_DEVICE_MODE = (7 << 4),
	CY_HST_OPERATE     = (0 << 4),
	CY_HST_SYSINFO     = (1 << 4),
	CY_HST_CAT         = (2 << 4),
	CY_HST_LOWPOW      = (1 << 2),
	CY_HST_SLEEP       = (1 << 1),
	CY_HST_RESET       = (1 << 0),
};

enum cyttsp_cmd_bits {
	CY_CMD_COMPLETE    = (1 << 6),
};

struct cyttsp6_core_platform_data {
	int irq_gpio;
	int rst_gpio;
	int err_gpio;
	int level_irq_udelay;
	int max_xfer_len;
	UINT32 flags;
	UINT8 easy_wakeup_gesture;
};

struct device {
	UINT8 member_a;
};


struct wait_queue {
	bool wake_up;
};

struct cyttsp6_core_data {
	//char core_id[20];
	struct device *dev;
	struct wait_queue wait_q;
	enum cyttsp6_mode mode;
	int int_status;	// u
	int cmd_toggle;
	int phys_num;
	int irq;
	int f_flag;
	void *exclusive_dev;
	int exclusive_waits;
	bool irq_enabled;
	bool irq_wake;
	bool wake_initiated_by_device;
	bool invalid_touch_app;
	bool bl_fast_exit;
	int max_xfer;
	int apa_mc_en;
	int glove_en;
	int stylus_en;
	int proximity_en;
	UINT8 default_scantype;
	UINT8 easy_wakeup_gesture;
	unsigned int active_refresh_cycle_ms;
	UINT8 heartbeat_count;
	UINT8 wr_buf[CY_DEFAULT_ADAP_MAX_XFER];
#ifdef VERBOSE_DEBUG
	UINT8 pr_buf[CY_MAX_PRBUF_SIZE];
	UINT8 rep_stat_counter;
#endif
	UINT8 xy_mode[128];			/* operational mode and status regs */
	UINT8 *xy_data;			/* operational touch regs */
};


// log
#define	TP_Debug	1
//#define dev_err(dev, format, arg...)	Print(format, ##arg)

#ifdef DEBUG
#define dev_dbg(dev, format, arg...)	print(format, ##arg)
	#ifdef VERBOSE_DEBUG
	#define dev_vdbg(dev, format, arg...)	print(format, ##arg);
	#else
	#define dev_vdbg(dev, format, arg...)
	#endif
#else
#define dev_dbg(dev, format, arg...)
#define dev_vdbg(dev, format, arg...)
#endif

#define kmalloc(size, flag)		malloc(size)
#define kfree(p)							free(p)

#define	ENOMEM		12	/* Out of memory */
#define EINVAL		13
#define EIO				14
#define ETIME			15

extern UINT16 TPTimerOutCount;
//extern UINT8 I2CTimerOutCount;

/* Timeout in ms. */
#define CY_COMMAND_COMPLETE_TIMEOUT							1000
#define CY_CALIBRATE_COMPLETE_TIMEOUT						10000
#define CY_WATCHDOG_TIMEOUT											1000
#define CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT				1000
#define CY_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT	2000
#define CY_DA_REQUEST_EXCLUSIVE_TIMEOUT					1000
#define CY_LDR_REQUEST_EXCLUSIVE_TIMEOUT				10000
#define CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT	10000
#define CY_CORE_WAIT_SYSINFO_MODE_TIMEOUT				4000
#define CY_CORE_MODE_CHANGE_TIMEOUT							2000
#define CY_CORE_RESET_AND_WAIT_TIMEOUT					1000
#define CY_CORE_WAKEUP_TIMEOUT									500
#define CY_LDR_CMD_TIMEOUT											1000
#define CY_LDR_CMD_INIT_TIMEOUT									20000
#define CY_CORE_CMD_WAIT_FOR_EVENT_TIMEOUT			50

/* TMA400 HOST SYNC BYTE */
#define CY_CMD_LDR_HOST_SYNC 		0xFF

#define CY_START_OF_PACKET			0x01
#define CY_END_OF_PACKET				0x17

/* CMD */
enum cyttsp6_cmd_bl {
	CY_CMD_LDR_VERIFY_CHKSUM = 0x31,
	CY_CMD_LDR_ERASE_ROW = 0x34,
	CY_CMD_LDR_SEND_DATA = 0x37,
	CY_CMD_LDR_ENTER,
	CY_CMD_LDR_PROG_ROW,
	CY_CMD_LDR_VERIFY_ROW,
	CY_CMD_LDR_EXIT,
	CY_CMD_LDR_FAST_EXIT,
	CY_CMD_LDR_INIT = 0x48,
};

//需要根据实际情况调整
#define CY_CMD_OFS				2
#define CY_REP_HDR_SIZE		19
#define CY_TCH_REC_SIZE		10
#define CY_REP_OFS				9
#define CY_TT_STAT_OFS		27
#define CY_MAX_TCHS				2//最多5个手指

extern struct cyttsp6_core_data 	g_cd;  

int cyttsp6_startup(struct cyttsp6_core_data *cd);
void cyttsp6_irq(struct cyttsp6_core_data *cd);
int cyttsp6_watchdog_work(struct cyttsp6_core_data *cd);

#endif //_CYTTSP6_REGS_H

cyttsp6_ts.c

/*
 * cyttsp5_ts.c
 * Parade TrueTouch(TM) Standard Product V5 Core Module.
 *
 * Copyright (C) 2017 Hwtc Co,.Ltd
 *
 */
#include "includes.h" 

//#include <malloc.h>
#include <string.h>

UINT16 TPTimerOutCount = 0;//计数
//UINT8 I2CTimerOutCount = 0;//超时标志

struct cyttsp6_core_data 	g_cd;  

static u8 ldr_exit[] = {
	CY_CMD_LDR_HOST_SYNC, CY_START_OF_PACKET, CY_CMD_LDR_EXIT, 0x00, 0x00,
	0x4F, 0x6D, CY_END_OF_PACKET
};

static u8 ldr_fast_exit[] = {
	CY_CMD_LDR_HOST_SYNC, CY_START_OF_PACKET, CY_CMD_LDR_FAST_EXIT,
	0x00, 0x00, 0xC3, 0x68, CY_END_OF_PACKET
};

static void wake_up(struct wait_queue *wq)
{
	wq->wake_up = 1;
}

//	if (pwa->wake_up)	\
//	{	\
//		TPCountTimerOut = 0;	\
//		goto __exit;	\
//	}	\
//	__exit: \	
//		if(TPCountTimerOutFlag == 1)	\
//		{	\
//			break;	\
//		}	\

#define wait_event_timeout(wq, condition, timeout) \
{	\
	struct wait_queue *pwa = (struct wait_queue *)wq;  \
	TPTimerOutCount = timeout;	\
	while ( !(condition))	\
	{	\
		if(TPTimerOutCount == 0)	\
		{	\
			break;	\
		}	\
	} \
	pwa->wake_up = 0; \
}

/******************************************************************************
** Function    : cyttsp6_adap_readyttsp6_adap_write
** Description : TP I2C读写操作
*******************************************************************************/
static int cyttsp6_adap_read(struct cyttsp6_core_data *cd, u16 addr,
	 void *buf, int size)
{
//	return cd->bus_ops->read(cd->dev, addr, buf, size, cd->max_xfer);
	return HALAPI_IIC1_Read(0x48, (UINT8)addr, buf , size);
}

static int cyttsp6_adap_write(struct cyttsp6_core_data *cd, u16 addr,
	 void *buf, int size)
{
//	return cd->bus_ops->write(cd->dev, addr, cd->wr_buf, buf, size,
//			cd->max_xfer);
//	while(1)
//	{
//		HALAPI_IIC1_Write(0x48, addr, buf , size);
//	}
	return HALAPI_IIC1_Write(0x48, (UINT8)addr, buf , size);
}


static int _exit_bootloader(struct cyttsp6_core_data *cd)
{
	//const u8 *exit_cmd;
	u8 *exit_cmd;
	int exit_cmd_size;
	int rc;

	cd->int_status &= ~CY_INT_IGNORE;
	cd->int_status |= CY_INT_MODE_CHANGE;

	//if ((cd->f_flag & CY_CORE_FLAG_BOOTLOADER_FAST_EXIT)&& cd->bl_fast_exit) 
	if(0)
	{
//		dev_vdbg(cd->dev, "%s: Issuing ldr_fast_exit\n", __func__);
		exit_cmd = ldr_fast_exit;
		exit_cmd_size = sizeof(ldr_fast_exit);
	} else {
//		dev_vdbg(cd->dev, "%s: Issuing ldr_exit\n", __func__);
		exit_cmd = ldr_exit;
		exit_cmd_size = sizeof(ldr_exit);
	}

	rc = cyttsp6_adap_write(cd, CY_REG_BASE, exit_cmd, exit_cmd_size);
	if (rc == 0)
	{
		DebugUart_Printf(TP_Debug,"_exit_bootloader:cyttsp6_adap_write err\r\n");
	}

	return rc;
}

static int cyttsp6_wait_sysinfo_mode(struct cyttsp6_core_data *cd)
{
	long t;

	//dev_vdbg(cd->dev, "%s: wait sysinfo...\n", __func__);
	DebugUart_Printf(TP_Debug,"wait sysinfo...\r\n");

	wait_event_timeout(&cd->wait_q, cd->mode == CY_MODE_SYSINFO, CY_CORE_WAIT_SYSINFO_MODE_TIMEOUT);
	t = TPTimerOutCount;
	TPTimerOutCount = 0;//停止计时器
	//TPTimerOutCount = 0//超时退出
//		t = wait_event_timeout(NULL, cd->mode == CY_MODE_SYSINFO,
			
	if (IS_TMO(t)) {
		DebugUart_Printf(TP_Debug,"tmo waiting exit bl cd->mode=%d\r\n",cd->mode);
		//dev_err(cd->dev, "%s: tmo waiting exit bl cd->mode=%d\n",__func__, cd->mode);
		cd->int_status &= ~CY_INT_MODE_CHANGE;
		return -ETIME;
	}

	return 0;
}

static int set_mode(struct cyttsp6_core_data *cd, int new_mode)
{
	u8 new_dev_mode;
	u8 mode;
	long t;
	int rc;

	switch (new_mode) {
	case CY_MODE_OPERATIONAL:
		new_dev_mode = CY_HST_OPERATE;
		break;
	case CY_MODE_SYSINFO:
		new_dev_mode = CY_HST_SYSINFO;
		break;
	case CY_MODE_CAT:
		new_dev_mode = CY_HST_CAT;
		break;
	default:
		//dev_err(cd->dev, "%s: invalid mode: %02X(%d)\n",__func__, new_mode, new_mode);
		DebugUart_Printf(TP_Debug,"set_mode:invalid mode: %2x(%d)\r\n",new_mode, new_mode);
		return -EINVAL;
	}

	/* change mode */
//	dev_dbg(cd->dev, "%s: have exclusive=%p new_dev_mode=%02X new_mode=%s\n",
//			__func__, cd->exclusive_dev,
//			new_dev_mode, mode2str(new_mode));

	rc = cyttsp6_adap_read(cd, CY_REG_BASE, &mode, sizeof(mode));
	if (rc < 0) {
		//dev_err(cd->dev, "%s: Fail read mode r=%d\n", __func__, rc);
		DebugUart_Printf(TP_Debug,"set_mode:Fail read mode r=%d\r\n",rc);
		goto exit;
	}

	/* Clear device mode bits and set to new mode */
	mode &= ~CY_HST_DEVICE_MODE;
	mode |= new_dev_mode | CY_HST_MODE_CHANGE;

	cd->int_status |= CY_INT_MODE_CHANGE;
	rc = cyttsp6_adap_write(cd, CY_REG_BASE, &mode, sizeof(mode));
	if (rc < 0) {
		//dev_err(cd->dev, "%s: Fail write mode change r=%d\n",__func__, rc);
		DebugUart_Printf(TP_Debug,"Fail write mode change rc=%d\r\n",rc);
		goto exit;
	}

	/* wait for mode change done interrupt */
	wait_event_timeout(&cd->wait_q,(cd->int_status & CY_INT_MODE_CHANGE) == 0,CY_CORE_MODE_CHANGE_TIMEOUT);
	t = TPTimerOutCount;
	TPTimerOutCount = 0;//停止计时器
	//t = 1;
//	dev_dbg(cd->dev, "%s: back from wait t=%ld cd->mode=%s\n",
//			__func__, t, mode2str(cd->mode));

	if (IS_TMO(t)) {
		//dev_err(cd->dev, "%s: tmo waiting mode change\n", __func__);
		DebugUart_Printf(TP_Debug,"tmo waiting mode change\r\n",rc);
		cd->int_status &= ~CY_INT_MODE_CHANGE;
		rc = -EINVAL;
	}

exit:
	return rc;
}


static void cyttsp6_parse_mode(struct device *dev, u8 mode,
		enum cyttsp6_mode *cur_mode)
{
	switch (mode & CY_HST_DEVICE_MODE) 
	{
	case CY_HST_OPERATE:
		*cur_mode = CY_MODE_OPERATIONAL;
//		dev_vdbg(dev, "%s: operational\n", __func__);
		break;
	case CY_HST_CAT:
		*cur_mode = CY_MODE_CAT;
//		dev_vdbg(dev, "%s: CaT\n", __func__);
		break;
	case CY_HST_SYSINFO:
		*cur_mode = CY_MODE_SYSINFO;
//		dev_vdbg(dev, "%s: sysinfo\n", __func__);
		break;
	default:
		*cur_mode = CY_MODE_UNKNOWN;
		//dev_err(dev, "%s: unknown HST mode 0x%02X\n", __func__, mode);
		DebugUart_Printf(TP_Debug,"cyttsp6_parse_mode:unknown HST mode 0x%2x\r\n",mode);
		break;
	}
}

//static char *mode2str(int mode)
//{
//	switch (mode) {
//	case CY_MODE_UNKNOWN:
//			return "unknown";
//	case CY_MODE_BOOTLOADER:
//		return "bootloader";
//	case CY_MODE_OPERATIONAL:
//		return "operational";
//	case CY_MODE_SYSINFO:
//		return "sysinfo";
//	case CY_MODE_CAT:
//		return "cat";
//	case CY_MODE_STARTUP:
//		return "startup";
//	case CY_MODE_LOADER:
//		return "loader";
//	case CY_MODE_CHANGE_MODE:
//		return "change_mode";
//	case CY_MODE_CHANGED:
//		return "changed";
//	case CY_MODE_CMD_COMPLETE:
//		return "cmd_complete";
//	default:
//		return "mode_failure";
//	}
//}

static int cyttsp6_handshake_(struct cyttsp6_core_data *cd, u8 mode)
{
	u8 cmd = mode ^ CY_HST_TOGGLE;
	int rc;

	if (mode & CY_HST_MODE_CHANGE) {
		//dev_err(cd->dev, "%s: Host mode change bit set, NO handshake\n",__func__);
		DebugUart_Printf(TP_Debug,"cyttsp6_handshake_:Host mode change bit set, NO handshake\r\n");
		return 0;
	}

	rc = cyttsp6_adap_write(cd, CY_REG_BASE, &cmd, sizeof(cmd));
	if (rc < 0)
		//dev_err(cd->dev, "%s: bus write fail on handshake (ret=%d)\n",__func__, rc);
		DebugUart_Printf(TP_Debug,"cyttsp6_handshake_:bus write fail on handshake (ret=%d)\r\n",rc);
	
	return rc;
}

static int cyttsp6_load_status_and_touch_regs_(struct cyttsp6_core_data *cd,bool optimize)
{
//	struct device *dev = cd->dev;
	int first_read_len;
	int second_read_off;
	int num_read_rec;
	u8 num_cur_rec;
	//u8 hst_mode;
	u8 rep_len;
//	u8 rep_stat;
	u8 tt_stat;
	int rc;
#ifdef VERBOSE_DEBUG
	u8 rep_stat_counter;
#endif
	u8 i = 0;

	first_read_len = CY_REP_HDR_SIZE; //si->si_ofs.rep_hdr_size;
	/* Read one touch record additionally */
	if (optimize)
		first_read_len += CY_TCH_REC_SIZE; //si->si_ofs.tch_rec_size;

	rc = cyttsp6_adap_read(cd, CY_REP_OFS /*si->si_ofs.rep_ofs*/,
			&cd->xy_mode[CY_REP_OFS/*si->si_ofs.rep_ofs*/], first_read_len);
	if (rc < 0) {
		//dev_err(dev, "%s: reading touch record failed r=%d\n",__func__, rc);
		DebugUart_Printf(TP_Debug,"cyttsp6_load_status_and_touch_regs_:reading touch record failed rc=%d\r\n",rc);
		return rc;
	}
	//DebugUart_Printf(1,"3\r\n");

//#ifdef VERBOSE_DEBUG
//	/* print xy data */
//	cyttsp6_pr_buf(dev, cd->pr_buf, si->xy_mode,
//		si->si_ofs.mode_size, "xy_mode");
//#endif

//	hst_mode = cd->xy_mode[CY_REG_BASE];
	rep_len = cd->xy_mode[CY_REP_OFS/*si->si_ofs.rep_ofs*/];
//	rep_stat = cd->xy_mode[CY_REP_OFS + 1 /*si->si_ofs.rep_ofs + 1*/];
	tt_stat = cd->xy_mode[CY_TT_STAT_OFS /*si->si_ofs.tt_stat_ofs*/];
//	dev_vdbg(dev, "%s: %s%02X %s%d %s%02X %s%02X\n", __func__,
//		"hst_mode=", hst_mode, "rep_len=", rep_len,
//		"rep_stat=", rep_stat, "tt_stat=", tt_stat);
//#ifdef VERBOSE_DEBUG
//	cd->rep_stat_counter = ((cd->rep_stat_counter + 1) & 0x3);
//	rep_stat_counter = rep_stat >> 6;
//	if (cd->rep_stat_counter != rep_stat_counter) {
//		dev_vdbg(dev, "Possibly missed a touch record expected:%d device:%d\n",
//				cd->rep_stat_counter, rep_stat_counter);
//		cd->rep_stat_counter = rep_stat_counter;
//	}
//#endif

	num_cur_rec = GET_NUM_TOUCH_RECORDS(tt_stat);
	//dev_vdbg(dev, "%s: num_cur_rec=%d\n", __func__, num_cur_rec);

	if (rep_len == 0 && num_cur_rec > 0) 
	{
		//dev_err(dev, "%s: report length error rep_len=%d num_rec=%d\n",__func__, rep_len, num_cur_rec);
		DebugUart_Printf(TP_Debug,"cyttsp6_load_status_and_touch_regs_:report length error rep_len=%d num_rec=%d\r\n",rep_len, num_cur_rec);
		return -EIO;
	}

	if (num_cur_rec > CY_MAX_TCHS /*si->si_ofs.max_tchs*/) 
	{
		//dev_err(dev, "%s: %s (n=%d c=%zu)\n", __func__,"too many tch; set to max tch",num_cur_rec, CY_MAX_TCHS /*si->si_ofs.max_tchs*/);
		//DebugUart_Printf(TP_Debug,"cyttsp6_load_status_and_touch_regs_:n=%d\r\n",num_cur_rec);
			
		num_cur_rec = CY_MAX_TCHS /*si->si_ofs.max_tchs*/;
	}

	num_read_rec = num_cur_rec;
	
	//DebugUart_Printf(TP_Debug,"num_read_rec=%d\r\n",num_read_rec);
	second_read_off = CY_TT_STAT_OFS + 1; //si->si_ofs.tt_stat_ofs + 1;
	if (optimize) 
	{
		num_read_rec--;
		second_read_off += CY_TCH_REC_SIZE; //si->si_ofs.tch_rec_size;
	}
	
	if (num_read_rec < 0)
	{
		//DebugUart_Printf(1,"4\r\n");
		goto exit_print;
	}
		
	//DebugUart_Printf(1,"5\r\n");
	rc = cyttsp6_adap_read(cd, second_read_off,&cd->xy_mode[second_read_off],num_read_rec * CY_TCH_REC_SIZE /*si->si_ofs.tch_rec_size*/);
	if (rc < 0) {
		//dev_err(dev, "%s: read fail on touch regs r=%d\n",__func__, rc);
		DebugUart_Printf(TP_Debug,"cyttsp6_load_status_and_touch_regs_:read fail on touch regs rc=%d\r\n",rc);
		return rc;
	}

	//DebugUart_Printf(TP_Debug,"TouchInfoNum:num_read_rec=%d\r\n",num_read_rec);
	//将数据传送出去
	if(I2C_SendBuf[I2CSendFillNum].NewDataFlg == 1)
	{
		DebugUart_Printf(TP_Debug,"Touch Buf FIFO:%d\r\n",I2CSendFillNum);
	}
	else
	{
		I2C_SendBuf[I2CSendFillNum].buf[0] = num_read_rec;//TouchNum
		for(i=0; i<num_read_rec; i++)
		{
			I2C_SendBuf[I2CSendFillNum].buf[1+i*7] = cd->xy_mode[28+i*10];
			I2C_SendBuf[I2CSendFillNum].buf[2+i*7] = cd->xy_mode[29+i*10];//X
			I2C_SendBuf[I2CSendFillNum].buf[3+i*7] = cd->xy_mode[30+i*10];
			I2C_SendBuf[I2CSendFillNum].buf[4+i*7] = cd->xy_mode[31+i*10];//Y
			I2C_SendBuf[I2CSendFillNum].buf[5+i*7] = cd->xy_mode[32+i*10];//P
			I2C_SendBuf[I2CSendFillNum].buf[6+i*7] = cd->xy_mode[33+i*10];//T
			I2C_SendBuf[I2CSendFillNum].buf[7+i*7] = cd->xy_mode[36+i*10];//MAJ
		}
		I2C_SendBuf[I2CSendFillNum].len = 7*num_read_rec + 1;
		I2C_SendBuf[I2CSendFillNum].NewDataFlg = 1;
	
		DebugUart_Printf(1,"TouchNum=%d,",I2C_SendBuf[I2CSendFillNum].buf[0]);
		for(i=0; i<I2C_SendBuf[I2CSendFillNum].buf[0]; i++)
		{
			//DebugUart_Printf(1,"X=%d,",((UINT16)I2C_SendBuf[I2CSendFillNum].buf[1+i*7]<<8|I2C_SendBuf[I2CSendFillNum].buf[2+i*7]));
			//DebugUart_Printf(1,"Y=%d,",((UINT16)I2C_SendBuf[I2CSendFillNum].buf[3+i*7]<<8|I2C_SendBuf[I2CSendFillNum].buf[4+i*7]));
			//DebugUart_Printf(1,"P=%d,",I2C_SendBuf[I2CSendFillNum].buf[5+i*7]);
			DebugUart_Printf(1,"T=0x%2x,",I2C_SendBuf[I2CSendFillNum].buf[6+i*7]);
			//DebugUart_Printf(1,"M=%d,",I2C_SendBuf[I2CSendFillNum].buf[7+i*7]);
		}	
		DebugUart_Printf(1,"\r\n");	
		
		I2CSendFillNum ++;
		if(I2CSendFillNum == I2C_SendMax)
		{
				I2CSendFillNum = 0;
		}
	}
		
exit_print:
	/* print xy data */
//	cyttsp6_pr_buf(dev, cd->pr_buf, si->xy_data,
//		num_cur_rec * si->si_ofs.tch_rec_size, "xy_data");
	//DebugUart_Printf(1,"6\r\n");	

	return 0;
}

/******************************************************************************
** Function    : cyttsp6_startup
** Description : TP初始化操作
*******************************************************************************/
int cyttsp6_startup(struct cyttsp6_core_data *cd)
{
//	struct device *dev = cd->dev;
	int rc;

	cd->xy_data = &cd->xy_mode[28];
//#if 0
//	rc = cyttsp6_wait_bl_heartbeat(cd);
//	if (rc) {
//		dev_err(dev, "%s: Error on waiting bl heartbeat r=%d\n",
//			__func__, rc);
//		return rc;
//	}
//#endif

	/* exit bl into sysinfo mode */
	rc = _exit_bootloader(cd);
	if (rc < 0) {
		//dev_err(dev, "%s: Fail exit bootloader rc=%d\n",__func__, rc);
		DebugUart_Printf(TP_Debug,"cyttsp6_startup:Fail exit bootloader rc=%d\r\n",rc);
		return rc;
	}

	rc = cyttsp6_wait_sysinfo_mode(cd);
	if (rc < 0) {
		//dev_err(dev, "%s: Fail switch to sysinfo mode, r=%d\n",__func__, rc);
		DebugUart_Printf(TP_Debug,"cyttsp6_startup:Fail switch to sysinfo mode, rc=%d\r\n",rc);
		goto exit_lock;
	}

	rc = set_mode(cd, CY_MODE_OPERATIONAL);
	if (rc < 0) {
		//dev_err(dev, "%s: Fail set mode to Operational mode, r=%d\n",__func__, rc);
		DebugUart_Printf(TP_Debug,"cyttsp6_startup:Fail set mode to Operational mode, rc=%d\r\n",rc);
		goto exit_lock;
	}
	
	DebugUart_Printf(TP_Debug,"cyttsp6_startup InitOk\r\n");
exit_lock:
	return rc;
}

/******************************************************************************
** Function    : cyttsp6_irq
** Description : INT中断处理函数
*******************************************************************************/
void cyttsp6_irq(struct cyttsp6_core_data *cd)
{
	struct device *dev = cd->dev;
	enum cyttsp6_mode cur_mode;

	u8 cmd_ofs = CY_CMD_OFS;//cd->sysinfo.si_ofs.cmd_ofs;
	bool command_complete = 0;
	u8 mode[3];
	int rc;

	rc = cyttsp6_adap_read(cd, CY_REG_BASE, mode, sizeof(mode));
	if (rc == 0) 
	{
		DebugUart_Printf(TP_Debug,"cyttsp6_irq:cyttsp6_adap_read err\r\n");
		goto cyttsp6_irq_exit;
	}

	if (IS_BOOTLOADER(mode[0], mode[1])) 
	{
		DebugUart_Printf(TP_Debug,"cyttsp6_irq:IS_BOOTLOADER\r\n");
		cur_mode = CY_MODE_BOOTLOADER;
		
		/* switch to bootloader */
		if (cd->mode != CY_MODE_BOOTLOADER)
		{
		}

		/* catch operation->bl glitch */
		if ((cd->mode != CY_MODE_BOOTLOADER) && (cd->mode != CY_MODE_UNKNOWN))
		{
			/* Incase startup_state, do not let startup_() */
			cd->mode = CY_MODE_UNKNOWN;
			DebugUart_Printf(TP_Debug,"cyttsp6_irq:CY_MODE_UNKNOWN\r\n");
			goto cyttsp6_irq_exit;
		}

		/* Recover if stuck in bootloader idle mode */
		if (cd->mode == CY_MODE_BOOTLOADER) 
		{
			if (IS_BOOTLOADER_IDLE(mode[0], mode[1])) 
			{
				if (cd->heartbeat_count > 3)
				{
					cd->heartbeat_count = 0;
					/* exit bl into sysinfo mode */
					rc = _exit_bootloader(cd);
					if (rc == 0) 
					{
						DebugUart_Printf(TP_Debug,"cyttsp6_startup:_exit_bootloader err\r\n");
					}					
					goto cyttsp6_irq_exit;
				}
				cd->heartbeat_count++;
			}
		}

		cd->mode = cur_mode;
		/* Signal bootloader heartbeat heard */
		wake_up(&cd->wait_q);
		goto cyttsp6_irq_exit;
	}

	cyttsp6_parse_mode(dev, mode[0], &cur_mode);

	/* Check whether this IRQ should be ignored (internal) */
	if (cd->int_status & CY_INT_IGNORE) 
	{
	}

	/* Check for wake up interrupt */
	if (cd->int_status & CY_INT_AWAKE) 
	{
		cd->int_status &= ~CY_INT_AWAKE;
		wake_up(&cd->wait_q);
		//DebugUart_Printf(1,"cyttsp6_irq_handshake1\r\n");
		goto cyttsp6_irq_handshake;
	}

	/* Expecting mode change interrupt */
	if ((cd->int_status & CY_INT_MODE_CHANGE) && ((mode[0] & CY_HST_MODE_CHANGE) == 0)) 
	{
		cd->int_status &= ~CY_INT_MODE_CHANGE;
		cd->mode = cur_mode;
		wake_up(&cd->wait_q);
		//DebugUart_Printf(1,"cyttsp6_irq_handshake2\r\n");
		goto cyttsp6_irq_handshake;
	}

	/* compare current core mode to current device mode */
	if (((mode[0] & CY_HST_MODE_CHANGE) == 0) && cd->mode != cur_mode) 
	{
		DebugUart_Printf(TP_Debug,"cyttsp6_irq:%d %d->%d int:%s\r\n",cd->mode,cur_mode, cd->int_status);
		goto cyttsp6_irq_exit;
	}

	/* Expecting command complete interrupt */
	if ((cd->int_status & CY_INT_EXEC_CMD)
			&& mode[cmd_ofs] & CY_CMD_COMPLETE) 
	{
		command_complete = 1;
		cd->int_status &= ~CY_INT_EXEC_CMD;
		wake_up(&cd->wait_q);
		/*
		 * It is possible to receive a single interrupt for
		 * command complete and touch/button status report.
		 * Continue processing for a possible status report.
		 */
	}

	if (!cd->xy_mode)
	{
		//DebugUart_Printf(1,"cyttsp6_irq_handshake3\r\n");
		goto cyttsp6_irq_handshake;
	}

	/* Copy the mode registers */
	memcpy(cd->xy_mode, mode, sizeof(mode));

	/* This should be status report, read status and touch regs */
	if (cd->mode == CY_MODE_OPERATIONAL) 
	{
		//DebugUart_Printf(1,"2\r\n");
		rc = cyttsp6_load_status_and_touch_regs_(cd, command_complete);
		if (rc < 0)
			DebugUart_Printf(TP_Debug,"cyttsp6_irq:fail read mode/touch regs rc=%d\r\n",rc);
	}

cyttsp6_irq_handshake:
	/* handshake the event */
	rc = cyttsp6_handshake_(cd, mode[0]);
	if (rc < 0)
		DebugUart_Printf(TP_Debug,"cyttsp6_irq:Fail handshake mode=0x%2x rc=%d\r\n",mode[0], rc);
	/*
	 * a non-zero udelay period is required for using
	 * IRQF_TRIGGER_LOW in order to delay until the
	 * device completes isr deassert
	 */
	//DebugUart_Printf(1,"cyttsp6_handshake_\r\n");
//	udelay(cd->cpdata->level_irq_udelay);

cyttsp6_irq_exit:
	//DebugUart_Printf(1,"cyttsp6_irq_exit\r\n");
	return;
}

int cyttsp6_watchdog_work(struct cyttsp6_core_data *cd)
{
	u8 mode[2];
	int rc;
	
	rc = cyttsp6_adap_read(cd,CY_REG_BASE,&mode,sizeof(mode));
	if(rc == 0)
	{
		DebugUart_Printf(1,"cyttsp6_adap_read I2C Err\r\n");
		return 0;
	}

	if(IS_BOOTLOADER(mode[0], mode[1]))
	{
		DebugUart_Printf(1,"Device found in bootloader mode\r\n");
		return 0;
	}
	
	return 1;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MCU (控制器单元) 是一种微控制器,它在触摸屏设计中扮演着重要的角色。 首先,触摸屏是一种通过感应触摸手指或触控笔输入的设备。MCU负责处理触摸屏输入的信号,将其转化为计算机可以理解的数据格式。MCU通常具有强大的处理能力和快速的响应时间,以确保触摸屏的准确性和流畅性。 其次,MCU还负责控制触摸屏的驱动电路。触摸屏通常由一层导电材料(如导电玻璃)和一层透明材料(如玻璃或塑料)组成。当用户触摸屏幕时,导电材料会与透明材料之间形成一个电流通路,而MCU就是负责监测和控制这个电流的流动。通过对电流的监测,MCU可以确定用户的触摸位置和动作。 此外,MCU还可以提供额外功能,如手势识别和多点触控。通过识别用户的手势,MCU可以实现一系列操作,如缩放、旋转和滑动。多点触控允许用户使用多个手指在屏幕上进行操作,提供更多的交互灵活性。 在触摸屏设计中,MCU的选择非常重要。一个高质量的MCU可以提供更好的触摸性能和用户体验。它需要具有稳定的信号处理和快速的响应速度,以确保触摸屏的准确性和流畅性。此外,低功耗和高可靠性也是选择MCU时需要考虑的因素。 总而言之,MCU触摸屏设计中起着关键的作用。它不仅负责处理触摸信号和控制触摸驱动电路,还可以提供额外的功能和用户体验优化。因此,在设计触摸屏时,我们需要仔细选择合适的MCU来确保良好的性能和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值