/** * \internal * \brief Setup Function: AC callback mode test. * * This function initializes the AC to generate interrupt when the AC * output toggles. * * \param test Current test case. */ static void setup_ac_callback_mode_test(const struct test_case *test) { enum status_code status = STATUS_ERR_IO; /* Structure for AC configuration */ struct ac_config config; struct ac_chan_config channel_config; /* Set the flag to false */ ac_init_success = false; ac_reset(&ac_inst); ac_get_config_defaults(&config); /* Initialize the AC */ status = ac_init(&ac_inst, AC, &config); /* Check for successful initialization */ test_assert_true(test, status == STATUS_OK, "AC initialization failed"); /* Configure the AC input pin */ struct system_pinmux_config ac0_pin_conf; system_pinmux_get_config_defaults(&ac0_pin_conf); ac0_pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; ac0_pin_conf.mux_position = MUX_PA04B_AC_AIN0; system_pinmux_pin_set_config(PIN_PA04B_AC_AIN0, &ac0_pin_conf); /* Channel configuration */ status = STATUS_ERR_IO; ac_chan_get_config_defaults(&channel_config); channel_config.sample_mode = AC_CHAN_MODE_CONTINUOUS; channel_config.positive_input = AC_CHAN_POS_MUX_PIN0; channel_config.negative_input = AC_CHAN_NEG_MUX_SCALED_VCC; channel_config.vcc_scale_factor = AC_SCALER_0_50_VOLT; status = ac_chan_set_config(&ac_inst, AC_CHAN_CHANNEL_0, &channel_config); /* Check for successful initialization */ test_assert_true(test, status == STATUS_OK, "AC channel initialization failed"); /* Callback configuration */ status = ac_register_callback(&ac_inst, ac_user_callback, AC_CALLBACK_COMPARATOR_0); test_assert_true(test, status == STATUS_OK, "AC callback registration failed"); /* Enable the AC channel & the module */ ac_chan_enable(&ac_inst, AC_CHAN_CHANNEL_0); ac_enable(&ac_inst); ac_enable_callback(&ac_inst, AC_CALLBACK_COMPARATOR_0); if (status == STATUS_OK) { ac_init_success = true; } }
/** * \brief Main function. */ int main(void) { enum ac_status_t status; pmic_init(); board_init(); sysclk_init(); sleepmgr_init(); ac_set_interrupt_callback(&ACA, example_aca_interrupt_callback); /* Write configuration of analog comparator A channel 0. */ ac_write_config(&ACA, 0, &aca0_config); /* Write predefined configuration of analog comparator A channel 1. */ ac_write_config(&ACA, 1, &aca1_config); /* Enable all the analog comparator channels. */ ac_enable(&ACA, 0); ac_enable(&ACA, 1); /* * Wait for analog comparator to stabilize (muxing, voltage scaler, * bandgap voltage, etc). */ mdelay(1); /* Check comparator status and initialize the LEDs. */ status = ac_get_status(&ACA, 0); example_ac_update_single_leds(0, status); status = ac_get_status(&ACA, 1); example_ac_update_single_leds(1, status); cpu_irq_enable(); for (;;) { /* Go to sleep, everything is handled by interrupts. */ sleepmgr_enter_sleep(); } }
/** * \brief Analog comparator interrupt callback function * * This function is called when an interrupt has occurred on a channel in analog * comparator. * * \param ac Pointer to the analog comparator (AC) base address which caused * the interrupt * \param channel The analog comparator channel that caused the interrupt * \param status Analog comparator window status given by a \ref ac_status_t * value */ static void example_aca_interrupt_callback(AC_t *ac, uint8_t channel, enum ac_status_t status) { /* * If trigger was caused by moving into above or below, switch to * trigger by being inside. If trigger was caused by moving inside the * window, switch to trigger on outside. */ if (status != AC_STATUS_INSIDE) { ac_set_interrupt_mode(&aca_config, AC_INT_MODE_INSIDE_WINDOW); } else { ac_set_interrupt_mode(&aca_config, AC_INT_MODE_OUTSIDE_WINDOW); } ac_disable(&ACA, 1); ac_disable(&ACA, 0); ac_write_config(&ACA, 0, &aca_config); ac_enable(&ACA, 0); ac_enable(&ACA, 1); example_ac_update_window_leds(status); }
static void configure_ac(void) { static struct ac_module ac_instance; struct ac_config config_ac; ac_get_config_defaults(&config_ac); config_ac.ana_source_generator = GCLK_GENERATOR_1; config_ac.dig_source_generator = GCLK_GENERATOR_1; /* Initialize and enable the Analog Comparator with the user settings */ ac_init(&ac_instance, AC1, &config_ac); /* Create a new configuration structure for the Analog Comparator channel * settings and fill with the default module channel settings. */ struct ac_chan_config ac_chan_conf; ac_chan_get_config_defaults(&ac_chan_conf); /* Set the Analog Comparator channel configuration settings */ ac_chan_conf.sample_mode = AC_CHAN_MODE_CONTINUOUS; ac_chan_conf.filter = AC_CHAN_FILTER_NONE; ac_chan_conf.positive_input = AC_CHAN_POS_MUX_PIN3; ac_chan_conf.negative_input = AC_CHAN_NEG_MUX_SCALED_VCC; ac_chan_conf.vcc_scale_factor = AC_SCALING_FACTOR; ac_chan_conf.output_mode = AC_CHAN_OUTPUT_INTERNAL; /* Initialize and enable the Analog Comparator channel with the user * settings */ ac_chan_set_config(&ac_instance, 0, &ac_chan_conf); /* Set up a pin as an AC channel input */ struct system_pinmux_config ac0_pin_conf; system_pinmux_get_config_defaults(&ac0_pin_conf); ac0_pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; ac0_pin_conf.mux_position = MUX_PB03B_AC1_AIN3; system_pinmux_pin_set_config(PIN_PB03B_AC1_AIN3, &ac0_pin_conf); /* Setup event output from AC */ struct ac_events ac_event_conf; memset(&ac_event_conf, 0, sizeof(struct ac_events)); ac_event_conf.generate_event_on_state[0] = true; ac_enable_events(&ac_instance, &ac_event_conf); /* enable AC channel */ ac_chan_enable(&ac_instance, 0); ac_enable(&ac_instance); }
//! [setup] int main(void) { //! [setup_init] system_init(); configure_ac(); configure_ac_channel(); configure_ac_callback(); //! [setup_17] ac_enable(&ac_instance); //! [setup_17] //! [setup_init] //! [main] //! [main_1] ac_chan_trigger_single_shot(&ac_instance, AC_COMPARATOR_CHANNEL); //! [main_1] //! [main_2] uint8_t last_comparison = AC_CHAN_STATUS_UNKNOWN; //! [main_2] port_pin_set_output_level(LED_0_PIN, true); //! [main_3] while (true) { //! [main_3] //! [main_4] if (callback_status == true) { //! [main_4] //! [main_5] do { last_comparison = ac_chan_get_status(&ac_instance, AC_COMPARATOR_CHANNEL); } while (last_comparison & AC_CHAN_STATUS_UNKNOWN); //! [main_5] //! [main_6] port_pin_set_output_level(LED_0_PIN, (last_comparison & AC_CHAN_STATUS_NEG_ABOVE_POS)); //! [main_6] //! [main_7] callback_status = false; //! [main_7] //! [main_8] ac_chan_trigger_single_shot(&ac_instance, AC_COMPARATOR_CHANNEL); //! [main_8] } } //! [main] }
/** * \internal * \brief Test for AC initialization. * * This test initializes the AC module and checks whether the * initialization is successful or not. * * If this test fails no other tests will run. * * \param test Current test case. */ static void run_ac_init_test(const struct test_case *test) { enum status_code status = STATUS_ERR_IO; /* Structure for AC configuration */ struct ac_config config; struct ac_chan_config channel_config; ac_get_config_defaults(&config); /* Initialize the AC */ status = ac_init(&ac_inst, AC, &config); /* Check for successful initialization */ test_assert_true(test, status == STATUS_OK, "AC initialization failed"); status = STATUS_ERR_IO; ac_chan_get_config_defaults(&channel_config); channel_config.sample_mode = AC_CHAN_MODE_SINGLE_SHOT; channel_config.positive_input = AC_CHAN_POS_MUX_PIN0; channel_config.negative_input = AC_CHAN_NEG_MUX_SCALED_VCC; channel_config.vcc_scale_factor = AC_SCALER_0_50_VOLT; struct system_pinmux_config ac0_pin_conf; system_pinmux_get_config_defaults(&ac0_pin_conf); ac0_pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; ac0_pin_conf.mux_position = MUX_PA04B_AC_AIN0; system_pinmux_pin_set_config(PIN_PA04B_AC_AIN0, &ac0_pin_conf); /* Set the channel configuration */ status = ac_chan_set_config(&ac_inst, AC_CHAN_CHANNEL_0, &channel_config); /* Check for successful configuration */ test_assert_true(test, status == STATUS_OK, "AC channel configuration failed"); /* Enable the AC channel & AC module */ ac_chan_enable(&ac_inst, AC_CHAN_CHANNEL_0); ac_enable(&ac_inst); if (status == STATUS_OK) { ac_init_success = true; } }
/** * \brief Main function. */ int main(void) { enum ac_status_t status; pmic_init(); board_init(); sysclk_init(); sleepmgr_init(); ac_set_interrupt_callback(&ACA, example_aca_interrupt_callback); /* Setup the analog comparator B in window mode. */ ac_set_mode(&aca_config, AC_MODE_WINDOW); ac_set_voltage_scaler(&aca_config, 11); ac_set_hysteresis(&aca_config, AC_HYSMODE_LARGE_gc); ac_set_negative_reference(&aca_config, AC_MUXNEG_SCALER_gc); ac_set_positive_reference(&aca_config, AC_MUXPOS_PIN1_gc); ac_set_interrupt_mode(&aca_config, AC_INT_MODE_INSIDE_WINDOW); ac_set_interrupt_level(&aca_config, AC_INT_LVL_MED); /* * Write configuration of analog comparator B channel 0, half of window * configuration. */ ac_write_config(&ACA, 0, &aca_config); /* Set the lower reference of the compare window. */ ac_set_negative_reference(&aca_config, AC_MUXNEG_BANDGAP_gc); /* * Write configuration of analog comparator B channel 1, other half of * window configuration. */ ac_write_config(&ACA, 1, &aca_config); /* Enable all the analog comparator channels. */ ac_enable(&ACA, 0); ac_enable(&ACA, 1); /* * Wait for analog comparator to stabilize (muxing, voltage scaler, * bandgap voltage, etc). */ mdelay(1); /* Check comparator status and initialize the LEDs. */ status = ac_get_status(&ACA, 0); example_ac_update_window_leds(status); /* * Read back analog comparator channel 0 configuration, to be used when * updating the window interrupt mode in the interrupt callback * function. */ ac_read_config(&ACA, 0, &aca_config); cpu_irq_enable(); for (;;) { /* Go to sleep, everything is handled by interrupts. */ sleepmgr_enter_sleep(); } }
/** * \internal * \brief Setup Function: AC window mode test. * * This function initializes the AC in window mode detection. * 0.25V and 0.75V from internal voltage scaler are used as lower * and upper limits of the window respectively. * * \param test Current test case. */ static void setup_ac_window_mode_test(const struct test_case *test) { enum status_code status = STATUS_ERR_IO; /* Structure for AC configuration */ struct ac_config config; struct ac_chan_config channel_config; struct ac_win_config window_config; /* Set the flag to false */ ac_init_success = false; ac_reset(&ac_inst); ac_get_config_defaults(&config); /* Initialize the AC */ status = ac_init(&ac_inst, AC, &config); /* Check for successful initialization */ test_assert_true(test, status == STATUS_OK, "AC initialization failed"); /* Configure the AC input pin */ struct system_pinmux_config ac0_pin_conf; system_pinmux_get_config_defaults(&ac0_pin_conf); ac0_pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT; ac0_pin_conf.mux_position = MUX_PA04B_AC_AIN0; system_pinmux_pin_set_config(PIN_PA04B_AC_AIN0, &ac0_pin_conf); /* Channel configuration */ status = STATUS_ERR_IO; ac_chan_get_config_defaults(&channel_config); channel_config.sample_mode = AC_CHAN_MODE_SINGLE_SHOT; channel_config.positive_input = AC_CHAN_POS_MUX_PIN0; channel_config.negative_input = AC_CHAN_NEG_MUX_SCALED_VCC; channel_config.vcc_scale_factor = AC_SCALER_0_25_VOLT; /* Set the channel configuration for CHAN1 - Lower limit*/ status = ac_chan_set_config(&ac_inst, AC_CHAN_CHANNEL_1, &channel_config); /* Check for successful initialization */ test_assert_true(test, status == STATUS_OK, "AC channel 1 initialization failed"); /* Set the channel configuration for CHAN0 - Upper limit*/ channel_config.vcc_scale_factor = AC_SCALER_0_75_VOLT; status = ac_chan_set_config(&ac_inst, AC_CHAN_CHANNEL_0, &channel_config); /* Check for successful initialization */ test_assert_true(test, status == STATUS_OK, "AC channel 0 initialization failed"); /* Window mode configuration */ status = STATUS_ERR_IO; ac_win_get_config_defaults(&window_config); status = ac_win_set_config(&ac_inst, AC_WIN_CHANNEL_0, &window_config); /* Check for successful initialization */ test_assert_true(test, status == STATUS_OK, "AC window mode initialization failed"); /* Enable the AC channels */ ac_chan_enable(&ac_inst, AC_CHAN_CHANNEL_0); ac_chan_enable(&ac_inst, AC_CHAN_CHANNEL_1); /* Enable window mode */ status = ac_win_enable(&ac_inst, AC_WIN_CHANNEL_0); /* Check for successful initialization */ test_assert_true(test, status == STATUS_OK, "AC window mode enable failed"); /* Enable AC module */ ac_enable(&ac_inst); if (status == STATUS_OK) { ac_init_success = true; } }