// 秒寻科技
// 计算各基站幅度
// 2023-03-12

#include "../../includes/includes.h"

// 导出全局变量定义
extern flt32 gg_afOneFrameLocationData[PUB_SLOT_FRAME_LEN];

// 计算频点幅度主控函数，负责输出基站幅度镜像数据队列和基站最强幅度数据队列
// pstLocationDataList:定位数据队列
// pstBtsAmplMirrorDataList:基站幅度镜像数据队列(返回参数)
// pstAmplDataList:基站最强幅度数据队列(返回参数)
void bts_ampl_main(PUB_LOCATION_DATA_T *pstLocationDataList, BTS_AMPL_MIRROR_DATA_T *pstBtsAmplMirrorDataList, BTS_MAX_AMPL_DATA_T *pstBtsMaxAmplDataList)
{
    PUB_LOCATION_DATA_T *pstLocationData = NULL;         // 一帧定位数据
    BTS_AMPL_MIRROR_DATA_T *pstBtsAmplMirrorData = NULL; // 一帧镜像数据
    BTS_MAX_AMPL_DATA_T *pstBtsMaxAmplData = NULL;       // 基站最强幅度数据
    uint32 dwFrameNo = 0;                                // 当前帧号
    uint8 byRemainder = 0;                               // 取模余数
    uint8 bySlotIndex = 0;                               // 时隙索引
    uint32 dwStartIndex = 0;
    flt32 *pfOneDataHead = NULL;
    flt32 *pfMultiDataHead = NULL;
    flt32 *pfDataHead = NULL;

    uint32 dwTmpIndex = 0;

    flt32 fMaxValue = 0;
    uint16 wMaxValueIndex = 0;
    flt32 fSnr = 0;

    //// 遍历基站，镜像数据（包括一秒数据和多秒数据）
    for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
    {
        pstLocationData = &pstLocationDataList[i];           // 基站定位数据
        pstBtsAmplMirrorData = &pstBtsAmplMirrorDataList[i]; // 基站信号幅度镜像数据

        // 计算前一帧的帧号(帧号从1开始，第2帧时镜像第1帧)
        dwFrameNo = pstLocationData->dwFrameNo - 1;
        if (dwFrameNo > 0)
        {
            // 1秒缓存队列重置
            byRemainder = dwFrameNo % PUB_SYS_SLOT_NUM;
            if (byRemainder == 1)
            {
                memset(pstBtsAmplMirrorData->afOneSecondData, 0, sizeof(flt32) * PUB_SIGNAL_SAMPLE_RATIO);
            }

            // 多秒缓存队列重置
            byRemainder = dwFrameNo % BTS_AMPL_MIRROR_FRAMES;
            if (byRemainder == 1)
            {
                memset(pstBtsAmplMirrorData->afMultiSecondData, 0, sizeof(flt32) * PUB_SIGNAL_SAMPLE_RATIO);
                pstBtsAmplMirrorData->byAmplValidTimes = 0;
            }

            // 获取当前帧的前一帧数据
            util_looplist_get_flt32(pstLocationData->afData, PUB_LCT_DATA_LIST_LEN, pstLocationData->dwFourthLocationIndex, gg_afOneFrameLocationData, PUB_SLOT_FRAME_LEN, &dwTmpIndex);
            pfDataHead = gg_afOneFrameLocationData;

            // 镜像数据
            bySlotIndex = (pstLocationData->dwFrameNo - 2) % PUB_SYS_SLOT_NUM; // 该帧所在时隙索引
            dwStartIndex = bySlotIndex * PUB_SLOT_FRAME_LEN;                   // 开始索引
            pfOneDataHead = &pstBtsAmplMirrorData->afOneSecondData[dwStartIndex];
            pfMultiDataHead = &pstBtsAmplMirrorData->afMultiSecondData[dwStartIndex];
            for (uint16 j = 0; j < PUB_SLOT_FRAME_LEN; j++)
            {
                *pfOneDataHead = *pfDataHead;
                *pfMultiDataHead += *pfDataHead / BTS_AMPL_MIRROR_SECONDS;

                pfDataHead++;
                pfOneDataHead++;
                pfMultiDataHead++;
            }

            // 检查当前一秒频点的有效性
            if ((bySlotIndex % PUB_SYS_SLOT_NUM) == 3)
            {
                // 检查当前一秒频点的有效性
                bts_ampl_check_freq_valid(pstLocationData, pstBtsAmplMirrorData);
            }

            // 计算4秒镜像数据的最大值和最大值索引
            byRemainder = dwFrameNo % BTS_AMPL_MIRROR_FRAMES;
            if (byRemainder == 0)
            {
                wMaxValueIndex = util_looplist_find_max_value_index_flt32(pstBtsAmplMirrorData->afMultiSecondData, PUB_SIGNAL_SAMPLE_RATIO);
                fMaxValue = pstBtsAmplMirrorData->afMultiSecondData[wMaxValueIndex];

                // 保存最前幅度数据
                pstBtsMaxAmplData = &pstBtsMaxAmplDataList[i];
                pstBtsMaxAmplData->byFreqIndex = i;
                pstBtsMaxAmplData->fMaxValue = fMaxValue;
                pstBtsMaxAmplData->wMaxValueIndex = wMaxValueIndex;

                // 判断基站是否有效
                pstLocationData->byBtsValidFlag = 0;
                if (pstBtsAmplMirrorData->byAmplValidTimes > 1) // 两次有效
                {
                    pstLocationData->byBtsValidFlag = 1;
                }
            }
        }
    }

    //  当前帧需要对基站幅度进行排序
    byRemainder = dwFrameNo % BTS_AMPL_MIRROR_FRAMES;
    if (byRemainder == 0)
    {
        // 对基站幅度进行排序，最强排在前面
        bts_ampl_sort_max_ampl_list(pstBtsMaxAmplDataList);
    }

    return;
}

