/********************************** (C) COPYRIGHT *******************************
* File Name          : MS928x_mpi.c
* Author             : Wingcool
* Version            : V1.0
* Date               : 2023/2/22
* Description        : ms928x SDK升级操作
*******************************************************************************/

/******************************************************************************/
/* 头文件包含 */
#include "include.h"
//#include <GoodixTouch.h>
#include "CONFIG.h"
//#include "CH57x_common.h"
#include "TouchCommon.h"
//#include "HAL.h"
//#include "hiddev.h"
//#include "hidtouch.h"
#include "iic.h"
//#include "DEBUG.H"
#include "HidReport.h"
//#include "usb_driver.H"
//#include "I2CTouchService.h"
//#include "Flash.h"
//#include "hidReportDesc.h"
//#include "central.h"
//#include "RF_PHY.h"
//#include "Flash.h"
#include "tmos.h"

#include "commlib.h"
#include "MS928x.h"
#include "MS928x_mpi.h"
#include "mst_typedef.h"
/*********************************************************************
 * GLOBAL TYPEDEFS
 */
#define MS_SERVICE                          0x0001
#define HID_DEBUG_EVT                       0x0200

#define PERIO_100ms 160
#define PERIO_1s    1600

/*********************************************************************/
UINT8 byIicDelay = 0;  //default 400KHz
static UINT8 MS928xTaskId = INVALID_TASK_ID;
BOOL bPressKeyFlag = 0;  //press reset key or not
UINT16 wHPixelShift,wVPixelShift;  //

static UINT16 MS928x_ProcessEvent( UINT8 task_id, UINT16 events );

void Delay_ms(UINT8 u8ms)
{
  delay_ms(u8ms);
}

void Delay_us(UINT8 u8us)
{
  delay_us(u8us);
}

void I2C_Sel_Speed(UINT8 u8speed)
{
  switch (u8speed)
  {
    case I2C_SPEED_20K:
      byIicDelay = 20;  //20K
      break;
    case I2C_SPEED_100K:
      byIicDelay = 0;  //100K
      break;
    case I2C_SPEED_400K:
      byIicDelay = 0;  //400K
      break;
    case I2C_SPEED_750K:
      byIicDelay = 0;  //400K
      break;
    case 100:
      byIicDelay = 0;  //100K
      break;
    case 20:
      byIicDelay = 20;  //20K
      break;
    default:
      byIicDelay = 0;  //400K
      break;
  }

  //byIicDelay = 20;  //20K
}

UINT8 I2C16_ReadByte(UINT8 u8addr, UINT16 u16index)
{
  GT_CMD_WR = u8addr;
  GT_CMD_RD = u8addr + 1;

  u16index = ((u16index & 0xff00) >> 8) + ((u16index & 0x00ff) << 8);

  return IICReadOneByte(u16index);
}

void I2C16_WriteByte(UINT8 u8addr, UINT16 u16index, UINT8 u8value)
{
  GT_CMD_WR = u8addr;
  GT_CMD_RD = u8addr + 1;

  u16index = ((u16index & 0xff00) >> 8) + ((u16index & 0x00ff) << 8);

  IICWriteOneByte(u16index, u8value);
}

BOOL I2C_ReadBytes(UINT8 u8addr, UINT8 u8index, UINT8 *pIn, UINT8 u8len)
{
  GT_CMD_WR = u8addr;
  GT_CMD_RD = u8addr + 1;

  UINT16 u16index = (UINT16)u8index * 256;

  return IICReadBytes(u16index, pIn, u8len);

}

//UINT8  I2C_ReadByte(UINT8 u8addr, UINT8 u8index)
//{
//
//}
//
//void I2C_WriteByte(UINT8 u8addr, UINT8 u8index, UINT8 u8value)
//{
//
//}

