void *platform_configure_timer(platform_hw_timer_callback_t bus_tc_cb_ptr)
{
	struct tc_config timer_config;
	
	system_interrupt_enter_critical_section();
	if (hw_timers[0].timer_usage == 0)
	{
		hw_timers[0].timer_usage = 1;
		platform_cc1_cb = bus_tc_cb_ptr;

		tc_get_config_defaults(&timer_config);
		timer_config.clock_prescaler		= TC_CLOCK_PRESCALER_DIV1;
		timer_config.oneshot				= true;
		timer_config.counter_size			= TC_COUNTER_SIZE_32BIT;
		timer_config.count_direction		= TC_COUNT_DIRECTION_UP;
		tc_init(&bus_tc_instance, CONF_BUS_TC_MODULE, &timer_config);
		timer_count_per_ms = ((system_gclk_gen_get_hz(timer_config.clock_source)) /1000);
		tc_set_count_value(&bus_tc_instance, 0);
		tc_enable(&bus_tc_instance);
		tc_stop_counter(&bus_tc_instance);
		tc_register_callback(&bus_tc_instance, tc_cc1_cb,
		TC_CALLBACK_OVERFLOW);
		tc_enable_callback(&bus_tc_instance, TC_CALLBACK_OVERFLOW);
		
		hw_timers[0].timer_frequency = (system_gclk_gen_get_hz(timer_config.clock_source));
		hw_timers[0].timer_instance = bus_tc_instance;
		system_interrupt_leave_critical_section();
		return (&hw_timers[0]);
	}
	system_interrupt_leave_critical_section();
	return NULL;
}
Esempio n. 2
0
/**
 * \internal
 * \brief Test of tc_init() and tc_get_config_defaults()
 *
 * This test is used to initialize the tcx_module structs and associate the given
 * hw module with the struct. This test should be run at the very beginning of
 * testing as other tests depend on the result of this test.
 */
static void run_init_test(const struct test_case *test)
{
	tc_get_config_defaults(&tc_test0_config);
	enum status_code test1 = tc_init(&tc_test0_module, CONF_TEST_TC0, &tc_test0_config);

	tc_get_config_defaults(&tc_test1_config);
	enum status_code test2 = tc_init(&tc_test1_module, CONF_TEST_TC1, &tc_test1_config);

	if ((test1 == STATUS_OK) && (test2 == STATUS_OK)) {
		tc_init_success = true;
	}

	test_assert_true(test,
			(test2 == STATUS_OK) && (test1 == STATUS_OK),
			"Failed to initialize modules");
}
Esempio n. 3
0
/*---------------------------------------------------------------------------*/
void
clock_init(void)
{
#define TIMER_PERIOD  UINT16_MAX
#define TIMER         TC3

    struct tc_config cfg;
    tc_get_config_defaults(&cfg);

    cfg.clock_source = GCLK_GENERATOR_5;
    cfg.clock_prescaler = TC_CLOCK_PRESCALER_DIV1;
    cfg.run_in_standby = false;

    cfg.counter_16_bit.compare_capture_channel[0] = TIMER_PERIOD;
    tc_init(&tc_instance, TIMER, &cfg);
    /*  tc_register_callback(&tc_instance, clock_irq_callback, TC_CALLBACK_OVERFLOW);*/
    tc_register_callback(&tc_instance, clock_irq_callback, TC_CALLBACK_CC_CHANNEL0);
    /*  tc_register_callback(&tc_instance, clock_irq_callback, TC_CALLBACK_CC_CHANNEL1);
        tc_register_callback(&tc_instance, clock_irq_callback, TC_CALLBACK_ERROR);*/
    /*  tc_enable_callback(&tc_instance, TC_CALLBACK_OVERFLOW);*/
    tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL0);
    /*  tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL1);
        tc_enable_callback(&tc_instance, TC_CALLBACK_ERROR);*/

    tc_enable(&tc_instance);


}
Esempio n. 4
0
static void configure_tc(struct tc_module *tc_instance)
{
	//! [setup_6]
	struct tc_config config_tc;
	struct tc_events config_events;
	//! [setup_6]

	//! [setup_7]
	tc_get_config_defaults(&config_tc);
	//! [setup_7]

	//! [setup_8]
	config_tc.counter_size    = TC_COUNTER_SIZE_8BIT;
	config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_FREQ;
	config_tc.clock_source    = GCLK_GENERATOR_1;
	config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV64;
	//! [setup_8]

	//! [setup_9]
	tc_init(tc_instance, CONF_TC_MODULE, &config_tc);
	//! [setup_9]

	//! [setup_10]
	config_events.generate_event_on_overflow = true;
	tc_enable_events(tc_instance, &config_events);
	//! [setup_10]

	//! [setup_11]
	tc_enable(tc_instance);
	//! [setup_11]

}
//! [setup]
void configure_tc(void)
{
	//! [setup_config]
	struct tc_config config_tc;
	//! [setup_config]
	//! [setup_config_defaults]
	tc_get_config_defaults(&config_tc);
	//! [setup_config_defaults]

	//! [setup_change_config]
	config_tc.counter_size    = TC_COUNTER_SIZE_16BIT;
	config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_PWM;
	config_tc.counter_16_bit.compare_capture_channel[0] = (0xFFFF / 4);
	//! [setup_change_config]

	//! [setup_change_config_pwm]
	config_tc.pwm_channel[0].enabled = true;
	config_tc.pwm_channel[0].pin_out = PWM_OUT_PIN;
	config_tc.pwm_channel[0].pin_mux = PWM_OUT_MUX;
	//! [setup_change_config_pwm]

	//! [setup_set_config]
	tc_init(&tc_instance, PWM_MODULE, &config_tc);
	//! [setup_set_config]

	//! [setup_enable]
	tc_enable(&tc_instance);
	//! [setup_enable]
}
Esempio n. 6
0
/*! \brief  to initialize hw timer
 */
