/* SPDX-License-Identifier: LGPL-2.1-or-later
 *
 * Frv - Frame vector library
 *
 * Copyright © 2001-2021 Laboratoire d'Annecy de physique des particules - CNRS
 * Copyright © 2019-2021 Institut pluridisciplinaire Hubert CURIEN - CNRS
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef FRVFILTER
#define FRVFILTER

#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#endif
/*---------------------------------------------------------------------------*/
/*  FrvFilter.h                                                              */
/*---------------------------------------------------------------------------*/

#include "FrameL.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct FrvFilter2 FrvFilter2;
typedef struct FrvFilterB FrvFilterB;

struct FrvFilter2 {
  double a0;                 /* filter coefficients (see definition below)   */
  double a1;                 /* filter coefficients (see definition below)   */
  double a2;                 /* filter coefficients (see definition below)   */
  double b0;                 /* filter coefficients (see definition below)   */
  double b1;                 /* filter coefficients (see definition below)   */
  double b2;                 /* filter coefficients (see definition below)   */
  double reg0;               /* internal registers                           */
  double reg1;               /* internal registers                           */
  double reg2;               /* internal registers                           */
  double alfa0;              /* internal coefficients                        */
  double alfa1;              /* internal coefficients                        */
  double alfa2;              /* internal coefficients                        */
  double beta0;              /* internal coefficients                        */
  double beta1;              /* internal coefficients                        */
  double beta2;              /* internal coefficients                        */
  FrVect *output;            /* vector to hold the last data chunk           */
  char error[256];           /* hold error message if any                    */
  int nCall;                 /* number of call for the algorithms            */
  FRBOOL outputIsInput;      /* is yes, the ouput vector is not created      */
  int nResets;               /* number of regiset reset due to abnormal data */
  FrvFilter2* next;          /* for linked list of 2nd order filter          */
};

/*---------------------------------------------------------------------------
  How does it work ? The transfer function (Laplace transform s=i*w) is:

                Yout(s)     a2 * s**2 + a1 * s + a0
                ------- =  -------------------------
                Yinp(s)     b2 * s**2 + b1 * s + b0

    Example 1 : first order low-pass filter at f0 with unity gain at dc
                a2=0.  a1=0.  a0=1.  b2=0.  b1=1/(2*pi*f0)  b0=1. 

    Example 2 : second order low-pass filter at f0 with quality factor Q 
                and unity gain at dc (e.g. pendulum)
                a2=0. a1=0. a0=1. b2=1/(2*pi*f0)**2  b1=1/(2*pi*f0*Q)  b0=1

    Example 3 : integrator with time constant t
                a2=0. a1=0. a0=1. b2=0. b1=t b0=0.
-----------------------------------------------------------------------------*/
    
void        FrvFilter2Free(FrvFilter2* filter);
int         FrvFilter2Proc(FrvFilter2 *filter, FrVect *vect);
int         FrvFilter2Init(FrvFilter2* filter, FrVect *vect);
FrvFilter2* FrvFilter2New(double a2,double a1,double a0,
                          double b2,double b1,double b0);

struct FrvFilterB {
  char  *name;             /* optional name                                  */
  int    order;            /* filter order                                   */
  double fMin;             /* low frequency cut or 0 for high pass filter    */
  double fMax;             /* high freq. cut or zero for a low pass filter   */
  double fMaxPreWrp;       /* high frequency cut with pre-warp correction    */
  FrvFilter2* filterHP;    /* for linked list of 2nd order HP filter         */
  FrvFilter2* filterLP;    /* for linked list of 2nd order LP filter         */
  FrvFilter2* filter2;     /* =filterLP for backward compatibilite; Obsolete */
  FrVect*     output;      /* pointer to the output vector                   */
  FRBOOL errorPrinted;     /* tell if an error message has been printed      */
  int         nResets;     /* number of reset due to NAN in registers        */
  int         lastError;   /* gps time for the last error                    */
  FrvFilterB* next;        /* for linked list of Butterworth filter          */
};

void        FrvFilterButFree(FrvFilterB* filter);
FrvFilterB* FrvFilterButNew(int order, double fMin, double fMax, char* name);
FrVect*     FrvFilterButProc(FrvFilterB *filter, FrVect* vect);
void        FrvFilterButReset(FrvFilterB* filter);

#ifdef __cplusplus
}
#endif

#endif
