int main(void)
{

	//! [setup_init]
	struct tc_module       tc_instance;
	struct events_resource example_event;
	struct events_hook     hook;

	system_init();
	system_interrupt_enable_global();

	configure_event_channel(&example_event);
	configure_event_user(&example_event);
	configure_event_interrupt(&example_event, &hook);
	configure_tc(&tc_instance);
	//! [setup_init]

	//! [main]

	//! [main_1]
	while (events_is_busy(&example_event)) {
		/* Wait for channel */
	};
	//! [main_1]

	//! [main_2]
	tc_start_counter(&tc_instance);
	//! [main_2]

	while (true) {
		/* Nothing to do */
	}

	//! [main]
}
/*!
* @brief		Implements a delay of the length of the argument in 
econds
*
* @param[in]	NULL
*
* @param[out]	NULL
*
* @return		NULL
*
*/
void tc4_wait_for_msec (uint32_t msec)
{
	/* Set the compare value */
	tc_set_compare_value(&tc4_instance, TC_COMPARE_CAPTURE_CHANNEL_0, (msec *500));
	
	/* start counting */
	tc_start_counter(&tc4_instance);
	
	/* delay until required time is elapsed */
	while (!tc4_callback_flag);
	
	/* stop the counter */
	tc_stop_counter(&tc4_instance);
	/* reset the interrupt flag */
	tc4_callback_flag = false;
}
Beispiel #3
0
/**
 * \internal
 * \brief Test basic functionality.
 *
 * This test tests the basic functionality for the TC. It tests the following functions:
 *  - tc_get_count_value()
 *  - tc_stop_counter()
 *  - tc_set_count_value()
 *  - tc_start_counter()
 *
 * \param test Current test case.
 */
static void run_basic_functionality_test(const struct test_case *test)
{
	test_assert_true(test,
			tc_init_success == true,
			"TC initialization failed, skipping test");

	/* Setup TC0 */
	tc_reset(&tc_test0_module);
	tc_get_config_defaults(&tc_test0_config);

	tc_init(&tc_test0_module, CONF_TEST_TC0, &tc_test0_config);
	tc_enable(&tc_test0_module);

	/* Test tc_get_count_value() */
	uint32_t test_val0 = tc_get_count_value(&tc_test0_module);

	test_assert_true(test,
			test_val0 > 0,
			"The tc_get_count_value() returned 0 expected larger value");

	/* Test tc_stop_counter() */
	tc_stop_counter(&tc_test0_module);

	uint32_t test_val1 = tc_get_count_value(&tc_test0_module);
	uint32_t test_val2 = tc_get_count_value(&tc_test0_module);

	test_assert_true(test,
			test_val1 == test_val2,
			"The counter failed to stop");

	/* Test tc_set_count_value() */
	tc_set_count_value(&tc_test0_module, 0x00FF);

	test_assert_true(test,
			tc_get_count_value(&tc_test0_module) == 0x00FF,
			"tc_set_count_value() have failed");

	/* Test tc_start_counter() */
	tc_start_counter(&tc_test0_module);

	test_assert_true(test,
			tc_get_count_value(&tc_test0_module) > 0x00FF,
			"tc_get_count_value() have failed");

	basic_functionality_test_passed = true;
}
Beispiel #4
0
/**
 * \brief Configures the DAC in event triggered mode.
 *
 * Configures the DAC to use the module's default configuration, with output
 * channel mode configured for event triggered conversions.
 *
 * \param dev_inst  Pointer to the DAC module software instance to initialize
 */
static void configure_dac(struct dac_module *dac_module)
{
    struct dac_config config;
    struct dac_chan_config channel_config;

    /* Get the DAC default configuration */
    dac_get_config_defaults(&config);

    /* Switch to GCLK generator 0 */
    config.clock_source = GCLK_GENERATOR_0;

    dac_init(dac_module, DAC, &config);

    /* Get the default DAC channel config */
    dac_chan_get_config_defaults(&channel_config);

    /* Set the channel configuration, and enable it */
    dac_chan_set_config(dac_module, DAC_CHANNEL_0, &channel_config);
    dac_chan_enable(dac_module, DAC_CHANNEL_0);

    /* Enable event triggered conversions */
    struct dac_events events = { .on_event_start_conversion = true };
    dac_enable_events(dac_module, &events);

    dac_enable(dac_module);
}

/**
 * \brief Configures the TC to generate output events at the sample frequency.
 *
 * Configures the TC in Frequency Generation mode, with an event output once
 * each time the audio sample frequency period expires.
 *
 * \param dev_inst  Pointer to the TC module software instance to initialize
 */
