Ejemplo n.º 1
0
void ADC_Handler(void)
{
	uint32_t i;
	uint32_t ul_temp;

	/* With PDC transfer */
	if (g_adc_test_mode.uc_pdc_en) {
		if ((adc_get_status(ADC) & ADC_SR_RXBUFF) ==
				ADC_SR_RXBUFF) {
			g_adc_sample_data.us_done = ADC_DONE_MASK;
			adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);

			/* Only keep sample value, and discard channel number. */
			for (i = 0; i < NUM_CHANNELS; i++) {
				g_adc_sample_data.us_value[i] &= ADC_LCDR_LDATA_Msk;
			}
		}
	} else {
		if ((adc_get_status(ADC) & ADC_SR_DRDY) ==
				ADC_SR_DRDY) {
			ul_temp = adc_get_latest_value(ADC);
			for (i = 0; i < NUM_CHANNELS; i++) {
				g_adc_sample_data.us_value[i] =
						ul_temp & ADC_LCDR_LDATA_Msk;
				g_adc_sample_data.us_done |= 1 << i;
			}
		}
	}
}
Ejemplo n.º 2
0
/**
* \brief ADC interrupt handler.
*/
void ADC_Handler(void)
{
	uint32_t tmp;
	uint32_t status ;

	status = adc_get_status(ADC);
	
	/* Checa se a interrupção é devido ao canal 5 */
	static float rad_antes = 0;
	if ((status & ADC_ISR_EOC5)) {
		tmp = adc_get_channel_value(ADC, ADC_POT_CHANNEL);

			ili93xx_set_foreground_color(COLOR_WHITE);
			ili93xx_draw_filled_rectangle(9, 39, ILI93XX_LCD_WIDTH,55);
			v=3.3*((float)tmp)/4095.0;
			rad=2*pi*((float)tmp)/4095.0;
			ili93xx_draw_line(120,160,120+54*arm_cos_f32(rad_antes),160+54*arm_sin_f32(rad_antes));
			ili93xx_set_foreground_color(COLOR_BLACK);
			sprintf(vet, "Tensao: %f", v);
			ili93xx_draw_string(10, 40, vet);
			ili93xx_draw_line(120,160,120+54*arm_cos_f32(rad),160+54*arm_sin_f32(rad));
			rad_antes = rad;

	}
	

	
}
Ejemplo n.º 3
0
/**
 * \brief Interrupt handler for the ADC.
 */
static void adc_irq_handler(void)
{
	uint32_t status;
 	uint8_t i, j;
	uint32_t value;

	/* Get Interrupt Status (ISR) */
	status = adc_get_status();

	/* check at least one EOCn flag set */
	if( status & 0x00000FFF ) {
		for (i=0; i < NUMBER_OF_ADC_CHANNELS; i++) {
			value = adc_get_converted_data(i);
			/* Check ISR "End of Conversion" corresponding bit */
			if ((status & (1u<<i))) {
				for (j = 0; j < NUM_CHANNELS; j++) {
					if ( _data.channel[j] == i) {
						_data.value[j] = value;
						_data.done |= 1 << i;
						break;
					}
				}
			}
		}
	}
}
Ejemplo n.º 4
0
// Start converting the enabled channels
void AnalogInStartConversion(uint32_t channels)
{
#if SAM3XA || SAM4S
	// Clear out any existing conversion complete bits in the status register
	for (uint32_t chan = 0; chan < 16; ++chan)
	{
		if ((adc_get_status(ADC) & (1 << chan)) != 0)
		{
			(void)adc_get_channel_value(ADC, static_cast<adc_channel_num_t>(chan));
		}
	}
	adc_start(ADC);
#elif SAM4E
	channels &= activeChannels;
	if ((channels & 0x0000FFFF) != 0)
	{
		StartConversion(AFEC0);
	}
	if ((channels & 0xFFFF0000) != 0)
	{
		StartConversion(AFEC1);
	}
#elif SAME70
	channels &= activeChannels;
	if ((channels & 0x000003FF) != 0)
	{
		StartConversion(AFEC0);
	}
	if ((channels & 0x003FF800) != 0)
	{
		StartConversion(AFEC1);
	}
#endif
}
Ejemplo n.º 5
0
/**
 * \brief ADC interrupt handler.
 * Entramos aqui quando a conversao for concluida.
 */
void ADC_Handler(void)
{
	uint32_t tempValue;
	uint32_t status ;

	status = adc_get_status(ADC);
	
	/* Checa se a interrupção é devido ao canal 5 */
	if ((status & ADC_ISR_EOC5)) {
		tempValue = adc_get_channel_value(ADC, ADC_POT_CHANNEL);
		if ((tempValue > adc_value_old + 2) || (tempValue < adc_value_old - 2))
		{
			if (isAmp){
				amplitude = tempValue;
				atualiza_amp(amplitude);
			} else {
				frequencia = tempValue;
				tc_stop(TC0,0);
				configure_tc((frequencia*32768/2000)/4095);
				atualiza_freq(frequencia);
			}
		}
		adc_value_old = tempValue;
	}
	
}
Ejemplo n.º 6
0
/**
*  Interrupt handler for TC0 interrupt.
*/
void ADC_Handler(void)
{
	uint32_t tmp;
	uint32_t status ;

	status = adc_get_status(ADC);
	max_digital = adc_get_channel_value(ADC, ADC_POT_CHANNEL);
}
Ejemplo n.º 7
0
/**
 * \brief Callback function for ADCIFE interrupt.
 */
static void adcife_read_conv_result(void)
{
	if ((adc_get_status(&g_adc_inst) & ADCIFE_SR_SEOC) == ADCIFE_SR_SEOC) {
		g_adc_sample_data[0] = adc_get_last_conv_value(&g_adc_inst);
		g_uc_condone_flag = 1;
		adc_clear_status(&g_adc_inst, ADCIFE_SCR_SEOC);
	}
}
Ejemplo n.º 8
0
/**
 * \brief Callback function for ADCIFE interrupt.
 */
static void adcife_set_conv_flag(void)
{
	if ((adc_get_status(&g_adc_inst) & ADCIFE_SR_SEOC) == ADCIFE_SR_SEOC) {
		g_uc_condone_flag = 1;
		adc_clear_status(&g_adc_inst, ADCIFE_SCR_SEOC);
		adc_disable_interrupt(&g_adc_inst, ADC_SEQ_SEOC);
	}
}
Ejemplo n.º 9
0
/**
 * \brief ADC interrupt handler.
 * Entramos aqui quando a conversao for concluida.
 */
void ADC_Handler(void)
{
	uint32_t resistencia;
	
	if ((adc_get_status(ADC) & ADC_ISR_RXBUFF) == ADC_ISR_RXBUFF) {

		resistencia = adc_get_channel_value(ADC, ADC_POT_CHANNEL);
	}
}
Ejemplo n.º 10
0
Archivo: adc.c Proyecto: avrxml/asf
/** \brief Disable channel
 *
 * \param *adc Base address of the ADC
 * \param  channel   channel to disable (0 to 7)
 */
