Beispiel #1
0
/**
 * \brief Test events driver with Software trigger.
 *
 * \param test Current test case.
 */
static void run_events_software_test(const struct test_case *test)
{
	uint32_t retry_times = 3;
	bool trigger_flag = false;

	/* Enable software trigger */
	events_ch_enable_software_trigger(CONF_TEST_USER_ID);

	/* Set new DACC value */
	dacc_write_conversion_data(DACC, DACC_MAX_DATA / 5);

	/* Software event trigger */
	events_ch_clear_trigger_status(CONF_TEST_USER_ID);
	do {
		events_ch_software_trigger(CONF_TEST_USER_ID);
		delay_ms(100);
		if (events_ch_is_triggered(CONF_TEST_USER_ID)) {
			trigger_flag = true;
			events_ch_clear_trigger_status(CONF_TEST_USER_ID);
			break;
		}
	} while (retry_times--);

	test_assert_true(test, trigger_flag, "Software event not triggered!");
}
Beispiel #2
0
void update_speed_motor_dac(float dac_float){
	uint32_t negativo = 0;
	//Verificando a necessidade de alterar a rotação do motor:
	if ( (dac_float < 0) && (MotorIsFoward) ){
		Reverse_Motor; //Invertendo rotação do Motor
		flag_revertion = !flag_revertion;
		hallA = 0;
		hallB = 0;
		} else if ( (dac_float > 0) && (MotorIsReverse) ) {
		Foward_Motor;
		flag_revertion = !flag_revertion;
		hallA = 0;
		hallB = 0;
	}
	
	if (dac_float < 0){
		dac_float = -dac_float;
		negativo = 1;
	}
	
	if (dac_float > DACC_MAX_DATA){
		dac_float = DACC_MAX_DATA;
	}
	//Transformar Valor de RPM para DAC(0-1023)
	dac_val = dac_float;
	while((dacc_get_interrupt_status(DACC) & DACC_ISR_TXRDY) != DACC_ISR_TXRDY);
	dacc_write_conversion_data(DACC, dac_val);
	if (negativo){
		dac_val = -dac_val;
	}
}
Beispiel #3
0
void TC0_Handler(void){

  volatile uint32_t ul_dummy, status;
  uint32_t valorDAC = 1024;
  ul_dummy = tc_get_status(TC0,0);
  UNUSED(ul_dummy);
  

  /************************************************************************/
  /* ADC                                                                     */
  /************************************************************************/
  if(nleituraADC >= 500){
	 adc_start(ADC);
	 nleituraADC = 0;
   }
   nleituraADC++;

  /************************************************************************/
  /* Escreve um novo valor no DAC                                         */
  /************************************************************************/
  status = dacc_get_interrupt_status(DACC_BASE);

  /* namostra > 2*pi  ?? */
  if(namostra > resolucao)
	namostra = 0;

  ySeno = (sin(deltaTeta*namostra)+1)*((float)max_digital)/MAX_AMPLITUDE_ANAG;
  dacc_write_conversion_data(DACC_BASE, ySeno);

  namostra++;

 
}
Beispiel #4
0
void update_speed_motor(float speed){
	uint32_t negativo = 0;
	//Verificando a necessidade de alterar a rotação do motor:
	if ( (speed < 0) && (MotorIsFoward) ){
		Reverse_Motor; //Invertendo rotação do Motor
		//speed = -speed;
		flag_revertion = !flag_revertion;
		hallA = 0;
		hallB = 0;
		} else if ( (speed > 0) && (MotorIsReverse) ) {
		Foward_Motor;
		flag_revertion = !flag_revertion;
		hallA = 0;
		hallB = 0;
	}
	
	if (speed < 0){
		speed = -speed;
		negativo = 1;
	}
	
	if (speed > MOTOR_MAX_RPM){
		speed = MOTOR_MAX_RPM;
	}
	//Transformar Valor de RPM para DAC(0-1023)
	dac_val = speed*RPMtoDAC + yo;
	while((dacc_get_interrupt_status(DACC) & DACC_ISR_TXRDY) != DACC_ISR_TXRDY);
	dacc_write_conversion_data(DACC, dac_val);
	if (negativo){
		dac_val = -dac_val;
	}
}
Beispiel #5
0
// 40kHz sampler.
//
// Runs at too high a priority to call FreeRTOS routines.
// This routine executes each (approximately) 2000 cycles. It is important that
// it is not slow.
void PWM_Handler(void) {
	// Read status to indicate that interrupt has been handled
	uint32_t isr = PWM->PWM_ISR1;
	if (isr != (1 << 2)) { // Must be interrupt two
		fatalBlink(1, 6);
	}
	
	if (mode == AM_ADC) {
		// Temporary code - read ADC, calculate result.
		// TODO: replace with DMA.
		// TODO: handle fading.
		uint32_t data0 = adc_get_channel_value(ADC, 0);
		uint32_t data1 = adc_get_channel_value(ADC, 1);
		uint32_t sum = data0 + data1; // sum is a 13 bit value
	
		// Calculate output value for DACC
		dacc_write_conversion_data(DACC, sum / 2);
	
		// Calculate duty cycle value for PWM Channel 2.
		// Calculated value must be between 0 and US_PERIOD-1, non inclusive.
	
		int32_t duty = ((US_PERIOD - 2) * sum / 8192) + 1;
		// For testing with silence
		// int32_t duty = US_PERIOD / 2;
		PWM->PWM_CH_NUM[2].PWM_CDTYUPD = duty;	
	} else if (mode == AM_HZ) {
		
		// Get TIOA value from status register
		bool mtioa = TC0->TC_CHANNEL[0].TC_SR & TC_SR_MTIOA;
		
		// Write to DACC
		int16_t dDelta = 2046 * audioVolume / 255;
		if (!mtioa) {
			dDelta = -dDelta;
		}
		dacc_write_conversion_data(DACC, dDelta + 2048);
		
		// Set PWM
		int16_t pDelta = (US_PERIOD - 2) / 2 * audioVolume / 255;
		if (!mtioa) {
			pDelta = -pDelta;
		}
		PWM->PWM_CH_NUM[2].PWM_CDTYUPD = pDelta + (US_PERIOD / 2);
	}
}
Beispiel #6
0
void task_PID(void *pvParameters) 
{
	const portTickType xTimeIncrement = 100;
	real_Target = calculateDistance(sent_Target);
	e = real_Target - distance;
	
	u = Kp * (e);
	dacc_write_conversion_data(DACC, u);
	sendParameters(e, distance);
	vTaskDelay(50);					// 50 millisecond delay
}
Beispiel #7
0
/**
 * \brief Test events driver with AST trigger.
 *
 * \param test Current test case.
 */
