app_io.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //
  2. // Created by kindring on 2025/12/26.
  3. //
  4. #include "esp_log.h"
  5. #include "app_io.h"
  6. #include "freertos/FreeRTOS.h"
  7. #include "freertos/task.h"
  8. #include "freertos/queue.h"
  9. #define TAG "app_io"
  10. static QueueHandle_t g_io_evt_queue = NULL;
  11. static void io_task(void* arg)
  12. {
  13. uint32_t io_num;
  14. while (true)
  15. {
  16. if(xQueueReceive(g_io_evt_queue, &io_num, portMAX_DELAY))
  17. {
  18. // 消抖处理
  19. vTaskDelay(50 / portTICK_PERIOD_MS);
  20. if(gpio_get_level(io_num) == 0)
  21. { // 确认仍然是低电平
  22. ESP_LOGI(TAG, "GPIO%"PRIu32" interrupt, button pressed", io_num);
  23. next_audio_mode();
  24. }
  25. }
  26. }
  27. }
  28. static void IRAM_ATTR gpio_isr_handler(void* arg)
  29. {
  30. const uint32_t gpio_num = (uint32_t) arg;
  31. xQueueSendFromISR(g_io_evt_queue, &gpio_num, NULL);
  32. }
  33. /**
  34. * 切换系统状态灯
  35. * @param on
  36. * @return
  37. */
  38. esp_err_t set_led_io(const bool on)
  39. {
  40. const esp_err_t err = gpio_set_level(IO_LED, on);
  41. if (err != ESP_OK) {
  42. ESP_LOGE(TAG, "Set system to %d failed: %s", on, esp_err_to_name(err));
  43. return err;
  44. }
  45. return ESP_OK;
  46. }
  47. esp_err_t init_led_io() {
  48. // system state led
  49. const gpio_config_t led_io_conf = {
  50. .pin_bit_mask = (1ULL << IO_LED), // GPIO15
  51. .mode = GPIO_MODE_OUTPUT, // 输出模式
  52. .pull_up_en = GPIO_PULLUP_DISABLE, // 禁用上拉
  53. .pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉
  54. .intr_type = GPIO_INTR_DISABLE // 禁用中断
  55. };
  56. // 配置GPIO
  57. const esp_err_t err = gpio_config(&led_io_conf);
  58. if (err != ESP_OK) {
  59. ESP_LOGE(TAG, "system led config failed: %s", esp_err_to_name(err));
  60. return err;
  61. }
  62. return set_led_io(0);
  63. }
  64. esp_err_t init_btn_io() {
  65. // 配置GPIO2为输入模式,用于低电平中断
  66. const gpio_config_t btn_conf = {
  67. .pin_bit_mask = (1ULL << IO_BTN),
  68. .mode = GPIO_MODE_INPUT,
  69. .pull_up_en = GPIO_PULLUP_ENABLE, // 启用上拉,按钮按下时拉低
  70. .pull_down_en = GPIO_PULLDOWN_DISABLE,
  71. .intr_type = GPIO_INTR_NEGEDGE // 下降沿触发(按下按钮)
  72. };
  73. const esp_err_t err = gpio_config(&btn_conf);
  74. if (err != ESP_OK) {
  75. ESP_LOGE(TAG, "BTN config failed: %s", esp_err_to_name(err));
  76. return err;
  77. }
  78. // 注册中断服务
  79. gpio_isr_handler_add(IO_BTN, gpio_isr_handler, (void*) IO_BTN);
  80. return ESP_OK;
  81. }
  82. // 更新输出引脚状态
  83. esp_err_t update_output_mode(const audio_mode_t mode)
  84. {
  85. esp_err_t err = ESP_OK;
  86. // 根据音频模式设置GPIO19输出状态
  87. switch(mode) {
  88. case AUDIO_MODE_AUX:
  89. err = gpio_set_level(IO_OUTPUT_SW, 0); // 低电平
  90. break;
  91. case AUDIO_MODE_BLE:
  92. err = gpio_set_level(IO_OUTPUT_SW, 1); // 高电平
  93. break;
  94. default:
  95. err = gpio_set_level(IO_OUTPUT_SW, 0);
  96. break;
  97. }
  98. ESP_LOGD(TAG, "GPIO19 set to: %d", gpio_get_level(IO_OUTPUT_SW));
  99. return err;
  100. }
  101. // 初始化输出引脚
  102. esp_err_t init_output_io() {
  103. // 配置GPIO2为输入模式,用于低电平中断
  104. const gpio_config_t output_conf = {
  105. .pin_bit_mask = (1ULL << IO_OUTPUT_SW),
  106. .mode = GPIO_MODE_OUTPUT,
  107. .pull_up_en = GPIO_PULLUP_DISABLE,
  108. .pull_down_en = GPIO_PULLDOWN_DISABLE,
  109. .intr_type = GPIO_INTR_DISABLE
  110. };
  111. const esp_err_t err = gpio_config(&output_conf);
  112. if (err != ESP_OK) {
  113. ESP_LOGE(TAG, "OUTPUT config failed: %s", esp_err_to_name(err));
  114. return err;
  115. }
  116. return ESP_OK;
  117. }
  118. // 启用或者关闭功放
  119. esp_err_t enable_amp(const bool on) {
  120. // 低有效, 高无效, 需要将电平反转
  121. const int io_level = !on;
  122. const esp_err_t err = gpio_set_level(IO_AMP_EN, io_level );
  123. if (err != ESP_OK) {
  124. ESP_LOGE(TAG, "%s apm failed: %s", on? "ENABLE" : "DISABLE", esp_err_to_name(err));
  125. return err;
  126. }
  127. return ESP_OK;
  128. }
  129. esp_err_t init_amp_io() {
  130. // 配置GPIO32为输出模式并拉低电平
  131. const gpio_config_t io_conf = {
  132. .pin_bit_mask = (1ULL << IO_AMP_EN), // GPIO32
  133. .mode = GPIO_MODE_OUTPUT, // 输出模式
  134. .pull_up_en = GPIO_PULLUP_DISABLE, // 禁用上拉
  135. .pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉
  136. .intr_type = GPIO_INTR_DISABLE // 禁用中断
  137. };
  138. // 配置GPIO
  139. const esp_err_t err = gpio_config(&io_conf);
  140. if (err != ESP_OK) {
  141. ESP_LOGE(TAG, "IO_AMP_EN config failed: %s", esp_err_to_name(err));
  142. return err;
  143. }
  144. return enable_amp(false);
  145. }
  146. // 初始化io引脚配置
  147. int init_io(audio_mode_t audio_mode) {
  148. // 安装GPIO ISR服务
  149. esp_err_t err = gpio_install_isr_service(0);
  150. g_io_evt_queue = xQueueCreate(10, sizeof(uint32_t));
  151. xTaskCreate(io_task, "io_task", 2048, NULL, 10, NULL);
  152. init_amp_io();
  153. init_output_io();
  154. init_led_io();
  155. init_btn_io();
  156. update_output_mode(audio_mode);
  157. return 0;
  158. }