feat: initial
This commit is contained in:
1 parent
8f8f9cf87c
commit
193719fd2d
9 files changed
+632
-3
No files matched your search
@@ -0,0 +1 @@
|
||||
.DS_Store
|
||||
+6
-1
@@ -1 +1,6 @@
|
||||
idf_component_register(SRCS "main.c" INCLUDE_DIRS "include")
|
||||
if(${IDF_VERSION_MAJOR} STREQUAL 6)
|
||||
set(requires esp_driver_rmt esp_driver_gpio esp_event)
|
||||
else()
|
||||
set(requires driver esp_event)
|
||||
endif()
|
||||
idf_component_register(SRCS "zh_ttp229.c" INCLUDE_DIRS "include" REQUIRES ${requires})
|
||||
@@ -1,3 +1,94 @@
|
||||
# esp_component_template
|
||||
# ESP32 ESP-IDF component for TTP229 touch pad (via RMT driver)
|
||||
|
||||
esp_component_template
|
||||
## Tested on
|
||||
|
||||
1. [ESP32 ESP-IDF v6.0.0](https://docs.espressif.com/projects/esp-idf/en/v6.0/esp32/index.html)
|
||||
|
||||
## SAST Tools
|
||||
|
||||
[PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code.
|
||||
|
||||
## Features
|
||||
|
||||
1. Support up to 4 touch pads on one device.
|
||||
2. Support 8 or 16 pad work mode.
|
||||
|
||||
## Note
|
||||
|
||||
1. After start/reset first touch not work.
|
||||
2. Multi touch not supported.
|
||||
|
||||
## Attention
|
||||
|
||||
1. For correct operation, please enable the following settings in the menuconfig:
|
||||
|
||||
```text
|
||||
CONFIG_GPIO_CTRL_FUNC_IN_IRAM
|
||||
CONFIG_RMT_ENCODER_FUNC_IN_IRAM
|
||||
CONFIG_RMT_TX_ISR_HANDLER_IN_IRAM
|
||||
CONFIG_RMT_RX_ISR_HANDLER_IN_IRAM
|
||||
CONFIG_RMT_RECV_FUNC_IN_IRAM
|
||||
CONFIG_RMT_TX_ISR_CACHE_SAFE
|
||||
CONFIG_RMT_RX_ISR_CACHE_SAFE
|
||||
```
|
||||
|
||||
## Using
|
||||
|
||||
In an existing project, run the following command to install the components:
|
||||
|
||||
```text
|
||||
cd ../your_project/components
|
||||
git clone https://github.com/aZholtikov/zh_ttp229
|
||||
```
|
||||
|
||||
In the application, add the component:
|
||||
|
||||
```c
|
||||
#include "zh_ttp229.h"
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
One touch pad on device:
|
||||
|
||||
```c
|
||||
#include "zh_ttp229.h"
|
||||
|
||||
#define TTP229_NUMBER 0x01
|
||||
|
||||
zh_ttp229_handle_t ttp229_handle = {0};
|
||||
|
||||
void zh_ttp229_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_log_level_set("zh_ttp229", ESP_LOG_ERROR);
|
||||
esp_event_loop_create_default();
|
||||
esp_event_handler_instance_register(ZH_TTP229, ESP_EVENT_ANY_ID, &zh_ttp229_event_handler, NULL, NULL);
|
||||
zh_ttp229_init_config_t config = ZH_TTP229_INIT_CONFIG_DEFAULT();
|
||||
config.scl_gpio = GPIO_NUM_25;
|
||||
config.sdo_gpio = GPIO_NUM_27;
|
||||
config.work_mode = ZH_TTP229_16_PAD;
|
||||
config.device_number = TTP229_NUMBER;
|
||||
config.debounce_time = 300;
|
||||
// The time between the low-level pulse in the interrupt and the actual start time of the RMT signal generator (in microseconds).
|
||||
// It is determined experimentally or using a logic analyzer.
|
||||
config.rmt_tx_start_delay = 19;
|
||||
zh_ttp229_init(&config, &ttp229_handle);
|
||||
for (;;)
|
||||
{
|
||||
const zh_ttp229_stats_t *stats = zh_ttp229_get_stats();
|
||||
printf("Number of RMT driver error: %ld.\n", stats->rmt_driver_error);
|
||||
printf("Number of event post error: %ld.\n", stats->event_post_error);
|
||||
printf("Number of queue overflow error: %ld.\n", stats->queue_overflow_error);
|
||||
printf("Minimum free stack size: %ld.\n", stats->min_stack_size);
|
||||
vTaskDelay(60000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void zh_ttp229_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
zh_ttp229_event_on_isr_t *ttp229_event = event_data;
|
||||
printf("Touch pad number %d pad number %d pressed.\n", ttp229_event->device_number, ttp229_event->pad_number);
|
||||
}
|
||||
```
|
||||
Binary file not shown.
Whitespace-only changes.
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @file zh_ttp229.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/rmt_tx.h"
|
||||
#include "driver/rmt_rx.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_event.h"
|
||||
|
||||
/**
|
||||
* @brief TTP229 touch pad initial default values.
|
||||
*/
|
||||
#define ZH_TTP229_INIT_CONFIG_DEFAULT() \
|
||||
{ \
|
||||
.task_priority = 1, \
|
||||
.stack_size = configMINIMAL_STACK_SIZE, \
|
||||
.queue_size = 1, \
|
||||
.work_mode = ZH_TTP229_8_PAD, \
|
||||
.rmt_tx_start_delay = 0, \
|
||||
.debounce_time = 100, \
|
||||
.device_number = 0, \
|
||||
.scl_gpio = GPIO_NUM_MAX, \
|
||||
.sdo_gpio = GPIO_NUM_MAX}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
extern TaskHandle_t zh_ttp229; /*!< Unique task handle. */
|
||||
|
||||
/**
|
||||
* @brief Enumeration of TTP229 touch pad work mode.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ZH_TTP229_8_PAD = 8,
|
||||
ZH_TTP229_16_PAD = 16,
|
||||
} zh_ttp229_work_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Structure for initial initialization of TTP229 touch pad.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t stack_size; /*!< Stack size for task for the TTP229 touch pad isr processing processing. @note The minimum size is configMINIMAL_STACK_SIZE. */
|
||||
uint16_t debounce_time; /*!< Touch pad button debounce time. @note Minimum value is 10 (in milliseconds). */
|
||||
uint8_t task_priority; /*!< Task priority for the TTP229 touch pad isr processing. @note Minimum value is 1. */
|
||||
uint8_t queue_size; /*!< Queue size for task for the touch pad processing. @note Minimum value is 1. */
|
||||
uint8_t device_number; /*!< Touch pad unique number. @note Must be greater than 0. */
|
||||
uint8_t rmt_tx_start_delay; /*!< The time between the low-level pulse in the interrupt and the actual start time of the RMT signal generator (in microseconds). @note Minimum value is 15. */
|
||||
gpio_num_t sdo_gpio; /*!< SDO GPIO. */
|
||||
gpio_num_t scl_gpio; /*!< SCL GPIO. */
|
||||
zh_ttp229_work_mode_t work_mode; /*!< Touch pad work mode. */
|
||||
} zh_ttp229_init_config_t;
|
||||
|
||||
/**
|
||||
* @brief TTP229 touch pad handle.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool is_initialized; /*!< Touch pad initialization flag. */
|
||||
gpio_num_t sdo_gpio; /*!< SDO GPIO. */
|
||||
uint8_t device_number; /*!< Touch pad unique number. */
|
||||
uint8_t rmt_tx_start_delay; /*!< The time between the low-level pulse in the interrupt and the actual start time of the RMT signal generator (in microseconds). */
|
||||
uint16_t debounce_time; /*!< Touch pad button debounce_time. */
|
||||
zh_ttp229_work_mode_t work_mode; /*!< Touch pad work mode. */
|
||||
rmt_symbol_word_t rx_symbols; /*!< Received symbols. */
|
||||
rmt_channel_handle_t tx_channel; /*!< Unique RMT TX device handle. */
|
||||
rmt_channel_handle_t rx_channel; /*!< Unique RMT RX device handle. */
|
||||
rmt_encoder_handle_t copy_encoder; /*!< Unique copy encoder handle. */
|
||||
} zh_ttp229_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Structure for error statistics storage.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t rmt_driver_error; /*!< Number of RMT driver error. */
|
||||
uint32_t event_post_error; /*!< Number of event post error. */
|
||||
uint32_t queue_overflow_error; /*!< Number of queue overflow error. */
|
||||
uint32_t min_stack_size; /*!< Minimum free stack size. */
|
||||
} zh_ttp229_stats_t;
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(ZH_TTP229);
|
||||
|
||||
/**
|
||||
* @brief Structure for sending data to the event handler when cause an interrupt.
|
||||
*
|
||||
* @note Should be used with ZH_TTP229 event base.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pad_number; /*!< The pad that caused the interrupt. */
|
||||
uint8_t device_number; /*!< Touch pad unique number. */
|
||||
} zh_ttp229_event_on_isr_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize TTP229 touch pad.
|
||||
*
|
||||
* @param[in] config Pointer to TTP229 initialized configuration structure. Can point to a temporary variable.
|
||||
* @param[out] handle Pointer to unique TTP229 handle.
|
||||
*
|
||||
* @attention I2C driver must be initialized first.
|
||||
*
|
||||
* @note Before initialize the expander recommend initialize zh_ttp229_init_config_t structure with default values.
|
||||
*
|
||||
* @code zh_ttp229_init_config_t config = ZH_TTP229_INIT_CONFIG_DEFAULT() @endcode
|
||||
*
|
||||
* @return ESP_OK if success or an error code otherwise.
|
||||
*/
|
||||
esp_err_t zh_ttp229_init(const zh_ttp229_init_config_t *config, zh_ttp229_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize TTP229 touch pad.
|
||||
*
|
||||
* @param[in] handle Pointer to unique TTP229 handle.
|
||||
*
|
||||
* @return ESP_OK if success or an error code otherwise.
|
||||
*/
|
||||
esp_err_t zh_ttp229_deinit(zh_ttp229_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief Get error statistics.
|
||||
*
|
||||
* @return Pointer to the statistics structure.
|
||||
*/
|
||||
const zh_ttp229_stats_t *zh_ttp229_get_stats(void);
|
||||
|
||||
/**
|
||||
* @brief Reset error statistics.
|
||||
*/
|
||||
void zh_ttp229_reset_stats(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
+388
@@ -0,0 +1,388 @@
|
||||
#include "zh_ttp229.h"
|
||||
|
||||
static const char *TAG = "zh_ttp229";
|
||||
|
||||
#define ZH_LOGI(msg, ...) ESP_LOGI(TAG, msg, ##__VA_ARGS__)
|
||||
#define ZH_LOGE(msg, err, ...) ESP_LOGE(TAG, "[%s:%d:%s] " msg, __FILE__, __LINE__, esp_err_to_name(err), ##__VA_ARGS__)
|
||||
|
||||
#define ZH_ERROR_CHECK(cond, err, cleanup, msg, ...) \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
ZH_LOGE(msg, err, ##__VA_ARGS__); \
|
||||
cleanup; \
|
||||
return err; \
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
zh_ttp229_handle_t *handle;
|
||||
} zh_ttp229_queue_t;
|
||||
|
||||
TaskHandle_t zh_ttp229 = NULL;
|
||||
static QueueHandle_t _queue_handle = NULL;
|
||||
|
||||
volatile static uint8_t _pad_counter = {0};
|
||||
volatile static uint8_t _pad_number_matrix[4] = {0};
|
||||
static zh_ttp229_stats_t _stats = {0};
|
||||
|
||||
static esp_err_t _zh_ttp229_validate_config(const zh_ttp229_init_config_t *config, zh_ttp229_handle_t *handle);
|
||||
static esp_err_t _zh_ttp229_gpio_init(const zh_ttp229_init_config_t *config, zh_ttp229_handle_t *handle);
|
||||
static esp_err_t _zh_ttp229_rmt_init(const zh_ttp229_init_config_t *config, zh_ttp229_handle_t *handle);
|
||||
static esp_err_t _zh_ttp229_resources_init(const zh_ttp229_init_config_t *config);
|
||||
static esp_err_t _zh_ttp229_task_init(const zh_ttp229_init_config_t *config);
|
||||
static void _zh_ttp229_isr_handler(void *arg);
|
||||
static void _zh_ttp229_isr_processing_task(void *pvParameter);
|
||||
static bool _zh_ttp229_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data);
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(ZH_TTP229);
|
||||
|
||||
esp_err_t zh_ttp229_init(const zh_ttp229_init_config_t *config, zh_ttp229_handle_t *handle) // -V2008
|
||||
{
|
||||
ZH_LOGI("Touch pad initialization started.");
|
||||
ZH_ERROR_CHECK(config != NULL && handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Touch pad initialization failed. Invalid argument.");
|
||||
ZH_ERROR_CHECK(handle->is_initialized == false, ESP_ERR_INVALID_STATE, NULL, "Touch pad initialization failed. Touch pad is already initialized.");
|
||||
ZH_ERROR_CHECK(_pad_counter < sizeof(_pad_number_matrix), ESP_ERR_INVALID_ARG, NULL, "Touch pad initialization failed. Maximum quantity reached.");
|
||||
ZH_ERROR_CHECK(_zh_ttp229_validate_config(config, handle) == ESP_OK, ESP_FAIL, NULL, "Touch pad initialization failed. Initial configuration check failed.");
|
||||
ZH_ERROR_CHECK(_zh_ttp229_resources_init(config) == ESP_OK, ESP_FAIL, NULL, "Touch pad initialization failed. Resources initialization failed.");
|
||||
ZH_ERROR_CHECK(_zh_ttp229_task_init(config) == ESP_OK, ESP_FAIL,
|
||||
vQueueDelete(_queue_handle), "Touch pad initialization failed. Processing task initialization failed.");
|
||||
ZH_ERROR_CHECK(_zh_ttp229_rmt_init(config, handle) == ESP_OK, ESP_FAIL,
|
||||
vQueueDelete(_queue_handle);
|
||||
vTaskDelete(zh_ttp229), "Touch pad initialization failed. RMT initialization failed.");
|
||||
ZH_ERROR_CHECK(_zh_ttp229_gpio_init(config, handle) == ESP_OK, ESP_FAIL,
|
||||
ZH_ERROR_CHECK(rmt_disable(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "TX channel disable failed.");
|
||||
ZH_ERROR_CHECK(rmt_disable(handle->rx_channel) == ESP_OK, ESP_FAIL, NULL, "RX channel disable failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_encoder(handle->copy_encoder) == ESP_OK, ESP_FAIL, NULL, "Delete encoder failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete TX channel failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->rx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete RX channel failed.");
|
||||
vQueueDelete(_queue_handle);
|
||||
vTaskDelete(zh_ttp229), "Encoder initialization failed. GPIO initialization failed.");
|
||||
if (_stats.min_stack_size == 0)
|
||||
{
|
||||
_stats.min_stack_size = config->stack_size;
|
||||
}
|
||||
handle->debounce_time = config->debounce_time;
|
||||
handle->is_initialized = true;
|
||||
++_pad_counter;
|
||||
for (uint8_t i = 0; i < sizeof(_pad_number_matrix); ++i)
|
||||
{
|
||||
if (_pad_number_matrix[i] == 0)
|
||||
{
|
||||
_pad_number_matrix[i] = handle->device_number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ZH_LOGI("Touch pad initialization completed successfully.");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t zh_ttp229_deinit(zh_ttp229_handle_t *handle) // -V2008
|
||||
{
|
||||
ZH_LOGI("Touch pad deinitialization started.");
|
||||
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Touch pad deinitialization failed. Invalid argument.");
|
||||
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Touch pad deinitialization failed. Touch pad not initialized.");
|
||||
ZH_ERROR_CHECK(rmt_disable(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "Touch pad deinitialization failed. TX channel disable failed.");
|
||||
ZH_ERROR_CHECK(rmt_disable(handle->rx_channel) == ESP_OK, ESP_FAIL, NULL, "Touch pad deinitialization failed. RX channel disable failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_encoder(handle->copy_encoder) == ESP_OK, ESP_FAIL, NULL, "Touch pad deinitialization failed. Delete encoder failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "Touch pad deinitialization failed. Delete TX channel failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->rx_channel) == ESP_OK, ESP_FAIL, NULL, "Touch pad deinitialization failed. Delete RX channel failed.");
|
||||
ZH_ERROR_CHECK(gpio_isr_handler_remove((gpio_num_t)handle->sdo_gpio) == ESP_OK, ESP_FAIL, NULL, "Touch pad deinitialization failed. Remove GPIO isr handler failed.");
|
||||
ZH_ERROR_CHECK(gpio_reset_pin((gpio_num_t)handle->sdo_gpio) == ESP_OK, ESP_FAIL, NULL, "Touch pad deinitialization failed. Reset GPIO failed.");
|
||||
if (_pad_counter == 1)
|
||||
{
|
||||
vQueueDelete(_queue_handle);
|
||||
vTaskDelete(zh_ttp229);
|
||||
}
|
||||
handle->is_initialized = false;
|
||||
--_pad_counter;
|
||||
for (uint8_t i = 0; i < sizeof(_pad_number_matrix); ++i)
|
||||
{
|
||||
if (_pad_number_matrix[i] == handle->device_number)
|
||||
{
|
||||
_pad_number_matrix[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ZH_LOGI("Touch pad deinitialization completed successfully.");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const zh_ttp229_stats_t *zh_ttp229_get_stats(void)
|
||||
{
|
||||
return &_stats;
|
||||
}
|
||||
|
||||
void zh_ttp229_reset_stats(void)
|
||||
{
|
||||
ZH_LOGI("Error statistic reset started.");
|
||||
_stats.rmt_driver_error = 0;
|
||||
_stats.event_post_error = 0;
|
||||
_stats.queue_overflow_error = 0;
|
||||
_stats.min_stack_size = 0;
|
||||
ZH_LOGI("Error statistic reset successfully.");
|
||||
}
|
||||
|
||||
static esp_err_t _zh_ttp229_validate_config(const zh_ttp229_init_config_t *config, zh_ttp229_handle_t *handle) // -V2008
|
||||
{
|
||||
ZH_ERROR_CHECK(config->task_priority >= 1 && config->stack_size >= configMINIMAL_STACK_SIZE, ESP_ERR_INVALID_ARG, NULL, "Invalid task settings.");
|
||||
ZH_ERROR_CHECK(config->queue_size >= 1, ESP_ERR_INVALID_ARG, NULL, "Invalid queue size.");
|
||||
ZH_ERROR_CHECK(config->debounce_time >= 10, ESP_ERR_INVALID_ARG, NULL, "Invalid debounce time.");
|
||||
ZH_ERROR_CHECK(config->rmt_tx_start_delay >= 15, ESP_ERR_INVALID_ARG, NULL, "Invalid RMT TX start delay.");
|
||||
ZH_ERROR_CHECK(config->work_mode == ZH_TTP229_8_PAD || config->work_mode == ZH_TTP229_16_PAD, ESP_ERR_INVALID_ARG, NULL, "Invalid touch pad work mode.");
|
||||
ZH_ERROR_CHECK(config->device_number > 0, ESP_ERR_INVALID_ARG, NULL, "Invalid touch pad number.");
|
||||
for (uint8_t i = 0; i < sizeof(_pad_number_matrix); ++i)
|
||||
{
|
||||
ZH_ERROR_CHECK(config->device_number != _pad_number_matrix[i], ESP_ERR_INVALID_ARG, NULL, "Touch pad number already present.");
|
||||
}
|
||||
handle->rmt_tx_start_delay = config->rmt_tx_start_delay;
|
||||
handle->device_number = config->device_number;
|
||||
handle->work_mode = config->work_mode;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _zh_ttp229_gpio_init(const zh_ttp229_init_config_t *config, zh_ttp229_handle_t *handle) // -V2008
|
||||
{
|
||||
ZH_ERROR_CHECK(config->scl_gpio < GPIO_NUM_MAX && config->sdo_gpio < GPIO_NUM_MAX, ESP_ERR_INVALID_ARG, NULL, "Invalid GPIO number.")
|
||||
ZH_ERROR_CHECK(config->scl_gpio != config->sdo_gpio, ESP_ERR_INVALID_ARG, NULL, "SCL GPIO and SDO GPIO is same.")
|
||||
gpio_config_t sdo_config = {
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pin_bit_mask = (1ULL << config->sdo_gpio),
|
||||
.intr_type = GPIO_INTR_POSEDGE};
|
||||
ZH_ERROR_CHECK(gpio_config(&sdo_config) == ESP_OK, ESP_FAIL, NULL, "GPIO initialization failed.");
|
||||
esp_err_t err = gpio_install_isr_service(ESP_INTR_FLAG_LOWMED);
|
||||
ZH_ERROR_CHECK(err == ESP_OK || err == ESP_ERR_INVALID_STATE, ESP_FAIL,
|
||||
ZH_ERROR_CHECK(gpio_reset_pin((gpio_num_t)config->sdo_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset GPIO failed."), "Failed install isr service.");
|
||||
ZH_ERROR_CHECK(gpio_isr_handler_add((gpio_num_t)config->sdo_gpio, _zh_ttp229_isr_handler, handle) == ESP_OK, ESP_FAIL,
|
||||
ZH_ERROR_CHECK(gpio_reset_pin((gpio_num_t)config->sdo_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset GPIO failed."), "Interrupt initialization failed.");
|
||||
handle->sdo_gpio = config->sdo_gpio;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _zh_ttp229_rmt_init(const zh_ttp229_init_config_t *config, zh_ttp229_handle_t *handle) // -V2008
|
||||
{
|
||||
rmt_tx_channel_config_t tx_chan_config = {
|
||||
.clk_src = RMT_CLK_SRC_DEFAULT,
|
||||
.gpio_num = config->scl_gpio,
|
||||
.mem_block_symbols = 64,
|
||||
.resolution_hz = 1000000,
|
||||
.trans_queue_depth = 4,
|
||||
.flags.init_level = 1,
|
||||
};
|
||||
ZH_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "TX channel creation failed.");
|
||||
rmt_copy_encoder_config_t copy_encoder_config = {};
|
||||
ZH_ERROR_CHECK(rmt_new_copy_encoder(©_encoder_config, &handle->copy_encoder) == ESP_OK, ESP_FAIL,
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete channel failed."), "Copy encoder creation failed.");
|
||||
ZH_ERROR_CHECK(rmt_enable(handle->tx_channel) == ESP_OK, ESP_FAIL,
|
||||
ZH_ERROR_CHECK(rmt_del_encoder(handle->copy_encoder) == ESP_OK, ESP_FAIL, NULL, "Delete encoder failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete channel failed."), "Enable TX channel failed.");
|
||||
rmt_rx_channel_config_t rx_chan_config = {
|
||||
.clk_src = RMT_CLK_SRC_DEFAULT,
|
||||
.gpio_num = config->sdo_gpio,
|
||||
.mem_block_symbols = 64,
|
||||
.resolution_hz = 1000000,
|
||||
};
|
||||
ZH_ERROR_CHECK(rmt_new_rx_channel(&rx_chan_config, &handle->rx_channel) == ESP_OK, ESP_FAIL,
|
||||
ZH_ERROR_CHECK(rmt_disable(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "TX channel disable failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_encoder(handle->copy_encoder) == ESP_OK, ESP_FAIL, NULL, "Delete encoder failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete TX channel failed."), "TX channel creation failed.");
|
||||
ZH_ERROR_CHECK(rmt_enable(handle->rx_channel) == ESP_OK, ESP_FAIL,
|
||||
ZH_ERROR_CHECK(rmt_disable(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "TX channel disable failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_encoder(handle->copy_encoder) == ESP_OK, ESP_FAIL, NULL, "Delete encoder failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete TX channel failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->rx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete RX channel failed."), "RX channel creation failed.");
|
||||
rmt_rx_event_callbacks_t cbs = {
|
||||
.on_recv_done = _zh_ttp229_rmt_rx_done_callback,
|
||||
};
|
||||
ZH_ERROR_CHECK(rmt_rx_register_event_callbacks(handle->rx_channel, &cbs, handle) == ESP_OK, ESP_FAIL,
|
||||
ZH_ERROR_CHECK(rmt_disable(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "TX channel disable failed.");
|
||||
ZH_ERROR_CHECK(rmt_disable(handle->rx_channel) == ESP_OK, ESP_FAIL, NULL, "RX channel disable failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_encoder(handle->copy_encoder) == ESP_OK, ESP_FAIL, NULL, "Delete encoder failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->tx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete TX channel failed.");
|
||||
ZH_ERROR_CHECK(rmt_del_channel(handle->rx_channel) == ESP_OK, ESP_FAIL, NULL, "Delete RX channel failed."), "TX callback registar failed.");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _zh_ttp229_resources_init(const zh_ttp229_init_config_t *config)
|
||||
{
|
||||
if (_pad_counter == 0)
|
||||
{
|
||||
_queue_handle = xQueueCreate(config->queue_size, sizeof(zh_ttp229_queue_t));
|
||||
ZH_ERROR_CHECK(_queue_handle != NULL, ESP_FAIL, NULL, "Failed to create queue.");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _zh_ttp229_task_init(const zh_ttp229_init_config_t *config)
|
||||
{
|
||||
if (_pad_counter == 0)
|
||||
{
|
||||
ZH_ERROR_CHECK(xTaskCreatePinnedToCore(&_zh_ttp229_isr_processing_task, "zh_ttp229_isr_processing", config->stack_size, NULL, config->task_priority, &zh_ttp229, tskNO_AFFINITY) == pdPASS,
|
||||
ESP_FAIL, NULL, "Failed to create isr processing task.");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR _zh_ttp229_isr_handler(void *arg)
|
||||
{
|
||||
zh_ttp229_handle_t *ttp229_handle = (zh_ttp229_handle_t *)arg;
|
||||
gpio_intr_disable(ttp229_handle->sdo_gpio);
|
||||
rmt_receive_config_t rx_receive_config = {.signal_range_min_ns = 100, .signal_range_max_ns = 2000000};
|
||||
if (rmt_receive(ttp229_handle->rx_channel, &ttp229_handle->rx_symbols, sizeof(ttp229_handle->rx_symbols), &rx_receive_config) != ESP_OK)
|
||||
{
|
||||
++_stats.rmt_driver_error;
|
||||
}
|
||||
gpio_set_direction(ttp229_handle->sdo_gpio, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(ttp229_handle->sdo_gpio, 0);
|
||||
gpio_set_level(ttp229_handle->sdo_gpio, 1);
|
||||
gpio_set_direction(ttp229_handle->sdo_gpio, GPIO_MODE_INPUT);
|
||||
rmt_symbol_word_t scl_symbols[ttp229_handle->work_mode];
|
||||
for (uint8_t i = 0; i < ttp229_handle->work_mode; ++i)
|
||||
{
|
||||
scl_symbols[i] = (rmt_symbol_word_t){.duration0 = 2, .level0 = 0, .duration1 = 2, .level1 = 1};
|
||||
}
|
||||
rmt_transmit_config_t tx_transmit_config = {.loop_count = 0, .flags.eot_level = 1, .flags.queue_nonblocking = 1};
|
||||
if (rmt_transmit(ttp229_handle->tx_channel, ttp229_handle->copy_encoder, scl_symbols, sizeof(scl_symbols), &tx_transmit_config) != ESP_OK)
|
||||
{
|
||||
++_stats.rmt_driver_error;
|
||||
}
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
static void IRAM_ATTR _zh_ttp229_isr_processing_task(void *pvParameter) // -V2008
|
||||
{
|
||||
zh_ttp229_queue_t ttp229_queue = {0};
|
||||
while (xQueueReceive(_queue_handle, &ttp229_queue, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
zh_ttp229_handle_t *ttp229_handle = ttp229_queue.handle;
|
||||
uint8_t pad_number = 0;
|
||||
if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay - 1)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 1)))
|
||||
{
|
||||
pad_number = 1;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 3)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 4)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 5)))
|
||||
{
|
||||
pad_number = 2;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 7)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 8)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 9)))
|
||||
{
|
||||
pad_number = 3;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 11)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 12)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 13)))
|
||||
{
|
||||
pad_number = 4;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 15)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 16)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 17)))
|
||||
{
|
||||
pad_number = 5;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 19)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 20)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 21)))
|
||||
{
|
||||
pad_number = 6;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 23)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 24)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 25)))
|
||||
{
|
||||
pad_number = 7;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 27)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 28)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 29)))
|
||||
{
|
||||
pad_number = 8;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 31)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 32)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 33)))
|
||||
{
|
||||
pad_number = 9;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 35)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 36)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 37)))
|
||||
{
|
||||
pad_number = 10;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 39)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 40)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 41)))
|
||||
{
|
||||
pad_number = 11;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 43)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 44)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 45)))
|
||||
{
|
||||
pad_number = 12;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 47)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 48)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 49)))
|
||||
{
|
||||
pad_number = 13;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 51)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 52)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 53)))
|
||||
{
|
||||
pad_number = 14;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 55)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 56)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 57)))
|
||||
{
|
||||
pad_number = 15;
|
||||
}
|
||||
else if ((ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 59)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 60)) ||
|
||||
(ttp229_handle->rx_symbols.duration1 == (ttp229_handle->rmt_tx_start_delay + 61)))
|
||||
{
|
||||
pad_number = 16;
|
||||
}
|
||||
if (pad_number != 0)
|
||||
{
|
||||
zh_ttp229_event_on_isr_t ttp229_data = {0};
|
||||
ttp229_data.pad_number = pad_number;
|
||||
ttp229_data.device_number = ttp229_handle->device_number;
|
||||
esp_err_t err = esp_event_post(ZH_TTP229, 0, &ttp229_data, sizeof(zh_ttp229_event_on_isr_t), 1000 / portTICK_PERIOD_MS);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
++_stats.event_post_error;
|
||||
ZH_LOGE("Touch pad isr processing failed. Failed to post interrupt event.", err);
|
||||
}
|
||||
}
|
||||
vTaskDelay(ttp229_handle->debounce_time / portTICK_PERIOD_MS);
|
||||
gpio_intr_enable(ttp229_handle->sdo_gpio);
|
||||
_stats.min_stack_size = (uint32_t)uxTaskGetStackHighWaterMark(NULL);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static bool IRAM_ATTR _zh_ttp229_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data)
|
||||
{
|
||||
zh_ttp229_handle_t *ttp229_handle = (zh_ttp229_handle_t *)user_data;
|
||||
zh_ttp229_queue_t ttp229_queue = {0};
|
||||
ttp229_queue.handle = ttp229_handle;
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
if (xQueueSendFromISR(_queue_handle, &ttp229_queue, &xHigherPriorityTaskWoken) != pdTRUE)
|
||||
{
|
||||
++_stats.queue_overflow_error;
|
||||
}
|
||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in new issue
Block a user