#ifndef _ADC_H__
#define _ADC_H__
#include "bsp/bsp.h"
#include "os/os_types.h"

float adc_vref_compesion(void);
float adc_5vref_compesion(void);

/*
inserted ADC 由timer0 ch3触发，
注意：adc所有外部触发都是下降沿触发 
*/
#define ISQ0_OFFSET 0
#define ISQ1_OFFSET 5
#define ISQ2_OFFSET 10
#define ISQ3_OFFSET 15
#define IL_OFFSET   20

#define ADC_INJ_SAMPLE_TIME ADC_SAMP_TIME_7CYCLES5
#define ADC_REGCHAN_SAMPLE_TIME ADC_SAMP_TIME_239CYCLES5


#define ADC_TRIGGER_PHASE ADC_EXT_TRIG_INJ_CONV_T1_CC4

#define PHASE_AB 0
#define PHASE_AC 1
#define PHASE_BC 2

#define JDAT_OFFSET ((uint8_t)0x28)
#define CTRL2_INJ_EXT_TRIG_SET   ((uint32_t)0x00008000)
#define CTRL2_INJ_EXT_TRIG_RESET ((uint32_t)0xFFFF7FFF)
#define INJ_CHAN_NUM 4
static u16 __inline ADC_GetInjectedDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel)
{
    __IO uint32_t tmp = 0;

    tmp = (uint32_t)ADCx;
    tmp += ADC_InjectedChannel + JDAT_OFFSET;

    /* Returns the selected injected channel conversion data value */
    return (uint16_t)(*(__IO uint32_t*)tmp);
}

#define v_calc(sum, v, min, max) \
	do { \
		if (v > max) { \
			max = v; \
		} \
		if (v < min) { \
			min = v; \
		}\
		sum += v; \
	}while(0);

static void __inline adc_phase_current_read(u8 phases, s32 *pv1, s32 *pv2) {
#if (INJ_CHAN_NUM == 4)
	u16 min, max;
	u16 sum = 0;
	u16 v1 = ADC_GetInjectedDat(ADC1, ADC_INJ_CH_1);
	u16 v2 = ADC_GetInjectedDat(ADC1, ADC_INJ_CH_2);
	u16 v3 = ADC_GetInjectedDat(ADC1, ADC_INJ_CH_3);
	u16 v4 = ADC_GetInjectedDat(ADC1, ADC_INJ_CH_4);
	min = max = v1;
	sum += v1;
	v_calc(sum, v2, min, max);
	v_calc(sum, v3, min, max);
	v_calc(sum, v4, min, max);
	*pv1 = (s32) ((sum-min-max)/2.0f * adc_5vref_compesion());

	sum = 0;
	v1 = ADC_GetInjectedDat(ADC2, ADC_INJ_CH_1);
	v2 = ADC_GetInjectedDat(ADC2, ADC_INJ_CH_2);
	v3 = ADC_GetInjectedDat(ADC2, ADC_INJ_CH_3);
	v4 = ADC_GetInjectedDat(ADC2, ADC_INJ_CH_4);
	min = max = v1;
	sum += v1;
	v_calc(sum, v2, min, max);
	v_calc(sum, v3, min, max);
	v_calc(sum, v4, min, max);
	*pv2 = (s32) ((sum-min-max)/2.0f * adc_5vref_compesion());
#else
	*pv1 = (s32)((float)ADC_GetInjectedDat(ADC1, ADC_INJ_CH_1) * adc_5vref_compesion());
	*pv2 = (s32)((float)ADC_GetInjectedDat(ADC2, ADC_INJ_CH_1) * adc_5vref_compesion());
#endif
}


static void __inline adc_current_sample_config(u8 phases) {

}

static void __inline adc_disable_ext_trigger(void) {   
	//ADC1->CTRL2 &= CTRL2_INJ_EXT_TRIG_RESET;
}

static void __inline adc_enable_ext_trigger(void) {	
	//ADC1->CTRL2 |= CTRL2_INJ_EXT_TRIG_SET;
}


static __inline__ void adc_clear_irq_flags(void) {
	ADC1->STS = (~(uint32_t)ADC_FLAG_JENDC);
	ADC2->STS = (~(uint32_t)ADC_FLAG_JENDC);
}


static __inline void adc_update_ext_trigger(u32 trigger) {
	//ADC1->CTRL2 |= trigger;
}

void adc_init(void);
s32 adc_sample_regular_channel(int chan, int times);
void adc_start_convert(void);
void adc_stop_convert(void);
u16 adc_get_vbus(void);
u16 adc_get_acc(void);
u16 adc_get_throttle(void);
void adc_get_uvw_phaseV(u16 *uvw);
u16 adc_get_mos_temp(void);
u16 adc_get_motor_temp(void);
u16 adc_get_ibus(void);
u16 adc_get_vref(void);
void adc_set_vref_calc(float v);
void adc_vref_filter(void);
u16 adc_get_5v_ref(void);
void adc_set_5vref_calc(float v);
u16 adc_get_throttle2(void);
u16 adc_get_thro_5v(void);
u16 adc_get_thro2_5v(void);

#endif /* _ADC_H__ */