void adc_disable(volatile avr32_adc_t *adc, uint16_t channel)
{
	Assert( adc != NULL );
	Assert( channel <= AVR32_ADC_CHANNELS_MSB ); /* check if channel exist
	                                              **/

	if (adc_get_status(adc, channel) == true) {
		/* disable channel */
		adc->chdr |= (1 << channel);
	}
}
Ejemplo n.º 11
0
uint16_t getLightSens()
{
	uint16_t result = 0;
	adc_start_conversion(&adc1);
	while(adc_get_status(&adc1) != ADC_STATUS_RESULT_READY);
	adc_read(&adc1, &result);
	result = result * 16;
	adc_clear_status(&adc1, ADC_STATUS_RESULT_READY);

	return result;
}
Ejemplo n.º 12
0
Archivo: adc.c Proyecto: keyhole/gitand
void adc_disable(volatile avr32_adc_t * adc, unsigned short channel)
{
  Assert( adc!=NULL );
  Assert( channel <= AVR32_ADC_CHANNELS_MSB ); // check if channel exist

  if (adc_get_status(adc, channel) == ENABLED)
  {
    // disable channel
    adc->chdr |= (1 << channel);
  }
}
Ejemplo n.º 13
0
/**
 * \brief Timmer handler (100ms) starts a new conversion.
 */
void TC0_Handler(void)
{
		volatile uint32_t ul_dummy;

		/* Clear status bit to acknowledge interrupt */
		ul_dummy = tc_get_status(TC0,0);

		/* Avoid compiler warning */
		UNUSED(ul_dummy);
		
	if (adc_get_status(ADC) & (1 << ADC_POT_CHANNEL)) {
		adc_start(ADC);
	}
}
Ejemplo n.º 14
0
/**
 * \brief Handler for ADC interrupt.
 */
void ADC_Handler(void)
{
	uint32_t low_threshold;
	uint32_t high_threshold;
	uint32_t status = adc_get_status(ADC);

	/* Read the status to ack the IT */
	if ((status & ADC_ISR_COMPE) == ADC_ISR_COMPE) {
		/* Get the potentiometer initial value */
		pontentiometer_value = adc_get_channel_value( ADC,
				ADC_CHANNEL_POTENTIOMETER );

		/* Set Window threshold according to the initial values */
		low_threshold = pontentiometer_value -
				(NB_INTERVALS * (0x1000 / 256));
		if (low_threshold > 0xf0000000) {
			low_threshold = 0;
		}

		high_threshold = pontentiometer_value +
				(NB_INTERVALS * (0x1000 / 256));
		if (high_threshold >= 0x1000) {
			high_threshold = 0x1000 - 1;
		}

		/* Normalize the value 0 -> 255 */
		pontentiometer_value
			= pontentiometer_value*100 + 1;
		ppt_delay_clapse_counter = 0;

		/* Setup Threshold*/
		adc_set_comparison_window( ADC, low_threshold,
				high_threshold);

		/* Compare mode, in the window. */
		adc_enable_interrupt(ADC, ADC_IER_COMPE);
	}

	if (status & ADC_ISR_ENDRX) {
		/* Start next buffer */
		ADC->ADC_RNPR = (uint32_t)
				frame_buffer[(adc_buf_ndx + 2) % AUDIO_NB_BUFFER];
		ADC->ADC_RNCR = AUDIO_FRAME_SIZE;

		adc_buf_ndx = (adc_buf_ndx + 1) % AUDIO_NB_BUFFER;
		adc_nb_samples += AUDIO_FRAME_SIZE;
	}
}
Ejemplo n.º 15
0
/**
 * \brief Enter sleep mode using WFI instruction.
 * Enable interrupt first and then disable it after wake up.
 */
static void enter_asleep(void)
{
	while (1) {
		puts("Now switching the device into sleep mode...\r");

		/* Clear status register. */
		adc_get_status(ADC);

		/* Enable Compare Interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_COMPE);

		__WFI();

		/* Every time waked up, break out of the loop. */
		break;
	}
}
Ejemplo n.º 16
0
/**
* \brief ADC interrupt handler.
*/
void ADC_Handler(void)
{
	uint32_t tmp;
	uint32_t status ;

	status = adc_get_status(ADC);
	
	/* Checa se a interrupção é devido ao canal 5 */
	if ((status & ADC_ISR_EOC5)) {
		tmp = adc_get_channel_value(ADC, ADC_POT_CHANNEL);
		if(tmp != adc_value_old)
		{
			adc_value_old = tmp;
			adc_value_new = 1;
		}
	}
}
Ejemplo n.º 17
0
/**
 * \brief Callback function for ADCIFE interrupt.
 */
static void adcife_wm_handler(void)
{
	uint32_t ul_mode;
	uint16_t us_adc;

	/* Disable Window Monitor Interrupt. */
	adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);

	if ((adc_get_status(&g_adc_inst) & ADCIFE_SR_WM) == ADCIFE_SR_WM) {

		ul_mode = adc_get_wm_mode(&g_adc_inst);
		us_adc = adc_get_last_conv_value(&g_adc_inst);

		switch (ul_mode) {
		case 1:
			printf("-ISR-:DAC output voltage %d mv is above the low threshold:%d mv!\n\r",
					(int)(us_adc * VOLT_REF / MAX_DIGITAL),
					(int)(gs_us_low_threshold * VOLT_REF / MAX_DIGITAL));
			break;

		case 2:
			printf("-ISR-:DAC output voltage %d mv is below the high threshold:%d mv!\n\r",
					(int)(us_adc * VOLT_REF / MAX_DIGITAL),
					(int)(gs_us_high_threshold * VOLT_REF / MAX_DIGITAL));
			break;

		case 3:
			printf("-ISR-:DAC output voltage %d mv is in the comparison window:%d-%d mv!\n\r",
					(int)(us_adc * VOLT_REF / MAX_DIGITAL),
					(int)(gs_us_low_threshold * VOLT_REF / MAX_DIGITAL),
					(int)(gs_us_high_threshold * VOLT_REF / MAX_DIGITAL));
			break;

		case 4:
			printf("-ISR-:DAC output voltage %d mv is out of the comparison window:%d-%d mv!\n\r",
					(int)(us_adc * VOLT_REF / MAX_DIGITAL),
					(int)(gs_us_low_threshold * VOLT_REF / MAX_DIGITAL),
					(int)(gs_us_high_threshold * VOLT_REF / MAX_DIGITAL));
			break;
		}
		adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM);
	}
}
Ejemplo n.º 18
0
// Check whether all conversions have been completed since the last call to AnalogStartConversion
bool AnalogInCheckReady(uint32_t channels)
{
#if SAM3XA || SAM4S
	const uint32_t mask = channels & activeChannels;
	return (adc_get_status(ADC) & mask) == mask;
#elif SAM4E
	channels &= activeChannels;
	const uint32_t afec0Mask = channels & 0x0000FFFF;
	const uint32_t afec1Mask = (channels >> 16) & 0x0000FFFF;
	return (afec_get_interrupt_status(AFEC0) & afec0Mask) == afec0Mask
		&& (afec_get_interrupt_status(AFEC1) & afec1Mask) == afec1Mask;
#elif SAME70
	channels &= activeChannels;
	const uint32_t afec0Mask = channels & 0x000003FF;
	const uint32_t afec1Mask = (channels >> 10) & 0x000003FF;
	return (afec_get_interrupt_status(AFEC0) & afec0Mask) == afec0Mask
		&& (afec_get_interrupt_status(AFEC1) & afec1Mask) == afec1Mask;
#endif
}
Ejemplo n.º 19
0
/**
 * \brief ADC interrupt handler.
 */