uint8_t tmr_init(void)
{
	uint8_t timer_multiplier;
	tc_get_config_defaults(&timer_config);
	#ifdef ENABLE_SLEEP
	if(sys_sleep == true)
	{
		timer_config.clock_source = GCLK_GENERATOR_1;
		timer_config.clock_prescaler = TC_CLOCK_PRESCALER_DIV2;
		timer_config.run_in_standby=true;
	}
	#endif
	timer_config.counter_16_bit.compare_capture_channel[0] = TIMER_PERIOD;
	tc_init(&module_inst, TIMER, &timer_config);
	tc_register_callback(&module_inst, tc_ovf_callback, TC_CALLBACK_OVERFLOW);
	tc_register_callback(&module_inst, tc_cca_callback, TC_CALLBACK_CC_CHANNEL0);
	tc_enable_callback(&module_inst, TC_CALLBACK_OVERFLOW);
	tc_enable_callback(&module_inst, TC_CALLBACK_CC_CHANNEL0);

	tc_enable(&module_inst);
	/* calculate how faster the timer with current clk freq compared to timer with 1Mhz */
	#ifdef ENABLE_SLEEP
	if(sys_sleep ==true)
	{
		timer_multiplier = system_gclk_gen_get_hz(1) / 2000000;
	}
	else
	{
	timer_multiplier = system_gclk_gen_get_hz(0) / DEF_1MHZ;
	}
    #else
	timer_multiplier = system_gclk_gen_get_hz(0) / DEF_1MHZ;
	#endif
	return timer_multiplier;
}
Esempio n. 7
0
/**
 * \internal
 * \brief Test the callback API
 *
 * This test tests the callback API for the TC. The TC uses one-shot mode.
 *
 * \param test Current test case.
 */
static void run_callback_test(const struct test_case *test)
{
	test_assert_true(test,
			tc_init_success == true,
			"TC initialization failed, skipping test");

	test_assert_true(test,
			basic_functionality_test_passed == true,
			"Basic functionality test failed, skipping test");

	/* Setup TC0 */
	tc_reset(&tc_test0_module);
	tc_get_config_defaults(&tc_test0_config);
	tc_test0_config.wave_generation                       = TC_WAVE_GENERATION_MATCH_PWM;
	tc_test0_config.counter_16_bit.compare_capture_channel\
		[TC_COMPARE_CAPTURE_CHANNEL_0]                    = 0x03FF;
	tc_test0_config.counter_16_bit.compare_capture_channel\
		[TC_COMPARE_CAPTURE_CHANNEL_1]                    = 0x03FA;


	tc_init(&tc_test0_module, CONF_TEST_TC0, &tc_test0_config);

	/* Setup callbacks */
	tc_register_callback(&tc_test0_module, tc_callback_function, TC_CALLBACK_CC_CHANNEL1);
	tc_enable_callback(&tc_test0_module, TC_CALLBACK_CC_CHANNEL1);

	tc_enable(&tc_test0_module);

	while ((tc_get_status(&tc_test0_module) & TC_STATUS_COUNT_OVERFLOW) == 0) {
		/* Wait for overflow of TC1*/
	}

	tc_disable(&tc_test0_module);
	tc_clear_status(&tc_test0_module, TC_STATUS_COUNT_OVERFLOW);

	test_assert_true(test,
			callback_function_entered == 1,
			"The callback has failed callback_function_entered = %d",
			(int)callback_function_entered);

	/* Test disable callback function */
	tc_disable_callback(&tc_test0_module, TC_CALLBACK_CC_CHANNEL1);
	tc_set_count_value(&tc_test0_module, 0x00000000);

	tc_enable(&tc_test0_module);

	while ((tc_get_status(&tc_test0_module) & TC_STATUS_COUNT_OVERFLOW) == 0) {
		/* Wait for overflow of TC1*/
	}

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

	test_assert_true(test,
			callback_function_entered == 1,
			"Disabling the callback has failed");
}
Esempio n. 8
0
/** Configures  TC function with the  driver.
 */
