Snapshot of JC3636W518EN kit before demo folder cleanup
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
9ee85bfd86
1862 files changed
+668877
No files matched your search
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "../private/CheckResult.h"
|
||||
#include "HT8574.h"
|
||||
|
||||
/* Timeout of each I2C communication */
|
||||
#define I2C_TIMEOUT_MS (10)
|
||||
|
||||
#define IO_COUNT (8)
|
||||
|
||||
/* Default register value on power-up */
|
||||
#define DIR_REG_DEFAULT_VAL (0xff)
|
||||
#define OUT_REG_DEFAULT_VAL (0xff)
|
||||
|
||||
/**
|
||||
* @brief Device Structure Type
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
esp_io_expander_t base;
|
||||
i2c_port_t i2c_num;
|
||||
uint32_t i2c_address;
|
||||
struct {
|
||||
uint8_t direction;
|
||||
uint8_t output;
|
||||
} regs;
|
||||
} esp_io_expander_ht8574_t;
|
||||
|
||||
static const char *TAG = "ht8574";
|
||||
|
||||
static esp_err_t esp_io_expander_new_i2c_ht8574(i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle);
|
||||
|
||||
ESP_IOExpander_HT8574::~ESP_IOExpander_HT8574()
|
||||
{
|
||||
if (i2c_need_init) {
|
||||
i2c_driver_delete(i2c_id);
|
||||
}
|
||||
if (handle) {
|
||||
del();
|
||||
}
|
||||
}
|
||||
|
||||
void ESP_IOExpander_HT8574::begin(void)
|
||||
{
|
||||
CHECK_ERROR_RETURN(esp_io_expander_new_i2c_ht8574(i2c_id, i2c_address, &handle));
|
||||
}
|
||||
|
||||
static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t write_output_reg(esp_io_expander_handle_t handle, uint32_t value);
|
||||
static esp_err_t read_output_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t write_direction_reg(esp_io_expander_handle_t handle, uint32_t value);
|
||||
static esp_err_t read_direction_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t reset(esp_io_expander_t *handle);
|
||||
static esp_err_t del(esp_io_expander_t *handle);
|
||||
|
||||
static esp_err_t esp_io_expander_new_i2c_ht8574(i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, TAG, "Invalid i2c num");
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "Invalid handle");
|
||||
|
||||
esp_io_expander_ht8574_t *ht8574 = (esp_io_expander_ht8574_t *)calloc(1, sizeof(esp_io_expander_ht8574_t));
|
||||
ESP_RETURN_ON_FALSE(ht8574, ESP_ERR_NO_MEM, TAG, "Malloc failed");
|
||||
|
||||
ht8574->base.config.io_count = IO_COUNT;
|
||||
ht8574->base.config.flags.dir_out_bit_zero = 1;
|
||||
ht8574->i2c_num = i2c_num;
|
||||
ht8574->i2c_address = i2c_address;
|
||||
ht8574->regs.output = OUT_REG_DEFAULT_VAL;
|
||||
ht8574->base.read_input_reg = read_input_reg;
|
||||
ht8574->base.write_output_reg = write_output_reg;
|
||||
ht8574->base.read_output_reg = read_output_reg;
|
||||
ht8574->base.write_direction_reg = write_direction_reg;
|
||||
ht8574->base.read_direction_reg = read_direction_reg;
|
||||
ht8574->base.del = del;
|
||||
ht8574->base.reset = reset;
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
/* Reset configuration and register status */
|
||||
ESP_GOTO_ON_ERROR(reset(&ht8574->base), err, TAG, "Reset failed");
|
||||
|
||||
*handle = &ht8574->base;
|
||||
return ESP_OK;
|
||||
err:
|
||||
free(ht8574);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_ht8574_t *ht8574 = (esp_io_expander_ht8574_t *)__containerof(handle, esp_io_expander_ht8574_t, base);
|
||||
|
||||
uint8_t temp = 0;
|
||||
// *INDENT-OFF*
|
||||
ESP_RETURN_ON_ERROR(
|
||||
i2c_master_read_from_device(ht8574->i2c_num, ht8574->i2c_address, &temp, 1, pdMS_TO_TICKS(I2C_TIMEOUT_MS)),
|
||||
TAG, "Read input reg failed");
|
||||
// *INDENT-ON*
|
||||
*value = temp;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t write_output_reg(esp_io_expander_handle_t handle, uint32_t value)
|
||||
{
|
||||
esp_io_expander_ht8574_t *ht8574 = (esp_io_expander_ht8574_t *)__containerof(handle, esp_io_expander_ht8574_t, base);
|
||||
value &= 0xff;
|
||||
|
||||
uint8_t data = (uint8_t)value;
|
||||
ESP_RETURN_ON_ERROR(
|
||||
i2c_master_write_to_device(ht8574->i2c_num, ht8574->i2c_address, &data, 1, pdMS_TO_TICKS(I2C_TIMEOUT_MS)),
|
||||
TAG, "Write output reg failed");
|
||||
ht8574->regs.output = value;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_output_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_ht8574_t *ht8574 = (esp_io_expander_ht8574_t *)__containerof(handle, esp_io_expander_ht8574_t, base);
|
||||
|
||||
*value = ht8574->regs.output;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t write_direction_reg(esp_io_expander_handle_t handle, uint32_t value)
|
||||
{
|
||||
esp_io_expander_ht8574_t *ht8574 = (esp_io_expander_ht8574_t *)__containerof(handle, esp_io_expander_ht8574_t, base);
|
||||
value &= 0xff;
|
||||
ht8574->regs.direction = value;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_direction_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_ht8574_t *ht8574 = (esp_io_expander_ht8574_t *)__containerof(handle, esp_io_expander_ht8574_t, base);
|
||||
|
||||
*value = ht8574->regs.direction;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t reset(esp_io_expander_t *handle)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(write_output_reg(handle, OUT_REG_DEFAULT_VAL), TAG, "Write output reg failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t del(esp_io_expander_t *handle)
|
||||
{
|
||||
esp_io_expander_ht8574_t *ht8574 = (esp_io_expander_ht8574_t *)__containerof(handle, esp_io_expander_ht8574_t, base);
|
||||
|
||||
free(ht8574);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "../ESP_IOExpander.h"
|
||||
|
||||
class ESP_IOExpander_HT8574: public ESP_IOExpander {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note After using this function, call `init()` will initialize I2C bus.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
* @param config Pointer to I2C bus configuration
|
||||
*/
|
||||
ESP_IOExpander_HT8574(i2c_port_t id, uint8_t address, const i2c_config_t *config): ESP_IOExpander(id, address, config) { };
|
||||
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note After using this function, call `init()` will initialize I2C bus.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
* @param scl SCL pin number
|
||||
* @param sda SDA pin number
|
||||
*/
|
||||
ESP_IOExpander_HT8574(i2c_port_t id, uint8_t address, int scl, int sda): ESP_IOExpander(id, address, scl, sda) { };
|
||||
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note If use this function, should initialize I2C bus before call `init()`.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
*/
|
||||
ESP_IOExpander_HT8574(i2c_port_t id, uint8_t address): ESP_IOExpander(id, address) { };
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*
|
||||
* @note This function will delete I2C driver if it is initialized by ESP_IOExpander and delete ESP_IOExpander object.
|
||||
*/
|
||||
~ESP_IOExpander_HT8574() override;
|
||||
|
||||
/**
|
||||
* @brief Begin IO expander
|
||||
*
|
||||
*/
|
||||
void begin(void) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief I2C address of the ht8574
|
||||
*
|
||||
* The 8-bit address format is as follows:
|
||||
*
|
||||
* (Slave Address)
|
||||
* ┌─────────────────┷─────────────────┐
|
||||
* ┌─────┐─────┐─────┐─────┐─────┐─────┐─────┐─────┐
|
||||
* | 0 | 1 | 1 | 1 | A2 | A1 | A0 | R/W |
|
||||
* └─────┘─────┘─────┘─────┘─────┘─────┘─────┘─────┘
|
||||
* └────────┯────────┘ └─────┯──────┘
|
||||
* (Fixed) (Hareware Selectable)
|
||||
*
|
||||
* And the 7-bit slave address is the most important data for users.
|
||||
* For example, if a chip's A0,A1,A2 are connected to GND, it's 7-bit slave address is 0111000b(0x38).
|
||||
* Then users can use `ESP_IO_EXPANDER_I2C_HT8574_ADDRESS_000` to init it.
|
||||
*/
|
||||
#define ESP_IO_EXPANDER_I2C_HT8574_ADDRESS_000 (0x38)
|
||||
#define ESP_IO_EXPANDER_I2C_HT8574_ADDRESS_001 (0x29)
|
||||
#define ESP_IO_EXPANDER_I2C_HT8574_ADDRESS_010 (0x2A)
|
||||
#define ESP_IO_EXPANDER_I2C_HT8574_ADDRESS_011 (0x2B)
|
||||
#define ESP_IO_EXPANDER_I2C_HT8574_ADDRESS_100 (0x2C)
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "../private/CheckResult.h"
|
||||
#include "TCA95xx_16bit.h"
|
||||
|
||||
/* Timeout of each I2C communication */
|
||||
#define I2C_TIMEOUT_MS (10)
|
||||
|
||||
#define IO_COUNT (16)
|
||||
|
||||
/* Register address */
|
||||
#define INPUT_REG_ADDR (0x00)
|
||||
#define OUTPUT_REG_ADDR (0x02)
|
||||
#define DIRECTION_REG_ADDR (0x06)
|
||||
|
||||
/* Default register value on power-up */
|
||||
#define DIR_REG_DEFAULT_VAL (0xffff)
|
||||
#define OUT_REG_DEFAULT_VAL (0xffff)
|
||||
|
||||
/**
|
||||
* @brief Device Structure Type
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
esp_io_expander_t base;
|
||||
i2c_port_t i2c_num;
|
||||
uint32_t i2c_address;
|
||||
struct {
|
||||
uint8_t direction;
|
||||
uint8_t output;
|
||||
} regs;
|
||||
} esp_io_expander_tca95xx_16bit_t;
|
||||
|
||||
static const char *TAG = "tca95xx_16bit";
|
||||
|
||||
ESP_IOExpander_TCA95xx_16bit::~ESP_IOExpander_TCA95xx_16bit()
|
||||
{
|
||||
if (i2c_need_init) {
|
||||
i2c_driver_delete(i2c_id);
|
||||
}
|
||||
if (handle) {
|
||||
del();
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t esp_io_expander_new_i2c_tca95xx_16bit(i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle);
|
||||
|
||||
void ESP_IOExpander_TCA95xx_16bit::begin(void)
|
||||
{
|
||||
CHECK_ERROR_RETURN(esp_io_expander_new_i2c_tca95xx_16bit(i2c_id, i2c_address, &handle));
|
||||
}
|
||||
|
||||
static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t write_output_reg(esp_io_expander_handle_t handle, uint32_t value);
|
||||
static esp_err_t read_output_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t write_direction_reg(esp_io_expander_handle_t handle, uint32_t value);
|
||||
static esp_err_t read_direction_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t reset(esp_io_expander_t *handle);
|
||||
static esp_err_t del(esp_io_expander_t *handle);
|
||||
|
||||
static esp_err_t esp_io_expander_new_i2c_tca95xx_16bit(i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, TAG, "Invalid i2c num");
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "Invalid handle");
|
||||
|
||||
esp_io_expander_tca95xx_16bit_t *tca = (esp_io_expander_tca95xx_16bit_t *)calloc(1, sizeof(esp_io_expander_tca95xx_16bit_t));
|
||||
ESP_RETURN_ON_FALSE(tca, ESP_ERR_NO_MEM, TAG, "Malloc failed");
|
||||
|
||||
tca->base.config.io_count = IO_COUNT;
|
||||
tca->base.config.flags.dir_out_bit_zero = 1;
|
||||
tca->i2c_num = i2c_num;
|
||||
tca->i2c_address = i2c_address;
|
||||
tca->base.read_input_reg = read_input_reg;
|
||||
tca->base.write_output_reg = write_output_reg;
|
||||
tca->base.read_output_reg = read_output_reg;
|
||||
tca->base.write_direction_reg = write_direction_reg;
|
||||
tca->base.read_direction_reg = read_direction_reg;
|
||||
tca->base.del = del;
|
||||
tca->base.reset = reset;
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
/* Reset configuration and register status */
|
||||
ESP_GOTO_ON_ERROR(reset(&tca->base), err, TAG, "Reset failed");
|
||||
|
||||
*handle = &tca->base;
|
||||
return ESP_OK;
|
||||
err:
|
||||
free(tca);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_tca95xx_16bit_t *tca = (esp_io_expander_tca95xx_16bit_t *)__containerof(handle, esp_io_expander_tca95xx_16bit_t, base);
|
||||
|
||||
uint8_t temp[2] = {0, 0};
|
||||
uint8_t reg = INPUT_REG_ADDR;
|
||||
// *INDENT-OFF*
|
||||
ESP_RETURN_ON_ERROR(
|
||||
i2c_master_write_read_device(tca->i2c_num, tca->i2c_address, ®, 1, (uint8_t*)&temp, 2, pdMS_TO_TICKS(I2C_TIMEOUT_MS)),
|
||||
TAG, "Read input reg failed");
|
||||
// *INDENT-ON*
|
||||
*value = (((uint32_t)temp[0]) << 8) | (temp[1]);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t write_output_reg(esp_io_expander_handle_t handle, uint32_t value)
|
||||
{
|
||||
esp_io_expander_tca95xx_16bit_t *tca = (esp_io_expander_tca95xx_16bit_t *)__containerof(handle, esp_io_expander_tca95xx_16bit_t, base);
|
||||
value &= 0xffff;
|
||||
|
||||
uint8_t data[] = {OUTPUT_REG_ADDR, (uint8_t)(value >> 8), (uint8_t)(value & 0xff)};
|
||||
ESP_RETURN_ON_ERROR(
|
||||
i2c_master_write_to_device(tca->i2c_num, tca->i2c_address, data, sizeof(data), pdMS_TO_TICKS(I2C_TIMEOUT_MS)),
|
||||
TAG, "Write output reg failed");
|
||||
tca->regs.output = value;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_output_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_tca95xx_16bit_t *tca = (esp_io_expander_tca95xx_16bit_t *)__containerof(handle, esp_io_expander_tca95xx_16bit_t, base);
|
||||
|
||||
*value = tca->regs.output;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t write_direction_reg(esp_io_expander_handle_t handle, uint32_t value)
|
||||
{
|
||||
esp_io_expander_tca95xx_16bit_t *tca = (esp_io_expander_tca95xx_16bit_t *)__containerof(handle, esp_io_expander_tca95xx_16bit_t, base);
|
||||
value &= 0xffff;
|
||||
|
||||
uint8_t data[] = {DIRECTION_REG_ADDR, (uint8_t)(value >> 8), (uint8_t)(value & 0xff)};
|
||||
ESP_RETURN_ON_ERROR(
|
||||
i2c_master_write_to_device(tca->i2c_num, tca->i2c_address, data, sizeof(data), pdMS_TO_TICKS(I2C_TIMEOUT_MS)),
|
||||
TAG, "Write direction reg failed");
|
||||
tca->regs.direction = value;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_direction_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_tca95xx_16bit_t *tca = (esp_io_expander_tca95xx_16bit_t *)__containerof(handle, esp_io_expander_tca95xx_16bit_t, base);
|
||||
|
||||
*value = tca->regs.direction;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t reset(esp_io_expander_t *handle)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(write_direction_reg(handle, DIR_REG_DEFAULT_VAL), TAG, "Write dir reg failed");
|
||||
ESP_RETURN_ON_ERROR(write_output_reg(handle, OUT_REG_DEFAULT_VAL), TAG, "Write output reg failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t del(esp_io_expander_t *handle)
|
||||
{
|
||||
esp_io_expander_tca95xx_16bit_t *tca = (esp_io_expander_tca95xx_16bit_t *)__containerof(handle, esp_io_expander_tca95xx_16bit_t, base);
|
||||
|
||||
free(tca);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "../ESP_IOExpander.h"
|
||||
|
||||
class ESP_IOExpander_TCA95xx_16bit: public ESP_IOExpander {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note After using this function, call `init()` will initialize I2C bus.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
* @param config Pointer to I2C bus configuration
|
||||
*/
|
||||
ESP_IOExpander_TCA95xx_16bit(i2c_port_t id, uint8_t address, const i2c_config_t *config): ESP_IOExpander(id, address, config) { };
|
||||
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note After using this function, call `init()` will initialize I2C bus.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
* @param scl SCL pin number
|
||||
* @param sda SDA pin number
|
||||
*/
|
||||
ESP_IOExpander_TCA95xx_16bit(i2c_port_t id, uint8_t address, int scl, int sda): ESP_IOExpander(id, address, scl, sda) { };
|
||||
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note If use this function, should initialize I2C bus before call `init()`.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
*/
|
||||
ESP_IOExpander_TCA95xx_16bit(i2c_port_t id, uint8_t address): ESP_IOExpander(id, address) { };
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*
|
||||
* @note This function will delete I2C driver if it is initialized by ESP_IOExpander and delete ESP_IOExpander object.
|
||||
*/
|
||||
~ESP_IOExpander_TCA95xx_16bit() override;
|
||||
|
||||
/**
|
||||
* @brief Begin IO expander
|
||||
*
|
||||
*/
|
||||
void begin(void) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief I2C address of the TCA9539 or TCA9555
|
||||
*
|
||||
* The 8-bit address format for the TCA9539 is as follows:
|
||||
*
|
||||
* (Slave Address)
|
||||
* ┌─────────────────┷─────────────────┐
|
||||
* ┌─────┐─────┐─────┐─────┐─────┐─────┐─────┐─────┐
|
||||
* | 1 | 1 | 1 | 0 | 1 | A1 | A0 | R/W |
|
||||
* └─────┘─────┘─────┘─────┘─────┘─────┘─────┘─────┘
|
||||
* └────────┯──────────────┘ └──┯──┘
|
||||
* (Fixed) (Hareware Selectable)
|
||||
*
|
||||
* The 8-bit address format for the TCA9555 is as follows:
|
||||
*
|
||||
* (Slave Address)
|
||||
* ┌─────────────────┷─────────────────┐
|
||||
* ┌─────┐─────┐─────┐─────┐─────┐─────┐─────┐─────┐
|
||||
* | 0 | 1 | 0 | 0 | A2 | A1 | A0 | R/W |
|
||||
* └─────┘─────┘─────┘─────┘─────┘─────┘─────┘─────┘
|
||||
* └────────┯────────┘ └─────┯──────┘
|
||||
* (Fixed) (Hareware Selectable)
|
||||
*
|
||||
* And the 7-bit slave address is the most important data for users.
|
||||
* For example, if a TCA9555 chip's A0,A1,A2 are connected to GND, it's 7-bit slave address is 0b0100000.
|
||||
* Then users can use `ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_000` to init it.
|
||||
*/
|
||||
enum esp_io_expander_tca_95xx_16bit_address {
|
||||
ESP_IO_EXPANDER_I2C_TCA9539_ADDRESS_00 = 0b1110100,
|
||||
ESP_IO_EXPANDER_I2C_TCA9539_ADDRESS_01 = 0b1110101,
|
||||
ESP_IO_EXPANDER_I2C_TCA9539_ADDRESS_10 = 0b1110110,
|
||||
ESP_IO_EXPANDER_I2C_TCA9539_ADDRESS_11 = 0b1110111,
|
||||
ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_000 = 0b0100000,
|
||||
ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_001 = 0b0100001,
|
||||
ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_010 = 0b0100010,
|
||||
ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_011 = 0b0100011,
|
||||
ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_100 = 0b0100000,
|
||||
ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_101 = 0b0100101,
|
||||
ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_110 = 0b0100110,
|
||||
ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_111 = 0b0100111,
|
||||
};
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "../private/CheckResult.h"
|
||||
#include "TCA95xx_8bit.h"
|
||||
|
||||
/* Timeout of each I2C communication */
|
||||
#define I2C_TIMEOUT_MS (10)
|
||||
|
||||
#define IO_COUNT (8)
|
||||
|
||||
/* Register address */
|
||||
#define INPUT_REG_ADDR (0x00)
|
||||
#define OUTPUT_REG_ADDR (0x01)
|
||||
#define DIRECTION_REG_ADDR (0x03)
|
||||
|
||||
/* Default register value on power-up */
|
||||
#define DIR_REG_DEFAULT_VAL (0xff)
|
||||
#define OUT_REG_DEFAULT_VAL (0xff)
|
||||
|
||||
/**
|
||||
* @brief Device Structure Type
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
esp_io_expander_t base;
|
||||
i2c_port_t i2c_num;
|
||||
uint32_t i2c_address;
|
||||
struct {
|
||||
uint8_t direction;
|
||||
uint8_t output;
|
||||
} regs;
|
||||
} esp_io_expander_tca95xx_8bit_t;
|
||||
|
||||
static const char *TAG = "tca95xx_8bit";
|
||||
|
||||
static esp_err_t esp_io_expander_new_i2c_tca95xx_8bit(i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle);
|
||||
|
||||
ESP_IOExpander_TCA95xx_8bit::~ESP_IOExpander_TCA95xx_8bit()
|
||||
{
|
||||
if (i2c_need_init) {
|
||||
i2c_driver_delete(i2c_id);
|
||||
}
|
||||
if (handle) {
|
||||
del();
|
||||
}
|
||||
}
|
||||
|
||||
void ESP_IOExpander_TCA95xx_8bit::begin(void)
|
||||
{
|
||||
CHECK_ERROR_RETURN(esp_io_expander_new_i2c_tca95xx_8bit(i2c_id, i2c_address, &handle));
|
||||
}
|
||||
|
||||
static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t write_output_reg(esp_io_expander_handle_t handle, uint32_t value);
|
||||
static esp_err_t read_output_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t write_direction_reg(esp_io_expander_handle_t handle, uint32_t value);
|
||||
static esp_err_t read_direction_reg(esp_io_expander_handle_t handle, uint32_t *value);
|
||||
static esp_err_t reset(esp_io_expander_t *handle);
|
||||
static esp_err_t del(esp_io_expander_t *handle);
|
||||
|
||||
static esp_err_t esp_io_expander_new_i2c_tca95xx_8bit(i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, TAG, "Invalid i2c num");
|
||||
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "Invalid handle");
|
||||
|
||||
esp_io_expander_tca95xx_8bit_t *tca = (esp_io_expander_tca95xx_8bit_t *)calloc(1, sizeof(esp_io_expander_tca95xx_8bit_t));
|
||||
ESP_RETURN_ON_FALSE(tca, ESP_ERR_NO_MEM, TAG, "Malloc failed");
|
||||
|
||||
tca->base.config.io_count = IO_COUNT;
|
||||
tca->base.config.flags.dir_out_bit_zero = 1;
|
||||
tca->i2c_num = i2c_num;
|
||||
tca->i2c_address = i2c_address;
|
||||
tca->base.read_input_reg = read_input_reg;
|
||||
tca->base.write_output_reg = write_output_reg;
|
||||
tca->base.read_output_reg = read_output_reg;
|
||||
tca->base.write_direction_reg = write_direction_reg;
|
||||
tca->base.read_direction_reg = read_direction_reg;
|
||||
tca->base.del = del;
|
||||
tca->base.reset = reset;
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
/* Reset configuration and register status */
|
||||
ESP_GOTO_ON_ERROR(reset(&tca->base), err, TAG, "Reset failed");
|
||||
|
||||
*handle = &tca->base;
|
||||
return ESP_OK;
|
||||
err:
|
||||
free(tca);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_tca95xx_8bit_t *tca = (esp_io_expander_tca95xx_8bit_t *)__containerof(handle, esp_io_expander_tca95xx_8bit_t, base);
|
||||
|
||||
uint8_t temp = 0;
|
||||
uint8_t reg = INPUT_REG_ADDR;
|
||||
// *INDENT-OFF*
|
||||
ESP_RETURN_ON_ERROR(
|
||||
i2c_master_write_read_device(tca->i2c_num, tca->i2c_address, ®, 1, &temp, 1, pdMS_TO_TICKS(I2C_TIMEOUT_MS)),
|
||||
TAG, "Read input reg failed");
|
||||
// *INDENT-ON*
|
||||
*value = temp;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t write_output_reg(esp_io_expander_handle_t handle, uint32_t value)
|
||||
{
|
||||
esp_io_expander_tca95xx_8bit_t *tca = (esp_io_expander_tca95xx_8bit_t *)__containerof(handle, esp_io_expander_tca95xx_8bit_t, base);
|
||||
value &= 0xff;
|
||||
|
||||
uint8_t data[] = {OUTPUT_REG_ADDR, (uint8_t)value};
|
||||
ESP_RETURN_ON_ERROR(
|
||||
i2c_master_write_to_device(tca->i2c_num, tca->i2c_address, data, sizeof(data), pdMS_TO_TICKS(I2C_TIMEOUT_MS)),
|
||||
TAG, "Write output reg failed");
|
||||
tca->regs.output = value;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_output_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_tca95xx_8bit_t *tca = (esp_io_expander_tca95xx_8bit_t *)__containerof(handle, esp_io_expander_tca95xx_8bit_t, base);
|
||||
|
||||
*value = tca->regs.output;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t write_direction_reg(esp_io_expander_handle_t handle, uint32_t value)
|
||||
{
|
||||
esp_io_expander_tca95xx_8bit_t *tca = (esp_io_expander_tca95xx_8bit_t *)__containerof(handle, esp_io_expander_tca95xx_8bit_t, base);
|
||||
value &= 0xff;
|
||||
|
||||
uint8_t data[] = {DIRECTION_REG_ADDR, (uint8_t)value};
|
||||
ESP_RETURN_ON_ERROR(
|
||||
i2c_master_write_to_device(tca->i2c_num, tca->i2c_address, data, sizeof(data), pdMS_TO_TICKS(I2C_TIMEOUT_MS)),
|
||||
TAG, "Write direction reg failed");
|
||||
tca->regs.direction = value;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t read_direction_reg(esp_io_expander_handle_t handle, uint32_t *value)
|
||||
{
|
||||
esp_io_expander_tca95xx_8bit_t *tca = (esp_io_expander_tca95xx_8bit_t *)__containerof(handle, esp_io_expander_tca95xx_8bit_t, base);
|
||||
|
||||
*value = tca->regs.direction;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t reset(esp_io_expander_t *handle)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(write_direction_reg(handle, DIR_REG_DEFAULT_VAL), TAG, "Write dir reg failed");
|
||||
ESP_RETURN_ON_ERROR(write_output_reg(handle, OUT_REG_DEFAULT_VAL), TAG, "Write output reg failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t del(esp_io_expander_t *handle)
|
||||
{
|
||||
esp_io_expander_tca95xx_8bit_t *tca = (esp_io_expander_tca95xx_8bit_t *)__containerof(handle, esp_io_expander_tca95xx_8bit_t, base);
|
||||
|
||||
free(tca);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "../ESP_IOExpander.h"
|
||||
|
||||
class ESP_IOExpander_TCA95xx_8bit: public ESP_IOExpander {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note After using this function, call `init()` will initialize I2C bus.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
* @param config Pointer to I2C bus configuration
|
||||
*/
|
||||
ESP_IOExpander_TCA95xx_8bit(i2c_port_t id, uint8_t address, const i2c_config_t *config): ESP_IOExpander(id, address, config) { };
|
||||
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note After using this function, call `init()` will initialize I2C bus.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
* @param scl SCL pin number
|
||||
* @param sda SDA pin number
|
||||
*/
|
||||
ESP_IOExpander_TCA95xx_8bit(i2c_port_t id, uint8_t address, int scl, int sda): ESP_IOExpander(id, address, scl, sda) { };
|
||||
|
||||
/**
|
||||
* @brief Constructor to create ESP_IOExpander object
|
||||
*
|
||||
* @note If use this function, should initialize I2C bus before call `init()`.
|
||||
*
|
||||
* @param id I2C port number
|
||||
* @param address I2C device address. Should be like `ESP_IO_EXPANDER_I2C_*`.
|
||||
* Can be found in the header file of each IO expander.h.
|
||||
*/
|
||||
ESP_IOExpander_TCA95xx_8bit(i2c_port_t id, uint8_t address): ESP_IOExpander(id, address) { };
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*
|
||||
* @note This function will delete I2C driver if it is initialized by ESP_IOExpander and delete ESP_IOExpander object.
|
||||
*/
|
||||
~ESP_IOExpander_TCA95xx_8bit() override;
|
||||
|
||||
/**
|
||||
* @brief Begin IO expander
|
||||
*
|
||||
*/
|
||||
void begin(void) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief I2C address of the TCA9554
|
||||
*
|
||||
* The 8-bit address format is as follows:
|
||||
*
|
||||
* (Slave Address)
|
||||
* ┌─────────────────┷─────────────────┐
|
||||
* ┌─────┐─────┐─────┐─────┐─────┐─────┐─────┐─────┐
|
||||
* | 0 | 1 | 0 | 0 | A2 | A1 | A0 | R/W |
|
||||
* └─────┘─────┘─────┘─────┘─────┘─────┘─────┘─────┘
|
||||
* └────────┯────────┘ └─────┯──────┘
|
||||
* (Fixed) (Hareware Selectable)
|
||||
*
|
||||
* And the 7-bit slave address is the most important data for users.
|
||||
* For example, if a chip's A0,A1,A2 are connected to GND, it's 7-bit slave address is 0100000b(0x20).
|
||||
* Then users can use `ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000` to init it.
|
||||
*/
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 (0x20)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_001 (0x21)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_010 (0x22)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_011 (0x23)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_100 (0x24)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_101 (0x25)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_110 (0x26)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_111 (0x27)
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2C address of the TCA9554A
|
||||
*
|
||||
* The 8-bit address format is as follows:
|
||||
*
|
||||
* (Slave Address)
|
||||
* ┌─────────────────┷─────────────────┐
|
||||
* ┌─────┐─────┐─────┐─────┐─────┐─────┐─────┐─────┐
|
||||
* | 0 | 1 | 1 | 1 | A2 | A1 | A0 | R/W |
|
||||
* └─────┘─────┘─────┘─────┘─────┘─────┘─────┘─────┘
|
||||
* └────────┯────────┘ └─────┯──────┘
|
||||
* (Fixed) (Hareware Selectable)
|
||||
*
|
||||
* And the 7-bit slave address is the most important data for users.
|
||||
* For example, if a chip's A0,A1,A2 are connected to GND, it's 7-bit slave address is 0111000b(0x38).
|
||||
* Then users can use `ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_000` to init it.
|
||||
*/
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_000 (0x38)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_001 (0x39)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_010 (0x3A)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_011 (0x3B)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_100 (0x3C)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_101 (0x3D)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_110 (0x3E)
|
||||
#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_111 (0x3F)
|
||||
Reference in new issue
Block a user