static void run_events_ast_test(const struct test_case *test)
{
	uint32_t retry_times = 3;
	bool trigger_flag = false;
	struct events_conf    events_config;
	struct events_ch_conf ch_config;

	init_ast();
	init_dacc();

	/* Initialize event module */
	events_get_config_defaults(&events_config);
	events_init(&events_config);
	events_enable();

	/*
	 * Configure an event channel
	 * - AST periodic event 0  --- Generator
	 * - DAC                   --- User
	 */
	events_ch_get_config_defaults(&ch_config);
	ch_config.channel_id = CONF_TEST_USER_ID;
	ch_config.generator_id = CONF_TEST_GEN_ID;
	ch_config.shaper_enable = true;
	ch_config.igf_edge = EVENT_IGF_EDGE_NONE;
	events_ch_configure(&ch_config);

	/* Enable the channel */
	events_ch_enable(CONF_TEST_USER_ID);

	/* Set new DACC value */
	dacc_write_conversion_data(DACC, DACC_MAX_DATA / 2);


	/* Wait for AST event trigger */
	events_ch_clear_trigger_status(CONF_TEST_USER_ID);
	do {
		if (events_ch_is_triggered(CONF_TEST_USER_ID)) {
			trigger_flag = true;
			events_ch_clear_trigger_status(CONF_TEST_USER_ID);
			break;
		}
		delay_ms(1000);
	} while (retry_times--);

	/* Disable the AST */
	ast_disable(AST);

	test_assert_true(test, trigger_flag, "AST event not triggered!");
}
Beispiel #8
0
/**
*  Interrupt handler for TC0 interrupt.
*/
void TC0_Handler(void){
  volatile uint32_t ul_dummy, status;
  uint32_t valorDAC = 1024;
  ul_dummy = tc_get_status(TC0,0);
  UNUSED(ul_dummy);
  
  /************************************************************************/
  /* Escreve um novo valor no DAC                                         */
  /************************************************************************/
  //status = dacc_get_interrupt_status(DACC_BASE);
  //dacc_write_conversion_data(DACC_BASE, valorDAC);
  
  if (i <= MAX_DIGITAL) {
	   dacc_write_conversion_data(DACC_BASE, desenhar_seno(i++));
	   } else {
	   i = 0;
   }
}
Beispiel #9
0
void config_dacc(void){
	sysclk_enable_peripheral_clock(ID_DACC);
	/* Reset DACC registers */
	dacc_reset(DACC);
	/* Half-Word transfer mode */
	dacc_set_transfer_mode(DACC, 0);
	/* Timing:
	 * startup                - 0x10 (17 clocks)
	 * internal trigger clock - 0x60 (96 clocks)
	 */
	dacc_set_timing(DACC, 0x10, 0x60);
	/*External trigger mode disabled. DACC in free running mode.*/
	dacc_disable_trigger(DACC);
	/* Enable DAC */
	dacc_enable(DACC);
	
	while((dacc_get_interrupt_status(DACC) & DACC_ISR_TXRDY) != DACC_ISR_TXRDY);
	dacc_write_conversion_data(DACC, 0);
}
Beispiel #10
0
/**
 * \brief SysTick IRQ handler.
 */
