/*
 * temperatureRegulation.c
 *
 *  Created on: Apr 16, 2023
 *      Author: Flax
 *
 *      Prefix : REG
 */

// ==============
// Local includes
// ==============
#include "temperatureRegulation.h"
#include "register.h"

// ===============
// Local constants
// ===============
#define cREGTempSPTMax				(400U)
#define cREGTempSPTMin				(50U)

#define cREGPwmMax					(65535)

#define cRegPIDProp					(10)
#define cRegPIDInteg				(10)
#define cRegPIDDeriv				(10)

// ===============
// Local variables
// ===============
static bool RegOffState_B;
static bool RegStandbyState_B;
static bool RegErrorState_B;

static uint16_t RegTempSPT_U16;
static uint16_t RegTempMeas_U16[2U];
static uint16_t RegTempMeasBuffer_U16A[2U];
static int32_t  RegPwmDyc_S32;
static uint32_t RegPwmDyc_U32;

// PID
static int32_t RegEpsilon_S32A[2U];

// ==========================
// Local functions prototypes
// ==========================

// ===========================
// Local functions definitions
// ===========================

// ============================
// Shared functions definitions
// ============================

void REGInit (void)
{
	RegOffState_B = true;
	RegStandbyState_B = false;
}

void REGStart (void)
{
	mREGAdcStartConversion();
}

void REGStop (void)
{
	mREGAdcStopConversion();
}

void REGCyclicTask (void)
{
	uint8_t cnt_u8;

	// Read ADC input
	RegTempMeasBuffer_U16A[1] = mREGAdcReadValue();

	// Calculate average
	RegTempMeasBuffer_U16A[0] += RegTempMeasBuffer_U16A[1];
	RegTempMeasBuffer_U16A[0] >> 1U;
	RegTempMeas_U16[1] = RegTempMeas_U16[0]; // Memorise previous value
	RegTempMeas_U16[0] = RegTempMeasBuffer_U16A[0];

	// PID
	RegEpsilon_S32A[1] = RegEpsilon_S32A[0]; // Memorise previous value
	RegEpsilon_S32A[0] = RegTempSPT_U16 - RegTempMeas_U16[0];

	RegPwmDyc_S32 = (RegEpsilon_S32A[0] * cRegPIDProp)
					+ ((RegEpsilon_S32A[0] - RegEpsilon_S32A[1]) * cRegPIDDeriv)
					+ (((RegEpsilon_S32A[0] + RegEpsilon_S32A[1]) >> 1U) * cRegPIDInteg);

	// Only keep positive values
	if (RegPwmDyc_S32 > 0)
	{
		RegPwmDyc_U32 = RegPwmDyc_S32;
	}
	else if (RegPwmDyc_S32 < (uint32_t)cREGPwmMax)
	{
		RegPwmDyc_U32 = (uint32_t)cREGPwmMax;
	}
	else
	{
		RegPwmDyc_U32 = 0U;
	}

	// Set PWM output duty cycle
	mREGPwmSetCompareValue(RegPwmDyc_U32);
}

bool REGIsError (void)
{
	return RegErrorState_B;
}

bool REGIsStandby(void)
{
	return RegStandbyState_B;
}

bool REGIsOff(void)
{
	return RegOffState_B;
}

void REGErrorReset (void)
{
	RegOffState_B = false;
}

void REGStandbySet(void)
{
	RegStandbyState_B = true;
}

void REGStandbyReset(void)
{
	RegStandbyState_B = false;
}

void REGOffSet(void)
{
	RegOffState_B = true;
}

void REGOffReset(void)
{
	RegOffState_B = false;
}

bool REGSPTSet (uint16_t temp_spt_u16)
{
	bool ret_B = false;
	if ((temp_spt_u16 <= (uint16_t)cREGTempSPTMax) && (temp_spt_u16 >= (uint16_t)cREGTempSPTMin))
	{
		RegTempSPT_U16 = temp_spt_u16;
		ret_B = true;
	}
	return (ret_B);
}

uint16_t REGSPTGet (void)
{
	return RegTempSPT_U16;
}

uint16_t REGTempGet (void)
{
	return RegTempMeas_U16[0];
}