/********************************** (C) COPYRIGHT *******************************
* File Name          : IIC.c
* Author             : WCH
* Version            : V1.0
* Date               : 2018/12/12
* Description        : I2C 读写
*******************************************************************************/


/*********************************************************************
 * INCLUDES
 */
#include "typedef.h"
#include "TouchInclude.h"

#define READ_TOUCH_POS_EVT                  0x0001
#define READ_RESET_TOUCH_IC_EVT             0x0002
#define SYS_INIT_FINISH_EVT                 0x0004
#define RELEASE_TOUCH_EVT                   0x0008
#define READ_ONE_POINT_EVT                  0x0010
#define START_REPORT_POS_EVT                0x0020
#define CHECK_TOUCH_INT_EVT                 0x0040
#define REPORT_AGAIN_EVT                    0x0080
#define CHECK_ESD_EVT                       0x0100
#define HID_DEBUG_EVT                       0x0200
#define CHECK_USB_STATUS_EVT                0x0400

#define PERIO_1s 1600
#define PERIO_2s (PERIO_1s*2)
#define PERIO_5s (PERIO_1s*5)
#define PERIO_40s (PERIO_1s*40)


#pragma pack(1)
typedef struct
{
    UINT8 Reserved0:3;
    UINT8 FPEvent:1;
    UINT8 HotknotEvent:1;
    UINT8 GestureEvent:1;
    UINT8 RequestEvent:1;
    UINT8 TouchEvent:1;

    UINT8 INTCounter;

    UINT8 TouchNum:4;
    UINT8 LargeTouch:1;
    UINT8 HoverApproachFlag:1;
    UINT8 EdgeFlag:1;
    UINT8 ReseINT:1;

    UINT8 CustomCoorInfoFlag:1;
    UINT8 StylusKey:3;
    UINT8 Reserved1:4;

    UINT8 StylusPower;
    UINT8 Reserved3;
    UINT16 CheckSum;
}ST_EVENT_HEAD;

#pragma pack(1)
typedef struct{
    UINT8 rom_pid[6];               /* rom PID */
    UINT8 rom_vid[3];               /* Mask VID */
    UINT8 rom_vid_reserved;
    UINT8 patch_pid[8];              /* Patch PID */
    UINT8 patch_vid[4];              /* Patch VID */
    UINT8 patch_vid_reserved;
    UINT8 sensor_id;
    UINT8 reserved[2];
    UINT16 checksum;
}ST_FW_VERSION;

static UINT8 IICTouchTaskId = INVALID_TASK_ID;
static UINT8 PointNum = 0;
static UINT8 ReadPointCnt = 0;
static BOOL ReportPosSuccess = TRUE;
static void ReadOnePoint(void);
static void CheckTouchINT(void);
static void StartReportPos(void);
static void ReportPos(void);
static UINT16 IICTouch_ProcessEvent( UINT8 task_id, UINT16 events );
static void BT_Check_ESD();

#ifdef MOUSE_REPORT
  #ifndef GESTURE
  extern UINT8 mouse_right_click_time;
  #endif
#ifndef GESTURE
  extern void ReportMousePos(POINTER * pTP);
#else
  void ReportMousePos(POINTER * pTP, UINT8 interface);
#endif

  BOOL StylusFlag;
#endif

static BOOL SysInitFinish = FALSE;
extern BOOL SleepEn;
/*******************************************************************************
* Function Name  : BT_WR_Reg
* Description    : 向GT911写入一次数据
* Input          : reg:起始寄存器地址
                   buf:数据缓缓存区
                   len:写数据长度
* Output         : None
* Return         : 0,成功;1,失败.
*******************************************************************************/
__attribute__((section(".highcode")))
UINT8 BT_WR_Reg(UINT32 reg,UINT8 *buf,UINT8 len)
{
    return IICWriteBytes(reg,buf,len);
}

