// 秒寻科技
// 解调模块-主控。该模块负责对信号进行解调，输出各频点的定位数据
// zt
// 2023-03-03

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

//// 定义全局变量（仅在本模块中使用的全局变量）
// 系统载波频率
uint32 gDmdl_adwCarrierList[PUB_SYS_CARRIER_NUM] = {18200, 18800, 19400, 20000, 20600, 21200, 21800, 22400, 23000};

int16 *gDmdl_pwAudioDataList = NULL; // 音频采样数据存储地址

int16 gDmdl_awButterflyList[PUB_FFT_FRAME_LEN] = {0};       // FFT蝴蝶表
flt32 gDmdl_afFftRealList[PUB_FFT_FRAME_LEN] = {0};         // fft的实部
flt32 gDmdl_afFftImagList[PUB_FFT_FRAME_LEN] = {0};         // fft的虚部
uint32 gDmdl_adwFrequencyFactor[PUB_SYS_CARRIER_NUM] = {0}; // 频率因子
flt32 gDmdl_afTmpDataList[PUB_FFT_FRAME_LEN] = {0};         // 临时数据队列

flt32 gDmdl_afDdcRealList[PUB_FFT_FRAME_LEN] = {0}; // 变频结果的实部
flt32 gDmdl_afDdcImagList[PUB_FFT_FRAME_LEN] = {0}; // 变频结果的虚部

static flt32 gDmdl_fDdcFactor = 0; // 变频因子

DMDL_OVERLAP_DATA_T gDmdl_astOverlapDataList[PUB_SYS_CARRIER_NUM] = {0}; // 交叠缓存队列

// 导入全局变量
extern flt32 gDmdl_afFilter390Real[PUB_FFT_FRAME_LEN]; // 滤波器实部
extern flt32 gDmdl_afFilter390Imag[PUB_FFT_FRAME_LEN]; // 滤波器虚部
extern uint32 gg_dwFrameNo;                            // 全局定位数据帧号
extern uint32 gg_dwDdcIndex;

// 模块初始化
void dmdl_main_init()
{
    // 申请存储音频数据的内存
    gDmdl_pwAudioDataList = malloc(sizeof(int16) * PUB_SLOT_FRAME_LEN);
    memset(gDmdl_pwAudioDataList, 0, sizeof(int16) * PUB_SLOT_FRAME_LEN);

    // fft队列
    memset(gDmdl_afFftRealList, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);
    memset(gDmdl_afFftImagList, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);
    memset(gDmdl_adwFrequencyFactor, 0, sizeof(uint32) * PUB_SYS_CARRIER_NUM);

    // 变频数据队列
    memset(gDmdl_afDdcRealList, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);
    memset(gDmdl_afDdcImagList, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);

    // 蝴蝶表
    memset(gDmdl_awButterflyList, 0, sizeof(int16) * PUB_FFT_FRAME_LEN);

    gDmdl_fDdcFactor = (flt32)PUB_FFT_FRAME_LEN / PUB_SIGNAL_SAMPLE_RATIO;

    // 交叠数据
    memset(gDmdl_astOverlapDataList, 0, sizeof(DMDL_OVERLAP_DATA_T) * PUB_SYS_CARRIER_NUM);

    // 生成蝴蝶表
    util_fft_init_butterfly_table(PUB_FFT_FRAME_LEN, gDmdl_awButterflyList);
}

// 查询音频采样数据
int16 *dmdl_main_get_audio_sample_data()
{
    return (int16 *)gDmdl_pwAudioDataList;
}

