Переглянути джерело

feat: 代码整理, 抽离io控制

kindring 4 днів тому
батько
коміт
90776d86e2
11 змінених файлів з 528 додано та 160 видалено
  1. 5 0
      main/app_ble.c
  2. 8 0
      main/app_ble.h
  3. 186 0
      main/app_io.c
  4. 25 0
      main/app_io.h
  5. 32 0
      main/app_manager.c
  6. 21 0
      main/app_manager.h
  7. 1 0
      main/audio.h
  8. 219 0
      main/ble_nvs.c
  9. 21 0
      main/ble_nvs.h
  10. 3 3
      main/bt_app_av.c
  11. 7 157
      main/main.c

+ 5 - 0
main/app_ble.c

@@ -0,0 +1,5 @@
+//
+// Created by kindring on 2025/12/26.
+//
+
+#include "app_ble.h"

+ 8 - 0
main/app_ble.h

@@ -0,0 +1,8 @@
+//
+// Created by kindring on 2025/12/26.
+//
+
+#ifndef YUNTUNE_APP_BLE_H
+#define YUNTUNE_APP_BLE_H
+
+#endif //YUNTUNE_APP_BLE_H

+ 186 - 0
main/app_io.c

@@ -0,0 +1,186 @@
+//
+// Created by kindring on 2025/12/26.
+//
+
+#include "esp_log.h"
+
+#include "app_io.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+
+
+
+#define TAG "app_io"
+
+static QueueHandle_t g_io_evt_queue = NULL;
+
+
+static void io_task(void* arg)
+{
+    uint32_t io_num;
+    while (true)
+    {
+        if(xQueueReceive(g_io_evt_queue, &io_num, portMAX_DELAY))
+        {
+            // 消抖处理
+            vTaskDelay(50 / portTICK_PERIOD_MS);
+            if(gpio_get_level(io_num) == 0)
+            { // 确认仍然是低电平
+                ESP_LOGI(TAG, "GPIO%"PRIu32" interrupt, button pressed", io_num);
+                next_audio_mode();
+            }
+        }
+    }
+}
+
+static void IRAM_ATTR gpio_isr_handler(void* arg)
+{
+    const uint32_t gpio_num = (uint32_t) arg;
+    xQueueSendFromISR(g_io_evt_queue, &gpio_num, NULL);
+}
+
+/**
+ * 切换系统状态灯
+ * @param on
+ * @return
+ */
+esp_err_t set_led_io(const bool on)
+{
+    const esp_err_t err = gpio_set_level(IO_LED, on);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Set system to %d failed: %s", on, esp_err_to_name(err));
+        return err;
+    }
+    return ESP_OK;
+}
+
+esp_err_t init_led_io() {
+    // system state led
+    const gpio_config_t led_io_conf = {
+        .pin_bit_mask = (1ULL << IO_LED),  // GPIO15
+        .mode = GPIO_MODE_OUTPUT,               // 输出模式
+        .pull_up_en = GPIO_PULLUP_DISABLE,      // 禁用上拉
+        .pull_down_en = GPIO_PULLDOWN_DISABLE,  // 禁用下拉
+        .intr_type = GPIO_INTR_DISABLE          // 禁用中断
+    };
+
+    // 配置GPIO
+    const esp_err_t err = gpio_config(&led_io_conf);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "system led config failed: %s", esp_err_to_name(err));
+        return err;
+    }
+
+    return set_led_io(0);
+}
+
+
+
+esp_err_t init_btn_io() {
+    // 配置GPIO2为输入模式,用于低电平中断
+    const gpio_config_t btn_conf = {
+        .pin_bit_mask = (1ULL << IO_BTN),
+        .mode = GPIO_MODE_INPUT,
+        .pull_up_en = GPIO_PULLUP_ENABLE,       // 启用上拉,按钮按下时拉低
+        .pull_down_en = GPIO_PULLDOWN_DISABLE,
+        .intr_type = GPIO_INTR_NEGEDGE          // 下降沿触发(按下按钮)
+    };
+
+    const esp_err_t err = gpio_config(&btn_conf);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "BTN config failed: %s", esp_err_to_name(err));
+        return err;
+    }
+    // 注册中断服务
+
+    gpio_isr_handler_add(IO_BTN, gpio_isr_handler, (void*) IO_BTN);
+    return ESP_OK;
+}
+
+// 更新输出引脚状态
+esp_err_t update_output_mode(const audio_mode_t mode)
+{
+    esp_err_t err = ESP_OK;
+    // 根据音频模式设置GPIO19输出状态
+    switch(mode) {
+        case AUDIO_MODE_NORMAL:
+            err = gpio_set_level(IO_OUTPUT_SW, 0); // 低电平
+            break;
+        case AUDIO_MODE_BASS_BOOST:
+            err = gpio_set_level(IO_OUTPUT_SW, 1); // 高电平
+            break;
+        default:
+            err = gpio_set_level(IO_OUTPUT_SW, 0);
+            break;
+    }
+    ESP_LOGD(TAG, "GPIO19 set to: %d", gpio_get_level(IO_OUTPUT_SW));
+    return err;
+}
+
+// 初始化输出引脚
+esp_err_t init_output_io() {
+    // 配置GPIO2为输入模式,用于低电平中断
+    const gpio_config_t output_conf = {
+        .pin_bit_mask = (1ULL << IO_OUTPUT_SW),
+        .mode = GPIO_MODE_OUTPUT,
+        .pull_up_en = GPIO_PULLUP_DISABLE,
+        .pull_down_en = GPIO_PULLDOWN_DISABLE,
+        .intr_type = GPIO_INTR_DISABLE
+    };
+
+    const esp_err_t err = gpio_config(&output_conf);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "OUTPUT config failed: %s", esp_err_to_name(err));
+        return err;
+    }
+    return ESP_OK;
+}
+
+// 启用或者关闭功放
+esp_err_t enable_amp(const bool on) {
+    // 低有效, 高无效, 需要将电平反转
+    const int io_level = !on;
+    const esp_err_t err = gpio_set_level(IO_AMP_EN, io_level );
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "%s apm failed: %s", on? "ENABLE" : "DISABLE", esp_err_to_name(err));
+        return err;
+    }
+    return ESP_OK;
+}
+
+esp_err_t init_amp_io() {
+    // 配置GPIO32为输出模式并拉低电平
+    const gpio_config_t io_conf = {
+        .pin_bit_mask = (1ULL << IO_AMP_EN),  // GPIO32
+        .mode = GPIO_MODE_OUTPUT,               // 输出模式
+        .pull_up_en = GPIO_PULLUP_DISABLE,      // 禁用上拉
+        .pull_down_en = GPIO_PULLDOWN_DISABLE,  // 禁用下拉
+        .intr_type = GPIO_INTR_DISABLE          // 禁用中断
+    };
+
+    // 配置GPIO
+    const esp_err_t err = gpio_config(&io_conf);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "IO_AMP_EN config failed: %s", esp_err_to_name(err));
+        return err;
+    }
+    return enable_amp(false);
+}
+
+
+// 初始化io引脚配置
+int init_io() {
+    // 安装GPIO ISR服务
+    esp_err_t err = gpio_install_isr_service(0);
+    g_io_evt_queue = xQueueCreate(10, sizeof(uint32_t));
+    xTaskCreate(io_task, "io_task", 2048, NULL, 10, NULL);
+
+    init_amp_io();
+    init_output_io();
+    init_led_io();
+    init_btn_io();
+
+    return 0;
+}

