#include "common_include.h"
#include "s6j3360_LCDB.h"

/*****************************************************************************/
/* Local pre-processor symbols/macros ('#define')                            */
/*****************************************************************************/
//#define     WRITE(r,v) r=v
//#define     READ(r) r

volatile  uint8_t     UP_VSYNC;
volatile  uint32_t    UpScreenTime;
volatile  uint8_t     UpScreenStep;
volatile  uint8_t     LcdBusState;

extern void bsp_HDOG_Feed(void);
/*
#define gImage_111 0x04000000 + (uint32_t)_Bottom_Theme1_Pointer02_X291_Y26_R
const unsigned char _Bottom_Theme1_Pointer02_X291_Y26_R[16] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
};
*/
/*
unsigned char gImage0[] = { //0X22,0X01,
0X0A,0X00,0X10,0X00, 
0X0F,0X03,0XF1,0XF8,0XFC,0XFC,0XFC,0XF1,0X03,0X0F,0XF0,0XC0,0X8F,0X1F,0X3F,0X3F,
0X3F,0X8F,0XC0,0XF0,};

unsigned char gImage_1[] = { // 0X22,0X01,
0X0A,0X00,0X10,0X00, 
0XF9,0XF9,0XF9,0XFC,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X3F,0X3F,0X3F,0X3F,0X00,0X00,
0X3F,0X3F,0X3F,0X3F,};

*/

#define     WPREG_PPC(n,d)                          \
{                                                   \
    un_ppc_keycdr_t wk;                             \
    unsigned long adr = (unsigned long)&n;          \
    unsigned char size_key;                         \
    wk.au16Halfword[0] = adr & 0x7FFF;              \
    size_key = (sizeof(n) >> 1) << 4;               \
    wk.au8Byte[3] = size_key | (0 << 6);            \
    PPC_KEYCDR = wk.u32Register;                    \
    wk.au8Byte[3] = size_key | (1 << 6);            \
    PPC_KEYCDR = wk.u32Register;                    \
    wk.au8Byte[3] = size_key | (2 << 6);            \
    PPC_KEYCDR = wk.u32Register;                    \
    wk.au8Byte[3] = size_key | (3 << 6);            \
    PPC_KEYCDR = wk.u32Register;                    \
    n = d;                                          \
}

/*-------------------------------------------------------------------------
* Function Name  : VsyncDetectCallback
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
*
--------------------------------------------------------------------------*/
static void VsyncDetectCallBack(uint8_t channel)
{
    uint8_t   sw = 0;

    if((UpScreenStep) && (UpScreenTime > 1000))
    {
        LCDPanelUpdtCtrl.Request = 0;
        UpScreenStep = 0;
        UP_VSYNC = 0;
        LcdBusState = 1;
    }
    else
    {
        sw = (memoryVramSel + 1) % 2;
        if((g_DrawInfo.VramCalOverFlag[ sw ]) && (UP_VSYNC == 0))
        {         
             LCDPanelGraphicRAM = (uint32_t*)VRAM_BUF[ sw ];
             memoryVramSel = sw;
             UP_VSYNC = 1;
             LCD_Panel_Update_Req(96,128);
             UpScreenStep = 1;
             UpScreenTime = 0;
        }
    }
}

/*-------------------------------------------------------------------------
* Function Name  : LcdBus_Check
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
*
--------------------------------------------------------------------------*/
void LcdBus_Check(void)
{
    if(LcdBusState)
    {
         LCD_BUS_Init();
    }
}

/*-------------------------------------------------------------------------
* Function Name  : LcdBus_InstrFifo_isr
* Description    :
* Input          : None
* Output         : None
* Return         : None
* onther         :
*
--------------------------------------------------------------------------*/
__irq __arm  void LcdBus_InstrFifo_isr(void)
{
    if((UpScreenStep) && (LcdBusState == 0))
    {
         LCD_Panel_Update_ISR(UpScreenStep);
    }
        
    LCDB_InterruptClear = 0x04;
    IRC0_IRQHC = INTERRUPTS_IRQ_NUMBER_86;
}

