#include "touch_panel_manager.h"
#include "event.h"

#ifdef CONFIG_TLSC6X

static struct sw_touch_panel_platform_data *_touch_panel_data = NULL;

/**IIC ADDR**/
#define TLSC6X_IIC_WADDR 0x5C//0x5C 0x34  
#define TLSC6X_IIC_RADDR 0X5D//0X5D 0x35

/**REG ADDR**/
#define TLSC6X_REG_IC_YTPE_ADDR 	0xD0 //0xa0
#define TLSC6X_REG_VENDOR_ID_ADDR 	0xa5 //0xa8


#define TLSC6X_REG_READ_COOR_ADDR      0x00//0xD000//0x02


/**OTHER DEFINE**/
#define TLSC6X_CNT_DOWN        1
#define TLSC6X_CNT_LONG        20
#define TLSC6X_CNT_HOLD        0

#define TLSC6X_MAX_TOUCH_POINT		2
#define TLSC6X_DATA_CNT_FOR_POINT 	7//6

#define TLSC6X_TOUCH_STATUS_PRESS 		6 //0
#define TLSC6X_TOUCH_STATUS_RELEASE 	1
#define TLSC6X_TOUCH_STATUS_CONTACT 	2
#define TLSC6X_TOUCH_STATUS_NG 		3


typedef struct {
    u8 fresh;
    u16 x;
    u16 y;
    u16 size;
} POINT;


extern void delay(unsigned int i);
extern void delay_2ms(int cnt);


POINT point[TLSC6X_MAX_TOUCH_POINT];


static int _touch_panel_timer_reg;



static void TCH_INT_H()
{
    if (_touch_panel_data) {
        gpio_direction_output(_touch_panel_data->int_pin, 1);
    }
}

static void TCH_INT_L()
{
    if (_touch_panel_data) {
        gpio_direction_output(_touch_panel_data->int_pin, 0);
    }
}

static void TCH_RST_H()
{
    if (_touch_panel_data) {
        gpio_direction_output(_touch_panel_data->rst_pin, 1);
    }
}

static void TCH_RST_L()
{
    if (_touch_panel_data) {
        gpio_direction_output(_touch_panel_data->rst_pin, 0);
    }
}

static void TCH_INT_IN()
{
    if (_touch_panel_data) {
        gpio_direction_input(_touch_panel_data->int_pin);
    }
}