void SysTick_Handler(void)
{
	uint32_t status;
	uint32_t dac_val;

	status = dacc_get_interrupt_status(DACC_BASE);

	/* If ready for new data */
	if ((status & DACC_ISR_TXRDY) == DACC_ISR_TXRDY) {
		g_ul_index_sample++;
		if (g_ul_index_sample >= SAMPLES) {
			g_ul_index_sample = 0;
		}
		dac_val = g_uc_wave_sel ?
				((g_ul_index_sample > SAMPLES / 2) ? 0 : MAX_AMPLITUDE)
				: wave_to_dacc(gc_us_sine_data[g_ul_index_sample],
					 g_l_amplitude,
					 MAX_DIGITAL * 2, MAX_AMPLITUDE);
		dacc_write_conversion_data(DACC_BASE, dac_val);
	}
}
Beispiel #11
0
/**
 * \brief Start DAC ouput.
 * Initialize DAC, set clock and timing, and set DAC to given mode.
 */
static void start_dac(void)
{
	sysclk_enable_peripheral_clock(DACC);

	/* Reset DACC registers */
	dacc_reset(DACC);

	/* Half word transfer mode */
	dacc_set_transfer_mode(DACC, 0);

	/* Timing:
	 * startup                - 0x10 (17 clocks)
	 * internal trigger clock - 0x60 (96 clocks)
	 */
	dacc_set_timing(DACC, 0x10, 0x60);

	/* Enable DAC */
	dacc_enable(DACC);

	/* The DAC is 10-bit resolution, so output voltage should be
	 * (3300 * 255) / ((1 << 10) - 1) = 823mv */
	dacc_write_conversion_data(DACC, 0xFF);
}
Beispiel #12
0
/**
 *  \brief ACC example application entry point.
 *
 *  \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	uint32_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, DACC_CHANNEL_0);
	/* Half word transfer mode */
	dacc_set_transfer_mode(DACC, 0);
#if (SAM3S) || (SAM3XA)
	/* Power save:
	 * sleep mode  - 0 (disabled)
	 * fast wakeup - 0 (disabled)
	 */
	dacc_set_power_save(DACC, 0, 0);
