#include "appTask.h"
#include "iodefine.h"
#include "extern.h"
#include "r_cg_adc.h"
#include "r_cg_intc.h"
#include "PINdef.h"
#include "hwCtrl.h"

#include "pfdl.h"

u8 can_data_init_flag = 0;

unsigned long Can_1ms_count_alive;



unsigned char IGN_Voltage_error_flag, IGN_Voltage_error_count;


volatile uint8_t flag_IIC_SendEnd;
volatile uint8_t flag_IIC_ReceiveEnd;

unsigned char Timer_1ms_flag;
unsigned char Timer_5ms_flag;
unsigned char Timer_10ms_flag;
unsigned char Timer_20ms_flag;
unsigned char Timer_50ms_flag;
unsigned char Timer_1000ms_flag;

unsigned int CAN_LostCount;
unsigned char key_count, key_last;
unsigned char IGN_Lost, IGN_Lost_Count;
unsigned char IGN_On, IGN_On_Count;
/********************* Network Manage ****************************/
unsigned char ucIgnStus;
unsigned int uiBusOffCnt;        // ms
unsigned char ucBusOffModeState; // 0:Normal  1~4:Fast Rec 5:Slow Rec
unsigned char BusoffFlag;
/***************************************************/
static unsigned int EEL_SAVE_CNT_DOWN_TIMER;
static uint8_t EEL_SAVE_ENABLE;

MotorStateEE_Type MotorStateEE;
MotorStateEE_Type *pEE;


uint16_t VehicleSpeedRaw,VehicleSpeed;

uint8_t lockstate,sbrstate,sbrWarnState;
uint8_t nouse;//Relocation value is odd number




void Apply_task(void)
{

    // DiagnosticSession_Present=MngDcm_GetDiagnosticSession(); 
    App28sTxRxStatus = GetNormalMsgSts();
    Nw28sTxRxStatus = GetNetworkMsgSts();

    // DiagnosticSession_Present=MngDcm_GetDiagnosticSession();
    if(CAN_STB == 0 && BusOff_flag == 0)//Tx enable
    {
        TxServe();
    }
    if (Timer_1ms_flag == 1)
    {
        Timer_1ms_flag = 0;
        MngDcm_MainFunction();
        MngCanTp_MainFunction();
        if (BusOff_Detect_delay_count == 0 /*&& (ad_voltage_fact[2]>=85 && ad_voltage_fact[2]<=165)*/)
        {
            BusOff_Detect();
        }
        KeyScan();
        XN_Scan();
        if (EEL_SAVE_CNT_DOWN_TIMER > 0)
        {
            EEL_SAVE_CNT_DOWN_TIMER--;
        }
        Can_Msg_Change();
        //IGN_Detect();
        //CanNwHandle();
    }
    if (Timer_5ms_flag == 1)
    {
        Timer_5ms_flag = 0;
        CAN_RX_Data_Handle();
        /*
        if (IGN_On == 1 && ucActiveWakeupBit != PASSIVE_WAKEUP)
            KeyScan();
        */
        
        KeyPro();
        // IGN_Detect();
        
    }

    if (Timer_10ms_flag == 1)
    {
        Timer_10ms_flag = 0;
        XN_Pro();
        
        // BAT_Voltage_Detect();
        // CanNwHandle();
    }
    if (Timer_20ms_flag == 1)
    {
        Timer_20ms_flag = 0;
        IGN_Voltage_Detect();

    }
    if (Timer_50ms_flag == 1)
    {
        Timer_50ms_flag = 0;
        //EEL_WRITE();
        //TxTestMsg();
        //SleepDetect();//TODO
    }
}