// 检查当前一秒频点的有效性
// pstLocationData:定位数据
// pstBtsAmplMirrorData:镜像数据
void bts_ampl_check_freq_valid(PUB_LOCATION_DATA_T *pstLocationData, BTS_AMPL_MIRROR_DATA_T *pstBtsAmplMirrorData)
{
    uint16 wStartIndex = 0;
    uint16 wMeanStartIndex = 0; // 计算均值

    flt32 fTmpValue = 0; // 临时变量
    flt32 *pfOneSecondData = NULL;

    flt32 fMaxValue = FLT_MIN; // FLT_MAX在系统库中有定义，最小值
    uint16 wMaxValueIndex = 0;

    int16 wIndexOffset = 0;

    flt32 fMinValue = FLT_MAX; // FLT_MAX在系统库中有定义，最大值
    uint16 wMinValueIndex = 0;

    flt32 fMeanValue = 0;              // 均值
    flt32 afDataNoiseList[1500] = {0}; // 计算噪声的队列
    flt32 fMiddleValue = 0;            // 中位数
    flt32 fFrameNoise = 0;             // 帧内噪声
    flt32 fSnr = 0;

    flt32 fAheadAmpl = pstLocationData->fCurrentMaxAmpl; // 前一次幅度

    ////1、计算1秒帧内最大值和最大值索引
    pfOneSecondData = pstBtsAmplMirrorData->afOneSecondData;
    wMaxValueIndex = util_looplist_find_max_value_index_flt32(pfOneSecondData, PUB_SIGNAL_SAMPLE_RATIO);
    fMaxValue = pfOneSecondData[wMaxValueIndex];
    pstBtsAmplMirrorData->fOneSecondMaxValue = fMaxValue;
    pstBtsAmplMirrorData->wOneSecondMaxValueIndex = wMaxValueIndex;

    ////2、在最大值索引左侧5000点内找一个最小值
    // 计算开始索引
    wIndexOffset = wMaxValueIndex - PUB_SYNC_INDEX_OFFSET_NUM;
    if (wIndexOffset >= 0)
    {
        wStartIndex = wIndexOffset;
    }
    else
    {
        wStartIndex = PUB_SIGNAL_SAMPLE_RATIO + wIndexOffset;
    }
    // 查找一个最小值，并镜像当前值
    for (uint16 j = 0; j < PUB_SYNC_INDEX_OFFSET_NUM; j++)
    {
        if (wStartIndex >= PUB_SIGNAL_SAMPLE_RATIO)
        {
            wStartIndex = 0;
        }

        fTmpValue = pstBtsAmplMirrorData->afOneSecondData[wStartIndex];
        if (fTmpValue < fMinValue)
        {
            fMinValue = fTmpValue;
            wMinValueIndex = wStartIndex;
        }
        wStartIndex++;
    }
    fMinValue *= 5; // 最小值放大5倍

    ////3、 计算最小值左侧1000点右侧500点的均值
    // 计算开始索引
    wIndexOffset = wMinValueIndex - 1000;
    if (wIndexOffset >= 0)
    {
        wStartIndex = wIndexOffset;
    }
    else
    {
        wStartIndex = PUB_SIGNAL_SAMPLE_RATIO + wIndexOffset;
    }

    // 计算均值
    fFrameNoise = 0;
    for (int16 k = 0; k < 1500; k++)
    {
        if (wStartIndex >= PUB_SIGNAL_SAMPLE_RATIO)
        {
            wStartIndex = 0;
        }

        // 计算均值
        fTmpValue = pstBtsAmplMirrorData->afOneSecondData[wStartIndex];
        fMeanValue += fTmpValue / 1500;
        wStartIndex++;

        // 保存当前值
        afDataNoiseList[k] = fTmpValue;
    }

    //// 计算中位数
    util_sort_flt32_asc(afDataNoiseList, 1500);
    fMiddleValue = afDataNoiseList[900]; // 6/10

    //// 4、计算帧内噪声
    fFrameNoise = fMeanValue > fMinValue ? fMeanValue : fMinValue;
    fFrameNoise = fFrameNoise > fMiddleValue ? fFrameNoise : fMiddleValue;
    fSnr = fMaxValue / fFrameNoise;

    ////5、检查频点有效性
    // 上一秒信号有效，则判断大值索引差值来检验当前信号是否有效
    if (pstLocationData->byCurrentAmplValidFlag)
    {
        if (fMaxValue > BTS_AMPL_BTS_AMPL_VALID_THRESHOLD && fMaxValue > (0.10 * fAheadAmpl) && fSnr > BTS_AMPL_BTS_SNR_VALID_THRESHOLD)
        {
            pstLocationData->byCurrentAmplValidFlag = 1;
            pstBtsAmplMirrorData->byAmplValidTimes++;
        }
        else
        {
            pstLocationData->byCurrentAmplValidFlag = 0;
        }
    }
    // 上一秒信号无效，则通过判断当前信号大值来检验当前信号是否有效
    else
    {
        // 通过幅度判断基站是否有效，信号幅度绝对值大于500
        if (fMaxValue > BTS_AMPL_BTS_AMPL_VALID_THRESHOLD && fSnr > BTS_AMPL_BTS_SNR_VALID_THRESHOLD)
        {
            pstLocationData->byCurrentAmplValidFlag = 1;
            pstBtsAmplMirrorData->byAmplValidTimes++;
        }
        else
        {
            pstLocationData->byCurrentAmplValidFlag = 0;
        }
    }

    // 更新上一次最大值和最大值索引
    pstLocationData->fCurrentMaxAmpl = fMaxValue;

    return;
}

// 对最强频点队列按照幅度大小倒排序
// pstBtsMaxAmplDataList:最强幅度队列
void bts_ampl_sort_max_ampl_list(BTS_MAX_AMPL_DATA_T *pstBtsMaxAmplDataList)
{
    BTS_MAX_AMPL_DATA_T stTmp = {0};

    // 按照信幅度倒排序，信噪比最大的站为主站
    for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
    {
        for (uint8 j = (i + 1); j < PUB_SYS_CARRIER_NUM; j++)
        {
            if (pstBtsMaxAmplDataList[i].fMaxValue < pstBtsMaxAmplDataList[j].fMaxValue)
            {
                stTmp = pstBtsMaxAmplDataList[i];
                pstBtsMaxAmplDataList[i] = pstBtsMaxAmplDataList[j]; // 数据交换
                pstBtsMaxAmplDataList[j] = stTmp;
            }
        }
    }

    return;
}