static int TLSC6X_get_coord(int *coord)
{
    u8 touch_info;
    u8 point_data[TLSC6X_MAX_TOUCH_POINT * TLSC6X_DATA_CNT_FOR_POINT + 1] = {0};
    static u8 fresh_comm = 0;
    u8 tid;
    u8 touch_num = 0, touch_status = 0x00;
    u16 xpos, ypos, touchSize;

  //  u8 *coor_data = NULL;


    int i;
    u8 ret = FALSE;

    ret = _touch_panel_read(TLSC6X_IIC_WADDR, TLSC6X_IIC_RADDR, TLSC6X_REG_READ_COOR_ADDR, point_data, (TLSC6X_MAX_TOUCH_POINT * TLSC6X_DATA_CNT_FOR_POINT + 1));

    if (ret != TRUE) {
        printf("I2C transfer error. errno:%d\n ", ret);
        return 0;
    }

#if 0
    for (i = 0; i < (TLSC6X_MAX_TOUCH_POINT * TLSC6X_DATA_CNT_FOR_POINT + 1); i++) {
        printf("TLSC6X TS 0x%02X : 0x%02X\n", (TLSC6X_REG_READ_COOR_ADDR + i), point_data[i]);
    }
#endif
  if(0x10 != point_data[8]){
		 // printf("error touch size:%d \n",point_data[8]);
		  return 0;
		}

    //touch_info = point_data[0];
	touch_info = (point_data[2] & 0x0f);
    if(touch_info < 1 || touch_info > 2)
		return 0;
//if (_touch_panel_data->_DEBUGP) 
   // printf("point_data:0x%02X,0x%02X,0x%02X,0x%02X,0x%02X\n  ,0x%02X,0x%02X,0x%02X\n", point_data[0],point_data[1],point_data[2],point_data[3],point_data[4],point_data[5],point_data[6],point_data[7]);

//	printf("touch info 0x%02X\n", touch_info);



    if (touch_info) {
        touch_num = touch_info;

    if (touch_num > _touch_panel_data->_MAX_POINT) {
           
            touch_num = _touch_panel_data->_MAX_POINT;
        }

		if (_touch_panel_data->_DEBUGP) 
 		   printf("touch number %d\n", touch_num);


        fresh_comm++;
         /* x =(point_data[1]<<8)|((point_data[3]>>4)&0x0f) 
            y =(point_data[2]<<8)|(point_data[3]&0x0f)*/
        for (i = 0; i < touch_num; i++) {
           // coor_data = &point_data[i * TLSC6X_DATA_CNT_FOR_POINT + 1];

         //   touch_status = point_data[i] & 0x0f;// touch_status = coor_data[0] >> 6;

			tid = i;//(point_data[i]&0xf0) >> 8; //触点id号
           // tid = coor_data[2] >> 4;

		    
			xpos = point_data[4]; //x的低8bit
			xpos = xpos | ((point_data[3] & 0x0f)<<4);
       
            ypos = point_data[6]; //y的低8bit
			ypos = ypos | ((point_data[5] & 0x0f)<<4);
			
            touchSize = point_data[8] ;//touchSize = coor_data[4];

		if (_touch_panel_data->_DEBUGP){
            printf("touch id %d\n", tid);
           // printf("touch status 0x%02X\n", touch_status);
			}
            if (tid > _touch_panel_data->_MAX_POINT - 1) {
                break;
            }

          

            point[tid].fresh = fresh_comm;
            // point[tid].y = ypos;
            // point[tid].x = xpos;
            point[tid].size = touchSize;

            if (_touch_panel_data->_X2Y_EN) {
                point[tid].x = ypos;
                point[tid].y = xpos;
            } else {
                point[tid].y = ypos;
                point[tid].x = xpos;
            }

            if (_touch_panel_data->_X_MIRRORING) {
                point[tid].x = _touch_panel_data->_MAX_X - 1 - point[tid].x;
            }

            if (_touch_panel_data->_Y_MIRRORING) {
#if defined(LCD_DSI_VDO_2LANE_MIPI_GC9503V_640X360_RGH_RT30HD033A)
                point[tid].y = 4 + (_touch_panel_data->_MAX_Y - 1 - point[tid].y);
#else
                point[tid].y = _touch_panel_data->_MAX_Y - 1 - point[tid].y;
#endif
            } else {
#if defined(LCD_DSI_VDO_2LANE_MIPI_GC9503V_640X360_RGH_RT30HD033A)
                point[tid].y += 4;
#endif
            }

            if (_touch_panel_data->_DEBUGP) {
                printf("\n touch_panel:(%d)(x=%d, y=%d)[%d]\n", tid, point[tid].x, point[tid].y, point[tid].size);
            }

            coord[0] = point[tid].x;
            coord[1] = point[tid].y;

            return TRUE;
        }
    } else {
        touch_num = 0;
    }

    return FALSE;
}


