
#include "Data_VSpeed\Data_VSpeed.h"
#include "Application.h"

static uint16_t DataVSpeedActual;
static uint16_t DataVSpeedDisp;
static uint16_t DataVSpeedHysteresis;
static uint8_t  DataVSpeedValid;
// static uint16_t DataVSpeedDisp_Mile;
static DataVSpeedSamplerStruct DataVSpeedSampler;
static DataVSPeedDampingStruct DataVSPeedDamping;


#define DATA_APPR_DIR_INC 0x01
#define DATA_APPR_DIR_DEC 0x02

/******************************************************************************
函数名：Data_Vehicle_Speed_KL30_Init
功  能：车速数据KL30初始化
参  数：无
返回值：无
******************************************************************************
注  意：该函数KL30初始化被调用一次
******************************************************************************/
void Data_Vehicle_Speed_KL30_Init(void)
{
    DataVSpeedActual         = 0;
    DataVSpeedDisp           = 0;
    DataVSpeedHysteresis     = 0;
    DataVSpeedValid          = 1;
    DataVSpeedSampler.Cnt    = 0;
    DataVSPeedDamping.Speed  = 0;
    DataVSPeedDamping.Delta  = 0;
    DataVSPeedDamping.Dir    = DATA_APPR_DIR_INC;
    DataVSpeedSampler.Timer1 = 0;
    DataVSpeedSampler.Timer  = 0;
}

/******************************************************************************
函数名：Data_Vehicle_Speed_Wakeup_Init
功  能：车速数据唤醒初始化
参  数：无
返回值：无
******************************************************************************
注  意：该函数唤醒初始化被调用一次
******************************************************************************/
void Data_Vehicle_Speed_Wakeup_Init(void)
{
    DataVSpeedDisp           = 0;
    DataVSpeedHysteresis     = 0;
    DataVSPeedDamping.Speed  = 0;
    DataVSPeedDamping.Delta  = 0;
    DataVSPeedDamping.Dir    = DATA_APPR_DIR_INC;
    DataVSpeedSampler.Timer1 = 0;
    DataVSpeedSampler.Timer  = 0;
}

