From 3fbca9454301c321cfd685d538cb6a53d828ff20 Mon Sep 17 00:00:00 2001 From: Liu Zhongwei Date: Thu, 2 Nov 2023 16:43:30 +0800 Subject: [PATCH] update more --- CHANGELOG.md | 39 +----- README.md | 27 ++-- examples/TestFunctions/TestFunctions.ino | 39 +++--- library.properties | 4 +- src/ESP_Knob.cpp | 156 +++++++++++++---------- src/ESP_Knob.h | 133 ++++++++++--------- test_apps/main/CMakeLists.txt | 4 +- test_apps/main/knob_test.c | 150 ---------------------- test_apps/main/test_ESP_Knob.cpp | 109 ++++++++++++++++ test_apps/sdkconfig.defaults | 1 + 10 files changed, 303 insertions(+), 359 deletions(-) delete mode 100644 test_apps/main/knob_test.c create mode 100644 test_apps/main/test_ESP_Knob.cpp create mode 100644 test_apps/sdkconfig.defaults diff --git a/CHANGELOG.md b/CHANGELOG.md index e578667..e8a04c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,41 +1,8 @@ # ChangeLog -## v0.1.3 - 2023-6-2 +## v0.0.1 - 2023-11-2 ### Enhancements: -* Add power on knob position detection to avoid logical inversion caused by knob position -* Change test to test_apps project - -## v0.1.2 - 2023-3-9 - -### Enhancements: - -* Use cu_pkg_define_version to define the version of this component. - -## v0.1.1 - 2023-1-18 - -### Bug Fixes: - -* Knob: - * Fix callback return usr_data root pointer, the usr_data of the relevant callback will now be returned. - -## v0.1.0 - 2023-1-5 - -### Enhancements: - -* Initial version - -* The following types of events are supported - -| EVENT | 描述 | -| ---------- | -------------------------------------- | -| KNOB_LEFT | EVENT: Rotate to the left | -| KNOB_RIGHT | EVENT: Rotate to the right | -| KNOB_H_LIM | EVENT: Count reaches maximum limit | -| KNOB_L_LIM | EVENT: Count reaches the minimum limit | -| KNOB_ZERO | EVENT: Count back to 0 | - -* Support for defining multiple knobs - -* Support binding callback functions for each event and adding user-data \ No newline at end of file +* Support for all ESP SoCs. +* Support multiple events, including `left`, `right`, `high limit`, `low limit`, and `back to zero`. diff --git a/README.md b/README.md index 1788fe4..9281f9c 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,15 @@ [![Arduino Lint](https://github.com/esp-arduino-libs/ESP32_Knob/actions/workflows/arduino_lint.yml/badge.svg)](https://github.com/esp-arduino-libs/ESP32_Knob/actions/workflows/arduino_lint.yml) [![pre-commit](https://github.com/esp-arduino-libs/ESP32_Knob/actions/workflows/pre-commit.yml/badge.svg)](https://github.com/esp-arduino-libs/ESP32_Knob/actions/workflows/pre-commit.yml) [![Build Test Apps](https://github.com/esp-arduino-libs/ESP32_Knob/actions/workflows/build_test.yml/badge.svg)](https://github.com/esp-arduino-libs/ESP32_Knob/actions/workflows/build_test.yml) +# ESP32_Knob -## Component Knob +ESP32_Knob is an Arduino library designed for driving encoders (such as EC11) using ESP SoCs. This library has implemented the quadrature decoding function similar to the ESP PCNT peripheral through software. It is useful for chips that do not have this peripheral, such as ESP32-C2 and ESP32-C3. -`Knob` is the component that provides the software PCNT, it can be used on chips(esp32c2, esp32c3) that do not have PCNT hardware capabilities. By using this component, you can quickly use a physical encoder, such as the EC11 encoder. +ESP32_Knob encapsulates the component from the [Espressif Components Registry](https://components.espressif.com/). It is developed based on [arduino-esp32](https://github.com/espressif/arduino-esp32) and can be easily downloaded and integrated into the Arduino IDE. -Features: +## Features -1. Support multiple knobs -2. Support each event can register its own callback -3. Support setting the upper and lower count limits - -List of supported events: - - * Knob left - * Knob right - * Knob high limit - * Knob low limit - * Knob back to zero +* Support for all ESP SoCs. +* Support multiple events, including `left`, `right`, `high limit`, `low limit`, and `back to zero`. ## Supported Drivers @@ -58,11 +50,8 @@ static void knob_left_cb(void *arg, void *data) knob->begin(); knob->registerEvent(KNOB_LEFT, knob_left_cb, NULL); -// Release the ESP_IOExpander object +// Release the ESP_Knob object delete knob; ``` -`Note`: This component is only suitable for decoding low-speed rotary encoders such as EC11, and does not guarantee the complete correctness of the pulse count. For high-speed and accurate calculations, please use hardware [PCNT](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/peripherals/pcnt.html?highlight=pcnt) - -* | Hardware PCNT Supported Targets | ESP32 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | - | ------------------------------- | ----- | -------- | -------- | -------- | -------- | \ No newline at end of file +**Note**: This component is only suitable for decoding low-speed rotary encoders such as EC11, and does not guarantee the complete correctness of the pulse count. For high-speed and accurate calculations, please use hardware [PCNT](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html?highlight=pcnt) diff --git a/examples/TestFunctions/TestFunctions.ino b/examples/TestFunctions/TestFunctions.ino index 72f31a7..f8719fa 100644 --- a/examples/TestFunctions/TestFunctions.ino +++ b/examples/TestFunctions/TestFunctions.ino @@ -1,46 +1,49 @@ #include #include -#define GPIO_KNOB_A 1 -#define GPIO_KNOB_B 2 +#define GPIO_NUM_KNOB_PIN_A 1 +#define GPIO_NUM_KNOB_PIN_B 2 -ESP_Knob *knob = new ESP_Knob(GPIO_KNOB_A, GPIO_KNOB_B); +ESP_Knob *knob; -static void knob_left_cb(void *arg, void *data) +void onKnobLeftEventCallback(int count, void *usr_data) { - Serial.printf("KNOB_LEFT Count is %d\n", knob->getCountValue()); + Serial.printf("Detect left event, count is %d\n", count); } -static void knob_right_cb(void *arg, void *data) +void onKnobRightEventCallback(int count, void *usr_data) { - Serial.printf("KNOB_RIGHT Count is %d\n", knob->getCountValue()); + Serial.printf("Detect right event, count is %d\n", count); } -static void knob_h_lim_cb(void *arg, void *data) +void onKnobHighLimitEventCallback(int count, void *usr_data) { - Serial.println("KNOB_H_LIM"); + Serial.printf("Detect high limit event, count is %d\n", count); } -static void knob_l_lim_cb(void *arg, void *data) +void onKnobLowLimitEventCallback(int count, void *usr_data) { - Serial.println("KNOB_L_LIM"); + Serial.printf("Detect low limit event, count is %d\n", count); } -static void knob_zero_cb(void *arg, void *data) +void onKnobZeroEventCallback(int count, void *usr_data) { - Serial.println("KNOB_ZERO"); + Serial.printf("Detect zero event, count is %d\n", count); } void setup() { Serial.begin(115200); Serial.println("ESP_Knob example"); + knob = new ESP_Knob(GPIO_NUM_KNOB_PIN_A, GPIO_NUM_KNOB_PIN_B); + + // knob->invertDirection(); knob->begin(); - knob->registerEvent(KNOB_LEFT, knob_left_cb, NULL); - knob->registerEvent(KNOB_RIGHT, knob_right_cb,NULL); - knob->registerEvent(KNOB_H_LIM, knob_h_lim_cb, NULL); - knob->registerEvent(KNOB_L_LIM, knob_l_lim_cb, NULL); - knob->registerEvent(KNOB_ZERO, knob_zero_cb, NULL); + knob->attachLeftEventCallback(onKnobLeftEventCallback); + knob->attachRightEventCallback(onKnobRightEventCallback); + knob->attachHighLimitEventCallback(onKnobHighLimitEventCallback); + knob->attachLowLimitEventCallback(onKnobLowLimitEventCallback); + knob->attachZeroEventCallback(onKnobZeroEventCallback); } void loop() { diff --git a/library.properties b/library.properties index 14e74ec..4dfbe8d 100644 --- a/library.properties +++ b/library.properties @@ -1,8 +1,8 @@ name=ESP32_Knob version=0.0.1 author=espressif -maintainer=espressif -sentence=ESP32_Knob is a library designed for driving encoders using ESP32 SoCs +maintainer=lijunru-hub +sentence=ESP32_Knob is a library designed for driving encoders using ESP SoCs paragraph=Currently support multiple encoders, such as the EC11. category=Other architectures=esp32 diff --git a/src/ESP_Knob.cpp b/src/ESP_Knob.cpp index d075e21..6e13d57 100644 --- a/src/ESP_Knob.cpp +++ b/src/ESP_Knob.cpp @@ -12,156 +12,174 @@ static const char *TAG = "ESP_Knob"; ESP_Knob::ESP_Knob(int gpio_encoder_a, int gpio_encoder_b): - knob_handle(NULL), - default_direction(0), - gpio_encoder_a(gpio_encoder_a), - gpio_encoder_b(gpio_encoder_b) + _knob_handle(NULL), + _direction(0), + _gpio_encoder_a(gpio_encoder_a), + _gpio_encoder_b(gpio_encoder_b), + _event_data({this, NULL}) { } -ESP_Knob::ESP_Knob(int gpio_encoder_a, int gpio_encoder_b, int default_direction): - knob_handle(NULL), - default_direction(default_direction), - gpio_encoder_a(gpio_encoder_a), - gpio_encoder_b(gpio_encoder_b) +ESP_Knob::~ESP_Knob() { + if (_knob_handle != NULL) { + iot_knob_delete(_knob_handle); + } } -ESP_Knob::~ESP_Knob() +void ESP_Knob::invertDirection(void) { - if (knob_handle != NULL) { - iot_knob_delete(knob_handle); - } + _direction = !_direction; } void ESP_Knob::begin() { const knob_config_t knob_cfg = { - .default_direction = (uint8_t)default_direction, - .gpio_encoder_a = (uint8_t)gpio_encoder_a, - .gpio_encoder_b = (uint8_t)gpio_encoder_b, + .default_direction = (uint8_t)_direction, + .gpio_encoder_a = (uint8_t)_gpio_encoder_a, + .gpio_encoder_b = (uint8_t)_gpio_encoder_b, }; - knob_handle = iot_knob_create(&knob_cfg); - if (knob_handle == NULL) { + _knob_handle = iot_knob_create(&knob_cfg); + if (_knob_handle == NULL) { ESP_LOGE(TAG, "Error create knob"); } } void ESP_Knob::del() { - if (knob_handle != NULL) { - iot_knob_delete(knob_handle); - knob_handle = NULL; + if (_knob_handle != NULL) { + iot_knob_delete(_knob_handle); + _knob_handle = NULL; } } -void ESP_Knob::registerLeftCb(knob_cb_t cb, void *usr_data) +knob_event_t ESP_Knob::getEvent() +{ + return iot_knob_get_event(_knob_handle); +} + +int ESP_Knob::getCountValue() +{ + return iot_knob_get_count_value(_knob_handle); +} + +void ESP_Knob::clearCountValue() +{ + iot_knob_clear_count_value(_knob_handle); +} + +void ESP_Knob::setEventUserDate(void *usr_data) +{ + _event_data.usr_data = usr_data; +} + +void ESP_Knob::attachLeftEventCallback(std::function callback) { - esp_err_t err = iot_knob_register_cb(knob_handle, KNOB_LEFT, cb, usr_data); + esp_err_t err = iot_knob_register_cb(_knob_handle, KNOB_LEFT, onEventCallback, &_event_data); if (err != ESP_OK) { ESP_LOGE(TAG, "Error register knob left callback"); } + _left_event_cb = callback; } -void ESP_Knob::unregisterLeftCb() +void ESP_Knob::detachLeftEventCallback() { - esp_err_t err = iot_knob_unregister_cb(knob_handle, KNOB_LEFT); + esp_err_t err = iot_knob_unregister_cb(_knob_handle, KNOB_LEFT); if (err != ESP_OK) { ESP_LOGE(TAG, "Error unregister knob left callback"); } } -void ESP_Knob::registerRightCb(knob_cb_t cb, void *usr_data) +void ESP_Knob::attachRightEventCallback(std::function callback) { - esp_err_t err = iot_knob_register_cb(knob_handle, KNOB_RIGHT, cb, usr_data); + esp_err_t err = iot_knob_register_cb(_knob_handle, KNOB_RIGHT, onEventCallback, &_event_data); if (err != ESP_OK) { ESP_LOGE(TAG, "Error register knob right callback"); } + _right_event_cb = callback; } -void ESP_Knob::unregisterRightCb() +void ESP_Knob::detachRightEventCallback() { - esp_err_t err = iot_knob_unregister_cb(knob_handle, KNOB_RIGHT); + esp_err_t err = iot_knob_unregister_cb(_knob_handle, KNOB_RIGHT); if (err != ESP_OK) { ESP_LOGE(TAG, "Error unregister knob right callback"); } } -void ESP_Knob::registerHighLimitCb(knob_cb_t cb, void *usr_data) +void ESP_Knob::attachHighLimitEventCallback(std::function callback) { - esp_err_t err = iot_knob_register_cb(knob_handle, KNOB_H_LIM, cb, usr_data); + esp_err_t err = iot_knob_register_cb(_knob_handle, KNOB_H_LIM, onEventCallback, &_event_data); if (err != ESP_OK) { ESP_LOGE(TAG, "Error register knob high limit callback"); } + _hight_limit_event_cb = callback; } -void ESP_Knob::unregisterHighLimitCb() +void ESP_Knob::detachHighLimitEventCallback() { - esp_err_t err = iot_knob_unregister_cb(knob_handle, KNOB_H_LIM); + esp_err_t err = iot_knob_unregister_cb(_knob_handle, KNOB_H_LIM); if (err != ESP_OK) { ESP_LOGE(TAG, "Error unregister knob high limit callback"); } } -void ESP_Knob::registerLowLimitCb(knob_cb_t cb, void *usr_data) +void ESP_Knob::attachLowLimitEventCallback(std::function callback) { - esp_err_t err = iot_knob_register_cb(knob_handle, KNOB_L_LIM, cb, usr_data); + esp_err_t err = iot_knob_register_cb(_knob_handle, KNOB_L_LIM, onEventCallback, &_event_data); if (err != ESP_OK) { ESP_LOGE(TAG, "Error register knob low limit callback"); } + _low_limit_event_cb = callback; } -void ESP_Knob::unregisterLowLimitCb() +void ESP_Knob::detachLowLimitEventCallback() { - esp_err_t err = iot_knob_unregister_cb(knob_handle, KNOB_L_LIM); + esp_err_t err = iot_knob_unregister_cb(_knob_handle, KNOB_L_LIM); if (err != ESP_OK) { ESP_LOGE(TAG, "Error unregister knob low limit callback"); } } -void ESP_Knob::registerZeroCb(knob_cb_t cb, void *usr_data) +void ESP_Knob::attachZeroEventCallback(std::function callback) { - esp_err_t err = iot_knob_register_cb(knob_handle, KNOB_ZERO, cb, usr_data); + esp_err_t err = iot_knob_register_cb(_knob_handle, KNOB_ZERO, onEventCallback, &_event_data); if (err != ESP_OK) { ESP_LOGE(TAG, "Error register knob zero callback"); } + _zero_event_cb = callback; } -void ESP_Knob::unregisterZeroCb() +void ESP_Knob::detachZeroEventCallback() { - esp_err_t err = iot_knob_unregister_cb(knob_handle, KNOB_ZERO); + esp_err_t err = iot_knob_unregister_cb(_knob_handle, KNOB_ZERO); if (err != ESP_OK) { ESP_LOGE(TAG, "Error unregister knob zero callback"); } } -void ESP_Knob::registerEvent(knob_event_t event, knob_cb_t cb, void *usr_data) -{ - esp_err_t err = iot_knob_register_cb(knob_handle, event, cb, usr_data); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error register knob callback"); - } -} - -void ESP_Knob::unregisterEvent(knob_event_t event) -{ - esp_err_t err = iot_knob_unregister_cb(knob_handle, event); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error unregister knob callback"); +void ESP_Knob::onEventCallback(void *arg, void *data) +{ + event_callback_data_t *event_data = (event_callback_data_t *)data; + ESP_Knob *knob = (ESP_Knob *)event_data->knob; + + switch (knob->getEvent()) { + case KNOB_LEFT: + knob->_left_event_cb(knob->getCountValue(), event_data->usr_data); + break; + case KNOB_RIGHT: + knob->_right_event_cb(knob->getCountValue(), event_data->usr_data); + break; + case KNOB_H_LIM: + knob->_hight_limit_event_cb(knob->getCountValue(), event_data->usr_data); + break; + case KNOB_L_LIM: + knob->_low_limit_event_cb(knob->getCountValue(), event_data->usr_data); + break; + case KNOB_ZERO: + knob->_zero_event_cb(knob->getCountValue(), event_data->usr_data); + break; + default: + break; } } - -knob_event_t ESP_Knob::getEvent() -{ - return iot_knob_get_event(knob_handle); -} - -int ESP_Knob::getCountValue() -{ - return iot_knob_get_count_value(knob_handle); -} - -void ESP_Knob::clearCountValue() -{ - iot_knob_clear_count_value(knob_handle); -} diff --git a/src/ESP_Knob.h b/src/ESP_Knob.h index aa50b74..e73efef 100644 --- a/src/ESP_Knob.h +++ b/src/ESP_Knob.h @@ -5,14 +5,19 @@ */ #pragma once -#include +#include #include "base/iot_knob.h" +typedef struct { + void *knob; + void *usr_data; +} event_callback_data_t; + class ESP_Knob { public: /** - * @brief Construct a new esp knob object + * @brief Construct a new knob object * * @param gpio_encoder_a Encoder Pin A * @param gpio_encoder_b Encoder Pin B @@ -20,141 +25,145 @@ class ESP_Knob { ESP_Knob(int gpio_encoder_a, int gpio_encoder_b); /** - * @brief Construct a new esp knob object + * @brief Destroy the knob object * - * @param gpio_encoder_a Encoder Pin A - * @param gpio_encoder_b Encoder Pin B - * @param default_direction 0:positive increase 1:negative increase */ - ESP_Knob(int gpio_encoder_a, int gpio_encoder_b, int default_direction); + ~ESP_Knob(void); /** - * @brief Destroy the esp knob object + * @brief Invert the roatae direction of the knob + * + * @note This function will change the direction of count value increment + * @note This function should be called before `begin()` * */ - ~ESP_Knob(void); + void invertDirection(void); /** - * @brief create a esp knob + * @brief create a knob * */ void begin(void); /** - * @brief Delete a esp knob + * @brief Delete a knob * */ void del(void); /** - * @brief Register the knob left callback function + * @brief Get knob event * - * @param cb Callback function - * @param usr_data user data + * @return knob_event_t Knob event */ - void registerLeftCb(knob_cb_t cb, void *usr_data); + knob_event_t getEvent(void); /** - * @brief Register the knob right callback function + * @brief Get knob count value * - * @param cb Callback function - * @param usr_data user data */ - void registerRightCb(knob_cb_t cb, void *usr_data); + int getCountValue(void); /** - * @brief Register the knob count reaches maximum limit callback function + * @brief Clear knob cout value to zero * - * @param cb Callback function - * @param usr_data user data */ - void registerHighLimitCb(knob_cb_t cb, void *usr_data); + void clearCountValue(void); /** - * @brief Register the knob count reaches minimum limit callback function + * @brief Set the user date for all events * - * @param cb Callback function - * @param usr_data user data + * @param usr_data */ - void registerLowLimitCb(knob_cb_t cb, void *usr_data); + void setEventUserDate(void *usr_data); /** - * @brief Register the knob count reaches zero callback function + * @brief Attach the knob left callback function * - * @param cb Callback function + * @param callback Callback function * @param usr_data user data */ - void registerZeroCb(knob_cb_t cb, void *usr_data); + void attachLeftEventCallback(std::function callback); /** - * @brief Register the knob event callback function + * @brief Detach the knob right callback function * - * @param event Knob event - * @param cb Callback function - * @param usr_data user data */ - void registerEvent(knob_event_t event, knob_cb_t cb, void *usr_data); + void detachLeftEventCallback(void); /** - * @brief Unregister the knob left callback function + * @brief Attach the knob right callback function * + * @param callback Callback function + * @param usr_data user data */ - void unregisterLeftCb(void); + void attachRightEventCallback(std::function callback); /** - * @brief Unregister the knob right callback function + * @brief Detach the knob right callback function * */ - void unregisterRightCb(void); + void detachRightEventCallback(void); /** - * @brief Unregister the knob count reaches maximum limit callback function + * @brief Attach the knob count reaches maximum limit callback function * - */ - void unregisterHighLimitCb(void); - - /** - * @brief Unregister the knob count reaches minimum limit callback function + * @note High limit is set to `1000` default * + * @param callback Callback function + * @param usr_data user data */ - void unregisterLowLimitCb(void); + void attachHighLimitEventCallback(std::function callback); /** - * @brief Unregister the knob count reaches zero callback function + * @brief Detach the knob count reaches maximum limit callback function * */ - void unregisterZeroCb(void); + void detachHighLimitEventCallback(void); /** - * @brief Unregister the knob event callback function + * @brief Attach the knob count reaches minimum limit callback function + * + * @note Low limit is set to `-1000` default * - * @param event Knob event + * @param callback Callback function + * @param usr_data user data */ - void unregisterEvent(knob_event_t event); + void attachLowLimitEventCallback(std::function callback); /** - * @brief Get esp knob event + * @brief Detach the knob count reaches minimum limit callback function * - * @return knob_event_t Knob event */ - knob_event_t getEvent(void); + void detachLowLimitEventCallback(void); /** - * @brief Get esp knob count value + * @brief Attach the knob count reaches zero callback function * + * @param callback Callback function + * @param usr_data user data */ - int getCountValue(void); + void attachZeroEventCallback(std::function callback); /** - * @brief Clear esp knob cout value to zero + * @brief Detach the knob count reaches zero callback function * */ - void clearCountValue(void); + void detachZeroEventCallback(void); private: - knob_handle_t knob_handle; /**< Knob handle */ + static void onEventCallback(void *arg, void *data); + + knob_handle_t _knob_handle; /**< Knob handle */ + + int _direction; /*!< Count increase direction */ + int _gpio_encoder_a; /*!< Encoder Pin A */ + int _gpio_encoder_b; /*!< Encoder Pin B */ - int default_direction; /*!< 0:positive increase 1:negative increase */ - int gpio_encoder_a; /*!< Encoder Pin A */ - int gpio_encoder_b; /*!< Encoder Pin B */ + event_callback_data_t _event_data; + std::function _left_event_cb; /*!< Callback function for knob left event */ + std::function _right_event_cb; /*!< Callback function for knob left event */ + std::function _hight_limit_event_cb; /*!< Callback function for knob left event */ + std::function _low_limit_event_cb; /*!< Callback function for knob left event */ + std::function _zero_event_cb; /*!< Callback function for knob left event */ }; diff --git a/test_apps/main/CMakeLists.txt b/test_apps/main/CMakeLists.txt index 7b2e7ea..1b7506b 100644 --- a/test_apps/main/CMakeLists.txt +++ b/test_apps/main/CMakeLists.txt @@ -1,3 +1 @@ -idf_component_register(SRC_DIRS "." - PRIV_INCLUDE_DIRS ".") - # PRIV_REQUIRES unity test_utils knob) \ No newline at end of file +idf_component_register(SRC_DIRS "." PRIV_INCLUDE_DIRS ".") \ No newline at end of file diff --git a/test_apps/main/knob_test.c b/test_apps/main/knob_test.c deleted file mode 100644 index e5b90fb..0000000 --- a/test_apps/main/knob_test.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/timers.h" -#include "esp_idf_version.h" -#include "esp_log.h" -#include "unity.h" -#include "base/iot_knob.h" -#include "sdkconfig.h" - -static const char *TAG = "KNOB TEST"; - -#define TEST_MEMORY_LEAK_THRESHOLD (-400) - -#define GPIO_KNOB_A 1 -#define GPIO_KNOB_B 2 -#define KNOB_NUM 3 - -static knob_handle_t s_knob[KNOB_NUM] = {0}; - -static int get_knob_index(knob_handle_t knob) -{ - for (size_t i = 0; i < KNOB_NUM; i++) { - if (knob == s_knob[i]) { - return i; - } - } - return -1; -} - -static void knob_left_cb(void *arg, void *data) -{ - TEST_ASSERT_EQUAL_HEX(KNOB_LEFT, iot_knob_get_event(arg)); - ESP_LOGI(TAG, "KNOB %d: KNOB_LEFT Count is %d usr_data: %s", get_knob_index((knob_handle_t)arg), iot_knob_get_count_value((knob_handle_t)arg), (char *)data); -} - -static void knob_right_cb(void *arg, void *data) -{ - TEST_ASSERT_EQUAL_HEX(KNOB_RIGHT, iot_knob_get_event(arg)); - ESP_LOGI(TAG, "KNOB%d: KNOB_RIGHT Count is %d usr_data: %s", get_knob_index((knob_handle_t)arg), iot_knob_get_count_value((knob_handle_t)arg), (char *)data); -} - -static void knob_h_lim_cb(void *arg, void *data) -{ - TEST_ASSERT_EQUAL_HEX(KNOB_H_LIM, iot_knob_get_event(arg)); - ESP_LOGI(TAG, "KNOB%d: KNOB_H_LIM usr_data: %s", get_knob_index((knob_handle_t)arg), (char *)data); -} - -static void knob_l_lim_cb(void *arg, void *data) -{ - TEST_ASSERT_EQUAL_HEX(KNOB_L_LIM, iot_knob_get_event(arg)); - ESP_LOGI(TAG, "KNOB%d: KNOB_L_LIM usr_data: %s", get_knob_index((knob_handle_t)arg), (char *)data); -} - -static void knob_zero_cb(void *arg, void *data) -{ - TEST_ASSERT_EQUAL_HEX(KNOB_ZERO, iot_knob_get_event(arg)); - ESP_LOGI(TAG, "KNOB%d: KNOB_ZERO usr_data: %s", get_knob_index((knob_handle_t)arg), (char *)data); -} - -static const char *knob_name[] = {"knob_0", - "knob_1", - "knob_2" - }; - -TEST_CASE("three knob test", "[knob][iot]") -{ - knob_config_t *cfg = calloc(1, sizeof(knob_config_t)); - cfg->default_direction = 0; - cfg->gpio_encoder_a = GPIO_KNOB_A; - cfg->gpio_encoder_b = GPIO_KNOB_B; - - for (int i = 0; i < KNOB_NUM; i++) { - s_knob[i] = iot_knob_create(cfg); - TEST_ASSERT_NOT_NULL(s_knob[i]); - iot_knob_register_cb(s_knob[i], KNOB_LEFT, knob_left_cb, (void *)knob_name[i]); - iot_knob_register_cb(s_knob[i], KNOB_RIGHT, knob_right_cb, (void *)knob_name[i]); - iot_knob_register_cb(s_knob[i], KNOB_H_LIM, knob_h_lim_cb, (void *)knob_name[i]); - iot_knob_register_cb(s_knob[i], KNOB_L_LIM, knob_l_lim_cb, (void *)knob_name[i]); - iot_knob_register_cb(s_knob[i], KNOB_ZERO, knob_zero_cb, (void *)knob_name[i]); - } - - while (1) { - vTaskDelay(pdMS_TO_TICKS(1000)); - } - - for (int i = 0; i < KNOB_NUM; i++) { - iot_knob_delete(s_knob[i]); - } -} - -TEST_CASE("one knob test", "[knob][iot]") -{ - knob_config_t *cfg = calloc(1, sizeof(knob_config_t)); - cfg->default_direction = 0; - cfg->gpio_encoder_a = GPIO_KNOB_A; - cfg->gpio_encoder_b = GPIO_KNOB_B; - - s_knob[0] = iot_knob_create(cfg); - TEST_ASSERT_NOT_NULL(s_knob[0]); - iot_knob_register_cb(s_knob[0], KNOB_LEFT, knob_left_cb, (void *)knob_name[0]); - iot_knob_register_cb(s_knob[0], KNOB_RIGHT, knob_right_cb, (void *)knob_name[0]); - iot_knob_register_cb(s_knob[0], KNOB_H_LIM, knob_h_lim_cb, (void *)knob_name[0]); - iot_knob_register_cb(s_knob[0], KNOB_L_LIM, knob_l_lim_cb, (void *)knob_name[0]); - iot_knob_register_cb(s_knob[0], KNOB_ZERO, knob_zero_cb, (void *)knob_name[0]); - - while (1) { - vTaskDelay(pdMS_TO_TICKS(1000)); - } - - iot_knob_delete(s_knob[0]); -} - - -static size_t before_free_8bit; -static size_t before_free_32bit; - -static void check_leak(size_t before_free, size_t after_free, const char *type) -{ - ssize_t delta = after_free - before_free; - printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); - TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak"); -} - -void setUp(void) -{ - before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); - before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); -} - -void tearDown(void) -{ - size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); - size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); - check_leak(before_free_8bit, after_free_8bit, "8BIT"); - check_leak(before_free_32bit, after_free_32bit, "32BIT"); -} - -void app_main(void) -{ - printf("USB STREAM TEST \n"); - unity_run_menu(); -} diff --git a/test_apps/main/test_ESP_Knob.cpp b/test_apps/main/test_ESP_Knob.cpp new file mode 100644 index 0000000..5fe070b --- /dev/null +++ b/test_apps/main/test_ESP_Knob.cpp @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/timers.h" +#include "esp_idf_version.h" +#include "esp_log.h" +#include "unity.h" +#include "sdkconfig.h" +#include "ESP_Knob.h" +#include "esp_log.h" + +static const char *TAG = "ESP_KNOB"; + +#define TEST_MEMORY_LEAK_THRESHOLD (-400) + +#define GPIO_KNOB_A 1 +#define GPIO_KNOB_B 2 +#define KNOB_NUM 3 + +void onKnobLeftEventCallback(int count, void *usr_data) +{ + ESP_LOGI(TAG, "Detect left event, count is %d\n", count); +} + +void onKnobRightEventCallback(int count, void *usr_data) +{ + ESP_LOGI(TAG, "Detect right event, count is %d\n", count); +} + +void onKnobHighLimitEventCallback(int count, void *usr_data) +{ + ESP_LOGI(TAG, "Detect high limit event, count is %d\n", count); +} + +void onKnobLowLimitEventCallback(int count, void *usr_data) +{ + ESP_LOGI(TAG, "Detect low limit event, count is %d\n", count); +} + +void onKnobZeroEventCallback(int count, void *usr_data) +{ + ESP_LOGI(TAG, "Detect zero event, count is %d\n", count); +} + +TEST_CASE("test ESP Knob", "[knob]") +{ + ESP_Knob knob(GPIO_KNOB_A, GPIO_KNOB_B); + + knob.begin(); + knob.invertDirection(); + knob.attachLeftEventCallback(onKnobLeftEventCallback); + knob.attachRightEventCallback(onKnobRightEventCallback); + knob.attachHighLimitEventCallback(onKnobHighLimitEventCallback); + knob.attachLowLimitEventCallback(onKnobLowLimitEventCallback); + knob.attachZeroEventCallback(onKnobZeroEventCallback); + + vTaskDelay(pdMS_TO_TICKS(3000)); + + knob.del(); +} + +static size_t before_free_8bit; +static size_t before_free_32bit; + +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); + TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak"); +} + +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); +} + +extern "C" void app_main(void) +{ + /** + * + * __ ___ ___ + * /\ /\ /\ \ \/___\/ __\ + * / //_// \/ // //__\// + * / __ \/ /\ / \_// \/ \ + * \/ \/\_\ \/\___/\_____/ + */ + printf(" __ ___ ___\r\n"); + printf(" /\\ /\\ /\\ \\ \\/___\\/ __\\\r\n"); + printf(" / //_// \\/ // //__\\//\r\n"); + printf("/ __ \\/ /\\ / \\_// \\/ \\\r\n"); + printf("\\/ \\/\\_\\ \\/\\___/\\_____/\r\n"); + unity_run_menu(); +} diff --git a/test_apps/sdkconfig.defaults b/test_apps/sdkconfig.defaults new file mode 100644 index 0000000..e4bfc20 --- /dev/null +++ b/test_apps/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ESP_TASK_WDT_EN=n