+ 25 - 0
main/app_io.h

@@ -0,0 +1,25 @@
+//
+// Created by kindring on 2025/12/26.
+//
+
+#ifndef YUNTUNE_APP_IO_H
+#define YUNTUNE_APP_IO_H
+#include "driver/gpio.h"
+#include "app_manager.h"
+
+
+// 功放使能引脚 低有效
+#define IO_AMP_EN           GPIO_NUM_32
+// 状态显示LED
+#define IO_LED              GPIO_NUM_15
+// 按钮引脚
+#define IO_BTN              GPIO_NUM_2
+// 输出选择引脚 1:AUX 0:蓝牙
+#define IO_OUTPUT_SW        GPIO_NUM_19
+
+esp_err_t set_led_io(const bool on);
+esp_err_t enable_amp(const bool on);
+esp_err_t update_output_mode(audio_mode_t  mode);
+int init_io();
+
+#endif //YUNTUNE_APP_IO_H

+ 32 - 0
main/app_manager.c

@@ -0,0 +1,32 @@
+//
+// Created by kindring on 2025/12/26.
+//
+
+
+#include "esp_log.h"
+
+#include "app_io.h"
+#include "app_manager.h"
+
+
+#define TAG "app_manager"
+
+audio_mode_t m_current_audio_mode = AUDIO_MODE_NORMAL;
+
+const char* mode_names[] = {
+    "NORMAL",
+    "BASS_BOOST",
+};
+
+// 切换为下一个播放模式
+audio_mode_t next_audio_mode()
+{
+    const audio_mode_t next_audio_mode = (m_current_audio_mode + 1) % AUDIO_MODE_MAX;
+
+    ESP_LOGI(TAG, "Audio mode switched to: %s", mode_names[next_audio_mode]);
+
+    update_output_mode(next_audio_mode);
+    return next_audio_mode;
+}
+
+