/*-------------------------------------------------------------------------
* Function Name  : VsyncDetectionInit
* Description    : ��ʼ���ⲿ�ж� Ϊ��VSYNCͬ��
* Input          :
* Output         : None
* Return         : None
* onther         : WindowY:page Number
--------------------------------------------------------------------------*/
void VsyncDetectionInit(void)
{
    stc_port_pin_config_t stc_port_pin_config0_12= { .enOutputFunction      = PortOutputResourceGPIO,
        .enOutputDrive         = PortOutputDriveA,
        .enPullResistor        = PortPullResistorNone,
        .enInputLevel          = PortInputLevelCmosA,
        .bInputEnable          = TRUE,
        .bNoiseFilterEnable    = FALSE,
        .enGpioDirection       = PortGpioInput,
    .enGpioInitOutputLevel = PortGpioLow};
    Port_SetPinConfig( 0, 12, &stc_port_pin_config0_12 );
    
    stc_eic_config_t      stcEicConfig;
    // EIC Configuration
    stcEicConfig.enRequestEvent               = EicFallingEdge;          // Detect rising edge
    stcEicConfig.bInputNoiseFilterEnable      = TRUE;                   // Enable the noise filter
    stcEicConfig.bDmaRequestEnable            = FALSE;                  // Disable the DMA request
    stcEicConfig.pfnCallback                  = &VsyncDetectCallBack;   // using interrupts
    
    Port_SelectInputPort( &RIC.unRESIN274, PortInputPortC );
    
    Eic_Init((stc_eic00_t *) &EIC00, 23, &stcEicConfig);
    
    Eic_Enable((stc_eic00_t *) &EIC00, 23);
    
    Port_EnableInput();
}