static void configure_tc(struct tc_module *tc_module)
{
    struct tc_config config;
    tc_get_config_defaults(&config);

    config.clock_source    = GCLK_GENERATOR_0;
    config.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;

    tc_init(tc_module, TC3, &config);

    /* Enable periodic event output generation */
    struct tc_events events = { .generate_event_on_overflow = true };
    tc_enable_events(tc_module, &events);

    /* Set the timer top value to alter the overflow frequency */
    tc_set_top_value(tc_module,
                     system_gclk_gen_get_hz(GCLK_GENERATOR_0) / sample_rate);


    tc_enable(tc_module);
}

/**
 * \brief Configures the event system to link the sample timer to the DAC.
 *
 * Configures the event system, linking the TC module used for the audio sample
 * rate timing to the DAC, so that a new conversion is triggered each time the
 * DAC receives an event from the timer.
 */
static void configure_events(struct events_resource *event)
{
    struct events_config config;

    events_get_config_defaults(&config);

    config.generator    = EVSYS_ID_GEN_TC3_OVF;
    config.path         = EVENTS_PATH_ASYNCHRONOUS;

    events_allocate(event, &config);
    events_attach_user(event, EVSYS_ID_USER_DAC_START);
}

/**
 * \brief Main application routine
 */
int main(void)
{
    struct dac_module dac_module;
    struct tc_module tc_module;
    struct events_resource event;

    /* Initialize all the system clocks, pm, gclk... */
    system_init();

    /* Enable the internal bandgap to use as reference to the DAC */
    system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_BANDGAP);

    /* Module configuration */
    configure_tc(&tc_module);
    configure_dac(&dac_module);
    configure_events(&event);

    /* Start the sample trigger timer */
    tc_start_counter(&tc_module);

    while (true) {
        while (port_pin_get_input_level(SW0_PIN) == SW0_INACTIVE) {
            /* Wait for the button to be pressed */
        }

        port_pin_toggle_output_level(LED0_PIN);

        for (uint32_t i = 0; i < number_of_samples; i++) {
            dac_chan_write(&dac_module, DAC_CHANNEL_0, wav_samples[i]);

            while (!(DAC->INTFLAG.reg & DAC_INTFLAG_EMPTY)) {
                /* Wait for data buffer to be empty */
            }

        }

        while (port_pin_get_input_level(SW0_PIN) == SW0_ACTIVE) {
            /* Wait for the button to be depressed */
        }
    }
}
void platform_start_bus_timer(void *timer_handle, uint32_t ms)
{
	tc_set_count_value(&bus_tc_instance, (0xFFFFFFFF - (timer_count_per_ms * ms)));
	tc_start_counter(&bus_tc_instance);
}
Beispiel #6
0
/** Set up the measurement and comparison timer events.
 *   - Configure the reference timer to generate an event upon comparison
 *     match with channel 0.
 *   - Configure the measurement timer to trigger a capture when an event is
 *     received.
 */
static void setup_tc_events(void)
{
	/* Enable incoming events on on measurement timer */
	struct tc_events events_calib = { .on_event_perform_action = true };
	tc_enable_events(&tc_calib, &events_calib);

	/* Generate events from the reference timer on channel 0 compare match */
	struct tc_events events_comp = { .generate_event_on_compare_channel[0] = true };
	tc_enable_events(&tc_comp, &events_comp);

	tc_enable(&tc_calib);
	tc_enable(&tc_comp);
}

/** Set up the event system, linking the measurement and comparison timers so
 *  that events generated from the reference timer are linked to the measurement
 *  timer.
 */
static void setup_events(struct events_resource *event)
{
	struct events_config config;

	events_get_config_defaults(&config);

	/* The event channel detects rising edges of the reference timer output
	 * event */
	config.edge_detect    = EVENTS_EDGE_DETECT_RISING;
	config.path           = EVENTS_PATH_SYNCHRONOUS;
	config.generator      = CONF_EVENT_GENERATOR_ID;

	events_allocate(event, &config);
	events_attach_user(event, CONF_EVENT_USED_ID);

}

/** Set up the USART for transmit-only communication at a fixed baud rate. */
static void setup_usart_channel(void)
{
	struct usart_config cdc_uart_config;
	usart_get_config_defaults(&cdc_uart_config);

	/* Configure the USART settings and initialize the standard I/O library */
	cdc_uart_config.mux_setting = EDBG_CDC_SERCOM_MUX_SETTING;
	cdc_uart_config.pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
	cdc_uart_config.pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
	cdc_uart_config.pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
	cdc_uart_config.pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;
	cdc_uart_config.baudrate    = 115200;
	stdio_serial_init(&usart_edbg, EDBG_CDC_MODULE, &cdc_uart_config);

	usart_enable(&usart_edbg);
}