void ADC_Handler(void)
{
	uint32_t ul_counter;
	int32_t l_vol;
	float f_temp;
	uint32_t ul_value = 0;
	uint32_t ul_temp_value = 0;

	if ((adc_get_status(ADC) & ADC_ISR_RXBUFF) == ADC_ISR_RXBUFF) {

		/* Multisample */
		for (ul_counter = 0; ul_counter < BUFFER_SIZE; ul_counter++) {
			ul_value += gs_s_adc_values[ul_counter];
		}
		/* Averaging */
		ul_temp_value = ul_value / 10;
		ul_value = ul_value / 100;
		ul_temp_value -= (ul_value * 10);
		/* Round for last decimal */
		if (ul_temp_value > 4) {
			ul_value++;
		}

		l_vol = ul_value * VOLT_REF / MAX_DIGITAL;
	#if SAM3S | SAM3XA	
		/* Using multiplication (*0.37736) instead of division (/2.65). */
		f_temp = (float)(l_vol - 800) * 0.37736 + 27.0;
	#else
		/* Using multiplication (*0.21186) instead of division (/4.72). */
		f_temp = (float)(l_vol - 1440) * 0.21186 + 27.0;
	#endif
		print_temp(f_temp);
		/* Clear the buffer. */
		memset(gs_s_adc_values, 0x0, sizeof(gs_s_adc_values));
		/* Start new pdc transfer. */
		adc_read_buffer(ADC, gs_s_adc_values, BUFFER_SIZE);

	}
}
Ejemplo n.º 20
0
int main(void)
{
	system_init();
	delay_init();
	
//! [setup_init]
	configure_adc();
//! [setup_init]

//! [main]
//! [start_conv]
	adc_start_conversion(&adc_instance);
//! [start_conv]

//! [get_res]
	uint16_t result=0;

	configure_console();
	

//! [get_res]

//! [inf_loop]
	while (1) {
		/* Infinite loop */
		//adc_read(&adc_instance, &result);
		do {
		/* Wait for conversion to be done and read out result */
		} while (adc_read(&adc_instance, &result) == STATUS_BUSY);
		printf("The result is %d\n",result);
		uint32_t far = 9.0/5.0*((float)result*.0002441406*6.0/.01)+32.0;
		printf(" The temp is %d", far);
		adc_clear_status(&adc_instance,adc_get_status(&adc_instance));
			adc_start_conversion(&adc_instance);
		delay_ms(500);
	}
//! [inf_loop]
//! [main]
}
Ejemplo n.º 21
0
void ADC_Handler(void)
{
	uint32_t ul_mode;
	uint16_t us_adc;

	/* Disable Compare Interrupt. */
	adc_disable_interrupt(ADC, ADC_IDR_COMPE);

	if ((adc_get_status(ADC) & ADC_ISR_COMPE) == ADC_ISR_COMPE) {
		ul_mode = adc_get_comparison_mode(ADC);
		us_adc = adc_get_channel_value(ADC, ADC_CHANNEL_POTENTIOMETER);

		switch (ul_mode) {
		case 0:
			printf("-ISR-:Potentiometer voltage %d mv is below the low "
				"threshold:%d mv!\n\r", us_adc * VOLT_REF / MAX_DIGITAL,
				gs_us_low_threshold * VOLT_REF / MAX_DIGITAL);
			break;

		case 1:
			printf("-ISR-:Potentiometer voltage %d mv is above the high "
				"threshold:%d mv!\n\r", us_adc * VOLT_REF / MAX_DIGITAL,
				gs_us_high_threshold * VOLT_REF / MAX_DIGITAL);
			break;

		case 2:
			printf("-ISR-:Potentiometer voltage %d mv is in the comparison "
				"window:%d-%d mv!\n\r", us_adc * VOLT_REF / MAX_DIGITAL,
				gs_us_low_threshold * VOLT_REF / MAX_DIGITAL, gs_us_high_threshold * VOLT_REF / MAX_DIGITAL);
			break;

		case 3:
			printf("-ISR-:Potentiometer voltage %d mv is out of the comparison"
				" window:%d-%d mv!\n\r", us_adc * VOLT_REF / MAX_DIGITAL,
				gs_us_low_threshold * VOLT_REF / MAX_DIGITAL, gs_us_high_threshold * VOLT_REF / MAX_DIGITAL);
			break;
		}
	}
}
Ejemplo n.º 22
0
uint16_t hal_analog_read(uint8_t adc_channel)
{
    uint32_t ulValue = 0;

    // Enable the corresponding channel
    adc_enable_channel( ADC, adc_channel );

    // Start the ADC
    adc_start( ADC );

    // Wait for end of conversion
    while ((adc_get_status(ADC) & ADC_ISR_DRDY) != ADC_ISR_DRDY)
      ;

    // Read the value
    ulValue = adc_get_latest_value(ADC);
    //!! ulValue = mapResolution(ulValue, ADC_RESOLUTION, _readResolution);

    // Disable the corresponding channel
    adc_disable_channel(ADC, adc_channel);

    return ulValue;
}
Ejemplo n.º 23
0
/**
 * \brief Systick handler, start new conversion.
 */
void SysTick_Handler(void)
{
	if ((adc_get_status(ADC) & ADC_ISR_EOC15) == ADC_ISR_EOC15) {
		adc_start(ADC);
	}
}
Ejemplo n.º 24
0
/**
 * \brief Configure to trigger ADC by PWM Event Line.
 */
