//----------------------------------------------------
/**
	\file		pid_reg.h

	\brief		knihovna PID regulace
				<<< ALL >>>

	\author		ConTeK s.r.o., Martin Kastner, Bc. Jan Prasil
*/
//----------------------------------------------------

#ifndef _PID_REG_H
#define _PID_REG_H

#include "libsets.h"
#include <stmachine.h>
#include <misc.h>

#define PID_REG_ELAST_ARRAY_LENGTH	100	//Todo premistit do libsets.h


//------------------------------------------
//!	Stavy automatu PID regulatoru
typedef enum _PID_AUTOMAT_STATE
{
	PID_STATE_RUN = STM_FIRST_USER_STATE,
} PID_AUTOMAT_STATE;


//-----------------------------------------
//! Periodicky obnovovane parametry na zaklade priznaku "Refresh"
typedef struct _PERIODIC_REFRESH_PARAM
{
	bool_t		Refresh;					//!< Priznak pro update parametru
	bool_t		Automatic;					//!< Automaticky rezim regulatoru
	float_t		MinW;						//!< Minimalni pozadovana hodnota
	float_t		MaxW;						//!< Maximalni pozadovana hodnota
	float_t		MinY;						//!< Minimalni vstupni hodnota
	float_t		MaxY;						//!< Maximalni vstupni hodnota
	float_t		EGap;						//!< Minimalni platna odchylka
	float_t		IGap;						//!< Maximalni odchylka pro integraci
	float_t		DGap;						//!< Maximalni odchylka pro derivaci
	float_t		SumIOver;					//!< Hodnota SumI pro pasmo nad
	float_t		SumIUnder;					//!< Hodnota SumI pro pasmo pod
	float_t		ManualU;					//!< Manualni akcni zasah
	float_t		NegCorr;					//!< Korekce P,I,D pro zapornou odchylku
	lticks_t	Period;						//!< Perioda regulacnich zasahu [ms]
	uint16_t	DerivPeriod;			//!< Nasobic periody, vysledkem je perioda pro ukladani E => ELast pole
	uint16_t	NumOfELast;					//!< Pocet ELast v poli
}PERIODIC_REFRESH_PARAM;

//-----------------------------------------
//! Aplikaci rizene parametry
typedef struct _APP_CONTROLLED_PARAM
{
	float_t		MinU;						//!< Minimalni akcni zasah
	float_t		MaxU;						//!< Maximalni akcni zasah
	float_t		SumIStart;					//!< Implicitni hodnota pri startu
	float_t		KP;							//!< Proporcionalni slozka
	float_t		KI;							//!< Integracni slozka
	float_t		KD;							//!< Derivacni slozka
}APP_CONTROLLED_PARAM;

//-----------------------------------------
//!	Struktura parametru PID regulatoru
typedef struct _PID_PARAM
{
	APP_CONTROLLED_PARAM	AppCtrlParam;
	PERIODIC_REFRESH_PARAM	RefreshParam;
} PID_PARAM;

//-----------------------------------------
//!	Struktura promennych PID regulatoru
typedef struct _PID_VAR
{
	float_t		W;							//!< Pozadovana hodnota
	float_t		Y;							//!< Vstupni (merena) hodnota
	float_t		U;							//!< Akcni zasah
	float_t		E;							//!< Regulacni odchylka
	float_t		SumI;						//!< Integracni slozka
	float_t		DeltaE;						//!< Rozdil aktualni a minule reg. odchylky
	lticks_t	PeriodTimer;				//!< Casovac pro nastaveni periody regulace

	//! Promenne pro pocitani derivace
	float_t		ELastArray[PID_REG_ELAST_ARRAY_LENGTH];	//!< Uchovani poslednich hodnot E
	uint16_t	PeriodCounter;							//!< Pocitadlo spousteni regulatoru
	uint16_t	LastElementIdx;							//!< Index posledniho vlozeneho prvku
	bool_t		ArrayFilled;							//!< Priznak naplneni pole do NumOfELast
}PID_VAR;

//------------------------------------------
//! Kontext PID regulatoru
typedef struct _PID_REG{
	STMACHINE	Stm;
	
	PID_PARAM	Param;
	PID_VAR 	Var;
} PID_REG;



//-------------------------------------------------
//!	\name	Rozhrani PID regulatoru
//@{
//--------------------------------------------------
/*
	\brief	Funkce nastavi vstupni promenne regulatoru

	\param	_reg	Kontext regulatoru
			_W		Pozadovana hodnota
			_Y		Namerena hodnota
*/
//--------------------------------------------------
inline void PIDSetRegulatorInput(PID_REG * const _reg, const float_t _W, const float_t _Y)
{
	_reg->Var.W = _W;
	_reg->Var.Y = _Y;
}

//--------------------------------------------------
/*
	\brief	Funkce navrati vystup regulatoru

	\param	_reg	Kontext regulatoru

	\return	Regulatorem spocitany akcni zasah U
*/
//--------------------------------------------------
inline float_t PIDGetRegulatorOutput(PID_REG *const _reg)
{
	return _reg->Var.U;
}

//--------------------------------------------------
/*
	\brief	Funkce provede restart regulatoru

	\param	_reg	Kontext regulatoru
*/
//--------------------------------------------------
void PIDRestartRegulator(PID_REG *const _reg);

