// 秒寻科技
// 信号同步处理模块，负责实施时隙同步和比特同步
// zt
// 2023-03-12

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

// 导出全局变量
extern PUB_SYS_STATUS_T gg_stSysStatus;                     // 系统状态
extern flt32 gg_afOneFrameLocationData[PUB_SLOT_FRAME_LEN]; // 一帧临时定位数据
extern uint32 gg_dwFrameNo;                                 // 全局帧号

// 同步主控函数，负责同步处理，包括时隙同步和位同步
// pstLocationDataList:定位数据队列
// pstBtsAmplMirrorDataList:基站幅度镜像数据队列
// pstBtsMaxAmplDataList:最强幅度队列
void bts_sync_main(PUB_LOCATION_DATA_T *pstLocationDataList, BTS_AMPL_MIRROR_DATA_T *pstBtsAmplMirrorDataList, BTS_MAX_AMPL_DATA_T *pstBtsMaxAmplDataList)
{
    uint8 byValidFlag = 0; // 基站有效标识符

    PUB_LOCATION_DATA_T *pstLocationData = NULL;         // 一帧定位数据
    BTS_AMPL_MIRROR_DATA_T *pstBtsAmplMirrorData = NULL; // 基站幅度镜像数据
    BTS_MAX_AMPL_DATA_T *pstBtsMaxAmplData = NULL;       // 基站最强幅度数据
    uint8 byFreqIndex = 0;                               // 基站频率索引

    uint8 byMainFlag = 0;
    uint8 byMainBtsSlot = 0;
    uint8 bySlaveBtsSlot = 0;

    int32 dwMainBtsSyncIndex = 0;  // 主站同步索引(可正可负)
    int32 dwSlaveBtsSyncIndex = 0; // 从站同步索引(可正可负)

    int8 bySlotOffset = 0; // 时隙偏移

    uint32 dwFrameNo = 0;  // 当前帧号
    uint8 byRemainder = 0; // 取模余数

    // 该帧不需要任何处理
    dwFrameNo = gg_dwFrameNo - 1;
    if (dwFrameNo <= 0)
    {
        return;
    }

    // 该帧需要同步
    byRemainder = dwFrameNo % BTS_SYNC_STABLE_SYNC_FRAMES;
    if (byRemainder == 0)
    {
        // 检查是否存在有效基站
        bts_sync_check_valid_bts(pstBtsMaxAmplDataList, &byValidFlag);
        if (byValidFlag) // 存在有效基站
        {
            // 遍历每个载波，实施同步处理，包括时隙同步和位同步
            for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
            {
                pstBtsMaxAmplData = (BTS_MAX_AMPL_DATA_T *)&pstBtsMaxAmplDataList[i];       // 基站幅度按照幅度大小已经做了倒排序
                byFreqIndex = pstBtsMaxAmplData->byFreqIndex;                               // 频率索引
                pstLocationData = (PUB_LOCATION_DATA_T *)&pstLocationDataList[byFreqIndex]; // 基站定位数据

                // 定位站
                if (pstLocationData->byLctBtsFlag)
                {
                    // 主站（幅度最强站排在第一）
                    if (!byMainFlag)
                    {
                        // 解算信号时隙结构(仅做一次)
                        byMainBtsSlot = pstLocationData->bySetSlot;                                         // 主站配置时隙
                        dwMainBtsSyncIndex = pstBtsMaxAmplData->wMaxValueIndex - PUB_SYNC_INDEX_OFFSET_NUM; // 计算主站信号同步索引
                        if (!gg_stSysStatus.bySyncFlag)
                        {
                            bts_sync_cal_signal_slot(byMainBtsSlot, dwMainBtsSyncIndex, gg_stSysStatus.abySlotList);
                        }

                        // 计算基站时隙同步偏移（同步到0号时隙）
                        bts_sync_cal_slot_sync_offset(gg_stSysStatus.abySlotList, byMainBtsSlot, &bySlotOffset);
                        pstLocationData->dwSignalSlotSyncOffset = bySlotOffset * PUB_SLOT_FRAME_LEN; // 时隙同步

                        // 计算主站同步索引
                        dwMainBtsSyncIndex = bts_sync_cal_main_bts_sync_index(byMainBtsSlot, pstBtsMaxAmplData->wMaxValueIndex, gg_stSysStatus.abySlotList);

                        // 配置基站信号同步
                        bts_sync_set_bts_signal_sync(pstLocationData, dwMainBtsSyncIndex);

                        byMainFlag = 1; // 主站找到了
                    }
                    // 从站(从站跟随主站同步)
                    else
                    {
                        // 计算基站时隙同步偏移（同步到0号时隙）
                        bySlaveBtsSlot = pstLocationData->bySetSlot; // 从站配置时隙
                        bts_sync_cal_slot_sync_offset(gg_stSysStatus.abySlotList, bySlaveBtsSlot, &bySlotOffset);
                        pstLocationData->dwSignalSlotSyncOffset = bySlotOffset * PUB_SLOT_FRAME_LEN; // 时隙同步

                        // 计算从站位同步索引
                        pstBtsAmplMirrorData = (BTS_AMPL_MIRROR_DATA_T *)&pstBtsAmplMirrorDataList[byFreqIndex]; // 基站幅度镜像数据
                        dwSlaveBtsSyncIndex = bts_sync_cal_slave_bts_sync_index(pstLocationData, byMainBtsSlot, dwMainBtsSyncIndex, gg_stSysStatus.abySlotList, pstBtsAmplMirrorData->afMultiSecondData);

                        // 配置基站信号同步
                        bts_sync_set_bts_signal_sync(pstLocationData, dwSlaveBtsSyncIndex);
                    }
                }
            }

            if (!gg_stSysStatus.bySyncFlag)
            {
                gg_stSysStatus.bySyncFlag = 1; // 同步标识符置1
            }
        }
        // 没有检测到有效基站，系统进入初始状态
        else
        {
            // 复位信号同步偏移量
            for (uint8 j = 0; j < PUB_SYS_CARRIER_NUM; j++)
            {
                pstLocationData = &pstLocationDataList[j]; // 基站定位数据
                pstLocationData->dwSignalSyncIndex = 0;
            }

            if (gg_stSysStatus.bySyncFlag)
            {
                gg_stSysStatus.bySyncFlag = 0; // 清除同步标识符，以便再次同步
            }

            if (gg_stSysStatus.byBtsCaptureFlag)
            {
                gg_stSysStatus.byBtsCaptureFlag = 0; // 清除主站捕获标识符，以便再次捕获主站
            }

            printf("no valid bts \n");
        }
    }

    return;
}

