feat!: handle changed to double pointer
This commit is contained in:
1 parent
e7c19680ae
commit
f57671206b
7 files changed
+493
-502
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
# ESP32 ESP-IDF component for PCF8574(A) 8-bit I/O expander
|
# ESP32 ESP-IDF component for PCF8574 8-bit I/O expander
|
||||||
|
|
||||||
## Wiki
|
## Wiki
|
||||||
|
|
||||||
@@ -10,33 +10,15 @@
|
|||||||
|
|
||||||
## SAST Tools
|
## 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.
|
[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
|
## Features
|
||||||
|
|
||||||
1. Support of 16 expanders on one bus.
|
1. I2C communication via esp-idf i2c_master driver.
|
||||||
2. Support of output and input GPIO's work mode.
|
2. Configurable GPIO direction for each pin (P0-P7).
|
||||||
3. Support of interrupts from input GPIO's.
|
3. Interrupt handling with GPIO level detection.
|
||||||
|
4. Event-based architecture using esp_event framework.
|
||||||
## Note
|
5. Statistics tracking for debugging and monitoring.
|
||||||
|
|
||||||
1. Enable interrupt support only if input GPIO's are used.
|
|
||||||
2. All the INT GPIO's on the extenders must be connected to the one GPIO on ESP.
|
|
||||||
3. The input GPIO's are always pullup to the power supply.
|
|
||||||
|
|
||||||
## Attention
|
|
||||||
|
|
||||||
For correct operation, please enable the following settings in the menuconfig:
|
|
||||||
|
|
||||||
```text
|
|
||||||
GPIO_CTRL_FUNC_IN_IRAM
|
|
||||||
I2C_ISR_IRAM_SAFE
|
|
||||||
I2C_MASTER_ISR_HANDLER_IN_IRAM
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
1. [zh_vector](https://github.com/aZholtikov/zh_vector)
|
|
||||||
|
|
||||||
## Using
|
## Using
|
||||||
|
|
||||||
@@ -55,88 +37,4 @@ In the application, add the component:
|
|||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
One expander on bus. All GPIO's as output (except P0 - input). Interrupt is enable:
|
See Wiki [EN](WIKI_EN.md#usage-examples) | [RU](WIKI_RU.md#примеры-использования)
|
||||||
|
|
||||||
```c
|
|
||||||
#include "zh_pcf8574.h"
|
|
||||||
|
|
||||||
#define I2C_PORT (I2C_NUM_MAX - 1)
|
|
||||||
|
|
||||||
zh_pcf8574_handle_t pcf8574_handle = {0};
|
|
||||||
|
|
||||||
void zh_pcf8574_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
|
||||||
|
|
||||||
void print_gpio_status(const char *message, uint8_t reg)
|
|
||||||
{
|
|
||||||
printf("%s", message);
|
|
||||||
for (uint8_t i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
printf("%c", (reg & 0x80) ? '1' : '0');
|
|
||||||
reg <<= 1;
|
|
||||||
}
|
|
||||||
printf(".\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_main(void)
|
|
||||||
{
|
|
||||||
esp_log_level_set("zh_pcf8574", ESP_LOG_ERROR);
|
|
||||||
esp_log_level_set("zh_vector", ESP_LOG_ERROR);
|
|
||||||
i2c_master_bus_config_t i2c_bus_config = {
|
|
||||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
|
||||||
.i2c_port = I2C_PORT,
|
|
||||||
.scl_io_num = GPIO_NUM_22,
|
|
||||||
.sda_io_num = GPIO_NUM_21,
|
|
||||||
.glitch_ignore_cnt = 7,
|
|
||||||
.flags.enable_internal_pullup = true,
|
|
||||||
};
|
|
||||||
i2c_master_bus_handle_t i2c_bus_handle = NULL;
|
|
||||||
i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
|
|
||||||
esp_event_loop_create_default();
|
|
||||||
esp_event_handler_instance_register(ZH_PCF8574, ESP_EVENT_ANY_ID, &zh_pcf8574_event_handler, NULL, NULL);
|
|
||||||
zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT();
|
|
||||||
config.i2c_handle = i2c_bus_handle;
|
|
||||||
config.i2c_address = 0x38;
|
|
||||||
config.p0_gpio_work_mode = ZH_PCF8574_GPIO_INPUT;
|
|
||||||
config.interrupt_gpio = GPIO_NUM_14;
|
|
||||||
zh_pcf8574_init(&config, &pcf8574_handle);
|
|
||||||
uint8_t reg = 0;
|
|
||||||
zh_pcf8574_read(&pcf8574_handle, ®);
|
|
||||||
print_gpio_status("GPIO status: ", reg);
|
|
||||||
printf("Set P7 to 1, P1 to 1 and P0 to 0.\n");
|
|
||||||
zh_pcf8574_write(&pcf8574_handle, 0b10000010);
|
|
||||||
zh_pcf8574_read(&pcf8574_handle, ®);
|
|
||||||
print_gpio_status("GPIO status: ", reg);
|
|
||||||
printf("Sets P0 to 0.\n");
|
|
||||||
zh_pcf8574_write_gpio(&pcf8574_handle, ZH_PCF8574_GPIO_NUM_P0, ZH_PCF8574_GPIO_LOW);
|
|
||||||
bool gpio = 0;
|
|
||||||
zh_pcf8574_read_gpio(&pcf8574_handle, ZH_PCF8574_GPIO_NUM_P0, &gpio);
|
|
||||||
printf("P0 status: %d.\n", gpio);
|
|
||||||
printf("Set P1 to 0.\n");
|
|
||||||
zh_pcf8574_write_gpio(&pcf8574_handle, ZH_PCF8574_GPIO_NUM_P1, ZH_PCF8574_GPIO_LOW);
|
|
||||||
zh_pcf8574_read_gpio(&pcf8574_handle, ZH_PCF8574_GPIO_NUM_P1, &gpio);
|
|
||||||
printf("P1 status: %d.\n", gpio);
|
|
||||||
zh_pcf8574_read(&pcf8574_handle, ®);
|
|
||||||
print_gpio_status("GPIO status: ", reg);
|
|
||||||
printf("Reset all GPIO.\n");
|
|
||||||
zh_pcf8574_reset(&pcf8574_handle);
|
|
||||||
zh_pcf8574_read(&pcf8574_handle, ®);
|
|
||||||
print_gpio_status("GPIO status: ", reg);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
const zh_pcf8574_stats_t *stats = zh_pcf8574_get_stats();
|
|
||||||
printf("Number of i2c driver error: %ld.\n", stats->i2c_driver_error);
|
|
||||||
printf("Number of event post error: %ld.\n", stats->event_post_error);
|
|
||||||
printf("Number of vector error: %ld.\n", stats->vector_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_pcf8574_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
zh_pcf8574_event_on_isr_t *event = event_data;
|
|
||||||
printf("Interrupt happened on device address 0x%02X on GPIO number %d at level %d at time %lld.\n", event->i2c_address, event->gpio_number,
|
|
||||||
event->gpio_level, event->interrupt_time);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
+25
-51
@@ -88,7 +88,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
i2c_master_bus_handle_t i2c_handle; // Unique I2C bus handle
|
i2c_master_bus_handle_t i2c_handle; // Unique I2C bus handle
|
||||||
uint32_t i2c_frequency; // I2C frequency of the expander (max 100000 Hz)
|
uint32_t i2c_frequency; // I2C frequency of the expander (max 100000 Hz)
|
||||||
uint16_t stack_size; // Stack size for interrupt processing task
|
uint32_t stack_size; // Stack size for interrupt processing task
|
||||||
uint8_t task_priority; // Priority of interrupt processing task
|
uint8_t task_priority; // Priority of interrupt processing task
|
||||||
uint8_t i2c_address; // I2C address of the expander (0x20-0x27 or 0x38-0x3F)
|
uint8_t i2c_address; // I2C address of the expander (0x20-0x27 or 0x38-0x3F)
|
||||||
bool p0_gpio_work_mode; // GPIO P0 work mode (false - output, true - input)
|
bool p0_gpio_work_mode; // GPIO P0 work mode (false - output, true - input)
|
||||||
@@ -115,17 +115,11 @@ Use `ZH_PCF8574_INIT_CONFIG_DEFAULT()` macro to initialize with default values:
|
|||||||
### zh_pcf8574_handle_t Structure
|
### zh_pcf8574_handle_t Structure
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef struct
|
typedef struct _zh_pcf8574_handle_t zh_pcf8574_handle_t;
|
||||||
{
|
|
||||||
uint8_t i2c_address; // I2C address of the expander
|
|
||||||
uint8_t gpio_work_mode; // GPIO work modes (bits 0-7)
|
|
||||||
uint8_t gpio_status; // Current GPIO status (bits 0-7)
|
|
||||||
bool is_initialized; // Expander initialization flag
|
|
||||||
i2c_master_dev_handle_t dev_handle; // Unique I2C device handle
|
|
||||||
void *system; // System pointer for use in other components
|
|
||||||
} zh_pcf8574_handle_t;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Opaque handle for a PCF8574 device instance. The internal structure is minimal, storing only the I2C address — the full device state is maintained in an internal vector.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### zh_pcf8574_stats_t Structure
|
### zh_pcf8574_stats_t Structure
|
||||||
@@ -163,15 +157,16 @@ Initializes the PCF8574 expander.
|
|||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- `config` - Pointer to PCF8574 initialization configuration structure
|
- `config` - Pointer to PCF8574 initialization configuration structure. Must not be NULL
|
||||||
- `handle` - Pointer to unique PCF8574 handle
|
- `handle` - Pointer to pointer to PCF8574 handle. Must be NULL
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
- `ESP_OK` - Success
|
||||||
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL config or handle)
|
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL config or handle)
|
||||||
- `ESP_ERR_INVALID_STATE` - Expander already initialized
|
- `ESP_ERR_INVALID_STATE` - Expander already initialized
|
||||||
- `ESP_FAIL` - Initialization failed
|
- `ESP_ERR_NO_MEM` - Insufficient memory
|
||||||
|
- `ESP_ERR_NOT_SUPPORTED` - I2C initialization error
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -181,14 +176,12 @@ Deinitializes the PCF8574 expander.
|
|||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- `handle` - Pointer to unique PCF8574 handle
|
- `handle` - Pointer to pointer to PCF8574 handle. Must not be NULL
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
- `ESP_OK` - Success
|
||||||
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
|
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or *handle)
|
||||||
- `ESP_ERR_INVALID_STATE` - Expander not initialized
|
|
||||||
- `ESP_FAIL` - Deinitialization failed
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -198,15 +191,14 @@ Reads the state of all GPIO pins of the expander.
|
|||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- `handle` - Pointer to unique PCF8574 handle
|
- `handle` - Pointer to pointer to PCF8574 handle. Must not be NULL
|
||||||
- `reg` - Pointer to store GPIO status (bits 0-7)
|
- `reg` - Pointer to store GPIO status (bits 0-7). Must not be NULL
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
- `ESP_OK` - Success
|
||||||
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or reg)
|
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or reg)
|
||||||
- `ESP_ERR_NOT_FOUND` - Expander not initialized
|
- `ESP_ERR_INVALID_STATE` - Expander not initialized
|
||||||
- `ESP_FAIL` - I2C communication error
|
|
||||||
|
|
||||||
**Note:** For input GPIOs, the value will always be 1 (HIGH).
|
**Note:** For input GPIOs, the value will always be 1 (HIGH).
|
||||||
|
|
||||||
@@ -218,15 +210,14 @@ Sets the state of all output GPIO pins of the expander.
|
|||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- `handle` - Pointer to unique PCF8574 handle
|
- `handle` - Pointer to pointer to PCF8574 handle. Must not be NULL
|
||||||
- `reg` - GPIO status (bits 0-7)
|
- `reg` - GPIO status (bits 0-7)
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
- `ESP_OK` - Success
|
||||||
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
|
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
|
||||||
- `ESP_ERR_NOT_FOUND` - Expander not initialized
|
- `ESP_ERR_INVALID_STATE` - Expander not initialized
|
||||||
- `ESP_FAIL` - I2C communication error
|
|
||||||
|
|
||||||
**Note:** Only output GPIOs are affected.
|
**Note:** Only output GPIOs are affected.
|
||||||
|
|
||||||
@@ -238,14 +229,12 @@ Resets all GPIO pins of the expander to the initial state.
|
|||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- `handle` - Pointer to unique PCF8574 handle
|
- `handle` - Pointer to pointer to PCF8574 handle. Must not be NULL
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
- `ESP_OK` - Success
|
||||||
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle)
|
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or *handle)
|
||||||
- `ESP_ERR_NOT_FOUND` - Expander not initialized
|
|
||||||
- `ESP_FAIL` - I2C communication error
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -255,16 +244,15 @@ Reads the state of one GPIO pin of the expander.
|
|||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- `handle` - Pointer to unique PCF8574 handle
|
- `handle` - Pointer to pointer to PCF8574 handle. Must not be NULL
|
||||||
- `gpio` - GPIO number (ZH_PCF8574_GPIO_NUM_P0 ... ZH_PCF8574_GPIO_NUM_P7)
|
- `gpio` - GPIO number (ZH_PCF8574_GPIO_NUM_P0 ... ZH_PCF8574_GPIO_NUM_P7)
|
||||||
- `status` - Pointer to store GPIO status (true - HIGH, false - LOW)
|
- `status` - Pointer to store GPIO status (true - HIGH, false - LOW). Must not be NULL
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
- `ESP_OK` - Success
|
||||||
- `ESP_ERR_INVALID_ARG` - Invalid argument
|
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle, gpio, status or gpio out of range)
|
||||||
- `ESP_ERR_NOT_FOUND` - Expander not initialized
|
- `ESP_ERR_INVALID_STATE` - Expander not initialized
|
||||||
- `ESP_FAIL` - I2C communication error
|
|
||||||
|
|
||||||
**Note:** For input GPIOs, the value will always be 1 (HIGH).
|
**Note:** For input GPIOs, the value will always be 1 (HIGH).
|
||||||
|
|
||||||
@@ -276,16 +264,15 @@ Sets the state of one output GPIO pin of the expander.
|
|||||||
|
|
||||||
**Parameters:**
|
**Parameters:**
|
||||||
|
|
||||||
- `handle` - Pointer to unique PCF8574 handle
|
- `handle` - Pointer to pointer to PCF8574 handle. Must not be NULL
|
||||||
- `gpio` - GPIO number (ZH_PCF8574_GPIO_NUM_P0 ... ZH_PCF8574_GPIO_NUM_P7)
|
- `gpio` - GPIO number (ZH_PCF8574_GPIO_NUM_P0 ... ZH_PCF8574_GPIO_NUM_P7)
|
||||||
- `status` - GPIO status (true - HIGH, false - LOW)
|
- `status` - GPIO status (true - HIGH, false - LOW)
|
||||||
|
|
||||||
**Returns:**
|
**Returns:**
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
- `ESP_OK` - Success
|
||||||
- `ESP_ERR_INVALID_ARG` - Invalid argument
|
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle, gpio, status or gpio out of range)
|
||||||
- `ESP_ERR_NOT_FOUND` - Expander not initialized
|
- `ESP_ERR_INVALID_STATE` - Expander not initialized
|
||||||
- `ESP_FAIL` - I2C communication error
|
|
||||||
|
|
||||||
**Note:** Only output GPIOs are affected.
|
**Note:** Only output GPIOs are affected.
|
||||||
|
|
||||||
@@ -299,25 +286,12 @@ Gets error statistics since last reset.
|
|||||||
|
|
||||||
- Pointer to the statistics structure
|
- Pointer to the statistics structure
|
||||||
|
|
||||||
**Example:**
|
|
||||||
|
|
||||||
```c
|
|
||||||
const zh_pcf8574_stats_t *stats = zh_pcf8574_get_stats();
|
|
||||||
printf("I2C errors: %ld\n", stats->i2c_driver_error);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### zh_pcf8574_reset_stats()
|
### zh_pcf8574_reset_stats()
|
||||||
|
|
||||||
Resets error statistics counters.
|
Resets error statistics counters.
|
||||||
|
|
||||||
**Example:**
|
|
||||||
|
|
||||||
```c
|
|
||||||
zh_pcf8574_reset_stats();
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Usage Examples
|
## Usage Examples
|
||||||
@@ -519,4 +493,4 @@ limitations under the License.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Generated for zh_pcf8574 v2.8.2*
|
"*Generated for zh_pcf8574 v3.0.0*"
|
||||||
+32
-58
@@ -24,13 +24,13 @@
|
|||||||
|
|
||||||
## Возможности
|
## Возможности
|
||||||
|
|
||||||
1. **Поддержка 16 расширителей**: До 16 PCF8574(A) на одной шине I2C (адреса 0x20-0x27 и 0x38-0x3F)
|
- **Поддержка 16 расширителей**: До 16 PCF8574(A) на одной шине I2C (адреса 0x20-0x27 и 0x38-0x3F)
|
||||||
2. **Режимы работы GPIO**: Поддержка выходных и входных режимов для каждого из 8 GPIO
|
- **Режимы работы GPIO**: Поддержка выходных и входных режимов для каждого из 8 GPIO
|
||||||
3. **Генерация прерываний**: Поддержка прерываний от входных GPIO (отрицательный фронт)
|
- **Генерация прерываний**: Поддержка прерываний от входных GPIO (отрицательный фронт)
|
||||||
4. **Статистика ошибок**: Встроенные счетчики ошибок I2C, событий, векторов и переполнения очереди
|
- **Статистика ошибок**: Встроенные счетчики ошибок I2C, событий, векторов и переполнения очереди
|
||||||
5. **Потокобезопасность**: Использует драйвер I2C ESP-IDF и FreeRTOS
|
- **Потокобезопасность**: Использует драйвер I2C ESP-IDF и FreeRTOS
|
||||||
6. **Минимальные накладные расходы**: Низкие требования к памяти и процессору
|
- **Минимальные накладные расходы**: Низкие требования к памяти и процессору
|
||||||
7. **Простой API**: Легкое чтение/запись состояния всех GPIO и отдельных пинов
|
- **Простой API**: Легкое чтение/запись состояния всех GPIO и отдельных пинов
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
i2c_master_bus_handle_t i2c_handle; // Уникальный дескриптор шины I2C
|
i2c_master_bus_handle_t i2c_handle; // Уникальный дескриптор шины I2C
|
||||||
uint32_t i2c_frequency; // Частота I2C расширителя (макс. 100000 Гц)
|
uint32_t i2c_frequency; // Частота I2C расширителя (макс. 100000 Гц)
|
||||||
uint16_t stack_size; // Размер стека задачи обработки прерываний
|
uint32_t stack_size; // Размер стека задачи обработки прерываний
|
||||||
uint8_t task_priority; // Приоритет задачи обработки прерываний
|
uint8_t task_priority; // Приоритет задачи обработки прерываний
|
||||||
uint8_t i2c_address; // Адрес устройства расширителя I2C (0x20-0x27 или 0x38-0x3F)
|
uint8_t i2c_address; // Адрес устройства расширителя I2C (0x20-0x27 или 0x38-0x3F)
|
||||||
bool p0_gpio_work_mode; // Режим работы GPIO P0 (false - output, true - input)
|
bool p0_gpio_work_mode; // Режим работы GPIO P0 (false - output, true - input)
|
||||||
@@ -115,17 +115,11 @@ typedef struct
|
|||||||
### Структура zh_pcf8574_handle_t
|
### Структура zh_pcf8574_handle_t
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef struct
|
typedef struct _zh_pcf8574_handle_t zh_pcf8574_handle_t;
|
||||||
{
|
|
||||||
uint8_t i2c_address; // Адрес I2C расширителя
|
|
||||||
uint8_t gpio_work_mode; // Режимы работы GPIO (биты 0-7)
|
|
||||||
uint8_t gpio_status; // Текущее состояние GPIO (биты 0-7)
|
|
||||||
bool is_initialized; // Флаг инициализации расширителя
|
|
||||||
i2c_master_dev_handle_t dev_handle; // Уникальный дескриптор устройства I2C
|
|
||||||
void *system; // Системный указатель для использования в других компонентах
|
|
||||||
} zh_pcf8574_handle_t;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Непрозрачный дескриптор экземпляра устройства PCF8574. Внутренняя структура минимальна — хранит только I2C-адрес; полное состояние устройства поддерживается во внутреннем векторе.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Структура zh_pcf8574_stats_t
|
### Структура zh_pcf8574_stats_t
|
||||||
@@ -163,15 +157,16 @@ typedef struct
|
|||||||
|
|
||||||
**Параметры:**
|
**Параметры:**
|
||||||
|
|
||||||
- `config` - Указатель на структуру конфигурации инициализации PCF8574
|
- `config` - Указатель на структуру конфигурации инициализации PCF8574. Не должен быть NULL
|
||||||
- `handle` - Указатель на уникальный дескриптор PCF8574
|
- `handle` - Указатель на указатель на дескриптор PCF8574. Должен быть NULL
|
||||||
|
|
||||||
**Возвращает:**
|
**Возвращает:**
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
- `ESP_OK` - Успех
|
||||||
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL config или handle)
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL config или handle)
|
||||||
- `ESP_ERR_INVALID_STATE` - Расширитель уже инициализирован
|
- `ESP_ERR_INVALID_STATE` - Расширитель уже инициализирован
|
||||||
- `ESP_FAIL` - Ошибка инициализации
|
- `ESP_ERR_NO_MEM` - Недостаточно памяти
|
||||||
|
- `ESP_ERR_NOT_SUPPORTED` - Ошибка инициализации I2C
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -181,14 +176,12 @@ typedef struct
|
|||||||
|
|
||||||
**Параметры:**
|
**Параметры:**
|
||||||
|
|
||||||
- `handle` - Указатель на уникальный дескриптор PCF8574
|
- `handle` - Указатель на указатель на дескриптор PCF8574. Не должен быть NULL
|
||||||
|
|
||||||
**Возвращает:**
|
**Возвращает:**
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
- `ESP_OK` - Успех
|
||||||
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или *handle)
|
||||||
- `ESP_ERR_INVALID_STATE` - Расширитель не инициализирован
|
|
||||||
- `ESP_FAIL` - Ошибка деинициализации
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -198,15 +191,14 @@ typedef struct
|
|||||||
|
|
||||||
**Параметры:**
|
**Параметры:**
|
||||||
|
|
||||||
- `handle` - Указатель на уникальный дескриптор PCF8574
|
- `handle` - Указатель на указатель на дескриптор PCF8574. Не должен быть NULL
|
||||||
- `reg` - Указатель для хранения состояния GPIO (биты 0-7)
|
- `reg` - Указатель для хранения состояния GPIO (биты 0-7). Не должен быть NULL
|
||||||
|
|
||||||
**Возвращает:**
|
**Возвращает:**
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
- `ESP_OK` - Успех
|
||||||
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или reg)
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или reg)
|
||||||
- `ESP_ERR_NOT_FOUND` - Расширитель не инициализирован
|
- `ESP_ERR_INVALID_STATE` - Расширитель не инициализирован
|
||||||
- `ESP_FAIL` - Ошибка связи I2C
|
|
||||||
|
|
||||||
**Примечание:** Для входных GPIO всегда будет 1 (HIGH).
|
**Примечание:** Для входных GPIO всегда будет 1 (HIGH).
|
||||||
|
|
||||||
@@ -218,15 +210,14 @@ typedef struct
|
|||||||
|
|
||||||
**Параметры:**
|
**Параметры:**
|
||||||
|
|
||||||
- `handle` - Указатель на уникальный дескриптор PCF8574
|
- `handle` - Указатель на указатель на дескриптор PCF8574. Не должен быть NULL
|
||||||
- `reg` - Состояние GPIO (биты 0-7)
|
- `reg` - Состояние GPIO (биты 0-7)
|
||||||
|
|
||||||
**Возвращает:**
|
**Возвращает:**
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
- `ESP_OK` - Успех
|
||||||
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
|
||||||
- `ESP_ERR_NOT_FOUND` - Расширитель не инициализирован
|
- `ESP_ERR_INVALID_STATE` - Расширитель не инициализирован
|
||||||
- `ESP_FAIL` - Ошибка связи I2C
|
|
||||||
|
|
||||||
**Примечание:** Влияет только на выходные GPIO.
|
**Примечание:** Влияет только на выходные GPIO.
|
||||||
|
|
||||||
@@ -238,14 +229,12 @@ typedef struct
|
|||||||
|
|
||||||
**Параметры:**
|
**Параметры:**
|
||||||
|
|
||||||
- `handle` - Указатель на уникальный дескриптор PCF8574
|
- `handle` - Указатель на указатель на дескриптор PCF8574. Не должен быть NULL
|
||||||
|
|
||||||
**Возвращает:**
|
**Возвращает:**
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
- `ESP_OK` - Успех
|
||||||
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle)
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или *handle)
|
||||||
- `ESP_ERR_NOT_FOUND` - Расширитель не инициализирован
|
|
||||||
- `ESP_FAIL` - Ошибка связи I2C
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -255,16 +244,15 @@ typedef struct
|
|||||||
|
|
||||||
**Параметры:**
|
**Параметры:**
|
||||||
|
|
||||||
- `handle` - Указатель на уникальный дескриптор PCF8574
|
- `handle` - Указатель на указатель на дескриптор PCF8574. Не должен быть NULL
|
||||||
- `gpio` - Номер GPIO (ZH_PCF8574_GPIO_NUM_P0 ... ZH_PCF8574_GPIO_NUM_P7)
|
- `gpio` - Номер GPIO (ZH_PCF8574_GPIO_NUM_P0 ... ZH_PCF8574_GPIO_NUM_P7)
|
||||||
- `status` - Указатель для хранения состояния GPIO (true - HIGH, false - LOW)
|
- `status` - Указатель для хранения состояния GPIO (true - HIGH, false - LOW). Не должен быть NULL
|
||||||
|
|
||||||
**Возвращает:**
|
**Возвращает:**
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
- `ESP_OK` - Успех
|
||||||
- `ESP_ERR_INVALID_ARG` - Неверный аргумент
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, gpio, status или выход gpio за пределы)
|
||||||
- `ESP_ERR_NOT_FOUND` - Расширитель не инициализирован
|
- `ESP_ERR_INVALID_STATE` - Расширитель не инициализирован
|
||||||
- `ESP_FAIL` - Ошибка связи I2C
|
|
||||||
|
|
||||||
**Примечание:** Для входных GPIO всегда будет 1 (HIGH).
|
**Примечание:** Для входных GPIO всегда будет 1 (HIGH).
|
||||||
|
|
||||||
@@ -276,16 +264,15 @@ typedef struct
|
|||||||
|
|
||||||
**Параметры:**
|
**Параметры:**
|
||||||
|
|
||||||
- `handle` - Указатель на уникальный дескриптор PCF8574
|
- `handle` - Указатель на указатель на дескриптор PCF8574. Не должен быть NULL
|
||||||
- `gpio` - Номер GPIO (ZH_PCF8574_GPIO_NUM_P0 ... ZH_PCF8574_GPIO_NUM_P7)
|
- `gpio` - Номер GPIO (ZH_PCF8574_GPIO_NUM_P0 ... ZH_PCF8574_GPIO_NUM_P7)
|
||||||
- `status` - Состояние GPIO (true - HIGH, false - LOW)
|
- `status` - Состояние GPIO (true - HIGH, false - LOW)
|
||||||
|
|
||||||
**Возвращает:**
|
**Возвращает:**
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
- `ESP_OK` - Успех
|
||||||
- `ESP_ERR_INVALID_ARG` - Неверный аргумент
|
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, gpio, status или выход gpio за пределы)
|
||||||
- `ESP_ERR_NOT_FOUND` - Расширитель не инициализирован
|
- `ESP_ERR_INVALID_STATE` - Расширитель не инициализирован
|
||||||
- `ESP_FAIL` - Ошибка связи I2C
|
|
||||||
|
|
||||||
**Примечание:** Влияет только на выходные GPIO.
|
**Примечание:** Влияет только на выходные GPIO.
|
||||||
|
|
||||||
@@ -299,25 +286,12 @@ typedef struct
|
|||||||
|
|
||||||
- Указатель на структуру статистики
|
- Указатель на структуру статистики
|
||||||
|
|
||||||
**Пример:**
|
|
||||||
|
|
||||||
```c
|
|
||||||
const zh_pcf8574_stats_t *stats = zh_pcf8574_get_stats();
|
|
||||||
printf("Ошибки I2C: %ld\n", stats->i2c_driver_error);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### zh_pcf8574_reset_stats()
|
### zh_pcf8574_reset_stats()
|
||||||
|
|
||||||
Сбрасывает счетчики статистики ошибок.
|
Сбрасывает счетчики статистики ошибок.
|
||||||
|
|
||||||
**Пример:**
|
|
||||||
|
|
||||||
```c
|
|
||||||
zh_pcf8574_reset_stats();
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Примеры использования
|
## Примеры использования
|
||||||
@@ -519,4 +493,4 @@ void app_main(void)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Сгенерировано для zh_pcf8574 v2.8.2*
|
"*Сгенерировано для zh_pcf8574 v3.0.0*"
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
description: ESP32 ESP-IDF component for PCF8574(A) 8-bit I/O expander
|
description: ESP32 ESP-IDF component for PCF8574(A) 8-bit I/O expander
|
||||||
url: https://github.com/aZholtikov/zh_pcf8574
|
url: https://github.com/aZholtikov/zh_pcf8574
|
||||||
version: "2.8.2"
|
version: "3.0.0"
|
||||||
license: "Apache-2.0"
|
license: "Apache-2.0"
|
||||||
maintainers:
|
maintainers:
|
||||||
- "Alexey Zholtikov <alexey.zholtikov@yandex.ru>"
|
- "Alexey Zholtikov <alexey.zholtikov@yandex.ru>"
|
||||||
|
|||||||
+149
-105
@@ -1,5 +1,22 @@
|
|||||||
/**
|
/**
|
||||||
* @file zh_pcf8574.h
|
* @file zh_pcf8574.h
|
||||||
|
*
|
||||||
|
* @brief Header file for PCF8574 I2C GPIO expander driver.
|
||||||
|
*
|
||||||
|
* This module provides a driver for the PCF8574 8-bit I2C GPIO
|
||||||
|
* expander, supporting both input and output operations, interrupt
|
||||||
|
* handling, and configuration of individual pin directions.
|
||||||
|
*
|
||||||
|
* Key features:
|
||||||
|
* - I2C communication via esp-idf i2c_master driver
|
||||||
|
* - Configurable GPIO direction for each pin (P0-P7)
|
||||||
|
* - Interrupt handling with GPIO level detection
|
||||||
|
* - Event-based architecture using esp_event framework
|
||||||
|
* - Statistics tracking for debugging and monitoring
|
||||||
|
*
|
||||||
|
* @note The driver creates an internal task for interrupt processing.
|
||||||
|
* @note Requires ESP-IDF v5.0+ with I2C master driver.
|
||||||
|
* @note Enable GPIO_CTRL_FUNC_IN_IRAM, I2C_ISR_IRAM_SAFE and I2C_MASTER_ISR_HANDLER_IN_IRAM in menuconfig.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -13,14 +30,11 @@
|
|||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "zh_vector.h"
|
#include "zh_vector.h"
|
||||||
|
|
||||||
#define ZH_PCF8574_GPIO_OUTPUT false
|
#define ZH_PCF8574_GPIO_OUTPUT false /*!< Configures GPIO pin as output */
|
||||||
#define ZH_PCF8574_GPIO_INPUT true
|
#define ZH_PCF8574_GPIO_INPUT true /*!< Configures GPIO pin as input */
|
||||||
#define ZH_PCF8574_GPIO_LOW false
|
#define ZH_PCF8574_GPIO_LOW false /*!< Logical low level */
|
||||||
#define ZH_PCF8574_GPIO_HIGH true
|
#define ZH_PCF8574_GPIO_HIGH true /*!< Logical high level */
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PCF8574 expander initial default values.
|
|
||||||
*/
|
|
||||||
#define ZH_PCF8574_INIT_CONFIG_DEFAULT() \
|
#define ZH_PCF8574_INIT_CONFIG_DEFAULT() \
|
||||||
{ \
|
{ \
|
||||||
.task_priority = 1, \
|
.task_priority = 1, \
|
||||||
@@ -42,178 +56,208 @@ extern "C"
|
|||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern TaskHandle_t zh_pcf8574; /*!< Unique task handle. */
|
extern TaskHandle_t zh_pcf8574; /*!< Handle of the internal PCF8574 processing task. */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration of PCF8574 expander GPIO.
|
* @brief Opaque handle for PCF8574 device instance.
|
||||||
|
*
|
||||||
|
* Forward declaration of the internal device handle structure.
|
||||||
|
* Used by all public API functions to reference a specific
|
||||||
|
* PCF8574 device instance.
|
||||||
|
*/
|
||||||
|
typedef struct _zh_pcf8574_handle_t zh_pcf8574_handle_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PCF8574 GPIO pin numbering enumeration.
|
||||||
|
*
|
||||||
|
* Defines the pin numbering scheme for accessing individual
|
||||||
|
* GPIO pins (P0-P7) of the PCF8574 device.
|
||||||
*/
|
*/
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
ZH_PCF8574_GPIO_NUM_P0 = 0,
|
ZH_PCF8574_GPIO_NUM_P0 = 0, /*!< GPIO pin P0 */
|
||||||
ZH_PCF8574_GPIO_NUM_P1,
|
ZH_PCF8574_GPIO_NUM_P1, /*!< GPIO pin P1 */
|
||||||
ZH_PCF8574_GPIO_NUM_P2,
|
ZH_PCF8574_GPIO_NUM_P2, /*!< GPIO pin P2 */
|
||||||
ZH_PCF8574_GPIO_NUM_P3,
|
ZH_PCF8574_GPIO_NUM_P3, /*!< GPIO pin P3 */
|
||||||
ZH_PCF8574_GPIO_NUM_P4,
|
ZH_PCF8574_GPIO_NUM_P4, /*!< GPIO pin P4 */
|
||||||
ZH_PCF8574_GPIO_NUM_P5,
|
ZH_PCF8574_GPIO_NUM_P5, /*!< GPIO pin P5 */
|
||||||
ZH_PCF8574_GPIO_NUM_P6,
|
ZH_PCF8574_GPIO_NUM_P6, /*!< GPIO pin P6 */
|
||||||
ZH_PCF8574_GPIO_NUM_P7,
|
ZH_PCF8574_GPIO_NUM_P7, /*!< GPIO pin P7 */
|
||||||
ZH_PCF8574_GPIO_NUM_MAX
|
ZH_PCF8574_GPIO_NUM_MAX /*!< Maximum number of GPIO pins */
|
||||||
} zh_pcf8574_gpio_num_t;
|
} zh_pcf8574_gpio_num_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure for initial initialization of PCF8574 expander.
|
* @brief Initialization configuration structure for PCF8574 device.
|
||||||
|
*
|
||||||
|
* Defines all parameters required to initialize and configure
|
||||||
|
* the PCF8574 I2C GPIO expander, including I2C settings,
|
||||||
|
* individual GPIO direction modes, and interrupt configuration.
|
||||||
|
*
|
||||||
|
* @note The I2C bus must be initialized before calling zh_pcf8574_init().
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
i2c_master_bus_handle_t i2c_handle; /*!< Unique I2C bus handle. @attention Must be same for all PCF8574 expanders. */
|
i2c_master_bus_handle_t i2c_handle; /*!< I2C bus handle for communication */
|
||||||
uint32_t i2c_frequency; /*!< Expander I2C frequency. */
|
uint32_t i2c_frequency; /*!< I2C clock frequency in Hz */
|
||||||
uint16_t stack_size; /*!< Stack size for task for the PCF8574 expander isr processing processing. @note The minimum size is configMINIMAL_STACK_SIZE. */
|
uint32_t stack_size; /*!< Stack size for the internal task */
|
||||||
uint8_t task_priority; /*!< Task priority for the PCF8574 expander isr processing. @note Minimum value is 1. */
|
uint8_t task_priority; /*!< Priority of the internal task */
|
||||||
uint8_t i2c_address; /*!< Expander I2C address. */
|
uint8_t i2c_address; /*!< 7-bit I2C address of the PCF8574 device */
|
||||||
bool p0_gpio_work_mode; /*!< Expander GPIO PO work mode. */
|
bool p0_gpio_work_mode; /*!< Operating mode for GPIO P0 (input/output) */
|
||||||
bool p1_gpio_work_mode; /*!< Expander GPIO P1 work mode. */
|
bool p1_gpio_work_mode; /*!< Operating mode for GPIO P1 (input/output) */
|
||||||
bool p2_gpio_work_mode; /*!< Expander GPIO P2 work mode. */
|
bool p2_gpio_work_mode; /*!< Operating mode for GPIO P2 (input/output) */
|
||||||
bool p3_gpio_work_mode; /*!< Expander GPIO P3 work mode. */
|
bool p3_gpio_work_mode; /*!< Operating mode for GPIO P3 (input/output) */
|
||||||
bool p4_gpio_work_mode; /*!< Expander GPIO P4 work mode. */
|
bool p4_gpio_work_mode; /*!< Operating mode for GPIO P4 (input/output) */
|
||||||
bool p5_gpio_work_mode; /*!< Expander GPIO P5 work mode. */
|
bool p5_gpio_work_mode; /*!< Operating mode for GPIO P5 (input/output) */
|
||||||
bool p6_gpio_work_mode; /*!< Expander GPIO P6 work mode. */
|
bool p6_gpio_work_mode; /*!< Operating mode for GPIO P6 (input/output) */
|
||||||
bool p7_gpio_work_mode; /*!< Expander GPIO P7 work mode. */
|
bool p7_gpio_work_mode; /*!< Operating mode for GPIO P7 (input/output) */
|
||||||
gpio_num_t interrupt_gpio; /*!< Interrupt GPIO. @attention Must be same for all PCF8574 expanders. */
|
gpio_num_t interrupt_gpio; /*!< GPIO pin for interrupt detection (GPIO_NUM_MAX if not used) */
|
||||||
} zh_pcf8574_init_config_t;
|
} zh_pcf8574_init_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PCF8574 expander handle.
|
* @brief Statistics structure for error tracking and diagnostics.
|
||||||
|
*
|
||||||
|
* Maintains counters for various error types and monitoring data
|
||||||
|
* to assist with debugging and system health monitoring.
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t i2c_address; /*!< Expander I2C address. */
|
uint32_t i2c_driver_error; /*!< Counter of I2C driver errors */
|
||||||
uint8_t gpio_work_mode; /*!< Expander GPIO's work mode. */
|
uint32_t event_post_error; /*!< Counter of event posting errors */
|
||||||
uint8_t gpio_status; /*!< Expander GPIO's status. */
|
uint32_t vector_error; /*!< Counter of vector operation errors */
|
||||||
bool is_initialized; /*!< Expander initialization flag. */
|
uint32_t queue_overflow_error; /*!< Counter of queue overflow errors */
|
||||||
i2c_master_dev_handle_t dev_handle; /*!< Unique I2C device handle. */
|
uint32_t min_stack_size; /*!< Minimum remaining stack size recorded */
|
||||||
void *system; /*!< System pointer for use in another components. */
|
|
||||||
} zh_pcf8574_handle_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Structure for error statistics storage.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t i2c_driver_error; /*!< Number of i2c driver error. */
|
|
||||||
uint32_t event_post_error; /*!< Number of event post error. */
|
|
||||||
uint32_t vector_error; /*!< Number of vector error. */
|
|
||||||
uint32_t queue_overflow_error; /*!< Number of queue overflow error. */
|
|
||||||
uint32_t min_stack_size; /*!< Minimum free stack size. */
|
|
||||||
} zh_pcf8574_stats_t;
|
} zh_pcf8574_stats_t;
|
||||||
|
|
||||||
ESP_EVENT_DECLARE_BASE(ZH_PCF8574);
|
ESP_EVENT_DECLARE_BASE(ZH_PCF8574);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure for sending data to the event handler when cause an interrupt.
|
* @brief Event structure for GPIO interrupt events.
|
||||||
*
|
*
|
||||||
* @note Should be used with ZH_PCF8574 event base.
|
* Passed as event data when a GPIO level change is detected
|
||||||
|
* on any input pin of the PCF8574 device.
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint64_t interrupt_time; /*!< Interrupt time. */
|
uint64_t interrupt_time; /*!< Timestamp of the interrupt occurrence */
|
||||||
zh_pcf8574_gpio_num_t gpio_number; /*!< The GPIO that caused the interrupt. */
|
zh_pcf8574_gpio_num_t gpio_number; /*!< GPIO pin that triggered the interrupt */
|
||||||
uint8_t i2c_address; /*!< The i2c address of PCF8574 expander that caused the interrupt. */
|
uint8_t i2c_address; /*!< I2C address of the device that generated the interrupt */
|
||||||
bool gpio_level; /*!< The GPIO level that caused the interrupt. */
|
bool gpio_level; /*!< Current level of the GPIO pin */
|
||||||
} zh_pcf8574_event_on_isr_t;
|
} zh_pcf8574_event_on_isr_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize PCF8574 expander.
|
* @brief Initialize PCF8574 device.
|
||||||
*
|
*
|
||||||
* @param[in] config Pointer to PCF8574 initialized configuration structure. Can point to a temporary variable.
|
* Creates an internal task for interrupt processing and configures
|
||||||
* @param[out] handle Pointer to unique PCF8574 handle.
|
* the I2C communication with the PCF8574 device according to the
|
||||||
|
* provided configuration.
|
||||||
*
|
*
|
||||||
* @attention I2C driver must be initialized first.
|
* @param[in] config Pointer to initialization configuration structure (must not be NULL)
|
||||||
|
* @param[out] handle Pointer to receive the device handle (must be NULL)
|
||||||
*
|
*
|
||||||
* @note Before initialize the expander recommend initialize zh_pcf8574_init_config_t structure with default values.
|
* @return ESP_OK on success
|
||||||
*
|
* @return ESP_ERR_INVALID_ARG if config parameter is NULL
|
||||||
* @code zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT() @endcode
|
* @return ESP_ERR_NO_MEM if memory allocation fails
|
||||||
*
|
* @return ESP_ERR_NOT_SUPPORTED if I2C initialization fails
|
||||||
* @return ESP_OK if success or an error code otherwise.
|
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_pcf8574_init(const zh_pcf8574_init_config_t *config, zh_pcf8574_handle_t *handle);
|
esp_err_t zh_pcf8574_init(const zh_pcf8574_init_config_t *config, zh_pcf8574_handle_t **handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deinitialize PCF8574 expander.
|
* @brief Deinitialize PCF8574 device.
|
||||||
*
|
*
|
||||||
* @param[in] handle Pointer to unique PCF8574 handle.
|
* Deletes the internal task and releases all allocated resources.
|
||||||
*
|
*
|
||||||
* @return ESP_OK if success or an error code otherwise.
|
* @param[in,out] handle Pointer to the device handle (must not be NULL)
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_ERR_INVALID_ARG if handle parameter is NULL
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_pcf8574_deinit(zh_pcf8574_handle_t *handle);
|
esp_err_t zh_pcf8574_deinit(zh_pcf8574_handle_t **handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read PCF8574 all GPIO's status.
|
* @brief Read data from PCF8574 device.
|
||||||
*
|
*
|
||||||
* @param[in] handle Pointer to unique PCF8574 handle.
|
* Reads a byte from the PCF8574 input ports via I2C communication.
|
||||||
* @param[out] reg Pointer to GPIO's status.
|
|
||||||
*
|
*
|
||||||
* @note For input GPIO's status will be 1 (HIGH) always.
|
* @param[in,out] handle Pointer to the device handle (must not be NULL)
|
||||||
|
* @param[out] reg Pointer to receive the read value (must not be NULL)
|
||||||
*
|
*
|
||||||
* @return ESP_OK if success or an error code otherwise.
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_ERR_INVALID_ARG if handle or reg is NULL
|
||||||
|
* @return ESP_ERR_INVALID_STATE if device is not initialized
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_pcf8574_read(zh_pcf8574_handle_t *handle, uint8_t *reg);
|
esp_err_t zh_pcf8574_read(zh_pcf8574_handle_t **handle, uint8_t *reg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set PCF8574 all GPIO's status.
|
* @brief Write data to PCF8574 device.
|
||||||
*
|
*
|
||||||
* @param[in] handle Pointer to unique PCF8574 handle.
|
* Writes a byte to the PCF8574 output ports via I2C communication.
|
||||||
* @param[in] reg GPIO's status.
|
|
||||||
*
|
*
|
||||||
* @attention Only the GPIO outputs are affected.
|
* @param[in,out] handle Pointer to the device handle (must not be NULL)
|
||||||
|
* @param[in] reg Value to write to the output ports
|
||||||
*
|
*
|
||||||
* @return ESP_OK if success or an error code otherwise.
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_ERR_INVALID_ARG if handle is NULL
|
||||||
|
* @return ESP_ERR_INVALID_STATE if device is not initialized
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_pcf8574_write(zh_pcf8574_handle_t *handle, uint8_t reg);
|
esp_err_t zh_pcf8574_write(zh_pcf8574_handle_t **handle, uint8_t reg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reset (set to initial) PCF8574 all GPIO's.
|
* @brief Reset PCF8574 device.
|
||||||
*
|
*
|
||||||
* @param[in] handle Pointer to unique PCF8574 handle.
|
* Resets the device to its default state, clearing all outputs
|
||||||
|
* and reinitializing internal structures.
|
||||||
*
|
*
|
||||||
* @return ESP_OK if success or an error code otherwise.
|
* @param[in,out] handle Pointer to the device handle (must not be NULL)
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_ERR_INVALID_ARG if handle is NULL
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_pcf8574_reset(zh_pcf8574_handle_t *handle);
|
esp_err_t zh_pcf8574_reset(zh_pcf8574_handle_t **handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read PCF8574 GPIO status.
|
* @brief Read the state of a specific GPIO pin.
|
||||||
*
|
*
|
||||||
* @param[in] handle Pointer to unique PCF8574 handle.
|
* Reads the current logical level of a specified GPIO pin.
|
||||||
* @param[in] gpio GPIO number.
|
|
||||||
* @param[out] status Pointer to GPIO status (true - HIGH, false - LOW).
|
|
||||||
*
|
*
|
||||||
* @note For input GPIO's status will be 1 (HIGH) always.
|
* @param[in,out] handle Pointer to the device handle (must not be NULL)
|
||||||
|
* @param[in] gpio GPIO pin number to read
|
||||||
|
* @param[out] status Pointer to receive the pin state (true = high, false = low)
|
||||||
*
|
*
|
||||||
* @return ESP_OK if success or an error code otherwise.
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_ERR_INVALID_ARG if handle, gpio, or status is NULL
|
||||||
|
* @return ESP_ERR_INVALID_ARG if gpio number exceeds ZH_PCF8574_GPIO_NUM_MAX
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_pcf8574_read_gpio(zh_pcf8574_handle_t *handle, zh_pcf8574_gpio_num_t gpio, bool *status);
|
esp_err_t zh_pcf8574_read_gpio(zh_pcf8574_handle_t **handle, zh_pcf8574_gpio_num_t gpio, bool *status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set PCF8574 GPIO status.
|
* @brief Write state to a specific GPIO pin.
|
||||||
*
|
*
|
||||||
* @param[in] handle Pointer to unique PCF8574 handle.
|
* Sets the logical level of a specified GPIO pin configured as output.
|
||||||
* @param[in] gpio GPIO number.
|
|
||||||
* @param[in] status GPIO status (true - HIGH, false - LOW).
|
|
||||||
*
|
*
|
||||||
* @attention Only the GPIO output is affected.
|
* @param[in,out] handle Pointer to the device handle (must not be NULL)
|
||||||
|
* @param[in] gpio GPIO pin number to write
|
||||||
|
* @param[in] status Logical level to set (true = high, false = low)
|
||||||
*
|
*
|
||||||
* @return ESP_OK if success or an error code otherwise.
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_ERR_INVALID_ARG if handle, gpio, or status is NULL
|
||||||
|
* @return ESP_ERR_INVALID_ARG if gpio number exceeds ZH_PCF8574_GPIO_NUM_MAX
|
||||||
*/
|
*/
|
||||||
esp_err_t zh_pcf8574_write_gpio(zh_pcf8574_handle_t *handle, zh_pcf8574_gpio_num_t gpio, bool status);
|
esp_err_t zh_pcf8574_write_gpio(zh_pcf8574_handle_t **handle, zh_pcf8574_gpio_num_t gpio, bool status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get error statistics.
|
* @brief Get device statistics.
|
||||||
*
|
*
|
||||||
* @return Pointer to the statistics structure.
|
* Returns a pointer to the structure containing error counters
|
||||||
|
* and monitoring data for debugging and diagnostics.
|
||||||
|
*
|
||||||
|
* @return Pointer to the statistics structure (valid until reset)
|
||||||
*/
|
*/
|
||||||
const zh_pcf8574_stats_t *zh_pcf8574_get_stats(void);
|
const zh_pcf8574_stats_t *zh_pcf8574_get_stats(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reset error statistics.
|
* @brief Reset device statistics.
|
||||||
|
*
|
||||||
|
* Clears all error counters and monitoring data.
|
||||||
*/
|
*/
|
||||||
void zh_pcf8574_reset_stats(void);
|
void zh_pcf8574_reset_stats(void);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
2.8.2
|
3.0.0
|
||||||
+277
-176
@@ -13,178 +13,322 @@ static const char *TAG = "zh_pcf8574";
|
|||||||
return err; \
|
return err; \
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskHandle_t zh_pcf8574 = NULL;
|
#define ZH_ERROR_CHECK_CONT(cond, cleanup, msg, ...) \
|
||||||
static SemaphoreHandle_t _interrupt_semaphore = NULL;
|
if (!(cond)) \
|
||||||
|
{ \
|
||||||
|
ZH_LOGE(msg, ESP_FAIL, ##__VA_ARGS__); \
|
||||||
|
cleanup; \
|
||||||
|
continue; \
|
||||||
|
}
|
||||||
|
|
||||||
volatile static gpio_num_t _interrupt_gpio = GPIO_NUM_MAX;
|
/**
|
||||||
volatile static uint8_t _i2c_matrix[16] = {0};
|
* @brief Internal handle structure for PCF8574 device.
|
||||||
static const uint8_t _gpio_matrix[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
|
*
|
||||||
static zh_pcf8574_stats_t _stats = {0};
|
* Minimal handle storing the I2C address of the device instance.
|
||||||
|
* The full state is maintained in the internal vector.
|
||||||
|
*/
|
||||||
|
struct _zh_pcf8574_handle_t
|
||||||
|
{
|
||||||
|
uint8_t i2c_address; /*!< I2C address of this device instance */
|
||||||
|
};
|
||||||
|
|
||||||
static zh_vector_t *_vector = NULL;
|
/**
|
||||||
|
* @brief Internal structure for per-device data stored in the vector.
|
||||||
|
*
|
||||||
|
* Holds device-specific state including I2C address, GPIO configuration
|
||||||
|
* mask, current status, and I2C device handle.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t i2c_address; /*!< I2C address of the device */
|
||||||
|
uint8_t gpio_work_mode; /*!< GPIO direction mask (1=input, 0=output) */
|
||||||
|
uint8_t gpio_status; /*!< Current GPIO port state */
|
||||||
|
i2c_master_dev_handle_t dev_handle; /*!< I2C device handle for communication */
|
||||||
|
} _zh_pcf8574_vector_data_t;
|
||||||
|
|
||||||
|
TaskHandle_t zh_pcf8574 = NULL; /*!< Handle of the internal PCF8574 processing task */
|
||||||
|
static SemaphoreHandle_t _interrupt_semaphore = NULL; /*!< Semaphore for interrupt-to-task synchronization */
|
||||||
|
|
||||||
|
volatile static gpio_num_t _interrupt_gpio = GPIO_NUM_MAX; /*!< GPIO pin used for interrupt detection */
|
||||||
|
static const uint8_t _gpio_matrix[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; /*!< Bit mask for each GPIO pin (P0-P7) */
|
||||||
|
static zh_pcf8574_stats_t _stats = {0}; /*!< Statistics structure for error tracking */
|
||||||
|
|
||||||
|
static zh_vector_t *_vector = NULL; /*!< Vector storing PCF8574 device data */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validate initialization configuration.
|
||||||
|
*
|
||||||
|
* Checks all configuration parameters for validity, including I2C address range,
|
||||||
|
* frequency limits, task settings, and checks for address conflicts.
|
||||||
|
*
|
||||||
|
* @param config Pointer to initialization configuration structure
|
||||||
|
*
|
||||||
|
* @return ESP_OK if configuration is valid
|
||||||
|
* @return ESP_ERR_INVALID_ARG if any parameter is invalid
|
||||||
|
*/
|
||||||
static esp_err_t _zh_pcf8574_validate_config(const zh_pcf8574_init_config_t *config);
|
static esp_err_t _zh_pcf8574_validate_config(const zh_pcf8574_init_config_t *config);
|
||||||
static esp_err_t _zh_pcf8574_gpio_init(const zh_pcf8574_init_config_t *config, zh_pcf8574_handle_t *handle);
|
|
||||||
static esp_err_t _zh_pcf8574_i2c_init(const zh_pcf8574_init_config_t *config, zh_pcf8574_handle_t *handle);
|
/**
|
||||||
static esp_err_t _zh_pcf8574_resources_init(const zh_pcf8574_init_config_t *config);
|
* @brief Configure interrupt GPIO pin.
|
||||||
|
*
|
||||||
|
* Sets up the GPIO pin for interrupt detection with negative edge trigger,
|
||||||
|
* pull-up enabled, and installs the ISR handler.
|
||||||
|
*
|
||||||
|
* @param config Pointer to initialization configuration with interrupt_gpio set
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_FAIL on configuration or ISR installation failure
|
||||||
|
*/
|
||||||
|
static esp_err_t _zh_pcf8574_gpio_init(const zh_pcf8574_init_config_t *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize I2C communication with PCF8574 device.
|
||||||
|
*
|
||||||
|
* Adds the device to the I2C bus, probes for device presence, configures
|
||||||
|
* GPIO directions, and performs initial read/write verification.
|
||||||
|
*
|
||||||
|
* @param config Pointer to initialization configuration
|
||||||
|
* @param vector_data Pointer to receive initialized vector data
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_FAIL on I2C communication or device probing failure
|
||||||
|
*/
|
||||||
|
static esp_err_t _zh_pcf8574_i2c_init(const zh_pcf8574_init_config_t *config, _zh_pcf8574_vector_data_t *vector_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize interrupt resources.
|
||||||
|
*
|
||||||
|
* Creates a binary semaphore used for interrupt-to-task synchronization.
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_ERR_NO_MEM if semaphore creation fails
|
||||||
|
*/
|
||||||
|
static esp_err_t _zh_pcf8574_resources_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create interrupt processing task.
|
||||||
|
*
|
||||||
|
* Creates a FreeRTOS task that processes interrupts from all connected
|
||||||
|
* PCF8574 devices and posts corresponding events.
|
||||||
|
*
|
||||||
|
* @param config Pointer to initialization configuration
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_FAIL if task creation fails
|
||||||
|
*/
|
||||||
static esp_err_t _zh_pcf8574_task_init(const zh_pcf8574_init_config_t *config);
|
static esp_err_t _zh_pcf8574_task_init(const zh_pcf8574_init_config_t *config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ISR handler for GPIO interrupt.
|
||||||
|
*
|
||||||
|
* Called when an interrupt occurs on the configured GPIO pin.
|
||||||
|
* Posts a signal to the semaphore to wake up the processing task.
|
||||||
|
* Executed in ISR context (IRAM).
|
||||||
|
*
|
||||||
|
* @param arg Unused callback argument
|
||||||
|
*/
|
||||||
static void _zh_pcf8574_isr_handler(void *arg);
|
static void _zh_pcf8574_isr_handler(void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interrupt processing task.
|
||||||
|
*
|
||||||
|
* Waits for interrupt signals, reads all PCF8574 devices, detects
|
||||||
|
* level changes on input pins, and posts events for each change.
|
||||||
|
* Monitors stack usage continuously.
|
||||||
|
*
|
||||||
|
* @param pvParameter Unused task parameter
|
||||||
|
*/
|
||||||
static void _zh_pcf8574_isr_processing_task(void *pvParameter);
|
static void _zh_pcf8574_isr_processing_task(void *pvParameter);
|
||||||
static esp_err_t _zh_pcf8574_read_register(zh_pcf8574_handle_t *handle, uint8_t *reg);
|
|
||||||
static esp_err_t _zh_pcf8574_write_register(zh_pcf8574_handle_t *handle, uint8_t reg);
|
/**
|
||||||
|
* @brief Read register from PCF8574 device via I2C.
|
||||||
|
*
|
||||||
|
* Reads the current GPIO port state from the device and updates
|
||||||
|
* the internal status in vector_data.
|
||||||
|
*
|
||||||
|
* @param vector_data Pointer to vector data containing device handle
|
||||||
|
* @param reg Pointer to receive the register value
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_FAIL on I2C communication failure
|
||||||
|
*/
|
||||||
|
static esp_err_t _zh_pcf8574_read_register(_zh_pcf8574_vector_data_t *vector_data, uint8_t *reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write register to PCF8574 device via I2C.
|
||||||
|
*
|
||||||
|
* Writes a value to the GPIO port output register and updates
|
||||||
|
* the internal status in vector_data.
|
||||||
|
*
|
||||||
|
* @param vector_data Pointer to vector data containing device handle
|
||||||
|
* @param reg Value to write to the register
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success
|
||||||
|
* @return ESP_FAIL on I2C communication failure
|
||||||
|
*/
|
||||||
|
static esp_err_t _zh_pcf8574_write_register(_zh_pcf8574_vector_data_t *vector_data, uint8_t reg);
|
||||||
|
|
||||||
ESP_EVENT_DEFINE_BASE(ZH_PCF8574);
|
ESP_EVENT_DEFINE_BASE(ZH_PCF8574);
|
||||||
|
|
||||||
esp_err_t zh_pcf8574_init(const zh_pcf8574_init_config_t *config, zh_pcf8574_handle_t *handle) // -V2008
|
esp_err_t zh_pcf8574_init(const zh_pcf8574_init_config_t *config, zh_pcf8574_handle_t **handle) // -V2008
|
||||||
{
|
{
|
||||||
ZH_LOGI("PCF8574 initialization started.");
|
ZH_LOGI("PCF8574 initialization started.");
|
||||||
ZH_ERROR_CHECK(config != NULL && handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 initialization failed. Invalid argument.");
|
ZH_ERROR_CHECK(config != NULL && handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 initialization failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(handle->is_initialized == false, ESP_ERR_INVALID_STATE, NULL, "PCF8574 initialization failed. PCF8574 is already initialized.");
|
ZH_ERROR_CHECK(*handle == NULL, ESP_ERR_INVALID_STATE, NULL, "PCF8574 initialization failed. PCF8574 is already initialized.");
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_validate_config(config) == ESP_OK, ESP_FAIL, NULL, "PCF8574 initialization failed. Initial configuration check failed.");
|
ZH_ERROR_CHECK(_zh_pcf8574_validate_config(config) == ESP_OK, ESP_FAIL, NULL, "PCF8574 initialization failed. Invalid config.");
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_i2c_init(config, handle) == ESP_OK, ESP_FAIL, NULL, "PCF8574 initialization failed. Failed to add I2C device.");
|
if (_vector == NULL)
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_write_register(handle, handle->gpio_work_mode) == ESP_OK, ESP_FAIL,
|
|
||||||
ZH_ERROR_CHECK(i2c_master_bus_rm_device(handle->dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed."), "PCF8574 initialization failed. Failed extender initial GPIO setup.");
|
|
||||||
if (config->interrupt_gpio < GPIO_NUM_MAX && handle->gpio_work_mode != 0)
|
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_gpio_init(config, handle) == ESP_OK, ESP_FAIL,
|
ZH_ERROR_CHECK(zh_vector_init(&_vector, sizeof(_zh_pcf8574_vector_data_t)) == ESP_OK, ESP_FAIL, NULL, "PCF8574 initialization failed. Failed to create vector.");
|
||||||
ZH_ERROR_CHECK(i2c_master_bus_rm_device(handle->dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed."), "PCF8574 initialization failed. Interrupt GPIO initialization failed.");
|
}
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_resources_init(config) == ESP_OK, ESP_FAIL,
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
ZH_ERROR_CHECK(i2c_master_bus_rm_device(handle->dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.");
|
ZH_ERROR_CHECK(_zh_pcf8574_i2c_init(config, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 initialization failed. Failed to add I2C device.");
|
||||||
ZH_ERROR_CHECK(gpio_isr_handler_remove(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Remove GPIO isr handler failed.");
|
*handle = heap_caps_calloc(1, sizeof(zh_pcf8574_handle_t), MALLOC_CAP_8BIT);
|
||||||
ZH_ERROR_CHECK(gpio_reset_pin(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset GPIO failed.");
|
ZH_ERROR_CHECK(*handle != NULL, ESP_ERR_NO_MEM,
|
||||||
ZH_ERROR_CHECK(zh_vector_free(&_vector) == ESP_OK, ESP_FAIL, NULL, "Free vector failed."), "PCF8574 initialization failed. Resources initialization failed.");
|
{ZH_ERROR_CHECK(i2c_master_bus_rm_device(vector_data.dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.")}, "PCF8574 initialization failed. Failed to allocate PCF8574 handle.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_push_back(&_vector, &vector_data) == ESP_OK, ESP_FAIL,
|
||||||
|
{ZH_ERROR_CHECK(i2c_master_bus_rm_device(vector_data.dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.")};
|
||||||
|
heap_caps_free(*handle); *handle = NULL, "PCF8574 initialization failed. Failed to add vector data.");
|
||||||
|
if (_interrupt_gpio == GPIO_NUM_MAX && config->interrupt_gpio < GPIO_NUM_MAX && vector_data.gpio_work_mode != 0)
|
||||||
|
{
|
||||||
|
ZH_ERROR_CHECK(_zh_pcf8574_gpio_init(config) == ESP_OK, ESP_FAIL,
|
||||||
|
{ZH_ERROR_CHECK(i2c_master_bus_rm_device(vector_data.dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.")};
|
||||||
|
zh_vector_delete_back(&_vector); heap_caps_free(*handle); *handle = NULL, "PCF8574 initialization failed. Interrupt GPIO initialization failed.");
|
||||||
|
ZH_ERROR_CHECK(_zh_pcf8574_resources_init() == ESP_OK, ESP_FAIL,
|
||||||
|
{ZH_ERROR_CHECK(i2c_master_bus_rm_device(vector_data.dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.")};
|
||||||
|
{ZH_ERROR_CHECK(gpio_isr_handler_remove(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Remove GPIO isr handler failed.")};
|
||||||
|
{ZH_ERROR_CHECK(gpio_reset_pin(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset GPIO failed.")};
|
||||||
|
zh_vector_delete_back(&_vector); heap_caps_free(*handle); *handle = NULL, "PCF8574 initialization failed. Resources initialization failed.");
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_task_init(config) == ESP_OK, ESP_FAIL,
|
ZH_ERROR_CHECK(_zh_pcf8574_task_init(config) == ESP_OK, ESP_FAIL,
|
||||||
ZH_ERROR_CHECK(i2c_master_bus_rm_device(handle->dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.");
|
{ZH_ERROR_CHECK(i2c_master_bus_rm_device(vector_data.dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.")};
|
||||||
ZH_ERROR_CHECK(gpio_isr_handler_remove(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Remove gpio isr handler failed.");
|
{ZH_ERROR_CHECK(gpio_isr_handler_remove(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Remove gpio isr handler failed.")};
|
||||||
ZH_ERROR_CHECK(gpio_reset_pin(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset gpio failed.");
|
{ZH_ERROR_CHECK(gpio_reset_pin(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset gpio failed.")};
|
||||||
ZH_ERROR_CHECK(zh_vector_free(&_vector) == ESP_OK, ESP_FAIL, NULL, "Free vector failed.");
|
vSemaphoreDelete(_interrupt_semaphore); _interrupt_semaphore = NULL; zh_vector_delete_back(&_vector); heap_caps_free(*handle); *handle = NULL, "PCF8574 initialization failed. Task initialization failed.");
|
||||||
vSemaphoreDelete(_interrupt_semaphore), "PCF8574 initialization failed. Task initialization failed.");
|
|
||||||
_interrupt_gpio = config->interrupt_gpio;
|
_interrupt_gpio = config->interrupt_gpio;
|
||||||
}
|
}
|
||||||
if (_stats.min_stack_size == 0)
|
if (_stats.min_stack_size == 0)
|
||||||
{
|
{
|
||||||
_stats.min_stack_size = config->stack_size;
|
_stats.min_stack_size = config->stack_size;
|
||||||
}
|
}
|
||||||
handle->is_initialized = true;
|
(*handle)->i2c_address = config->i2c_address;
|
||||||
for (uint8_t i = 0; i < sizeof(_i2c_matrix); ++i)
|
|
||||||
{
|
|
||||||
if (_i2c_matrix[i] == 0)
|
|
||||||
{
|
|
||||||
_i2c_matrix[i] = handle->i2c_address;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ZH_LOGI("PCF8574 initialization completed successfully.");
|
ZH_LOGI("PCF8574 initialization completed successfully.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t zh_pcf8574_deinit(zh_pcf8574_handle_t *handle) // -V2008
|
esp_err_t zh_pcf8574_deinit(zh_pcf8574_handle_t **handle) // -V2008
|
||||||
{
|
{
|
||||||
ZH_LOGI("PCF8574 deinitialization started.");
|
ZH_LOGI("PCF8574 deinitialization started.");
|
||||||
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 deinitialization failed. Invalid argument.");
|
ZH_ERROR_CHECK(handle != NULL && *handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 deinitialization failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_ERR_INVALID_STATE, NULL, "PCF8574 deinitialization failed. PCF8574 not initialized.");
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
if (_interrupt_gpio < GPIO_NUM_MAX && handle->gpio_work_mode != 0)
|
int32_t index = 0;
|
||||||
{
|
ZH_ERROR_CHECK(zh_vector_find_item_in_field(&_vector, &vector_data, &vector_data.i2c_address, sizeof(vector_data.i2c_address), &(*handle)->i2c_address, 0, &index) == ESP_OK,
|
||||||
|
ESP_ERR_NOT_FOUND, NULL, "PCF8574 deinitialization failed. Failed to find vector item.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_get_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Failed to get vector item data.");
|
||||||
|
ZH_ERROR_CHECK(i2c_master_bus_rm_device(vector_data.dev_handle) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. I2C remove device failed.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_delete_item(&_vector, (uint16_t)index) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Vector delete item failed.");
|
||||||
uint16_t vector_size = 0;
|
uint16_t vector_size = 0;
|
||||||
ZH_ERROR_CHECK(zh_vector_get_size(&_vector, &vector_size) == ESP_OK, ESP_ERR_INVALID_STATE, NULL, "PCF8574 deinitialization failed. Vector get size fail.");
|
ZH_ERROR_CHECK(zh_vector_get_size(&_vector, &vector_size) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Failed to get vector size.");
|
||||||
for (uint16_t i = 0; i < vector_size; ++i)
|
|
||||||
{
|
|
||||||
zh_pcf8574_handle_t temp_handle = {0};
|
|
||||||
ZH_ERROR_CHECK(zh_vector_get_item(&_vector, i, &temp_handle) == ESP_OK, ESP_ERR_INVALID_STATE, NULL, "PCF8574 deinitialization failed. Vector get item fail.");
|
|
||||||
if (handle->i2c_address == temp_handle.i2c_address)
|
|
||||||
{
|
|
||||||
ZH_ERROR_CHECK(zh_vector_delete_item(&_vector, i) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Vector delete item fail.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ZH_ERROR_CHECK(zh_vector_get_size(&_vector, &vector_size) == ESP_OK, ESP_ERR_INVALID_STATE, NULL, "PCF8574 deinitialization failed. Vector get size fail.");
|
|
||||||
if (vector_size == 0)
|
if (vector_size == 0)
|
||||||
|
{
|
||||||
|
if (_interrupt_gpio != GPIO_NUM_MAX)
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(gpio_isr_handler_remove(_interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Remove GPIO isr handler failed.");
|
ZH_ERROR_CHECK(gpio_isr_handler_remove(_interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Remove GPIO isr handler failed.");
|
||||||
ZH_ERROR_CHECK(gpio_reset_pin(_interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Reset GPIO failed.");
|
ZH_ERROR_CHECK(gpio_reset_pin(_interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Reset GPIO failed.");
|
||||||
ZH_ERROR_CHECK(zh_vector_free(&_vector) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Free vector failed.");
|
|
||||||
vSemaphoreDelete(_interrupt_semaphore);
|
|
||||||
vTaskDelete(zh_pcf8574);
|
vTaskDelete(zh_pcf8574);
|
||||||
|
zh_pcf8574 = NULL;
|
||||||
|
vSemaphoreDelete(_interrupt_semaphore);
|
||||||
|
_interrupt_semaphore = NULL;
|
||||||
_interrupt_gpio = GPIO_NUM_MAX;
|
_interrupt_gpio = GPIO_NUM_MAX;
|
||||||
}
|
}
|
||||||
|
ZH_ERROR_CHECK(zh_vector_free(&_vector) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. Free vector failed.");
|
||||||
}
|
}
|
||||||
if (handle->system != NULL)
|
heap_caps_free(*handle);
|
||||||
{
|
*handle = NULL;
|
||||||
heap_caps_free(handle->system);
|
|
||||||
}
|
|
||||||
ZH_ERROR_CHECK(i2c_master_bus_rm_device(handle->dev_handle) == ESP_OK, ESP_FAIL, NULL, "PCF8574 deinitialization failed. I2C remove device failed.");
|
|
||||||
handle->is_initialized = false;
|
|
||||||
for (uint8_t i = 0; i < sizeof(_i2c_matrix); ++i)
|
|
||||||
{
|
|
||||||
if (_i2c_matrix[i] == handle->i2c_address)
|
|
||||||
{
|
|
||||||
_i2c_matrix[i] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ZH_LOGI("PCF8574 deinitialization completed successfully.");
|
ZH_LOGI("PCF8574 deinitialization completed successfully.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t zh_pcf8574_read(zh_pcf8574_handle_t *handle, uint8_t *reg)
|
esp_err_t zh_pcf8574_read(zh_pcf8574_handle_t **handle, uint8_t *reg) // -V2008
|
||||||
{
|
{
|
||||||
ZH_LOGI("PCF8574 read register started.");
|
ZH_LOGI("PCF8574 read register started.");
|
||||||
ZH_ERROR_CHECK(handle != NULL && reg != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 read register failed. Invalid argument.");
|
ZH_ERROR_CHECK(handle != NULL && *handle != NULL && reg != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 read register failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_ERR_NOT_FOUND, NULL, "PCF8574 read register failed. PCF8574 not initialized.");
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_read_register(handle, reg) == ESP_OK, ESP_FAIL, NULL, "PCF8574 read register failed.");
|
int32_t index = 0;
|
||||||
|
ZH_ERROR_CHECK(zh_vector_find_item_in_field(&_vector, &vector_data, &vector_data.i2c_address, sizeof(vector_data.i2c_address), &(*handle)->i2c_address, 0, &index) == ESP_OK,
|
||||||
|
ESP_ERR_NOT_FOUND, NULL, "PCF8574 read register failed. Failed to find vector item.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_get_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 read register failed. Failed to get vector item data.");
|
||||||
|
ZH_ERROR_CHECK(_zh_pcf8574_read_register(&vector_data, reg) == ESP_OK, ESP_FAIL, NULL, "PCF8574 read register failed. PCF8574 read register failed.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_change_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 read register failed. Failed to change vector item data.");
|
||||||
ZH_LOGI("PCF8574 read register completed successfully.");
|
ZH_LOGI("PCF8574 read register completed successfully.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t zh_pcf8574_write(zh_pcf8574_handle_t *handle, uint8_t reg)
|
esp_err_t zh_pcf8574_write(zh_pcf8574_handle_t **handle, uint8_t reg) // -V2008
|
||||||
{
|
{
|
||||||
ZH_LOGI("PCF8574 write register started.");
|
ZH_LOGI("PCF8574 write register started.");
|
||||||
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 write register failed. Invalid argument.");
|
ZH_ERROR_CHECK(handle != NULL && *handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 write register failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_ERR_NOT_FOUND, NULL, "PCF8574 write register failed. PCF8574 not initialized.");
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_write_register(handle, (reg | handle->gpio_work_mode)) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write register failed.");
|
int32_t index = 0;
|
||||||
|
ZH_ERROR_CHECK(zh_vector_find_item_in_field(&_vector, &vector_data, &vector_data.i2c_address, sizeof(vector_data.i2c_address), &(*handle)->i2c_address, 0, &index) == ESP_OK,
|
||||||
|
ESP_ERR_NOT_FOUND, NULL, "PCF8574 write register failed. Failed to find vector item.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_get_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write register failed. Failed to get vector item data.");
|
||||||
|
ZH_ERROR_CHECK(_zh_pcf8574_write_register(&vector_data, (reg | vector_data.gpio_work_mode)) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write register failed. PCF8574 write register failed.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_change_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write register failed. Failed to change vector item data.");
|
||||||
ZH_LOGI("PCF8574 write register completed successfully.");
|
ZH_LOGI("PCF8574 write register completed successfully.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t zh_pcf8574_reset(zh_pcf8574_handle_t *handle)
|
esp_err_t zh_pcf8574_reset(zh_pcf8574_handle_t **handle) // -V2008
|
||||||
{
|
{
|
||||||
ZH_LOGI("PCF8574 reset register started.");
|
ZH_LOGI("PCF8574 reset register started.");
|
||||||
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 reset register failed. Invalid argument.");
|
ZH_ERROR_CHECK(handle != NULL && *handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 reset register failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_ERR_NOT_FOUND, NULL, "PCF8574 reset register failed. PCF8574 not initialized.");
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_write_register(handle, handle->gpio_work_mode) == ESP_OK, ESP_FAIL, NULL, "PCF8574 reset register failed.");
|
int32_t index = 0;
|
||||||
|
ZH_ERROR_CHECK(zh_vector_find_item_in_field(&_vector, &vector_data, &vector_data.i2c_address, sizeof(vector_data.i2c_address), &(*handle)->i2c_address, 0, &index) == ESP_OK,
|
||||||
|
ESP_ERR_NOT_FOUND, NULL, "PCF8574 read register failed. Failed to find vector item.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_get_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 reset register failed. Failed to get vector item data.");
|
||||||
|
ZH_ERROR_CHECK(_zh_pcf8574_write_register(&vector_data, vector_data.gpio_work_mode) == ESP_OK, ESP_FAIL, NULL, "PCF8574 reset register failed. PCF8574 write register failed.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_change_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 reset register failed. Failed to change vector item data.");
|
||||||
ZH_LOGI("PCF8574 reset register completed successfully.");
|
ZH_LOGI("PCF8574 reset register completed successfully.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t zh_pcf8574_read_gpio(zh_pcf8574_handle_t *handle, zh_pcf8574_gpio_num_t gpio, bool *status) // -V2008
|
esp_err_t zh_pcf8574_read_gpio(zh_pcf8574_handle_t **handle, zh_pcf8574_gpio_num_t gpio, bool *status) // -V2008
|
||||||
{
|
{
|
||||||
ZH_LOGI("PCF8574 read GPIO started.");
|
ZH_LOGI("PCF8574 read GPIO started.");
|
||||||
ZH_ERROR_CHECK(handle != NULL && status != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 read GPIO failed. Invalid argument.");
|
ZH_ERROR_CHECK(handle != NULL && *handle != NULL && status != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 read GPIO failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(gpio >= ZH_PCF8574_GPIO_NUM_P0 && gpio < ZH_PCF8574_GPIO_NUM_MAX, ESP_FAIL, NULL, "PCF8574 read GPIO failed. Invalid GPIO number.")
|
ZH_ERROR_CHECK(gpio >= ZH_PCF8574_GPIO_NUM_P0 && gpio < ZH_PCF8574_GPIO_NUM_MAX, ESP_FAIL, NULL, "PCF8574 read GPIO failed. Invalid GPIO number.")
|
||||||
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_ERR_NOT_FOUND, NULL, "PCF8574 read GPIO failed. PCF8574 not initialized.");
|
|
||||||
uint8_t gpio_temp = _gpio_matrix[gpio];
|
|
||||||
uint8_t reg_temp = 0;
|
uint8_t reg_temp = 0;
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_read_register(handle, ®_temp) == ESP_OK, ESP_FAIL, NULL, "PCF8574 read GPIO failed.");
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
*status = ((reg_temp & gpio_temp) ? 1 : 0);
|
int32_t index = 0;
|
||||||
|
ZH_ERROR_CHECK(zh_vector_find_item_in_field(&_vector, &vector_data, &vector_data.i2c_address, sizeof(vector_data.i2c_address), &(*handle)->i2c_address, 0, &index) == ESP_OK,
|
||||||
|
ESP_ERR_NOT_FOUND, NULL, "PCF8574 read GPIO failed. Failed to find vector item.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_get_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 read GPIO failed. Failed to get vector item data.");
|
||||||
|
ZH_ERROR_CHECK(_zh_pcf8574_read_register(&vector_data, ®_temp) == ESP_OK, ESP_FAIL, NULL, "PCF8574 read GPIO failed. PCF8574 read register failed.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_change_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 read GPIO failed. Failed to change vector item data.");
|
||||||
|
*status = ((reg_temp & _gpio_matrix[(uint8_t)gpio]) ? 1 : 0);
|
||||||
ZH_LOGI("PCF8574 read GPIO completed successfully.");
|
ZH_LOGI("PCF8574 read GPIO completed successfully.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t zh_pcf8574_write_gpio(zh_pcf8574_handle_t *handle, zh_pcf8574_gpio_num_t gpio, bool status) // -V2008
|
esp_err_t zh_pcf8574_write_gpio(zh_pcf8574_handle_t **handle, zh_pcf8574_gpio_num_t gpio, bool status) // -V2008
|
||||||
{
|
{
|
||||||
ZH_LOGI("PCF8574 write GPIO started.");
|
ZH_LOGI("PCF8574 write GPIO started.");
|
||||||
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 write GPIO failed. Invalid argument.");
|
ZH_ERROR_CHECK(handle != NULL && *handle != NULL, ESP_ERR_INVALID_ARG, NULL, "PCF8574 write GPIO failed. Invalid argument.");
|
||||||
ZH_ERROR_CHECK(gpio >= ZH_PCF8574_GPIO_NUM_P0 && gpio < ZH_PCF8574_GPIO_NUM_MAX, ESP_FAIL, NULL, "PCF8574 write GPIO failed. Invalid GPIO number.")
|
ZH_ERROR_CHECK(gpio >= ZH_PCF8574_GPIO_NUM_P0 && gpio < ZH_PCF8574_GPIO_NUM_MAX, ESP_FAIL, NULL, "PCF8574 write GPIO failed. Invalid GPIO number.")
|
||||||
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_ERR_NOT_FOUND, NULL, "PCF8574 write GPIO failed. PCF8574 not initialized.");
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
uint8_t gpio_temp = _gpio_matrix[gpio];
|
int32_t index = 0;
|
||||||
|
ZH_ERROR_CHECK(zh_vector_find_item_in_field(&_vector, &vector_data, &vector_data.i2c_address, sizeof(vector_data.i2c_address), &(*handle)->i2c_address, 0, &index) == ESP_OK,
|
||||||
|
ESP_ERR_NOT_FOUND, NULL, "PCF8574 write GPIO failed. Failed to find vector item.");
|
||||||
|
ZH_ERROR_CHECK(zh_vector_get_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write GPIO failed. Failed to get vector item data.");
|
||||||
if (status == true)
|
if (status == true)
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_write_register(handle, handle->gpio_status | handle->gpio_work_mode | gpio_temp) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write GPIO failed.");
|
ZH_ERROR_CHECK(_zh_pcf8574_write_register(&vector_data, vector_data.gpio_status | vector_data.gpio_work_mode | _gpio_matrix[(uint8_t)gpio]) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write GPIO failed. PCF8574 write register failed."); /*!< Set GPIO pin high, preserving work mode. */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_write_register(handle, (handle->gpio_status & ~gpio_temp) | handle->gpio_work_mode) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write GPIO failed.");
|
ZH_ERROR_CHECK(_zh_pcf8574_write_register(&vector_data, (vector_data.gpio_status & ~_gpio_matrix[(uint8_t)gpio]) | vector_data.gpio_work_mode) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write GPIO failed. PCF8574 write register failed."); /*!< Clear GPIO pin, preserving work mode. */
|
||||||
}
|
}
|
||||||
|
ZH_ERROR_CHECK(zh_vector_change_item(&_vector, (uint16_t)index, &vector_data) == ESP_OK, ESP_FAIL, NULL, "PCF8574 write GPIO failed. Failed to change vector item data.");
|
||||||
ZH_LOGI("PCF8574 write GPIO completed successfully.");
|
ZH_LOGI("PCF8574 write GPIO completed successfully.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -212,26 +356,18 @@ static esp_err_t _zh_pcf8574_validate_config(const zh_pcf8574_init_config_t *con
|
|||||||
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->task_priority >= 1 && config->stack_size >= configMINIMAL_STACK_SIZE, ESP_ERR_INVALID_ARG, NULL, "Invalid task settings.");
|
||||||
ZH_ERROR_CHECK(config->interrupt_gpio <= GPIO_NUM_MAX, ESP_ERR_INVALID_ARG, NULL, "Invalid GPIO number.");
|
ZH_ERROR_CHECK(config->interrupt_gpio <= GPIO_NUM_MAX, ESP_ERR_INVALID_ARG, NULL, "Invalid GPIO number.");
|
||||||
ZH_ERROR_CHECK(config->i2c_handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Invalid I2C handle.");
|
ZH_ERROR_CHECK(config->i2c_handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Invalid I2C handle.");
|
||||||
for (uint8_t i = 0; i < sizeof(_i2c_matrix); ++i)
|
if (_vector != NULL)
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(config->i2c_address != _i2c_matrix[i], ESP_ERR_INVALID_ARG, NULL, "I2C address already present.");
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
|
int32_t index = 0;
|
||||||
|
ZH_ERROR_CHECK(zh_vector_find_item_in_field(&_vector, &vector_data, &vector_data.i2c_address, sizeof(vector_data.i2c_address), &config->i2c_address, 0, &index) == ESP_ERR_NOT_FOUND,
|
||||||
|
ESP_ERR_INVALID_ARG, NULL, "I2C address already present.");
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _zh_pcf8574_gpio_init(const zh_pcf8574_init_config_t *config, zh_pcf8574_handle_t *handle) // -V2008
|
static esp_err_t _zh_pcf8574_gpio_init(const zh_pcf8574_init_config_t *config) // -V2008
|
||||||
{
|
{
|
||||||
uint8_t reg_temp = 0;
|
|
||||||
if (_interrupt_gpio != GPIO_NUM_MAX)
|
|
||||||
{
|
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_read_register(handle, ®_temp) == ESP_OK, ESP_FAIL, NULL, "Failed to read expander register.");
|
|
||||||
ZH_ERROR_CHECK(zh_vector_push_back(&_vector, handle) == ESP_OK, ESP_FAIL, NULL, "Failed add item to vector.")
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
ZH_ERROR_CHECK(zh_vector_init(&_vector, sizeof(zh_pcf8574_handle_t)) == ESP_OK, ESP_FAIL, NULL, "Failed create vector.")
|
|
||||||
ZH_ERROR_CHECK(_zh_pcf8574_read_register(handle, ®_temp) == ESP_OK, ESP_FAIL, NULL, "Failed to read expander register.");
|
|
||||||
ZH_ERROR_CHECK(zh_vector_push_back(&_vector, handle) == ESP_OK, ESP_FAIL,
|
|
||||||
ZH_ERROR_CHECK(zh_vector_free(&_vector) == ESP_OK, ESP_FAIL, NULL, "Free vector failed."), "Failed add item to vector.")
|
|
||||||
gpio_config_t interrupt_gpio_config = {
|
gpio_config_t interrupt_gpio_config = {
|
||||||
.intr_type = GPIO_INTR_NEGEDGE,
|
.intr_type = GPIO_INTR_NEGEDGE,
|
||||||
.mode = GPIO_MODE_INPUT,
|
.mode = GPIO_MODE_INPUT,
|
||||||
@@ -239,19 +375,16 @@ static esp_err_t _zh_pcf8574_gpio_init(const zh_pcf8574_init_config_t *config, z
|
|||||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||||
};
|
};
|
||||||
ZH_ERROR_CHECK(gpio_config(&interrupt_gpio_config) == ESP_OK, ESP_FAIL,
|
ZH_ERROR_CHECK(gpio_config(&interrupt_gpio_config) == ESP_OK, ESP_FAIL, NULL, "GPIO configuration failed.")
|
||||||
ZH_ERROR_CHECK(zh_vector_free(&_vector) == ESP_OK, ESP_FAIL, NULL, "Free vector failed."), "GPIO configuration failed.")
|
|
||||||
esp_err_t err = gpio_install_isr_service(ESP_INTR_FLAG_LOWMED);
|
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(err == ESP_OK || err == ESP_ERR_INVALID_STATE, ESP_FAIL,
|
||||||
ZH_ERROR_CHECK(gpio_reset_pin(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset gpio failed.");
|
{ZH_ERROR_CHECK(gpio_reset_pin(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset gpio failed.")}, "Failed install isr service.")
|
||||||
ZH_ERROR_CHECK(zh_vector_free(&_vector) == ESP_OK, ESP_FAIL, NULL, "Free vector failed."), "Failed install isr service.")
|
|
||||||
ZH_ERROR_CHECK(gpio_isr_handler_add(config->interrupt_gpio, _zh_pcf8574_isr_handler, NULL) == ESP_OK, ESP_FAIL,
|
ZH_ERROR_CHECK(gpio_isr_handler_add(config->interrupt_gpio, _zh_pcf8574_isr_handler, NULL) == ESP_OK, ESP_FAIL,
|
||||||
ZH_ERROR_CHECK(gpio_reset_pin(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset gpio failed.");
|
{ZH_ERROR_CHECK(gpio_reset_pin(config->interrupt_gpio) == ESP_OK, ESP_FAIL, NULL, "Reset gpio failed.")}, "Failed add isr handler.")
|
||||||
ZH_ERROR_CHECK(zh_vector_free(&_vector) == ESP_OK, ESP_FAIL, NULL, "Free vector failed."), "Failed add isr handler.")
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _zh_pcf8574_i2c_init(const zh_pcf8574_init_config_t *config, zh_pcf8574_handle_t *handle)
|
static esp_err_t _zh_pcf8574_i2c_init(const zh_pcf8574_init_config_t *config, _zh_pcf8574_vector_data_t *vector_data) // -V2008
|
||||||
{
|
{
|
||||||
i2c_device_config_t pcf8574_config = {
|
i2c_device_config_t pcf8574_config = {
|
||||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||||
@@ -261,33 +394,31 @@ static esp_err_t _zh_pcf8574_i2c_init(const zh_pcf8574_init_config_t *config, zh
|
|||||||
i2c_master_dev_handle_t _dev_handle = NULL;
|
i2c_master_dev_handle_t _dev_handle = NULL;
|
||||||
ZH_ERROR_CHECK(i2c_master_bus_add_device(config->i2c_handle, &pcf8574_config, &_dev_handle) == ESP_OK, ESP_FAIL, NULL, "Failed to add I2C device.");
|
ZH_ERROR_CHECK(i2c_master_bus_add_device(config->i2c_handle, &pcf8574_config, &_dev_handle) == ESP_OK, ESP_FAIL, NULL, "Failed to add I2C device.");
|
||||||
ZH_ERROR_CHECK(i2c_master_probe(config->i2c_handle, config->i2c_address, 1000 / portTICK_PERIOD_MS) == ESP_OK, ESP_FAIL,
|
ZH_ERROR_CHECK(i2c_master_probe(config->i2c_handle, config->i2c_address, 1000 / portTICK_PERIOD_MS) == ESP_OK, ESP_FAIL,
|
||||||
ZH_ERROR_CHECK(i2c_master_bus_rm_device(_dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed."), "Expander not connected or not responding.");
|
{ZH_ERROR_CHECK(i2c_master_bus_rm_device(_dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.")}, "Expander not connected or not responding.");
|
||||||
handle->dev_handle = _dev_handle;
|
vector_data->gpio_work_mode = (config->p7_gpio_work_mode << 7) | (config->p6_gpio_work_mode << 6) | (config->p5_gpio_work_mode << 5) |
|
||||||
handle->gpio_work_mode = (config->p7_gpio_work_mode << 7) | (config->p6_gpio_work_mode << 6) | (config->p5_gpio_work_mode << 5) |
|
|
||||||
(config->p4_gpio_work_mode << 4) | (config->p3_gpio_work_mode << 3) | (config->p2_gpio_work_mode << 2) |
|
(config->p4_gpio_work_mode << 4) | (config->p3_gpio_work_mode << 3) | (config->p2_gpio_work_mode << 2) |
|
||||||
(config->p1_gpio_work_mode << 1) | (config->p0_gpio_work_mode << 0);
|
(config->p1_gpio_work_mode << 1) | (config->p0_gpio_work_mode << 0);
|
||||||
handle->gpio_status = handle->gpio_work_mode;
|
vector_data->dev_handle = _dev_handle;
|
||||||
handle->i2c_address = config->i2c_address;
|
vector_data->i2c_address = config->i2c_address;
|
||||||
|
ZH_ERROR_CHECK(_zh_pcf8574_write_register(vector_data, vector_data->gpio_work_mode) == ESP_OK, ESP_FAIL,
|
||||||
|
{ZH_ERROR_CHECK(i2c_master_bus_rm_device(_dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.")}, "Failed extender initial GPIO setup.");
|
||||||
|
uint8_t reg_temp = 0;
|
||||||
|
ZH_ERROR_CHECK(_zh_pcf8574_read_register(vector_data, ®_temp) == ESP_OK, ESP_FAIL,
|
||||||
|
{ZH_ERROR_CHECK(i2c_master_bus_rm_device(_dev_handle) == ESP_OK, ESP_FAIL, NULL, "I2C remove device failed.")}, "Failed to read expander register.");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _zh_pcf8574_resources_init(const zh_pcf8574_init_config_t *config)
|
static esp_err_t _zh_pcf8574_resources_init(void)
|
||||||
{
|
|
||||||
if (_interrupt_gpio == GPIO_NUM_MAX)
|
|
||||||
{
|
{
|
||||||
_interrupt_semaphore = xSemaphoreCreateBinary();
|
_interrupt_semaphore = xSemaphoreCreateBinary();
|
||||||
ZH_ERROR_CHECK(_interrupt_semaphore != NULL, ESP_ERR_NO_MEM, NULL, "Failed to create semaphore.")
|
ZH_ERROR_CHECK(_interrupt_semaphore != NULL, ESP_ERR_NO_MEM, NULL, "Failed to create semaphore.")
|
||||||
}
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _zh_pcf8574_task_init(const zh_pcf8574_init_config_t *config)
|
static esp_err_t _zh_pcf8574_task_init(const zh_pcf8574_init_config_t *config)
|
||||||
{
|
|
||||||
if (_interrupt_gpio == GPIO_NUM_MAX)
|
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(xTaskCreatePinnedToCore(&_zh_pcf8574_isr_processing_task, "zh_pcf8574_isr_processing_task", config->stack_size, NULL, config->task_priority, &zh_pcf8574, tskNO_AFFINITY) == pdPASS,
|
ZH_ERROR_CHECK(xTaskCreatePinnedToCore(&_zh_pcf8574_isr_processing_task, "zh_pcf8574_isr_processing_task", config->stack_size, NULL, config->task_priority, &zh_pcf8574, tskNO_AFFINITY) == pdPASS,
|
||||||
ESP_FAIL, NULL, "Failed to create isr processing task.")
|
ESP_FAIL, NULL, "Failed to create isr processing task.")
|
||||||
}
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,63 +435,33 @@ static void IRAM_ATTR _zh_pcf8574_isr_handler(void *arg)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRAM_ATTR _zh_pcf8574_isr_processing_task(void *pvParameter)
|
static void IRAM_ATTR _zh_pcf8574_isr_processing_task(void *pvParameter) // -V2008
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
xSemaphoreTake(_interrupt_semaphore, portMAX_DELAY);
|
xSemaphoreTake(_interrupt_semaphore, portMAX_DELAY);
|
||||||
uint16_t vector_size = 0;
|
uint16_t vector_size = 0;
|
||||||
if (zh_vector_get_size(&_vector, &vector_size) != ESP_OK)
|
ZH_ERROR_CHECK_CONT(zh_vector_get_size(&_vector, &vector_size) == ESP_OK, ++_stats.vector_error, "PCF8574 isr processing failed. Failed to get vector size.");
|
||||||
{
|
|
||||||
++_stats.vector_error;
|
|
||||||
ZH_LOGE("PCF8574 isr processing failed. Failed to get vector size.", ESP_FAIL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (uint16_t i = 0; i < vector_size; ++i)
|
for (uint16_t i = 0; i < vector_size; ++i)
|
||||||
{
|
{
|
||||||
zh_pcf8574_handle_t handle = {0};
|
_zh_pcf8574_vector_data_t vector_data = {0};
|
||||||
esp_err_t err = zh_vector_get_item(&_vector, i, &handle);
|
ZH_ERROR_CHECK_CONT(zh_vector_get_item(&_vector, i, &vector_data) == ESP_OK, ++_stats.vector_error, "PCF8574 isr processing failed. Failed to get vector item data.");
|
||||||
if (err != ESP_OK)
|
|
||||||
{
|
|
||||||
++_stats.vector_error;
|
|
||||||
ZH_LOGE("PCF8574 isr processing failed. Failed to get vector item data.", ESP_FAIL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
zh_pcf8574_event_on_isr_t event = {0};
|
zh_pcf8574_event_on_isr_t event = {0};
|
||||||
event.i2c_address = handle.i2c_address;
|
event.i2c_address = vector_data.i2c_address;
|
||||||
uint8_t old_reg = handle.gpio_status;
|
uint8_t old_reg = vector_data.gpio_status;
|
||||||
uint8_t new_reg = 0;
|
uint8_t new_reg = 0;
|
||||||
err = _zh_pcf8574_read_register(&handle, &new_reg);
|
ZH_ERROR_CHECK_CONT(_zh_pcf8574_read_register(&vector_data, &new_reg) == ESP_OK, NULL, "PCF8574 isr processing failed. Failed to read expander register.");
|
||||||
if (err != ESP_OK)
|
ZH_ERROR_CHECK_CONT(zh_vector_change_item(&_vector, i, &vector_data) == ESP_OK, ++_stats.vector_error, "PCF8574 isr processing failed. Failed to change vector item data.");
|
||||||
{
|
|
||||||
ZH_LOGE("PCF8574 isr processing failed. Failed to read expander register.", err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
err = zh_vector_change_item(&_vector, i, &handle);
|
|
||||||
if (err != ESP_OK)
|
|
||||||
{
|
|
||||||
++_stats.vector_error;
|
|
||||||
ZH_LOGE("PCF8574 isr processing failed. Failed to change vector item data.", ESP_FAIL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (uint8_t j = 0; j <= 7; ++j)
|
for (uint8_t j = 0; j <= 7; ++j)
|
||||||
{
|
{
|
||||||
if ((handle.gpio_work_mode & _gpio_matrix[j]) != 0)
|
if ((vector_data.gpio_work_mode & _gpio_matrix[j]) != 0)
|
||||||
{
|
{
|
||||||
if ((old_reg & _gpio_matrix[j]) != (new_reg & _gpio_matrix[j]))
|
if ((old_reg & _gpio_matrix[j]) != (new_reg & _gpio_matrix[j]))
|
||||||
{
|
{
|
||||||
event.gpio_number = j;
|
event.gpio_number = j;
|
||||||
event.gpio_level = new_reg & _gpio_matrix[j];
|
event.gpio_level = new_reg & _gpio_matrix[j];
|
||||||
event.interrupt_time = esp_timer_get_time();
|
event.interrupt_time = esp_timer_get_time();
|
||||||
err = esp_event_post(ZH_PCF8574, 0, &event, sizeof(event), 1000 / portTICK_PERIOD_MS);
|
ZH_ERROR_CHECK_CONT(esp_event_post(ZH_PCF8574, 0, &event, sizeof(event), 1000 / portTICK_PERIOD_MS) == ESP_OK, ++_stats.event_post_error, "PCF8574 isr processing failed. Failed to post interrupt event.");
|
||||||
if (err != ESP_OK)
|
|
||||||
{
|
|
||||||
++_stats.event_post_error;
|
|
||||||
ZH_LOGE("PCF8574 isr processing failed. Failed to post interrupt event.", err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,18 +471,18 @@ static void IRAM_ATTR _zh_pcf8574_isr_processing_task(void *pvParameter)
|
|||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _zh_pcf8574_read_register(zh_pcf8574_handle_t *handle, uint8_t *reg)
|
static esp_err_t _zh_pcf8574_read_register(_zh_pcf8574_vector_data_t *vector_data, uint8_t *reg)
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(i2c_master_receive(handle->dev_handle, &handle->gpio_status, sizeof(handle->gpio_status), 1000 / portTICK_PERIOD_MS) == ESP_OK, ESP_FAIL,
|
ZH_ERROR_CHECK(i2c_master_receive(vector_data->dev_handle, &vector_data->gpio_status, sizeof(vector_data->gpio_status), 1000 / portTICK_PERIOD_MS) == ESP_OK, ESP_FAIL,
|
||||||
++_stats.i2c_driver_error, "I2C driver error.");
|
++_stats.i2c_driver_error, "I2C driver error.");
|
||||||
*reg = handle->gpio_status;
|
*reg = vector_data->gpio_status;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _zh_pcf8574_write_register(zh_pcf8574_handle_t *handle, uint8_t reg)
|
static esp_err_t _zh_pcf8574_write_register(_zh_pcf8574_vector_data_t *vector_data, uint8_t reg)
|
||||||
{
|
{
|
||||||
ZH_ERROR_CHECK(i2c_master_transmit(handle->dev_handle, ®, sizeof(reg), 1000 / portTICK_PERIOD_MS) == ESP_OK, ESP_FAIL,
|
ZH_ERROR_CHECK(i2c_master_transmit(vector_data->dev_handle, ®, sizeof(reg), 1000 / portTICK_PERIOD_MS) == ESP_OK, ESP_FAIL,
|
||||||
++_stats.i2c_driver_error, "I2C driver error.");
|
++_stats.i2c_driver_error, "I2C driver error.");
|
||||||
handle->gpio_status = reg;
|
vector_data->gpio_status = reg;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user