From 5dea9413a88371a373fb4e0f9da509e0966af2d4 Mon Sep 17 00:00:00 2001 From: Chen Jichang Date: Wed, 3 Jul 2024 16:24:05 +0800 Subject: [PATCH] feat(gptimer): add wiegand interface example Closes https://github.com/espressif/esp-idf/issues/13892 --- examples/peripherals/.build-test-rules.yml | 6 +- .../timer_group/legacy_driver/README.md | 50 ------ .../legacy_driver/main/CMakeLists.txt | 2 - .../main/timer_group_example_main.c | 130 -------------- .../legacy_driver/pytest_timer_group.py | 21 --- .../legacy_driver/sdkconfig.defaults | 7 - .../CMakeLists.txt | 4 +- .../timer_group/wiegand_interface/README.md | 55 ++++++ .../wiegand_interface/img/image.png | Bin 0 -> 10695 bytes .../wiegand_interface/main/CMakeLists.txt | 3 + .../main/wiegand_example_main.c | 35 ++++ .../wiegand_interface/main/wiegand_io.c | 166 ++++++++++++++++++ .../wiegand_interface/main/wiegand_io.h | 59 +++++++ .../wiegand_interface/pytest_wiegand.py | 18 ++ .../wiegand_interface/sdkconfig.defaults | 3 + 15 files changed, 345 insertions(+), 214 deletions(-) delete mode 100644 examples/peripherals/timer_group/legacy_driver/README.md delete mode 100644 examples/peripherals/timer_group/legacy_driver/main/CMakeLists.txt delete mode 100644 examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c delete mode 100644 examples/peripherals/timer_group/legacy_driver/pytest_timer_group.py delete mode 100644 examples/peripherals/timer_group/legacy_driver/sdkconfig.defaults rename examples/peripherals/timer_group/{legacy_driver => wiegand_interface}/CMakeLists.txt (81%) create mode 100644 examples/peripherals/timer_group/wiegand_interface/README.md create mode 100644 examples/peripherals/timer_group/wiegand_interface/img/image.png create mode 100644 examples/peripherals/timer_group/wiegand_interface/main/CMakeLists.txt create mode 100644 examples/peripherals/timer_group/wiegand_interface/main/wiegand_example_main.c create mode 100644 examples/peripherals/timer_group/wiegand_interface/main/wiegand_io.c create mode 100644 examples/peripherals/timer_group/wiegand_interface/main/wiegand_io.h create mode 100644 examples/peripherals/timer_group/wiegand_interface/pytest_wiegand.py create mode 100644 examples/peripherals/timer_group/wiegand_interface/sdkconfig.defaults diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 1b2c076edb..81b5f992b8 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -396,11 +396,11 @@ examples/peripherals/timer_group/gptimer_capture_hc_sr04: depends_components: - esp_driver_gptimer -examples/peripherals/timer_group/legacy_driver: +examples/peripherals/timer_group/wiegand_interface: disable: - - if: SOC_GPTIMER_SUPPORTED != 1 + - if: SOC_TIMER_GROUP_TOTAL_TIMERS < 2 depends_components: - - driver # legacy driver is still located in the "driver" component + - esp_driver_gptimer examples/peripherals/touch_sensor: disable: diff --git a/examples/peripherals/timer_group/legacy_driver/README.md b/examples/peripherals/timer_group/legacy_driver/README.md deleted file mode 100644 index fb7f50aab6..0000000000 --- a/examples/peripherals/timer_group/legacy_driver/README.md +++ /dev/null @@ -1,50 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | - -# Example: General Purpose Timer - -This example uses the **legacy timer group driver** to generate timer interrupts with and without auto-reload. But we highly recommend you to use the new [GPTimer Driver](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/gptimer.html) in your new projects. - -## How to Use Example - -### Hardware Required - -* A development board with ESP SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) -* A USB cable for Power supply and programming - -### Build and Flash - -Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the [ESP-IDF Getting Started Guide](https://idf.espressif.com/) for all the steps to configure and use the ESP-IDF to build projects. - -## Example Output - -```text -I (0) cpu_start: Starting scheduler on APP CPU. -I (325) example: Init timer with auto-reload -I (835) example: Timer auto reloaded, count value in ISR: 3 -I (1335) example: Timer auto reloaded, count value in ISR: 3 -I (1835) example: Timer auto reloaded, count value in ISR: 3 -I (2335) example: Timer auto reloaded, count value in ISR: 3 -I (2335) example: Init timer without auto-reload -I (2835) example: Timer alarmed at 500003 -I (3335) example: Timer alarmed at 1000003 -I (3835) example: Timer alarmed at 1500003 -I (4335) example: Timer alarmed at 2000003 -``` - -## Functionality Overview - -* Configure one timer with auto-reload enabled, alarm period set to 0.5s -* On reaching the interval value the timer will generate an alarm -* The timer will reload with initial count value on alarm, by hardware -* Reconfigure the timer with auto-reload disabled, initial alarm value set to 0.5s -* The timer keeps incrementing and in the alarm callback, the software reconfigures its alarm value by increasing 0.5s -* The main task will print the count value that captured in the alarm callback - -## Troubleshooting - -For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/timer_group/legacy_driver/main/CMakeLists.txt b/examples/peripherals/timer_group/legacy_driver/main/CMakeLists.txt deleted file mode 100644 index 24d6c81190..0000000000 --- a/examples/peripherals/timer_group/legacy_driver/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "timer_group_example_main.c" - INCLUDE_DIRS ".") diff --git a/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c b/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c deleted file mode 100644 index 90090deb71..0000000000 --- a/examples/peripherals/timer_group/legacy_driver/main/timer_group_example_main.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: CC0-1.0 - */ - -#include -#include "soc/soc.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "driver/timer.h" -#include "esp_clk_tree.h" -#include "esp_log.h" - -#define TIMER_RESOLUTION_HZ 1000000 // 1MHz resolution -#define TIMER_ALARM_PERIOD_S 0.5 // Alarm period 0.5s - -static const char *TAG = "example"; - -/** - * @brief A sample structure to pass events from the timer ISR to task - */ -typedef struct { - uint64_t timer_count_value; -} example_timer_event_t; - -/** - * @brief Timer user data, will be pass to timer alarm callback - */ -typedef struct { - QueueHandle_t user_queue; - int timer_group; - int timer_idx; - int alarm_value; - bool auto_reload; -} example_timer_user_data_t; - -static bool IRAM_ATTR timer_group_isr_callback(void *args) -{ - BaseType_t high_task_awoken = pdFALSE; - example_timer_user_data_t *user_data = (example_timer_user_data_t *) args; - // fetch current count value - uint64_t timer_count_value = timer_group_get_counter_value_in_isr(user_data->timer_group, user_data->timer_idx); - example_timer_event_t evt = { - .timer_count_value = timer_count_value, - }; - - // set new alarm value if necessary - if (!user_data->auto_reload) { - user_data->alarm_value += TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ; - timer_group_set_alarm_value_in_isr(user_data->timer_group, user_data->timer_idx, user_data->alarm_value); - } - - // Send the event data back to the main program task - xQueueSendFromISR(user_data->user_queue, &evt, &high_task_awoken); - - return high_task_awoken == pdTRUE; // return whether a task switch is needed -} - -static void example_tg_timer_init(example_timer_user_data_t *user_data) -{ - int group = user_data->timer_group; - int timer = user_data->timer_idx; - - uint32_t clk_src_hz = 0; - ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)TIMER_SRC_CLK_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_hz)); - timer_config_t config = { - .clk_src = TIMER_SRC_CLK_DEFAULT, - .divider = clk_src_hz / TIMER_RESOLUTION_HZ, - .counter_dir = TIMER_COUNT_UP, - .counter_en = TIMER_PAUSE, - .alarm_en = TIMER_ALARM_EN, - .auto_reload = user_data->auto_reload, - }; - ESP_ERROR_CHECK(timer_init(group, timer, &config)); - - // For the timer counter to a initial value - ESP_ERROR_CHECK(timer_set_counter_value(group, timer, 0)); - // Set alarm value and enable alarm interrupt - ESP_ERROR_CHECK(timer_set_alarm_value(group, timer, user_data->alarm_value)); - ESP_ERROR_CHECK(timer_enable_intr(group, timer)); - // Hook interrupt callback - ESP_ERROR_CHECK(timer_isr_callback_add(group, timer, timer_group_isr_callback, user_data, 0)); - // Start timer - ESP_ERROR_CHECK(timer_start(group, timer)); -} - -static void example_tg_timer_deinit(int group, int timer) -{ - ESP_ERROR_CHECK(timer_isr_callback_remove(group, timer)); - ESP_ERROR_CHECK(timer_deinit(group, timer)); -} - -void app_main(void) -{ - example_timer_user_data_t *user_data = calloc(1, sizeof(example_timer_user_data_t)); - assert(user_data); - user_data->user_queue = xQueueCreate(10, sizeof(example_timer_event_t)); - assert(user_data->user_queue); - user_data->timer_group = 0; - user_data->timer_idx = 0; - user_data->alarm_value = TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ; - - ESP_LOGI(TAG, "Init timer with auto-reload"); - user_data->auto_reload = true; - example_tg_timer_init(user_data); - - example_timer_event_t evt; - uint32_t test_count = 4; - while (test_count--) { - xQueueReceive(user_data->user_queue, &evt, portMAX_DELAY); - ESP_LOGI(TAG, "Timer auto reloaded, count value in ISR: %llu", evt.timer_count_value); - } - example_tg_timer_deinit(user_data->timer_group, user_data->timer_idx); - - ESP_LOGI(TAG, "Init timer without auto-reload"); - user_data->auto_reload = false; - example_tg_timer_init(user_data); - - test_count = 4; - while (test_count--) { - xQueueReceive(user_data->user_queue, &evt, portMAX_DELAY); - ESP_LOGI(TAG, "Timer alarmed at %llu", evt.timer_count_value); - } - example_tg_timer_deinit(user_data->timer_group, user_data->timer_idx); - - vQueueDelete(user_data->user_queue); - free(user_data); -} diff --git a/examples/peripherals/timer_group/legacy_driver/pytest_timer_group.py b/examples/peripherals/timer_group/legacy_driver/pytest_timer_group.py deleted file mode 100644 index 058638029d..0000000000 --- a/examples/peripherals/timer_group/legacy_driver/pytest_timer_group.py +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: CC0-1.0 - -import pytest -from pytest_embedded import Dut - - -@pytest.mark.supported_targets -@pytest.mark.generic -def test_timer_group_example(dut: Dut) -> None: - dut.expect(r'Init timer with auto-reload', timeout=5) - res = dut.expect(r'Timer auto reloaded, count value in ISR: (\d+)', timeout=5) - reloaded_count = res.group(1).decode('utf8') - assert 0 <= int(reloaded_count) < 10 - - alarm_increase_step = 500000 - dut.expect(r'Init timer without auto-reload') - for i in range(1, 5): - res = dut.expect(r'Timer alarmed at (\d+)', timeout=3) - alarm_count = res.group(1).decode('utf8') - assert (i * alarm_increase_step - 10) < int(alarm_count) < (i * alarm_increase_step + 10) diff --git a/examples/peripherals/timer_group/legacy_driver/sdkconfig.defaults b/examples/peripherals/timer_group/legacy_driver/sdkconfig.defaults deleted file mode 100644 index 03820fcd3c..0000000000 --- a/examples/peripherals/timer_group/legacy_driver/sdkconfig.defaults +++ /dev/null @@ -1,7 +0,0 @@ -# This file was generated using idf.py save-defconfig. It can be edited manually. -# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration -# -CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN=y - -# Disable nano printf, because we need to print the timer count in %llu format -CONFIG_NEWLIB_NANO_FORMAT=n diff --git a/examples/peripherals/timer_group/legacy_driver/CMakeLists.txt b/examples/peripherals/timer_group/wiegand_interface/CMakeLists.txt similarity index 81% rename from examples/peripherals/timer_group/legacy_driver/CMakeLists.txt rename to examples/peripherals/timer_group/wiegand_interface/CMakeLists.txt index 121745608a..b77b0be2ae 100644 --- a/examples/peripherals/timer_group/legacy_driver/CMakeLists.txt +++ b/examples/peripherals/timer_group/wiegand_interface/CMakeLists.txt @@ -2,5 +2,7 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) +set(COMPONENTS main) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(timer_group) +project(wiegand_interface) diff --git a/examples/peripherals/timer_group/wiegand_interface/README.md b/examples/peripherals/timer_group/wiegand_interface/README.md new file mode 100644 index 0000000000..11f0dbbb97 --- /dev/null +++ b/examples/peripherals/timer_group/wiegand_interface/README.md @@ -0,0 +1,55 @@ +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | + +# Wiegand Interface Example + +This example uses the **gptimer and gpio driver** to simulate Wiegand Interface. See the [Wiegand Interface](https://en.wikipedia.org/wiki/Wiegand_interface) +In this example, we use two timers (one in one-shot mode and another in periodic mode) to trigger the interrupt and change the output state of the gpio in the interrupt. + +### Note on timing requirements + +Due to the tight timing requirements of wiegand protocol, the gpio control function, timer control function and timer isr handle should be placed in IRAM. This circumvents the timing variations caused by cache misses/invalidation when executing a function placed in flash. + +Configure sdkconfig as follows: + +``` +CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y +CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM=y +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y + +``` + +## How to Use Example + +### Hardware Required + +* A development board with ESP SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) +* A USB cable for Power supply and programming + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [ESP-IDF Getting Started Guide](https://idf.espressif.com/) for all the steps to configure and use the ESP-IDF to build projects. + +## Example Output + +```text +I (0) cpu_start: Starting scheduler on APP CPU. +I (319) example: Configure wiegand interface +I (319) gpio: GPIO[2]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 +I (329) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 +I (339) example: send wiegand data +I (339) main_task: Returned from app_main() +``` + +The wiegand interface io will transfer data after the initialization. + +The wiegand data are as follow: + + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/peripherals/timer_group/wiegand_interface/img/image.png b/examples/peripherals/timer_group/wiegand_interface/img/image.png new file mode 100644 index 0000000000000000000000000000000000000000..23cbafe0e34796d5bba882b2a65dc6f21bf4c041 GIT binary patch literal 10695 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 y=W}q#K0bC#5xe&{e(fp55r0Sn=l|t2A`()C% +#include +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "wiegand_io.h" + +#define DATA_PIN0_GPIO GPIO_NUM_0 +#define DATA_PIN1_GPIO GPIO_NUM_2 + +static const char *TAG = "example"; +uint64_t wiegand_data = 0x5a5a5a5a; + +void app_main(void) +{ + wiegand_io_handle_t wiegand_io_handle = NULL; + wiegand_io_config_t wiegand_io_config = { + .data_pin0 = DATA_PIN0_GPIO, + .data_pin1 = DATA_PIN1_GPIO, + .pulse_width_us = 50, + .interval_width_us = 1000, + }; + + ESP_LOGI(TAG, "Configure wiegand interface"); + ESP_ERROR_CHECK(wiegand_new_io(&wiegand_io_config, &wiegand_io_handle)); + + ESP_LOGI(TAG, "send wiegand data"); + ESP_ERROR_CHECK(wiegand_io_send(wiegand_io_handle, &wiegand_data, 26)); +} diff --git a/examples/peripherals/timer_group/wiegand_interface/main/wiegand_io.c b/examples/peripherals/timer_group/wiegand_interface/main/wiegand_io.c new file mode 100644 index 0000000000..29b046bc46 --- /dev/null +++ b/examples/peripherals/timer_group/wiegand_interface/main/wiegand_io.c @@ -0,0 +1,166 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include "esp_check.h" +#include "esp_attr.h" +#include "esp_heap_caps.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "wiegand_io.h" + +static const char *TAG = "wiegand_io"; + +typedef struct wiegand_interface_t { + SemaphoreHandle_t sem; + gptimer_handle_t interval_timer; + gptimer_handle_t pulse_timer; + gpio_num_t data_pin0; + gpio_num_t data_pin1; + uint8_t pulse_width_us; + uint16_t interval_width_us; + uint64_t bit_mask; + uint64_t *current_data; +} wiegand_interface_t; + +static bool IRAM_ATTR interval_timer_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) +{ + wiegand_io_handle_t wiegand_io = (wiegand_io_handle_t)user_data; + if (wiegand_io->bit_mask == 1) { + gptimer_stop(timer); + } + + gptimer_set_raw_count(wiegand_io->pulse_timer, 0); + gptimer_start(wiegand_io->pulse_timer); + + if (*wiegand_io->current_data & wiegand_io->bit_mask) { + gpio_set_level(wiegand_io->data_pin1, 0); + } else { + gpio_set_level(wiegand_io->data_pin0, 0); + } + + return false; +} + +static bool IRAM_ATTR pulse_timer_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) +{ + BaseType_t task_woken = pdFALSE; + wiegand_io_handle_t wiegand_io = (wiegand_io_handle_t)user_data; + gpio_set_level(wiegand_io->data_pin0, 1); + gpio_set_level(wiegand_io->data_pin1, 1); + + gptimer_stop(timer); + + if (!(wiegand_io->bit_mask >>= 1)) { + xSemaphoreGiveFromISR(wiegand_io->sem, &task_woken); + } + + return task_woken == pdTRUE; +} + +static esp_err_t set_alarm_action(gptimer_handle_t timer, uint64_t count, bool reload) +{ + gptimer_alarm_config_t alarm_config = { + .reload_count = 0, + .alarm_count = count, + .flags.auto_reload_on_alarm = reload, + }; + ESP_RETURN_ON_ERROR(gptimer_set_alarm_action(timer, &alarm_config), TAG, "set alarm action failed!"); + + return ESP_OK; +} + +static esp_err_t setup_timer(gptimer_handle_t *timer, gptimer_alarm_cb_t alarm_cb, wiegand_io_handle_t wiegand_io, uint64_t count, bool reload) +{ + esp_err_t ret = ESP_OK; + gptimer_config_t timer_config = { + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .resolution_hz = 1000000, // 1 tick = 1us + }; + ESP_RETURN_ON_ERROR(gptimer_new_timer(&timer_config, timer), TAG, "add new timer failed!"); + + gptimer_event_callbacks_t cbs = { + .on_alarm = alarm_cb, + }; + ESP_GOTO_ON_ERROR(gptimer_register_event_callbacks(*timer, &cbs, wiegand_io), err, TAG, "register callbacks failed!"); + ESP_GOTO_ON_ERROR(set_alarm_action(*timer, count, reload), err, TAG, "set alarm action failed!"); + ESP_GOTO_ON_ERROR(gptimer_enable(*timer), err, TAG, "enable timer failed!"); + + return ESP_OK; + +err: + if (*timer) { + gptimer_del_timer(*timer); + } + return ret; +} + +esp_err_t wiegand_new_io(const wiegand_io_config_t *config, wiegand_io_handle_t *ret_handle) +{ + esp_err_t ret = ESP_OK; + wiegand_interface_t *wiegand_io = NULL; + ESP_RETURN_ON_FALSE(config && ret_handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + + wiegand_io = heap_caps_calloc(1, sizeof(wiegand_interface_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + ESP_RETURN_ON_FALSE(wiegand_io, ESP_ERR_NO_MEM, TAG, "no mem for wiegand_io"); + + wiegand_io->sem = xSemaphoreCreateBinaryWithCaps(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + wiegand_io->data_pin0 = config->data_pin0; + wiegand_io->data_pin1 = config->data_pin1; + wiegand_io->pulse_width_us = config->pulse_width_us; + wiegand_io->interval_width_us = config->interval_width_us; + + gpio_config_t io_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = (1ULL << wiegand_io->data_pin0) | (1ULL << wiegand_io->data_pin1), + }; + ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "gpio config failed!"); + + // data pins are high by default + gpio_set_level(wiegand_io->data_pin0, 1); + gpio_set_level(wiegand_io->data_pin1, 1); + + // Setup the pulse timer + ESP_GOTO_ON_ERROR(setup_timer(&wiegand_io->pulse_timer, pulse_timer_cb, wiegand_io, wiegand_io->pulse_width_us, false), err, TAG, "setup pulse timer failed!"); + // Setup the interval timer + ESP_GOTO_ON_ERROR(setup_timer(&wiegand_io->interval_timer, interval_timer_cb, wiegand_io, wiegand_io->interval_width_us, true), err, TAG, "setup interval timer failed!"); + + // return handle + *ret_handle = wiegand_io; + xSemaphoreGive(wiegand_io->sem); + + return ESP_OK; + +err: + if (wiegand_io->pulse_timer) { + gptimer_disable(wiegand_io->pulse_timer); + gptimer_del_timer(wiegand_io->pulse_timer); + } + if (wiegand_io->interval_timer) { + gptimer_disable(wiegand_io->interval_timer); + gptimer_del_timer(wiegand_io->interval_timer); + } + if (wiegand_io) { + free(wiegand_io); + } + return ret; + +} + +esp_err_t wiegand_io_send(wiegand_io_handle_t wiegand_io, void *data, uint8_t num_of_bits) +{ + ESP_RETURN_ON_FALSE(wiegand_io && num_of_bits && data, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(num_of_bits > 0 && num_of_bits <= 64, ESP_ERR_INVALID_ARG, TAG, "bits is out of range [1,64]"); + + xSemaphoreTake(wiegand_io->sem, portMAX_DELAY); + wiegand_io->current_data = (uint64_t *)data; + wiegand_io->bit_mask = 1ULL << (num_of_bits - 1); + + ESP_RETURN_ON_ERROR(gptimer_set_raw_count(wiegand_io->interval_timer, 0), TAG, "set timer raw count failed!"); + ESP_RETURN_ON_ERROR(gptimer_start(wiegand_io->interval_timer), TAG, "start timer failed!"); + + return ESP_OK; +} diff --git a/examples/peripherals/timer_group/wiegand_interface/main/wiegand_io.h b/examples/peripherals/timer_group/wiegand_interface/main/wiegand_io.h new file mode 100644 index 0000000000..d7e8da06f8 --- /dev/null +++ b/examples/peripherals/timer_group/wiegand_interface/main/wiegand_io.h @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#pragma once + +#include +#include +#include "driver/gpio.h" +#include "driver/gptimer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Wiegand interface configuration + */ +typedef struct { + gpio_num_t data_pin0; /*!< Pin of Data0 */ + gpio_num_t data_pin1; /*!< Pin of Data1 */ + uint8_t pulse_width_us; /*!< Negative pulse width, in microseconds */ + uint16_t interval_width_us; /*!< Wiegand data interval, a.k.a. period, in microseconds */ +} wiegand_io_config_t; + +/** + * @brief Type of Wiegand interface handle + */ +typedef struct wiegand_interface_t *wiegand_io_handle_t; + +/** + * @brief Create a new wiegand interface io, and return the handle + * + * @param[in] config Wiegand interface configuration + * @param[out] ret_handle Returned wiegand interface handle + * @return + * - ESP_ERR_INVALID_ARG for any invalid arguments + * - ESP_ERR_NO_MEM out of memory when creating wiegand interface + * - ESP_OK if creating wiegand interface successfully + */ +esp_err_t wiegand_new_io(const wiegand_io_config_t *config, wiegand_io_handle_t *ret_handle); + +/** + * @brief Send data via created wiegand interface io + * + * @param[in] wiegand_io Wiegand interface io handle + * @param[in] data Wiegand data + * @param[in] num_of_bits The bits number of wiegand data + * @return + * - ESP_ERR_INVALID_STATE if previous data has not sent completely + * - ESP_OK if start sending data successfully + */ +esp_err_t wiegand_io_send(wiegand_io_handle_t wiegand_io, void *data, uint8_t num_of_bits); + +#ifdef __cplusplus +} +#endif diff --git a/examples/peripherals/timer_group/wiegand_interface/pytest_wiegand.py b/examples/peripherals/timer_group/wiegand_interface/pytest_wiegand.py new file mode 100644 index 0000000000..2035f56782 --- /dev/null +++ b/examples/peripherals/timer_group/wiegand_interface/pytest_wiegand.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32 +@pytest.mark.esp32c3 +@pytest.mark.esp32c5 +@pytest.mark.esp32c6 +@pytest.mark.esp32h2 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32p4 +@pytest.mark.generic +def test_gptimer_wiegand(dut: Dut) -> None: + dut.expect_exact('example: Configure wiegand interface') + dut.expect_exact('example: send wiegand data') diff --git a/examples/peripherals/timer_group/wiegand_interface/sdkconfig.defaults b/examples/peripherals/timer_group/wiegand_interface/sdkconfig.defaults new file mode 100644 index 0000000000..2177bc5993 --- /dev/null +++ b/examples/peripherals/timer_group/wiegand_interface/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y +CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM=y +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y