void Sys_Reset(void)
{

    gpio_init_typedef gpio_init_structure;

    gpio_init_structure.gpio_dir = GPIO_DIR_OUTPUT;
    gpio_init_structure.gpio_fen = GPIO_FEN_GPIO;
    gpio_init_structure.gpio_fdir = GPIO_FDIR_SELF;
    gpio_init_structure.gpio_mode = GPIO_MODE_DIGITAL;
    gpio_init_structure.gpio_pupd = GPIO_PUPD_PU10K;
    gpio_init_structure.gpio_drv = GPIO_DRV_6MA;

    gpio_init_structure.gpio_pin = RST_PIN;
    gpio_init(GPIOA_REG, &gpio_init_structure);
    gpio_reset_bits(GPIOA_REG, RST_PIN);

    delay_us(200);
    gpio_init_structure.gpio_dir = GPIO_DIR_INPUT;
    gpio_init(GPIOA_REG, &gpio_init_structure);
    gpio_set_bits(GPIOA_REG, RST_PIN);
}

void MS928X_MPI_Init(BOOL bpresskeyflag)
{
  UINT8 u8status;
  SYSPARAM_T stParam;

  tmos_stop_task(MS928xTaskId, MS_SERVICE);

  Sys_Reset();

  memset(&stParam, 0, sizeof(SYSPARAM_T));

  stParam.u8chipAddr = MS928X_I2C_ADDR_92;  //MS928X IIC address, SASEL Pin -> GND, select 0x9A

  stParam.u16sysConfig = SYS_CFG_SIG_CHANNEL_1;// | SYS_CFG_SIG_SYNC_SOG_1;// | SYS_CFG_ADDPLL_HIGH_REFCLK;  // 配置根据系统板来选择信号输入通道

  stParam.videoParam.u8sourceIn = IN_ANALOG_VGA;  // 当前输入信号选择 VGA input

  // 调用初始化函数
  u8status = MS928X_Init(&stParam);

  //PRINT("MS928X init status:0x%x\n", u8status);

  if (bpresskeyflag)  //press key
  {
    bPressKeyFlag = 1;
  }

  tmos_start_task(MS928xTaskId, MS_SERVICE, PERIO_100ms);
}

void MS928XInit()
{
  UINT8 u8hvpixeldata[4];

  if (bTransmitEn == TRUE)  //transmit
  {
    return;
  }

  GT_CMD_WR = MS928X_I2C_ADDR_92;
  GT_CMD_RD = MS928X_I2C_ADDR_92 + 1;

  if (GetHVPixel(u8hvpixeldata))
  {
    //PRINT("Get HV Pixel Success\n");
    wHPixelShift = (UINT16)(((UINT16)u8hvpixeldata[0] << 8) + u8hvpixeldata[1]);
    wVPixelShift = (UINT16)(((UINT16)u8hvpixeldata[2] << 8) + u8hvpixeldata[3]);
  }
  else  //没有存储，给一个默认的
  {
    //PRINT("No HV Pixel Data\n");
    wHPixelShift = 1593;
    wVPixelShift = 1;
  }

  //PRINT("wHPixelShift:%05d, wVPixelShift:%05d\n", wHPixelShift, wVPixelShift);

  MS928xTaskId = TMOS_ProcessEventRegister(MS928x_ProcessEvent);

//  if (MS928xTaskId == INVALID_TASK_ID)
//  {
//    MS928xTaskId = TMOS_ProcessEventRegister(MS928x_ProcessEvent);
//    tmos_set_event(MS928xTaskId, HID_DEBUG_EVT);
//  }

  tmos_set_event(MS928xTaskId, HID_DEBUG_EVT);

  MS928X_MPI_Init(0);

}

