#include <stdio.h>

#include "main.h"
#include "dac.h"
#include "dma.h"
#include "precharge.h"

#define DELAYS_NUM			7U

extern void (*MOSFETS_Management)(void);
extern void DoNothing(void);

static void (*WhereToGoAfterPrecharge)(void);

//------------------------------------------------------------------------------

void SetReturnFunction(void (*WhereToReturnControl)(void))
{
	if (WhereToReturnControl != NULL) WhereToGoAfterPrecharge = WhereToReturnControl;
}

//------------------------------------------------------------------------------

#ifdef USE_RAM_FUNC
__RAM_FUNC void PreChargeStage(void)
#else
		   void PreChargeStage(void)
#endif
{
	const int32_t MHz = 1000000U;
	static int stage = 0;
	static int cnt = 0;
	static int mal = 0;
								//   DAC = 0   DAC = 3V
	const int32_t delay_µs[DELAYS_NUM] = {   3, 3,	  // 0, 1	  - 6710µs is MAX @320kHz, [0,1,2,3] = 3µs, [4] = 5.5µs
									       700, 3,	  // 2, 3
										   700, 4, 	  // 4, 5
										   700		  // 6
									     };
	const int32_t delay_cnt[DELAYS_NUM] = { (delay_µs[ 0 ] * CURRENT_INTEGRAL_FREQ) / MHz,
										    (delay_µs[ 1 ] * CURRENT_INTEGRAL_FREQ) / MHz,
										    (delay_µs[ 2 ] * CURRENT_INTEGRAL_FREQ) / MHz,
										    (delay_µs[ 3 ] * CURRENT_INTEGRAL_FREQ) / MHz,
										    (delay_µs[ 4 ] * CURRENT_INTEGRAL_FREQ) / MHz,
										    (delay_µs[ 5 ] * CURRENT_INTEGRAL_FREQ) / MHz,
										    (delay_µs[ 6 ] * CURRENT_INTEGRAL_FREQ) / MHz,
									      };
	 
	switch(stage)
	{
		case 0:
			// Setting new values for DAC
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_A_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_0V;
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_B_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_0V;

			if (cnt++ >= delay_cnt[0])	// 1c
			{
				cnt = 0;
				stage++;
			}
			break;

		case 1:
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_A_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_3V >> 1;
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_B_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_3V >> 1;

			if (cnt++ >= delay_cnt[1])	// 1c
			{
				cnt = 0;
				stage++;
			}
			break;

		case 2:
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_A_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_0V;
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_B_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_0V;

			if (cnt++ >= delay_cnt[2])	// 300c
			{
				cnt = 0;
				stage++;
			}
			break;

		case 3:
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_A_ALIGNMENT(DAC_ALIGN_12B_R)) = 0xBFF;//DAC_3V;
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_B_ALIGNMENT(DAC_ALIGN_12B_R)) = 0xBFF;//DAC_3V;

			if (cnt++ >= delay_cnt[3])	// 1c
			{
				cnt = 0;
				stage++;
			}
			break;

		case 4:
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_A_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_0V;
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_B_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_0V;

			if (cnt++ >= delay_cnt[4])	// 50c
			{
				cnt = 0;
				stage++;
			}
			break;

		case 5:
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_A_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_3V;
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_B_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_3V;

			if (cnt++ >= delay_cnt[5])	// 1c
			{
				cnt = 0;
				stage++;
			}
			break;

		case 6:
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_A_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_0V;
			*(__IO uint32_t *)((uint32_t)DAC_HANDLE.Instance + DAC_CH_B_ALIGNMENT(DAC_ALIGN_12B_R)) = DAC_0V;

			if (cnt++ >= delay_cnt[6])	// 50c
			{
				cnt = 0;
				stage = 5;
				
				if (mal++ >= 100/*12000*/)	  // approx 4.25s
				{
					mal = 0;
					stage = 0;
					HAL_NVIC_DisableIRQ(ADC_DMA_IRQ);
					if (WhereToGoAfterPrecharge != NULL) MOSFETS_Management = WhereToGoAfterPrecharge;
					else MOSFETS_Management = &DoNothing;
					HAL_NVIC_EnableIRQ(ADC_DMA_IRQ);
				}
			}
			break;
	}
}

//------------------------------------------------------------------------------