#endif

	/* 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, DACC_CHANNEL_0);
	l_volt_dac0 = (MAX_DIGITAL / 2) * (2 * VOLT_REF / 3) / MAX_DIGITAL +
			VOLT_REF / 6;

	/* Enable clock for AFEC */
	afec_enable(AFEC0);

	struct afec_config afec_cfg;

	afec_get_config_defaults(&afec_cfg);
	/* Initialize AFEC */
	afec_init(AFEC0, &afec_cfg);

	struct afec_ch_config afec_ch_cfg;
	afec_ch_get_config_defaults(&afec_ch_cfg);
	afec_ch_cfg.gain = AFEC_GAINVALUE_0;
	afec_ch_set_config(AFEC0, AFEC_CHANNEL_POTENTIOMETER, &afec_ch_cfg);
	/*
	 * Because the internal ADC offset is 0x200, it should cancel it and shift
	 * down to 0.
	 */
	afec_channel_set_analog_offset(AFEC0, AFEC_CHANNEL_POTENTIOMETER, 0x200);

	afec_set_trigger(AFEC0, AFEC_TRIG_SW);

	/* Enable channel for potentiometer. */
	afec_channel_enable(AFEC0, AFEC_CHANNEL_POTENTIOMETER);

	/* Enable clock for ACC */
	pmc_enable_periph_clk(ID_ACC);
	
	/* Initialize ACC */
	acc_init(ACC, ACC_MR_SELPLUS_AFE0_AD0, ACC_MR_SELMINUS_DAC0,
			ACC_MR_EDGETYP_ANY, ACC_MR_INV_DIS);

	/* Enable ACC interrupt */
	NVIC_EnableIRQ(ACC_IRQn);

	/* Enable */
	acc_enable_interrupt(ACC);

	dsplay_menu();

	while (1) {
		while (usart_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, DACC_CHANNEL_0);
				puts("-I- Set ok\r");
			} else {
				puts("-I- Input voltage is invalid\r");
			}
			break;
		case 'v':
		case 'V':
			/* Start conversion */
			afec_start_software_conversion(AFEC0);
			ul_status = afec_get_interrupt_status(AFEC0);
			while ((ul_status & AFEC_ISR_EOC0) != AFEC_ISR_EOC0) {
				ul_status = afec_get_interrupt_status(AFEC0);
			}
			/* Conversion is done */
			ul_value = afec_channel_get_value(AFEC0, AFEC_CHANNEL_POTENTIOMETER);

			/*
			 * Convert AFEC 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(AD0) 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;
		}
	}
}
Beispiel #13
0
/**
 * \brief Start ADC sample.
 * Initialize ADC, set clock and timing, and set ADC to given mode.
 */