// 检查是否存在有效基站（假设定位终端更靠近某一个基站，因此至少有一个基站的幅度值要非常大，才判断该组信号中存在一个有效基站）
// pstBtsMaxAmplDataList:基站最强幅度数据队列
// pbyValidFlag:有效标识符
void bts_sync_check_valid_bts(BTS_MAX_AMPL_DATA_T *pstBtsMaxAmplDataList, uint8 *pbyValidFlag)
{
    *pbyValidFlag = 0;
    for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
    {
        // 基站幅度大于主站幅度有效门限，表示当前手机靠近某个基站
        if (pstBtsMaxAmplDataList[i].fMaxValue > BTS_AMPL_MAIN_BTS_AMPL_VALID_THRESHOLD)
        {
            *pbyValidFlag = 1;
            break;
        }
    }

    return;
}

// 解算信号时隙
// byMainBtsSetSlot:主站配置时隙
// dwMainBtsFrameStartIndex:主站信号帧开始索引
// pbySignalSlotList:信号时隙队列，返回参数
void bts_sync_cal_signal_slot(uint8 byMainBtsSetSlot, int32 dwMainBtsFrameStartIndex, uint8 *pbySignalSlotList)
{
    uint8 byCounter = 0;
    int16 wPreSlotStartIndex = 0;

    // 主站信号帧开始索引为负
    if (dwMainBtsFrameStartIndex <= 0)
    {
        if (byMainBtsSetSlot == 0)
        {
            pbySignalSlotList[0] = byMainBtsSetSlot;
            pbySignalSlotList[1] = byMainBtsSetSlot + 1;
            pbySignalSlotList[2] = byMainBtsSetSlot + 2;
            pbySignalSlotList[3] = byMainBtsSetSlot + 3;
        }
        else if (byMainBtsSetSlot == 1)
        {
            pbySignalSlotList[0] = byMainBtsSetSlot;
            pbySignalSlotList[1] = byMainBtsSetSlot + 1;
            pbySignalSlotList[2] = byMainBtsSetSlot + 2;
            pbySignalSlotList[3] = byMainBtsSetSlot - 1;
        }
        else if (byMainBtsSetSlot == 2)
        {
            pbySignalSlotList[0] = byMainBtsSetSlot;
            pbySignalSlotList[1] = byMainBtsSetSlot + 1;
            pbySignalSlotList[2] = byMainBtsSetSlot - 2;
            pbySignalSlotList[3] = byMainBtsSetSlot - 1;
        }
        else if (byMainBtsSetSlot == 3)
        {
            pbySignalSlotList[0] = byMainBtsSetSlot;
            pbySignalSlotList[1] = byMainBtsSetSlot - 3;
            pbySignalSlotList[2] = byMainBtsSetSlot - 2;
            pbySignalSlotList[3] = byMainBtsSetSlot - 1;
        }
    }
    // 主站信号帧开始索引为负
    else
    {
        // 向左寻找信号的开始时隙
        for (uint8 i = 0; i < 3; i++)
        {
            wPreSlotStartIndex = dwMainBtsFrameStartIndex - (i + 1) * PUB_SLOT_FRAME_LEN;
            if (wPreSlotStartIndex >= -PUB_SYNC_INDEX_OFFSET_NUM)
            {
                byCounter++;
            }
            else
            {
                break;
            }
        }

        if (byMainBtsSetSlot == 0)
        {
            if (byCounter == 0)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot;
                pbySignalSlotList[1] = byMainBtsSetSlot + 1;
                pbySignalSlotList[2] = byMainBtsSetSlot + 2;
                pbySignalSlotList[3] = byMainBtsSetSlot + 3;
            }
            else if (byCounter == 1)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot + 3;
                pbySignalSlotList[1] = byMainBtsSetSlot;
                pbySignalSlotList[2] = byMainBtsSetSlot + 1;
                pbySignalSlotList[3] = byMainBtsSetSlot + 2;
            }
            else if (byCounter == 2)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot + 2;
                pbySignalSlotList[1] = byMainBtsSetSlot + 3;
                pbySignalSlotList[2] = byMainBtsSetSlot;
                pbySignalSlotList[3] = byMainBtsSetSlot + 1;
            }
            else if (byCounter == 3)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot + 1;
                pbySignalSlotList[1] = byMainBtsSetSlot + 2;
                pbySignalSlotList[2] = byMainBtsSetSlot + 3;
                pbySignalSlotList[3] = byMainBtsSetSlot;
            }
        }
        else if (byMainBtsSetSlot == 1)
        {
            if (byCounter == 0)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot;
                pbySignalSlotList[1] = byMainBtsSetSlot + 1;
                pbySignalSlotList[2] = byMainBtsSetSlot + 2;
                pbySignalSlotList[3] = byMainBtsSetSlot - 1;
            }
            else if (byCounter == 1)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot - 1;
                pbySignalSlotList[1] = byMainBtsSetSlot;
                pbySignalSlotList[2] = byMainBtsSetSlot + 1;
                pbySignalSlotList[3] = byMainBtsSetSlot + 2;
            }
            else if (byCounter == 2)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot + 2;
                pbySignalSlotList[1] = byMainBtsSetSlot - 1;
                pbySignalSlotList[2] = byMainBtsSetSlot;
                pbySignalSlotList[3] = byMainBtsSetSlot + 1;
            }
            else if (byCounter == 3)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot + 1;
                pbySignalSlotList[1] = byMainBtsSetSlot + 2;
                pbySignalSlotList[2] = byMainBtsSetSlot - 1;
                pbySignalSlotList[3] = byMainBtsSetSlot;
            }
        }
        else if (byMainBtsSetSlot == 2)
        {
            if (byCounter == 0)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot;
                pbySignalSlotList[1] = byMainBtsSetSlot + 1;
                pbySignalSlotList[2] = byMainBtsSetSlot - 2;
                pbySignalSlotList[3] = byMainBtsSetSlot - 1;
            }
            else if (byCounter == 1)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot - 1;
                pbySignalSlotList[1] = byMainBtsSetSlot;
                pbySignalSlotList[2] = byMainBtsSetSlot + 1;
                pbySignalSlotList[3] = byMainBtsSetSlot - 2;
            }
            else if (byCounter == 2)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot - 2;
                pbySignalSlotList[1] = byMainBtsSetSlot - 1;
                pbySignalSlotList[2] = byMainBtsSetSlot;
                pbySignalSlotList[3] = byMainBtsSetSlot + 1;
            }
            else if (byCounter == 3)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot + 1;
                pbySignalSlotList[1] = byMainBtsSetSlot - 2;
                pbySignalSlotList[2] = byMainBtsSetSlot - 1;
                pbySignalSlotList[3] = byMainBtsSetSlot;
            }
        }
        else if (byMainBtsSetSlot == 3)
        {
            if (byCounter == 0)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot;
                pbySignalSlotList[1] = byMainBtsSetSlot - 3;
                pbySignalSlotList[2] = byMainBtsSetSlot - 2;
                pbySignalSlotList[3] = byMainBtsSetSlot - 1;
            }
            else if (byCounter == 1)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot - 1;
                pbySignalSlotList[1] = byMainBtsSetSlot;
                pbySignalSlotList[2] = byMainBtsSetSlot - 3;
                pbySignalSlotList[3] = byMainBtsSetSlot - 2;
            }
            else if (byCounter == 2)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot - 2;
                pbySignalSlotList[1] = byMainBtsSetSlot - 1;
                pbySignalSlotList[2] = byMainBtsSetSlot;
                pbySignalSlotList[3] = byMainBtsSetSlot - 3;
            }
            else if (byCounter == 3)
            {
                pbySignalSlotList[0] = byMainBtsSetSlot - 3;
                pbySignalSlotList[1] = byMainBtsSetSlot - 2;
                pbySignalSlotList[2] = byMainBtsSetSlot - 1;
                pbySignalSlotList[3] = byMainBtsSetSlot;
            }
        }
    }
}