static void configure_pwm_trigger(void)
{
	/* PWM frequency in Hz. */
#define PWM_FREQUENCY               2
	/* Maximum duty cycle value. */
#define MAX_DUTY_CYCLE              1000

	/* Enable PWMC peripheral clock. */
	pmc_enable_periph_clk(ID_PWM);

	/* Disable PWM channel 0. */
	pwm_channel_disable(PWM, PWM_CHANNEL_0);

	gpio_configure_pin(PIN_PWMC_PWMH0_TRIG, PIN_PWMC_PWMH0_TRIG_FLAG);

	/* Set clock A to run at PWM_FREQUENCY * MAX_DUTY_CYCLE (clock B is not used). */
	pwm_clock_t pwm_clock_setting = {
		.ul_clka = PWM_FREQUENCY * MAX_DUTY_CYCLE,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM, &pwm_clock_setting);

	/* Configure PWMC for channel 0 (left-aligned). */
		pwm_channel_t pwm_trigger_channel = {
			.channel = PWM_CHANNEL_0,
			.alignment = PWM_ALIGN_LEFT,
			.polarity = PWM_LOW,
		.ul_prescaler = PWM_CMR_CPRE_CLKA,
		.ul_period = MAX_DUTY_CYCLE,
		.ul_duty = MAX_DUTY_CYCLE / 2
	};
	pwm_channel_init(PWM, &pwm_trigger_channel);

	pwm_cmp_t pwm_comparison_setting = {
		.unit = PWM_CMP_UNIT_0,
		.b_enable = true,
		.ul_value = MAX_DUTY_CYCLE / 2,
		.b_pulse_on_line_0 = true
	};
	pwm_cmp_init(PWM, &pwm_comparison_setting);


	/* Enable PWM channel 0. */
	pwm_channel_enable(PWM, PWM_CHANNEL_0);
	/* Set PWM Event Line 0 trigger. */
#if SAM3S || SAM3XA || SAM4S
	adc_configure_trigger(ADC, ADC_TRIG_PWM_EVENT_LINE_0, 0);
#elif SAM3U
#ifdef ADC_12B
	adc12b_configure_trigger(ADC12B, ADC12B_TRIG_PWM_EVENT_LINE_0);
#else
	adc_configure_trigger(ADC, ADC_TRIG_PWM_EVENT_LINE_0);
#endif
#endif
}
#endif

/**
 * \brief Read converted data through PDC channel.
 *
 * \param p_adc The pointer of adc peripheral.
 * \param p_s_buffer The destination buffer.
 * \param ul_size The size of the buffer.
 */
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
static uint32_t adc_read_buffer(Adc * p_adc, uint16_t * p_s_buffer, uint32_t ul_size)
{
	/* Check if the first PDC bank is free. */
	if ((p_adc->ADC_RCR == 0) && (p_adc->ADC_RNCR == 0)) {
		p_adc->ADC_RPR = (uint32_t) p_s_buffer;
		p_adc->ADC_RCR = ul_size;
		p_adc->ADC_PTCR = ADC_PTCR_RXTEN;

		return 1;
	} else { /* Check if the second PDC bank is free. */
		if (p_adc->ADC_RNCR == 0) {
			p_adc->ADC_RNPR = (uint32_t) p_s_buffer;
			p_adc->ADC_RNCR = ul_size;

			return 1;
		} else {
			return 0;
		}
	}
}
#elif SAM3U
#ifdef ADC_12B
static uint32_t adc12_read_buffer(Adc12b * p_adc, uint16_t * p_s_buffer,
		uint32_t ul_size)
{
	/* Check if the first PDC bank is free. */
	if ((p_adc->ADC12B_RCR == 0) && (p_adc->ADC12B_RNCR == 0)) {
		p_adc->ADC12B_RPR = (uint32_t) p_s_buffer;
		p_adc->ADC12B_RCR = ul_size;
		p_adc->ADC12B_PTCR = ADC12B_PTCR_RXTEN;

		return 1;
	} else {	/* Check if the second PDC bank is free. */
		if (p_adc->ADC12B_RNCR == 0) {
			p_adc->ADC12B_RNPR = (uint32_t) p_s_buffer;
			p_adc->ADC12B_RNCR = ul_size;

			return 1;
		} else {
			return 0;
		}
	}
}
#else
static uint32_t adc_read_buffer(Adc * p_adc, uint16_t * p_s_buffer, uint32_t ul_size)
{
	/* Check if the first PDC bank is free. */
	if ((p_adc->ADC_RCR == 0) && (p_adc->ADC_RNCR == 0)) {
		p_adc->ADC_RPR = (uint32_t) p_s_buffer;
		p_adc->ADC_RCR = ul_size;
		p_adc->ADC_PTCR = ADC_PTCR_RXTEN;

		return 1;
	} else {	/* Check if the second PDC bank is free. */
		if (p_adc->ADC_RNCR == 0) {
			p_adc->ADC_RNPR = (uint32_t) p_s_buffer;
			p_adc->ADC_RNCR = ul_size;

			return 1;
		} else {
			return 0;
		}
	}
}
#endif
#endif

/**
 * \brief Start ADC sample.
 * Initialize ADC, set clock and timing, and set ADC to given mode.
 */