//--------------------------------------------------
/*
	\brief	Funkce ukonci regulator

	\param	_reg	Kontext regulatoru
*/
//--------------------------------------------------
void PIDFinishRegulator(PID_REG *const _reg);

//--------------------------------------------------
/*
	\brief	Funkce nastavi priznak obnovy parametru

	\param	_reg	Kontext regulatoru
*/
//--------------------------------------------------
inline void PIDSetParamRefreshFlag(PID_REG *const _reg)
{
	_reg->Param.RefreshParam.Refresh = TRUE;
}


//--------------------------------------------------
/*
	\brief	Tick PID regulatoru

	\param	_reg	Kontext regulatoru
*/
//--------------------------------------------------
void PIDTick(PID_REG * const _reg);

//----------------------------------------------------
/*
	\brief	Funkce obnoveni periodickych parametru z datove zakladny

	\param	_reg				Kontext regulatoru
			_automatic			Automaticky rezim regulatoru
			_minW				Minimalni pozadovana hodnota
			_maxW				Maximalni pozadovana hodnota
			_minY				Minimalni vstupni hodnota
			_maxY				Maximalni vstupni hodnota
			_eGap				Minimalni platna odchylka
			_iGap				Maximalni odchylka pro integraci
			_dGap				Maximalni odchylka pro derivaci
			_sumIOver			Hodnota SumI pro pasmo nad
			_sumIUnder			Hodnota SumI pro pasmo pod
			_manualU			Manualni akcni zasah
			_negCorr			Korekce P,I,D pro zapornou odchylku
			_period				Perioda regulacnich zasahu [ms]
			_periodMul			Nasobic periody, vysledkem je perioda pro ukladani E
			_numOfELast			Pocet ELast v poli
*/
//----------------------------------------------------
void PIDSetRefreshParam(PID_REG * _reg, const bool_t _automatic, const float_t _minW, const float_t _maxW, const float_t _minY, const float_t _maxY,
								const float_t _eGap, const float_t _iGap, const float_t _dGap, const float_t _sumIOver, const float_t _sumIUnder,
								const float_t _manualU, const float_t _negCorr, const lticks_t _period, const uint16_t _periodMul, const uint16_t _numOfELast);

//----------------------------------------------------
/*
	\brief	Funkce nastavi parametr "SumIStart"

	\param	_reg				Kontext regulatoru
			_sumIStart			Hodnota SumI pri startu (resp. restartu)
*/
//----------------------------------------------------
void PIDSetParamSumIStart(PID_REG * _reg, const float_t _sumIStart);

//----------------------------------------------------
/*
	\brief	Funkce nastavi parametry "minU" a "maxU"

	\param	_reg				Kontext regulatoru
			_minU				Minimalni akcni zasah
			_maxU				Maximalni akcni zasah
*/
//----------------------------------------------------
void PIDSetParamMinUMaxU(PID_REG * _reg, const float_t _minU, const float_t _maxU);

//----------------------------------------------------
/*
	\brief	Funkce nastavi parametry "KP" "KI" "KD"

	\param	_reg				Kontext regulatoru
			_kP					Proporcionalni slozka
			_kI					Integracni slozka
			_kD					Derivacni slozka
*/
//----------------------------------------------------
void PIDSetParamKpKiKd(PID_REG * _reg, const float_t _kP, const float_t _kI, const float_t _kD);

//----------------------------------------------------
/*
	\brief	Inicializace
	
	\param	_reg				Kontext regulatoru
			_automatic			Automaticky rezim regulatoru
			_minW				Minimalni pozadovana hodnota
			_maxW				Maximalni pozadovana hodnota
			_minY				Minimalni vstupni hodnota
			_maxY				Maximalni vstupni hodnota
			_minU				Minimalni akcni zasah
			_maxU				Maximalni akcni zasah
			_eGap				Minimalni platna odchylka
			_iGap				Maximalni odchylka pro integraci
			_dGap				Maximalni odchylka pro derivaci
			_sumIStart			Hodnota SumI pri startu
			_sumIOver			Hodnota SumI pro pasmo nad
			_sumIUnder			Hodnota SumI pro pasmo pod
			_manualU			Manualni akcni zasah
			_negCorr			Korekce P,I,D pro zapornou odchylku
			_kP					Proporcionalni slozka
			_kI					Integracni slozka
			_kD					Derivacni slozka
			_period				Perioda regulacnich zasahu [ms]
			_periodMul			Nasobic periody, vysledkem je perioda pro ukladani E
			_numOfELast			Pocet ELast v poli
*/
//----------------------------------------------------
void PIDInitialize(PID_REG * _reg, const bool_t _automatic, const float_t _minW, const float_t _maxW, const float_t _minY, const float_t _maxY,
									const float_t _minU, const float_t _maxU, const float_t _eGap, const float_t _iGap, const float_t _dGap,
									const float_t _sumIStart, const float_t _sumIOver, const float_t _sumIUnder, const float_t _manualU,
									const float_t _negCorr, const float_t _kP, const float_t _kI, const float_t _kD, const lticks_t _period,
									const uint16_t _periodMul, const uint16_t _numOfELast);

//----------------------------------------------------
/**
	\brief	Finalizace
	
	\param	_reg	kontext
*/
//----------------------------------------------------
void PIDFinalize(PID_REG * _reg);

//@}

#endif //_PID_REG_H
