/*
 * measurement.c
 *
 *  Created on: Oct 28, 2019
 *      Author: Standa
 *
 *	This module provides fixed count (ADC_READSPERMEASPERIOD) of fast analog measurements of VM10R, VM100R and IM channels during single period (1/freq_Hz).
 *	Secondary function is to provide monitoring of VM10R, VM100R, IM, VBAT, VREF (for VDDA calculation) and TEMP when fast measurement is not active.
 *	TIM1 is the counter reserved for ADC conversion triggering and DMA1 CH1 used to transfer the converted data into memory.
 */

#include "measurement.h"
#include "error.h"
#include "adc.h"
#include "dma.h"
#include "tim.h"

#define VREF_MV					3284
#define ADCRESOLUTION			256
#define VBAT_SCALER_TO_MV		167	//VBATSCALER=3284/256*(98.22+8.175)/8.175 = 166.953927752
#define VBAT_OFFSET_MV			0

#define VCAP_SCALER_TO_MV		167	//VCAPSCALER=3284/256*(98.1+8.175)/8.175 = 166.765625
#define VCAP_OFFSET_MV			0

#define VE2_SCALER_TO_MV		168	//VE2CALER=3284/256*(98.8+8.175)/8.175 = 167.864057722
#define VE2_OFFSET_MV			0



#define CHANNEL_CNT	3	//VBAT, VCAP, VE2
static volatile uint8_t ADCBuffer[CHANNEL_CNT] = {0};

static uint16_t Vbat = 0, Vcap = 0, Ve2 = 0;
static uint32_t ConvCntr;


/*
 * Initialize generator module, used typically during boot only
 */
void meas_Init(void){
	ConvCntr = 0;
	LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_NONE);								//DMA transfer must be disabled before ADC calibration
	LL_ADC_StartCalibration(ADC1);
	while(LL_ADC_IsCalibrationOnGoing(ADC1));
	LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_UNLIMITED);							//Activate DMA ADC to memory transfer

	//Prepare ADC trigger timer TIM1
	LL_TIM_SetCounter(TIM1, 0);																	//Restart the counter
	LL_TIM_SetPrescaler(TIM1, 48-1);															//Set actual prescaler
	LL_TIM_SetAutoReload(TIM1, 100-1);															//Set counter period
	LL_TIM_ClearFlag_UPDATE(TIM1);																//Clear update flag which might be set during configuration
	LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
	LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_1, (uint32_t)(&(ADC1->DR)), (uint32_t)(ADCBuffer), LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
	LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, CHANNEL_CNT * 1);
	LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
	LL_ADC_Enable(ADC1);
	LL_ADC_REG_StartConversion(ADC1);

	LL_DMA_ClearFlag_TC1(DMA1);
	LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
	LL_TIM_EnableCounter(TIM1);
	LL_TIM_GenerateEvent_UPDATE(TIM1);
}


uint16_t meas_GetVbat(void){
	return Vbat;
}


uint16_t meas_GetVcap(void){
	return Vcap;
}

uint16_t meas_GetVe2(void){
	return Ve2;
}


void meas_ResetConvCntr(void){
	ConvCntr = 0;
}


uint32_t meas_GetConvCntr(void){
	return ConvCntr;
}

/*
 * Gets called by DMA1 after last measurement is transferred via DMA into buffer.
 */
void meas_EndOfADCReadingHandler(void){
	LL_DMA_ClearFlag_TC1(DMA1);

	Vbat = ADCBuffer[0] * VBAT_SCALER_TO_MV;
	Vcap = ADCBuffer[1] * VCAP_SCALER_TO_MV;
	Ve2 = ADCBuffer[2] * VE2_SCALER_TO_MV;

	ConvCntr++;
}