static void start_adc(void)
{
	/* Enable peripheral clock. */
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	uint32_t i;
	pmc_enable_periph_clk(ID_ADC);
#elif SAM3U
#ifdef ADC_12B
	pmc_enable_periph_clk(ID_ADC12B);
#else
	pmc_enable_periph_clk(ID_ADC);
#endif
#endif

	/* Initialize ADC. */
	/*
	 * Formula: ADCClock = MCK / ( (PRESCAL+1) * 2 )
	 * For example, MCK = 64MHZ, PRESCAL = 4, then:
	 * ADCClock = 64 / ((4+1) * 2) = 6.4MHz;
	 */
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	/* Formula:
	 *     Startup  Time = startup value / ADCClock
	 *     Startup time = 64 / 6.4MHz = 10 us
	 */
	adc_init(ADC, sysclk_get_cpu_hz(), 6400000, ADC_STARTUP_TIME_4);
#elif SAM3U
#ifdef ADC_12B
	/* Formula:
	 *     Startup  Time = (startup value + 1) * 8 / ADCClock
	 *     Startup time = (7 + 1) * 8 / 6.4MHz = 10 us
	 */
	adc12b_init(ADC12B, sysclk_get_cpu_hz(), 6400000, STARTUP_TIME, OFF_MODE_STARTUP_TIME);
#else
	/* Formula:
	 *     Startup  Time = (startup value + 1) * 8 / ADCClock
	 *     Startup time = (3 + 1) * 8 / 3.2MHz = 10 us
	 */
	adc_init(ADC, sysclk_get_cpu_hz(), 3200000, STARTUP_TIME);
#endif
#endif

	memset((void *)&g_adc_sample_data, 0, sizeof(g_adc_sample_data));

	/* Set ADC timing. */
#if SAM3S ||  SAM3XA || SAM4S
	/* Formula:
	 *     Transfer Time = (TRANSFER * 2 + 3) / ADCClock
	 *     Tracking Time = (TRACKTIM + 1) / ADCClock
	 *     Settling Time = settling value / ADCClock
	 *
	 *     Transfer Time = (1 * 2 + 3) / 6.4MHz = 781 ns
	 *     Tracking Time = (1 + 1) / 6.4MHz = 312 ns
	 *     Settling Time = 3 / 6.4MHz = 469 ns
	 */
	adc_configure_timing(ADC, TRACKING_TIME, ADC_SETTLING_TIME_3, TRANSFER_PERIOD);
#elif  SAM3N || SAM4C
	adc_configure_timing(ADC, TRACKING_TIME);
#elif SAM3U
	/* Formula:
	 *     Sample & Hold Time = SHTIM/ADCClock
	 *
	 *     Sample & Hold Time = 6 / 6.4 = 938 ns
	 */
#ifdef ADC_12B
	adc12b_configure_timing(ADC12B, SAMPLE_HOLD_TIME);
#else
	adc_configure_timing(ADC, SAMPLE_HOLD_TIME);
#endif
#endif

#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	/* Enable channel number tag. */
	adc_enable_tag(ADC);
	/* Enable/disable sequencer. */
	if (g_adc_test_mode.uc_sequence_en) {
		/* Set user defined channel sequence. */
		adc_configure_sequence(ADC, ch_list, 2);

		/* Enable sequencer. */
		adc_start_sequencer(ADC);

		/* Enable channels. */
		for (i = 0; i < 2; i++) {
			adc_enable_channel(ADC, (enum adc_channel_num_t)i);
		}
		/* Update channel number. */
		g_adc_sample_data.uc_ch_num[0] = ch_list[0];
		g_adc_sample_data.uc_ch_num[1] = ch_list[1];
	} else {
		/* Disable sequencer. */
		adc_stop_sequencer(ADC);

		/* Enable channels. */
		adc_enable_channel(ADC, ADC_CHANNEL_POTENTIOMETER);
#if SAM3S || SAM3XA || SAM4S || SAM4C
		adc_enable_channel(ADC, ADC_TEMPERATURE_SENSOR);
#endif
		/* Update channel number. */
		g_adc_sample_data.uc_ch_num[0] = ADC_CHANNEL_POTENTIOMETER;
#if SAM3S || SAM3XA || SAM4S || SAM4C
		g_adc_sample_data.uc_ch_num[1] = ADC_TEMPERATURE_SENSOR;
#else
		g_adc_sample_data.uc_ch_num[1] = ADC_CHANNEL_POTENTIOMETER;
#endif
	}
#elif SAM3U
#ifdef ADC_12B
	adc12b_enable_channel(ADC12B, ADC_CHANNEL_POTENTIOMETER);
#else
	adc_enable_channel(ADC, ADC_CHANNEL_POTENTIOMETER);
#endif
	g_adc_sample_data.uc_ch_num[0] = ADC_CHANNEL_POTENTIOMETER;
	g_adc_sample_data.uc_ch_num[1] = ADC_CHANNEL_POTENTIOMETER;
#endif

#if SAM3S ||  SAM3XA || SAM4S || SAM4C
	/* Enable the temperature sensor. */
	adc_enable_ts(ADC);
#endif
	/* Set gain and offset (only single ended mode used here). */
#if SAM3S || SAM3XA || SAM4S
	adc_disable_anch(ADC); /* Disable analog change. */
#endif
	if (g_adc_test_mode.uc_gain_en) {
#if SAM3S || SAM3XA || SAM4S
		adc_enable_anch(ADC);
		/* gain = 2 */
		adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_2);
#elif SAM3U
#ifdef ADC_12B
		adc12b_set_input_gain(ADC12B, ADC_GAINVALUE_2);
#endif
#endif
	} else {
#if SAM3S || SAM3XA || SAM4S
		/* gain = 1 */
		adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_0);
#elif SAM3U
#ifdef ADC_12B
		adc12b_set_input_gain(ADC12B, ADC_GAINVALUE_0);
#endif
#endif
	}

	if (g_adc_test_mode.uc_offset_en) {
#if SAM3S || SAM3XA || SAM4S
		adc_enable_anch(ADC);
		adc_enable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER);
#elif 	SAM3U
#ifdef ADC_12B
		adc12b_enable_input_offset(ADC12B);
#endif
#endif
	} else {
#if SAM3S || SAM3XA || SAM4S
		adc_disable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER);
#elif 	SAM3U
#ifdef ADC_12B
		adc12b_disable_input_offset(ADC12B);
#endif
#endif
	}
	/* Set Auto Calibration Mode. */
#if  SAM3S8 || SAM3SD8 || SAM4S
	if (g_adc_test_mode.uc_auto_calib_en) {
		adc_set_calibmode(ADC);
		while (1) {
			if ((adc_get_status(ADC) & ADC_ISR_EOCAL) ==
					ADC_ISR_EOCAL)
				break;
		}
	}
#endif

#if SAM3S8 || SAM4S || SAM3N || SAM3SD8
	/* Set power save. */
	if (g_adc_test_mode.uc_power_save_en) {
		adc_configure_power_save(ADC, 1, 0);
	} else {
		adc_configure_power_save(ADC, 0, 0);;
	}
#elif SAM3U || SAM4C
#ifdef ADC_12B
	/* Set power save. */
	if (g_adc_test_mode.uc_power_save_en) {
		adc12b_configure_power_save(ADC12B, 1, 0);
	} else {
		adc12b_configure_power_save(ADC12B, 0, 0);;
	}

#else
	/* Set power save. */
	if (g_adc_test_mode.uc_power_save_en) {
		adc_configure_power_save(ADC, 1);
	} else {
		adc_configure_power_save(ADC, 0);;
	}
#endif
#endif

#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	/* Transfer with/without PDC. */
	if (g_adc_test_mode.uc_pdc_en) {
		adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);
		/* Enable PDC channel interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_RXBUFF);
	} else {
		/* Enable Data ready interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_DRDY);
	}
	/* Enable ADC interrupt. */
	NVIC_EnableIRQ(ADC_IRQn);
#elif SAM3U
#ifdef ADC_12B
	/* Transfer with/without PDC. */
	if (g_adc_test_mode.uc_pdc_en) {
		adc12_read_buffer(ADC12B, g_adc_sample_data.us_value, BUFFER_SIZE);
		/* Enable PDC channel interrupt. */
		adc12b_enable_interrupt(ADC12B, ADC12B_IER_RXBUFF);
	} else {
		/* Enable Data ready interrupt. */
		adc12b_enable_interrupt(ADC12B, ADC12B_IER_DRDY);

	}
	/* Enable ADC interrupt. */
	NVIC_EnableIRQ(ADC12B_IRQn);
#else
	/* Transfer with/without PDC. */
	if (g_adc_test_mode.uc_pdc_en) {
		adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);
		/* Enable PDC channel interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_RXBUFF);
	} else {
		/* Enable Data ready interrupt. */
		adc_enable_interrupt(ADC, ADC_IER_DRDY);

	}
	/* Enable ADC interrupt. */
	NVIC_EnableIRQ(ADC_IRQn);
