/*
  各类滤波器。
*/

#include "filter.h"

#include "user_math.h"

/**
 * @brief 初始化滤波器
 *
 * @param f 滤波器
 * @param sample_freq 采样频率
 * @param cutoff_freq 截止频率
 */
void LowPassFilter2p_Init(LowPassFilter2p_t *f, float sample_freq,
                          float cutoff_freq) {
  if (f == NULL) return;

  f->cutoff_freq = cutoff_freq;

  f->delay_element_1 = 0.0f;
  f->delay_element_2 = 0.0f;

  if (f->cutoff_freq <= 0.0f) {
    /* no filtering */
    f->b0 = 1.0f;
    f->b1 = 0.0f;
    f->b2 = 0.0f;

    f->a1 = 0.0f;
    f->a2 = 0.0f;

    return;
  }
  const float fr = sample_freq / f->cutoff_freq;
  const float ohm = tanf(M_PI / fr);
  const float c = 1.0f + 2.0f * cosf(M_PI / 4.0f) * ohm + ohm * ohm;

  f->b0 = ohm * ohm / c;
  f->b1 = 2.0f * f->b0;
  f->b2 = f->b0;

  f->a1 = 2.0f * (ohm * ohm - 1.0f) / c;
  f->a2 = (1.0f - 2.0f * cosf(M_PI / 4.0f) * ohm + ohm * ohm) / c;
}

/**
 * @brief 施加一次滤波计算
 *
 * @param f 滤波器
 * @param sample 采样的值
 * @return float 滤波后的值
 */
float LowPassFilter2p_Apply(LowPassFilter2p_t *f, float sample) {
  if (f == NULL) return 0.0f;

  /* do the filtering */
  float delay_element_0 =
      sample - f->delay_element_1 * f->a1 - f->delay_element_2 * f->a2;

  if (isinf(delay_element_0)) {
    /* don't allow bad values to propagate via the filter */
    delay_element_0 = sample;
  }

  const float output = delay_element_0 * f->b0 + f->delay_element_1 * f->b1 +
                       f->delay_element_2 * f->b2;

  f->delay_element_2 = f->delay_element_1;
  f->delay_element_1 = delay_element_0;

  /* return the value. Should be no need to check limits */
  return output;
}

/**
 * @brief 重置滤波器
 *
 * @param f 滤波器
 * @param sample 采样的值
 * @return float 滤波后的值
 */
float LowPassFilter2p_Reset(LowPassFilter2p_t *f, float sample) {
  if (f == NULL) return 0.0f;

  const float dval = sample / (f->b0 + f->b1 + f->b2);

  if (isfinite(dval)) {
    f->delay_element_1 = dval;
    f->delay_element_2 = dval;

  } else {
    f->delay_element_1 = sample;
    f->delay_element_2 = sample;
  }

  return LowPassFilter2p_Apply(f, sample);
}

/**
 * @brief 初始化滤波器
 *
 * @param f 滤波器
 * @param sample_freq 采样频率
 * @param notch_freq 中心频率
 * @param bandwidth 带宽
 */
void NotchFilter_Init(NotchFilter_t *f, float sample_freq, float notch_freq,float bandwidth) 
{
  if (f == NULL) return;

  f->notch_freq = notch_freq;
  f->bandwidth = bandwidth;

  f->delay_element_1 = 0.0f;
  f->delay_element_2 = 0.0f;

  if (notch_freq <= 0.0f) {
    /* no filtering */
    f->b0 = 1.0f;
    f->b1 = 0.0f;
    f->b2 = 0.0f;

    f->a1 = 0.0f;
    f->a2 = 0.0f;

    return;
  }

  const float alpha = tanf(M_PI * bandwidth / sample_freq);
  const float beta = -cosf(M_2PI * notch_freq / sample_freq);
  const float a0_inv = 1.0f / (alpha + 1.0f);

  f->b0 = a0_inv;
  f->b1 = 2.0f * beta * a0_inv;
  f->b2 = a0_inv;

  f->a1 = f->b1;
  f->a2 = (1.0f - alpha) * a0_inv;
}

/**
 * @brief 施加一次滤波计算
 *
 * @param f 滤波器
 * @param sample 采样的值
 * @return float 滤波后的值
 */
inline float NotchFilter_Apply(NotchFilter_t *f, float sample) {
  if (f == NULL) return 0.0f;

  /* Direct Form II implementation */
  const float delay_element_0 = sample - f->delay_element_1 * f->a1 - f->delay_element_2 * f->a2;
  const float output = delay_element_0 * f->b0 + f->delay_element_1 * f->b1 +
                       f->delay_element_2 * f->b2;

  f->delay_element_2 = f->delay_element_1;
  f->delay_element_1 = delay_element_0;

  return output;
}

/**
 * @brief 重置滤波器
 *
 * @param f 滤波器
 * @param sample 采样的值
 * @return float 滤波后的值
 */
float NotchFilter_Reset(NotchFilter_t *f, float sample) {
  if (f == NULL) return 0.0f;

  float dval = sample;

  if (fabsf(f->b0 + f->b1 + f->b2) > FLT_EPSILON) {
    dval = dval / (f->b0 + f->b1 + f->b2);
  }

  f->delay_element_1 = dval;
  f->delay_element_2 = dval;

  return NotchFilter_Apply(f, sample);
}
