From 9ab24acac79c1c4189fb940e2a2cb2156f0f47e9 Mon Sep 17 00:00:00 2001 From: YangJie Date: Fri, 6 Jun 2025 18:06:16 +0800 Subject: [PATCH 1/3] refactor: Optimize XL9555 I/O Expander Driver --- boards/ESP32/common/audio/tdd_xl9555_io.c | 149 ----------- boards/ESP32/common/audio/tdd_xl9555_io.h | 54 ---- boards/ESP32/common/io_expander/xl9555.c | 306 ++++++++++++++++++++++ boards/ESP32/common/io_expander/xl9555.h | 41 +++ 4 files changed, 347 insertions(+), 203 deletions(-) delete mode 100644 boards/ESP32/common/audio/tdd_xl9555_io.c delete mode 100644 boards/ESP32/common/audio/tdd_xl9555_io.h create mode 100644 boards/ESP32/common/io_expander/xl9555.c create mode 100644 boards/ESP32/common/io_expander/xl9555.h diff --git a/boards/ESP32/common/audio/tdd_xl9555_io.c b/boards/ESP32/common/audio/tdd_xl9555_io.c deleted file mode 100644 index 2a2be97f..00000000 --- a/boards/ESP32/common/audio/tdd_xl9555_io.c +++ /dev/null @@ -1,149 +0,0 @@ -#include "esp_check.h" -#include "driver/i2c_master.h" - -#include "tal_log.h" -#include "tal_memory.h" - -#include "tdd_xl9555_io.h" - -#define IIC_SPEED_CLK 100000 /* Speed 100K */ - -static i2c_master_dev_handle_t xl9555_handle = NULL; - -/** - * @brief Read data from XL9555 registers - * - * @param data buffer pointer - * @param len buffer length - */ -static void xl9555_read_byte(uint8_t *data, size_t len) -{ - esp_err_t err = ESP_OK; - uint8_t reg_addr = XL9555_INPUT_PORT0_REG; - - err = i2c_master_transmit_receive(xl9555_handle, ®_addr, 1, data, len, -1); - if (err != ESP_OK) { - PR_ERR("i2c_master_transmit_receive error: %d", err); - } -} - -/** - * @brief Write data to XL9555 registers - * - * @param reg register address - * @param data buffer pointer - * @param len buffer length - */ -static void xl9555_write_byte(uint8_t reg, uint8_t *data, size_t len) -{ - esp_err_t err = ESP_OK; - size_t size = len + 1; - uint8_t *buf = NULL; - - buf = tal_malloc(size); - if (buf == NULL) { - PR_ERR("tal_malloc error"); - return; - } - memset(buf, 0, size); - - buf[0] = reg; /* Register address */ - memcpy(buf + 1, data, len); /* Register data */ - - err = i2c_master_transmit(xl9555_handle, buf, size, -1); - if (err != ESP_OK) { - PR_ERR("i2c_master_transmit error: %d, reg: %02x", err, reg); - } - - free(buf); - - return; -} - -static void xl9555_ioconfig(uint16_t value) -{ - uint8_t data[2] = {0}; - - data[0] = (uint8_t)(0xFF & value); - data[1] = (uint8_t)(0xFF & (value >> 8)); - - xl9555_write_byte(XL9555_CONFIG_PORT0_REG, data, 2); - - return; -} - -OPERATE_RET tdd_xl9555_io_init(void *handle, uint16_t config) -{ - i2c_master_bus_handle_t i2c_bus_handle = (i2c_master_bus_handle_t)handle; - - uint8_t r_data[2] = {0}; - - if (i2c_bus_handle == NULL) { - PR_ERR("I2C bus handle is NULL"); - return OPRT_COM_ERROR; - } - - i2c_device_config_t dev_cfg = { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, /* Select Slave address length 7 */ - .scl_speed_hz = IIC_SPEED_CLK, /* Transfer rate */ - .device_address = XL9555_ADDR, /* 7-bit slave address */ - }; - ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_handle, &dev_cfg, &xl9555_handle)); - - /* Read once after power-up to clear interrupt flag */ - xl9555_read_byte(r_data, 2); - /* Configure which expansion pins are input/output mode */ - xl9555_ioconfig(config); - - return OPRT_OK; -} - -OPERATE_RET tdd_xl9555_io_set(uint16_t pin, int val) -{ - uint8_t w_data[2]; - uint16_t mask = 0x0000; - - PR_DEBUG("xl9555 IO pin: %04x, val: %d", pin, val); - - xl9555_read_byte(w_data, 2); - - if (pin <= 0x0080) { - if (val) { - w_data[0] |= (uint8_t)(0xFF & pin); - } else { - w_data[0] &= ~(uint8_t)(0xFF & pin); - } - } else { - if (val) { - w_data[1] |= (uint8_t)(0xFF & (pin >> 8)); - } else { - w_data[1] &= ~(uint8_t)(0xFF & (pin >> 8)); - } - } - - mask = ((uint16_t)w_data[1] << 8) | w_data[0]; - PR_INFO("xl9555 IO mask: %04x", mask); - - xl9555_write_byte(XL9555_OUTPUT_PORT0_REG, w_data, 2); - - return OPRT_OK; -} - -OPERATE_RET tdd_xl9555_io_get(uint16_t pin, int *val) -{ - uint16_t mask = 0; - uint8_t r_data[2] = {0}; - - if (val == NULL) { - PR_ERR("val is NULL"); - return OPRT_INVALID_PARM; - } - - xl9555_read_byte(r_data, 2); - - mask = r_data[1] << 8 | r_data[0]; - - *val = (mask & pin) ? 1 : 0; - - return OPRT_OK; -} \ No newline at end of file diff --git a/boards/ESP32/common/audio/tdd_xl9555_io.h b/boards/ESP32/common/audio/tdd_xl9555_io.h deleted file mode 100644 index ab6a5e1e..00000000 --- a/boards/ESP32/common/audio/tdd_xl9555_io.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __TDD_XL9555_IO_H__ -#define __TDD_XL9555_IO_H__ - -#include "tuya_cloud_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define XL9555_ADDR 0x20 /* XL9555 device 7-bit address --> Refer to manual (9.1. Device Address) */ - -#define XL9555_INPUT_PORT0_REG 0 /* Input register 0 address */ -#define XL9555_INPUT_PORT1_REG 1 /* Input register 1 address */ -#define XL9555_OUTPUT_PORT0_REG 2 /* Output register 0 address */ -#define XL9555_OUTPUT_PORT1_REG 3 /* Output register 1 address */ -#define XL9555_INVERSION_PORT0_REG 4 /* Polarity inversion register 0 address */ -#define XL9555_INVERSION_PORT1_REG 5 /* Polarity inversion register 1 address */ -#define XL9555_CONFIG_PORT0_REG 6 /* Direction configuration register 0 address */ -#define XL9555_CONFIG_PORT1_REG 7 /* Direction configuration register 1 address */ - -/** - * @brief Initialize XL9555 IO expander - * - * @param handle I2C master bus handle - * @param config Configuration value for PORT0 - * - * @return OPERATE_RET Operation result - */ -OPERATE_RET tdd_xl9555_io_init(void *handle, uint16_t config); - -/** - * @brief Set XL9555 IO pin value - * - * @param pin Pin number to set - * @param val Value to set (0 or 1) - * - * @return OPERATE_RET Operation result - */ -OPERATE_RET tdd_xl9555_io_set(uint16_t pin, int val); - -/** - * @brief Read XL9555 IO pin value - * - * @param pin Pin number to read - * - * @return int Pin value (0 or 1) - */ -OPERATE_RET tdd_xl9555_io_get(uint16_t pin, int *val); - -#ifdef __cplusplus -} -#endif - -#endif /* __XL9555_IO_H__ */ \ No newline at end of file diff --git a/boards/ESP32/common/io_expander/xl9555.c b/boards/ESP32/common/io_expander/xl9555.c new file mode 100644 index 00000000..245320a4 --- /dev/null +++ b/boards/ESP32/common/io_expander/xl9555.c @@ -0,0 +1,306 @@ +/** + * @file xl9555.c + * @brief xl9555 module is used to + * @version 0.1 + * @date 2025-06-05 + */ + +#include "xl9555.h" + +#include "board_config.h" + +#if defined(BOARD_IO_EXPANDER_TYPE) && (BOARD_IO_EXPANDER_TYPE == IO_EXPANDER_TYPE_XL9555) + +#include "esp_err.h" +#include "esp_log.h" + +#include "driver/i2c_master.h" + +/*********************************************************** +************************macro define************************ +***********************************************************/ +#define TAG "XL9555" + +#ifndef IO_EXPANDER_XL9555_ADDR +// Default I2C address for XL9555 +#define IO_EXPANDER_XL9555_ADDR (0x20) +#endif // IO_EXPANDER_XL9555_ADDR + +// xl9555 input register address +#define XL9555_INPUT_PORT_0_REG_ADDR (0x00) +#define XL9555_INPUT_PORT_1_REG_ADDR (0x01) +// xl9555 output register address +#define XL9555_OUTPUT_PORT_0_REG_ADDR (0x02) +#define XL9555_OUTPUT_PORT_1_REG_ADDR (0x03) +// xl9555 polarity inversion register address +#define XL9555_POLARITY_INVERSION_PORT_0_REG_ADDR (0x04) +#define XL9555_POLARITY_INVERSION_PORT_1_REG_ADDR (0x05) +// xl9555 configuration register address +#define XL9555_CONFIGURATION_PORT_0_REG_ADDR (0x06) +#define XL9555_CONFIGURATION_PORT_1_REG_ADDR (0x07) + +/*********************************************************** +***********************typedef define*********************** +***********************************************************/ +typedef struct { + i2c_master_bus_handle_t i2c_bus; + i2c_master_dev_handle_t xl9555_handle; +} XL9555_CONFIG_T; + +/*********************************************************** +********************function declaration******************** +***********************************************************/ + +/*********************************************************** +***********************variable define********************** +***********************************************************/ +static XL9555_CONFIG_T xl9555_config = {0}; + +/*********************************************************** +***********************function define********************** +***********************************************************/ + +static i2c_master_bus_handle_t __i2c_init(int i2c_num, int scl_io, int sda_io) +{ + i2c_master_bus_handle_t i2c_bus = NULL; + esp_err_t esp_rt = ESP_OK; + + // retrieve i2c bus handle + esp_rt = i2c_master_get_bus_handle(i2c_num, &i2c_bus); + if (esp_rt == ESP_OK && i2c_bus) { + // ESP_LOGI(TAG, "I2C bus handle retrieved successfully"); + return i2c_bus; + } + + // initialize i2c bus + i2c_master_bus_config_t i2c_bus_cfg = { + .i2c_port = i2c_num, + .sda_io_num = sda_io, + .scl_io_num = scl_io, + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .intr_priority = 0, + .trans_queue_depth = 0, + .flags = + { + .enable_internal_pullup = 1, + }, + }; + esp_rt = i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to create I2C bus: %s", esp_err_to_name(esp_rt)); + return NULL; + } + + return i2c_bus; +} + +int xl9555_init(void) +{ + if (xl9555_config.xl9555_handle) { + ESP_LOGI(TAG, "XL9555 I2C expander already initialized"); + return 0; + } + + xl9555_config.i2c_bus = __i2c_init(I2C_NUM, I2C_SCL_IO, I2C_SDA_IO); + if (!xl9555_config.i2c_bus) { + ESP_LOGE(TAG, "Failed to initialize I2C bus"); + return -1; + } + + i2c_device_config_t i2c_device_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = IO_EXPANDER_XL9555_ADDR, + .scl_speed_hz = 400 * 1000, + .scl_wait_us = 0, + .flags = + { + .disable_ack_check = 0, + }, + }; + ESP_ERROR_CHECK(i2c_master_bus_add_device(xl9555_config.i2c_bus, &i2c_device_cfg, &xl9555_config.xl9555_handle)); + if (NULL == xl9555_config.xl9555_handle) { + ESP_LOGE(TAG, "Failed to create XL9555 I2C expander"); + return -1; + } + ESP_LOGI(TAG, "XL9555 I2C expander initialized successfully"); + + return 0; +} + +int xl9555_set_dir(uint32_t pin_num_mask, int is_input) +{ + esp_err_t esp_rt = ESP_OK; + uint8_t reg, value; + + if (NULL == xl9555_config.xl9555_handle) { + ESP_LOGE(TAG, "XL9555 I2C expander not initialized"); + return -1; + } + + // ESP_LOGI(TAG, "Setting pin direction: pin_num_mask=0x%08X, is_input=%d", pin_num_mask, is_input); + + if (pin_num_mask & 0x000000FF) { + reg = XL9555_CONFIGURATION_PORT_0_REG_ADDR; + + uint8_t read_value = 0; + esp_rt = i2c_master_transmit_receive(xl9555_config.xl9555_handle, ®, 1, &read_value, 1, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to read configuration port 0: %s", esp_err_to_name(esp_rt)); + return -1; + } + // ESP_LOGI(TAG, "Read configuration port 0: 0x%02X", read_value); + + if (is_input) { + value = read_value | (pin_num_mask & 0x000000FF); + } else { + value = read_value & ~(pin_num_mask & 0x000000FF); + } + // ESP_LOGI(TAG, "Setting configuration port 0 to: 0x%02X", value); + + uint8_t buffer[2] = {reg, value}; + esp_rt = i2c_master_transmit(xl9555_config.xl9555_handle, buffer, 2, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to set configuration port 0: %s", esp_err_to_name(esp_rt)); + return -1; + } + } + + if (pin_num_mask & 0x0000FF00) { + reg = XL9555_CONFIGURATION_PORT_1_REG_ADDR; + + uint8_t read_value = 0; + esp_rt = i2c_master_transmit_receive(xl9555_config.xl9555_handle, ®, 1, &read_value, 1, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to read configuration port 1: %s", esp_err_to_name(esp_rt)); + return -1; + } + // ESP_LOGI(TAG, "Read configuration port 1: 0x%02X", read_value); + + if (is_input) { + value = read_value | ((pin_num_mask >> 8) & 0xFF); + } else { + value = read_value & ~((pin_num_mask >> 8) & 0xFF); + } + // ESP_LOGI(TAG, "Setting configuration port 1 to: 0x%02X", value); + + uint8_t buffer[2] = {reg, value}; + esp_rt = i2c_master_transmit(xl9555_config.xl9555_handle, buffer, 2, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to set configuration port 1: %s", esp_err_to_name(esp_rt)); + return -1; + } + } + + return 0; +} + +int xl9555_set_level(uint32_t pin_num_mask, uint32_t level) +{ + esp_err_t esp_rt = ESP_OK; + + if (NULL == xl9555_config.xl9555_handle) { + ESP_LOGE(TAG, "XL9555 I2C expander not initialized"); + return -1; + } + + if (pin_num_mask & 0x000000FF) { + uint8_t reg = XL9555_OUTPUT_PORT_0_REG_ADDR; + uint8_t value = 0; + + uint8_t read_value = 0; + esp_rt = i2c_master_transmit_receive(xl9555_config.xl9555_handle, ®, 1, &read_value, 1, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to read output port 0: %s", esp_err_to_name(esp_rt)); + return -1; + } + // ESP_LOGI(TAG, "Read output port 0: 0x%02X", read_value); + + if (level) { + value = read_value | (pin_num_mask & 0x000000FF); + } else { + value = read_value & (~(pin_num_mask & 0x000000FF)); + } + // ESP_LOGI(TAG, "Setting output port 0 to: 0x%02X", value); + uint8_t buffer[2] = {reg, value}; + esp_rt = i2c_master_transmit(xl9555_config.xl9555_handle, buffer, 2, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to set output port 0: %s", esp_err_to_name(esp_rt)); + return -1; + } + } + + if (pin_num_mask & 0x0000FF00) { + uint8_t reg = XL9555_OUTPUT_PORT_1_REG_ADDR; + uint8_t value = 0; + + uint8_t read_value = 0; + esp_rt = i2c_master_transmit_receive(xl9555_config.xl9555_handle, ®, 1, &read_value, 1, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to read output port 1: %s", esp_err_to_name(esp_rt)); + return -1; + } + // ESP_LOGI(TAG, "Read output port 1: 0x%02X", read_value); + + if (level) { + value = read_value | ((pin_num_mask >> 8) & 0xFF); + } else { + value = read_value & (~((pin_num_mask >> 8) & 0xFF)); + } + // ESP_LOGI(TAG, "Setting output port 1 to: 0x%02X", value); + uint8_t buffer[2] = {reg, value}; + esp_rt = i2c_master_transmit(xl9555_config.xl9555_handle, buffer, 2, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to set output port 1: %s", esp_err_to_name(esp_rt)); + return -1; + } + } + + return 0; +} + +int xl9555_get_level(uint32_t pin_num_mask, uint32_t *level) +{ + esp_err_t esp_rt = ESP_OK; + + if (NULL == xl9555_config.xl9555_handle) { + ESP_LOGE(TAG, "XL9555 I2C expander not initialized"); + return -1; + } + + if (level == NULL) { + ESP_LOGE(TAG, "Level pointer is NULL"); + return -1; + } + + *level = 0; + + if (pin_num_mask & 0x000000FF) { + uint8_t reg = XL9555_INPUT_PORT_0_REG_ADDR; + uint8_t value = 0; + + esp_rt = i2c_master_transmit_receive(xl9555_config.xl9555_handle, ®, 1, &value, 1, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to read input port 0: %s", esp_err_to_name(esp_rt)); + return -1; + } + + *level = (value & (pin_num_mask & 0x000000FF)); + } + + if (pin_num_mask & 0x0000FF00) { + uint8_t reg = XL9555_INPUT_PORT_1_REG_ADDR; + uint8_t value = 0; + + esp_rt = i2c_master_transmit_receive(xl9555_config.xl9555_handle, ®, 1, &value, 1, 100); + if (esp_rt != ESP_OK) { + ESP_LOGE(TAG, "Failed to read input port 1: %s", esp_err_to_name(esp_rt)); + return -1; + } + *level |= (value & ((pin_num_mask >> 8) & 0xFF)) << 8; + } + + return 0; +} + +#endif // IO_EXPANDER_TYPE_XL9555 \ No newline at end of file diff --git a/boards/ESP32/common/io_expander/xl9555.h b/boards/ESP32/common/io_expander/xl9555.h new file mode 100644 index 00000000..d248f69d --- /dev/null +++ b/boards/ESP32/common/io_expander/xl9555.h @@ -0,0 +1,41 @@ +/** + * @file xl9555.h + * @brief xl9555 module is used to + * @version 0.1 + * @date 2025-06-05 + */ + +#ifndef __XL9555_H__ +#define __XL9555_H__ + +#include "tuya_cloud_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************** +************************macro define************************ +***********************************************************/ + +/*********************************************************** +***********************typedef define*********************** +***********************************************************/ + +/*********************************************************** +********************function declaration******************** +***********************************************************/ + +int xl9555_init(void); + +int xl9555_set_dir(uint32_t pin_num_mask, int is_input); + +int xl9555_set_level(uint32_t pin_num_mask, uint32_t level); + +int xl9555_get_level(uint32_t pin_num_mask, uint32_t *level); + +#ifdef __cplusplus +} +#endif + +#endif /* __XL9555_H__ */ From e7caacfd306a144ae8a83fc2e527b5989a299b62 Mon Sep 17 00:00:00 2001 From: YangJie Date: Fri, 6 Jun 2025 18:12:44 +0800 Subject: [PATCH 2/3] refactor: Use the new xl9555 driver --- boards/ESP32/DNESP32S3/board_config.h | 44 +++++++----- boards/ESP32/DNESP32S3/dnesp32s3.c | 53 ++++++++++++--- .../common/audio/tdd_audio_atk_no_codec.c | 67 +++---------------- 3 files changed, 79 insertions(+), 85 deletions(-) diff --git a/boards/ESP32/DNESP32S3/board_config.h b/boards/ESP32/DNESP32S3/board_config.h index 1486d2c5..2739f949 100644 --- a/boards/ESP32/DNESP32S3/board_config.h +++ b/boards/ESP32/DNESP32S3/board_config.h @@ -40,23 +40,33 @@ extern "C" { #define AUDIO_CODEC_DMA_FRAME_NUM (240) #define AUDIO_CODEC_ES8388_ADDR (0x20) -/* XL9555 Extended IO */ -#define SPK_EN_IO 0x0004 /* Speaker enable IO pin */ -#define BEEP_IO 0x0008 -#define AP_INT_IO 0x0001 -#define QMA_INT_IO 0x0002 -#define OV_PWDN_IO 0x0010 -#define OV_RESET_IO 0x0020 -#define GBC_LED_IO 0x0040 -#define GBC_KEY_IO 0x0080 -#define LCD_BL_IO 0x0100 -#define CT_RST_IO 0x0200 -#define SLCD_RST_IO 0x0400 -#define SLCD_PWR_IO 0x0800 -#define KEY3_IO 0x1000 -#define KEY2_IO 0x2000 -#define KEY1_IO 0x4000 -#define KEY0_IO 0x8000 +/* io expander start */ +#define IO_EXPANDER_TYPE_UNKNOWN 0 +#define IO_EXPANDER_TYPE_TCA9554 1 +#define IO_EXPANDER_TYPE_XL9555 2 + +#define BOARD_IO_EXPANDER_TYPE IO_EXPANDER_TYPE_XL9555 + +#define IO_EXPANDER_XL9555_ADDR_000 (0x20) +#define IO_EXPANDER_XL9555_ADDR IO_EXPANDER_XL9555_ADDR_000 + +#define EX_IO_AP_INT (0x0001 << 0) +#define EX_IO_QMA_INT (0x0001 << 1) +#define EX_IO_SPK_EN (0x0001 << 2) +#define EX_IO_BEEP (0x0001 << 3) +#define EX_IO_OV_PWDN (0x0001 << 4) +#define EX_IO_OV_RESET (0x0001 << 5) +#define EX_IO_GBC_LED (0x0001 << 6) +#define EX_IO_GBC_KEY (0x0001 << 7) +#define EX_IO_LCD_BL (0x0001 << 8) +#define EX_IO_CTP_RST (0x0001 << 9) +#define EX_IO_SLCD_RST (0x0001 << 10) +#define EX_IO_SLCD_PWR (0x0001 << 11) +#define EX_IO_KEY_3 (0x0001 << 12) +#define EX_IO_KEY_2 (0x0001 << 13) +#define EX_IO_KEY_1 (0x0001 << 14) +#define EX_IO_KEY_0 (0x0001 << 15) +/* io expander end */ /* display */ #define DISPLAY_TYPE_UNKNOWN 0 diff --git a/boards/ESP32/DNESP32S3/dnesp32s3.c b/boards/ESP32/DNESP32S3/dnesp32s3.c index cfae18c7..0edfa5a6 100644 --- a/boards/ESP32/DNESP32S3/dnesp32s3.c +++ b/boards/ESP32/DNESP32S3/dnesp32s3.c @@ -12,11 +12,12 @@ #include "tdd_audio_codec_bus.h" #include "tdd_audio_es8388_codec.h" -#include "tdd_xl9555_io.h" #include "lcd_st7789_spi.h" #include "board_com_api.h" +#include "xl9555.h" + /*********************************************************** ************************macro define************************ ***********************************************************/ @@ -35,6 +36,42 @@ static TDD_AUDIO_I2S_RX_HANDLE i2s_rx_handle = NULL; /*********************************************************** ***********************function define********************** ***********************************************************/ +static OPERATE_RET __io_expander_init(void) +{ + OPERATE_RET rt = OPRT_OK; + + rt = xl9555_init(); + if (rt != OPRT_OK) { + PR_ERR("xl9555_init failed: %d", rt); + return rt; + } + + uint32_t pin_out_mask = 0; + pin_out_mask |= EX_IO_SPK_EN; + pin_out_mask |= EX_IO_BEEP; + pin_out_mask |= EX_IO_OV_PWDN; + pin_out_mask |= EX_IO_OV_RESET; + pin_out_mask |= EX_IO_GBC_LED; + pin_out_mask |= EX_IO_GBC_KEY; + pin_out_mask |= EX_IO_LCD_BL; + pin_out_mask |= EX_IO_CTP_RST; + pin_out_mask |= EX_IO_SLCD_RST; + pin_out_mask |= EX_IO_SLCD_PWR; + rt = xl9555_set_dir(pin_out_mask, 0); // Set output direction + if (rt != OPRT_OK) { + PR_ERR("xl9555_set_dir out failed: %d", rt); + return rt; + } + uint32_t pin_in_mask = ~pin_out_mask; + rt = xl9555_set_dir(pin_in_mask, 1); // Set input direction + if (rt != OPRT_OK) { + PR_ERR("xl9555_set_dir in failed: %d", rt); + return rt; + } + + return OPRT_OK; +} + static OPERATE_RET __board_register_audio(void) { OPERATE_RET rt = OPRT_OK; @@ -58,14 +95,6 @@ static OPERATE_RET __board_register_audio(void) tdd_audio_codec_bus_i2c_new(bus_cfg, &i2c_bus_handle); tdd_audio_codec_bus_i2s_new(bus_cfg, &i2s_tx_handle, &i2s_rx_handle); - /* P10, P11, P12, P13, and P14 are inputs, other pins are outputs --> 0001 1111 0000 0000 Note: 0 is output, 1 is - * input */ - tdd_xl9555_io_init(i2c_bus_handle, 0xF003); - /* Turn off buzzer */ - tdd_xl9555_io_set(BEEP_IO, 1); - /* Turn on Speaker */ - tdd_xl9555_io_set(SPK_EN_IO, 0); - TDD_AUDIO_ES8388_CODEC_T codec = { .i2c_id = I2C_NUM, .i2c_handle = i2c_bus_handle, @@ -78,8 +107,10 @@ static OPERATE_RET __board_register_audio(void) .pa_pin = -1, /* The speaker power is controlled by XL9555. */ .default_volume = 80, }; - TUYA_CALL_ERR_RETURN(tdd_audio_es8388_codec_register(AUDIO_CODEC_NAME, codec)); + + xl9555_set_dir(EX_IO_SPK_EN, 0); + xl9555_set_level(EX_IO_SPK_EN, 0); // Enable speaker #endif return rt; @@ -94,6 +125,8 @@ OPERATE_RET board_register_hardware(void) { OPERATE_RET rt = OPRT_OK; + TUYA_CALL_ERR_LOG(__io_expander_init()); + TUYA_CALL_ERR_LOG(__board_register_audio()); return rt; diff --git a/boards/ESP32/common/audio/tdd_audio_atk_no_codec.c b/boards/ESP32/common/audio/tdd_audio_atk_no_codec.c index 1445c145..dc436f15 100644 --- a/boards/ESP32/common/audio/tdd_audio_atk_no_codec.c +++ b/boards/ESP32/common/audio/tdd_audio_atk_no_codec.c @@ -60,6 +60,15 @@ static i2c_master_dev_handle_t i2c_device_ = NULL; ***********************************************************/ static void InitializeCodecI2c(const TDD_AUDIO_ATK_NO_CODEC_T *i2s_config) { + esp_err_t esp_rt = ESP_OK; + + // retrieve i2c bus handle + esp_rt = i2c_master_get_bus_handle(i2s_config->i2c_id, &codec_i2c_bus_); + if (esp_rt == ESP_OK && codec_i2c_bus_) { + ESP_LOGI(TAG, "I2C bus handle retrieved successfully"); + return; + } + // Initialize I2C peripheral i2c_master_bus_config_t i2c_bus_cfg = { .i2c_port = i2s_config->i2c_id, @@ -77,63 +86,6 @@ static void InitializeCodecI2c(const TDD_AUDIO_ATK_NO_CODEC_T *i2s_config) ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); } -static void __WriteReg(uint8_t reg, uint8_t value) -{ - uint8_t buffer[2] = {reg, value}; - ESP_ERROR_CHECK(i2c_master_transmit(i2c_device_, buffer, 2, 100)); -} - -static uint8_t __ReadReg(uint8_t reg) -{ - uint8_t buffer[1]; - ESP_ERROR_CHECK(i2c_master_transmit_receive(i2c_device_, ®, 1, buffer, 1, 100)); - return buffer[0]; -} - -static void __SetOutputState(uint8_t bit, uint8_t level) -{ - uint16_t data; - if (bit < 8) { - data = __ReadReg(0x02); - } else { - data = __ReadReg(0x03); - bit -= 8; - } - - data = (data & ~(1 << bit)) | (level << bit); - - if (bit < 8) { - __WriteReg(0x02, data); - } else { - __WriteReg(0x03, data); - } -} - -static void xl9555_in_setup(i2c_master_bus_handle_t i2c_bus, uint8_t addr) -{ - i2c_device_config_t i2c_device_cfg = { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, - .device_address = addr, - .scl_speed_hz = 400 * 1000, - .scl_wait_us = 0, - .flags = - { - .disable_ack_check = 0, - }, - }; - ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus, &i2c_device_cfg, &i2c_device_)); - assert(i2c_device_ != NULL); - - __WriteReg(0x06, 0x3B); - __WriteReg(0x07, 0xFE); - - __WriteReg(0x06, 0x1B); - __WriteReg(0x07, 0xFE); - - __SetOutputState(5, 1); - __SetOutputState(7, 1); -} - static void SetOutputVolume(int volume) { output_volume_ = volume; @@ -213,7 +165,6 @@ OPERATE_RET atk_no_codec_init(TUYA_I2S_NUM_E i2s_num, const TDD_AUDIO_ATK_NO_COD // i2s_config->dma_desc_num, i2s_config->dma_frame_num); InitializeCodecI2c(i2s_config); - xl9555_in_setup(codec_i2c_bus_, 0x20); CreateDuplexChannels(i2s_config->i2s_mck_io, i2s_config->i2s_bck_io, i2s_config->i2s_ws_io, i2s_config->i2s_do_io, i2s_config->i2s_di_io, i2s_config->dma_desc_num, i2s_config->dma_frame_num); From 86c5f295d56805e2f7e89f68e2435f2c9914e108 Mon Sep 17 00:00:00 2001 From: YangJie Date: Fri, 6 Jun 2025 18:15:14 +0800 Subject: [PATCH 3/3] feat: Compatible with both DNESP32-BOX ES8311 and NS4168 versions of hardware --- boards/ESP32/DNESP32S3-BOX/DNESP32S3-BOX.c | 94 +++++++++++++++---- boards/ESP32/DNESP32S3-BOX/board_config.h | 32 ++++++- .../ESP32/common/audio/tdd_audio_8311_codec.c | 3 +- 3 files changed, 108 insertions(+), 21 deletions(-) diff --git a/boards/ESP32/DNESP32S3-BOX/DNESP32S3-BOX.c b/boards/ESP32/DNESP32S3-BOX/DNESP32S3-BOX.c index 92155cc0..b106034e 100644 --- a/boards/ESP32/DNESP32S3-BOX/DNESP32S3-BOX.c +++ b/boards/ESP32/DNESP32S3-BOX/DNESP32S3-BOX.c @@ -9,16 +9,15 @@ #include "tal_api.h" -#if USE_8311 -#include "tdd_audio_8311_codec.h" -#else -#include "tdd_audio_atk_no_codec.h" -#endif - #include "board_config.h" #include "lcd_st7789_80.h" #include "board_com_api.h" +#include "xl9555.h" + +#include "tdd_audio_8311_codec.h" +#include "tdd_audio_atk_no_codec.h" + /*********************************************************** ************************macro define************************ ***********************************************************/ @@ -26,25 +25,72 @@ /*********************************************************** ***********************typedef define*********************** ***********************************************************/ +typedef struct { + uint8_t is_es8311; // 1-ES8311, 0-NS4168 +} DNSESP32S3_BOX_CONFIG_T; /*********************************************************** ***********************variable define********************** ***********************************************************/ +static DNSESP32S3_BOX_CONFIG_T sg_dnesp32s3_box = {0}; /*********************************************************** ***********************function define********************** ***********************************************************/ +static OPERATE_RET __io_expander_init(void) +{ + OPERATE_RET rt = OPRT_OK; + + rt = xl9555_init(); + if (rt != OPRT_OK) { + PR_ERR("xl9555_init failed: %d", rt); + return rt; + } + + uint32_t pin_out_mask = 0; + pin_out_mask |= EX_IO_BEEP; + pin_out_mask |= EX_IO_CTP_RST; + pin_out_mask |= EX_IO_LCD_BL; + pin_out_mask |= EX_IO_LED_R; + pin_out_mask |= EX_IO_1_2; + pin_out_mask |= EX_IO_1_3; + pin_out_mask |= EX_IO_1_4; + pin_out_mask |= EX_IO_1_5; + pin_out_mask |= EX_IO_1_6; + pin_out_mask |= EX_IO_1_7; + rt = xl9555_set_dir(pin_out_mask, 0); // Set output direction + if (rt != OPRT_OK) { + PR_ERR("xl9555_set_dir out failed: %d", rt); + return rt; + } + uint32_t pin_in_mask = ~pin_out_mask; + rt = xl9555_set_dir(pin_in_mask, 1); // Set input direction + if (rt != OPRT_OK) { + PR_ERR("xl9555_set_dir in failed: %d", rt); + return rt; + } + + return OPRT_OK; +} + static OPERATE_RET __board_register_audio(void) { OPERATE_RET rt = OPRT_OK; #if defined(AUDIO_CODEC_NAME) + xl9555_set_dir(EX_IO_SPK_CTRL, 1); + uint32_t read_level = 0; + xl9555_get_level(EX_IO_SPK_CTRL, &read_level); + PR_DEBUG("Speaker control level: 0x%04x", read_level); + if (EX_IO_SPK_CTRL & read_level) { + sg_dnesp32s3_box.is_es8311 = 1; // ES8311 codec + PR_DEBUG("ES8311 codec is enabled"); + } else { + sg_dnesp32s3_box.is_es8311 = 0; // NS4168 codec + PR_DEBUG("NS4168 codec is enabled"); + } -#if USE_8311 TDD_AUDIO_8311_CODEC_T cfg = {0}; -#else - TDD_AUDIO_ATK_NO_CODEC_T cfg = {0}; -#endif cfg.i2c_id = I2C_NUM; cfg.i2c_scl_io = I2C_SCL_IO; @@ -63,13 +109,18 @@ static OPERATE_RET __board_register_audio(void) cfg.dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM; cfg.default_volume = 80; -#if USE_8311 - TUYA_CALL_ERR_RETURN(tdd_audio_8311_codec_register(AUDIO_CODEC_NAME, cfg)); -#else - TUYA_CALL_ERR_RETURN(tdd_audio_atk_no_codec_register(AUDIO_CODEC_NAME, cfg)); -#endif + if (sg_dnesp32s3_box.is_es8311) { + TUYA_CALL_ERR_RETURN(tdd_audio_8311_codec_register(AUDIO_CODEC_NAME, cfg)); + } else { + TDD_AUDIO_ATK_NO_CODEC_T NS4168_cfg = {0}; + memcpy(&NS4168_cfg, &cfg, sizeof(TDD_AUDIO_ATK_NO_CODEC_T)); + TUYA_CALL_ERR_RETURN(tdd_audio_atk_no_codec_register(AUDIO_CODEC_NAME, NS4168_cfg)); + } + xl9555_set_dir(EX_IO_SPK_CTRL, 0); + xl9555_set_level(EX_IO_SPK_CTRL, 1); // Enable speaker #endif + return rt; } @@ -82,6 +133,8 @@ OPERATE_RET board_register_hardware(void) { OPERATE_RET rt = OPRT_OK; + TUYA_CALL_ERR_LOG(__io_expander_init()); + TUYA_CALL_ERR_LOG(__board_register_audio()); return rt; @@ -89,7 +142,16 @@ OPERATE_RET board_register_hardware(void) int board_display_init(void) { - return lcd_st7789_80_init(); + int rt = lcd_st7789_80_init(); + if (rt != OPRT_OK) { + PR_ERR("lcd_st7789_80_init failed: %d", rt); + return rt; + } + + xl9555_set_dir(EX_IO_LCD_BL, 0); + xl9555_set_level(EX_IO_LCD_BL, 1); // Enable LCD backlight + + return 0; } void *board_display_get_panel_io_handle(void) diff --git a/boards/ESP32/DNESP32S3-BOX/board_config.h b/boards/ESP32/DNESP32S3-BOX/board_config.h index 5f52a3bb..fcef91a8 100644 --- a/boards/ESP32/DNESP32S3-BOX/board_config.h +++ b/boards/ESP32/DNESP32S3-BOX/board_config.h @@ -18,9 +18,6 @@ extern "C" { /*********************************************************** ************************macro define************************ ***********************************************************/ -/* Example configurations */ -#define USE_8311 (0) // 1-ES8311 0-NS4168 - #define I2S_INPUT_SAMPLE_RATE (16000) #define I2S_OUTPUT_SAMPLE_RATE (16000) @@ -63,6 +60,35 @@ extern "C" { #define DISPLAY_WIDTH 320 #define DISPLAY_HEIGHT 240 +/* io expander start */ +#define IO_EXPANDER_TYPE_UNKNOWN 0 +#define IO_EXPANDER_TYPE_TCA9554 1 +#define IO_EXPANDER_TYPE_XL9555 2 + +#define BOARD_IO_EXPANDER_TYPE IO_EXPANDER_TYPE_XL9555 + +#define IO_EXPANDER_XL9555_ADDR_000 (0x20) +#define IO_EXPANDER_XL9555_ADDR IO_EXPANDER_XL9555_ADDR_000 + +#define EX_IO_AP_INT (0x0001 << 0) +#define EX_IO_QMA_INT (0x0001 << 1) +#define EX_IO_BEEP (0x0001 << 2) +#define EX_IO_KEY_1 (0x0001 << 3) +#define EX_IO_KEY_0 (0x0001 << 4) +#define EX_IO_SPK_CTRL (0x0001 << 5) +#define EX_IO_CTP_RST (0x0001 << 6) +#define EX_IO_LCD_BL (0x0001 << 7) +#define EX_IO_LED_R (0x0001 << 8) +#define EX_IO_CTP_INT (0x0001 << 9) +#define EX_IO_1_2 (0x0001 << 10) +#define EX_IO_1_3 (0x0001 << 11) +#define EX_IO_1_4 (0x0001 << 12) +#define EX_IO_1_5 (0x0001 << 13) +#define EX_IO_1_6 (0x0001 << 14) +#define EX_IO_1_7 (0x0001 << 15) + +/* io expander end */ + /* display */ #define DISPLAY_TYPE_UNKNOWN 0 #define DISPLAY_TYPE_OLED_SSD1306 1 diff --git a/boards/ESP32/common/audio/tdd_audio_8311_codec.c b/boards/ESP32/common/audio/tdd_audio_8311_codec.c index 426268d6..eb8f9357 100644 --- a/boards/ESP32/common/audio/tdd_audio_8311_codec.c +++ b/boards/ESP32/common/audio/tdd_audio_8311_codec.c @@ -200,7 +200,6 @@ OPERATE_RET codec_8311_init(TUYA_I2S_NUM_E i2s_num, const TDD_AUDIO_8311_CODEC_T void *i2c_master_handle = NULL; i2c_port_t i2c_port = (i2c_port_t)(i2s_config->i2c_id); uint8_t es8311_addr = i2s_config->es8311_addr; - bool use_mclk = true; pa_pin_ = i2s_config->gpio_output_pa; input_sample_rate_ = i2s_config->mic_sample_rate; output_sample_rate_ = i2s_config->spk_sample_rate; @@ -247,7 +246,7 @@ OPERATE_RET codec_8311_init(TUYA_I2S_NUM_E i2s_num, const TDD_AUDIO_8311_CODEC_T es8311_cfg.gpio_if = gpio_if_; es8311_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH; es8311_cfg.pa_pin = pa_pin_; - es8311_cfg.use_mclk = use_mclk; + es8311_cfg.use_mclk = ((i2s_config->i2s_mck_io != -1) ? true : false); es8311_cfg.hw_gain.pa_voltage = 5.0; es8311_cfg.hw_gain.codec_dac_voltage = 3.3; codec_if_ = es8311_codec_new(&es8311_cfg);