static void configure_tc(void)
{
	struct tc_config config_tc;

	tc_get_config_defaults(&config_tc);
	config_tc.counter_size    = TC_COUNTER_SIZE_16BIT;
	config_tc.counter_16_bit.value = TC_COUNT_VALUE;

	tc_init(&tc_instance, CONF_TC_INSTANCE, &config_tc);
	tc_enable(&tc_instance);
}
void us_ticker_init(void)
{
    uint32_t			cycles_per_us;
    uint32_t			prescaler = 0;
    struct tc_config	config_tc;
    enum status_code	ret_status;

    if (us_ticker_inited) return;
    us_ticker_inited = 1;

    if (g_sys_init == 0) {
        system_init();
        g_sys_init = 1;
    }

    tc_get_config_defaults(&config_tc);

    cycles_per_us = system_gclk_gen_get_hz(config_tc.clock_source) / 1000000;
    MBED_ASSERT(cycles_per_us > 0);
    /*while((cycles_per_us & 1) == 0 && prescaler <= 10) {
    	cycles_per_us = cycles_per_us >> 1;
    	prescaler++;
    }*/
    while((cycles_per_us > 1) && (prescaler <= 10)) {
        cycles_per_us = cycles_per_us >> 1;
        prescaler++;
    }
    if (prescaler >= 9) {
        prescaler = 7;
    } else if (prescaler >= 7) {
        prescaler = 6;
    } else if (prescaler >= 5) {
        prescaler = 5;
    }

    config_tc.clock_prescaler = TC_CTRLA_PRESCALER(prescaler);
    config_tc.counter_size = TC_COUNTER_SIZE_32BIT;
    config_tc.run_in_standby = true;
    config_tc.counter_32_bit.value = 0;
    config_tc.counter_32_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0] = 0xFFFFFFFF;
    config_tc.counter_32_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_1] = 0xFFFFFFFF;

    /* Initialize the timer */
    ret_status = tc_init(&us_ticker_module, TICKER_COUNTER_uS, &config_tc);
    MBED_ASSERT(ret_status == STATUS_OK);

    /* Register callback function */
    tc_register_callback(&us_ticker_module, (tc_callback_t)us_ticker_irq_handler_internal, TC_CALLBACK_CC_CHANNEL0);

    /* Enable the timer module */
    tc_enable(&us_ticker_module);
}
Esempio n. 10
0
/** Configures  TC function with the  driver.
 */
static void configure_tc(void)
{
    struct tc_config config_tc;

    tc_get_config_defaults(&config_tc);
    config_tc.counter_size    = TC_COUNTER_SIZE_16BIT;
    config_tc.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;
    config_tc.counter_16_bit.compare_capture_channel[0] = 2000;
    config_tc.clock_prescaler=TC_CLOCK_PRESCALER_DIV1024;

    tc_init(&tc_instance, CONF_TC_INSTANCE, &config_tc);
    tc_enable(&tc_instance);
}
Esempio n. 11
0
void configure_tc(void)
{
	struct tc_config config_tc;
	
	tc_get_config_defaults(&config_tc);
	config_tc.clock_source    = GCLK_GENERATOR_3;
	config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV1024;
	config_tc.counter_size    = TC_COUNTER_SIZE_8BIT;
	config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_FREQ;
	config_tc.count_direction = TC_COUNT_DIRECTION_UP;
	
	tc_init(&tc_instance, TC4, &config_tc);
	tc_enable(&tc_instance);

}
Esempio n. 12
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;
}
Esempio n. 13
0
void configure_tc3(void)
{


    REG_GCLK_GENDIV = 1 << 8 | 2;
    REG_GCLK_GENCTRL =
        1 << 21 | /* run in stdby */
        1 << 16 | /* enable */
        5 << 8 |  /* XOSC32 is source */
        2 << 0;   /* output to GCLKx */

    /* enable GCLKx for TC0/TC1, clocked at 32.768 kHz */
    REG_GCLK_CLKCTRL = 1 << 14 | 2 << 8 | 0x0013;

    TC3_WAIT_BUSY();

    //! [setup_config]
    struct tc_config config_tc;
    //! [setup_config]
    //! [setup_config_defaults]
    tc_get_config_defaults(&config_tc);
    //! [setup_config_defaults]

    //! [setup_change_config]
    config_tc.counter_size    = TC_COUNTER_SIZE_16BIT;
    config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_PWM;
    config_tc.counter_16_bit.compare_capture_channel[0] = 0x0101;
    //! [setup_change_config]

    //! [setup_change_config_pwm]
    //config_tc.pwm_channel[0].enabled = true;
    //config_tc.pwm_channel[0].pin_out = PWM_OUT_PIN;
    //config_tc.pwm_channel[0].pin_mux = PWM_OUT_MUX;
    //! [setup_change_config_pwm]

    //! [setup_set_config]
    //tc_init(&tc_instance, PWM_MODULE, &config_tc);
    tc_init(&tc3_instance, TC3, &config_tc);
    //! [setup_set_config]

    //! [setup_enable]
    tc_enable(&tc3_instance);
    //! [setup_enable]

    configure_tc3_callbacks();
}
Esempio n. 14
0
/** Set up the measurement and comparison timers for calibration.
 *   - Configure the measurement timer to run from the CPU clock, in capture
 *     mode.
 *   - Configure the reference timer to run from the reference clock, generating
 *     a capture every time the calibration resolution count is met.
 */
