feat: Add audio BSP component with welcome sound playback functionality
This commit is contained in:
@@ -1,11 +1,32 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
# Reuse the proven codec_board component for startup audio chime support.
|
||||
set(EXTRA_COMPONENT_DIRS
|
||||
"${CMAKE_SOURCE_DIR}/02_Example/07_Audio_Test/components/ExternLib/codec_board")
|
||||
|
||||
# ESP-IDF v6 moved i2c_master.h to esp_driver_i2c; expose it for managed components
|
||||
if(EXISTS "$ENV{IDF_PATH}/components/esp_driver_i2c/include/driver/i2c_master.h")
|
||||
idf_build_set_property(INCLUDE_DIRECTORIES "$ENV{IDF_PATH}/components/esp_driver_i2c/include" APPEND)
|
||||
endif()
|
||||
|
||||
# ESP-IDF v6 splits more driver headers; keep legacy include resolution for codec stack.
|
||||
if(EXISTS "$ENV{IDF_PATH}/components/esp_driver_gpio/include/driver/gpio.h")
|
||||
idf_build_set_property(INCLUDE_DIRECTORIES "$ENV{IDF_PATH}/components/esp_driver_gpio/include" APPEND)
|
||||
endif()
|
||||
if(EXISTS "$ENV{IDF_PATH}/components/esp_driver_i2s/include/driver/i2s_std.h")
|
||||
idf_build_set_property(INCLUDE_DIRECTORIES "$ENV{IDF_PATH}/components/esp_driver_i2s/include" APPEND)
|
||||
endif()
|
||||
if(EXISTS "$ENV{IDF_PATH}/components/esp_driver_spi/include/driver/spi_common.h")
|
||||
idf_build_set_property(INCLUDE_DIRECTORIES "$ENV{IDF_PATH}/components/esp_driver_spi/include" APPEND)
|
||||
endif()
|
||||
if(EXISTS "$ENV{IDF_PATH}/components/esp_hal_gpspi/include/hal/spi_types.h")
|
||||
idf_build_set_property(INCLUDE_DIRECTORIES "$ENV{IDF_PATH}/components/esp_hal_gpspi/include" APPEND)
|
||||
endif()
|
||||
if(EXISTS "$ENV{IDF_PATH}/components/esp_hal_i2s/include/hal/i2s_types.h")
|
||||
idf_build_set_property(INCLUDE_DIRECTORIES "$ENV{IDF_PATH}/components/esp_hal_i2s/include" APPEND)
|
||||
endif()
|
||||
|
||||
# Work around managed-component warnings that are promoted by global -Werror.
|
||||
add_compile_options(-Wno-error=attributes -Wno-error=cpp -Wno-error=missing-field-initializers)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ idf_component_register(
|
||||
espressif__esp_lvgl_adapter
|
||||
port_bsp
|
||||
lvgl__lvgl
|
||||
esp_timer
|
||||
main
|
||||
INCLUDE_DIRS
|
||||
"./")
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"audio_bsp.cpp"
|
||||
REQUIRES
|
||||
hw_platform
|
||||
codec_board
|
||||
espressif__esp_codec_dev
|
||||
PRIV_REQUIRES
|
||||
freertos
|
||||
INCLUDE_DIRS
|
||||
"./")
|
||||
@@ -0,0 +1,125 @@
|
||||
#include "audio_bsp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "hw_platform.h"
|
||||
|
||||
#if PLATFORM_HAS_AUDIO
|
||||
#include "codec_board.h"
|
||||
#include "codec_init.h"
|
||||
#include "esp_codec_dev.h"
|
||||
#endif
|
||||
|
||||
#define TAG "audio_bsp"
|
||||
|
||||
#if PLATFORM_HAS_AUDIO
|
||||
static esp_err_t board_audio_play_square_tone(esp_codec_dev_handle_t speaker,
|
||||
uint32_t freq_hz,
|
||||
uint32_t duration_ms,
|
||||
uint32_t sample_rate_hz)
|
||||
{
|
||||
if(speaker == NULL || freq_hz == 0 || sample_rate_hz == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
static constexpr uint32_t kChunkFrames = 256;
|
||||
static constexpr int16_t kAmplitude = 5000;
|
||||
int16_t pcm[kChunkFrames * 2] = {};
|
||||
|
||||
uint32_t frames_total = (sample_rate_hz * duration_ms) / 1000U;
|
||||
if(frames_total == 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t half_period = sample_rate_hz / (freq_hz * 2U);
|
||||
if(half_period == 0) {
|
||||
half_period = 1;
|
||||
}
|
||||
|
||||
uint32_t frame_index = 0;
|
||||
while(frame_index < frames_total) {
|
||||
uint32_t frames_now = frames_total - frame_index;
|
||||
if(frames_now > kChunkFrames) {
|
||||
frames_now = kChunkFrames;
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < frames_now; ++i) {
|
||||
uint32_t phase_block = (frame_index + i) / half_period;
|
||||
int16_t sample = (phase_block & 1U) ? kAmplitude : (int16_t)-kAmplitude;
|
||||
pcm[(i * 2U)] = sample;
|
||||
pcm[(i * 2U) + 1U] = sample;
|
||||
}
|
||||
|
||||
int write_ret = esp_codec_dev_write(speaker, pcm, frames_now * sizeof(int16_t) * 2U);
|
||||
if(write_ret != ESP_CODEC_DEV_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
frame_index += frames_now;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t BoardAudio_PlayWelcomeSound(void)
|
||||
{
|
||||
#if !PLATFORM_HAS_AUDIO
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#else
|
||||
set_codec_board_type("C6_AMOLED_2_16");
|
||||
|
||||
codec_init_cfg_t codec_cfg = {};
|
||||
codec_cfg.in_mode = CODEC_I2S_MODE_NONE;
|
||||
codec_cfg.out_mode = CODEC_I2S_MODE_TDM;
|
||||
codec_cfg.in_use_tdm = false;
|
||||
codec_cfg.reuse_dev = false;
|
||||
|
||||
if(init_codec(&codec_cfg) != 0) {
|
||||
ESP_LOGW(TAG, "Audio codec init failed; skipping welcome sound");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_codec_dev_handle_t speaker = get_playback_handle();
|
||||
if(speaker == NULL) {
|
||||
ESP_LOGW(TAG, "No speaker handle available; skipping welcome sound");
|
||||
deinit_codec();
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
esp_codec_dev_sample_info_t sample_info = {};
|
||||
sample_info.sample_rate = 16000;
|
||||
sample_info.channel = 2;
|
||||
sample_info.bits_per_sample = 16;
|
||||
|
||||
if(esp_codec_dev_open(speaker, &sample_info) != ESP_CODEC_DEV_OK) {
|
||||
ESP_LOGW(TAG, "Failed to open speaker; skipping welcome sound");
|
||||
deinit_codec();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_codec_dev_set_out_vol(speaker, 75);
|
||||
|
||||
esp_err_t tone_ret = ESP_OK;
|
||||
if(board_audio_play_square_tone(speaker, 880, 90, sample_info.sample_rate) != ESP_OK) {
|
||||
tone_ret = ESP_FAIL;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
if(board_audio_play_square_tone(speaker, 1175, 90, sample_info.sample_rate) != ESP_OK) {
|
||||
tone_ret = ESP_FAIL;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
if(board_audio_play_square_tone(speaker, 1568, 140, sample_info.sample_rate) != ESP_OK) {
|
||||
tone_ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_codec_dev_close(speaker);
|
||||
deinit_codec();
|
||||
|
||||
return tone_ret;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <esp_err.h>
|
||||
|
||||
/**
|
||||
* Play a short welcome chime during desktop power-up.
|
||||
* Returns ESP_OK when played, ESP_ERR_NOT_SUPPORTED when audio is unavailable,
|
||||
* or another error when initialization/playback fails.
|
||||
*/
|
||||
esp_err_t BoardAudio_PlayWelcomeSound(void);
|
||||
@@ -4,12 +4,12 @@ idf_component_register(
|
||||
"display_bsp.cpp"
|
||||
REQUIRES
|
||||
hw_platform
|
||||
waveshare__esp_lcd_touch_cst9217
|
||||
PRIV_REQUIRES
|
||||
driver
|
||||
esp_driver_i2c
|
||||
pmicpower
|
||||
espressif__esp_lcd_sh8601
|
||||
waveshare__esp_lcd_touch_cst9217
|
||||
esp_timer
|
||||
INCLUDE_DIRS
|
||||
"./")
|
||||
|
||||
+12
-1
@@ -33,6 +33,16 @@ dependencies:
|
||||
registry_url: https://components.espressif.com
|
||||
type: service
|
||||
version: 0.5.3
|
||||
espressif/esp_codec_dev:
|
||||
component_hash: 3a1df01ee46d64c55155341bb6f4834db33db7dbd9b637e476e1eab64d01295a
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.4.0
|
||||
espressif/esp_lcd_sh8601:
|
||||
component_hash: 9597cce74af4bae0ec423ee819a2916b995ff3e5bb8d590bdb0a27fa9e715dab
|
||||
dependencies:
|
||||
@@ -292,6 +302,7 @@ dependencies:
|
||||
type: service
|
||||
version: 1.0.1
|
||||
direct_dependencies:
|
||||
- espressif/esp_codec_dev
|
||||
- espressif/esp_lcd_sh8601
|
||||
- espressif/esp_lvgl_adapter
|
||||
- espressif/network_provisioning
|
||||
@@ -300,6 +311,6 @@ direct_dependencies:
|
||||
- waveshare/esp_lcd_touch_cst9217
|
||||
- waveshare/pcf85063a
|
||||
- waveshare/qmi8658
|
||||
manifest_hash: 516a65b37cebe774fee5b9aee6de566de65d59f83ddaf940faac1c9ffd781a0a
|
||||
manifest_hash: f4b0c1c694d3b31623b46182f2333db8f19aa8982ef96218ec14d864550e5cfa
|
||||
target: esp32c6
|
||||
version: 3.0.0
|
||||
|
||||
@@ -2,6 +2,11 @@ idf_component_register(
|
||||
SRCS "app/app_main.cpp"
|
||||
"modules/desktop_ui/desktop_ui.cpp"
|
||||
"modules/wifi_provisioning/wifi_provisioning.cpp"
|
||||
REQUIRES
|
||||
audio_bsp
|
||||
app_bsp
|
||||
pmicpower
|
||||
nvs_flash
|
||||
INCLUDE_DIRS "."
|
||||
"app"
|
||||
"modules/desktop_ui"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "desktop_ui.h"
|
||||
#include "wifi_provisioning.h"
|
||||
#include "qmi8658.h"
|
||||
#include "audio_bsp.h"
|
||||
|
||||
#define TAG "main"
|
||||
|
||||
@@ -110,6 +111,8 @@ extern "C" void app_main(void)
|
||||
Lvgl_unlock();
|
||||
}
|
||||
|
||||
(void)BoardAudio_PlayWelcomeSound();
|
||||
|
||||
ESP_ERROR_CHECK(WifiProvisioning_Bootstrap());
|
||||
|
||||
esp_err_t ret = qmi8658_init(&qmi8658, user_i2cbus.Get_I2cBusHandle(), QMI8658_ADDRESS_HIGH);
|
||||
|
||||
Reference in New Issue
Block a user