///*******************************************************************************
//* Function Name  : BT_RD_Reg
//* Description    : 从GT911读出一次数据
//* Input          : reg:起始寄存器地址
//                   buf:数据缓缓存区
//                   len:读数据长度
//* Output         : None
//* Return         : None
//*******************************************************************************/
//__attribute__((section(".highcode")))
UINT8 BT_RD_Reg(UINT32 reg, UINT8 *buf,UINT8 len)
{
    return IICReadBytes(reg, buf, len);
}



static void ShutdownHIDI2C()
{
    UINT8 nTryTimes = 50;

    if(IICWriteOneByte(0x3030AABB, 0xCC))
    {
        delay_ms(80);
        while(nTryTimes--)
        {
          if(SearchAddress(100))
            break;
          delay_ms(10);
        }
    }
}

BOOL EntryUpdateMode()
{
    UINT8 tryTimes = 3,i;

    UINT8 cmd[6] = {0x00,0x00,0x00,0x02,0x01,0x00};

    UINT32 state1,state2;

    gpio_reset_bits(GPIOA_REG, RST_PIN);
    delay_ms(20);//RST
    gpio_set_bits(GPIOA_REG, RST_PIN);
    delay_ms(15);//RST
    GioInterruptFlag = 0;
    if(!SearchAddress(100))
    {
        return FALSE;
    }
    while(tryTimes--)
    {
        IICWriteBytes(0x00000002, cmd + 4, 2);
        cmd[2] = 0x20;
        cmd[3] = 0x00;

        IICReadBytes(0x00002000, (UINT8*)&state1, 4);
        for(i=0; i<3; i++)
        {
            IICReadBytes(0x00002000, (UINT8*)&state2, 4);

            if(state1 != state2)
            {
                break;
            }
        }
        if(i==3) return TRUE;
    }
    return FALSE;
}


static void CheckTouchChipType(void)
{
    UINT8 i;
    ST_FW_VERSION  fw;

    for(i=0; i<100; i++)
    {
        if(IICReadBytes(0x1000C, (UINT8*)&fw, sizeof(fw)))
        {
          if(GetCheckSum8((UINT8*)&fw,  sizeof(fw)-2)==fw.checksum)
          {
             PRINT("pid1=%s\n", fw.patch_pid);
             if(fw.patch_pid[0] == '9' && fw.patch_pid[1] == '8' && fw.patch_pid[2] == '9' && fw.patch_pid[3] == '7' )
             {
                 ChipType = CHIP_TYPE_BERLINA;
                 break;
             }
          }
        }
        if(IICReadBytes(0x10014, (UINT8*)&fw, sizeof(fw)))
        {
          if(GetCheckSum8((UINT8*)&fw, sizeof(fw)-2)==fw.checksum)
          {
             PRINT("pid2=%s\n", fw.patch_pid);
             if((fw.patch_pid[0]=='2' && fw.patch_pid[1] == '9' && fw.patch_pid[2] == '3' && (fw.patch_pid[3] == '3' || fw.patch_pid[3] == '6'))
              ||(fw.patch_pid[0]=='6' && fw.patch_pid[1] == '8' && fw.patch_pid[2] == '7' )
              )
             {
                ChipType = CHIP_TYPE_BERLINB;
                break;
             }
             else if(fw.patch_pid[0]=='2' && fw.patch_pid[1] == '9' && fw.patch_pid[2] == '3' && fw.patch_pid[3] == '1' )
             {
                 ChipType = CHIP_TYPE_BERLIND;
                 break;
             }
          }
        }
    }
    if(i==10)
    {
        PRINT("Chip type unknown\n");

        if(!IsBerlinChipType(ChipType))
        {
            ChipType = CHIP_TYPE_BERLIND;
        }
    }
}


