
#include "Mileage\Services_Mileage_User.h"
#include "Mileage\Services_Mileage.h"
#include "Eeprom\eepromManage.h"
#include "CommonInterface.h"



__align(4)
uint8_t DataMilleageBuf[Data_MEM_Block_Mileage];
uint8_t DataODOBuf[Data_MEM_Block_ODO];
uint8_t DataTripBuf[Data_MEM_Block_Trip * EM_TRIP_MAX];
Mileage_t g_WriteMileage;
Mileage_t g_ReadMileage;
uint8_t odo_writeState;
uint8_t odo_readState;
static uint32_t Data_User_EEPROM_Read(uint16_t u16BlockID, uint32_t u32Data[], uint16_t u16Len);
static void Data_User_EEPROM_Write(Data_EEPROM_Enum_t BlockID, uint32_t u32Data[], uint16_t u16Len);

#define EEPROM_BLOCK_00     0
#define EEPROM_BLOCK_01     16
#define EEPROM_BLOCK_02     32
#define EEPROM_BLOCK_03     48
#define EEPROM_BLOCK_04     64
#define EEPROM_BLOCK_05     80
#define EEPROM_BLOCK_06     96




/******************************************************************************
  Function：Data_ODO_KL30Init
  Description：
  Input:
  Output:
 ******************************************************************************/
void Data_User_Mileage_KL30Init(void)
{
    uint32_t TempBuf[20] = {0};
    Mileage_Init_t MileInit = {0};
    Mileage_Func_t Func = {0};
    ODO_Init_t ODOInit = {0};
    Trip_Init_t TripInit[4] = {0};

    (void)Data_User_EEPROM_Read(EM_MILEAGE_BLOCK, TempBuf, 1);
    if (TempBuf[0] == 0xFFFFFFFF)
    {
        MileInit.Mileage = 0u;
    }
    else
    {
        MileInit.Mileage = TempBuf[0];
    }
    Func.Get_Sys_IG_Sts = Common_Get_IG_Sts;
    Func.Get_Act_V_Speed_Valid = Common_Get_Act_V_Speed_Valid;
    Func.Get_Act_V_Speed = Common_Get_Act_V_Speed;
    Func.Get_TireSize = (void *)0;
    Func.EEPromWrite_Cbk = Data_User_EEPROM_Write;
    Data_Mileage_KL30_Init(DataMilleageBuf, &MileInit, &Func);

    (void)Data_User_EEPROM_Read(EM_ODO_BLOCK, TempBuf + 1, 2);
    if (TempBuf[1] == 0xFFFFFFFF)
    {
        ODOInit.Stamp = 0;
    }
    else
    {
        ODOInit.Stamp = TempBuf[1];
    }
    if (TempBuf[1] == 0xFFFFFFFF)
    {
        ODOInit.Offset = 0;
    }
    else
    {
        ODOInit.Offset = TempBuf[2];
    }
    ODOInit.MaxValue = 9999999;
    Data_ODO_KL30_Init(DataODOBuf, &ODOInit, Func.EEPromWrite_Cbk);

    (void)Data_User_EEPROM_Read(EM_TRIP_BLOCK, TempBuf + 3, 8);
    if (TempBuf[3] == 0XFFFFFFFF)
    {
        TripInit[EM_TRIP_A].Stamp = 0;
    }
    else
    {
        TripInit[EM_TRIP_A].Stamp = TempBuf[3];
    }
    TripInit[EM_TRIP_A].Offset = TempBuf[4];
    TripInit[EM_TRIP_A].MaxValue = 99999; /* 最大999.9Mile 进行复位 */
    TripInit[EM_TRIP_A].IsRestart = 1u;

    TripInit[EM_TRIP_B].Stamp = 0xFFFFFFFFu;
    TripInit[EM_TRIP_B].MaxValue = 99999;
    TripInit[EM_TRIP_B].IsRestart = 1u;

    TripInit[EM_TRIP_C].Stamp = 0xFFFFFFFFu;
    TripInit[EM_TRIP_C].MaxValue = 99999;
    TripInit[EM_TRIP_C].IsRestart = 1u;

    TripInit[EM_TRIP_D].Stamp = 0xFFFFFFFFu;
    TripInit[EM_TRIP_D].MaxValue = 99999;
    TripInit[EM_TRIP_D].IsRestart = 1u;
    Data_Trip_KL30_Init(DataTripBuf, TripInit, EM_TRIP_MAX, Func.EEPromWrite_Cbk);

}