#endif
#endif
	/* Configure trigger mode and start convention. */
	switch (g_adc_test_mode.uc_trigger_mode) {
	case TRIGGER_MODE_SOFTWARE:
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
		adc_configure_trigger(ADC, ADC_TRIG_SW, 0);	/* Disable hardware trigger. */
#elif SAM3U
#ifdef ADC_12B
		adc12b_configure_trigger(ADC12B, ADC12B_TRIG_SW);
#else
		adc_configure_trigger(ADC, ADC_TRIG_SW);
#endif
#endif
		break;

	case TRIGGER_MODE_ADTRG:
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
		gpio_configure_pin(PINS_ADC_TRIG, PINS_ADC_TRIG_FLAG);
		adc_configure_trigger(ADC, ADC_TRIG_EXT, 0);
#elif SAM3U
#ifdef ADC_12B
		gpio_configure_pin(PINS_ADC12B_TRIG, PINS_ADC12B_TRIG_FLAG);
		adc12b_configure_trigger(ADC12B, ADC12B_TRIG_EXT);
#else
		gpio_configure_pin(PINS_ADC_TRIG, PINS_ADC_TRIG_FLAG);
		adc_configure_trigger(ADC, ADC_TRIG_EXT);
#endif
#endif
		break;

	case TRIGGER_MODE_TIMER:
		configure_time_trigger();
		break;
#if SAM3S || SAM3U || SAM3XA || SAM4S
	case TRIGGER_MODE_PWM:
		configure_pwm_trigger();
		break;
#endif
#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
	case TRIGGER_MODE_FREERUN:
		adc_configure_trigger(ADC, ADC_TRIG_SW, 1);
		break;
#endif
	default:
		break;
	}
}

/**
 * \brief Systick handler.
 */
void SysTick_Handler(void)
{
	gs_ul_ms_ticks++;
}

#if SAM3S || SAM3N || SAM3XA || SAM4S || SAM4C
/**
 * \brief Interrupt handler for the ADC.
 */
void ADC_Handler(void)
{
	uint32_t i;
	uint32_t ul_temp;
	uint8_t uc_ch_num;

	/* With PDC transfer */
	if (g_adc_test_mode.uc_pdc_en) {
		if ((adc_get_status(ADC) & ADC_ISR_RXBUFF) ==
				ADC_ISR_RXBUFF) {
			g_adc_sample_data.us_done = ADC_DONE_MASK;
			adc_read_buffer(ADC, g_adc_sample_data.us_value, BUFFER_SIZE);
			/* Only keep sample value, and discard channel number. */
			for (i = 0; i < NUM_CHANNELS; i++) {
				g_adc_sample_data.us_value[i] &= ADC_LCDR_LDATA_Msk;
			}
		}
	} else {	/* Without PDC transfer */
		if ((adc_get_status(ADC) & ADC_ISR_DRDY) ==
				ADC_ISR_DRDY) {
			ul_temp = adc_get_latest_value(ADC);
			for (i = 0; i < NUM_CHANNELS; i++) {
				uc_ch_num = (ul_temp & ADC_LCDR_CHNB_Msk) >>
						ADC_LCDR_CHNB_Pos;
				if (g_adc_sample_data.uc_ch_num[i] == uc_ch_num) {
					g_adc_sample_data.us_value[i] =
							ul_temp &
							ADC_LCDR_LDATA_Msk;
					g_adc_sample_data.us_done |= 1 << i;
				}
			}
		}
	}
}
Ejemplo n.º 25
0
/**
 *  \brief ACC example application entry point.
 *
 *  \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	uint8_t uc_key;
	int16_t s_volt = 0;
	uint32_t ul_value = 0;
	volatile uint32_t ul_status = 0x0;
	int32_t l_volt_dac0 = 0;

	/* Initialize the system */
	sysclk_init();
	board_init();

	/* Initialize debug console */
	configure_console();

	/* Output example information */
	puts(STRING_HEADER);

	/* Initialize DACC */
	/* Enable clock for DACC */
	pmc_enable_periph_clk(ID_DACC);
	/* Reset DACC registers */
	dacc_reset(DACC);
	/* External trigger mode disabled. DACC in free running mode. */
	dacc_disable_trigger(DACC);
	/* Half word transfer mode */
	dacc_set_transfer_mode(DACC, 0);
	/* Power save:
	 * sleep mode  - 0 (disabled)
	 * fast wake-up - 0 (disabled)
	 */
	dacc_set_power_save(DACC, 0, 0);
	/* Timing:
	 * refresh        - 0x08 (1024*8 dacc clocks)
	 * max speed mode -    0 (disabled)
	 * startup time   - 0xf (960 dacc clocks)
	 */
	dacc_set_timing(DACC, 0x08, 0, 0xf);
	/* Disable TAG and select output channel DACC_CHANNEL */
	dacc_set_channel_selection(DACC, DACC_CHANNEL_0);
	/* Enable output channel DACC_CHANNEL */
	dacc_enable_channel(DACC, DACC_CHANNEL_0);
	/* Setup analog current */
	dacc_set_analog_control(DACC, DACC_ANALOG_CONTROL);

	/* Set DAC0 output at ADVREF/2. The DAC formula is:
	 *
	 * (5/6 * VOLT_REF) - (1/6 * VOLT_REF)     volt - (1/6 * VOLT_REF)
	 * ----------------------------------- = --------------------------
	 *              MAX_DIGITAL                       digit
	 *
	 * Here, digit = MAX_DIGITAL/2
	 */
	dacc_write_conversion_data(DACC, MAX_DIGITAL / 2);
	l_volt_dac0 = (MAX_DIGITAL / 2) * (2 * VOLT_REF / 3) / MAX_DIGITAL +
			VOLT_REF / 6;

	/* Initialize ADC */
	/* Enable clock for ADC */
	pmc_enable_periph_clk(ID_ADC);
	/*
	 * Formula: ADCClock = MCK / ( (PRESCAL+1) * 2 )
	 * For example, MCK = 64MHZ, PRESCAL = 4, then:
	 *     ADCClock = 64 / ((4+1) * 2) = 6.4MHz;
	 */
	adc_init(ADC, sysclk_get_cpu_hz(), ADC_CLOCK, ADC_STARTUP_TIME_SETTING);

	/* Formula:
	 *     Startup  Time = startup value / ADCClock
	 *     Transfer Time = (TRANSFER * 2 + 3) / ADCClock
	 *     Tracking Time = (TRACKTIM + 1) / ADCClock
	 *     Settling Time = settling value / ADCClock
	 * For example, ADC clock = 6MHz (166.7 ns)
	 *     Startup time = 512 / 6MHz = 85.3 us
	 *     Transfer Time = (1 * 2 + 3) / 6MHz = 833.3 ns
	 *     Tracking Time = (0 + 1) / 6MHz = 166.7 ns
	 *     Settling Time = 3 / 6MHz = 500 ns
	 */
	/* Set ADC timing */
	adc_configure_timing(ADC, ADC_TRACK_SETTING, ADC_SETTLING_TIME_3,
			ADC_TRANSFER_SETTING);

	/* Channel 5 has to be compared */
	adc_enable_channel(ADC, ADC_CHANNEL_5);

	//! [acc_enable_clock]
	/** Enable clock for ACC */
	pmc_enable_periph_clk(ID_ACC);
	//! [acc_enable_clock]

	//! [acc_init]
	/** Initialize ACC */
	acc_init(ACC, ACC_MR_SELPLUS_AD5, ACC_MR_SELMINUS_DAC0,
			ACC_MR_EDGETYP_ANY, ACC_MR_INV_DIS);
	//! [acc_init]

	//! [acc_irq_enable]
	/** Enable ACC interrupt */
	NVIC_EnableIRQ(ACC_IRQn);

	/** Enable */
	acc_enable_interrupt(ACC);
	//! [acc_irq_enable]

	dsplay_menu();

	while (1) {
		while (uart_read(CONSOLE_UART, &uc_key)) {
		}

		printf("input: %c\r\n", uc_key);

		switch (uc_key) {
		case 's':
		case 'S':
			printf("Input DAC0 output voltage (%d~%d mv): ",
					(VOLT_REF / 6), (VOLT_REF * 5 / 6));
			s_volt = get_input_voltage();
			puts("\r");

			if (s_volt > 0) {
				l_volt_dac0 = s_volt;
				/* The DAC formula is:
				 *
				 * (5/6 * VOLT_REF) - (1/6 * VOLT_REF)     volt - (1/6 * VOLT_REF)
				 * ----------------------------------- = --------------------------
				 *              MAX_DIGITAL                       digit
				 *
				 */
				ul_value = ((s_volt - (VOLT_REF / 6))
					* (MAX_DIGITAL * 6) / 4) / VOLT_REF;
				dacc_write_conversion_data(DACC, ul_value);
				puts("-I- Set ok\r");
			} else {
				puts("-I- Input voltage is invalid\r");
			}
			break;
		case 'v':
		case 'V':
			/* Start conversion */
			adc_start(ADC);
			ul_status = adc_get_status(ADC);
			while ((ul_status & ADC_ISR_EOC5) != ADC_ISR_EOC5) {
				ul_status = adc_get_status(ADC);
			}
			/* Conversion is done */
			ul_value = adc_get_channel_value(ADC, ADC_CHANNEL_5);

			/*
			 * Convert ADC sample data to voltage value:
			 * voltage value = (sample data / max. resolution) * reference voltage
			 */
			s_volt = (ul_value * VOLT_REF) / MAX_DIGITAL;
			printf("-I- Voltage on potentiometer(AD5) is %d mv\n\r", s_volt);
			printf("-I- Voltage on DAC0 is %ld mv \n\r", (long)l_volt_dac0);
			break;
			
		case 'm':
		case 'M':
			dsplay_menu();
			break;
		}
	}
}
Ejemplo n.º 26
0
/**
 * \brief Test ADCIFE in Differential mode.
 *
 * \param test Current test case.
 */
