/*
 * @Author: mypx
 * @Date: 2025-08-21 10:11:11
 * @LastEditTime: 2025-08-27 17:13:37
 * @LastEditors: mypx mypx_coder@163.com
 * @Description: 
 * This module provides functions to detect zero-crossings in
 * sampled signals, with optional DC offset removal and linear
 * interpolation for more accurate crossing positions.
 *
 * Supports both floating-point and unsigned 16-bit integer input.
 */
#ifndef __ET_ZERO_CROSS_H__
#define __ET_ZERO_CROSS_H__
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

// Constants definition
#define ET_ZERO_CROSS_EPSILON             1e-10f // Epsilon for float comparison
#define ET_ZERO_CROSS_DEFAULT_LOW_THRESH  0.5f   // Default lower threshold
#define ET_ZERO_CROSS_DEFAULT_HIGH_THRESH 1.5f   // Default upper threshold
#define ET_ZERO_CROSS_MIN_THRESH          0.1f   // Minimum allowed threshold
#define ET_ZERO_CROSS_MAX_THRESH          5.0f   // Maximum allowed threshold

typedef struct
{
    uint16_t val;
    double   angle;
    uint32_t time;
} et_zc_point_t;

typedef struct
{
    uint32_t count;   // Number of zero crossings
    float   *pos_buf; // Multi-purpose buffer for positions and intervals

    float   *interval_buf;
    uint32_t max_pos_size;
    float    thresh_low;  // Lower threshold multiplier for outlier rejection (default: 0.5)
    float    thresh_high; // Upper threshold multiplier for outlier rejection (default: 1.5)
} et_zero_cross_t;

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * @brief Count zero crossings (uint16_t input)
 * @param data   Pointer to input uint16_t array
 * @param length Number of samples
 * @param offset DC offset to subtract
 * @return int   Number of zero crossings
 */
uint32_t et_zero_cross_count_u16(const uint16_t *data, uint32_t length, uint16_t offset);

/**
 * @brief Detect zero-crossing positions with interpolation (uint16_t input)
 * @param zc     Pointer to et_zero_cross_t structure for storing results
 * @param data   Pointer to input uint16_t array
 * @param length Number of samples
 * @param offset DC offset to subtract
 * @return int   Number of zero crossings detected
 */
uint32_t et_zero_cross_pos_u16(et_zero_cross_t *zc, const uint16_t *data, uint32_t length, uint16_t offset);

/**
 * @brief Estimate signal frequency using zero-crossing method (uint16_t input)
 * @param zc            Pointer to et_zero_cross_t structure for storing results
 * @param data          Pointer to input uint16_t array
 * @param length        Number of samples
 * @param sampling_rate Sampling rate in Hz
 * @param offset        DC offset to subtract
 * @return float        Estimated frequency in Hz
 */
float et_zero_cross_freq_u16(et_zero_cross_t *zc, const uint16_t *data, uint32_t length, float sampling_rate,
                             uint16_t offset);

/**
 * @brief Enhanced frequency estimation with median filtering and outlier rejection (uint16_t input)
 * @param zc            Pointer to et_zero_cross_t structure for storing results
 * @param data          Pointer to input uint16_t array
 * @param length        Number of samples
 * @param sampling_rate Sampling rate in Hz
 * @param offset        DC offset to subtract
 * @return float        Estimated frequency in Hz
 */
float et_zero_cross_freq_u16_ex(et_zero_cross_t *zc, const uint16_t *data, uint32_t length, float sampling_rate,
                                uint16_t offset);

/**
 * @brief Count zero-crossings in floating-point data.
 * @param data   Input data array
 * @param length Number of samples
 * @param offset DC offset to subtract from each sample
 * @return int   Number of zero-crossings detected
 */
uint32_t et_zero_cross_count_f32(const float *data, uint32_t length, float offset);

/**
 * @brief Detect zero-crossing positions with interpolation (float input)
 * @param zc     Pointer to et_zero_cross_t structure for storing results
 * @param data   Pointer to input float array
 * @param length Number of samples
 * @param offset DC offset to subtract
 * @return int   Number of zero crossings detected
 */
uint32_t et_zero_cross_pos_f32(et_zero_cross_t *zc, const float *data, uint32_t length, float offset);

/**
 * @brief Estimate signal frequency using zero-crossing method (float input)
 * @param zc            Pointer to et_zero_cross_t structure for storing results
 * @param data          Pointer to input float array
 * @param length        Number of samples
 * @param sampling_rate Sampling rate in Hz
 * @param offset        DC offset to subtract
 * @return float        Estimated frequency in Hz
 */
float et_zero_cross_freq_f32(et_zero_cross_t *zc, const float *data, uint32_t length, float sampling_rate,
                             float offset);

/**
 * @brief Enhanced frequency estimation with median filtering and outlier rejection (float input)
 * @param zc            Pointer to et_zero_cross_t structure for storing results
 * @param data          Pointer to input float array
 * @param length        Number of samples
 * @param sampling_rate Sampling rate in Hz
 * @param offset        DC offset to subtract
 * @return float        Estimated frequency in Hz
 */