void MS928XService()
{
  VIDEOSHIFT_T sysVideoShift;
  UINT8 u8status;
  //UINT8 u8vic = 0;
  UINT8 u8hvpixeldatabuf[4];

  u8status = MS928X_Poll(); // 返回当前系统运行状态
  //PRINT("MS928X Poll status:%d\n", u8status);

  if (u8status == STATE_SUCCESS)
  {
    //WDT_DIS();
    //PRINT("Disable watch dog\n");

    //u8vic = MS928X_GetInputVideoMode();
    //PRINT("MS928X vic:%03d\n", u8vic);

    //MS928X_SetVideo();  // 设置 Video
    MS928X_SetVideo(&sysVideoShift);  // 设置 Video
    //MS928X_SetAudio(); // 设置 Audio

    //if (u8vic == 4)
    {
      if (bPressKeyFlag == 1)  //press key
      {
        bPressKeyFlag = 0;

        u8hvpixeldatabuf[0] = sysVideoShift.u16HShift >> 8;
        u8hvpixeldatabuf[1] = sysVideoShift.u16HShift & 0xFF;
        u8hvpixeldatabuf[2] = sysVideoShift.u16VShift >> 8;
        u8hvpixeldatabuf[3] = sysVideoShift.u16VShift & 0xFF;

        wHPixelShift = sysVideoShift.u16HShift;
        wVPixelShift = sysVideoShift.u16VShift;

        if (StoreHVPixel(u8hvpixeldatabuf))
        {
          //PRINT("Store HV Pixel Success\n");
        }
      }
      else
      {
        sysVideoShift.u16HShift = wHPixelShift;
        sysVideoShift.u16VShift = wVPixelShift;
      }
      //MS928X_WriteShift(1593,1);
      //MS928X_WriteShift(sysVideoShift.u16HShift,sysVideoShift.u16VShift);
      //MS928X_Video_SetShift(1593,1);
      MS928X_Video_SetShift(sysVideoShift.u16HShift, sysVideoShift.u16VShift);
      //PRINT("u16HShift:%05d, u16VShift:%05d\n", sysVideoShift.u16HShift, sysVideoShift.u16VShift);
    }
  }
  else {
    //WDT_EN();
    //WDT_CLR();
  }

  //PRINT("MS928X Poll status:0x%x\n", u8status);
  //PRINT("u16HShift:%05d, u16VShift:%05d\n", sysVideoShift.u16HShift, sysVideoShift.u16VShift);
}

bool GetHVPixel(UINT8* HVPixelData)
{
  UINT8 buf[10];

  bsp_param_read(buf, HV_PIXEL_ADDR, HV_PIXEL_LEN);  //从flash读出来,len = 4 + 4

  if(buf[0] == 0xAA && buf[1] == 0x55 && buf[2] == 0xAA && buf[3] == 0x55)  //if flag is right
  {
    memcpy(HVPixelData, &buf[4], 4);  //return 4 bytes HV Pixel
    return TRUE;
  }
  memset(HVPixelData, 0, 4);  //if flag is wrong, clear HV Pixel
  return FALSE;
}

bool StoreHVPixel(UINT8* HVPixelData)
{
  u8 buf[8];

  buf[0] = 0xAA;
  buf[1] = 0x55;
  buf[2] = 0xAA;
  buf[3] = 0x55;

  //DataFlash_BlockErase(HV_PIXEL_ADDR);  //erase a block

  //DataFlash_WriteDW(HV_PIXEL_ADDR, 0xAA55AA55);   //write 0xAA55AA55

  memcpy(&buf[4], HVPixelData, 4);  //copy 4 bytes HV Pixel to buf

  //DataFlash_Write((PUINT8)HV_PIXEL_ADDR + 4, (PUINT8)buf, HV_PIXEL_LEN);  //接着第4位开始写HV Pixel，len = 4

  bsp_param_write(buf, HV_PIXEL_ADDR, HV_PIXEL_LEN);

  bsp_param_sync();

  return GetHVPixel(HVPixelData);  //judge and return HV Pixel
}

static UINT16 MS928x_ProcessEvent( UINT8 task_id, UINT16 events )
{
    if(events & MS_SERVICE)
    {
      MS928XService();
      events ^= MS_SERVICE;

      tmos_start_task(MS928xTaskId, MS_SERVICE, PERIO_100ms );

      goto OUT_FUMC;
    }

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

    return 0;

OUT_FUMC:

    return  events;
}

/******************************** endfile @ MS928x_mpi ******************************/