/** Set up the clock output pin so that the current system clock frequency can
 *  be monitored via an external frequency counter or oscilloscope. */
static void setup_clock_out_pin(void)
{
	struct system_pinmux_config pin_mux;
	system_pinmux_get_config_defaults(&pin_mux);

	/* MUX out the system clock to a I/O pin of the device */
	pin_mux.mux_position = CONF_CLOCK_PIN_MUX;
	system_pinmux_pin_set_config(CONF_CLOCK_PIN_OUT, &pin_mux);
}

/** Retrieves the current system clock frequency, computed from the reference
 *  clock.
 *
 * \return Current system clock frequency in Hz.
 */
static uint32_t get_osc_frequency(void)
{
	/* Clear any existing match status on the measurement timer */
	tc_clear_status(&tc_comp, TC_STATUS_CHANNEL_0_MATCH);

	/* Restart both measurement and reference timers */
	tc_start_counter(&tc_calib);
	tc_start_counter(&tc_comp);

	/* Wait for the measurement timer to signal a compare match */
	while (!(tc_get_status(&tc_comp) & TC_STATUS_CHANNEL_0_MATCH)) {
		/* Wait for channel 0 match */
	}

	/* Compute the real clock frequency from the measurement timer count and
	 * reference count */
	uint64_t tmp = tc_get_capture_value(&tc_calib, TC_COMPARE_CAPTURE_CHANNEL_0);
	return ((tmp * REFERENCE_CLOCK_HZ) >> CALIBRATION_RESOLUTION);
}

int main(void)
{
	struct events_resource event;

	/* System initialization */
	system_init();
	delay_init();

	/* Module initialization */
	setup_tc_channels();
	setup_tc_events();
	setup_events(&event);
	setup_clock_out_pin();

	/* Init the variables with default calibration settings */
	uint8_t frange_cal = SYSCTRL->OSC8M.bit.FRANGE;
	uint8_t temp_cal = SYSCTRL->OSC8M.bit.CALIB >> TEMP_CAL_OFFSET;
	uint8_t comm_cal = SYSCTRL->OSC8M.bit.CALIB & COMM_CAL_MAX;
	/* Set the calibration test range */
	uint8_t frange_cal_min = max((frange_cal - CONF_FRANGE_CAL), FRANGE_CAL_MIN);
	uint8_t frange_cal_max = min((frange_cal + CONF_FRANGE_CAL), FRANGE_CAL_MAX);
	uint8_t temp_cal_min = max((temp_cal - CONF_TEMP_CAL), TEMP_CAL_MIN);
	uint8_t temp_cal_max = min((temp_cal + CONF_TEMP_CAL), TEMP_CAL_MAX);

	/* Variables to track the previous and best calibration settings */
	uint16_t comm_best   = 0;
	uint8_t  frange_best = 0;
	uint32_t freq_best   = 0;
	uint32_t freq_before = get_osc_frequency();

	/* Run calibration loop */
	for (frange_cal = frange_cal_min; frange_cal <= frange_cal_max; frange_cal++) {
		for (temp_cal = temp_cal_min; temp_cal <= temp_cal_max; temp_cal++) {
			for (comm_cal = COMM_CAL_MIN; comm_cal <= COMM_CAL_MAX; comm_cal++) {
				/* Set the test calibration values */
				system_clock_source_write_calibration(
						SYSTEM_CLOCK_SOURCE_OSC8M, (temp_cal << 7) | comm_cal, frange_cal);

				/* Wait for stabilization */
				delay_cycles(1000);

				/* Compute the deltas of the current and best system clock
				 * frequencies, save current settings if they are closer to the
				 * ideal frequency than the previous best values
				 */
				uint32_t freq_current = get_osc_frequency();
				if (abs(freq_current - TARGET_FREQUENCY) < abs(freq_best - TARGET_FREQUENCY)) {
					freq_best   = freq_current;
					comm_best   = comm_cal;
					frange_best = frange_cal;

					port_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
				} else {
					port_pin_set_output_level(LED_0_PIN, !LED_0_ACTIVE);
				}
			}
		}
	}

	/* Set the found best calibration values */
	system_clock_source_write_calibration(
			SYSTEM_CLOCK_SOURCE_OSC8M, (temp_cal << 7) | comm_best, frange_best);

	/* Setup USART module to output results */
	setup_usart_channel();

	/* Write previous and current frequency and new calibration settings to the
	 * USART
	 */
	printf("Freq Before: %lu\r\n", freq_before);
	printf("Freq Best: %lu\r\n", freq_best);

	printf("Freq Range: %u\r\n", frange_best);
	printf("Calib Value: 0x%x\r\n", (temp_cal << 7) | comm_best);

	/* Rapidly flash the board LED to signal the calibration completion */
	while (1) {
		port_pin_toggle_output_level(LED_0_PIN);
		delay_ms(200);
	}
}
/*!
* @brief		Starts TC6 counter
*
* @param[in]	NULL
*
* @param[out]	NULL
*
* @return		NULL
*
*/
void tc6_start_counter (void)
{
	tc_set_count_value(&tc6_instance, TC6_COUNT_VALUE);
	tc_start_counter(&tc6_instance);
}
Beispiel #8
0
/* Timer 0 Initialization */
void timer_init(void)
{
	struct tc_config conf_tc;
	struct tc_events conf_tc_events = {.generate_event_on_compare_channel[0] = 1};
	tc_get_config_defaults(&conf_tc);
	conf_tc.clock_source = GCLK_GENERATOR_0;
	conf_tc.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;
	conf_tc.counter_16_bit.compare_capture_channel[0] = 0xFFFF;
	tc_init(&tc_inst, TC0, &conf_tc);
	tc_enable_events(&tc_inst, &conf_tc_events);
	tc_enable(&tc_inst);
	tc_stop_counter(&tc_inst);
	/* Enable TC0 match/capture channel 0 interrupt */
	TC0->COUNT16.INTENSET.bit.MC0 = 1;
	/* Enable TC0 module interrupt */
	NVIC_EnableIRQ(TC0_IRQn);
}

