// 周涛 2023-02-08
// 基于传感器参数计算位移

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

// 定义模块所需的全局变量
static IMU_INIT_PARAM_T gImu_stInitParam = {0}; // 模块初始化参数

uint8 *pgImu_byAccDataList = NULL;                       // 加速度数据队列(存储js模块注入的加速度)
static flt32 gImu_afAccDataList[IMU_ACC_LIST_LEN] = {0}; // 加速度点列表
static uint8 gImu_byGenerateIndex = 0;                   // 生产索引
static uint8 gImu_byConsumeIndex = 0;                    // 消费索引
static uint8 gImu_byRunFlag = 0;                         // 系统正常运行标识符，0：初始化，1：正常运行

// 模块初始化
void imu_init()
{
    pgImu_byAccDataList = (uint8 *)malloc(IMU_ACC_LIST_SIZE); // 申请一片内存，用于存储js注入的加速度数据队列

    gImu_byRunFlag = 0; // 初始化状态
    memset(&gImu_stInitParam, 0, sizeof(IMU_INIT_PARAM_T));
    memset(&gImu_afAccDataList, 0, sizeof(flt32) * IMU_ACC_LIST_LEN);

    // 加速度噪声
    gImu_stInitParam.fNoiseX = -0.0057304;
    gImu_stInitParam.fNoiseY = 0.047326;  // 0.057326
    gImu_stInitParam.fNoiseZ = -0.015313; //-0.984687

    // 选峰参数
    gImu_stInitParam.dwPeakPeakDistance = 35; // 35; // 峰间距
    gImu_stInitParam.dwPeakValueThres = 102;  // 102; // 峰值门限

    printf("imu init ok \n");

    return;
}

// 释放内存
void imu_free_memory()
{
    if (!pgImu_byAccDataList)
    {
        free(pgImu_byAccDataList);
        pgImu_byAccDataList = NULL;
    }
}

// 查询加速度存储地址(exchange模块使用)
int32 *imu_get_acc_address_exchange()
{
    return (int32 *)pgImu_byAccDataList;
}

// 保存加速度(exchange模块使用)
void imu_save_acc_list_exchange()
{
    uint32 dwAccListLen = 0;

    // 获得数队列长度
    memcpy(&dwAccListLen, (uint32 *)pgImu_byAccDataList, 4);
    imu_save_acc_xyz(dwAccListLen);
    memset(pgImu_byAccDataList, 0, IMU_ACC_LIST_SIZE); // 清空数据缓存
}

// 保存加速度
// fAccX:X轴加速度
// fAccY:Y轴加速度
// fAccZ:Z轴加速度
// dwTimestamp:时间戳
void imu_save_acc_xyz(uint32 dwAccListLen)
{
    IMU_ACC_DATA_T *pstAccData = NULL;

    flt32 fAccX = 0;
    flt32 fAccY = 0;
    flt32 fAccZ = 0;
    flt32 fAccTotal = 0; // 三轴加速度之和

    // 加速度队列
    pstAccData = (IMU_ACC_DATA_T *)(pgImu_byAccDataList + 4);
    for (uint32 i = 0; i < dwAccListLen; i++)
    {
        fAccX = pstAccData->fAccX - gImu_stInitParam.fNoiseX;
        fAccY = pstAccData->fAccY - gImu_stInitParam.fNoiseY;
        fAccZ = pstAccData->fAccZ - gImu_stInitParam.fNoiseZ;
        fAccTotal = fAccX * fAccX + fAccY * fAccY + fAccZ * fAccZ;
        fAccTotal = sqrt(fAccTotal); // 合加速度
        gImu_afAccDataList[gImu_byGenerateIndex] = fAccTotal;
        pstAccData++;

        // 生产索引加1
        gImu_byGenerateIndex++;
    }

    // 运行标识符置位
    if (!gImu_byRunFlag)
    {
        if (gImu_byGenerateIndex > 60)
        {
            gImu_byRunFlag = 1;
        }
    }

    return;
}

