#include <stdio.h>
#include "main.h"
#include <string.h>
#include <stdbool.h>
#include "cmsis_os.h"
#include "commonMsg.h"

/* Demo includes. */
#include "adcMeas.h"
#include "fdcan_bus.h"
#include "stm32_mem.h"
#include "vt100.h"

#define ADC1_DMABufferSize	   	10
#define ADC1_CHANNELS			4

#define BASELINE	20

extern ADC_HandleTypeDef hadc1;
extern osSemaphoreId ADC1semHandle;

extern TIM_HandleTypeDef htim2;

volatile uint16_t adc1_buffer[ADC1_DMABufferSize][ADC1_CHANNELS] = {0};
float vref, temp;
uint16_t busVoltage, photoTransistorVoltage;

/*-----------------------------------------------------------*/

/**
 * @brief  Process the ADC1 buffer
 * @param  buffer: Pointer to the ADC buffer
 * @retval None
 */
void process_adc1_buffer()
{
	//HAL_GPIO_WritePin(DBG_GPIO_Port,DBG_Pin,GPIO_PIN_SET);

	uint32_t sumVREF=0, sumAIN15=0, sumAIN10=0, sumTEMP=0;
	for( int i = 0; i < ADC1_DMABufferSize; i++ )
	{
		sumVREF += adc1_buffer[i][0];
		sumAIN15 += adc1_buffer[i][1];
		sumAIN10 += adc1_buffer[i][2];
		sumTEMP += adc1_buffer[i][3];
	}
	// Calculating VRef voltage
	if( sumVREF == 0 )
		return;
	uint32_t raw_vref = sumVREF  / ADC1_DMABufferSize;
	vref = __HAL_ADC_CALC_VREFANALOG_VOLTAGE(raw_vref, ADC_RESOLUTION_12B);

	// Calculating photo transistor voltage
	uint16_t adc_AIN15 = sumAIN15 / ADC1_DMABufferSize;
	photoTransistorVoltage = adc_AIN15 * vref / 4095;
    // Calculating bus voltage
	uint16_t adc_AIN10 = sumAIN10 / ADC1_DMABufferSize;
	busVoltage = vref * adc_AIN10 / 4095;
	busVoltage *= 4;
    temp = __HAL_ADC_CALC_TEMPERATURE(vref, sumTEMP/ADC1_DMABufferSize, ADC_RESOLUTION_12B);

	//HAL_GPIO_WritePin(DBG_GPIO_Port,DBG_Pin,GPIO_PIN_RESET);
}

void sendDataToCANbus()
{
CAN_Frame_t xFrame;
dev_test *device = (dev_test*)xFrame.data;

	device->MCU_ExternalTemperature = (temp + 40);
	device->MCU_BusVoltage = busVoltage / 100; // * 10
	device->MCU_AlgeaCount = photoTransistorVoltage;
	xFrame.identifier = MCU_S_TEST;
	xFrame.dataLength = FDCAN_DLC_BYTES_4;
	xFrame.dataSize = sizeof(dev_test);
	CAN_EnqueueFrame(&xFrame);

#ifndef DATA_LOGGER
	move_cursor(BASELINE, 1);
	APP_LOG(TS_OFF, VLEVEL_M, "Junction temp.: %2d C, Bus voltage: %.1f V, %ld counts",device->MCU_ExternalTemperature - 40,
			(float)(device->MCU_BusVoltage/10.0), (long)photoTransistorVoltage);
#endif
}

void ADC1_ConvCplt()
{
	BaseType_t  xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR(ADC1semHandle, &xHigherPriorityTaskWoken);
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

void vADCMeasTask( void *pvParameters )
{
/* Remove warning for unused parameter */
    (void)pvParameters ;

    // *** Algea sensor
    // Start timer 2 used for drive blue led at 1 KHZ duty 10 -> Blue led ON during 100us
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);

    // Start ADC Conversion
    while(HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED) != HAL_OK )
    	;

	while(1) {
		// Conversion time
		// ADC clock APB2 / 32 = 3.75 MHz
		// Tconv = (SamplingTime + 12.5 ) / ADC Clock = ( 247,5 + 12,5 ) / 3750000 = 69 us
		HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc1_buffer, (uint32_t)(ADC1_DMABufferSize*ADC1_CHANNELS));

	    // Wait for DMA transfer
	    xSemaphoreTake(ADC1semHandle, portMAX_DELAY);
	    process_adc1_buffer();
	    sendDataToCANbus();
	    vTaskDelay(pdMS_TO_TICKS(1500));
	}
}