+ 21 - 0
main/app_manager.h

@@ -0,0 +1,21 @@
+//
+// Created by kindring on 2025/12/26.
+//
+
+#ifndef YUNTUNE_APP_MANAGER_H
+#define YUNTUNE_APP_MANAGER_H
+
+/**
+ * 功放工作模式, 切换aux与蓝牙模式
+ */
+typedef enum {
+    AUDIO_MODE_NORMAL = 0,
+    AUDIO_MODE_BASS_BOOST,
+    AUDIO_MODE_MAX
+} audio_mode_t;
+
+audio_mode_t next_audio_mode();
+
+
+
+#endif //YUNTUNE_APP_MANAGER_H

+ 1 - 0
main/audio.h

@@ -8,4 +8,5 @@
 #define I2S_DO_IO       (GPIO_NUM_23)
 
 
+
 #endif /* __AUDIO_H__*/

+ 219 - 0
main/ble_nvs.c

@@ -0,0 +1,219 @@
+//
+// Created by kindring on 2025/12/25.
+//
+
+#include "ble_nvs.h"
+
+#include "esp_err.h"
+#include "esp_log.h"
+#include "nvs_flash.h"
+
+static const char *TAG = "BLE_NVS";
+
+#define NVS_STORAGE_NAMESPACE "bt_device"
+#define NVS_KEY_BT_ADDR "last_addr"
+#define NVS_KEY_BT_NAME "last_name"
+#define NVS_KEY_IS_PAIRED "is_paired"
+#define NVS_KEY_CONNECT_COUNT "connect_count"
+#define NVS_KEY_LAST_CONNECT_TIME "last_connect_time"
+#define NVS_KEY_AUTO_RECONNECT "auto_reconnect"
+
+static bool s_auto_reconnect = true;
+static bool s_reconnect_active = false;
+
+esp_err_t ble_nvs_init()
+{
+    esp_err_t ret = nvs_flash_init();
+
+    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
+        ESP_LOGW(TAG, "NVS partition needs to be erased");
+        ESP_ERROR_CHECK(nvs_flash_erase());
+        ret = nvs_flash_init();
+    }
+
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to initialize NVS: %s", esp_err_to_name(ret));
+        return ret;
+    }
+
+    ESP_LOGI(TAG, "Bluetooth Device Manager initialized");
+    return ESP_OK;
+}
+
+esp_err_t bt_device_save_info(const bt_device_info_t *device_info)
+{
+    if (!device_info) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    nvs_handle_t handle;
+    esp_err_t ret;
+
+    ret = nvs_open(NVS_STORAGE_NAMESPACE, NVS_READWRITE, &handle);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(ret));
+        return ret;
+    }
+
+    // 保存蓝牙设备地址
+    ret = nvs_set_blob(handle, NVS_KEY_BT_ADDR, device_info->bda, 6);
+    if (ret != ESP_OK)
+    {
+        ESP_LOGE(TAG, "Failed to save Bluetooth address: %s", esp_err_to_name(ret));
+        nvs_close(handle);
+        return ret;
+    }
+
+    // 保存设备名称
+    ret = nvs_set_str(handle, NVS_KEY_BT_NAME, device_info->device_name);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to save device name: %s", esp_err_to_name(ret));
+        nvs_close(handle);
+        return ret;
+    }
+
+    // 保存配对状态
+    ret = nvs_set_u8(handle, NVS_KEY_IS_PAIRED, device_info->is_paired ? 1 : 0);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to save pairing status: %s", esp_err_to_name(ret));
+        nvs_close(handle);
+        return ret;
+    }
+
+    // 保存连接次数
+    ret = nvs_set_u32(handle, NVS_KEY_CONNECT_COUNT, device_info->connect_count);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to save connect count: %s", esp_err_to_name(ret));
+        nvs_close(handle);
+        return ret;
+    }
+
+    // 保存最后连接时间
+    ret = nvs_set_u64(handle, NVS_KEY_LAST_CONNECT_TIME, device_info->last_connect_time);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to save last connect time: %s", esp_err_to_name(ret));
+        nvs_close(handle);
+        return ret;
+    }
+
+    // 提交更改
+    ret = nvs_commit(handle);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to commit NVS changes: %s", esp_err_to_name(ret));
+    }
+
+    nvs_close(handle);
+
+    ESP_LOGI(TAG, "Bluetooth device info saved successfully");
+    return ret;
+}
+
+esp_err_t bt_device_load_info(bt_device_info_t *device_info)
+{
+    if (!device_info) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    nvs_handle_t handle;
+    esp_err_t ret;
+
+    ret = nvs_open(NVS_STORAGE_NAMESPACE, NVS_READONLY, &handle);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(ret));
+        return ret;
+    }
+
+    // 读取蓝牙设备地址
+    size_t addr_len = 6;
+    ret = nvs_get_blob(handle, NVS_KEY_BT_ADDR, device_info->bda, &addr_len);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to load Bluetooth address: %s", esp_err_to_name(ret));
+        nvs_close(handle);
+        return ret;
+    }
+
+    // 读取设备名称
+    size_t name_len = sizeof(device_info->device_name);
+    ret = nvs_get_str(handle, NVS_KEY_BT_NAME, device_info->device_name, &name_len);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to load device name: %s", esp_err_to_name(ret));
+        nvs_close(handle);
+        return ret;
+    }
+
+    // 读取配对状态
+    uint8_t is_paired;
+    ret = nvs_get_u8(handle, NVS_KEY_IS_PAIRED, &is_paired);
+    if (ret == ESP_OK) {
+        device_info->is_paired = (is_paired != 0);
+    } else {
+        device_info->is_paired = false;
+    }
+
+    // 读取连接次数
+    ret = nvs_get_u32(handle, NVS_KEY_CONNECT_COUNT, &device_info->connect_count);
+    if (ret != ESP_OK) {
+        device_info->connect_count = 0;
+    }
+
+    // 读取最后连接时间
+    ret = nvs_get_u64(handle, NVS_KEY_LAST_CONNECT_TIME, &device_info->last_connect_time);
+    if (ret != ESP_OK) {
+        device_info->last_connect_time = 0;
+    }
+
+    nvs_close(handle);
+
+    ESP_LOGI(TAG, "Bluetooth device info loaded successfully");
+    return ESP_OK;
+}
+
+esp_err_t bt_device_clear_info(void)
+{
+    nvs_handle_t handle;
+    esp_err_t ret;
+
+    ret = nvs_open(NVS_STORAGE_NAMESPACE, NVS_READWRITE, &handle);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "Error opening NVS handle: %s", esp_err_to_name(ret));
+        return ret;
+    }
+
+    // 清除所有键值
+    nvs_erase_all(handle);
+    ret = nvs_commit(handle);
+    nvs_close(handle);
+
+    ESP_LOGI(TAG, "Bluetooth device info cleared");
+    return ret;
+}
+
+void bt_device_set_auto_reconnect(bool enable)
+{
+    s_auto_reconnect = enable;
+
+    nvs_handle_t handle;
+    if (nvs_open(NVS_STORAGE_NAMESPACE, NVS_READWRITE, &handle) == ESP_OK) {
+        nvs_set_u8(handle, NVS_KEY_AUTO_RECONNECT, enable ? 1 : 0);
+        nvs_commit(handle);
+        nvs_close(handle);
+    }
+}
+
+bool bt_device_get_auto_reconnect(void)
+{
+    uint8_t auto_reconnect;
+    nvs_handle_t handle;
+    esp_err_t ret;
+
+    ret = nvs_open(NVS_STORAGE_NAMESPACE, NVS_READONLY, &handle);
+    if (ret == ESP_OK) {
+        ret = nvs_get_u8(handle, NVS_KEY_AUTO_RECONNECT, &auto_reconnect);
+        nvs_close(handle);
+        if (ret == ESP_OK) {
+            s_auto_reconnect = (auto_reconnect != 0);
+        }
+    }
+
+    return s_auto_reconnect;
+}