void LCD_BUS_Init(void)
{
    un_lcdb_interfaceconfig_t                     interfaceCofigTemp      = { 0 };
    un_lcdb_writetimingconfig_t                   writeTimingCofigTemp    = { 0 };
    un_lcdb_readtimingconfig_t                    readTimingCofigTemp     = { 0 };
    un_lcdb_commandtransfermapping0_t             cmdTransMap0CofigTemp   = { 0 };
    un_lcdb_datatransfermapping0_t                dataTransMap0CofigTemp  = { 0 };
    un_lcdb_datatransfermapping1_t                dataTransMap1CofigTemp  = { 0 };
    un_lcdb_colorcomponentbits_t                  colorComponentBitsTemp  = { 0 };
    un_lcdb_colorcomponentshift_t                 colorComponentShiftTemp = { 0 };
    un_lcdb_destinationattributes_t               destAttributesTemp      = { 0 };
    un_lcdb_instructionfifoconfig_t               instructionfifoconfigTemp = { 0 };
    un_lcdb_interruptenable_t                     interruptenableTemp = { 0 };
    
    LcdBusState = 0;
    memoryVramSel = 0;
    
    //�˿�����
    WPREG_PPC(PPC_PCFGR215, 0x1002);  // LCDD0  pin127
    WPREG_PPC(PPC_PCFGR216, 0x1002);  // LCDD1  pin128
    WPREG_PPC(PPC_PCFGR217, 0x1002);  // LCDD2  pin129
    WPREG_PPC(PPC_PCFGR218, 0x1002);  // LCDD3  pin130
    WPREG_PPC(PPC_PCFGR222, 0x1002);  // LCDD4  pin136
    WPREG_PPC(PPC_PCFGR223, 0x1002);  // LCDD5  pin137
    WPREG_PPC(PPC_PCFGR224, 0x1002);  // LCDD6  pin138
    WPREG_PPC(PPC_PCFGR225, 0x1002);  // LCDD7  pin139
    
    WPREG_PPC(PPC_PCFGR006, 0x1002);  // CS#    pin008
    WPREG_PPC(PPC_PCFGR007, 0x1002);  // WR#    pin011
    WPREG_PPC(PPC_PCFGR008, 0x1002);  // RD#    pin012
    WPREG_PPC(PPC_PCFGR010, 0x1002);  // RS     pin014
    WPREG_PPC(PPC_PCFGR011, 0x1002);  // RES#   pin015
    VsyncDetectionInit();//WPREG_PPC(PPC_PCFGR012, 0x1002);  // TE     pin016
    
    
    //��������
    //Interface Config
    LCDB_LockUnlockLcd = 0x691DB936;
    interfaceCofigTemp.stcField.u2InterfaceType       = 0;      // 0: INTEL80_TYPE1
    interfaceCofigTemp.stcField.u2InterfaceWidth      = 0;      // 0: 8bit LCDBus
    interfaceCofigTemp.stcField.u1CsPolarity          = 0;      // CS is low active
    interfaceCofigTemp.stcField.u1WrPolarity          = 0;      // WR# is default protocol
    interfaceCofigTemp.stcField.u1RdPolarity          = 0;      // RD# is default protocol
    interfaceCofigTemp.stcField.u1RsPolarity          = 0;      // RS is low signal level
    interfaceCofigTemp.stcField.u1DataPolarity        = 0;      // Data bus is used
    interfaceCofigTemp.stcField.u1TePolarity          = 0;      // TE is high active
    LCDB_InterfaceConfig = interfaceCofigTemp.u32Register;
    
    //Write Timing Config
    LCDB_LockUnlockLcd = 0x691DB936;
    writeTimingCofigTemp.u32Register                  = LCDB_WriteTimingConfig;
    writeTimingCofigTemp.stcField.u8WriteSetupCycles  = 1;
    writeTimingCofigTemp.stcField.u8WriteActiveCycles = 3;
    writeTimingCofigTemp.stcField.u8WriteHoldCycles   = 1;
    LCDB_WriteTimingConfig = writeTimingCofigTemp.u32Register;
    
    //Read Timing Config (addr: 0x0014)
    LCDB_LockUnlockLcd = 0x691DB936;
    readTimingCofigTemp.u32Register                   = LCDB_ReadTimingConfig;
    readTimingCofigTemp.stcField.u8ReadSetupCycles    = 2;
    readTimingCofigTemp.stcField.u8ReadActiveCycles   = 5;
    readTimingCofigTemp.stcField.u8ReadHoldCycles     = 2;
    LCDB_ReadTimingConfig = readTimingCofigTemp.u32Register;
    
    //Command Transfer Mapping 0
    LCDB_LockUnlockLcd = 0x691DB936;
    cmdTransMap0CofigTemp.stcField.u5CommandTransfer0Bits   = 8;    // sbits
    cmdTransMap0CofigTemp.stcField.u5CommandTransfer0SrcLsb = 0;    // slsb
    cmdTransMap0CofigTemp.stcField.u5CommandTransfer0DstLsb = 0;    // dlsb
    cmdTransMap0CofigTemp.stcField.u1CommandTransfer0Next   = 0;    // next
    LCDB_CommandTransferMapping0 = cmdTransMap0CofigTemp.u32Register;
    
    //Data Transfer Mapping 0
    LCDB_LockUnlockLcd = 0x691DB936;
    dataTransMap0CofigTemp.stcField.u5DataTransfer0Bits   = 8;      // sbits
    dataTransMap0CofigTemp.stcField.u5DataTransfer0SrcLsb = 0;      // slsb
    dataTransMap0CofigTemp.stcField.u5DataTransfer0DstLsb = 0;      // dlsb
    dataTransMap0CofigTemp.stcField.u1DataTransfer0Next   = 0;      // next
    LCDB_DataTransferMapping0 = dataTransMap0CofigTemp.u32Register;
    
    //ColorComponentBits
    LCDB_LockUnlockLcd = 0x691DB936;
    colorComponentBitsTemp.stcField.u4ComponentBitsBlue  = 0;
    colorComponentBitsTemp.stcField.u4ComponentBitsGreen = 4;
    colorComponentBitsTemp.stcField.u4ComponentBitsRed   = 0;
    LCDB_ColorComponentBits = colorComponentBitsTemp.u32Register;
    
    //ColorComponentShift
    LCDB_LockUnlockLcd = 0x691DB936;
    colorComponentShiftTemp.stcField.u5ComponentShiftBlue  = 0;
    colorComponentShiftTemp.stcField.u5ComponentShiftGreen = 0;
    colorComponentShiftTemp.stcField.u5ComponentShiftRed   = 0;
    LCDB_ColorComponentShift = colorComponentShiftTemp.u32Register;
    
    //DestinationAttributes
    LCDB_LockUnlockLcd = 0x691DB936;
    destAttributesTemp.stcField.u5BitsPerTransfer = 8;
    destAttributesTemp.stcField.u5BitsPerPixel    = 4;
    LCDB_DestinationAttributes = destAttributesTemp.u32Register;
    
    //reset and clear the content of command fifo
    LCDB_LockUnlockLcd = 0x691DB936;
    LCDB_SoftwareReset = 1;
    
    //clear the content of rxfifo
    LCDB_LockUnlockLcd = 0x691DB936;
    LCDB_RxFifoControl = 1;
    
#if 1
    LCDB_LockUnlockLcd = 0x691DB936;
    instructionfifoconfigTemp.stcField.u6InstrThresholdLow = 0;     //������ 0
    instructionfifoconfigTemp.stcField.u6InstrThresholdHigh = 1;
    instructionfifoconfigTemp.stcField.u2InstrThresholdTrigger = 0;  //0 = LOW
    LCDB_InstructionFifoConfig = instructionfifoconfigTemp.u32Register;

    LCDB_LockUnlockLcd = 0x691DB936;
    interruptenableTemp.stcField.u1InstrFifoInterruptEnable = 1;
    LCDB_InterruptEnable = interruptenableTemp.u32Register;
#endif
}



