/*
 * ADC_measures.c
 *
 * Created: 22.4.2016 10:45:13
 *  Author: Chenda
 */ 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <stdbool.h>


#include "../API_common_defs.h"
#include "../../Common/DataOperations.h"
#include "../../conf/conf_brd.h"
#include "../../lib_mcu/ADC/ADC_drv.h"

#include "ADC_measures.h"

/************************************************************************/
/* Global variables                                                     */
/************************************************************************/
static struct stRegAPI_layer *spAPI;

// measured values
static float Val,ValOld;

// meas channels
static uint8_t MChannels[] = {SNS_PRE_REG_VOLTAGE,SNS_POST_REG_VOLTAGE,SNS_TERM_VOLTAGE,SNS_CURRENT};
static float GChannels[] = {SNS_PRE_REG_VOLTAGE_GAIN,SNS_POST_REG_VOLTAGE_GAIN,SNS_TERM_VOLTAGE_GAIN,SNS_CURRENT_GAIN};
static struct stValue *spMeasVals[4];

/************************************************************************/
/* Private functions prototypes                                         */
/************************************************************************/
uint16_t ReadADCconversion(void);
void StoreConvertedValue (uint8_t MeasChannelIndex);

/************************************************************************/
/* Public functions                                                     */
/************************************************************************/
void ADC_MEAS_INIT(struct stRegAPI_layer *spRegAPIL)
{
	spAPI = spRegAPIL;
	
	mADC_SelReference(ADC_VREF_AVCC);
	mADC_SelPrescaler(ADC_PRESC_128);
	mADC_DigInp_Dis(SNS_PRE_REG_VOLTAGE);
	mADC_DigInp_Dis(SNS_POST_REG_VOLTAGE);
	mADC_DigInp_Dis(SNS_TERM_VOLTAGE);
	mADC_DigInp_Dis(SNS_CURRENT);
	//mAdc3PullUp_Enab();
	
	spMeasVals[0] = &spAPI->Meas.MeasPreRegU;
	spMeasVals[1] = &spAPI->Meas.MeasPostRegU;
	spMeasVals[2] = &spAPI->Meas.MeasTermU;
	spMeasVals[3] = &spAPI->Meas.MeasC;
	
	mADC_Enable(); 
}

void ADC_MEAS(void)
{
	static bool ConversionRunning = false;
	static uint8_t ChannelIndex = SNS_CURRENT;
	
	if (ConversionRunning && mADC_IsConvDone()) {
		// Conversion finished
		mADC_ClrConvDoneFlag();
		ConversionRunning = false;
		// Reading converted value and storing it in according measure value structure
		StoreConvertedValue (ChannelIndex);
	}
	if (!ConversionRunning) {
		// previous conversion done, incrementing channel index
		ChannelIndex++;
		ChannelIndex &= 0b11;
		// initiate new conversion
		mADC_SelChannel(MChannels[ChannelIndex]);
		mADC_StartConversion();
		// conversion in progress
		ConversionRunning = true;
		DAT_OPS_16int_to_Float(&ValOld,&spMeasVals[ChannelIndex]->Int,&spMeasVals[ChannelIndex]->Tenth);
	}
}


/************************************************************************/
/* Private functions                                                    */
/************************************************************************/
void StoreConvertedValue (uint8_t MeasChannelIndex)
{
	uint16_t ReadConversion;
	float tmp;
	
	ReadConversion = ReadADCconversion();
	Val = ReadConversion * 10;
	Val *= ADC_BIT_VOLTAGE;
	Val *= 100; 
	Val /= GChannels[MeasChannelIndex];
	Val /= 1000;

	if (MeasChannelIndex == 1) {
		// linearize claculations - post reg voltage,
		Val = (0.9946*Val) + 0.132;
	}
	if (MeasChannelIndex == 2) {
		// linearize claculations - terminal voltage
		Val = (0.993*Val) + 0.1315;
	}
	if (MeasChannelIndex == 3) {
		// current computing
		Val /= SNS_CURR_RESISTOR;
		// linearize claculations - current
		tmp = Val*Val;
		Val = (0.0221*tmp)+(0.8705*Val)+0.0546;
		spAPI->Meas.MeasureRoundFinished = true;
	}
	//if(Val < 0) Val = 0;
	DAT_OPS_Float_Average(&Val,&ValOld,AVE_FLOAT_WINDOW_LEN);
	DAT_OPS_Float_to_16int(&Val,&spMeasVals[MeasChannelIndex]->Int,&spMeasVals[MeasChannelIndex]->Tenth);
}


uint16_t ReadADCconversion(void)
{
	return (uint16_t) (mADC_ReadConvVal_Low() | (mADC_ReadConvVal_High()<<8)); 
}