uint8_t xn_counter,xn_tx_num;
uint8_t keyPressState = 0,keyLongPressState=0;
uint8_t btn_req,toggle_req,rotation_req;
uint8_t xn_state;
#define XN_STATE_INIT       0
#define XN_STATE_IDLE       1
#define XN_STATE_MIDDLE     2
#define XN_STATE_MIDDLE_2   3
#define XN_STATE_STOP       4
void XN_StateMachine(void)
{
    static uint8_t xn_dir;
    switch (xn_state)
    {
    case XN_STATE_INIT:
        if (GetIOState(KEYID_XNM) == 1 && GetIOState(KEYID_XNP) == 1)
        {
            xn_state = XN_STATE_IDLE;
            xn_dir = 0;
        }
        break;
    case XN_STATE_IDLE:
        if (GetIOState(KEYID_XNM) == 1 && GetIOState(KEYID_XNP) == 0)
        {
            xn_dir = 1;
            xn_state = XN_STATE_MIDDLE;
        }
        else if (GetIOState(KEYID_XNM) == 0 && GetIOState(KEYID_XNP) == 1)
        {
            xn_dir = 2;
            xn_state = XN_STATE_MIDDLE;
        }
        else
        {
            xn_dir = 0;
        }
        break;
    case XN_STATE_MIDDLE:
        if (GetIOState(KEYID_XNM) == 0 && GetIOState(KEYID_XNP) == 0)
        {
            xn_state = XN_STATE_MIDDLE_2;
        }
        else if ((GetIOState(KEYID_XNM) == 1 && GetIOState(KEYID_XNP) == 1))
        {
            xn_state = XN_STATE_IDLE;
        }
        break;
    case XN_STATE_MIDDLE_2:
        if (xn_dir == 1 && GetIOState(KEYID_XNM) == 0 && GetIOState(KEYID_XNP) == 1)
        {
            xn_state = XN_STATE_STOP;
        }
        else if (xn_dir == 2 && GetIOState(KEYID_XNM) == 1 && GetIOState(KEYID_XNP) == 0)
        {
            xn_state = XN_STATE_STOP;
        }
        else if ((GetIOState(KEYID_XNM) == 1 && GetIOState(KEYID_XNP) == 1))
        {
            xn_state = XN_STATE_IDLE;
        }
        break;
    case XN_STATE_STOP:
        if (GetIOState(KEYID_XNM) == 1 && GetIOState(KEYID_XNP) == 1)
        {
            xn_state = XN_STATE_IDLE;
            if (xn_dir == 1)
            {
                xn_counter++;
            }
            else if (xn_dir == 2)
            {
                xn_counter--;
            }
        }
        break;
    default:
        xn_state = 0;
        break;
    }
}

void XN_Scan(void)
{
    if (keyPressState == KEY_NOPRESSED && keyLongPressState == KEY_NOPRESSED)
    {
        XN_StateMachine();
    }
    
}

void XN_Pro(void)
{
    static uint8_t xn_txstate = 0;
    static uint8_t tx_counter = 0;
    switch (xn_txstate)
    {
    case 0:
        if (xn_counter != xn_tx_num)
        {
            xn_tx_num = xn_counter;
            xn_txstate++;
            ClearTxCounter();
            tx_counter = 0;
        }
        break;
    case 1:
        tx_counter++;
        if (tx_counter > 2)
        {
            xn_txstate++;
            ClearTxCounter();
            tx_counter = 0;
        }
        break;
    case 2:
        tx_counter++;
        if (tx_counter > 2)
        {
            xn_txstate = 0;
            ClearTxCounter();
            tx_counter = 0;
        }
        break;
    
    default:
        xn_txstate = 0;
        break;
    }
}


#define KEY_LONGPRESS_500MS     100
void KeyPro(void)//5ms
{
    uint8_t i,num,key;
    static uint16_t keyPressCounter;
    static uint8_t LastKey;
    static uint8_t KeyProState = 0,KeyProCounter=0;
    switch (KeyProState)
    {
    case 0:
        keyLongPressState = 0;
        keyPressState = 0;
        for (i = 1; i < 6; i++)
        {
            key = GetKeyState(i);
            if (key == KEY_Long_PRESSED)
            {
                keyLongPressState = i;
                KeyProState = 1;
                break;
            }
            key = getKeyReleaseFlag(i);
            if (key == KEY_PRESSED)
            {
                keyPressState = i;
                KeyProState = 5;
                break;
            }
        }
        break;
    case 1://长按
        if (keyLongPressState == KEYID_MIDDLE)
        {
            btn_req = 2;
            toggle_req = 0;
        }
        else if (keyLongPressState > KEY_NOPRESSED && keyLongPressState < KEYID_MIDDLE)
        {
            btn_req = 0;
            toggle_req = keyLongPressState+4;
        }
        ClearTxCounter();
        KeyProState++;
        KeyProCounter = 0;
        break;
    case 2://
        KeyProCounter++;
        if (KeyProCounter >= 4)
        {
            KeyProCounter = 0;
            ClearTxCounter();
            KeyProState++;
        }
        break;
    case 3://
        KeyProCounter++;
        if (KeyProCounter >= 4)
        {
            KeyProCounter = 0;
            ClearTxCounter();
            KeyProState++;
        }
        break;
    case 4://
        for (i = 1; i < 6; i++)
        {
            key = GetKeyState(i);
            if (key != KEY_NOPRESSED)
            {
                break;
            }
        }
        if (i == 6)
        {
            KeyProState = 0;
            btn_req = 0;
            toggle_req = 0;
            keyLongPressState = 0;
            keyPressState = 0;
            ClearKeyState();
        }
        break;
    case 5:
        if (keyPressState == KEYID_MIDDLE)
        {
            btn_req = 1;
            toggle_req = 0;
        }
        else if (keyPressState > KEY_NOPRESSED && keyPressState < KEYID_MIDDLE)
        {
            btn_req = 0;
            toggle_req = keyPressState;
        }
        ClearTxCounter();
        KeyProState++;
        KeyProCounter = 0;
        
        break;
    case 6://
        KeyProCounter++;
        if (KeyProCounter >= 4)
        {
            KeyProCounter = 0;
            ClearTxCounter();
            KeyProState++;
        }
        break;
    case 7://
        KeyProCounter++;
        if (KeyProCounter >= 4)
        {
            KeyProCounter = 0;
            ClearTxCounter();
            KeyProState++;
        }
        break;
    case 8://
        btn_req = 0;
        toggle_req = 0;
        KeyProState = 0;
        ClearKeyState();
        break;
    default:
        KeyProState = 0;
        break;
    }
    
}