/**
功能： TLSC6X读数据
输入： void
输出： touch_num 触点个数
**/
static u8 TLSC6X_event_handler(void)
{
    u8 touch_info;
    u8 point_data[TLSC6X_MAX_TOUCH_POINT * TLSC6X_DATA_CNT_FOR_POINT + 1] = {0};
    static u8 fresh_comm = 0;
    u8 tid;
    u8 touch_num = 0, touch_status = 0x00;
    u16 xpos, ypos, touchSize;

 //   u8 *coor_data = NULL;


    int i;
    u8 ret = FALSE;

    ret = touch_panel_RReg(TLSC6X_REG_READ_COOR_ADDR, point_data, (TLSC6X_MAX_TOUCH_POINT * TLSC6X_DATA_CNT_FOR_POINT + 1));

    if (ret != TRUE) {
        printf("I2C transfer error. errno:%d\n ", ret);
        return 0;
    }

#if 0
    for (i = 0; i < (TLSC6X_MAX_TOUCH_POINT * TLSC6X_DATA_CNT_FOR_POINT + 1); i++) {
        printf("TLSC6X TS 0x%02X : 0x%02X\n", (TLSC6X_REG_READ_COOR_ADDR + i), point_data[i]);
    }
#endif
	if(0x10 != point_data[8]){
		  printf("error: invalid tp date \n");
		  return 0;
		}

	touch_info = (point_data[5] & 0x0f);
   // touch_info = point_data[0];
	printf("TLSC6X_event_handler touch info 0x%02X\n", touch_info);

    if (touch_info) {
        touch_num = touch_info;

        if (touch_num > _touch_panel_data->_MAX_POINT) {
            /* goto exit_work_func; */
            touch_num = _touch_panel_data->_MAX_POINT;
        }

//		printf("touch number %d\n", touch_num);


        fresh_comm++;

        for (i = 0; i < touch_num; i++) {
           // coor_data = &point_data[i * TLSC6X_DATA_CNT_FOR_POINT + 1];

           // touch_status = point_data[i] & 0x0f;

           tid = i;//(point_data[i]&0xf0) >> 8; //触点id号
           // tid = coor_data[2] >> 4;

		    
			xpos = point_data[4]; //x的低8bit
			xpos = xpos | ((point_data[3] & 0x0f)<<4);
       
            ypos = point_data[6]; //y的低8bit
			ypos = ypos | ((point_data[5] & 0x0f)<<4);
			
            touchSize = point_data[8] ;//touchSize = coor_data[4];

            //printf("touch id %d\n", tid);
            //printf("touch status 0x%02X\n", touch_status);

            if (tid > _touch_panel_data->_MAX_POINT - 1) {
                continue;
            }

            

            point[tid].fresh = fresh_comm;
            // point[tid].y = ypos;
            // point[tid].x = xpos;
            point[tid].size = touchSize;

            if (_touch_panel_data->_X2Y_EN) {
                point[tid].x = ypos;
                point[tid].y = xpos;
            } else {
                point[tid].y = ypos;
                point[tid].x = xpos;
            }

            if (_touch_panel_data->_X_MIRRORING) {
                point[tid].x = _touch_panel_data->_MAX_X - 1 - point[tid].x;
            }

            if (_touch_panel_data->_Y_MIRRORING) {
                #if defined(LCD_DSI_VDO_2LANE_MIPI_GC9503V_640X360_RGH_RT30HD033A)
                point[tid].y = 4 + (_touch_panel_data->_MAX_Y - 1 - point[tid].y);
                #else
                point[tid].y = _touch_panel_data->_MAX_Y - 1 - point[tid].y;
                #endif
            } else {
                #if defined(LCD_DSI_VDO_2LANE_MIPI_GC9503V_640X360_RGH_RT30HD033A)
                point[tid].y += 4;
                #endif
            }

            if (_touch_panel_data->_DEBUGP) {
                printf("\ntouch_panel:(%d)(x=%d, y=%d)[%d]\n", tid, point[tid].x, point[tid].y, point[tid].size);
            }
        }
    } else {
        touch_num = 0;

        //printf("touch number %d\n", touch_num);
    }


    for (i = 0; i < _touch_panel_data->_MAX_POINT; i++) {
        if (touch_num == 0 || point[i].fresh != fresh_comm) {
            point[i].fresh = fresh_comm;
            point[i].x = 0x7FFF;
            point[i].y = 0x7FFF;
            point[i].size = 0x7FFF;
        }
    }


    return touch_num;
}