void LCD_BUS_Panel_Reset_Ctrl(uint8_t Level)
{
    uint16_t cnt = 0;
    while (LCD_BUS_Get_Status())
    {
        cnt ++;
        if(cnt > 60000)
        {
            break;
        }
    }
    
    if(Level)
    {
        LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_SET_RESET, 1);
    }
    else
    {
        LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_SET_RESET, 0);
    }
    LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_NOP, 16);
}


void LCD_BUS_Write_Cmd(uint8_t Cmd, uint8_t *pPara, uint8_t ParaLen)
{
    uint16_t i = 0;
    
    if ((ParaLen) && (pPara == NULL))
        return;
    
    while (LCD_BUS_Get_Status())
    {
        i ++;
        if(i > 800)
        {
            break;
        }
    }

    LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_IR_SET, Cmd);
    
    if(ParaLen)
    {   
        for(i = 0; i < ParaLen; i++)
        {
            LCD_BUS_Write_Bus_Cmd(LCD_BUS_CMD_DR_SET, pPara[ i ]);
        }
    }
}

uint8_t LCD_BUS_Get_Status(void)
{
    if ((LCDB_InstrFifoStatus_InstrEmpty == 0) && (LCDB_SequencerStatus_LcdInterfaceState == 0))
        return 1;
    
    return 0;
}

void LCD_BUS_Write_Bus_Cmd(uint32_t Opcode, uint8_t Para)
{
    if(LCDB_InstrFifoStatus_InstrFull)
    {
        NOP();NOP();NOP();NOP();NOP();
    }
    if (LCDB_InstrFifoStatus_InstrFull == 0)
    {
        LCDB_InstructionFifo0 = (Opcode + Para);
    }
}