// 信号解调主控。完成信号解调，输出定位数据
// pstLocationDataList:定位数据队列
void dmdl_main(PUB_LOCATION_DATA_T *pstLocationDataList)
{
    uint8 byFlag = 0;
    uint32 dwFrequency = 0;
    DMDL_OVERLAP_DATA_T *pstOverlapData = NULL;  // 交叠数据
    PUB_LOCATION_DATA_T *pstLocationData = NULL; // 定位数据

    // 正变换，所有频点共用该次变换结果
    dmdl_main_fft(gDmdl_pwAudioDataList, gDmdl_afFftRealList, gDmdl_afFftImagList, gDmdl_awButterflyList);

    //// 解调
    for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
    {
        memset(gDmdl_afDdcRealList, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);
        memset(gDmdl_afDdcImagList, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);

        // 变频处理
        dwFrequency = gDmdl_adwCarrierList[i]; // 载波频率
        dmdl_ddc_organize_data(dwFrequency, gDmdl_fDdcFactor, &gDmdl_adwFrequencyFactor[i], gDmdl_afFftRealList, gDmdl_afFftImagList, gDmdl_afDdcRealList, gDmdl_afDdcImagList);

        // 时域卷积(转换到频域做点乘)，结果保存在gDmdl_afDdcRealList和gDmdl_afDdcImagList队列中
        util_complex_sequence_multiply(PUB_FFT_FRAME_LEN, gDmdl_afDdcRealList, gDmdl_afDdcImagList, gDmdl_afFilter390Real, gDmdl_afFilter390Imag);

        // IFFT，变换结果保存在gDmdl_afDdcRealList和gDmdl_afDdcImagList队列中
        byFlag = (uint8)util_fft_ifft(PUB_FFT_FRAME_LEN, gDmdl_afDdcRealList, gDmdl_afDdcImagList, gDmdl_awButterflyList);
        if (!byFlag)
        {
            return;
        }

        // 交叠计算
        pstOverlapData = (DMDL_OVERLAP_DATA_T *)&gDmdl_astOverlapDataList[i];
        byFlag = dmdl_overlap(pstOverlapData, gDmdl_afDdcRealList, gDmdl_afDdcImagList, PUB_FFT_FRAME_LEN);
        if (byFlag != RET_OK)
        {
            return;
        }

        // 复数取模并将结果插入定位数据队列
        pstLocationData = (PUB_LOCATION_DATA_T *)&pstLocationDataList[i];
        dmdl_modulus(pstLocationData, gDmdl_afDdcRealList, gDmdl_afDdcImagList, DMDL_FFT_FRAME_PAYLOAD_LEN);
    }

    // 全局帧号加1
    gg_dwFrameNo++;

    // 将缓存复位
    memset(gDmdl_pwAudioDataList, 0, sizeof(int16) * PUB_SLOT_FRAME_LEN);

    return;
}