static void setup_tc_channels(void)
{
	struct tc_config config;
	tc_get_config_defaults(&config);

	/* Configure measurement timer to run from Fcpu and capture */
	config.counter_size    = TC_COUNTER_SIZE_32BIT;
	config.clock_prescaler = TC_CLOCK_PRESCALER_DIV1;
	config.wave_generation = TC_WAVE_GENERATION_NORMAL_FREQ;
	config.enable_capture_on_channel[0] = true;
	tc_init(&tc_calib, CONF_TC_MEASUREMENT, &config);

	/* Configure reference timer to run from reference clock and capture when the resolution count is met */
	config.counter_size    = TC_COUNTER_SIZE_16BIT;
	config.clock_source    = REFERENCE_CLOCK;
	config.enable_capture_on_channel[0] = false;
	config.counter_16_bit.compare_capture_channel[0] = (1 << CALIBRATION_RESOLUTION);
	tc_init(&tc_comp, CONF_TC_REFERENCE, &config);
}
/*!
* @brief		Configures TC6 of the MCU
*
* @param[in]	NULL
*
* @param[out]	NULL
*
* @return		NULL
*
*/
void tc6_configure(void)
{
	/* TC's configuration structure */
	struct tc_config config_tc;
	
	/* Get TC configuration default */
	tc_get_config_defaults(&config_tc);
	
	/* set the counter size */
	config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
	/* set TC GLCK */
	config_tc.clock_source = GCLK_GENERATOR_1;
	
	/* initialize TC6 with current configurations */
	tc_init(&tc6_instance,TC6,&config_tc);
	
	/* enable the TC module */
	tc_enable(&tc6_instance);
}
Esempio n. 16
0
void sys_init_timing(void)
{
	struct tc_config config_tc;
	tc_get_config_defaults(&config_tc);

	config_tc.counter_size    = TC_COUNTER_SIZE_16BIT;
	config_tc.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;
	config_tc.counter_16_bit.compare_capture_channel[0] = 0x5DC0;
	config_tc.clock_source = GCLK_GENERATOR_0;
	config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV2;

	tc_init(&tc_instance, TIMER, &config_tc);
	tc_enable(&tc_instance);
	tc_register_callback(&tc_instance, tc_callback, TC_CALLBACK_CC_CHANNEL0);
	tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL0);

	/* Enable system interrupts. */
	system_interrupt_enable_global();
}
void hw_timer_init(void)
{
	struct tc_config config_tc;

	tc_get_config_defaults(&config_tc);

	config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
	config_tc.clock_source = GCLK_GENERATOR_0;
	config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV1024;
	config_tc.counter_8_bit.period = 0;
	config_tc.counter_16_bit.compare_capture_channel[0] = TC_COUNT_1SEC;
	config_tc.counter_16_bit.compare_capture_channel[1] = 0xFFFF;

	tc_init(&tc_instance, CONF_TC_MODULE, &config_tc);

	tc_enable(&tc_instance);
	
	tc_register_callback(&tc_instance, tc_cc0_cb,
						TC_CALLBACK_CC_CHANNEL0);
}
void Adafruit_ZeroTimer::configure(tc_clock_prescaler prescale, tc_counter_size countersize, tc_wave_generation wavegen, tc_count_direction countdir)
{
  if (_timernum > TC_INST_MAX_ID) return;
  Tc *const tc_modules[TC_INST_NUM] = TC_INSTS;

  _countersize = countersize;

  tc_get_config_defaults(&config_tc);
  if (countersize == TC_COUNTER_SIZE_8BIT) {
    config_tc.counter_8_bit.period = 0xFF;
  }

  config_tc.clock_prescaler = prescale;
  config_tc.counter_size    = countersize;
  config_tc.wave_generation = wavegen;
  config_tc.count_direction = countdir;

  // initialize
  tc_init(&tc_instance, tc_modules[_timernum - TC_INSTANCE_OFFSET], &config_tc);
}
/*!
* @brief		Configures TC4 of the MCU
*
* @param[in]	NULL
*
* @param[out]	NULL
*
* @return		NULL
*
*/
void tc4_configure (void)
{
	/* TC's configuration structure */
	struct tc_config config_tc;
	
	/* Get TC configuration default */
	tc_get_config_defaults(&config_tc);
	
	/* set TC GLCK */
	config_tc.clock_source = GCLK_GENERATOR_1;
	
	/* Set the initial compare value */
	config_tc.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0] = 500;
	
	/* initialize TC4 with current configurations */
	tc_init(&tc4_instance, TC4, &config_tc);
	
	/* enable the TC module */
	tc_enable(&tc4_instance);
	
	/* Stop the counter */
	tc_stop_counter(&tc4_instance);
}
/* 
 * \brief Initialize and start timer for tick
 *
 * Function that sets up a timer to use for os tick. The same timer is also
 * used as the sleep timer.
 * The timer runs at 48MHz, i.e. with no prescaler on GCLK0. Wavegen function
 * Match Frequency is chosen to reload the count register on every CC0 match.
 * 8 bit counter mode must not be chosen.
 * The function is weakly defined in freeRTOS, and redefined here.
 */
void vPortSetupTimerInterrupt(void)
{
	// Struct for configuring TC
	struct tc_config tcconf;
	// Set up configuration values
	tc_get_config_defaults(&tcconf);
	tcconf.counter_size    = TC_COUNTER_SIZE_32BIT;
	tcconf.run_in_standby  = true;
	tcconf.clock_prescaler = TC_CLOCK_PRESCALER_DIV1;
	tcconf.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;

	// Initialize the TC
	tc_init(&tc, TICK_TC, &tcconf);

	// Register and enable callback for freeRTOS tick handler
	tc_register_callback(&tc, (tc_callback_t) xPortSysTickHandler, TC_CALLBACK_CC_CHANNEL0);
	tc_enable_callback(&tc, TC_CALLBACK_CC_CHANNEL0);

	// Set top value equal to one os tick
	tc_set_top_value(&tc, TIMER_RELOAD_VALUE_ONE_TICK);

	// Enable the timer
	tc_enable(&tc);
}
Esempio n. 21
0
/**
 * \internal
 * \brief Test initializing and resetting 32-bit TC and reinitialize
 *
 * This test tests the software reset of a 32-bit TC by the use of the
 * tc_reset(). It also test re-enabling the two TC modules used in the 32-bit
 * TC into two separate 16-bit TC's.
 *
 * \param test Current test case.
 */