static void run_adcife_diff_test(const struct test_case *test)
{
	uint32_t timeout = ADC_NUM_OF_ATTEMPTS;
	bool conversion_timeout = false;

	struct adc_seq_config adc_seq_cfg = {
		/* Select Vref for shift cycle */
		.zoomrange = ADC_ZOOMRANGE_0,
		/* Pad Ground */
		.muxneg = ADC_MUXNEG_1,
		/* Scaled Vcc, Vcc/10 */
		.muxpos = ADC_MUXPOS_2,
		/* Enables the internal voltage sources */
		.internal = ADC_INTERNAL_3,
		/* Disables the ADC gain error reduction */
		.gcomp = ADC_GCOMP_DIS,
		/* Disables the HWLA mode */
		.hwla = ADC_HWLA_DIS,
		/* 12-bits resolution */
		.res = ADC_RES_12_BIT,
		/* Enables the differential mode */
		.bipolar = ADC_BIPOLAR_DIFFERENTIAL
	};
	struct adc_ch_config adc_ch_cfg = {
		.seq_cfg = &adc_seq_cfg,
		/* Internal Timer Max Counter */
		.internal_timer_max_count = 60,
		/* Window monitor mode is off */
		.window_mode = 0,
		.low_threshold = 0,
		.high_threshold = 0,
	};

	adc_ch_set_config(&g_adc_inst, &adc_ch_cfg);
	adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON);
	adc_configure_gain(&g_adc_inst, ADC_GAIN_1X);
	while (!((adc_get_status(&g_adc_inst) & ADCIFE_SR_SEOC) ==
			ADCIFE_SR_SEOC)) {
		if (!timeout--) {
			conversion_timeout = true;
		}
	}

	test_assert_true(test, conversion_timeout == false, "ADCIFE Differential conversion timeout");

	/* Because selected channel is positive input, then in differential mode
	 * the output conversion result will = 2047 + (Vin/Vref)*2047.
	 */
	test_assert_true(test, adc_get_last_conv_value(&g_adc_inst) > 2047,
			"ADCIFE Differential test failed");
}

/**
 * \brief Test ADCIFE in internal timer trigger mode,
 *        which also tests interrupt driven conversions.
 *
 * \param test Current test case.
 */
static void run_adcife_itimer_trig_test(const struct test_case *test)
{
	struct adc_seq_config adc_seq_cfg = {
		/* Select Vref for shift cycle */
		.zoomrange = ADC_ZOOMRANGE_0,
		/* Pad Ground */
		.muxneg = ADC_MUXNEG_1,
		/* Scaled Vcc, Vcc/10 */
		.muxpos = ADC_MUXPOS_2,
		/* Enables the internal voltage sources */
		.internal = ADC_INTERNAL_3,
		/* Disables the ADC gain error reduction */
		.gcomp = ADC_GCOMP_DIS,
		/* Disables the HWLA mode */
		.hwla = ADC_HWLA_DIS,
		/* 12-bits resolution */
		.res = ADC_RES_12_BIT,
		/* Enables the single-ended mode */
		.bipolar = ADC_BIPOLAR_SINGLEENDED
	};
	struct adc_ch_config adc_ch_cfg = {
		.seq_cfg = &adc_seq_cfg,
		/* Internal Timer Max Counter */
		.internal_timer_max_count = 60,
		/* Window monitor mode is off */
		.window_mode = 0,
		.low_threshold = 0,
		.high_threshold = 0,
	};

	adc_ch_set_config(&g_adc_inst, &adc_ch_cfg);
	adc_set_callback(&g_adc_inst, ADC_SEQ_SEOC, adcife_set_conv_flag,
			ADCIFE_IRQn, 1);
	adc_configure_trigger(&g_adc_inst, ADC_TRIG_INTL_TIMER);
	adc_configure_gain(&g_adc_inst, ADC_GAIN_1X);
	adc_configure_itimer_period(&g_adc_inst,
			adc_ch_cfg.internal_timer_max_count);
	adc_start_itimer(&g_adc_inst);
	delay_ms(100);

	test_assert_true(test, g_uc_condone_flag == 1,
			"ADCIFE Internal Timer trigger test failed");
}