static void start_adc(void)
{
	struct adc_config adc_cfg = {
		/* System clock division factor is 16 */
		.prescal = ADC_PRESCAL_DIV16,
		/* The APB clock is used */
		.clksel = ADC_CLKSEL_APBCLK,
		/* Max speed is 150K */
		.speed = ADC_SPEED_150K,
		/* ADC Reference voltage is 0.625*VCC */
		.refsel = ADC_REFSEL_1,
		/* Enables the Startup time */
		.start_up = CONFIG_ADC_STARTUP
	};
	struct adc_seq_config adc_seq_cfg = {
		/* Select Vref for shift cycle */
		.zoomrange = ADC_ZOOMRANGE_0,
		/* Pad Ground */
		.muxneg = ADC_MUXNEG_1,
		/* DAC internal */
		.muxpos = ADC_MUXPOS_3,
		/* 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,
	};
	if(adc_init(&g_adc_inst, ADCIFE, &adc_cfg) != STATUS_OK) {
		puts("-F- ADC Init Fail!\n\r");
		while(1);
	}
	if(adc_enable(&g_adc_inst) != STATUS_OK) {
		puts("-F- ADC Enable Fail!\n\r");
		while(1);
	}

	if (g_adc_test_mode.uc_pdc_en) {
		adc_disable_interrupt(&g_adc_inst, ADC_SEQ_SEOC);
		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);
	} else {
		pdca_channel_disable_interrupt(CONFIG_ADC_PDCA_RX_CHANNEL,
				PDCA_IDR_TRC);
		pdca_channel_disable_interrupt(CONFIG_ADC_PDCA_TX_CHANNEL,
				PDCA_IDR_TRC);
		adc_ch_set_config(&g_adc_inst, &adc_ch_cfg);
		adc_set_callback(&g_adc_inst, ADC_SEQ_SEOC, adcife_read_conv_result,
				ADCIFE_IRQn, 1);
	}

	/* Configure trigger mode and start convention. */
	switch (g_adc_test_mode.uc_trigger_mode) {
	case TRIGGER_MODE_SOFTWARE:
		adc_configure_trigger(&g_adc_inst, ADC_TRIG_SW);
		break;
	case TRIGGER_MODE_CON:
		adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON);
		break;
	case TRIGGER_MODE_ITIMER:
		adc_configure_trigger(&g_adc_inst, ADC_TRIG_INTL_TIMER);
		adc_configure_itimer_period(&g_adc_inst,
				adc_ch_cfg.internal_timer_max_count);
		adc_start_itimer(&g_adc_inst);
		break;
	default:
		break;
	}

	if (g_adc_test_mode.uc_gain_en) {
		adc_configure_gain(&g_adc_inst, ADC_GAIN_2X);
	} else {
		adc_configure_gain(&g_adc_inst, ADC_GAIN_1X);
	}
}

/**
 * \brief Start DAC ouput.
 * Initialize DAC, set clock and timing, and set DAC to given mode.
 */
static void start_dac(void)
{
	sysclk_enable_peripheral_clock(DACC);

	/* Reset DACC registers */
	dacc_reset(DACC);

	/* Half word transfer mode */
	dacc_set_transfer_mode(DACC, 0);

	/* Timing:
	 * startup                - 0x10 (17 clocks)
	 * internal trigger clock - 0x60 (96 clocks)
	 */
	dacc_set_timing(DACC, 0x10, 0x60);

	/* Enable DAC */
	dacc_enable(DACC);

	/* The DAC is 10-bit resolution, so output voltage should be
	 * (3300 * 255) / ((1 << 10) - 1) = 823mv */
	dacc_write_conversion_data(DACC, 0xFF);
}
Beispiel #14
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;
		}
	}
}
/**
 * \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. */
	uint32_t i;
	pmc_enable_periph_clk(ID_ADC);

	/* Initialize ADC. */
	/*
	 * Formula: ADCClock = MCK / ( (PRESCAL+1) * 2 )
	 * For example, MCK = 64MHZ, PRESCAL = 4, then:
	 * ADCClock = 64 / ((4+1) * 2) = 6.4MHz;
	 */

	/* 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);
	memset((void *)&g_adc_sample_data, 0, sizeof(g_adc_sample_data));

	/* Set ADC timing. */

	/* 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);

	/* 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);

		adc_enable_channel(ADC, ADC_TEMPERATURE_SENSOR);

		/* Update channel number. */
		g_adc_sample_data.uc_ch_num[0] = ADC_CHANNEL_POTENTIOMETER;

		g_adc_sample_data.uc_ch_num[1] = ADC_TEMPERATURE_SENSOR;

	}



	/* Enable the temperature sensor. */
	adc_enable_ts(ADC);

	/* Set gain and offset (only single ended mode used here). */

	adc_disable_anch(ADC); /* Disable analog change. */

	if (g_adc_test_mode.uc_gain_en) {

		adc_enable_anch(ADC);
		/* gain = 2 */
		adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_2);
	} else {

		/* gain = 1 */
		adc_set_channel_input_gain(ADC, ADC_CHANNEL_POTENTIOMETER, ADC_GAINVALUE_0);
	}

	if (g_adc_test_mode.uc_offset_en) {

		adc_enable_anch(ADC);
		adc_enable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER);
	} else {

		adc_disable_channel_input_offset(ADC, ADC_CHANNEL_POTENTIOMETER);
	}
	/* Set Auto Calibration Mode. */

	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;
		}
	}


	/* 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);;
	}


	/* 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);

	/* Configure trigger mode and start convention. */
	switch (g_adc_test_mode.uc_trigger_mode) {
	case TRIGGER_MODE_SOFTWARE:
		adc_configure_trigger(ADC, ADC_TRIG_SW, 0);	/* Disable hardware trigger. */
		break;

	case TRIGGER_MODE_ADTRG:

		gpio_configure_pin(PINS_ADC_TRIG, PINS_ADC_TRIG_FLAG);
		adc_configure_trigger(ADC, ADC_TRIG_EXT, 0);
		break;

	case TRIGGER_MODE_TIMER:
		configure_time_trigger();
		break;

	case TRIGGER_MODE_PWM:
		configure_pwm_trigger();
		break;


	case TRIGGER_MODE_FREERUN:
		adc_configure_trigger(ADC, ADC_TRIG_SW, 1);
		break;

	default:
		break;
	}
}