/**
功能： TLSC6X读坐标及数据处理
输入： void
输出： void
**/
static void TLSC6X_read_point(void *arg)
{
    int i;
    putchar('P');
    //if (gpio_read(_touch_panel_data->int_pin))
    if (1) {
        _touch_panel_data->points.point_num = TLSC6X_event_handler();
    } else {
        _touch_panel_data->points.point_num = 0;
    }
  //yguohua add start
	if (_touch_panel_data->_DEBUGE) {
					printf(" TLSC6X_read_point [%d](%d) (%d,%d)\n", i, _touch_panel_data->points.p[i].e, _touch_panel_data->points.p[i].x, _touch_panel_data->points.p[i].y);
				}
	//yguohua add end

    for (i = 0; i < _touch_panel_data->_MAX_POINT; i++) {
        _touch_panel_data->points.p[i].e = 0xff;

        if (point[i].x >= _touch_panel_data->_MAX_X || point[i].y >= _touch_panel_data->_MAX_Y) {
            if (_touch_panel_data->points.p[i].c < TLSC6X_CNT_DOWN) {
                _touch_panel_data->points.p[i].e = 0xff;
            } else {
                _touch_panel_data->points.p[i].e = TOUCH_EVENT_UP;
            }
            _touch_panel_data->points.p[i].c = 0;

        } else {
            _touch_panel_data->points.p[i].c++;
            if (_touch_panel_data->points.p[i].c == TLSC6X_CNT_DOWN) {
                _touch_panel_data->points.p[i].x = point[i].x;
                _touch_panel_data->points.p[i].y = point[i].y;
                _touch_panel_data->points.p[i].e = TOUCH_EVENT_DOWN;
            } else if (_touch_panel_data->points.p[i].c > TLSC6X_CNT_DOWN) {
                if (point[i].x != _touch_panel_data->points.p[i].x ||
                    point[i].y != _touch_panel_data->points.p[i].y) {
                    if (_touch_panel_data->points.p[i].c > TLSC6X_CNT_DOWN + TLSC6X_CNT_DOWN) {
                        _touch_panel_data->points.p[i].x = point[i].x;
                        _touch_panel_data->points.p[i].y = point[i].y;
                        _touch_panel_data->points.p[i].e = TOUCH_EVENT_MOVE;
                        _touch_panel_data->points.p[i].c = TLSC6X_CNT_DOWN;
                    }
                }

                if (_touch_panel_data->points.p[i].c == TLSC6X_CNT_LONG + TLSC6X_CNT_HOLD) {
                    _touch_panel_data->points.p[i].x = point[i].x;
                    _touch_panel_data->points.p[i].y = point[i].y;
                    _touch_panel_data->points.p[i].e = TOUCH_EVENT_HOLD;
                }

                if (_touch_panel_data->points.p[i].c > TLSC6X_CNT_LONG + TLSC6X_CNT_HOLD) {
                    _touch_panel_data->points.p[i].c = TLSC6X_CNT_LONG;
                }
            }
        }

        if (_touch_panel_data->points.p[i].e != 0xff) {
            struct sys_event eve;
            eve.type = SYS_TOUCH_EVENT;
            eve.u.touch.event = _touch_panel_data->points.p[i].e;
            eve.u.touch.pos.x = _touch_panel_data->points.p[i].x;
            eve.u.touch.pos.y = _touch_panel_data->points.p[i].y;
            sys_event_notify(&eve);
            printf(">>>\n");
            // printf("type: %d, event: %d, x: %d, y: %d\n", eve.type, eve.u.touch.event, eve.u.touch.pos.x, eve.u.touch.pos.y);

            if (_touch_panel_data->_DEBUGE) {
                printf(" TLSC6X_read_point [%d](%d) (%d,%d)\n", i, _touch_panel_data->points.p[i].e, _touch_panel_data->points.p[i].x, _touch_panel_data->points.p[i].y);
            }
        }
    }
}




/**
功能： TLSC6X读ID
输入： void
输出： TRUE - 成功
       FALSE- 失败
**/
static u8 TLSC6X_read_id(void)
{
    u8 ret = TRUE;//FALSE

    u8 gt_TLSC6X_product_id = 0xff, gt_TLSC6X_vendor_id = 0xff;

    /* Read product and vendor ID */
    ret = _touch_panel_read(TLSC6X_IIC_WADDR, TLSC6X_IIC_RADDR, TLSC6X_REG_IC_YTPE_ADDR, &gt_TLSC6X_product_id, 1);
    printf("TLSC6X_read_id ===>1 ret value: %d\n", ret);
    ret = _touch_panel_read(TLSC6X_IIC_WADDR, TLSC6X_IIC_RADDR, TLSC6X_REG_VENDOR_ID_ADDR, &gt_TLSC6X_vendor_id, 1);
    printf("===>2 ret value: %d\n", ret);


    printf("TLSC6X produrc ID = 0x%02X, vendor ID = 0x%02X\r\n", gt_TLSC6X_product_id, gt_TLSC6X_vendor_id);


    return ret;
}