void Can_Msg_Change(void)
{
    //CAN_45A.Msg_Part.SCM_PsngrSeatBeltWarnSts = sbrWarnState;
    CAN_212.Msg_Part.MSW_PsdBtnReq = btn_req;
    CAN_212.Msg_Part.MSW_TogReq = toggle_req;
    CAN_212.Msg_Part.MSW_BtnFltSts = 0;
    CAN_212.Msg_Part.MSW_RotStep = xn_tx_num;
    CAN_212.Msg_Part.Reserve_7 = ucBusOffModeState;
}

static uint8_t EEL_BUF[50];
void EEL_READ(void)
{
    uint16_t checksum;
    uint8_t *src,*des,i;
    ReadFlashData(EEL_BUF, 0x000F1000, sizeof(MotorStateEE));
    pEE = (MotorStateEE_Type *)EEL_BUF;
    checksum = pEE->kbsoft1 + pEE->kbsoft2 + pEE->kbnow + pEE->zysoft1 + pEE->zysoft2 + pEE->zynow;
    if (pEE ->start == 0x55AA && pEE->stop == 0xAA55 && checksum == pEE->checksum)
    {
        des = &MotorStateEE;
        src = EEL_BUF;
        for (i = 0; i < sizeof(MotorStateEE); i++)
        {
            des[i] = src[i];
        }
    }
    else
    {
        MotorStateEE.start = 0x55AA;
        MotorStateEE.stop = 0xAA55;
        MotorStateEE.kbnow = 0x8000;
        MotorStateEE.kbsoft1 = 0;
        MotorStateEE.kbsoft2 = 0;
        MotorStateEE.zynow = 0x8000;
        MotorStateEE.zysoft1 = 0;
        MotorStateEE.zysoft2 = 0;
        EEL_Write_Enable_Check();
    }
    
}

#define SC_500MS_PC_1MS 500

void EEL_WRITE(void)
{
    static unsigned char EEL_SAVE_REQUIRE_FLAG=0;
    uint8_t i,*p;
    if (EEL_SAVE_ENABLE)
    {
        EEL_SAVE_REQUIRE_FLAG = 1;
        EEL_SAVE_CNT_DOWN_TIMER = SC_500MS_PC_1MS;
        EEL_SAVE_ENABLE = 0;
    }
    
    if (0 == EEL_SAVE_CNT_DOWN_TIMER && 1 == EEL_SAVE_REQUIRE_FLAG)
    {
        MotorStateEE.checksum = MotorStateEE.kbsoft1 + MotorStateEE.kbsoft2 + MotorStateEE.kbnow + MotorStateEE.zysoft1 + MotorStateEE.zysoft2 + MotorStateEE.zynow;
        p = &MotorStateEE;
        for (i = 0; i < sizeof(MotorStateEE); i++)
        {
            EEL_BUF[i] = p[i];
        }
        
        if(WriteDataflash(EEL_BUF,0x000F1000,sizeof(MotorStateEE)) == 0x11)
        {
            EEL_SAVE_REQUIRE_FLAG=0;
        }
        
    }
}

void EEL_Write_Enable_Check(void)
{
    EEL_SAVE_ENABLE = 1;
}