+ 21 - 0
main/ble_nvs.h

@@ -0,0 +1,21 @@
+//
+// Created by kindring on 2025/12/25.
+//
+
+#ifndef YUNTUNE_BLE_NVS_H
+#define YUNTUNE_BLE_NVS_H
+
+#define BT_DEVICE_NAME_MAX_LEN 64
+#define MAX_RECONNECT_ATTEMPTS 3
+// 蓝牙设备信息结构
+typedef struct {
+    uint8_t bda[6];                           // 蓝牙设备地址
+    char device_name[BT_DEVICE_NAME_MAX_LEN]; // 设备名称
+    bool is_paired;                           // 是否已配对
+    uint32_t connect_count;                   // 连接次数
+    uint64_t last_connect_time;               // 最后连接时间戳
+} bt_device_info_t;
+
+
+
+#endif //YUNTUNE_BLE_NVS_H

+ 3 - 3
main/bt_app_av.c

@@ -30,6 +30,7 @@
 #include "sys/lock.h"
 
 #include "audio.h"
+#include "ble_device_manager.h"
 
 /* AVRCP used transaction labels */
 #define APP_RC_CT_TL_GET_CAPS            (0)
@@ -280,14 +281,13 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param)
             esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
             bt_i2s_driver_uninstall();
             bt_i2s_task_shut_down();