/******************************************************************************
函数名：Data_Vehicle_Speed_Processing_Service
功  能：车速数据处理函数
参  数：无
返回值：无
******************************************************************************
注  意：该函数必须每20ms被调用一次
******************************************************************************/
void Data_Vehicle_Speed_Processing_Service(void)
{
    uint8_t  i;
    uint16_t Delta;
    uint32_t VSpeed;
    uint32_t VSpeedCal;
    //uint8_t  ESC_VehicleSpeedvalid;
    uint32_t Vehicle_Speed;

    Vehicle_Speed = Get_CAN_CH0_ID_101_Sig_ECU_Vehicle_Speed( );
    //ESC_VehicleSpeedvalid = Get_CAN_CH0_ID_330_Sig_ESC_Vehicle_speed_valid( );

    // 第1步：获取实际车速值及车速有效性
    if( Common_Get_IG_Sts( ) == COMMON_POWER_ON )
    {
        if ((CAN_MSG_Status(&CAN_CH0_CanMsgOp, CAN_CH0_ID_CAN_0x101_Msg_Count) == CAN_SIG_LOST) || (Vehicle_Speed > 0XFF))
        {
            /* 先判断掉线 */
            if (CAN_MSG_Status(&CAN_CH0_CanMsgOp, CAN_CH0_ID_CAN_0x101_Msg_Count) == CAN_SIG_LOST)
            {
                DataVSpeedValid          = 0;
                DataVSpeedActual         = 0;
                DataVSpeedSampler.Backup = 0;
            }
            #if 0
            else if ( ESC_VehicleSpeedvalid == 1 )//发送can无效标志位
            {
                if ( DataVSpeedSampler.Timer1 <= 10 ) /* 10帧无效 */
                {
                    if ( DataVSpeedValid )//判断车速是否有效,有效采集10次,车速等于上次值
                    {
                        DataVSpeedSampler.Timer1++;
                        DataVSpeedActual = DataVSpeedSampler.Backup;
                    }
                    else//无效,不采集,车速=0
                    {
                        DataVSpeedSampler.Timer1 = 10;
                        DataVSpeedActual         = 0;
                        DataVSpeedSampler.Backup = 0;
                    }
                }
                else//不采集就,车速=0
                {
                    DataVSpeedValid          = 0;
                    DataVSpeedActual         = 0;
                    DataVSpeedSampler.Backup = 0;
                }
            }
            #endif
            else /* 收到无效值 */
            {
                if ( DataVSpeedSampler.Timer <= 100 ) /* 100帧无效值 */
                {
                    if ( DataVSpeedValid )
                    {
                        DataVSpeedSampler.Timer++;
                        DataVSpeedActual = DataVSpeedSampler.Backup;
                    }
                    else
                    {
                        DataVSpeedSampler.Timer  = 100;
                        DataVSpeedActual         = 0;
                        DataVSpeedSampler.Backup = 0;
                    }
                }
                else    // 接收到100帧无效值
                {
                    DataVSpeedValid          = 0;
                    DataVSpeedActual         = 0;
                    DataVSpeedSampler.Backup = 0;
                }
            }  
        }
        else //车速在线且有效
        {
            if ( DataVSpeedValid == 0 )
            {
                DataVSpeedValid = 1;
                VSpeed = Vehicle_Speed;
                // VSpeed *= 9;
                // VSpeed >>= 4; 
                DataVSpeedActual = VSpeed * 10;
            }
            else
            {
                DataVSpeedSampler.Buffer [ DataVSpeedSampler.Cnt ] = Vehicle_Speed;

                i = DataVSpeedSampler.Cnt;
                while ( (i > 0) && (DataVSpeedSampler.Buffer [ i ] < DataVSpeedSampler.Buffer [ i - 1 ]) )
                {
                    VSpeed                             = DataVSpeedSampler.Buffer [ i ];
                    DataVSpeedSampler.Buffer [ i ]     = DataVSpeedSampler.Buffer [ i - 1 ];
                    DataVSpeedSampler.Buffer [ i - 1 ] = VSpeed;
                    i--;
                }

                DataVSpeedSampler.Cnt++;
                if ( DataVSpeedSampler.Cnt >= 3 )
                {
                    DataVSpeedSampler.Cnt = 0;
                    VSpeed                = DataVSpeedSampler.Buffer [ 1 ];
                    //VSpeed *= 9;
                    //VSpeed >>= 4;
                    DataVSpeedActual = VSpeed * 10;
                }
                DataVSpeedSampler.Timer  = 0;
                DataVSpeedSampler.Timer1 = 0;
                DataVSpeedSampler.Backup = DataVSpeedActual;
            }
        }
    }
    else
    {
        DataVSpeedValid          = 0;
        DataVSpeedActual         = 0;
        DataVSpeedSampler.Timer  = 0;
        DataVSpeedSampler.Timer1 = 0;
        DataVSpeedSampler.Cnt    = 0;
        DataVSpeedSampler.Backup = 0;
    }

    // 第2步：车速的阻尼处理
    VSpeed = DataVSpeedActual;
    if ( VSpeed > DataVSPeedDamping.Speed )    // 实际值比当前显示值大时
    {
        Delta = ( uint16_t )VSpeed - DataVSPeedDamping.Speed;

        if ( DataVSPeedDamping.Dir == DATA_APPR_DIR_INC )    // 显示值正在向实际值增加,则维持当前方向调节增加速度
        {
            if ( DataVSPeedDamping.Delta < Delta )           // 当前增量小于显示值与实际值的差值,则提升增加的速度
            {
                DataVSPeedDamping.Delta += DATA_VSPEED_INC_STEP;
                if ( DataVSPeedDamping.Delta > Delta )
                    DataVSPeedDamping.Delta = Delta;
            }
            else    // 当前增量大于等于显示值与实际值的差值,保持增量与当前差值同步,增加的速度即逐步减小
                DataVSPeedDamping.Delta = Delta;

            Delta = DataVSPeedDamping.Delta;
            Delta /= DATA_VSPEED_DAMPING_FACTOR;

            if ( Delta < DATA_VSPEED_APPR_SPEED_MIN )
                Delta = DATA_VSPEED_APPR_SPEED_MIN;

            DataVSPeedDamping.Speed += Delta;
            if ( DataVSPeedDamping.Speed > VSpeed )
                DataVSPeedDamping.Speed = ( uint16_t )VSpeed;
        }
        else    // 显示值正在减小,则尽快减速至速度为最小时更换方向
        {
            if ( DataVSPeedDamping.Delta > DATA_VSPEED_DEC_STEP )
                DataVSPeedDamping.Delta -= DATA_VSPEED_DEC_STEP;
            else
                DataVSPeedDamping.Delta = 0;

            Delta = DataVSPeedDamping.Delta;
            Delta /= DATA_VSPEED_DAMPING_FACTOR;

            if ( Delta < DATA_VSPEED_APPR_SPEED_MIN )         // 已减速至最小速度
                DataVSPeedDamping.Dir = DATA_APPR_DIR_INC;    // 更换方向
            else
            {
                if ( DataVSPeedDamping.Speed > Delta )
                    DataVSPeedDamping.Speed -= Delta;
                else
                    DataVSPeedDamping.Speed = 0;
            }
        }
    }
    else if ( VSpeed < DataVSPeedDamping.Speed )    // 实际值比当前显示值小时
    {
        Delta = DataVSPeedDamping.Speed - ( uint16_t )VSpeed;

        if ( DataVSPeedDamping.Dir == DATA_APPR_DIR_INC )    // 显示值仍在增加,则尽快减速至速度为最小时更换方向
        {
            if ( DataVSPeedDamping.Delta > DATA_VSPEED_DEC_STEP )
                DataVSPeedDamping.Delta -= DATA_VSPEED_DEC_STEP;
            else
                DataVSPeedDamping.Delta = 0;

            Delta = DataVSPeedDamping.Delta;
            Delta /= DATA_VSPEED_DAMPING_FACTOR;

            if ( Delta < DATA_VSPEED_APPR_SPEED_MIN )         // 已减速至最小速度
                DataVSPeedDamping.Dir = DATA_APPR_DIR_DEC;    // 更换方向
            else
            {
                DataVSPeedDamping.Speed += Delta;
                if ( DataVSPeedDamping.Speed > 1200 )
                     DataVSPeedDamping.Speed = 1200;
            }
        }
        else                                          // 显示值正在向实际值减小,则维持当前方向调节增加速度
        {
            if ( DataVSPeedDamping.Delta < Delta )    // 当前(负)增量小于显示值与实际值的差值,则提升减小的速度
            {
                DataVSPeedDamping.Delta += DATA_VSPEED_INC_STEP;
                if ( DataVSPeedDamping.Delta > Delta )
                    DataVSPeedDamping.Delta = Delta;
            }
            else    // 当前(负)增量大于等于显示值与实际值的差值,保持(负)增量与当前差值同步,减小的速度即逐步减小
                DataVSPeedDamping.Delta = Delta;

            Delta = DataVSPeedDamping.Delta;
            Delta /= DATA_VSPEED_DAMPING_FACTOR;

            if ( Delta < DATA_VSPEED_APPR_SPEED_MIN )
                Delta = DATA_VSPEED_APPR_SPEED_MIN;

            if ( DataVSPeedDamping.Speed < VSpeed + Delta )
                DataVSPeedDamping.Speed = ( uint16_t )VSpeed;
            else
                DataVSPeedDamping.Speed -= Delta;
        }
    }
    else    // 实际值与当前显示值相等时
    {
        Delta = DataVSPeedDamping.Delta;
        Delta /= DATA_VSPEED_DAMPING_FACTOR;

        if ( Delta > DATA_VSPEED_APPR_SPEED_MIN )                    // 当前的速度不是最小,说明数值正在增加/减小中,则继续原过程
        {
            if ( DataVSPeedDamping.Delta > DATA_VSPEED_DEC_STEP )    // 显示值越过了实际值,必然要先减速至最小速度,再改变方向返回实际值
                DataVSPeedDamping.Delta -= DATA_VSPEED_DEC_STEP;
            else
                DataVSPeedDamping.Delta = 0;

            Delta = DataVSPeedDamping.Delta;
            Delta /= DATA_VSPEED_DAMPING_FACTOR;

            if ( DataVSPeedDamping.Dir == DATA_APPR_DIR_INC )     // 显示值当前是增加方向
            {
                if ( Delta < DATA_VSPEED_APPR_SPEED_MIN )         // 已减速至最小速度
                    DataVSPeedDamping.Dir = DATA_APPR_DIR_DEC;    // 更换方向
                else
                {
                    DataVSPeedDamping.Speed += Delta;
                    if ( DataVSPeedDamping.Speed > 1200 )
                         DataVSPeedDamping.Speed = 1200;
                }
            }
            else                                                  // 显示值当前是减小方向
            {
                if ( Delta < DATA_VSPEED_APPR_SPEED_MIN )         // 已减速至最小速度
                    DataVSPeedDamping.Dir = DATA_APPR_DIR_INC;    // 更换方向
                else
                {
                    if ( DataVSPeedDamping.Speed > Delta )
                        DataVSPeedDamping.Speed -= Delta;
                    else
                        DataVSPeedDamping.Speed = 0;
                }
            }
        }
    }

    // 第3步：生成显示车速
     if ( (DataVSPeedDamping.Speed >= DataVSpeedHysteresis) || (DataVSPeedDamping.Speed < DATA_VSPEED_HYSTERESIS) )
    {
        DataVSpeedHysteresis = DataVSPeedDamping.Speed;
    }
    else
    {
        if ( DataVSpeedHysteresis - DataVSPeedDamping.Speed >= DATA_VSPEED_HYSTERESIS )
        {
            DataVSpeedHysteresis = DataVSPeedDamping.Speed;
        }
    } 

    VSpeedCal = ( uint32_t )DataVSpeedHysteresis;

    if ( DataVSpeedValid )
    {
        VSpeedCal *= 108; 
        VSpeedCal /= 100;
        if((VSpeedCal % 10) >= 5)
        {
            VSpeedCal += 5; /* 四舍五入 */
        }
        DataVSpeedDisp = ( uint16_t )VSpeedCal;
    }
    else
    {
        DataVSpeedDisp = 0;
    }
}

/*车速有效位：有效=1，无效=0*/
uint8_t Get_VechileSpeedValid(void)
{
    return DataVSpeedValid;
}
/*真实的车速，精度10倍,*/
uint16_t Get_ActualVechileSpeed(void)
{
    return DataVSpeedActual;
}
/*显示车速，精度10倍，取整，舍去小数点*/
uint16_t Get_DispVechileSpeed(void)
{
    uint16_t Vspeed = 0;
    if(Get_Dis_KM_Unit() == 0) /* KM */
    {
        if ( DataVSpeedDisp >= 1200 )
        {
            DataVSpeedDisp = 1200;
        }
        Vspeed = DataVSpeedDisp;
    }
    else //if (Get_Dis_KM_Unit() == 1)   /* MILE */
    {
        Vspeed = Data_Km_To_Mile(DataVSpeedDisp);
        if ( Vspeed >= 750 )
        {
            Vspeed = 750;
        }
    }
    // else    
    // {
    //     ;
    // }
    return Vspeed;
}