/*******************************************************************************
* Function Name  : BT_Init
* Description    : 触摸板初始化，获取ID，确认是否工作
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void BT_Init(void)
{
    TouchProc = CheckTouchINT;

    CheckPos = MAX_POINT;

    CheckTouchChipType();

    if(ChipType==CHIP_TYPE_BERLINB || ChipType==CHIP_TYPE_BERLIND)
    {
        ShutdownHIDI2C();
    }

    if (IICTouchTaskId == INVALID_TASK_ID)
    {
      IICTouchTaskId = TMOS_ProcessEventRegister(IICTouch_ProcessEvent);
      tmos_set_event(IICTouchTaskId, HID_DEBUG_EVT);
    }

    tmos_start_task(IICTouchTaskId, CHECK_ESD_EVT, PERIO_2s );
    tmos_start_task(IICTouchTaskId, SYS_INIT_FINISH_EVT, PERIO_40s );

    PRINT("sys init\n");
}


static void BT_Check_ESD()
{

  UINT32 reg_addr = 0x10170;
  if(ChipType==CHIP_TYPE_BERLINA)
  {
      reg_addr = 0x10168;
  }


  if(!enable_ESD_check) return;

  if(IICReadOneByte(reg_addr) == 0xAA)
  {
      PRINT("BT Check ESD Error!\n");
      ResetTouchChip(); //Rstart touch ic
  }
  else
  {
      IICWriteOneByte(reg_addr, 0xAA);
  }
}


static void ClearTouchFlag()
{
  UINT32 reg_addr = 0x10274;

  if(ChipType == CHIP_TYPE_BERLINA)
  {
      reg_addr = 0x10338;
  }
  else  if(ChipType == CHIP_TYPE_BERLIND)
  {
      reg_addr = 0x10308;
  }


  if(!IsDebugMode && !ReleaseFlag)
  {
      IICWriteOneByte(reg_addr, 0);            //清标志
  }
}
void BT_SetTouchEvent()
{

  tmos_set_event(IICTouchTaskId, CHECK_TOUCH_INT_EVT);
}



static UINT16 IICTouch_ProcessEvent( UINT8 task_id, UINT16 events )
{
    //BOOL bSuccess = TRUE;;
    if(events & REPORT_AGAIN_EVT)
    {
      ReportPos();
      events ^= REPORT_AGAIN_EVT;
      goto OUT_FUMC;
    }

    if(events & START_REPORT_POS_EVT)
    {
      //PRINT("SR");
      StartReportPos();
      events ^= START_REPORT_POS_EVT;
      goto OUT_FUMC;
    }

    if(events & READ_ONE_POINT_EVT)
    {
      ReadOnePoint();
      events ^= READ_ONE_POINT_EVT;

      //有中断，取消USB检测
      events &= ~CHECK_USB_STATUS_EVT;
      tmos_stop_task(IICTouchTaskId, CHECK_USB_STATUS_EVT);

      goto OUT_FUMC;
    }

    if(events & CHECK_TOUCH_INT_EVT)
    {
      //PRINT("TI");

      CheckTouchINT();
      events ^= CHECK_TOUCH_INT_EVT;

      if(PointNum == 0 && SysInitFinish) //松键
      {
        tmos_start_task(IICTouchTaskId, CHECK_USB_STATUS_EVT, PERIO_1s ); //1s后开启USB检测
      }

      goto OUT_FUMC;
    }

    if(events & CHECK_ESD_EVT)
    {
      //PRINT("esd check\n");
      BT_Check_ESD();
      events ^= CHECK_ESD_EVT;
      tmos_start_task(IICTouchTaskId, CHECK_ESD_EVT, PERIO_2s );
      goto OUT_FUMC;
    }

    if(events & SYS_INIT_FINISH_EVT)
    {
      SysInitFinish = TRUE;

      events ^= SYS_INIT_FINISH_EVT;
      tmos_start_task(IICTouchTaskId, CHECK_USB_STATUS_EVT, PERIO_1s);
      goto OUT_FUMC;
    }

    if(events & CHECK_USB_STATUS_EVT)
    {

      events ^= CHECK_USB_STATUS_EVT;

      if(CheckUsbStatus())
      {
          tmos_start_task(IICTouchTaskId, CHECK_USB_STATUS_EVT, PERIO_5s );//避免系统重连慢造成反复复位重连
      }
      else {
          tmos_start_task(IICTouchTaskId, CHECK_USB_STATUS_EVT, PERIO_1s );
      }


      goto OUT_FUMC;
    }

    if(events & HID_DEBUG_EVT)
    {
      CommandHandle();
      events ^= HID_DEBUG_EVT;
      tmos_set_event(task_id, HID_DEBUG_EVT);
      goto OUT_FUMC;
    }

    return 0;

OUT_FUMC:

    return  events;
}



static void CheckTouchINT()
{
  //UINT8 PointNum;

  ST_EVENT_HEAD event_head;

  UINT32 reg_addr = 0x10274;

  if(ChipType == CHIP_TYPE_BERLINA)
  {
      reg_addr = 0x10338;
  }
  else  if(ChipType == CHIP_TYPE_BERLIND)
  {
      reg_addr = 0x10308;
  }


  StylusFlag = FALSE;

  IICReadBytes(reg_addr, (UINT8*)&event_head, sizeof(ST_EVENT_HEAD));

  if(event_head.TouchEvent==0 && !ReleaseFlag)
  {
     IICWriteOneByte(reg_addr, 0);                               //清标志,如果延迟较长可以去掉

     return ;
  }

  PointNum = event_head.TouchNum;

  TouchNum = 0;


  if(PointNum > MAX_POINT)   PointNum = MAX_POINT;


#ifdef MOUSE_REPORT
    StylusFlag = FALSE;
#endif
    NoTouchTimer = 0;

    ReadPointCnt = 0;

    OutRangeFlag = 0xFFFF;

    Press_Flag = 0;

    if(PointNum==0)
    {
      tmos_set_event(IICTouchTaskId, START_REPORT_POS_EVT);
    }
    else
    {
      tmos_set_event(IICTouchTaskId, READ_ONE_POINT_EVT);
    }
}

//__attribute__((section(".highcode")))
static void ReadOnePoint()
{
    UINT8 buf[13];
    UINT8 index;
    UINT16 tmp;

    UINT32 reg_addr = 0x10274;

    if(ChipType == CHIP_TYPE_BERLINA)
    {
        reg_addr = 0x10338;
    }
    else  if(ChipType == CHIP_TYPE_BERLIND)
    {
        reg_addr = 0x10308;
    }
    reg_addr += (ReadPointCnt<<3) + sizeof(ST_EVENT_HEAD);

    IICReadBytes(reg_addr, buf, 8);

#ifdef STYLUS_REPORT
    if(buf[0]&0x80)
    {
      BT_RD_Reg(BT_GSTID_REG + (PointNum << 3) ,buf+7,6);     //stylus keY

      StylusPress = ((UINT16)buf[6]<<8)+buf[5] ; //stylus pressure

      StylusFlag = TRUE;

      if((DeviceMode!=DEVICE_MODE_MOUSE) && (BleDeviceMode!=DEVICE_MODE_MOUSE) && (!UartReportPosEn))
      {
        Press_Flag = (((UINT16)buf[12] & 0xFC) << 8) | 0x8000;

        buf[0] =9;//&= 0x7F;
        index = 9;
      }
      else
      {
        if(StylusPress==0)
          goto OUT_FUNC;

        ShareBuf[0] =0;
        index = 0;
      }
    }
    else
#endif
    {//查找和上次相同Press_Flag的索引位置
      for(index=0; index<10; index++)
      {
        if(((Press_Flag_Bak0 & (1L<<index))!= 0) && TP[ index ].Contact_Identifier == (buf[0]>>4))
        {
          break; //
        }
      }

      if(index>=10)//没有找到配对位置，找一个空位
      {
        for(index=0; index<10; index++)
        {
          if(((Press_Flag_Bak0 | Press_Flag ) & (1L<<index)) == 0)
          {
            break; //
          }
        }
      }
    }

    if(index>=10) goto OUT_FUNC; //没有空位

    if((Press_Flag & 0x8000) && buf[0] == 9) //stylus Press_Flag
    {
    #ifdef STYLUS_TILT
      StylusTiltX = ((UINT16)buf[8]<<8)+buf[7] ;
      StylusTiltY = ((UINT16)buf[10]<<8)+buf[9] ;
    #endif
    }
    else
    {
      tmp = ((UINT16)buf[7]<<8)+buf[6];
      if(tmp==0)
      {
        goto OUT_FUNC;
      }
    }


  #ifdef AUTO_ADJUST_SOLUTION
    if(bSolutionValid)
    {
      TP[index].X_pos = (UINT32)(((UINT16)buf[2]<<8)+buf[1] ) * (RESOLUTION_X-1) / wMaxX;
      TP[index].Y_pos = (UINT32)(((UINT16)buf[4]<<8)+buf[3] ) * (RESOLUTION_Y-1) / wMaxY;
    }
    else
  #else
    {
      TP[index].X_pos = ( ((UINT16)buf[3]<<8)+buf[2] );
      TP[index].Y_pos = ( ((UINT16)buf[5]<<8)+buf[4] );
    }
  #endif

    TP[index].X_pos_back = TP[index].X_pos;
    TP[index].Y_pos_back = TP[index].Y_pos;
#ifdef NEW_REVOLVE_PROTOCAL
    if (PosConvert(TP, index) == FALSE)  //超出黑边的坐标返回FALSE，裁剪掉
      goto OUT_FUNC;
#endif
    TP[ index ].Tip_Switch = 1;

    Press_Flag |= ((UINT16)1<<index);

    TP[ index ].Contact_Identifier = buf[0]>>4;


OUT_FUNC:
    ReadPointCnt++;

    if(ReadPointCnt >= PointNum)
    {
      tmos_set_event(IICTouchTaskId, START_REPORT_POS_EVT);

    }
    else
    {
      tmos_set_event(IICTouchTaskId, READ_ONE_POINT_EVT);
    }
}
//__attribute__((section(".highcode")))
void StartReportPos()
{
  TouchNum = 0;
  for(UINT8 i=0; i<MAX_POINT; i++)
  {
    if((Press_Flag & (((UINT16)1)<<i)) == 0)
    {
      TP[i].Tip_Switch = 0;
    }
    else
    {
      TouchNum++;
    }
  }

#ifdef DOUBLECLIK_FILETER
  if(TouchNum <= 1)  //&& (DeviceMode == DEVICE_MODE_MOUSE))
  {
    DoubleClickFilter(StylusFlag, 0);
  }
  else
  {
    DoubleClickTimer = 100;
  }
#endif
  Press_Flag &= OutRangeFlag;
  Press_Flag_Bak0 = Press_Flag;
  Press_Flag |= Press_Flag_Bak1|Press_Flag_Bak2;//|Press_Flag_Bak3;

#ifdef CALL_OSD_MENU
  CallOSDMenu();    //双指在右下角下滑，串口上报命令调用OSD菜单
#endif
#ifdef GESTURE
  if ( DeviceMode == DEVICE_MODE_MOUSE || BleDeviceMode == DEVICE_MODE_MOUSE)
  {
    WheelMove();

    if (TwoPointsClick() == 1)
    {
      bclickFlag = 1;
    }
  }
#endif

  ReportPos();
}


//__attribute__((section(".highcode")))
static void ReportPos()
{
  //static UINT8 nUSBFailedTimes = 0;
  ReportPosSuccess = TRUE;

  if(UsbReportPosEn || BleReportPosEn)
  {
    if(((DeviceMode == DEVICE_MODE_MULTITOUCH) && (config.report_type != EN_MOUSE_ONLY)) || (config.report_type == EN_MULTITOUCH_ONLY))
    {
      Absolute_Up_Pack(TP);
    }
    else if(config.report_type != EN_MULTITOUCH_ONLY)
    {
      ReportMousePos(TP);
    }
  }
#ifdef UART_ENABLE
  else if(UartReportPosEn)
  {
    UartUpdatePos( &TP[0]);
  }
#endif

    ClearTouchFlag();

    Press_Flag_Bak3 = Press_Flag_Bak2;
    Press_Flag_Bak2 = Press_Flag_Bak1;
    Press_Flag_Bak1 = Press_Flag_Bak0;

    tmos_stop_task( IICTouchTaskId, REPORT_AGAIN_EVT );

}

/*********************************************************************
*********************************************************************/