void DID_data_save_init(void)
{
    unsigned char DID_init_Buf[33], i;
    ReadFlashData(DID_init_Buf, 0x000F1000 + 0x400, 1);

    if (DID_init_Buf[0] == 0xff)
    {
        for (i = 0; i < 33; i++)
        {
            if (i < 8)
            {
                DID_init_Buf[i] = DID_0xF110_VehicleNetworkConfiguration[i];
            }
            else if (i < 25)
            {
                DID_init_Buf[i] = DID_0xF190_vehicleIdentificationNumber[i - 8];
            }
            else if (i < 33)
            {
                DID_init_Buf[i] = DID_0xF197_SystemNameOrEngineType[i - 25];
            }
        }
        WriteDataflash(DID_init_Buf, 0x000F1000 + 0x400, 33);
    }
    ReadFlashData(DID_init_Buf, 0x000F1000 + 0x800, 1);
    if (DID_init_Buf[0] == 0xff)
    {
        for (i = 0; i < 32; i++)
        {
            if (i < 16)
            {
                DID_init_Buf[i] = DID_0xF198_RepairShopCodeOrTesterSerialNumber[i];
            }
            else if (i < 20)
            {
                DID_init_Buf[i] = DID_0xF199_ProgrammingOrConfigurationDate[i - 16];
            }
            else if (i < 24)
            {
                DID_init_Buf[i] = DID_0xF19D_ECUInstallationDateDataIdentifier[i - 20];
            }
            else if (i < 32)
            {
                DID_init_Buf[i] = DID_0xF112_VehicleName[i - 24];
            }
        }
        WriteDataflash(DID_init_Buf, 0x000F1000 + 0x800, 32);
    }
}

unsigned char BusOffTimeCnt = 0;
unsigned short BusOff1msCnt = 0;
unsigned char CanBusOffPro(void)
{
    unsigned char ret = 0;
    if (C0ERFLLL & 0x08) // Bus-Off Stutas
    {
        ret = 1;
    }
    if ((C0CTRLL & 0x02) == 0x02) // Channal Halt Mode
    {

        if (C0ERFLLL & 0x08) // Bus-Off Stutas
        {
            BusOff1msCnt++;
            ret = 1;
        }

        if ((BusOffTimeCnt < 10) && (BusOff1msCnt >= 100))
        {
            BusOffTimeCnt++;
            BusOff1msCnt = 0;
            C0ERFLL = 0;
            C0CTRL &= ~0x03; /* CHMDC[1:0] = 00B   change to communication mode. */
        }
        else if ((BusOffTimeCnt >= 10) && (BusOff1msCnt >= 1000))
        {
            BusOffTimeCnt = 10;
            BusOff1msCnt = 0;
            C0ERFLL = 0;
            C0CTRL &= ~0x03; /* CHMDC[1:0] = 00B   change to communication mode. */
        }
    }
    return ret;
}

#define FAST_BUSOFF_THRESHOULD 50  // 100MS
#define SLOW_BUSOFF_THRESHOULD 200 // 100MS

void BusOff_Recovery(void);

void BusOff_Detect(void)
{

    if ((C0ERFLL & 0x08) && (R_CAN_ReadChStatus_CH0() & 0x02))
    {
        BusOff_flag = 1;
        if (uiBusOffCnt == 0)
        {
            if (ucBusOffModeState == 0)
            {
                uiBusOffCnt = FAST_BUSOFF_THRESHOULD;
                //BusOff_Recovery();
            }
            if ((ucBusOffModeState > 0) && (ucBusOffModeState < 5))
            {
                BusOff_Recovery();
                uiBusOffCnt = FAST_BUSOFF_THRESHOULD; //fast recover
            }
            else if (ucBusOffModeState >= 5)
            {
                BusOff_Recovery();
                uiBusOffCnt = SLOW_BUSOFF_THRESHOULD; //soft recover
            }
            else
            {
                ;
            }
            if (ucBusOffModeState < 5)
            {
                ucBusOffModeState++;
            }
        }
    }
    else
    {
        if (ucBusOffModeState > 0)
        {
            if (uiBusOffCnt == 0)
            {
                //ucBusOffModeState = 0;

                // 原来程序的标志位
            }
        }
        else
        {
            ;
        }
        BusOff_flag = 0;
    }
}

void BusOff_Recovery(void)
{
    CFCCL0L &= ~0x01;
    NOP();
    CFCCL0L |= 0x01;
    if (C0ERFLL != 0)
    {
        C0ERFLL = 0;
    }
    C0CTRL &= 0xfffc; // bus off
}
uint16_t SupplyVoltage;
void IGN_Voltage_Detect(void)
{
    uint32_t adval;
    adval = getAdval(ADCH_IGN);
    SupplyVoltage = (adval*57*5)>>10;   
    if (adval <= 305 )
    {
        IGN_Voltage_error_count++;
        if (IGN_Voltage_error_count >= 250)
        {
            IGN_Voltage_error_count = 0;
            IGN_Voltage_error_flag = 1;
        }
    }
    else if (adval >= 592 )//16.5
    {
        IGN_Voltage_error_count++;
        if (IGN_Voltage_error_count >= 250)
        {
            IGN_Voltage_error_count = 0;
            IGN_Voltage_error_flag = 2;
        }
    }
    else if (adval >= 323 && adval <= 574)
    {
        IGN_Voltage_error_count = 0;
        IGN_Voltage_error_flag = 0;
    }


    if (IGN_Voltage_error_flag != 0)
    {
        // TAU0_Channel1_ChangeDuty(0);
    }
}


