|
|
@@ -0,0 +1,140 @@
|
|
|
+/*
|
|
|
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
|
|
+ *
|
|
|
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
|
|
|
+ */
|
|
|
+
|
|
|
+#include <stdio.h>
|
|
|
+#include "freertos/FreeRTOS.h"
|
|
|
+#include "freertos/task.h"
|
|
|
+#include "driver/gpio.h"
|
|
|
+#include "driver/ana_cmpr.h"
|
|
|
+#include "esp_log.h"
|
|
|
+
|
|
|
+#define EXAMPLE_ANA_CMPR_UNIT ANA_CMPR_UNIT_0 // Analog Comparator unit
|
|
|
+#define EXAMPLE_WAIT_TIME_PROP (0.1) // The wait time proportion in one relative signal period
|
|
|
+#define EXAMPLE_WAITE_TIME_US(freq_approx) (1000000.0 * EXAMPLE_WAIT_TIME_PROP / (freq_approx))
|
|
|
+
|
|
|
+#define EXAMPLE_MONITOR_GPIO_NUM (0) // The gpio to monitor the on cross callback
|
|
|
+
|
|
|
+static const char *TAG = "ana_cmpr_example";
|
|
|
+
|
|
|
+static bool IRAM_ATTR example_ana_cmpr_on_cross_callback(ana_cmpr_handle_t cmpr,
|
|
|
+ const ana_cmpr_cross_event_data_t *edata,
|
|
|
+ void *user_ctx)
|
|
|
+{
|
|
|
+#if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR
|
|
|
+ static ana_cmpr_intl_ref_config_t ref_cfg = {
|
|
|
+ .ref_volt = ANA_CMPR_REF_VOLT_70_PCT_VDD,
|
|
|
+ };
|
|
|
+ bool is_70p = ref_cfg.ref_volt == ANA_CMPR_REF_VOLT_70_PCT_VDD;
|
|
|
+ /* Toggle the GPIO, monitor the gpio on a oscilloscope. */
|
|
|
+ gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, is_70p);
|
|
|
+ /* Set the internal reference voltage to 30% VDD and 70 %VDD alternately */
|
|
|
+ ana_cmpr_set_intl_reference(cmpr, &ref_cfg);
|
|
|
+ ref_cfg.ref_volt = is_70p ? ANA_CMPR_REF_VOLT_30_PCT_VDD : ANA_CMPR_REF_VOLT_70_PCT_VDD;
|
|
|
+#else
|
|
|
+ static int lvl = 0;
|
|
|
+ /* Toggle the GPIO, monitor the gpio on a oscilloscope. */
|
|
|
+ gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, lvl);
|
|
|
+ lvl = !lvl;
|
|
|
+#endif
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+void example_init_analog_comparator(void)
|
|
|
+{
|
|
|
+ /* Step 0: Show the source channel and reference channel GPIO */
|
|
|
+ int src_gpio = -1;
|
|
|
+ int ext_ref_gpio = -1;
|
|
|
+ ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_SOURCE_CHAN, &src_gpio));
|
|
|
+ ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_EXT_REF_CHAN, &ext_ref_gpio));
|
|
|
+ ESP_LOGI(TAG, "Analog Comparator source gpio %d, external reference gpio %d", src_gpio, ext_ref_gpio);
|
|
|
+
|
|
|
+ ana_cmpr_handle_t cmpr = NULL;
|
|
|
+
|
|
|
+#if CONFIG_EXAMPLE_INTERNAL_REF
|
|
|
+ /* Step 1: Allocate the new analog comparator unit */
|
|
|
+ ana_cmpr_config_t config = {
|
|
|
+ .unit = EXAMPLE_ANA_CMPR_UNIT,
|
|
|
+ .clk_src = ANA_CMPR_CLK_SRC_DEFAULT,
|
|
|
+ .ref_src = ANA_CMPR_REF_SRC_INTERNAL,
|
|
|
+ .intr_type = ANA_CMPR_INTR_ANY_CROSS,
|
|
|
+ };
|
|
|
+ ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
|
|
|
+ ESP_LOGI(TAG, "Allocate Analog Comparator with internal reference");
|
|
|
+
|
|
|
+ /* Step 1.1: As we are using the internal reference source, we need to configure the internal reference */
|
|
|
+ ana_cmpr_intl_ref_config_t ref_cfg = {
|
|
|
+#if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR
|
|
|
+ /* Set the initial internal reference voltage to 70% VDD, it will be updated in the callback every time the interrupt triggered */
|
|
|
+ .ref_volt = ANA_CMPR_REF_VOLT_70_PCT_VDD
|
|
|
+#else
|
|
|
+ .ref_volt = ANA_CMPR_REF_VOLT_50_PCT_VDD,
|
|
|
+#endif
|
|
|
+ };
|
|
|
+ ESP_ERROR_CHECK(ana_cmpr_set_intl_reference(cmpr, &ref_cfg));
|
|
|
+#else
|
|
|
+ /* Step 1: Allocate the new analog comparator unit */
|
|
|
+ ana_cmpr_config_t config = {
|
|
|
+ .unit = EXAMPLE_ANA_CMPR_UNIT,
|
|
|
+ .clk_src = ANA_CMPR_CLK_SRC_DEFAULT,
|
|
|
+ .ref_src = ANA_CMPR_REF_SRC_EXTERNAL,
|
|
|
+ .intr_type = ANA_CMPR_INTR_ANY_CROSS,
|
|
|
+ };
|
|
|
+ ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
|
|
|
+ ESP_LOGI(TAG, "Allocate Analog Comparator with internal reference");
|
|
|
+#endif
|
|
|
+
|
|
|
+ /* Step 2: (Optional) Set the debounce configuration
|
|
|
+ * It's an optional configuration, if the wait time is set in debounce configuration,
|
|
|
+ * the cross interrupt will be disabled temporary after it is triggered, and it will be enabled
|
|
|
+ * automatically enabled after `wait_us`, so that the duplicate interrupts
|
|
|
+ * can be suppressed while the source signal crossing the reference signal. */
|
|
|
+ ana_cmpr_debounce_config_t dbc_cfg = {
|
|
|
+ /* Normally the `wait_us` is related to how fast the source signal or reference signal changes
|
|
|
+ * comparing to another one. This example adopts an approximate frequency as the relative signal
|
|
|
+ * frequency, and set the default wait time to EXAMPLE_WAIT_TIME_PROP of the relative signal period.
|
|
|
+ * We need to estimate an appropriate `freq_approx` and EXAMPLE_WAIT_TIME_PROP
|
|
|
+ * to make sure the interrupt neither triggers duplicate interrupts, nor misses the next crossing interrupt.
|
|
|
+ * Here we take 1 KHz for example */
|
|
|
+ .wait_us = EXAMPLE_WAITE_TIME_US(1000),
|
|
|
+ };
|
|
|
+ ESP_ERROR_CHECK(ana_cmpr_set_debounce(cmpr, &dbc_cfg));
|
|
|
+
|
|
|
+ /* Step 3: Register the event callbacks */
|
|
|
+ ana_cmpr_event_callbacks_t cbs = {
|
|
|
+ .on_cross = example_ana_cmpr_on_cross_callback,
|
|
|
+ };
|
|
|
+ ESP_ERROR_CHECK(ana_cmpr_register_event_callbacks(cmpr, &cbs, NULL));
|
|
|
+
|
|
|
+ /* Step 4: Enable the analog comparator unit */
|
|
|
+ ESP_ERROR_CHECK(ana_cmpr_enable(cmpr));
|
|
|
+
|
|
|
+#if CONFIG_EXAMPLE_INTERNAL_REF
|
|
|
+ ESP_LOGI(TAG, "Analog comparator enabled, reference voltage: %d%% * VDD", (int)ref_cfg.ref_volt * 10);
|
|
|
+#else
|
|
|
+ ESP_LOGI(TAG, "Analog comparator enabled, external reference selected");
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+void example_init_monitor_gpio(void)
|
|
|
+{
|
|
|
+ gpio_config_t io_conf = {
|
|
|
+ .intr_type = GPIO_INTR_DISABLE,
|
|
|
+ .mode = GPIO_MODE_OUTPUT,
|
|
|
+ .pin_bit_mask = (1ULL << EXAMPLE_MONITOR_GPIO_NUM),
|
|
|
+ .pull_down_en = false,
|
|
|
+ .pull_up_en = false,
|
|
|
+ };
|
|
|
+ gpio_config(&io_conf);
|
|
|
+ gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, 0);
|
|
|
+}
|
|
|
+
|
|
|
+void app_main(void)
|
|
|
+{
|
|
|
+ /* Initialize GPIO to monitor the comparator interrupt */
|
|
|
+ example_init_monitor_gpio();
|
|
|
+ /* Initialize Analog Comparator */
|
|
|
+ example_init_analog_comparator();
|
|
|
+}
|