├── LICENSE ├── README.md └── components └── ai-thinker-esp32-a1s ├── CMakeLists.txt ├── Kconfig.projbuild ├── ai_thinker_esp32_a1s ├── board.c ├── board.h ├── board_def.h └── board_pins_config.c └── component.mk /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 4 | Copyright (c) 2023 Tomoyuki Sakurai 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ai Thinker ESP32 A1S Audio Kit board definition for `esp-adf` 2 | 3 | ## Usage 4 | 5 | * Clone the repository by `git clone https://github.com/trombik/esp-adf-component-ai-thinker-esp32-a1s.git` 6 | * Create `components` directory in a project directory 7 | * Create a symlink to 8 | `idf-component-ai-thinker-esp32-a1s/components/ai-thinker-esp32-a1s` under 9 | `components`. 10 | * Run `idf.py menuconfig` 11 | * Select `Custom audio board` under `Audio HAL` > `Audio board` 12 | * Select a custom board under `Custom Audio Board` 13 | 14 | ## Supported boards 15 | 16 | There are two different Ai Thinker A1S chips in the market: one with `ac101` 17 | audio codec, another with `es8388`. Both chips has the same name. The one with 18 | `ac101` is EoLed, the vendor claims. In addition, there are different Ai 19 | Thinker A1S Audio Kit boards in the market: A1S `es8388` chips with different 20 | pin assignments. 21 | 22 | * Ai Thinker A1S with `es8388` variant 5 (probably the latest variant available in 23 | AliExpress) 24 | * Ai Thinker A1S with `es8388` variant 7 25 | 26 | ## What works 27 | 28 | Here is a list of tested peripherals: 29 | 30 | - [x] Audio output to speakers 31 | - [x] Keys 32 | - [x] On-board LEDs 33 | - [x] Bluetooth 34 | - [ ] Mic input 35 | - [ ] Line input 36 | - [x] On-board microphones 37 | - [ ] SD card 38 | - [x] Battery charger 39 | 40 | ### Speaker outputs 41 | 42 | To test speaker outputs, use `${ADF_PATH}/examples/player/pipeline_http_mp3`. 43 | 44 | ### Keys 45 | 46 | To test keys, use `${ADF_PATH}/examples/checks/check_board_buttons`. 47 | 48 | | Name | Function in `esp-adf` | 49 | |--------|-----------------------| 50 | | `KEY1` | Mode | 51 | | `KEY2` | Rec | 52 | | `KEY3` | Play | 53 | | `KEY4` | Set | 54 | | `KEY5` | Volume down | 55 | | `KEY6` | Volume up | 56 | 57 | Note that `KEY2` cannot be used with SD card because the `GPIO` for `KEY2` is 58 | shared with SD card peripheral. 59 | 60 | According to the schematic, 61 | [ADC Button Peripheral](https://docs.espressif.com/projects/esp-adf/en/latest/api-reference/peripherals/periph_adc_button.html) 62 | is supposed to work. However, my board does not have necessary resistors 63 | (`R60`, `R61` ...). If yours has them, 64 | give `CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_ADC` a try. 65 | 66 | ### On-board LED 67 | 68 | The board has two red LEDs connected to GPIO pins. By default, only one LED is 69 | useable. Unlike official development boards from `espressif`, the color is 70 | red. `esp-adf` provides `get_blue_led_gpio()` and `get_green_led_gpio()`, not 71 | one for red LED. 72 | 73 | To test the LED, use `${ADF_PATH}/examples/checks/check_display_led`. 74 | 75 | ## Bluetooth 76 | 77 | To test `a2dp` sink, use `${ADF_PATH}/examples/player/pipeline_a2dp_sink_stream`. 78 | 79 | `a2dp` source has not been tested. 80 | 81 | ## On-board microphones 82 | 83 | To test on-board microphones, use `${ADF_PATH}/examples/recorder/pipeline_raw_http`. 84 | 85 | See also "Known issues" below. 86 | 87 | ## Battery charger 88 | 89 | The battery charger should work, but no GPIO pin is connected to the charger 90 | circuit. As such, the battery service in `esp-adf` cannot be used. 91 | 92 | ## Tested environment 93 | 94 | - `esp-idf` `v5.0.2` 95 | - `esp-adf` `master` 96 | 97 | ## Known issues 98 | 99 | The Audio Kit board has hardware bugs. Two capacitors must be connected to on-board microphones. See 100 | [a post](https://community.home-assistant.io/t/esp32-a1s-audio-kit-for-voice-assistant/568301/18) in 101 | Home Assistant forum. 102 | 103 | ## Resources 104 | 105 | * [The‘AI Thinker Audio Kit' Arduino Challenge](https://www.pschatzmann.ch/home/2021/12/06/the-ai-thinker-audio-kit-experience-or-nothing-is-right/) 106 | A series of posts about Ai Thinker ESP32 A1S Audio Kit 107 | * [Schematic](https://docs.ai-thinker.com/_media/esp32-audio-kit_v2.2_sch.pdf) 108 | * [arduino-audiokit/tree/main/src/audio_board](https://github.com/pschatzmann/arduino-audiokit/tree/main/src/audio_board) 109 | An implementation for Arduino 110 | * [ES8388 User Guide](https://dl.radxa.com/rock2/docs/hw/ds/ES8388%20user%20Guide.pdf) 111 | -------------------------------------------------------------------------------- /components/ai-thinker-esp32-a1s/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Edit following two lines to set component requirements (see docs) 2 | set(COMPONENT_REQUIRES) 3 | set(COMPONENT_PRIV_REQUIRES audio_sal audio_hal esp_dispatcher esp_peripherals display_service) 4 | 5 | if(CONFIG_AUDIO_BOARD_CUSTOM) 6 | message(STATUS "Current board name is " CONFIG_AUDIO_BOARD_CUSTOM) 7 | list(APPEND COMPONENT_ADD_INCLUDEDIRS ./ai_thinker_esp32_a1s) 8 | set(COMPONENT_SRCS 9 | ./ai_thinker_esp32_a1s/board.c 10 | ./ai_thinker_esp32_a1s/board_pins_config.c 11 | ) 12 | endif() 13 | 14 | register_component() 15 | 16 | IF (IDF_VERSION_MAJOR GREATER 3) 17 | idf_component_get_property(audio_board_lib audio_board COMPONENT_LIB) 18 | set_property(TARGET ${audio_board_lib} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${COMPONENT_LIB}) 19 | 20 | ELSEIF (IDF_VERSION_MAJOR EQUAL 3) 21 | set_property(TARGET idf_component_audio_board APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES $) 22 | 23 | ENDIF (IDF_VERSION_MAJOR GREATER 3) 24 | -------------------------------------------------------------------------------- /components/ai-thinker-esp32-a1s/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Custom Audio Board" 2 | 3 | choice CUSTOM_AUDIO_BOARD 4 | prompt "Select a custom audio board" 5 | default AI_THINKER_ESP32_A1S_ES8388_VARIANT_5 6 | help 7 | Select an audio board to use with the ESP-ADF 8 | 9 | # TODO add more variants, see https://github.com/pschatzmann/arduino-audiokit/tree/main/src/audio_board 10 | config AI_THINKER_ESP32_A1S_ES8388_VARIANT_7 11 | bool "Ai Thinker ESP32 A1S Audio Kit (ES8388, variant 7)" 12 | config AI_THINKER_ESP32_A1S_ES8388_VARIANT_5 13 | bool "Ai Thinker ESP32 A1S Audio Kit (ES8388, variant 5)" 14 | endchoice 15 | 16 | choice 17 | prompt "Select button type" 18 | default AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_GPIO 19 | help 20 | The board supports two type of buttons; GPIO or ADC. 21 | 22 | With GPIO type, key inputs are handled by GPIO pins. 23 | 24 | With ADC type, key inputs are handled by a single ADC pin. However, 25 | the board must have necessary resistors (R60 - R64) soldered. Check 26 | the board first. 27 | config AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_GPIO 28 | bool "Use GPIO pins for key inputs" 29 | config AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_ADC 30 | bool "Use an ADC pin for key inputs (see help)" 31 | endchoice 32 | 33 | config AI_THINKER_ESP32_A1S_AUDIO_KIT_USING_SDCARD 34 | bool "Use on-board SD card" 35 | default n 36 | help 37 | Choose y to use on-board SD card. 38 | endmenu 39 | -------------------------------------------------------------------------------- /components/ai-thinker-esp32-a1s/ai_thinker_esp32_a1s/board.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2020 5 | * Copyright (c) 2023 Tomoyuki Sakurai 6 | * 7 | * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, 8 | * it is free of charge, to any person obtaining a copy of this software and associated 9 | * documentation files (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 12 | * to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all copies or 15 | * substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #include "esp_log.h" 27 | #include "board.h" 28 | #include "audio_mem.h" 29 | 30 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_AUDIO_KIT_USING_SDCARD) 31 | #include "periph_sdcard.h" 32 | #endif 33 | #include "led_indicator.h" 34 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_ADC) 35 | #include "periph_adc_button.h" 36 | #elif defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_GPIO) 37 | #include "periph_button.h" 38 | #endif 39 | 40 | static const char *TAG = "AUDIO_BOARD"; 41 | 42 | static audio_board_handle_t board_handle = 0; 43 | 44 | audio_board_handle_t audio_board_init(void) 45 | { 46 | if (board_handle) { 47 | ESP_LOGW(TAG, "The board has already been initialized!"); 48 | return board_handle; 49 | } 50 | board_handle = (audio_board_handle_t) audio_calloc(1, sizeof(struct audio_board_handle)); 51 | AUDIO_MEM_CHECK(TAG, board_handle, return NULL); 52 | board_handle->audio_hal = audio_board_codec_init(); 53 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_ADC) 54 | board_handle->adc_hal = audio_board_adc_init(); 55 | #endif 56 | return board_handle; 57 | } 58 | 59 | audio_hal_handle_t audio_board_codec_init(void) 60 | { 61 | audio_hal_codec_config_t audio_codec_cfg = AUDIO_CODEC_DEFAULT_CONFIG(); 62 | audio_hal_handle_t codec_hal = audio_hal_init(&audio_codec_cfg, &AUDIO_CODEC_ES8388_DEFAULT_HANDLE); 63 | AUDIO_NULL_CHECK(TAG, codec_hal, return NULL); 64 | return codec_hal; 65 | } 66 | 67 | display_service_handle_t audio_board_led_init(void) 68 | { 69 | led_indicator_handle_t led = led_indicator_init((gpio_num_t)get_green_led_gpio()); 70 | display_service_config_t display = { 71 | .based_cfg = { 72 | .task_stack = 0, 73 | .task_prio = 0, 74 | .task_core = 0, 75 | .task_func = NULL, 76 | .service_start = NULL, 77 | .service_stop = NULL, 78 | .service_destroy = NULL, 79 | .service_ioctl = led_indicator_pattern, 80 | .service_name = "DISPLAY_serv", 81 | .user_data = NULL, 82 | }, 83 | .instance = led, 84 | }; 85 | 86 | return display_service_create(&display); 87 | } 88 | 89 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_ADC) 90 | esp_err_t audio_board_key_init(esp_periph_set_handle_t set) 91 | { 92 | esp_err_t ret = ESP_OK; 93 | periph_adc_button_cfg_t adc_btn_cfg = PERIPH_ADC_BUTTON_DEFAULT_CONFIG(); 94 | adc_arr_t adc_btn_tag = ADC_DEFAULT_ARR(); 95 | adc_btn_tag.adc_ch = ADC1_CHANNEL_0; 96 | adc_btn_tag.total_steps = 6; 97 | int btn_array[7] = {100, 600, 1000, 1375, 1775, 2195, 3100}; 98 | adc_btn_tag.adc_level_step = btn_array; 99 | adc_btn_cfg.arr = &adc_btn_tag; 100 | adc_btn_cfg.arr_size = 1; 101 | esp_periph_handle_t adc_btn_handle = periph_adc_button_init(&adc_btn_cfg); 102 | AUDIO_NULL_CHECK(TAG, adc_btn_handle, return ESP_ERR_ADF_MEMORY_LACK); 103 | ret = esp_periph_start(set, adc_btn_handle); 104 | return ret; 105 | } 106 | #elif defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_GPIO) 107 | esp_err_t audio_board_key_init(esp_periph_set_handle_t set) 108 | { 109 | periph_button_cfg_t btn_cfg = { 110 | .gpio_mask = (1ULL << get_input_volup_id()) | \ 111 | (1ULL << get_input_voldown_id()) | \ 112 | (1ULL << get_input_mode_id()) | \ 113 | (1ULL << get_input_set_id()) | \ 114 | (1ULL << get_input_rec_id()) | \ 115 | (1ULL << get_input_play_id()) 116 | }; 117 | esp_periph_handle_t button_handle = periph_button_init(&btn_cfg); 118 | AUDIO_NULL_CHECK(TAG, button_handle, return ESP_ERR_ADF_MEMORY_LACK); 119 | esp_err_t ret = ESP_OK; 120 | ret = esp_periph_start(set, button_handle); 121 | return ret; 122 | } 123 | #endif 124 | 125 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_AUDIO_KIT_USING_SDCARD) 126 | esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set, periph_sdcard_mode_t mode) 127 | { 128 | if (mode >= SD_MODE_4_LINE) { 129 | ESP_LOGE(TAG, "Please select the correct sd mode!, current mode is %d", mode); 130 | return ESP_FAIL; 131 | } 132 | periph_sdcard_cfg_t sdcard_cfg = { 133 | .root = "/sdcard", 134 | .card_detect_pin = get_sdcard_intr_gpio(), 135 | .mode = mode, 136 | }; 137 | esp_periph_handle_t sdcard_handle = periph_sdcard_init(&sdcard_cfg); 138 | esp_err_t ret = esp_periph_start(set, sdcard_handle); 139 | int retry_time = 5; 140 | bool mount_flag = false; 141 | while (retry_time --) { 142 | if (periph_sdcard_is_mounted(sdcard_handle)) { 143 | mount_flag = true; 144 | break; 145 | } else { 146 | vTaskDelay(500 / portTICK_PERIOD_MS); 147 | } 148 | } 149 | if (mount_flag == false) { 150 | ESP_LOGE(TAG, "Sdcard mount failed"); 151 | return ESP_FAIL; 152 | } 153 | return ret; 154 | } 155 | #endif 156 | 157 | audio_board_handle_t audio_board_get_handle(void) 158 | { 159 | return board_handle; 160 | } 161 | 162 | esp_err_t audio_board_deinit(audio_board_handle_t audio_board) 163 | { 164 | esp_err_t ret = ESP_OK; 165 | ret |= audio_hal_deinit(audio_board->audio_hal); 166 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_ADC) 167 | ret |= audio_hal_deinit(audio_board->adc_hal); 168 | #endif 169 | audio_free(audio_board); 170 | board_handle = NULL; 171 | return ret; 172 | } 173 | -------------------------------------------------------------------------------- /components/ai-thinker-esp32-a1s/ai_thinker_esp32_a1s/board.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2020 5 | * 6 | * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef _AUDIO_BOARD_H_ 26 | #define _AUDIO_BOARD_H_ 27 | 28 | #include "audio_hal.h" 29 | #include "board_def.h" 30 | #include "board_pins_config.h" 31 | #include "esp_peripherals.h" 32 | #include "display_service.h" 33 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_AUDIO_KIT_USING_SDCARD) 34 | #include "periph_sdcard.h" 35 | #endif 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | /** 42 | * @brief Audio board handle 43 | */ 44 | struct audio_board_handle { 45 | audio_hal_handle_t audio_hal; /*!< audio hardware abstract layer handle */ 46 | audio_hal_handle_t adc_hal; /*!< adc hardware abstract layer handle */ 47 | }; 48 | 49 | typedef struct audio_board_handle *audio_board_handle_t; 50 | 51 | /** 52 | * @brief Initialize audio board 53 | * 54 | * @return The audio board handle 55 | */ 56 | audio_board_handle_t audio_board_init(void); 57 | 58 | /** 59 | * @brief Initialize codec chip 60 | * 61 | * @return The audio hal handle 62 | */ 63 | audio_hal_handle_t audio_board_codec_init(void); 64 | 65 | /** 66 | * @brief Initialize adc 67 | * 68 | * @return The adc hal handle 69 | */ 70 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_ADC) 71 | audio_hal_handle_t audio_board_adc_init(void); 72 | #endif 73 | 74 | /** 75 | * @brief Initialize led peripheral and display service 76 | * 77 | * @return The audio display service handle 78 | */ 79 | display_service_handle_t audio_board_led_init(void); 80 | 81 | /** 82 | * @brief Initialize key peripheral 83 | * 84 | * @param set The handle of esp_periph_set_handle_t 85 | * 86 | * @return 87 | * - ESP_OK, success 88 | * - Others, fail 89 | */ 90 | esp_err_t audio_board_key_init(esp_periph_set_handle_t set); 91 | 92 | /** 93 | * @brief Initialize sdcard peripheral 94 | * 95 | * @param set The handle of esp_periph_set_handle_t 96 | * 97 | * @return 98 | * - ESP_OK, success 99 | * - Others, fail 100 | */ 101 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_AUDIO_KIT_USING_SDCARD) 102 | esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set, periph_sdcard_mode_t mode); 103 | #endif 104 | 105 | /** 106 | * @brief Query audio_board_handle 107 | * 108 | * @return The audio board handle 109 | */ 110 | audio_board_handle_t audio_board_get_handle(void); 111 | 112 | /** 113 | * @brief Uninitialize the audio board 114 | * 115 | * @param audio_board The handle of audio board 116 | * 117 | * @return 0 success, 118 | * others fail 119 | */ 120 | esp_err_t audio_board_deinit(audio_board_handle_t audio_board); 121 | 122 | #ifdef __cplusplus 123 | } 124 | #endif 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /components/ai-thinker-esp32-a1s/ai_thinker_esp32_a1s/board_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2020 5 | * Copyright (c) 2023 Tomoyuki Sakurai 6 | * 7 | * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, 8 | * it is free of charge, to any person obtaining a copy of this software and associated 9 | * documentation files (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 12 | * to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all copies or 15 | * substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef _AI_THINKER_ESP32_A1S_H_ 27 | #define _AI_THINKER_ESP32_A1S_H_ 28 | 29 | /** 30 | * @brief SDCARD Function Definition 31 | */ 32 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_AUDIO_KIT_USING_SDCARD) 33 | #define FUNC_SDCARD_EN (1) 34 | #define SDCARD_OPEN_FILE_NUM_MAX 5 35 | #define SDCARD_INTR_GPIO GPIO_NUM_34 36 | #define ESP_SD_PIN_CLK GPIO_NUM_14 37 | #define ESP_SD_PIN_CMD GPIO_NUM_15 38 | #define ESP_SD_PIN_D0 GPIO_NUM_2 39 | #define ESP_SD_PIN_D1 GPIO_NUM_4 40 | #define ESP_SD_PIN_D2 GPIO_NUM_12 41 | #define ESP_SD_PIN_D3 GPIO_NUM_13 42 | #else 43 | #define FUNC_SDCARD_EN (0) 44 | #define SDCARD_OPEN_FILE_NUM_MAX 5 45 | #define SDCARD_INTR_GPIO -1 46 | #define ESP_SD_PIN_CLK -1 47 | #define ESP_SD_PIN_CMD -1 48 | #define ESP_SD_PIN_D0 -1 49 | #define ESP_SD_PIN_D1 -1 50 | #define ESP_SD_PIN_D2 -1 51 | #define ESP_SD_PIN_D3 -1 52 | #endif 53 | 54 | /** 55 | * @brief LED Function Definition 56 | */ 57 | #define FUNC_SYS_LEN_EN (1) 58 | #define GREEN_LED_GPIO GPIO_NUM_22 59 | 60 | 61 | /** 62 | * @brief Audio Codec Chip Function Definition 63 | */ 64 | #define FUNC_AUDIO_CODEC_EN (1) 65 | #define AUXIN_DETECT_GPIO (-1) 66 | #define HEADPHONE_DETECT GPIO_NUM_39 67 | #define PA_ENABLE_GPIO GPIO_NUM_21 68 | #define CODEC_ADC_I2S_PORT (0) 69 | #define CODEC_ADC_BITS_PER_SAMPLE I2S_BITS_PER_SAMPLE_16BIT 70 | #define CODEC_ADC_SAMPLE_RATE (48000) 71 | #define RECORD_HARDWARE_AEC (false) 72 | #define BOARD_PA_GAIN (10) /* Power amplifier gain defined by board (dB) */ 73 | 74 | extern audio_hal_func_t AUDIO_CODEC_ES8388_DEFAULT_HANDLE; 75 | #define AUDIO_CODEC_DEFAULT_CONFIG(){ \ 76 | .adc_input = AUDIO_HAL_ADC_INPUT_LINE1, \ 77 | .dac_output = AUDIO_HAL_DAC_OUTPUT_ALL, \ 78 | .codec_mode = AUDIO_HAL_CODEC_MODE_BOTH, \ 79 | .i2s_iface = { \ 80 | .mode = AUDIO_HAL_MODE_SLAVE, \ 81 | .fmt = AUDIO_HAL_I2S_NORMAL, \ 82 | .samples = AUDIO_HAL_48K_SAMPLES, \ 83 | .bits = AUDIO_HAL_BIT_LENGTH_16BITS, \ 84 | }, \ 85 | }; 86 | 87 | /** 88 | * @brief Button Function Definition 89 | */ 90 | #define FUNC_BUTTON_EN (1) 91 | #define INPUT_KEY_NUM 6 92 | 93 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_GPIO) 94 | #define BUTTON_VOLUP_ID GPIO_NUM_5 /* KEY6 */ 95 | #define BUTTON_VOLDOWN_ID GPIO_NUM_18 /* KEY5 */ 96 | #define BUTTON_SET_ID GPIO_NUM_23 /* KEY4 */ 97 | #define BUTTON_PLAY_ID GPIO_NUM_19 /* KEY3 */ 98 | #define BUTTON_REC_ID GPIO_NUM_13 /* KEY2 */ 99 | #define BUTTON_MODE_ID GPIO_NUM_36 /* KEY1 */ 100 | 101 | #define INPUT_KEY_DEFAULT_INFO() { \ 102 | { \ 103 | .type = PERIPH_ID_BUTTON, \ 104 | .user_id = INPUT_KEY_USER_ID_REC, \ 105 | .act_id = BUTTON_REC_ID, \ 106 | }, \ 107 | { \ 108 | .type = PERIPH_ID_BUTTON, \ 109 | .user_id = INPUT_KEY_USER_ID_MODE, \ 110 | .act_id = BUTTON_MODE_ID, \ 111 | }, \ 112 | { \ 113 | .type = PERIPH_ID_BUTTON, \ 114 | .user_id = INPUT_KEY_USER_ID_SET, \ 115 | .act_id = BUTTON_SET_ID, \ 116 | }, \ 117 | { \ 118 | .type = PERIPH_ID_BUTTON, \ 119 | .user_id = INPUT_KEY_USER_ID_PLAY, \ 120 | .act_id = BUTTON_PLAY_ID, \ 121 | }, \ 122 | { \ 123 | .type = PERIPH_ID_BUTTON, \ 124 | .user_id = INPUT_KEY_USER_ID_VOLUP, \ 125 | .act_id = BUTTON_VOLUP_ID, \ 126 | }, \ 127 | { \ 128 | .type = PERIPH_ID_BUTTON, \ 129 | .user_id = INPUT_KEY_USER_ID_VOLDOWN, \ 130 | .act_id = BUTTON_VOLDOWN_ID, \ 131 | } \ 132 | } 133 | #elif defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_BUTTON_KEY_ADC) 134 | #define ADC_DETECT_GPIO GPIO_NUM_36 135 | #define BUTTON_VOLUP_ID 5 /* KEY6 */ 136 | #define BUTTON_VOLDOWN_ID 4 /* KEY5 */ 137 | #define BUTTON_SET_ID 3 /* KEY4 */ 138 | #define BUTTON_PLAY_ID 2 /* KEY3 */ 139 | #define BUTTON_REC_ID 1 /* KEY2 */ 140 | #define BUTTON_MODE_ID 0 /* KEY1 */ 141 | #define INPUT_KEY_DEFAULT_INFO() { \ 142 | { \ 143 | .type = PERIPH_ID_ADC_BTN, \ 144 | .user_id = INPUT_KEY_USER_ID_REC, \ 145 | .act_id = BUTTON_REC_ID, \ 146 | }, \ 147 | { \ 148 | .type = PERIPH_ID_ADC_BTN, \ 149 | .user_id = INPUT_KEY_USER_ID_MODE, \ 150 | .act_id = BUTTON_MODE_ID, \ 151 | }, \ 152 | { \ 153 | .type = PERIPH_ID_ADC_BTN, \ 154 | .user_id = INPUT_KEY_USER_ID_SET, \ 155 | .act_id = BUTTON_SET_ID, \ 156 | }, \ 157 | { \ 158 | .type = PERIPH_ID_ADC_BTN, \ 159 | .user_id = INPUT_KEY_USER_ID_PLAY, \ 160 | .act_id = BUTTON_PLAY_ID, \ 161 | }, \ 162 | { \ 163 | .type = PERIPH_ID_ADC_BTN, \ 164 | .user_id = INPUT_KEY_USER_ID_VOLUP, \ 165 | .act_id = BUTTON_VOLUP_ID, \ 166 | }, \ 167 | { \ 168 | .type = PERIPH_ID_ADC_BTN, \ 169 | .user_id = INPUT_KEY_USER_ID_VOLDOWN, \ 170 | .act_id = BUTTON_VOLDOWN_ID, \ 171 | } \ 172 | } 173 | #endif 174 | 175 | #endif 176 | -------------------------------------------------------------------------------- /components/ai-thinker-esp32-a1s/ai_thinker_esp32_a1s/board_pins_config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2020 5 | * 6 | * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include "esp_log.h" 26 | #include "driver/gpio.h" 27 | #include 28 | #include "board.h" 29 | #include "audio_error.h" 30 | #include "audio_mem.h" 31 | #include "soc/soc_caps.h" 32 | 33 | static const char *TAG = "AI_THINKER_ESP32_A1S"; 34 | 35 | esp_err_t get_i2c_pins(i2c_port_t port, i2c_config_t *i2c_config) 36 | { 37 | AUDIO_NULL_CHECK(TAG, i2c_config, return ESP_FAIL); 38 | if (port == I2C_NUM_0 || port == I2C_NUM_1) { 39 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_VARIANT_7) 40 | i2c_config->sda_io_num = GPIO_NUM_18; 41 | i2c_config->scl_io_num = GPIO_NUM_23; 42 | #elif defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_VARIANT_5) 43 | i2c_config->sda_io_num = GPIO_NUM_33; 44 | i2c_config->scl_io_num = GPIO_NUM_32; 45 | #endif 46 | } else { 47 | i2c_config->sda_io_num = -1; 48 | i2c_config->scl_io_num = -1; 49 | ESP_LOGE(TAG, "i2c port %d is not supported", port); 50 | return ESP_FAIL; 51 | } 52 | return ESP_OK; 53 | } 54 | 55 | esp_err_t get_i2s_pins(i2s_port_t port, board_i2s_pin_t *i2s_config) 56 | { 57 | AUDIO_NULL_CHECK(TAG, i2s_config, return ESP_FAIL); 58 | if (port == I2S_NUM_0) { 59 | i2s_config->mck_io_num = GPIO_NUM_0; 60 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_VARIANT_7) 61 | i2s_config->bck_io_num = GPIO_NUM_5; 62 | #elif defined(CONFIG_AI_THINKER_ESP32_A1S_ES8388_VARIANT_5) 63 | i2s_config->bck_io_num = GPIO_NUM_27; 64 | #endif 65 | i2s_config->ws_io_num = GPIO_NUM_25; 66 | i2s_config->data_out_num = GPIO_NUM_26; 67 | i2s_config->data_in_num = GPIO_NUM_35; 68 | } else if (port == I2S_NUM_1) { 69 | i2s_config->bck_io_num = -1; 70 | i2s_config->ws_io_num = -1; 71 | i2s_config->data_out_num = -1; 72 | i2s_config->data_in_num = -1; 73 | } else { 74 | memset(i2s_config, -1, sizeof(board_i2s_pin_t)); 75 | ESP_LOGE(TAG, "i2s port %d is not supported", port); 76 | return ESP_FAIL; 77 | } 78 | 79 | return ESP_OK; 80 | } 81 | 82 | esp_err_t get_spi_pins(spi_bus_config_t *spi_config, spi_device_interface_config_t *spi_device_interface_config) 83 | { 84 | AUDIO_NULL_CHECK(TAG, spi_config, return ESP_FAIL); 85 | AUDIO_NULL_CHECK(TAG, spi_device_interface_config, return ESP_FAIL); 86 | 87 | spi_config->mosi_io_num = -1; 88 | spi_config->miso_io_num = -1; 89 | spi_config->sclk_io_num = -1; 90 | spi_config->quadwp_io_num = -1; 91 | spi_config->quadhd_io_num = -1; 92 | 93 | spi_device_interface_config->spics_io_num = -1; 94 | 95 | ESP_LOGW(TAG, "SPI interface is not supported"); 96 | return ESP_OK; 97 | } 98 | 99 | // sdcard detect gpio 100 | #if defined(CONFIG_AI_THINKER_ESP32_A1S_AUDIO_KIT_USING_SDCARD) 101 | int8_t get_sdcard_intr_gpio(void) 102 | { 103 | return SDCARD_INTR_GPIO; 104 | } 105 | 106 | int8_t get_sdcard_open_file_num_max(void) 107 | { 108 | return SDCARD_OPEN_FILE_NUM_MAX; 109 | } 110 | #endif 111 | 112 | // volume up button 113 | int8_t get_input_volup_id(void) 114 | { 115 | return BUTTON_VOLUP_ID; 116 | } 117 | 118 | // volume down button 119 | int8_t get_input_voldown_id(void) 120 | { 121 | return BUTTON_VOLDOWN_ID; 122 | } 123 | 124 | // pa enable 125 | int8_t get_pa_enable_gpio(void) 126 | { 127 | return PA_ENABLE_GPIO; 128 | } 129 | 130 | // mode button 131 | int8_t get_input_mode_id(void) 132 | { 133 | return BUTTON_MODE_ID; 134 | } 135 | 136 | // set button 137 | int8_t get_input_set_id(void) 138 | { 139 | return BUTTON_SET_ID; 140 | } 141 | 142 | // play button 143 | int8_t get_input_play_id(void) 144 | { 145 | return BUTTON_PLAY_ID; 146 | } 147 | 148 | // rec button, or key 2 149 | int8_t get_input_rec_id(void) 150 | { 151 | return BUTTON_REC_ID; 152 | } 153 | 154 | int8_t get_green_led_gpio(void) 155 | { 156 | return GREEN_LED_GPIO; 157 | } 158 | -------------------------------------------------------------------------------- /components/ai-thinker-esp32-a1s/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | ifdef CONFIG_AUDIO_BOARD_CUSTOM 7 | COMPONENT_ADD_INCLUDEDIRS += ./ai_thinker_esp32_a1s 8 | COMPONENT_SRCDIRS += ./ai_thinker_esp32_a1s 9 | endif 10 | --------------------------------------------------------------------------------