/* DAC Initialization */
void dac_initialize(void)
{
	struct dac_config conf_dac;
	struct dac_events conf_dac_events = {.on_event_start_conversion = 1};
	dac_get_config_defaults(&conf_dac);
	conf_dac.clock_source = GCLK_GENERATOR_3;
	conf_dac.reference = DAC_REFERENCE_INT1V;
	dac_init(&dac_inst, DAC, &conf_dac);
	dac_enable_events(&dac_inst, &conf_dac_events);
	dac_enable(&dac_inst);
}

/* Event System Initialization */
void evsys_init(void)
{
	struct events_resource conf_event_resource;
	struct events_config conf_event;
	events_get_config_defaults(&conf_event);
	conf_event.edge_detect = EVENTS_EDGE_DETECT_NONE;
	conf_event.path = EVENTS_PATH_ASYNCHRONOUS;
	conf_event.generator = EVSYS_ID_GEN_TC0_MCX_0;
	events_allocate(&conf_event_resource, &conf_event);
	events_attach_user(&conf_event_resource, EVSYS_ID_USER_DAC_START);
}

/* Initialize the selected waveform buffer with output data */
void buffer_init(void)
{
#if WAVE_MODE==SINE_WAVE
	for (i = 0; i < DEGREES_PER_CYCLE; i++)	{
		sine_wave_buf[i] = (uint16_t)(500 + (500*sin((double)i*DEGREE)));
	}
#elif WAVE_MODE==SAW_TOOTH_WAVE
	for (i = 0; i < 256; i++) {
		sawtooth_wave_buf[i] = i*4;
	}
#elif WAVE_MODE==TRIANGLE_WAVE
	for (i = 0; i < 128; i++) {
		triangle_wave_buf[i] = i*8;
	}
	for (i = 128; i < 256; i++) {
		triangle_wave_buf[i] = 1023 - (i*8);
	}
#endif
}

/* Main function */
int main(void)
{
	system_init();
	timer_init();
	dac_initialize();
	evsys_init();
	buffer_init();
	/* Set the TC0 compare value corresponding to specified frequency */
#if WAVE_MODE==SINE_WAVE
	tc_set_compare_value(&tc_inst, 0, \
		system_gclk_gen_get_hz(GCLK_GENERATOR_0)/(FREQUENCY*360));
#else
	tc_set_compare_value(&tc_inst, 0, \
		system_gclk_gen_get_hz(GCLK_GENERATOR_0)/(FREQUENCY*256));
#endif
	/* Start TC0 timer */
	tc_start_counter(&tc_inst);
	/* Enable global interrupt */
	system_interrupt_enable_global();
	
	while (true) {

	}
}