// 信号解调主控(老方案)。完成信号解调，输出定位数据
// pstLocationDataList:定位数据队列
void dmdl_main_old(PUB_LOCATION_DATA_T *pstLocationDataList)
{
    uint8 byFlag = 0;
    uint32 dwFrequency = 0;
    int16 *pwData = NULL;

    DMDL_OVERLAP_DATA_T *pstOverlapData = NULL;  // 交叠数据
    PUB_LOCATION_DATA_T *pstLocationData = NULL; // 定位数据

    //// 解调
    for (uint8 i = 0; i < PUB_SYS_CARRIER_NUM; i++)
    {
        memset(gDmdl_afDdcRealList, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);
        memset(gDmdl_afDdcImagList, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);

        // 变频
        pwData = gDmdl_pwAudioDataList;
        dwFrequency = gDmdl_adwCarrierList[i];
        dmdl_ddc(pwData, PUB_SLOT_FRAME_LEN, dwFrequency, gg_dwDdcIndex, gDmdl_afDdcRealList, gDmdl_afDdcImagList);

        // 正变换
        util_fft_fft(PUB_FFT_FRAME_LEN, gDmdl_afDdcRealList, gDmdl_afDdcImagList, gDmdl_awButterflyList);

        // 时域卷积(转换到频域做点乘)，结果保存在gDmdl_afDdcRealList和gDmdl_afDdcImagList队列中
        util_complex_sequence_multiply(PUB_FFT_FRAME_LEN, gDmdl_afDdcRealList, gDmdl_afDdcImagList, gDmdl_afFilter390Real, gDmdl_afFilter390Imag);

        // IFFT，变换结果保存在gDmdl_afDdcRealList和gDmdl_afDdcImagList队列中
        byFlag = (uint8)util_fft_ifft(PUB_FFT_FRAME_LEN, gDmdl_afDdcRealList, gDmdl_afDdcImagList, gDmdl_awButterflyList);
        if (!byFlag)
        {
            return;
        }

        // 交叠计算
        pstOverlapData = (DMDL_OVERLAP_DATA_T *)&gDmdl_astOverlapDataList[i];
        byFlag = dmdl_overlap(pstOverlapData, gDmdl_afDdcRealList, gDmdl_afDdcImagList, PUB_FFT_FRAME_LEN);
        if (byFlag != RET_OK)
        {
            return;
        }

        // 复数取模并将结果插入定位数据队列
        pstLocationData = (PUB_LOCATION_DATA_T *)&pstLocationDataList[i];
        dmdl_modulus(pstLocationData, gDmdl_afDdcRealList, gDmdl_afDdcImagList, DMDL_FFT_FRAME_PAYLOAD_LEN);
    }

    // 全局帧号加1
    gg_dwFrameNo++;
    gg_dwDdcIndex += PUB_SLOT_FRAME_LEN;

    // 将缓存复位
    memset(gDmdl_pwAudioDataList, 0, sizeof(int16) * PUB_SLOT_FRAME_LEN);

    return;
}

// 信号正变换
// pwData:音频采样数据
void dmdl_main_fft(int16 *pwData, flt32 *pfFftReal, flt32 *pfFftImag, int16 *pwButterflyList)
{
    int16 *pwDataHead = pwData;
    flt32 *pfFftDataHead = pfFftReal;

    // 组织数据
    memset(pfFftReal, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);
    memset(pfFftImag, 0, sizeof(flt32) * PUB_FFT_FRAME_LEN);
    for (uint16 i = 0; i < PUB_SLOT_FRAME_LEN; i++)
    {
        *pfFftDataHead = (flt32)(*pwDataHead);

        pfFftDataHead++;
        pwDataHead++;
    }

    // 正变换
    util_fft_fft(PUB_FFT_FRAME_LEN, pfFftReal, pfFftImag, pwButterflyList);

    return;
}

// 复数队列乘法
// pfSignalReal:信号实部
// pfSignalImag:信号虚部
// pfFilterReal:滤波器实部
// pfFilterImag:滤波器虚部
void dmdl_main_complex_sequence_multiply(flt32 *pfSignalReal, flt32 *pfSignalImag, flt32 *pfFilterReal, flt32 *pfFilterImag)
{
    flt32 fTmpReal = 0;
    flt32 fTmpImag = 0;

    // 队列头相乘
    for (uint16 i = 0; i < 103; i++)
    {
        fTmpReal = pfSignalReal[i] * pfFilterReal[i] - pfSignalImag[i] * pfFilterImag[i];
        fTmpImag = pfSignalReal[i] * pfFilterImag[i] + pfSignalImag[i] * pfFilterReal[i];

        pfSignalReal[i] = fTmpReal;
        pfSignalImag[i] = fTmpImag;
    }

    // 队列尾相乘
    for (uint16 j = (PUB_FFT_FRAME_LEN - 102); j < PUB_FFT_FRAME_LEN; j++)
    {
        fTmpReal = pfSignalReal[j] * pfFilterReal[j] - pfSignalImag[j] * pfFilterImag[j];
        fTmpImag = pfSignalReal[j] * pfFilterImag[j] + pfSignalImag[j] * pfFilterReal[j];

        pfSignalReal[j] = fTmpReal;
        pfSignalImag[j] = fTmpImag;
    }

    return;
}