-            // todo 自动重连回设备
-            // 如果启用了自动重连,尝试重新连接
+            // todo 如果启用了自动重连,尝试重新连接
         } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED){
             esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
             bt_i2s_task_start_up();
             // 保存连接的设备信息到NVS
             // todo 获取设备名称
-
+            bt_device_update_stats(bda, "Unknown_Device"); // 实际应用中应该获取设备名称
 
         } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTING) {
             bt_i2s_driver_install();

+ 7 - 157
main/main.c

@@ -9,6 +9,8 @@
 #include <unistd.h>
 #include <string.h>
 #include <inttypes.h>
+
+#include "app_io.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/queue.h"
@@ -49,7 +51,7 @@ typedef enum {
 } audio_mode_t;
 
 static audio_mode_t current_audio_mode = AUDIO_MODE_NORMAL;
-static QueueHandle_t gpio_evt_queue = NULL;
+
 
 /********************************
  * STATIC FUNCTION DECLARATIONS
@@ -65,8 +67,7 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param);
 
 /* GPIO interrupt handler */
 static void IRAM_ATTR gpio_isr_handler(void* arg);
-/* GPIO task to handle events */
-static void gpio_task(void* arg);
+
 /* Switch audio mode */
 static void switch_audio_mode(void);
 /* Update GPIO output based on audio mode */
@@ -210,58 +211,6 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
 }
 
 