void LCD_BUS_Write_Bus_Fifo(uint32_t Data)
{
    if(LCDB_InstrFifoStatus_InstrFull)
    {
        NOP();NOP();NOP();NOP();NOP();
    }
    if (LCDB_InstrFifoStatus_InstrFull == 0)
    {
        LCDB_InstructionFifo0 = Data;
    }
}

void UpdateScanDsp(void)
{
		if((Flag_BarcodeErr == 1) && (Flag_SetTime == 1))
		{
			//ɨ�����������ɨ�룬����ɨ��N�Ρ�
			UpdateSetQRcodeErr();
		}
		else if(Flag_SetTime == 1)
		{
			//��ɨ���ά�����ü��̨������ɨ��N�Ρ�
			UpdateSetQRcode();
		}
		else if (CheckClusterValid == 0) 
		{
			UpdateConnectCluster();
		}
		else if(SetClusterState == 0)
		{
			//ɨ��ɹ����������DZ�
			UpdateConfigingClu();
		}
		else if(SetClusterState == 1)
		{
			//�������
			UpdateConfigComplete();
		}
		else if(SetClusterState == 2)
		{
			//ɨ��ʧ��������ɨ���˶Զ�ά��
			UpdateConfigErr();
		}
		else if(SetClusterState == 3)
		{
			//��ɨ���ά��
			UpdatePleaseScan();
		}
		else if(SetClusterState == 4)
		{
			//����
			UpdateConfigFail();
		}
}
uint8_t g_uiUpdateStep = 0;
uint16_t g_uiFastFlushTimer = 0;
extern uint16_t g_uiDL3CDelayTimer;
void UpdataCenterDisp(uint8_t n)
{
  uint8_t uiProTye = 1;
  
  if ((g_DrawInfo.VramCalOverFlag[ 0 ] == 0) || (g_DrawInfo.VramCalOverFlag[ 1 ] == 0))
  {
    if(g_DrawInfo.VramCalOverFlag[ 0 ] == 0)
    {
      g_DrawInfo.VramSelectBuf = 0;
    }
    if(g_DrawInfo.VramCalOverFlag[ 1 ] == 0)
    {
      g_DrawInfo.VramSelectBuf = 1;
    }
    if(g_DrawInfo.VramSelectBuf > 1)
    {
      g_DrawInfo.VramSelectBuf = 0;
    }
    if (g_Stage == 0) {
      if (g_uiFastFlushTimer > 0) {
          Api_ClearAllVram(g_DrawInfo.VramSelectBuf,0xffffffff);  
      } 
      else {
          if (g_uiFunctionListDspFlag == 0) {
            Api_ClearAllVram(g_DrawInfo.VramSelectBuf,0xffffffff);
          }
      }
    }
    else {
      Api_ClearAllVram(g_DrawInfo.VramSelectBuf,0xffffffff);
    }
    
    if(Flag_DisplayErr == 1)
    {
      UpdateErrNum();
    }
    else if (uiProTye == 0) {
      
    }      
    else {
      switch(g_uiUpdateStep) {
      case 0:
        if(CheckClusterValid == 0) {
          GetPartNumSent = 0;
          GetPartNumFinish = 0;
          ClusterValidTimerCnts = CLUSTER_CHECK_TIME;
          g_uiUpdateStep = 4;
        }
        g_uiDL3CDelayTimer = 800;
        break;
      case 1:
        if (Flag_SetTime == 1) {
#if (PRO_CONFIG_SCAN_APPLY)        
          UpdateScanDsp();
#endif   
        } else {
          if(BlinkDspTimer % 2 == 0) 
          {
            UpdateConnectCluster();
            g_Stage = 0;
#if SEMI_AUTOMATIC_STAGE
          g_uiSemiAutomaticStage = 0;
#endif            
            CANSendEnable = OFF; //�ر��������ķ���
          }
#if (PRO_DL3C)
          if (g_uiDL3CDelayTimer <= 0)
#endif
          GetPartNum();
          if (GetPartNumSent == 3) {
            g_VehicleType = GetVehicleType(CluPartNum);
          }
#if ((PRO_DL3C) || (PRO_KU))
          if (GetPartNumSent >= 3) {   //��Ʒ��
            g_uiUpdateStep = 2;
          } 
#elif (PRO_US4)
        if (g_VehicleType == CAR_TYPE_ICV){
              if (GetPartNumSent >= 3) {   //��Ʒ��
                g_uiUpdateStep = 2;
              } 
        } else if (g_VehicleType == CAR_TYPE_HEV){
              if (GetPartNumSent >= 4) {   //��Ʒ��
               g_uiUpdateStep = 2;
              } 
        }
#else 
          if (GetPartNumSent >= 4) {   //��Ʒ��
            g_uiUpdateStep = 2;
          } 
#endif
          else {
            if(ClusterValidTimerCnts == 0) {
              g_uiUpdateStep = 0;
            }
          }
        }
        
        break;
      case 2:
        if (CheckPartNumber(CluPartNum) == 1u) { 
#if (NOBARCODE_CHECK) 
          CheckBarcode = 0;
#else
          CheckBarcode = 1;
#endif
          CANSendEnable = ON; 
          g_uiUpdateStep = 3;
          //g_VehicleType = GetVehicleType(CluPartNum);
          memset(g_szCheckBenchName,0,sizeof(g_szCheckBenchName));
          strncpy(g_szCheckBenchName,GetProjectName(CluPartNum),strlen(GetProjectName(CluPartNum)) > (sizeof(g_szCheckBenchName) - 1) ? (sizeof(g_szCheckBenchName) - 1):strlen(GetProjectName(CluPartNum)));
        } else  {
          g_uiUpdateStep = 4;
        }
        break;
      case 3:
#if (PRO_CONFIG_EOL_APPLY)        
        UpdateCenterEol();
#endif                    
#if (PRO_CONFIG_SCAN_APPLY)    
        UpdateTitle();
        UpdateScanDsp();
#endif                      
#if (PRO_CONFIG_CHECK_APPLY)
        if(CheckBarcode == 1) {
          if (g_uiQueryState == ST_INIT) {
              UpdateBarcode();//��ʾɨ��ά��
              g_uiFastFlushTimer = 500;
          } else if (g_uiQueryState == ST_QUERY) {
              UpdateCenterInfo(g_uiQueryState);//�DZ�����׷�ݲ�ѯ
          }  else if (g_uiQueryState == ST_FAIL) {
              UpdateCenterInfo(g_uiQueryState);//�DZ�����׷��ʧ��
          } else if (g_uiQueryState == ST_NCK) {
              UpdateCenterInfo(g_uiQueryState);//�DZ�����׷��CAN ��ͨ���쳣
          } else if (g_uiQueryState == ST_SUCC) {
              CheckBarcode = 0;//�DZ�����׷�ݳɹ�
              Api_ClearAllVram(g_DrawInfo.VramSelectBuf,0xffffffff);    
          }
          g_Stage = 0;
#if SEMI_AUTOMATIC_STAGE
          g_uiSemiAutomaticStage = 0;
#endif
          CANSendEnable = OFF; //�ر��������ķ���
        } 
        else {
          if (g_uiFastFlushTimer == 0)
            UpdateCenterTripC();//������ʾ�����б�
        }
#endif                     
        break;
      case 4:
        CheckClusterValid = 1;
        ClusterValidTimerCnts = 1000;
        UpdateCenterTripC();
        break;
      }
    }
  }
  else {
    //if(CheckClusterValid == 0) {
    //     LcdError();
    //}
  }
  
  g_DrawInfo.VramCalOverFlag[ g_DrawInfo.VramSelectBuf ] = 1;
}