static void run_reset_32bit_master_test(const struct test_case *test)
{
	test_assert_true(test,
			tc_init_success == true,
			"TC initialization failed, skipping test");

	/* Configure 32-bit TC module and run test*/
	tc_reset(&tc_test0_module);
	tc_get_config_defaults(&tc_test0_config);
	tc_test0_config.counter_size = TC_COUNTER_SIZE_32BIT;

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

	while (tc_is_syncing(&tc_test0_module)) {
		/* Synchronize enable */
	}

	test_assert_true(test,
			tc_test0_module.hw->COUNT32.CTRLA.reg & TC_CTRLA_ENABLE,
			"Failed first enable of 32-bit TC");

	/* Reset and test if both TC modules are disabled after reset */
	tc_reset(&tc_test0_module);

	while (tc_is_syncing(&tc_test0_module)) {
		/* Synchronize reset */
	}

	test_assert_false(test,
			tc_test0_module.hw->COUNT32.CTRLA.reg & TC_CTRLA_ENABLE,
			"Failed reset of 32-bit master TC TEST0");
	test_assert_false(test,
			tc_test1_module.hw->COUNT32.CTRLA.reg & TC_CTRLA_ENABLE,
			"Failed reset of 32-bit slave TC TEST1");

	/* Change to 16-bit counter on TC0  */
	tc_test0_config.counter_size = TC_COUNTER_SIZE_16BIT;

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

	while (tc_is_syncing(&tc_test0_module)) {
		/* Synchronize enable */
	}


	tc_init(&tc_test1_module, CONF_TEST_TC1, &tc_test1_config);
	tc_enable(&tc_test1_module);

	while (tc_is_syncing(&tc_test1_module)) {
		/* Synchronize enable */
	}

	test_assert_true(test,
			tc_test0_module.hw->COUNT16.CTRLA.reg & TC_CTRLA_ENABLE,
			"Failed re-enable of TC TEST0");
	test_assert_true(test,
			tc_test1_module.hw->COUNT16.CTRLA.reg & TC_CTRLA_ENABLE,
			"Failed re-enable of TC TEST1");
}
Esempio n. 22
0
/** Initializes the XOSC32K crystal failure detector, and starts it.
 *
 *  \param[in]  ok_callback    Callback function to run upon XOSC32K operational
 *  \param[in]  fail_callback  Callback function to run upon XOSC32K failure
 */