void value_init(void)
{
    CAN_LostCount = 500;
    BusOff_Detect_delay_count = 1000;
    ucIgnStus = IGN_OFF;
}
void CAN_RX_Data_Handle(void)
{

   VehicleSpeedRaw = CAN_403.Msg_Bit.VCU_VehSpd1;
   VehicleSpeedRaw <<= 8;
   VehicleSpeedRaw |= CAN_403.Msg_Bit.VCU_VehSpd2;
   VehicleSpeedRaw <<= 2;
   VehicleSpeedRaw |= CAN_403.Msg_Bit.VCU_VehSpd3;

   VehicleSpeed = VehicleSpeedRaw>>4;
}


void SleepDetect(void)
{

    // if(CAN_LostCount==0 && IGN_Lost == 1)
    {

        R_TAU0_Channel0_Stop();
        // R_TAU0_Channel2_Stop();
        // R_TAU0_Channel6_Stop();
        // R_TAU1_Channel0_Stop();
        TO0 = 0;
        TO1 = 0;
        TOE0 = 0;
        TOE1 = 0;
        TO0 = 0;
        TO1 = 0;

        // R_IICA0_Stop();
        R_ADC_Stop();
        ADCE = 0;
        IICA0EN = 0;
        TAU0EN = 0;
        TAU1EN = 0;

        P6_bit.no2 = 0;
        P6_bit.no3 = 0;
        P12_bit.no0 = 0;
        P3_bit.no3 = 0;
        P1_bit.no3 = 0;
        P1_bit.no4 = 0;
        P3_bit.no0 = 0;

        CAN_STB = 1;

        C0CTRL |= (uint16_t)(CAN_STP_BIT_ON);
        GCTRL |= 0x01;
        NOP();
        GCTRL |= (uint16_t)(CAN_GLB_STP_BIT_ON);
        PLLON = 0;
        //R_INTC3_Start();
        CAN0WUPIF = 0U;
        CAN0WUPMK = 0U;

        if (I_IGN_SIGN != IGN_ON)
            STOP();

        WakeUP();
    }
}

void WakeUP(void)
{
    // stop can and ex interrupt
    CAN0WUPIF = 0U;
    CAN0WUPMK = 1U;
    //R_INTC3_Stop();
    // WDTE = 0xff;  //reset
    CAN_STB = 0;
    hdwinit();
    R_MAIN_UserInit();
    R_TAU0_Channel0_Start(); // timer


}

void Signal_Lost_Detect(unsigned char Pin,
                        unsigned char Lost_state,
                        unsigned char *Signal_Lost,
                        unsigned char *Signal_Lost_count,
                        unsigned char Lost_time)
{
    if (Pin == Lost_state)
    {
        (*Signal_Lost_count)++;
        if ((*Signal_Lost_count) >= Lost_time)
        {
            *Signal_Lost_count = 0;
            *Signal_Lost = 1;
        }
    }
    else
    {
        *Signal_Lost_count = 0;
        *Signal_Lost = 0;
    }
}

void IGN_Detect(void)
{
    static unsigned char IGN_last;
    Signal_Lost_Detect(I_IGN_SIGN, 1, &IGN_Lost, &IGN_Lost_Count, 5);
    Signal_Lost_Detect(I_IGN_SIGN, 0, &IGN_On, &IGN_On_Count, 5);

    if (IGN_On == 1)
    {
        ucIgnStus = IGN_ON;
    }
    else if (IGN_Lost == 1)
    {
        ucIgnStus = IGN_OFF;

        PWN_KEY = 0;
    }
    if (IGN_last != ucIgnStus)
    {
        IGN_last = ucIgnStus;
        if (IGN_ON == ucIgnStus)
            C0CTRH &= ~0x0300; // 设置正常模式
    }
}

void LED_Light_Ctrl(void)
{

}


/*****************diagnostic******************/

void getIGNVoltage(unsigned char* data)
{
    data[0] = (uint8_t)SupplyVoltage;
}