// 计算主站信号同步索引
// byMainBtsSetSlot:主站配置时隙
// dwMainBtsMaxIndex:主站最值大值索引
// pbySignalSoltList:信号时隙队列
int32 bts_sync_cal_main_bts_sync_index(uint8 byMainBtsSetSlot, int32 dwMainBtsMaxIndex, uint8 *pbySignalSoltList)
{
    uint8 byMainBtsSlotIndex = 0;
    int32 dwMainBtsSyncIndex = dwMainBtsMaxIndex - PUB_SYNC_INDEX_OFFSET_NUM;

    // 抽取时隙索引
    for (uint8 i = 0; i < PUB_SYS_SLOT_NUM; i++)
    {
        if (pbySignalSoltList[i] == byMainBtsSetSlot)
        {
            byMainBtsSlotIndex = i;
            break;
        }
    }

    //// 计算主站信号同步索引
    // 信号在0号时隙上
    if (byMainBtsSlotIndex == 0)
    {
        if (dwMainBtsMaxIndex > 3 * PUB_SLOT_FRAME_LEN)
        {
            // 修正主站信号同步索引
            dwMainBtsSyncIndex = PUB_SIGNAL_SAMPLE_RATIO - dwMainBtsMaxIndex - PUB_SYNC_INDEX_OFFSET_NUM;
        }
    }
    // 信号在3号时隙上
    else if (byMainBtsSlotIndex == (PUB_SYS_SLOT_NUM - 1))
    {
        if (dwMainBtsMaxIndex < PUB_SLOT_FRAME_LEN)
        {
            // 修正主站信号同步索引
            dwMainBtsSyncIndex = PUB_SIGNAL_SAMPLE_RATIO + dwMainBtsMaxIndex - PUB_SYNC_INDEX_OFFSET_NUM;
        }
    }

    return dwMainBtsSyncIndex;
}