static void init_xosc32k_fail_detector(
		const tc_callback_t ok_callback,
		const tc_callback_t fail_callback)
{
	/* TC pairs share the same clock, ensure reference and crystal timers use
	 * different clocks */
	Assert(Abs(_tc_get_inst_index(CONF_TC_OSC32K) -
			_tc_get_inst_index(CONF_TC_XOSC32K)) >= 2);

	/* The crystal detection cycle count must be less than the reference cycle
	 * count, so that the reference timer is periodically reset before expiry */
	Assert(CRYSTAL_RESET_CYCLES < CRYSTAL_FAIL_CYCLES);

	/* Must use different clock generators for the crystal and reference, must
	 * not be CPU generator 0 */
	Assert(GCLK_GENERATOR_XOSC32K != GCLK_GENERATOR_OSC32K);
	Assert(GCLK_GENERATOR_XOSC32K != GCLK_GENERATOR_0);
	Assert(GCLK_GENERATOR_OSC32K  != GCLK_GENERATOR_0);

	/* Configure and enable the XOSC32K GCLK generator */
	struct system_gclk_gen_config xosc32k_gen_conf;
	system_gclk_gen_get_config_defaults(&xosc32k_gen_conf);
	xosc32k_gen_conf.source_clock = SYSTEM_CLOCK_SOURCE_XOSC32K;
	system_gclk_gen_set_config(GCLK_GENERATOR_XOSC32K, &xosc32k_gen_conf);
	system_gclk_gen_enable(GCLK_GENERATOR_XOSC32K);

	/* Configure and enable the reference clock GCLK generator */
	struct system_gclk_gen_config ref_gen_conf;
	system_gclk_gen_get_config_defaults(&ref_gen_conf);
	ref_gen_conf.source_clock = SYSTEM_CLOCK_SOURCE_OSC32K;
	system_gclk_gen_set_config(GCLK_GENERATOR_OSC32K, &ref_gen_conf);
	system_gclk_gen_enable(GCLK_GENERATOR_OSC32K);

	/* Set up crystal counter - when target count elapses, trigger event */
	struct tc_config tc_xosc32k_conf;
	tc_get_config_defaults(&tc_xosc32k_conf);
	tc_xosc32k_conf.clock_source = GCLK_GENERATOR_XOSC32K;
	tc_xosc32k_conf.counter_16_bit.compare_capture_channel[0] =
			CRYSTAL_RESET_CYCLES;
	tc_xosc32k_conf.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;
	tc_init(&tc_xosc32k, CONF_TC_XOSC32K, &tc_xosc32k_conf);

	/* Set up reference counter - when event received, restart */
	struct tc_config tc_osc32k_conf;
	tc_get_config_defaults(&tc_osc32k_conf);
	tc_osc32k_conf.clock_source = GCLK_GENERATOR_OSC32K;
	tc_osc32k_conf.counter_16_bit.compare_capture_channel[0] =
			CRYSTAL_FAIL_CYCLES;
	tc_osc32k_conf.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;
	tc_init(&tc_osc32k, CONF_TC_OSC32K, &tc_osc32k_conf);

	/* Configure event channel and link it to the xosc32k counter */
	struct events_config config;
	struct events_resource event;
	events_get_config_defaults(&config);
	config.edge_detect  = EVENTS_EDGE_DETECT_NONE;
	config.generator    = CONF_EVENT_GENERATOR_ID;
	config.path         = EVENTS_PATH_ASYNCHRONOUS;
	events_allocate(&event, &config);
	/* Configure event user and link it to the osc32k counter */
	events_attach_user(&event, CONF_EVENT_USED_ID);

	/* Enable event generation for crystal counter */
	struct tc_events tc_xosc32k_events = { .generate_event_on_overflow = true };
	tc_enable_events(&tc_xosc32k, &tc_xosc32k_events);

	/* Enable event reception for reference counter */
	struct tc_events tc_osc32k_events = { .on_event_perform_action = true };
	tc_osc32k_events.event_action = TC_EVENT_ACTION_RETRIGGER;
	tc_enable_events(&tc_osc32k, &tc_osc32k_events);

	/* Enable overflow callback for the crystal counter - if crystal count
	 * has been reached, crystal is operational */
	tc_register_callback(&tc_xosc32k, ok_callback, TC_CALLBACK_CC_CHANNEL0);
	tc_enable_callback(&tc_xosc32k, TC_CALLBACK_CC_CHANNEL0);

	/* Enable compare callback for the reference counter - if reference count
	 * has been reached, crystal has failed */
	tc_register_callback(&tc_osc32k, fail_callback, TC_CALLBACK_CC_CHANNEL0);
	tc_enable_callback(&tc_osc32k, TC_CALLBACK_CC_CHANNEL0);

	/* Start both crystal and reference counters */
	tc_enable(&tc_xosc32k);
	tc_enable(&tc_osc32k);
}

/** Main application entry point. */
int main(void)
{
	system_init();

	system_flash_set_waitstates(2);

	init_osc32k();
	init_xosc32k();
	init_xosc32k_fail_detector(
			xosc32k_ok_callback, xosc32k_fail_callback);

#if ENABLE_CPU_CLOCK_OUT == true
	/* Configure a GPIO pin as the CPU clock output */
	struct system_pinmux_config clk_out_pin;
	system_pinmux_get_config_defaults(&clk_out_pin);
	clk_out_pin.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT;
	clk_out_pin.mux_position = CONF_CLOCK_PIN_MUX;
	system_pinmux_pin_set_config(CONF_CLOCK_PIN_OUT, &clk_out_pin);
#endif

	for (;;) {
		static bool old_run_osc = true;
		bool new_run_osc =
				(port_pin_get_input_level(BUTTON_0_PIN) == BUTTON_0_INACTIVE);

		/* Check if the XOSC32K needs to be started or stopped when the board
		 * button is pressed or released */
		if (new_run_osc != old_run_osc) {
			if (new_run_osc) {
				system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC32K);
				while(!system_clock_source_is_ready(
						SYSTEM_CLOCK_SOURCE_XOSC32K));
			}
			else {
				system_clock_source_disable(SYSTEM_CLOCK_SOURCE_XOSC32K);
			}

			old_run_osc = new_run_osc;
		}
	}
}
Esempio n. 23
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 */
        }
    }
}
Esempio n. 24
0
/**
 * \brief Initialize the TC3 & RTC for unit test
 *
 * Initializes the RTC module and TC3 module which are used as
 * event generator and event user respectively.
 */
static void test_event_gen_user_init(void)
{
	enum status_code status;
	init_success = true;

	/* Timer configuration (Event User) */
	struct tc_config config_tc;

	tc_get_config_defaults(&config_tc);
	config_tc.counter_16_bit.compare_capture_channel[0]
		= (0xFFFF / 4);

	/* Initialize the TC3 */
	status = tc_init(&tc_inst, TC3, &config_tc);
	if (status != STATUS_OK) {
		init_success = false;
	}

	struct tc_events events_tc;

	events_tc.on_event_perform_action = true;
	events_tc.event_action = TC_EVENT_ACTION_START;

	tc_enable_events(&tc_inst, &events_tc);

	/* Enable the TC3 */
	tc_enable(&tc_inst);

	/* RTC configuration (Event Generator) */
	struct rtc_count_config config_rtc_count;
	struct rtc_count_events config_rtc_event
		= { .generate_event_on_overflow = true };

	/* Initialize the RTC module */
	rtc_count_get_config_defaults(&config_rtc_count);
	config_rtc_count.prescaler           = RTC_COUNT_PRESCALER_DIV_1;
	config_rtc_count.mode                = RTC_COUNT_MODE_16BIT;
#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED
	config_rtc_count.continuously_update = true;
#endif
	config_rtc_count.compare_values[0]   = 50;
	status = rtc_count_init(&rtc_inst, RTC, &config_rtc_count);

	if (status != STATUS_OK) {
		init_success = false;
	}

	/* Enable RTC events */
	config_rtc_event.generate_event_on_overflow = true;
	rtc_count_enable_events(&rtc_inst, &config_rtc_event);
}