void TLSC6X_IoInit(void)
{

#if 1
    delay_2ms(60);

#if 1
    /* reset */
    TCH_RST_H();
    delay_2ms(60);
    TCH_RST_L();
    delay_2ms(60);
    TCH_RST_H();
    delay_2ms(60);
#endif

    delay_2ms(60);
    TCH_INT_IN();
    delay_2ms(60);

#endif

}


/**
功能： TLSC6X进入睡眠模式
输入： void
输出： TRUE - 成功
       FALSE- 失败
**/
static u8 TLSC6X_sleep(void)
{
    u8 ret = FALSE;
    return ret;
}


/**
功能： TLSC6X唤醒
输入： void
输出： void
**/
static void TLSC6X_wakeup(void)
{
    TLSC6X_IoInit();
}





/**********************************/
/*********以下为接口函数**********/
/**********************************/

/**
功能： TLSC6X检查ID
输入： void
输出： TRUE - 成功
       FALSE- 失败
**/
static char TLSC6X_check(struct sw_touch_panel_platform_data *data)
{
    _touch_panel_data = data;

    TLSC6X_IoInit();

    return TLSC6X_read_id();
}

/**
功能： TLSC6X初始化
输入： void
输出： TRUE - 成功
       FALSE- 失败
**/
static char TLSC6X_init(void)
{
    u8 ret = TRUE;
    int reset_count = 0;

    if (_touch_panel_data == NULL) {
        puts("need call check before init");
        return FALSE;
    }

    for (int i = 0; i < TLSC6X_MAX_TOUCH_POINT; i++) {
        point[i].fresh = 0;
        point[i].x = 0x7FFF;
        point[i].y = 0x7FFF;
        point[i].size = 0x7FFF;
    }

    if (ret == TRUE) {
        if (_touch_panel_data->enable) {
            _touch_panel_timer_reg = sys_timer_add((void *)0, TLSC6X_read_point, 20);
        }
    }

    return ret;
}

/**
功能： TLSC6X控制
输入： void
输出： TRUE - 成功
       FALSE- 失败
**/
static char TLSC6X_ioctl(u32 cmd, u32 arg)
{
    switch (cmd) {
    case TOUCH_PANEL_CMD_SLEEP:
        TLSC6X_sleep();
        break;
    case TOUCH_PANEL_CMD_WAKEUP:
        TLSC6X_wakeup();
        break;
    case TOUCH_PANEL_CMD_RESET:
        TLSC6X_init();
        break;
    case TOUCH_PANEL_CMD_DISABLE:
        if (_touch_panel_data->enable) {
            _touch_panel_data->enable = 0;
            sys_timer_del(_touch_panel_timer_reg);
        }
        break;
    case TOUCH_PANEL_CMD_ENABLE:
        if (!_touch_panel_data->enable) {
            _touch_panel_data->enable = 1;
            _touch_panel_timer_reg = sys_timer_add((void *)0, TLSC6X_read_point, 20);
        }
        break;
    case TOUCH_PANEL_CMD_COORD:
        return TLSC6X_get_coord((int *)arg);
        break;

    default:
        return FALSE;
    }
    return TRUE;
}


#if 1
_TOUCH_PANEL_INTERFACE TLSC6X_ops = {
    .touch_panel_check   =   TLSC6X_check,
    .touch_panel_init    =   TLSC6X_init,
    .touch_panel_ioctl   =   TLSC6X_ioctl,
};

REGISTER_TOUCH_PANEL(TLSC6X)
.touch_panel_ops = &TLSC6X_ops,
};
#endif




#endif