-static void IRAM_ATTR gpio_isr_handler(void* arg)
-{
-    uint32_t gpio_num = (uint32_t) arg;
-    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
-}
-
-static void gpio_task(void* arg)
-{
-    uint32_t io_num;
-    for(;;) {
-        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
-            // 消抖处理
-            vTaskDelay(50 / portTICK_PERIOD_MS);
-            if(gpio_get_level(io_num) == 0) { // 确认仍然是低电平
-                ESP_LOGI(BT_AV_TAG, "GPIO%"PRIu32" interrupt, button pressed", io_num);
-                switch_audio_mode();
-            }
-        }
-    }
-}
-static void switch_audio_mode(void)
-{
-    // 切换音频模式
-    current_audio_mode = (current_audio_mode + 1) % AUDIO_MODE_MAX;
-    
-    const char* mode_names[] = {
-        "NORMAL",
-        "BASS_BOOST", 
-    };
-    
-    ESP_LOGI(BT_AV_TAG, "Audio mode switched to: %s", mode_names[current_audio_mode]);
-    
-    // 更新GPIO输出状态
-    update_gpio_output();
-}
-static void update_gpio_output(void)
-{
-    // 根据音频模式设置GPIO19输出状态
-    switch(current_audio_mode) {
-        case AUDIO_MODE_NORMAL:
-            gpio_set_level(GPIO_OUTPUT, 0); // 低电平
-            break;
-        case AUDIO_MODE_BASS_BOOST:
-            gpio_set_level(GPIO_OUTPUT, 1); // 高电平
-            break;
-        default:
-            gpio_set_level(GPIO_OUTPUT, 0);
-            break;
-    }
-    
-    ESP_LOGI(BT_AV_TAG, "GPIO19 set to: %d", gpio_get_level(GPIO_OUTPUT));
-}
 
 /*******************************
  * MAIN ENTRY POINT
@@ -277,107 +226,9 @@ void app_main(void)
         err = nvs_flash_init();
     }
     ESP_ERROR_CHECK(err);
-
-    // todo 拉低引脚 io32
-    // todo 拉低引脚 io32 - 已完善
-    // 配置GPIO32为输出模式并拉低电平
-    gpio_config_t io_conf = {
-        .pin_bit_mask = (1ULL << GPIO_NUM_32),  // GPIO32
-        .mode = GPIO_MODE_OUTPUT,               // 输出模式
-        .pull_up_en = GPIO_PULLUP_DISABLE,      // 禁用上拉
-        .pull_down_en = GPIO_PULLDOWN_DISABLE,  // 禁用下拉
-        .intr_type = GPIO_INTR_DISABLE          // 禁用中断
-    };
-    
-    // 配置GPIO
-    err = gpio_config(&io_conf);
-    if (err != ESP_OK) {
-        ESP_LOGE(BT_AV_TAG, "GPIO32 config failed: %s", esp_err_to_name(err));
-        return;
-    }
-    
-    // 拉低GPIO32
-    err = gpio_set_level(GPIO_NUM_32, 0);
-    if (err != ESP_OK) {
-        ESP_LOGE(BT_AV_TAG, "Set GPIO32 low failed: %s", esp_err_to_name(err));
-        return;
-    }
-
-    // system state led
-    gpio_config_t led_io_conf = {
-        .pin_bit_mask = (1ULL << GPIO_NUM_15),  // GPIO15
-        .mode = GPIO_MODE_OUTPUT,               // 输出模式
-        .pull_up_en = GPIO_PULLUP_DISABLE,      // 禁用上拉
-        .pull_down_en = GPIO_PULLDOWN_DISABLE,  // 禁用下拉
-        .intr_type = GPIO_INTR_DISABLE          // 禁用中断
-    };
-    
-    // 配置GPIO
-    err = gpio_config(&led_io_conf);
-    if (err != ESP_OK) {
-        ESP_LOGE(BT_AV_TAG, "GPIO15 config failed: %s", esp_err_to_name(err));
-        return;
-    }
-    
-    // 拉低GPIO15
-    err = gpio_set_level(GPIO_NUM_15, 0);
-    if (err != ESP_OK) {
-        ESP_LOGE(BT_AV_TAG, "Set GPIO15 low failed: %s", esp_err_to_name(err));
-        return;
-    }
-    
-    ESP_LOGI(BT_AV_TAG, "GPIO15 set to low level");
-
-    // 配置GPIO2为输入模式,用于低电平中断
-    gpio_config_t btn_conf = {
-        .pin_bit_mask = (1ULL << GPIO_BTN),
-        .mode = GPIO_MODE_INPUT,
-        .pull_up_en = GPIO_PULLUP_ENABLE,       // 启用上拉,按钮按下时拉低
-        .pull_down_en = GPIO_PULLDOWN_DISABLE,
-        .intr_type = GPIO_INTR_NEGEDGE          // 下降沿触发(按下按钮)
-    };
-    
-    err = gpio_config(&btn_conf);
-    if (err != ESP_OK) {
-        ESP_LOGE(BT_AV_TAG, "GPIO2 config failed: %s", esp_err_to_name(err));
-        return;
-    }
-
-    // 配置GPIO19为输出模式
-    gpio_config_t output_conf = {
-        .pin_bit_mask = (1ULL << GPIO_OUTPUT),
-        .mode = GPIO_MODE_OUTPUT,
-        .pull_up_en = GPIO_PULLUP_DISABLE,
-        .pull_down_en = GPIO_PULLDOWN_DISABLE,
-        .intr_type = GPIO_INTR_DISABLE
-    };
-    
-    err = gpio_config(&output_conf);
-    if (err != ESP_OK) {
-        ESP_LOGE(BT_AV_TAG, "GPIO19 config failed: %s", esp_err_to_name(err));
-        return;
-    }
-
-    // 初始化GPIO19为低电平
-    gpio_set_level(GPIO_OUTPUT, 0);
-
-    // 创建GPIO事件队列
-    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
-    
-    // 启动GPIO任务
-    xTaskCreate(gpio_task, "gpio_task", 2048, NULL, 10, NULL);
-
-    // 安装GPIO ISR服务
-    gpio_install_isr_service(0);
-    
-    // 注册GPIO2的中断处理函数
-    gpio_isr_handler_add(GPIO_BTN, gpio_isr_handler, (void*) GPIO_BTN);
-
-    ESP_LOGI(BT_AV_TAG, "GPIO2 interrupt and GPIO19 output initialized");
-
-
-
-
+    ESP_LOGI(BT_AV_TAG, "Initializing hw gpio ...");
+    init_io();
+    ESP_LOGI(BT_AV_TAG, "Initializing bluetooth ...");
 
     /*
      * This example only uses the functions of Classical Bluetooth.
@@ -424,7 +275,6 @@ void app_main(void)
     pin_code[2] = '3';
     pin_code[3] = '4';
     esp_bt_gap_set_pin(pin_type, 4, pin_code);
-
     ESP_LOGI(BT_AV_TAG, "Own address:[%s]", bda2str((uint8_t *)esp_bt_dev_get_address(), bda_str, sizeof(bda_str)));
     bt_app_task_start_up();
     /* bluetooth device name, connection mode and profile set up */