// 计算从站信号同步索引
int32 bts_sync_cal_slave_bts_sync_index(PUB_LOCATION_DATA_T *pstLocationData, uint8 byMainBtsSlot, int32 dwMainBtsSyncIndex, uint8 *pbySignalSoltList, flt32 *pfData)
{
    int32 dwSlaveBtsSyncIndex = 0;                     // 从站信号同步索引
    uint8 bySlaveBtsSlot = pstLocationData->bySetSlot; // 从站配置时隙

    uint8 byMainBtsSlotIndex = 0;
    uint8 bySlaveBtsSlotIndex = 0;
    int8 bySlotGap = 0; // 主从站时隙间隔

    flt32 *pfHead = NULL; // 数据头指针
    int32 dwSlaveBtsStartIndex = 0;

    flt32 fTmpValue = 0;
    flt32 fMaxValue = 0;
    uint16 wSlaveBtsMaxValueIndex = 0;

    // 该基站是定位基站，并且该基站有效
    if (pstLocationData->byLctBtsFlag && pstLocationData->byBtsValidFlag)
    {
        // 从站时隙不合法
        if (bySlaveBtsSlot == PUB_SYS_SLOT_NUM)
        {
            bySlaveBtsSlot = byMainBtsSlot;
        }

        // 抽取时隙索引
        for (uint8 i = 0; i < PUB_SYS_SLOT_NUM; i++)
        {
            if (pbySignalSoltList[i] == byMainBtsSlot)
            {
                byMainBtsSlotIndex = i;
                if (byMainBtsSlot == bySlaveBtsSlot)
                {
                    bySlaveBtsSlotIndex = i;
                    break;
                }
            }
            else if (pbySignalSoltList[i] == bySlaveBtsSlot)
            {
                bySlaveBtsSlotIndex = i;
            }
        }

        // 从站相对于主站的时隙偏移量
        bySlotGap = bySlaveBtsSlotIndex - byMainBtsSlotIndex;

        // 1、计算从站同步索引
        //  主站从站时隙相同
        if (bySlaveBtsSlot == byMainBtsSlot)
        {
            dwSlaveBtsStartIndex = dwMainBtsSyncIndex;
        }
        // 主站从站时隙不同
        else
        {
            dwSlaveBtsStartIndex = dwMainBtsSyncIndex + bySlotGap * PUB_SLOT_FRAME_LEN;
            if (dwSlaveBtsStartIndex >= PUB_SIGNAL_SAMPLE_RATIO)
            {
                dwSlaveBtsStartIndex = dwSlaveBtsStartIndex % PUB_SIGNAL_SAMPLE_RATIO;
            }
            else if (dwSlaveBtsStartIndex < 0)
            {
                dwSlaveBtsStartIndex = PUB_SIGNAL_SAMPLE_RATIO + dwSlaveBtsStartIndex;
            }
        }

        ////3、 查找信号的最大值索引
        pfHead = &pfData[dwSlaveBtsStartIndex]; // 数据头指针
        for (uint16 i = 0; i < PUB_SLOT_FRAME_LEN; i++)
        {
            if (dwSlaveBtsStartIndex >= PUB_SIGNAL_SAMPLE_RATIO)
            {
                dwSlaveBtsStartIndex = 0;
                pfHead = &pfData[dwSlaveBtsStartIndex]; // 数据指针归0
            }

            fTmpValue = *pfHead;
            if (fTmpValue > fMaxValue)
            {
                fMaxValue = fTmpValue;
                wSlaveBtsMaxValueIndex = dwSlaveBtsStartIndex;
            }

            pfHead++;
            dwSlaveBtsStartIndex++;
        }

        //// 计算从站信号同步索引
        dwSlaveBtsSyncIndex = wSlaveBtsMaxValueIndex - PUB_SYNC_INDEX_OFFSET_NUM;
        // 信号在0号时隙上
        if (bySlaveBtsSlotIndex == 0)
        {
            if (wSlaveBtsMaxValueIndex > 3 * PUB_SLOT_FRAME_LEN)
            {
                // 修正从站信号同步索引
                dwSlaveBtsSyncIndex = PUB_SIGNAL_SAMPLE_RATIO - wSlaveBtsMaxValueIndex - PUB_SYNC_INDEX_OFFSET_NUM;
            }
        }
        // 信号在3号时隙上
        else if (bySlaveBtsSlotIndex == (PUB_SYS_SLOT_NUM - 1))
        {
            if (wSlaveBtsMaxValueIndex < PUB_SLOT_FRAME_LEN)
            {
                // 修正从站信号同步索引
                dwSlaveBtsSyncIndex = PUB_SIGNAL_SAMPLE_RATIO + wSlaveBtsMaxValueIndex - PUB_SYNC_INDEX_OFFSET_NUM;
            }
        }
    }
    // 基站无效，跟随主站调整
    else
    {
        dwSlaveBtsSyncIndex = dwMainBtsSyncIndex;
    }

    return dwSlaveBtsSyncIndex;
}