/**
 * \brief Systick handler.
 */

void SysTick_Handler(void)
{
	uint32_t status;
	uint32_t dac_val;
	int i = 0;
	
	gs_ul_ms_ticks++;
	status = dacc_get_interrupt_status(DACC_BASE);

	/* If ready for new data */
	if ((status & DACC_ISR_TXRDY) == DACC_ISR_TXRDY) {		
		/*dac_val = g_uc_wave_sel ?
				((g_ul_index_sample > SAMPLES / 2) ? 0 : MAX_AMPLITUDE)
				: wave_to_dacc(gc_us_sine_data[g_ul_index_sample],
					 g_l_amplitude,
					 MAX_DIGITAL * 2, MAX_AMPLITUDE);*/
		
		
		//reading sample from ADC
		adc_start(ADC);		
		/* Check if ADC sample is done. */
		if (g_adc_sample_data.us_done == ADC_DONE_MASK) {
			/*for (i = 0; i < NUM_CHANNELS; i++) {
				printf("CH%02d: %04d mv.    ",
						(int)g_adc_sample_data.uc_ch_num[i],
						(int)(g_adc_sample_data.
								us_value[i] *
								VOLT_REF /
								MAX_DIGITAL));
			}
			puts("\r");*/
			g_adc_sample_data.us_done = 0;
			//end reading 
		
			//write to the DACC
			dacc_write_conversion_data(DACC_BASE, g_adc_sample_data.us_value[0]);
		}
		
		
	}
}

#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;
				}
			}
		}
	}
