/*
 * @Author: mypx
 * @Date: 2025-08-11 08:30:53
 * @LastEditTime: 2025-10-24 17:11:50
 * @LastEditors: mypx mypx_coder@163.com
 * @Description: 
 */
#ifndef __PM_MEAS_H__
#define __PM_MEAS_H__
#include "et_goertzel.h"
#include "et_zero_cross.h"
#include "etk_pid.h"
#include "etk_slope.h"
#include "pm_common.h"

#define FZ_CALI_MAX_COUNT       4
#define ZC_COUNT_STABLE_TIMES   5
#define ZERO_POS_THRESHOLD      1.0f
#define PID_TARGET_ZERO_POS_VAL 0.0f
#define RUN_OFFSET_ANGLE_RPM    (1000)


#define FZ_UNKNOWN_STAGE_RPM      2000
#define FZ_SATURATED_STAGE_RPM    2000
#define FZ_WAVE_ENTER_STAGE_RPM   2000
#define FZ_PREPARE_STAGE_RPM      2000
#define FZ_FAST_CLOSE_STAGE_RPM   1400
#define FZ_PRECISE_ADJUST_MIN_RPM (0.6f * MOTOR_TO_ENCODER_FACTOR) // 0.6rpm->0.001

#define FZ_SATURATED_POWER_MAX 5.0f
#define FZ_SATURATED_SLOPE_MAX 50.0f


#define FZ_FAST_CLOSE_ENTER_FREQ_MIN 48.0f
#define FZ_FAST_CLOSE_ENTER_FREQ_MAX 52.0f

#define FZ_PRECISE_ADJUST_LEAVE_POWER_MAX FZ_PRECISE_ADJUST_ENTER_POWER_MAX

#define FZ_PREPARE_LEAVE_SLOPE_MIN -100000
#define FZ_PREPARE_LEAVE_FREQ_MIN  48.0f
#define FZ_PREPARE_LEAVE_FREQ_MAX  52.0f

typedef enum
{
    TREND_UNKNOWN = 0, // 未知（首次调用，无历史数据）
    TREND_STABLE,      // 稳定（无连续6次升/降，或当前值与上次相等）
    TREND_INCREASE,    // 上升（连续6次大于上次值）
    TREND_DECREASE     // 下降（连续6次小于上次值）
} TrendStatus;
#define TREND_MAX_CNT 20

typedef enum
{
    ZF_UNKNOWN_STAGE = 0,
    ZF_SATURATED_STAGE,
    ZF_WAVE_ENTER_STAGE,    // little magnitude 50hz wave detected
    ZF_PREPARE_ENTER_STAGE, // big magnitude 50hz wave detected
    ZF_FAST_CLOSE_STAGE,    // near zero, fast close
    ZF_ZERO_STAGE,          // zero found, and judgement next setup
    ZF_FAST_LEAVE_STAGE,
    ZF_PREPARE_LEAVE_STAGE, // ZF_PREPARE_ENTER_STAGE->ZF_WAVE_ENTER_STAGE or ZF_WAVE_ENTER_STAGE->ZF_SATURATED_STAGE
    ZF_WAVE_LEAVE_STAGE,
    ZF_STATE_MAX,
} ZeroFindState;

typedef enum
{
    PM_FSM_STOP = 0,
    PM_FSM_RUNNING,
} FzFsmState;

typedef struct
{
    double  last_val;
    uint8_t inc_cnt;
    uint8_t dec_cnt;
} trend_handle_t;

typedef enum
{
    STAGE_RESULT_NO,
    STAGE_RESULT_OK,
    STAGE_RESULT_UNDETERMINED,
} StageResult;

typedef struct
{
    uint8_t  is_updated : 1;
    uint8_t  is_print   : 1;
    float    angle;
    double   p50;
    float    slope;
    float    freq;
    uint32_t time; // enter time(ms)
} fz_stage_t;

typedef struct
{
    uint32_t start_time; // ms
    uint32_t end_time;   // ms
    float    angle;      // zero pos
    float    target_angle;
    float    power;
    float    cali_angle;
    int8_t   m_dir;
} calib_info_t;

typedef struct
{
    ZeroFindState state;

    fz_stage_t stage_info[ZF_STATE_MAX];

    uint8_t      calib_cnt;
    int          target_dir; //  1: forward, -1: backward
    calib_info_t calib_info[FZ_CALI_MAX_COUNT];

    uint8_t              zero_stable_count;
    et_zero_cross_t      zc;
    et_goertzel_config_t cfg;
    etk_pos_pid_t        pid;
    double               p50;
    float                freq;
    etk_slope_t          slope_handle;
    float                slope;
    double               last_p50_slope;
    TrendStatus          trend;
    trend_handle_t       trend_handle;
} pm_meas_t;

typedef struct
{
    FzFsmState fz_fsm_state;
    pm_meas_t   meas;
    PmMeasMode meas_mode;
} pm_fsm_t;

ZeroFindState get_find_zero_state(pm_meas_t *fz);

void trend_handle_init(trend_handle_t *handle);


int find_zero_process(pm_meas_t *fz, const uint16_t *adc_val, uint32_t len);

int pm_fsm_init(pm_fsm_t *fsm);

pm_fsm_t *get_pm_fsm(void);

#endif