// 计算位移(定位模块使用)
// 返回值，0：失败，1：成功，静止，50：成功，移动
uint32 imu_cal_distance_lct()
{
    uint8 byMoveFlag = 0;
    uint8 byEndIndex = 0;

    if (!gImu_byRunFlag)
    {
        return 0;
    }

    // 计算位移
    byMoveFlag = imu_cal_distance();
    return byMoveFlag;
}

// 计算位移
// 返回值，0：失败，1：成功，静止，50：成功，移动
uint32 imu_cal_distance()
{
    uint8 byResult = 0;
    uint32 dwStartTimestamp = 0;                            // 开始时间戳头，队列往前推1.25秒
    flt32 afAccDataList[IMU_ACC_LIST_ONE_SECOND_LEN] = {0}; // 有效加速度点队列（1秒）
    uint8 byAccDataListLen = 0;                             // 有效加速度点队列长度

    uint8 byPeakValueIndexListLen = 0;

    uint8 byMoveFlag = 0;

    // 系统处于初始化阶段
    if (!gImu_byRunFlag)
    {
        return 0;
    }

    memset(afAccDataList, 0, sizeof(flt32) * IMU_ACC_LIST_ONE_SECOND_LEN);

    // 选择加速度
    byResult = imu_select_acc_xyz(afAccDataList, &byAccDataListLen);
    if (!byResult || byAccDataListLen <= 0)
    {
        return 0;
    }

    // 判断加速度是否超过移动门限值
    byResult = imu_check_max_acc(afAccDataList, byAccDataListLen, &byMoveFlag);
    if (!byResult)
    {
        return 0;
    }

    // 检查移动标识
    if (byMoveFlag)
    {
        return 50; // 成功，但移动
    }

    return 1; // 成功，但静止
}

// 选择加速度点集
// pfValidAccDataList:有效加速度队列，返回参数
// pfValidAccDataListLen:有效加速度队列长度，返回参数
uint8 imu_select_acc_xyz(flt32 *pfValidAccDataList, uint8 *pfValidAccDataListLen)
{
    flt32 *pfData = gImu_afAccDataList; // 加速度数据队列
    uint8 byCounter = 0;                // 有效加速度计数器

    // 容错处理
    if (pfValidAccDataList == NULL || pfValidAccDataListLen == NULL)
    {
        return 0;
    }

    // 遍历队列，选择当前窗口内的加速度(全部)
    while (gImu_byConsumeIndex != gImu_byGenerateIndex)
    {
        pfValidAccDataList[byCounter] = pfData[gImu_byConsumeIndex];
        byCounter++;

        if (byCounter >= IMU_ACC_LIST_ONE_SECOND_LEN)
        {
            gImu_byConsumeIndex++;
            break;
        }
        gImu_byConsumeIndex++;
    }

    *pfValidAccDataListLen = byCounter;

    return 1;
}

// 检查加最大速度是否超过门限值
// pfAccDataList:加速度队列
// byListLen:加速度队列长度
// pbyMoveFlag:移动标识符，1:移动，0:不移动
uint8 imu_check_max_acc(flt32 *pfAccDataList, uint8 byListLen, uint8 *pbyMoveFlag)
{
    flt32 fMaxValue = FLT_MIN;
    flt32 fThres = (flt32)gImu_stInitParam.dwPeakValueThres / 100; // 峰值门限

    if (pfAccDataList == NULL || byListLen <= 0 || pbyMoveFlag == NULL)
    {
        return 0;
    }

    // 查找加速度最大值
    for (uint8 i = 0; i < byListLen; i++)
    {
        if (pfAccDataList[i] > fMaxValue)
        {
            fMaxValue = pfAccDataList[i];
        }
    }

    // 判断加速度是否超过门限
    if (fMaxValue > fThres)
    {
        *pbyMoveFlag = 1; // 有移动
    }
    else
    {
        *pbyMoveFlag = 0; // 静止
    }

    return 1;
}