Beispiel #16
0
/**
 * \brief Example entry point.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	uint8_t c_choice;
	int16_t s_adc_value;
	int16_t s_dac_value;
	int16_t s_threshold = 0;
	float f_dac_data;
	uint32_t ul_dac_data;

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

	configure_console();

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

	/* Initialize threshold. */
	gs_us_low_threshold = 500;
	gs_us_high_threshold = 2000;

	struct adc_config adc_cfg = {
		/* System clock division factor is 16 */
		.prescal = ADC_PRESCAL_DIV16,
		/* The APB clock is used */
		.clksel = ADC_CLKSEL_APBCLK,
		/* Max speed is 150K */
		.speed = ADC_SPEED_150K,
		/* ADC Reference voltage is 0.625*VCC */
		.refsel = ADC_REFSEL_1,
		/* Enables the Startup time */
		.start_up = CONFIG_ADC_STARTUP
	};
	struct adc_seq_config adc_seq_cfg = {
		/* Select Vref for shift cycle */
		.zoomrange = ADC_ZOOMRANGE_0,
		/* Pad Ground */
		.muxneg = ADC_MUXNEG_1,
		/* DAC Internal */
		.muxpos = ADC_MUXPOS_3,
		/* 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 500 * VOLT_REF / 4095 = 251mv. */
		.low_threshold = gs_us_low_threshold,
		/* The equivalent voltage value is 2000 * VOLT_REF / 4095 = 1002mv. */
		.high_threshold = gs_us_high_threshold,
	};

	start_dac();

	if(adc_init(&g_adc_inst, ADCIFE, &adc_cfg) != STATUS_OK) {
		puts("-F- ADC Init Fail!\n\r");
		while(1);
	}
	if(adc_enable(&g_adc_inst) != STATUS_OK) {
		puts("-F- ADC Enable Fail!\n\r");
		while(1);
	}
	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_wm_handler,
			ADCIFE_IRQn, 1);

	/* Display main menu. */
	display_menu();

	while (1) {

		scanf("%c", (char *)&c_choice);
		printf("%c\r\n", c_choice);
		switch (c_choice) {
		case '0':
			adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			printf("DAC output is set to(mv) from 0mv to %dmv: ",
					(int32_t)VOLT_REF);
			s_dac_value = get_voltage();
			puts("\r");
			f_dac_data = (float)s_dac_value * DACC_MAX_DATA / VDDANA;
			ul_dac_data = f_to_int(f_dac_data);
			if (s_dac_value >= 0) {
				dacc_write_conversion_data(DACC, ul_dac_data);
			}
			delay_ms(100);
			adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM);
			adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			break;

		case '1':
			adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			printf("Low threshold is set to(mv) from 0mv to %dmv: ",
					(int32_t)VOLT_REF);
			s_threshold = get_voltage();
			puts("\r");
			if (s_threshold >= 0) {
				s_adc_value = s_threshold * MAX_DIGITAL /
						VOLT_REF;
				adc_configure_wm_threshold(&g_adc_inst,
						s_adc_value,
						gs_us_high_threshold);
				/* Renew low threshold. */
				gs_us_low_threshold = s_adc_value;
				float f_low_threshold =
						(float)gs_us_low_threshold *
						VOLT_REF / MAX_DIGITAL;
				uint32_t ul_low_threshold =
						f_to_int(f_low_threshold);
				printf("Setting low threshold to %u mv (reg value to 0x%x ~%d%%)\n\r",
						ul_low_threshold, gs_us_low_threshold,
						gs_us_low_threshold * 100 / MAX_DIGITAL);
			}
			adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM);
			adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			break;

		case '2':
			adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			printf("High threshold is set to(mv)from 0mv to %dmv:",
					(int32_t)VOLT_REF);
			s_threshold = get_voltage();
			puts("\r");
			if (s_threshold >= 0) {
				s_adc_value = s_threshold * MAX_DIGITAL /
						VOLT_REF;
				adc_configure_wm_threshold(&g_adc_inst,
						gs_us_low_threshold,
						s_adc_value);
				/* Renew high threshold. */
				gs_us_high_threshold = s_adc_value;
				float f_high_threshold =
						(float)gs_us_high_threshold *
						VOLT_REF / MAX_DIGITAL;
				uint32_t ul_high_threshold =
						f_to_int(f_high_threshold);
				printf("Setting high threshold to %u mv (reg value to 0x%x ~%d%%)\n\r",
						ul_high_threshold, gs_us_high_threshold,
						gs_us_high_threshold * 100 / MAX_DIGITAL);
			}
			adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM);
			adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			break;

		case '3':
			adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			puts("-a. Above low threshold.\n\r"
					"-b. Below high threshold.\n\r"
					"-c. In the comparison window.\n\r"
					"-d. Out of the comparison window.\n\r"
					"-q. Quit the setting.\r");
			c_choice = get_wm_mode();
			adc_configure_wm_mode(&g_adc_inst, c_choice);
			printf("Comparison mode is %c.\n\r", 'a' + c_choice - 1);
			adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM);
			adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			break;

		case 'm':
			display_menu();
			break;

		case 'i':
			display_info();
			adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM);
			adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR);
			break;
		}
		puts("Press \'m\' or \'M\' to display the main menu again!\r");
	}
}