void generator_qenc_set_freq(uint32_t freq)
{
	/* Number of ticks per step */
	uint16_t ticks = 0;

	/* The following code calculates the upper boundary of the timer and the
	 * interrupt positions to get a correct Quadrature signal of the given
	 * frequency.
	 * The different compare interrupts sets the phase0 and phase90 signals.
	 * Phase-0 uses Pin1, Phase90-Pin2 and Index-Pin3 from selected port
	 *
	 * Compare A interrupt clear phase0 and sets phase90
	 * Compare B interrupt sets phase0 and phase90
	 * Compare C interrupt sets phase0 and clear phase90
	 * Compare D interrupt clears phase0 and phase90.
	 *
	 * Compare A interrupt also sets the index signal when one round has
	 * passed.
	 */

	/* Calculates upper boundary of timer to get desired frequency */
	tc_set_resolution(generator_qenc_timer,
			(freq * generator_qenc_revolution) / 1000);
	ticks = ((uint64_t)tc_get_resolution(generator_qenc_timer) *
			1000) / (freq * generator_qenc_revolution);

	/* Write timer period register */
	tc_write_count(generator_qenc_timer, 0);
	tc_write_period(generator_qenc_timer, ticks);
}
예제 #2
0
/**
 * \internal
 * \brief Generate a delay in ms
 *
 * \param delay_ms  Number of ms to wait
 */
static void main_delay_ms(uint16_t delay_ms)
{
	uint16_t ticks_delay;

	tc_write_count(CONF_DELAY_TC, 0);
	ticks_delay = (uint64_t)tc_get_resolution(CONF_DELAY_TC) * delay_ms
			/ 1000;
	while (ticks_delay > tc_read_count(CONF_DELAY_TC)) {
	}
}
예제 #3
0
void app_cpu_load_exit_sleep(void)
{
	if (app_cpu_load_sleep) {
		/* It is a sleep mode exit */
		app_cpu_load_sleep = false;
		app_cpu_load_time_sleep += tc_read_count(&TCC1);
		/* Reset Timer counter */
		tc_write_count(&TCC1, 0);
	}
}
예제 #4
0
void app_cpu_load_enter_sleep(void)
{
	/* Disable all interrupts to avoid interrupt
	 * before enter the CPU in sleep mode */
	cpu_irq_disable();
	app_cpu_load_sleep = true;
	app_cpu_load_time_actif += tc_read_count(&TCC1);
	/* Reset Timer counter */
	tc_write_count(&TCC1, 0);
}
예제 #5
0
static void qdec_enabled_tc(qdec_config_t *config)
{
	/* Configure TC for quadrature decode for event action and
	 * event channel selection:
	 * - Set event source and event action as per sent parameters
	 * - Load Period register of TC with number of counts for single
	 *   revolution
	 * - Write clock value and start timer
	 */
	tc_enable(config->timer);
	tc_set_input_capture(config->timer,
			(TC_EVSEL_t)(TC_EVSEL_CH0_gc + config->event_channel),
			TC_EVACT_QDEC_gc);
	tc_write_count(config->timer, 0);
	tc_write_period(config->timer, config->revolution - 1);
	tc_write_clock_source(config->timer, TC_CLKSEL_DIV1_gc);
}
예제 #6
0
파일: main.c 프로젝트: Tjalling7/asf
/**
 * \brief Delay function which use a Timer Counter and can be aborted
 * SW1 pressed stop delay.
 *
 * \param delay_ms  delay in ms
 */
static void main_introduction_delay(uint16_t delay_ms)
{
    /* Initialization TC to manage a delay between each slide */
    tc_enable(&TCC1);
    tc_write_clock_source(&TCC1, TC_CLKSEL_DIV1024_gc); /* 24MHz / 1024 */
    tc_set_direction(&TCC1, TC_UP);
    while (delay_ms) {
        tc_write_count(&TCC1, 0);
        uint16_t delay_step = delay_ms;
        if (delay_step > 2800) {
            delay_step = 2500;
        }

        while (tc_read_count(&TCC1) <
                ((24000lu * delay_step) / 1024lu)) {
            if (main_introduction_is_exist()) {
                break;
            }
        }
        delay_ms -= delay_step;
    }
    tc_disable(&TCC1);
}
예제 #7
0
void qdec_reset_position(qdec_config_t *config)
{
	tc_write_count(config->timer, 0);
}
예제 #8
0
static void qdec_enabled_tc_freq(qdec_config_t *config)
{
	volatile uint8_t *evsys_chctrl, *evsys_chctrl_freq;

	/* Configuration of frequency calculation */
	Assert(config->event_channel != config->freq_opt.event_channel);
	if (config->index.enabled) {
		Assert((config->event_channel + 1)
				!= config->freq_opt.event_channel);
	}

#if XMEGA_E

	/* Channel must be < 4, because QDec channel is 0
	 * and EVSYS.DFCTRL enables filter per event group */
	Assert(config->freq_opt.event_channel < 4);
#endif

	/* In event channel enable digital filter as QDec event channel */
#if XMEGA_E
	if (EVSYS.DFCTRL & EVSYS_PRESCFILT_CH04_gc) {
		if (config->freq_opt.event_channel == 1) {
			EVSYS.DFCTRL |= EVSYS_PRESCFILT_CH15_gc;
		} else if (config->freq_opt.event_channel == 2) {
			EVSYS.DFCTRL |= EVSYS_PRESCFILT_CH26_gc;
		} else {
			EVSYS.DFCTRL |= EVSYS_PRESCFILT_CH37_gc;
		}
	}

#endif
	evsys_chctrl_freq = &EVSYS.CH0CTRL + config->freq_opt.event_channel;
	evsys_chctrl = &EVSYS.CH0CTRL + config->event_channel;
	*evsys_chctrl_freq = *evsys_chctrl & EVSYS_DIGFILT_gm;

	/* Configure event channel for frequency calculation */
	qdec_evsys_pin_2_chmux(config->port, config->pins_base,
			config->freq_opt.event_channel);

	/* Configure TC to capture frequency
	 * Load timer period register
	 * Enable capture on CCA channel
	 * Select timer clock source
	 */
	tc_enable(config->freq_opt.timer);
	tc_set_input_capture(config->freq_opt.timer,
			(TC_EVSEL_t)(TC_EVSEL_CH0_gc
			+ config->freq_opt.event_channel),
			TC_EVACT_FRQ_gc);
	tc_write_count(config->freq_opt.timer, 0);
	tc_write_period(config->freq_opt.timer, 0xFFFF);
	tc_enable_cc_channels(config->freq_opt.timer, TC_CCAEN);
	tc_set_resolution(config->freq_opt.timer,
			(config->freq_opt.unit / 1000) / config->revolution);
	config->freq_opt.coef
			= (((uint64_t)tc_get_resolution(config->freq_opt.timer) * 1000)
			/ config->freq_opt.unit)
			* 4
			/ config->revolution;
	config->freq_opt.last_freq = 0; /* Initialize frequence to 0Hz */
}