void Data_User_Mileage_WakeupInit(void)
{
    Mileage_Func_t Func = {0};

    Func.Get_Sys_IG_Sts = Common_Get_IG_Sts;
    Func.Get_Act_V_Speed_Valid = Common_Get_Act_V_Speed_Valid;
    Func.Get_Act_V_Speed = Common_Get_Act_V_Speed;
    Func.Get_TireSize = (void *)0;
    Func.EEPromWrite_Cbk = Data_User_EEPROM_Write; // ��ʱδ����
    Data_Mileage_Wakeup_Init(DataMilleageBuf, &Func);

    Data_ODO_Wakeup_Init(DataODOBuf, Func.EEPromWrite_Cbk);

    Data_Trip_Wakeup_Init(DataTripBuf, EM_TRIP_MAX, Func.EEPromWrite_Cbk);

}


static uint32_t Data_User_EEPROM_Read(uint16_t u16BlockID, uint32_t u32Data[], uint16_t u16Len)
{
    switch (u16BlockID)
    {
    case EM_MILEAGE_BLOCK:
        odo_readState = eeprom_ReadODO(&g_ReadMileage);
        u32Data[0] = g_ReadMileage.Odo / 100;
        break;

    case EM_ODO_BLOCK:

        eeprom_ReadRecord(EEPROM_BLOCK_01, (uint8_t *)u32Data, u16Len * 4);
        break;

    case EM_TRIP_BLOCK:
        eeprom_ReadRecord(EEPROM_BLOCK_03, (uint8_t *)u32Data, u16Len * 4);
        break;

    default:
        break;
    }

    return 0;
}

static void Data_User_EEPROM_Write(Data_EEPROM_Enum_t BlockID, uint32_t u32Data[], uint16_t u16Len)
{
    switch (BlockID)
    {
    case EM_MILEAGE_BLOCK:
        if (u32Data[0] == 0)
        {
            eeprom_ClearOdoSection();
        }
        else
        {
            g_WriteMileage.Odo = u32Data[0] * 100;
            odo_writeState = WRITE_FAIL;
            odo_writeState = eeprom_WriteODO(&g_WriteMileage, distance_100m, 1);
        }
        break;

    case EM_ODO_BLOCK:
        eeprom_WriteRecord(EEPROM_BLOCK_01, (uint8_t *)u32Data, u16Len * 4);
        break;

    case EM_TRIP_BLOCK:
        eeprom_WriteRecord(EEPROM_BLOCK_03, (uint8_t *)u32Data, u16Len * 4);
        break;

    default:
        break;
    }
}

void Services_Mileage_Callback(void)
{
    Data_Mileage_ISR();
    Data_ODO_Processing();
    Data_Trip_Processing();
    Trip_Clear_Km_Service();
}

/**
 * @brief 获取大计里程值
 * @return 根据当前单位输出对应大计里程值
 */
uint32_t Get_ODO_Value(void)
{
    uint32_t ODO = 0;
    if (Get_Dis_Unit() == 0) /* 公制 */
    {
        ODO = Data_ODO_Read();
    }
    else if (Get_Dis_Unit() == 1) /* 英制 */
    {
        ODO = Data_Km_To_Mile(Data_ODO_Read());
    }
    else /* 无效值，按照公里处理，理论上不会执行到这 */
    {
        ODO = Data_ODO_Read();
    }
    return ODO;
}

/**
 * @brief 获取小计里程值
 * @return 根据当前单位输出对应小计里程值
 */
uint32_t Get_Trip_Value(void)
{
    uint32_t Trip = 0;
    if (Get_Dis_Unit() == 0) /* 公制 */
    {
        Trip = Data_Read_Trip(EM_TRIP_B);
    }
    else if (Get_Dis_Unit() == 1) /* 英制 */
    {
        Trip = Data_Km_To_Mile(Data_Read_Trip(EM_TRIP_B));
    }
    else /* 无效值，按照公里处理，理论上不会执行到这 */
    {
        Trip = Data_Read_Trip(EM_TRIP_B);
    }
    return Trip;
}

/**
 * @brief 当前单位在KM时，小计里程大于999.9KM，主动触发小计清零
 *
 */
void Trip_Clear_Km_Service(void)
{
    if (Get_Dis_Unit() == 0) /* 公制 */
    {
        if (Data_Read_Trip(EM_TRIP_B) > 9999) /* 当前单位在KM时，里程大于999.9KM进行清零 */
        {
            Data_Clear_Trip_All();
        }
    }
}


/**
 * @brief 触发单位转换时调用，如当前单位英里且里程大于621Mile时，单位转换为公里后需主动写入小计里程为999.9KM；
 * 需要单位转换标志位赋值后进行调用！！！
 * 
 */
void Unit_Convert_Service(void)
{
    if (Get_Dis_Unit() == 0) /* 公制 */
    {
        if (Data_Read_Trip(EM_TRIP_A) > 9999) /* 当前单位在KM时，里程大于999.9KM进行清零 */
        {
            Data_Write_Trip(EM_TRIP_A, 9999);
        }
    }   
}