/**
 * \internal
 * \brief Setup Function: Synchronous event propagation.
 *
 * This function initializes the event system channel 0 and the RTC
 * module (event generator) to be in the same clock domain for
 * synchronous event propagation.
 *
 * \param test Current test case.
 */
static void setup_synchronous_event_test(const struct test_case *test)
{
	struct events_config   events_conf;

	/* Get default event channel configuration */
	events_get_config_defaults(&events_conf);

	events_conf.clock_source   = GCLK_GENERATOR_2;
	events_conf.edge_detect    = EVENTS_EDGE_DETECT_RISING;
	events_conf.path           = EVENTS_PATH_SYNCHRONOUS;
	events_conf.generator      = TEST_EVENT_GEN;

	events_allocate(&events, &events_conf);
	events_attach_user(&events, TEST_EVENT_USER);
}

/**
 * \internal
 * \brief Test for event system in synchronous mode.
 *
 * This test waits for event channel and user to be ready and then
 * starts the RTC to generate overflow event. It waits until the timer
 * is started. If the timer starts running then it can be assumed that
 * the event has been propagated properly.
 *
 * \param test Current test case.
 */
static void run_synchronous_event_test(const struct test_case *test)
{
	uint32_t timeout_cycles = 1000;

	/* Skip test if initialization failed */
	test_assert_true(test, init_success,
			"Skipping test due to failed initialization");

	/* Check whether event user is ready */
	do {

		timeout_cycles--;
		if (events_is_users_ready(&events)) {
			break;
		}

	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Timeout error: Event user not ready");

	/* Check whether event channel is ready */
	timeout_cycles = 1000;
	do {

		timeout_cycles--;
		if (!events_is_busy(&events)) {
			break;
		}

	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Timeout error: Event channel not ready");

	/* Event action test */
	rtc_count_enable(&rtc_inst);
	rtc_count_set_period(&rtc_inst, 100);
	timeout_cycles = 10000;

	do {

		timeout_cycles--;
		if (tc_get_count_value(&tc_inst)) {
			break;
		}

	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Error: Timeout in event reception/action");
}
Esempio n. 25
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) {

	}
}
Esempio n. 26
0
/**
 * \internal
 * \brief Test capture and compare
 *
 * This test uses TC module 0 as a PWM generator (compare function).
 * TC module 1 will be set to capture the signal from TC module 0 to test the capture
 * functionality.
 *
 * \param test Current test case.
 */
static void run_16bit_capture_and_compare_test(const struct test_case *test)
{
	test_assert_true(test,
			tc_init_success == true,
			"TC initialization failed, skipping test");

	test_assert_true(test,
			callback_function_entered == 1,
			"The callback test has failed, skipping test");

	/* Configure 16-bit TC module for PWM generation */
	tc_reset(&tc_test0_module);
	tc_get_config_defaults(&tc_test0_config);
	tc_test0_config.wave_generation  = TC_WAVE_GENERATION_MATCH_PWM;
	tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0]  = 0x03FF;
	tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_1]  = 0x01FF;

	/* Calculate the theoretical PWM frequency & duty */
	uint32_t frequency_output, duty_output;
	frequency_output = system_clock_source_get_hz(SYSTEM_CLOCK_SOURCE_OSC8M)/ (0x03FF+1);

	/* This value is depend on the WaveGeneration Mode */
	duty_output = (uint32_t)(tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_1]) * 100 \
					/ tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0];

	tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].enabled = true;
	tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].pin_out = CONF_TEST_PIN_OUT;
	tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].pin_mux = CONF_TEST_PIN_MUX;
	tc_init(&tc_test0_module, CONF_TEST_TC0, &tc_test0_config);

	tc_register_callback(&tc_test0_module, tc_callback_function, TC_CALLBACK_CC_CHANNEL0);
	tc_enable_callback(&tc_test0_module, TC_CALLBACK_CC_CHANNEL0);

	/* Configure 16-bit TC module for capture */
	tc_reset(&tc_test1_module);
	tc_get_config_defaults(&tc_test1_config);
	tc_test1_config.clock_prescaler              = TC_CLOCK_PRESCALER_DIV1;
	tc_test1_config.enable_capture_on_channel[CONF_CAPTURE_CHAN_0] = true;
	tc_test1_config.enable_capture_on_channel[CONF_CAPTURE_CHAN_1] = true;

	tc_init(&tc_test1_module, CONF_TEST_TC1, &tc_test1_config);

	struct tc_events tc_events = { .on_event_perform_action = true,
								.event_action = TC_EVENT_ACTION_PPW,};

	tc_enable_events(&tc_test1_module, &tc_events);

	/* Configure external interrupt controller */
	struct extint_chan_conf extint_chan_config;
	extint_chan_config.gpio_pin            = CONF_EIC_PIN;
	extint_chan_config.gpio_pin_mux        = CONF_EIC_MUX;
	extint_chan_config.gpio_pin_pull       = EXTINT_PULL_UP;
	extint_chan_config.wake_if_sleeping    = false;
	extint_chan_config.filter_input_signal = false;
	extint_chan_config.detection_criteria  = EXTINT_DETECT_HIGH;
	extint_chan_set_config(0, &extint_chan_config);

	/* Configure external interrupt module to be event generator */
	struct extint_events extint_event_conf;
	extint_event_conf.generate_event_on_detect[0] = true;
	extint_enable_events(&extint_event_conf);

	/* Configure event system */
	struct events_resource event_res;

	/* Configure channel */
	struct events_config config;
	events_get_config_defaults(&config);
	config.generator      = CONF_EVENT_GENERATOR_ID;
	config.edge_detect    = EVENTS_EDGE_DETECT_NONE;
	config.path           = EVENTS_PATH_ASYNCHRONOUS;
	events_allocate(&event_res, &config);

	/* Configure user */
	events_attach_user(&event_res, CONF_EVENT_USED_ID);

	/* Enable TC modules */
	tc_enable(&tc_test1_module);
	tc_enable(&tc_test0_module);

	uint16_t period_after_capture = 0;
	uint16_t pulse_width_after_capture = 0;
	uint32_t capture_frequency = 0;
	uint32_t capture_duty = 0;


	while (callback_function_entered < 4) {
		period_after_capture = tc_get_capture_value(&tc_test1_module,
				TC_COMPARE_CAPTURE_CHANNEL_0);
		pulse_width_after_capture = tc_get_capture_value(&tc_test1_module,
				TC_COMPARE_CAPTURE_CHANNEL_1);
	}

	if(period_after_capture != 0) {
		capture_frequency = system_clock_source_get_hz(SYSTEM_CLOCK_SOURCE_OSC8M)/ period_after_capture;
		capture_duty = (uint32_t)(pulse_width_after_capture) * 100 / period_after_capture;
	}

	test_assert_true(test,
			(capture_frequency <= (frequency_output * (100 + CONF_TEST_TOLERANCE) / 100)) && \
			(capture_frequency >= (frequency_output * (100 - CONF_TEST_TOLERANCE) / 100)) && \
			(capture_duty <= (duty_output * (100 + CONF_TEST_TOLERANCE) / 100)) && \
			(capture_duty >= (duty_output * (100 - CONF_TEST_TOLERANCE) / 100)) \
			,"The result of Capture is wrong, captured frequency: %ldHz, captured duty: %ld%%",
			capture_frequency,
			capture_duty
			);
}

