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); }
/** * \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)) { } }
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); } }
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); }
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); }
/** * \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); }
void qdec_reset_position(qdec_config_t *config) { tc_write_count(config->timer, 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 */ }