/* When VDDANA is in MIN value = 2.4V, the equivalent voltage value is
 * (2400 * 255) / ((1 << 10) - 1) = 598mv. The relative digital value is
 * 598 * 4095 / 1000 = 2449. */
#define DAC_INTERNAL_MIN_VALUE          2449
/* When VDDANA is in MAX value = 3.6V the equivalent voltage value is
 * (3600 * 255) / ((1 << 10) - 1) = 897mv. The relative digital value is
 * 897 * 4095 / 1000 = 3673. */
#define DAC_INTERNAL_MAX_VALUE          3673
/* When VCC is in MIN value = 1.6V, the equivalent voltage value is
 * 1600 / 10 = 160mv. The relative digital value is
 * 160 * 4095 / 1000 = 434. */
#define VCC_SCALED_MIN_VALUE            434
/* When VCC is in MAX value = 3.6V, the equivalent voltage value is
 * 3600 / 10 = 360mv. The relative digital value is
 * 360 * 4095 / 1000 = 1474. */
#define VCC_SCALED_MAX_VALUE            1474

/**
 * \brief Test ADCIFE in multiple channel mode.
 *
 * \param test Current test case.
 */
static void run_adcife_multichannel_test(const struct test_case *test)
{
	start_dac();

	adc_pdca_set_config(&g_adc_pdca_cfg);
	pdca_channel_set_callback(CONFIG_ADC_PDCA_RX_CHANNEL, pdca_transfer_done,
			PDCA_0_IRQn, 1, PDCA_IER_TRC);
	adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON);
	adc_configure_gain(&g_adc_inst, ADC_GAIN_1X);

	delay_ms(100);

	/* The DAC output voltage value is 823mv, so the equivalent ADC value should be
	 * 4095 * 823 / 1000 = 3370. The scaled VCC output voltage is 330mv, so the
	 * equivalent ADC value should be 4095 * 330 / 1000 =  1351. */
	test_assert_true(test,
			((DAC_INTERNAL_MIN_VALUE < g_adc_sample_data[0] < DAC_INTERNAL_MAX_VALUE)
			&& (VCC_SCALED_MIN_VALUE < g_adc_sample_data[1] < VCC_SCALED_MAX_VALUE)),
			"ADCIFE Multichannel test failed");
}

/**
 * \brief Test ADCIFE in window monitor mode.
 *
 * \param test Current test case.
 */
static void run_adcife_wm_test(const struct test_case *test)
{
	struct adc_seq_config adc_seq_cfg = {
		/* Select Vref for shift cycle */
		.zoomrange = ADC_ZOOMRANGE_0,
		/* Pad Ground */
		.muxneg = ADC_MUXNEG_1,
		/* Scaled Vcc, Vcc/10 */
		.muxpos = ADC_MUXPOS_2,
		/* Enables the internal voltage sources */
		.internal = ADC_INTERNAL_3,
		/* Disables the ADC gain error reduction */
		.gcomp = ADC_GCOMP_DIS,
		/* Disables the HWLA mode */
		.hwla = ADC_HWLA_DIS,
		/* 12-bits resolution */
		.res = ADC_RES_12_BIT,
		/* Enables the single-ended mode */
		.bipolar = ADC_BIPOLAR_SINGLEENDED
	};
	struct adc_ch_config adc_ch_cfg = {
		.seq_cfg = &adc_seq_cfg,
		/* Internal Timer Max Counter */
		.internal_timer_max_count = 60,
		/* Window monitor mode is off */
		.window_mode = ADC_WM_MODE_3,
		/*  The equivalent voltage value is 205 * 1000 / 4095 = 50mv. */
		.low_threshold = 205,
		/*  The equivalent voltage value is 2050 * 1000 / 4095 = 500mv. */
		.high_threshold = 2050,
	};

	adc_ch_set_config(&g_adc_inst, &adc_ch_cfg);
	adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON);
	adc_configure_gain(&g_adc_inst, ADC_GAIN_1X);

	adc_set_callback(&g_adc_inst, ADC_WINDOW_MONITOR, adcife_set_wm_flag,
			ADCIFE_IRQn, 1);
	delay_ms(100);
	test_assert_true(test, g_uc_enter_win_flag == 1,
			"ADCIFE Inside Window Mode test failed");

	/* The teseted channel voltage is outside window */
	adc_disable(&g_adc_inst);
	g_uc_enter_win_flag = 0;
	adc_seq_cfg.muxpos = ADC_MUXPOS_3;
	adc_ch_set_config(&g_adc_inst, &adc_ch_cfg);
	adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON);
	adc_configure_gain(&g_adc_inst, ADC_GAIN_1X);
	adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);

	delay_ms(100);
	test_assert_true(test, g_uc_enter_win_flag == 0,
			"ADCIFE Outside Window Mode test failed");
}

/**
 * \brief Run ADCIFE driver unit tests.
 */
int main(void)
{
	const usart_serial_options_t usart_serial_options = {
		.baudrate = CONF_TEST_BAUDRATE,
		.charlength = CONF_TEST_CHARLENGTH,
		.paritytype = CONF_TEST_PARITY,
		.stopbits = CONF_TEST_STOPBITS
	};

	/* Initialize the system clock and board */
	sysclk_init();
	board_init();

	/* Enable the debug uart */
	stdio_serial_init(CONF_TEST_USART, &usart_serial_options);

#if defined(__GNUC__)
	setbuf(stdout, NULL);
#endif

	/* Define all the test cases */
	DEFINE_TEST_CASE(adcife_init_test, NULL, run_adcife_init_test, NULL,
			"ADCIFE Initialize test");
	DEFINE_TEST_CASE(adcife_diff_test, NULL, run_adcife_diff_test, NULL,
			"ADCIFE Differential test");
	DEFINE_TEST_CASE(adcife_itmer_trig_test, NULL, run_adcife_itimer_trig_test,
			NULL, "ADCIFE Internal Timer trigger test");
	DEFINE_TEST_CASE(adcife_multichannel_test, NULL, run_adcife_multichannel_test, NULL,
			"ADCIFE Multichannel test");
	DEFINE_TEST_CASE(adcife_wm_test, NULL, run_adcife_wm_test,
			NULL, "ADCIFE Window Monitor Mode test");

	/* Put test case addresses in an array */
	DEFINE_TEST_ARRAY(adcife_tests) = {
	&adcife_init_test,
	&adcife_diff_test,
	&adcife_itmer_trig_test,
	&adcife_multichannel_test,
	&adcife_wm_test,
	};

	/* Define the test suite */
	DEFINE_TEST_SUITE(adcife_suite, adcife_tests,
			"SAM ADCIFE driver test suite");

	/* Run all tests in the test suite */
	test_suite_run(&adcife_suite);

	while (1) {
		/* Busy-wait forever. */
	}
}