/**
 * \brief Initialize the USART for unit test
 *
 * Initializes the SERCOM USART used for sending the unit test status to the
 * computer via the EDBG CDC gateway.
 */
static void cdc_uart_init(void)
{
	struct usart_config usart_conf;

	/* Configure USART for unit test output */
	usart_get_config_defaults(&usart_conf);
	usart_conf.mux_setting = CONF_STDIO_MUX_SETTING;
	usart_conf.pinmux_pad0 = CONF_STDIO_PINMUX_PAD0;
	usart_conf.pinmux_pad1 = CONF_STDIO_PINMUX_PAD1;
	usart_conf.pinmux_pad2 = CONF_STDIO_PINMUX_PAD2;
	usart_conf.pinmux_pad3 = CONF_STDIO_PINMUX_PAD3;
	usart_conf.baudrate    = CONF_STDIO_BAUDRATE;

	stdio_serial_init(&cdc_uart_module, CONF_STDIO_USART, &usart_conf);
	usart_enable(&cdc_uart_module);
}

/**
 * \brief Run TC unit tests
 *
 * Initializes the system and serial output, then sets up the TC unit test
 * suite and runs it.
 */
int main(void)
{
	system_init();
	cdc_uart_init();

	/* Define Test Cases */
	DEFINE_TEST_CASE(init_test, NULL,
			run_init_test, NULL,
			"Initialize tc_xmodules");

	DEFINE_TEST_CASE(basic_functionality_test, NULL,
			run_basic_functionality_test, NULL,
			"test start stop and getters and setters");

	DEFINE_TEST_CASE(callback_test, NULL,
			run_callback_test, NULL,
			"test callback API");

	DEFINE_TEST_CASE(reset_32bit_master_test, NULL,
			run_reset_32bit_master_test, NULL,
			"Setup, reset and reinitialize TC modules of a 32-bit TC");


	DEFINE_TEST_CASE(capture_and_compare_test, NULL,
			run_16bit_capture_and_compare_test, NULL,
			"Test capture and compare");

	/* Put test case addresses in an array */
	DEFINE_TEST_ARRAY(tc_tests) = {
		&init_test,
		&basic_functionality_test,
		&callback_test,
		&reset_32bit_master_test,
		&capture_and_compare_test,
	};

	/* Define the test suite */
	DEFINE_TEST_SUITE(tc_suite, tc_tests,
			"SAM TC driver test suite");

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

	tc_reset(&tc_test0_module);
	tc_reset(&tc_test1_module);

	while (true) {
		/* Intentionally left empty */
	}
}