// 计算基站时隙同步偏移(相对于0号时隙的偏移)
// pbySignalSoltList:信号时隙队列
// byBtsSetSlot:基站配置时隙
// pbySlotOffset:时隙偏移
void bts_sync_cal_slot_sync_offset(uint8 *pbySignalSoltList, uint8 byBtsSetSlot, int8 *pbySlotOffset)
{
    uint8 byZeroSlotIndex = 0;
    uint8 byBtsSlotIndex = 0;
    int8 byIndexGap = 0; // 与0号时隙的的间隔

    // 抽取时隙索引
    for (uint8 i = 0; i < PUB_SYS_SLOT_NUM; i++)
    {
        if (pbySignalSoltList[i] == 0)
        {
            byZeroSlotIndex = i;
            if (byBtsSetSlot == 0)
            {
                byBtsSlotIndex = i;
                break;
            }
        }
        else if (pbySignalSoltList[i] == byBtsSetSlot)
        {
            byBtsSlotIndex = i;
        }
    }

    *pbySlotOffset = byZeroSlotIndex - byBtsSlotIndex; // 相对于0号时隙的偏移
}

// 配置基站信号同步
// pstLocationData:定位数据
// wBtsSyncIndex:基站同步索引
void bts_sync_set_bts_signal_sync(PUB_LOCATION_DATA_T *pstLocationData, int32 dwBtsSyncIndex)
{
    int32 dwSyncOffset = 0; // 同步偏移

    // 计算信号偏移量(第二个同步周期后方可计算同步偏移)
    if (pstLocationData->dwFrameNo > (BTS_SYNC_STABLE_SYNC_FRAMES + 1))
    {
        dwSyncOffset = dwBtsSyncIndex - pstLocationData->dwSignalSyncIndex;
    }

    // 调整帧内跟踪索引
    if (pstLocationData->wAheadFrameCalPahtIndex > 0)
    {
        pstLocationData->wAheadFrameCalPahtIndex -= dwSyncOffset;
    }

    // 调整帧内跟踪索引
    if (pstLocationData->wAheadFrameTrackPathIndex > 0)
    {
        pstLocationData->wAheadFrameTrackPathIndex -= dwSyncOffset;
    }

    // 修改信号同步索引
    pstLocationData->dwSignalSyncIndex = dwBtsSyncIndex;

    return;
}