Skip to content

Commit

Permalink
Merge pull request espressif#141 from espressif2022/feature/add_io_ex…
Browse files Browse the repository at this point in the history
…pander_ht8574

io_expander: Added io_expander of HT8574. (BSP-280)
  • Loading branch information
tore-espressif authored Jun 2, 2023
2 parents 6f02d62 + 2c68f27 commit bf0ba8e
Show file tree
Hide file tree
Showing 7 changed files with 456 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/upload_component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ jobs:
components/bh1750;components/ds18b20;components/es8311;components/es7210;components/fbm320;components/hts221;components/mag3110;components/mpu6050;components/ssd1306;components/esp_lvgl_port;
components/lcd_touch/esp_lcd_touch;components/lcd_touch/esp_lcd_touch_ft5x06;components/lcd_touch/esp_lcd_touch_gt911;components/lcd_touch/esp_lcd_touch_tt21100;components/lcd_touch/esp_lcd_touch_gt1151;components/lcd_touch/esp_lcd_touch_cst816s;
components/lcd/esp_lcd_gc9a01;components/lcd/esp_lcd_ili9341;components/lcd/esp_lcd_ra8875;components/lcd_touch/esp_lcd_touch_stmpe610;components/lcd/esp_lcd_sh1107;components/lcd/esp_lcd_st7796;
components/io_expander/esp_io_expander;components/io_expander/esp_io_expander_tca9554;components/io_expander/esp_io_expander_tca95xx_16bit;
components/io_expander/esp_io_expander;components/io_expander/esp_io_expander_tca9554;components/io_expander/esp_io_expander_tca95xx_16bit;components/io_expander/esp_io_expander_ht8574;
namespace: "espressif"
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
idf_component_register(SRCS "esp_io_expander_ht8574.c" INCLUDE_DIRS "include" REQUIRES "driver")
39 changes: 39 additions & 0 deletions components/io_expander/esp_io_expander_ht8574/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ESP IO Expander Chip HT8574

Implementation of the HT8574 io expander chip with esp_io_expander component.

| Chip | Communication interface | Component name | Link to datasheet |
| :--------------: | :---------------------: | :------------: | :---------------: |
| HT8574 | I2C | esp_io_expander_ht8574 | [datasheet](https://datasheet.lcsc.com/lcsc/2109081930_HTCSEMI-HT8574ARTZ_C2895056.pdf) |

## Add to project

Packages from this repository are uploaded to [Espressif's component service](https://components.espressif.com/).
You can add them to your project via `idf.py add-dependency`, e.g.
```
idf.py add-dependency esp_io_expander_ht8574==1.0.0
```

Alternatively, you can create `idf_component.yml`. More is in [Espressif's documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html).

## Example use

Creation of the component.

```
esp_io_expander_handle_t io_expander = NULL;
esp_io_expander_new_i2c_ht8574(1, ESP_IO_EXPANDER_I2C_HT8574_ADDRESS_000, &io_expander);
```

Set pin 0 and pin 1 with output dircetion and low level:

```
esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_OUTPUT);
esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 0);
```

Print all pins's status to the log:

```
esp_io_expander_print_state(io_expander);
```
146 changes: 146 additions & 0 deletions components/io_expander/esp_io_expander_ht8574/esp_io_expander_ht8574.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* 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 "esp_io_expander.h"
#include "esp_io_expander_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 char *TAG = "ht8574";

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);

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->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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dependencies:
esp_io_expander:
version: ^1.0.1
idf: '>=4.4.2'
description: ESP IO Expander - HT8574
url: https://github.com/espressif/esp-bsp/tree/master/components/io_expander/esp_io_expander_ht8574
version: 1.0.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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_io_expander.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Create a new ht8574 IO expander driver
*
* @note The I2C communication should be initialized before use this function
*
* @param i2c_num: I2C port num
* @param i2c_address: I2C address of chip
* @param handle: IO expander handle
*
* @return
* - ESP_OK: Success, otherwise returns ESP_ERR_xxx
*/
esp_err_t esp_io_expander_new_i2c_ht8574(i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle);

/**
* @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)


#ifdef __cplusplus
}
#endif
Loading

0 comments on commit bf0ba8e

Please sign in to comment.