float et_zero_cross_freq_f32_ex(et_zero_cross_t *zc, const float *data, uint32_t length, float sampling_rate,
                                float offset);

/**
 * @brief Count zero crossings (uint32_t input)
 * @param data   Pointer to input uint32_t array
 * @param length Number of samples
 * @param offset DC offset to subtract
 * @return int   Number of zero crossings
 */
uint32_t et_zero_cross_count_u32(const uint32_t *data, uint32_t length, uint32_t offset);

/**
 * @brief Detect zero-crossing positions with interpolation (uint32_t input)
 * @param zc     Pointer to et_zero_cross_t structure for storing results
 * @param data   Pointer to input uint32_t array
 * @param length Number of samples
 * @param offset DC offset to subtract
 * @return int   Number of zero crossings detected
 */
uint32_t et_zero_cross_pos_u32(et_zero_cross_t *zc, const uint32_t *data, uint32_t length, uint32_t offset);

/**
 * @brief Estimate signal frequency using zero-crossing method (uint32_t input)
 * @param zc            Pointer to et_zero_cross_t structure for storing results
 * @param data          Pointer to input uint32_t array
 * @param length        Number of samples
 * @param sampling_rate Sampling rate in Hz
 * @param offset        DC offset to subtract
 * @return float        Estimated frequency in Hz
 */
float et_zero_cross_freq_u32(et_zero_cross_t *zc, const uint32_t *data, uint32_t length, float sampling_rate,
                             uint32_t offset);

/**
 * @brief Enhanced frequency estimation with median filtering and outlier rejection (uint32_t input)
 * @param zc            Pointer to et_zero_cross_t structure for storing results
 * @param data          Pointer to input uint32_t array
 * @param length        Number of samples
 * @param sampling_rate Sampling rate in Hz
 * @param offset        DC offset to subtract
 * @return float        Estimated frequency in Hz
 */
float et_zero_cross_freq_u32_ex(et_zero_cross_t *zc, const uint32_t *data, uint32_t length, float sampling_rate,
                                uint32_t offset);

/**
 * @brief Create and initialize a zero cross detector
 * @param zc     Pointer to et_zero_cross_t structure
 * @param max_pos Maximum number of zero crossing positions to store
 * @return int   0 on success, -1 on failure
 */
int et_zero_cross_create(et_zero_cross_t *zc, uint32_t max_pos);

/**
 * @brief Destroy a zero cross detector and free its resources
 * @param zc     Pointer to et_zero_cross_t structure
 */
void et_zero_cross_destroy(et_zero_cross_t *zc);

/**
 * @brief Count zero crossings (et_zc_point_t input)
 * @param point  Pointer to input et_zc_point_t array
 * @param length Number of samples
 * @param offset DC offset to subtract
 * @return int   Number of zero crossings
 */
uint32_t et_zero_cross_count_point(const et_zc_point_t *point, uint32_t length, uint16_t offset);

/**
 * @brief Detect zero-crossing positions with interpolation (et_zc_point_t input)
 * @param zc     Pointer to et_zero_cross_t structure for storing results
 * @param point  Pointer to input et_zc_point_t array
 * @param length Number of samples
 * @param offset DC offset to subtract
 * @return int   Number of zero crossings detected
 */
uint32_t et_zero_cross_pos_point(et_zero_cross_t *zc, const et_zc_point_t *point, uint32_t length, uint16_t offset);

/**
 * @brief Estimate signal frequency using zero-crossing method (et_zc_point_t input)
 * @param zc            Pointer to et_zero_cross_t structure for storing results
 * @param point         Pointer to input et_zc_point_t array
 * @param length        Number of samples
 * @param sampling_rate Sampling rate in Hz
 * @param offset        DC offset to subtract
 * @return float        Estimated frequency in Hz
 */
float et_zero_cross_freq_point(et_zero_cross_t *zc, const et_zc_point_t *point, uint32_t length, uint16_t offset);

/**
 * @brief Enhanced frequency estimation with median filtering and outlier rejection (et_zc_point_t input)
 * @param zc            Pointer to et_zero_cross_t structure for storing results
 * @param point         Pointer to input et_zc_point_t array
 * @param length        Number of samples
 * @param offset        DC offset to subtract
 * @return float        Estimated frequency in Hz
 */
float et_zero_cross_freq_point_ex(et_zero_cross_t *zc, const et_zc_point_t *point, uint32_t length, uint16_t offset);

/**
 * @brief Set threshold multipliers for outlier rejection
 * @param zc          Pointer to et_zero_cross_t structure
 * @param thresh_low  Lower threshold multiplier (relative to median)
 * @param thresh_high Upper threshold multiplier (relative to median)
 * @return int        0 on success, -1 on failure
 */
int et_zero_cross_set_threshold(et_zero_cross_t *zc, float thresh_low, float thresh_high);

#ifdef __cplusplus
}
#endif

#endif // ET_ZERO_CROSS_H
