这是一次长久的提交:

1. 应用界面增加了返回主页的按钮
2. 修复了gif渲染内存泄漏的严重bug
3. 将PetDao当中的cJSON API替换为cpp_json,完美通过测试
4. 整合已经实现的各种上层建筑,实现了一个宠物对话基本业务应用,用于样品测试展示用
5. 重构了音频播放类,使其更modern,更加便于移植和拓展
This commit is contained in:
Misaki
2025-10-16 11:36:45 +08:00
parent 801138631e
commit ba5e47bc77
38 changed files with 2487 additions and 2008 deletions
+1 -1
View File
@@ -303,7 +303,7 @@ void WebSocketManager::heartbeatThread() {
if (connected && config.heartbeat_interval > 0) { // 如果处于连接状态且心跳间隔大于0
// 发送心跳消息
cppjson::Json hb = cppjson::Json::object();
hb.set("type", cppjson::Json("heartbeat"))
hb.set("type", cppjson::Json("ping"))
.set("timestamp", cppjson::Json(esp_log_timestamp()));
sendJson(hb); // 已经重载好了,直接塞
+198 -462
View File
@@ -4,217 +4,20 @@
#include "CppHandle.h"
#include "OTAClass.h"
#include "PetBaseClass.h"
#include "PetDao.h"
#include <iostream>
#include <optional>
void testPetSystem() {
std::cout << "Test point1" << std::endl;
// 创建阶段策略
auto stageStrategy = std::make_unique<PetStageStrategy>();
stageStrategy->addStage(PetStageType::PET_STAGE_YOUNG, "models/young.obj");
stageStrategy->addStage(PetStageType::PET_STAGE_ADULT, "models/adult.obj");
stageStrategy->addStage(PetStageType::PET_STAGE_OLD, "models/old.obj");
stageStrategy->addStageAudio(PetStageType::PET_STAGE_YOUNG, "audio/young.mp3");
stageStrategy->addStageAudio(PetStageType::PET_STAGE_ADULT, "audio/adult.mp3");
stageStrategy->addStageAudio(PetStageType::PET_STAGE_OLD, "audio/old.mp3");
// 创建动作策略
auto actionStrategy = std::make_unique<PetActionStrategy>();
actionStrategy->addAction(PetActionType::PET_ACTION_EAT, "models/eat.obj");
actionStrategy->addAction(PetActionType::PET_ACTION_HAPPY, "models/happy.obj");
actionStrategy->addAction(PetActionType::PET_ACTION_SLEEP, "models/sleep.obj");
actionStrategy->addAction(PetActionType::PET_ACTION_ANGRY, "models/angry.obj");
actionStrategy->addAction(PetActionType::PET_ACTION_SAD, "models/sad.obj");
actionStrategy->addAction(PetActionType::PET_ACTION_EVOLVE, "models/evolve.obj");
actionStrategy->addAction(PetActionType::PET_ACTION_TOUCH, "models/touch.obj");
actionStrategy->addActionAudio(PetActionType::PET_ACTION_EAT, "audio/eat.mp3");
actionStrategy->addActionAudio(PetActionType::PET_ACTION_HAPPY, "audio/happy.mp3");
actionStrategy->addActionAudio(PetActionType::PET_ACTION_SLEEP, "audio/sleep.mp3");
std::cout << "Test point2" << std::endl;
// 创建宠物信息
PetBaseInfo info;
info.pet_name = "芝士雪豹";
info.pet_hp = 100;
info.pet_density = 50;
info.pet_identity = "我是顶真";
// 创建宠物
auto pet = std::make_shared<PetBase>(info, std::move(stageStrategy), std::move(actionStrategy));
std::cout << "Test point3" << std::endl;
// 创建音频观察者
auto audioStrategy = std::make_shared<PetAudioStrategy>();
audioStrategy->setAudioCallback([](const std::string& audioPath) {
std::cout << "Playing audio: " << audioPath << std::endl;
});
audioStrategy->subscribe(pet);
std::cout << "Test point4" << std::endl;
// 创建渲染器观察者
auto rendererStrategy = std::make_shared<PetRendererStrategy>(
pet->getStageStrategy(),
pet->getActionStrategy()
);
rendererStrategy->setRenderCallback([](const std::string& modelPath) {
std::cout << "Rendering model: " << modelPath << std::endl;
});
rendererStrategy->subscribe(pet);
std::cout << "Test point5" << std::endl;
// 执行一些动作
std::cout << "=== Testing basic actions ===" << std::endl;
pet->feed();
pet->play();
pet->touch();
std::cout << "Test point6" << std::endl;
// 检查当前状态
std::cout << "Current HP: " << pet->getPetInfo().pet_hp << std::endl;
std::cout << "Current density: " << pet->getPetInfo().pet_density << std::endl;
std::cout << "Current stage: " << static_cast<int>(pet->getCurrentStage()) << std::endl;
std::cout << "Current action: " << static_cast<int>(pet->getCurrentAction()) << std::endl;
std::cout << "Test point7" << std::endl;
// 测试进化
std::cout << "\n=== Testing evolution ===" << std::endl;
// 直接修改亲密度来测试进化
PetBaseInfo newInfo = pet->getPetInfo();
newInfo.pet_density = 100; // 达到进化条件
pet->setPetInfo(newInfo);
std::cout << "Test point8" << std::endl;
if (pet->checkEvolution()) {
std::cout << "Evolution successful!" << std::endl;
} else {
std::cout << "Evolution failed!" << std::endl;
}
// 进一步增加亲密度到150,尝试再次进化
newInfo.pet_density = 150;
pet->setPetInfo(newInfo);
if (pet->checkEvolution()) {
std::cout << "Second evolution successful!" << std::endl;
} else {
std::cout << "Second evolution failed!" << std::endl;
}
std::cout << "Final stage: " << static_cast<int>(pet->getCurrentStage()) << std::endl;
PetDAO petDAO(SDFileManager::getInstance());
petDAO.savePet(pet, "my_pet.json");
// 列出所有宠物文件
auto petFiles = petDAO.listPetFiles();
for (const auto& file : petFiles) {
std::cout << "Pet file: " << file << std::endl;
}
std::cout << SDFileManager::getInstance()->catCommand("/sdcard/pet_data/my_pet.json") << std::endl;
}
#include "SpeechRecognizer.h"
#include <nvs.h>
#include <nvs_flash.h>
// 命令回调函数
void commandCallback(int command_id, const std::string& phrase, float probability) {
ESP_LOGI("Example", "Received command: ID=%d, Phrase='%s', Probability=%.2f",
command_id, phrase.c_str(), probability);
// 根据命令执行相应操作
switch (command_id) {
case 0:
ESP_LOGI("Example", "执行命令0");
// 执行命令0的操作
break;
case 1:
ESP_LOGI("Example", "执行命令1");
// 执行命令1的操作
break;
case 2:
ESP_LOGI("Example", "执行命令2");
// 执行命令2的操作
break;
default:
ESP_LOGI("Example", "未知的命令ID: %d", command_id);
break;
}
}
// 状态回调函数
void stateCallback(const std::string& state) {
ESP_LOGI("Example", "状态改变到: %s", state.c_str());
}
#include "SDFileManager.h"
void testMIC() {
// 初始化NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// 初始化SD卡管理器
SDFileManager::getInstance()->tryInitSDCard();
// 获取SpeechRecognizer实例
SpeechRecognizer* recognizer = SpeechRecognizer::getInstance();
// 配置识别器
SpeechRecognizerConfig config;
config.enable_vad = true;
config.vad_mode = VAD_MODE_3; // 更高的VAD灵敏度
config.model_path = "/sdcard/srmodels";
// 初始化
if (!recognizer->init(config)) {
ESP_LOGE("main", "Failed to initialize speech recognizer");
return;
}
// 添加自定义命令
std::vector<std::pair<int, std::string>> commands = {
{0, "kai deng"}, // 开灯
{1, "guan deng"}, // 关灯
{2, "ti gao liang du"}, // 提高亮度
{3, "jiang di liang du"}, // 降低亮度
{4, "bo fang yin yue"}, // 播放音乐
{5, "ting zhi bo fang"} // 停止播放
};
if (!recognizer->addCommands(commands)) {
ESP_LOGE("main", "Failed to add some commands");
}
// 注册回调函数
recognizer->registerCommandCallback(commandCallback);
recognizer->registerStateCallback(stateCallback);
// 开始识别
if (!recognizer->start()) {
ESP_LOGE("main", "Failed to start speech recognition");
return;
}
ESP_LOGI("main", "Speech recognition system started successfully");
}
#include <mbedtls/base64.h>
#include "ToolsClass.h"
#include "WifiConnectors.h"
#include "CommClass.h"
#include "sys_conf_singleton.h"
#include "HttpOtaUpdater.h"
using namespace std::chrono;
const auto sleep_time = seconds{
5
};
#include "AudioOutput.h"
// OTA相关
HttpOtaUpdater otaUpdater;
void setupOtaCallbacks() {
// 设置进度回调
otaUpdater.setProgressCallback([](int progress, int total) {
@@ -222,15 +25,15 @@ void setupOtaCallbacks() {
});
// 设置状态回调
otaUpdater.setStateCallback([](HttpOtaUpdater::OtaState state, const std::string& message) {
const char* stateNames[] = {
otaUpdater.setStateCallback([](HttpOtaUpdater::OtaState state, const std::string &message) {
const char *stateNames[] = {
"IDLE", "CONNECTING", "DOWNLOADING", "VERIFYING", "SUCCESS", "FAILED"
};
ESP_LOGI("OTA", "State: %s - %s", stateNames[static_cast<int>(state)], message.c_str());
});
// 设置完成回调
otaUpdater.setFinishCallback([](bool success, const std::string& message) {
otaUpdater.setFinishCallback([](bool success, const std::string &message) {
if (success) {
ESP_LOGI("OTA", "Completed successfully: %s", message.c_str());
} else {
@@ -243,6 +46,55 @@ void setupOtaCallbacks() {
// otaUpdater.skipCertCommonNameCheck(true); // 仅用于测试
}
// 把 HTTP 文件完整下载到 PSRAM,返回首地址和长度
uint8_t *download_to_psram(const char *url, size_t *out_len)
{
uint8_t *buf = nullptr;
size_t total = 0;
esp_http_client_config_t cfg = {
.url = url,
.timeout_ms = 10000,
.keep_alive_enable = true,
};
esp_http_client_handle_t client = esp_http_client_init(&cfg);
if (esp_http_client_open(client, 0) != ESP_OK) {
ESP_LOGE("HTTP", "Failed to open HTTP connection");
}
int content_len = esp_http_client_fetch_headers(client);
if (content_len <= 0) {
ESP_LOGE("HTTP", "Content-Length invalid");
goto err;
}
buf = (uint8_t *)heap_caps_malloc(content_len, MALLOC_CAP_SPIRAM);
if (!buf) {
ESP_LOGE("HTTP", "PSRAM malloc %d bytes failed", content_len);
goto err;
}
int read;
do {
read = esp_http_client_read(client, (char *)buf + total, content_len - total);
if (read > 0) total += read;
} while (read > 0 && total < content_len);
if (total != content_len) {
ESP_LOGE("HTTP", "Download incomplete %d/%d", total, content_len);
heap_caps_free(buf);
buf = nullptr;
goto err;
}
*out_len = total;
ESP_LOGI("HTTP", "Download done, %d bytes in PSRAM", total);
err:
esp_http_client_close(client);
esp_http_client_cleanup(client);
return buf;
}
// JSON 数据回调函数
/** 交互所使用的json内容
{
@@ -250,14 +102,14 @@ void setupOtaCallbacks() {
"xxx":"xxx", // 其他数据
......
}
此回调函数为核心业务处理函数!!!
*/
void onJsonData(const cppjson::Json& json)
{
void onJsonData(const cppjson::Json &json) {
// 打印收到的 JSON
ESP_LOGI("JSON_CALLBACK", "收到JSON数据: %s", json.dump().c_str());
// 解析消息类型
const cppjson::Json& type = json["type"];
const cppjson::Json &type = json["type"];
if (!type.isString()) return;
std::string typeStr = type.asString();
@@ -276,11 +128,11 @@ void onJsonData(const cppjson::Json& json)
ESP_LOGI("JSON_CALLBACK", "收到OTA消息");
// 进一步处理OTA消息
// 获取OTA中的版本信息
const cppjson::Json& version = json["version"];
const cppjson::Json &version = json["version"];
if (!version.isString()) return;
std::string versionStr = version.asString();
// 获取OTA中的HTTP URL
const cppjson::Json& url = json["url"];
const cppjson::Json &url = json["url"];
if (!url.isString()) return;
std::string urlStr = url.asString();
// 告诉服务端,升级开始
@@ -288,12 +140,25 @@ void onJsonData(const cppjson::Json& json)
response.set("type", cppjson::Json("ota_start"));
WebSocketManager::getInstance()->sendJson(response);
otaUpdater.start(urlStr);
} else if (typeStr == "audio") {
ESP_LOGI("JSON_CALLBACK", "收到音频消息");
// 进一步解析音频消息内容
// 获取音频信息
cppjson::Json audio_url = json["audio_url"]; // 音频信息
cppjson::Json audio_size = json["audio_size"]; // 音频信息
if (!audio_url.isObject()) return;
if (!audio_size.isObject()) return;
std::cout << "base64: " << audio_url.asString() << std::endl;
std::cout << "size: " << audio_size.asInt() << std::endl;
size_t size;
const uint8_t *pcm_buf = download_to_psram(audio_url.asString().c_str(), &size);
// 播放音频
AudioOutput::getInstance()->playPcmStream(pcm_buf, size);
}
}
// WebSocket事件回调函数
void onWebSocketEvent(WebSocketEvent event, const std::string& message) {
void onWebSocketEvent(WebSocketEvent event, const std::string &message) {
switch (event) {
case WebSocketEvent::CONNECTED:
ESP_LOGI("EVENT_CALLBACK", "WebSocket已连接: %s", message.c_str());
@@ -311,16 +176,15 @@ void onWebSocketEvent(WebSocketEvent event, const std::string& message) {
}
// 发送状态信息函数
void sendStatus()
{
void sendStatus() {
cppjson::Json status = cppjson::Json::object();
status.set("type", cppjson::Json("status"));
cppjson::Json data = cppjson::Json::object();
data.set("free_heap", cppjson::Json(esp_get_free_heap_size()))
.set("uptime", cppjson::Json(xTaskGetTickCount() * portTICK_PERIOD_MS / 1000));
.set("uptime", cppjson::Json(xTaskGetTickCount() * portTICK_PERIOD_MS / 1000));
status.set("data", data); // 嵌套对象
status.set("data", data); // 嵌套对象
if (WebSocketManager::getInstance()->sendJson(status)) {
ESP_LOGI("SEND", "已发送状态信息");
@@ -330,8 +194,7 @@ void sendStatus()
}
// 发送问候消息函数
void sendGreeting()
{
void sendGreeting() {
cppjson::Json greeting = cppjson::Json::object();
greeting.set("type", cppjson::Json("greeting"))
.set("message", cppjson::Json("Hello from ESP32-S3"))
@@ -343,6 +206,7 @@ void sendGreeting()
ESP_LOGE("SEND", "发送问候消息失败");
}
}
void websocket_task() {
TickType_t lastStatusTime = 0;
TickType_t lastHeartbeatTime = 0;
@@ -392,7 +256,8 @@ void createWebSocket() {
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
// 保存SN
SysConfJson::getInstance()->saveSN(ToolsClass::GenerateSN(ToolsClass::getChipMAC(), ToolsClass::getChipSerialNumber()));
SysConfJson::getInstance()->saveSN(
ToolsClass::GenerateSN(ToolsClass::getChipMAC(), ToolsClass::getChipSerialNumber()));
// 读取SN
std::string sn = SysConfJson::getInstance()->loadSN();
ESP_LOGI("conf", "loaded sn = %s", sn.c_str());
@@ -400,15 +265,15 @@ void createWebSocket() {
// 配置WebSocket
WebSocketConfig config;
config.uri = "ws://" + std::string("192.168.1.11") + ":" + std::to_string(8080) + "/ws";
config.auto_reconnect = true; // 自动重连
config.reconnect_interval = 5000; // 重连间隔(毫秒)
config.heartbeat_interval = 30000; // 心跳间隔(毫秒)
config.auto_reconnect = true; // 自动重连
config.reconnect_interval = 5000; // 重连间隔(毫秒)
config.heartbeat_interval = 30000; // 心跳间隔(毫秒)
config.max_reconnect_attempts = 10; // 最大重连尝试次数
// TODO: 此处通信类存在线程重复创建bug,似乎是来自esp-idf的bug,待查证
// 初始化WebSocket管理器
if (!WebSocketManager::getInstance()->initialize(config)) {
ESP_LOGE("APP_TASK", "WebSocket管理器初始化失败");
vTaskDelete(NULL);
vTaskDelete(nullptr);
return;
}
@@ -432,248 +297,120 @@ void createWebSocket() {
std::thread websocket_thread = ThreadManager::createThread(websocket_config, websocket_task);
websocket_thread.detach();
}
#include "LVGLRender.h"
#include <lvgl.h>
#define TAG "BIN_TEST"
/* 从 SD 卡读任意 .bin 到堆 → 直接显示 */
void test_show_bin(const char* fileName)
{
ESP_LOGI(TAG, "=== fast bin test: %s ===", fileName);
/* 1. 读文件 */
std::string path = "/sdcard/" + std::string(fileName);
std::string data = SDFileManager::getInstance()->readFileSync(path.c_str());
if (data.empty()) {
ESP_LOGE(TAG, "read fail");
return;
}
size_t sz = data.size();
ESP_LOGI(TAG, "file size = %zu", sz);
ESP_LOG_BUFFER_HEX(TAG, data.data(), 16); // 头 16 字节
/* 2. 拷到堆(LVGL 长期持有)*/
void* buf = heap_caps_malloc(sz, MALLOC_CAP_8BIT);
memcpy(buf, data.data(), sz);
/* 3. 离线量好的尺寸(先填 320×240 测试,不对再改)*/
uint32_t w = 720;
uint32_t h = 720;
if (sz != w * h * 2) { // RGB565 每像素 2 字节
ESP_LOGW(TAG, "size mismatch, expect %ld, got %zu", w * h * 2, sz);
}
/* 4. 一次性描述符 */
static lv_img_dsc_t dsc;
dsc.data = static_cast<const uint8_t *>(buf);
dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
dsc.header.w = w;
dsc.header.h = h;
dsc.data_size = sz;
/* 5. 直接显示(不经过 PNG 解码器)*/
lv_obj_t* img = lv_img_create(lv_scr_act());
lv_img_set_src(img, &dsc);
lv_obj_center(img);
ESP_LOGI(TAG, "bin displayed, w=%ld h=%ld", w, h);
}
#include "SimpleI2SForwarder.h"
#include "lvpp.h"
#include "BaseApp.h"
LV_FONT_DECLARE(SiYuanHeiTiGoogleBan);
// 使用全局智能指针管理主要对象
static std::shared_ptr<lvgl_cpp::Screen> g_screen;
using namespace lvgl_cpp;
struct AppCalc : BaseApp {
using BaseApp::BaseApp;
void onShow() override {
Label(*this).text("Calculator").center();
static std::shared_ptr<lvgl_cpp::HomePage> g_home;
static std::shared_ptr<lvgl_cpp::AppMenu> g_menu;
int pet_Test() {
/*
// 存档
PetDAO dao(SDFileManager::getInstance());
const string filename = "cheese_snow_leopard.json";
cout << "\n===== 存档 =====" << endl;
if (dao.savePet(pet, filename))
cout << "✅ 已保存到 " << filename << endl;
else
cout << "❌ 保存失败" << endl;
// 5. 读档
cout << "\n===== 读档 =====" << endl;
auto loaded = dao.loadPet(filename);
if (!loaded) {
cout << "❌ 读档失败" << endl;
return 0;
}
};
struct AppMusic : BaseApp {
using BaseApp::BaseApp;
void onShow() override {
btn_.emplace(*this);
gif.emplace(*this);
btn_->size(180, 60)
.align(LV_ALIGN_CENTER, nullptr, 0, 80)
.on(LV_EVENT_CLICKED, [&](lv_event_t*) {
/* 居中 GIF,背景黑 */
lv_obj_set_style_bg_color(this->raw(), lv_color_black(), 0);
lv_obj_set_style_bg_opa(this->raw(), LV_OPA_COVER, 0);
gif->src("small_-min.gif")
.center();
});
cout << "✅ 读档成功,继续互动:" << endl;
printPet(*loaded);
/* 按钮文字 */
lv_obj_t* label = lv_label_create(btn_->raw());
lv_obj_set_style_text_font(label, &SiYuanHeiTiGoogleBan, LV_PART_MAIN);
lv_label_set_text(label, "Gif测试");
lv_obj_center(label);
}
private:
std::optional<lvgl_cpp::Button> btn_; // c++17 轻量 RAII
std::optional<lvgl_cpp::Gif> gif;
};
// 6. 对新对象继续互动
loaded->neglect(); printPet(*loaded);
loaded->feed(); printPet(*loaded);
*/
return 1;
}
class ButtonApp : public BaseApp {
public:
using BaseApp::BaseApp; // 继承 exit 按钮机制
void onShow() override {
/* 居中按钮:180×60 px,圆角,现代蓝 */
btn_.emplace(*this);
btn_->size(180, 60)
.align(LV_ALIGN_CENTER, nullptr, 0, 80)
.on(LV_EVENT_CLICKED, [](lv_event_t*) {
lvgl_cpp::Toast::show("咕咕嘎嘎!",
lvgl_cpp::Toast::Type::INFO,
1000);
});
LV_FONT_DECLARE(SiYuanHeiTiGoogleBan);
/* 按钮文字 */
lv_obj_t* label = lv_label_create(btn_->raw());
lv_obj_set_style_text_font(label, &SiYuanHeiTiGoogleBan, LV_PART_MAIN);
lv_label_set_text(label, "按我");
lv_obj_center(label);
}
private:
std::optional<lvgl_cpp::Button> btn_; // c++17 轻量 RAII
};
static std::shared_ptr<HomePage> g_home;
static std::shared_ptr<AppMenu> g_menu;
void Cpp_Hand() {
// testMIC();
// testPetSystem();
SDFileManager::getInstance()->tryInitSDCard();
// 打印设备信息
ESP_LOGI("CppHandle::Cpp_Hand", "当前固件版本 %s:", ToolsClass::getDeviceVersion().c_str());
ESP_LOGI("CppHandle::Cpp_Hand", "当前设备MAC地址 %s:", ToolsClass::getChipMAC().c_str());
ESP_LOGI("CppHandle::Cpp_Hand", "当前设备固件序列号 %s:", ToolsClass::getChipSerialNumber().c_str());
SDFileManager::getInstance()->tryInitSDCard(); // 初始化SD卡
LVGLRender::getInstance()->tryToInitRenderGif(); // 初始化lvgl驱动(包括任务循环)
LVGLRender::setFps(60); // 设置lvgl刷新频率
LVGLRender::setFps(60); // 设置lvgl刷新频率
/* LVGL 已经初始化,屏幕驱动已注册 */
// auto scr = lvgl_cpp::Screen{}; // RAII,离开作用域自动 del
// lv_scr_load(scr.raw()); // 让 LVGL 把它当活动屏幕
// lvgl_cpp::Image img(scr);
// img.bin("pic_no_alp_swap.bin", 720, 720)
// .center();
//
// /* 1. 创建按钮 */
// /* 1. 黑色文字样式 */
// static lvgl_cpp::Style txt_style;
// txt_style.text_color(lv_color_black());
//
// /* 2. 按钮 */
// lvgl_cpp::Button btn{scr};
// btn.size(150, 60).pos(40, 40);
// /* 3. 先创建 Label 对象并保存,再链式调 */
// lvgl_cpp::Label lbl{btn}; // 一定要存实例
// lbl.text("Click Me")
// .add_style(&txt_style.s, LV_PART_MAIN); // 样式作用到文字本身
// /* 3. 注册点击事件 */
// btn.on(LV_EVENT_CLICKED, [](lv_event_t*){
// lvgl_cpp::Toast::show("Saved successfully !");
// /* 2. 警告,3 s,顶部 */
// lvgl_cpp::Toast::show("SD card missing", lvgl_cpp::Toast::Type::WARN, 3000, LV_ALIGN_TOP_MID, 20);
//
// /* 3. 错误,1.5 s,底部右侧 */
// lvgl_cpp::Toast::show("Network error", lvgl_cpp::Toast::Type::ERROR, 1500, LV_ALIGN_BOTTOM_RIGHT, -30);
// ESP_LOGI("BTN", "pressed");
// });
//
// /* 1. 消息框 */
// // const char* btns[] = {"Yes", "No", ""};
// // auto mbox = lvgl_cpp::MsgBox::create("Hint", "Delete file ?", btns);
//
// /* 3. 进度条(双向 + 动画) */
// lvgl_cpp::Bar bar(scr);
// bar.range(0, 100)
// .start_value(20) // 左端
// .value(80, LV_ANIM_ON) // 右端带动画
// .anim_time(500)
// .size(200, 15)
// .align(LV_ALIGN_CENTER, nullptr, 0, 40);
//
// /* 4. 折线:画一个 △ */
// std::vector<lv_point_t> triangle = {{0,0}, {40,0}, {20,40}, {0,0}};
// lvgl_cpp::Line line(scr);
// line.points(triangle)
// .y_invert(false)
// .align(LV_ALIGN_CENTER, nullptr, 0, 100);
//
// lvgl_cpp::Battery bat(scr);
// bat.size(60, 30) // 手机经典尺寸
// .percent(true) // 显示 50%
// .onRead([]() -> uint8_t { // 替换成你的 ADC/INA219 回调
// static uint8_t v = 100;
// if (v) --v;
// return v;
// })
// .align(LV_ALIGN_TOP_RIGHT, -10, 10); // 九宫格对齐
//
// /* 3. 日期时间 */
// lvgl_cpp::DateTime dt(scr);
// dt.format("%m/%d %a %H:%M")
// .onRead([](char* buf, size_t len){
// /* 这里用 SNTP / RTC 填充,示例直接给假时间 */
// snprintf(buf, len, "06/25 Tue 14:30");
// })
// .align(LV_ALIGN_BOTTOM_MID, nullptr, 0, -10);
// lvgl_cpp::ColorPicker cp(scr);
// cp.size(120, 120)
// .align(LV_ALIGN_BOTTOM_MID, nullptr, 0, -20)
// .on(LV_EVENT_VALUE_CHANGED, [&](lv_event_t*){
// lv_color_t c = cp.color();
// ESP_LOGI("CP", "rgb=%d,%d,%d", c.ch.red, c.ch.green_h, c.ch.blue);
// });
// 1. 创建屏幕
// 创建屏幕
g_screen = std::make_shared<lvgl_cpp::Screen>();
lv_scr_load(g_screen->raw());
// 2. 延迟创建界面组件
// 延迟创建界面组件
auto init_timer = std::make_unique<lvgl_cpp::Timer>([&]() {
ESP_LOGI("MAIN", "Initializing UI components...");
// 创建主页
g_home = std::make_shared<HomePage>(*g_screen);
g_home = std::make_shared<lvgl_cpp::HomePage>(*g_screen);
g_home->bg("pic360.bin", 360, 360)
.onBattery([]() -> uint8_t {
static uint8_t v = 100;
if (v) --v;
return 88;
})
.onDateTime([](char* buf, size_t len) {
snprintf(buf, len, "06/25 Tue 14:30");
});
// 创建菜单
g_menu = std::make_shared<AppMenu>(*g_screen);
g_menu->addItem("Calcu", 100, 50)
.addItem("Gif测试", 100, 50)
.addItem("Button", 100, 50)
.onClick([](const char* name) {
ESP_LOGI("APP", "Launching: %s", name);
/* 1. 让工厂创建子应用 */
auto app = AppFactory::create(name, *g_screen);
if (!app) return;
/* 2. 隐藏菜单,显示应用 */
lv_obj_add_flag(g_menu->raw(), LV_OBJ_FLAG_HIDDEN);
app->onShow();
/* 3. 应用退出时回到菜单 */
app->onExit([app_ptr = app.release()]() { // 转移所有权到 lambda
lv_obj_clear_flag(g_menu->raw(), LV_OBJ_FLAG_HIDDEN);
lv_obj_del(app_ptr->raw()); // 自毁
.onBattery([]() -> uint8_t {
return static_cast<uint8_t>(ToolsClass::getInstance()->getBatteryPer());
})
.onDateTime([](char *buf, const size_t len) {
snprintf(buf, len, "06/25 Tue 14:30");
});
});
// 创建菜单
g_menu = std::make_shared<lvgl_cpp::AppMenu>(*g_screen);
g_menu->addItem("Calcu", 100, 50)
.addItem("Gif测试", 100, 50)
.addItem("Button", 100, 50)
.addItem("AI测试", 100, 50)
.addItem("长按录音", 100, 50)
.addItem("宠物样例", 100, 50)
.onClick([](const char *name) {
ESP_LOGI("APP", "Launching: %s", name);
// 让工厂创建子应用
auto app = lvgl_cpp::AppFactory::create(name, *g_screen);
if (!app) return;
// 隐藏菜单,显示应用
lv_obj_add_flag(g_menu->raw(), LV_OBJ_FLAG_HIDDEN);
app->onShow();
// 应用退出时回到菜单
app->onExit([app_ptr = app.release()]() {
// 转移所有权到 lambda
lv_obj_clear_flag(g_menu->raw(), LV_OBJ_FLAG_HIDDEN);
lv_obj_del(app_ptr->raw()); // 自毁
});
});
g_menu->onBack([]() {
ESP_LOGI("AppMenu", "返回主页回调执行");
// 添加调试信息
if (g_menu && g_menu->raw()) {
ESP_LOGI("AppMenu", "隐藏菜单");
lv_obj_add_flag(g_menu->raw(), LV_OBJ_FLAG_HIDDEN);
} else {
ESP_LOGE("AppMenu", "菜单对象无效");
}
if (g_home && g_home->raw()) {
ESP_LOGI("AppMenu", "显示主页");
lv_obj_clear_flag(g_home->raw(), LV_OBJ_FLAG_HIDDEN);
} else {
ESP_LOGE("AppMenu", "主页对象无效");
}
// 强制刷新显示
lv_refr_now(nullptr);
});
lv_obj_add_flag(g_menu->raw(), LV_OBJ_FLAG_HIDDEN);
// 安全的事件连接
g_home->onOpenMenu([]() {
if (g_home && g_menu) {
@@ -681,44 +418,43 @@ void Cpp_Hand() {
lv_obj_clear_flag(g_menu->raw(), LV_OBJ_FLAG_HIDDEN);
}
});
ESP_LOGI("MAIN", "UI initialization complete");
}, 1000, true); // 1秒后执行一次
// 注册应用
AppFactory::registerApp("Calcu", [](Obj& p) {
lvgl_cpp::AppFactory::registerApp("Calcu", [](lvgl_cpp::Obj &p) {
return std::make_unique<AppCalc>(p);
});
AppFactory::registerApp("Gif测试", [](Obj& p) {
lvgl_cpp::AppFactory::registerApp("Gif测试", [](lvgl_cpp::Obj &p) {
return std::make_unique<AppMusic>(p);
});
AppFactory::registerApp("Button", [](lvgl_cpp::Obj& p) {
lvgl_cpp::AppFactory::registerApp("Button", [](lvgl_cpp::Obj &p) {
return std::make_unique<ButtonApp>(p);
});
// test_show_bin("pic_no_alp_swap.bin");
// LVGLRender::getInstance()->RenderGif("sequence02mmm.gif");
ESP_LOGI("CppHandle::Cpp_Hand", "当前固件版本 %s:", ToolsClass::getDeviceVersion().c_str());
ESP_LOGI("CppHandle::Cpp_Hand", "当前设备MAC地址 %s:", ToolsClass::getChipMAC().c_str());
ESP_LOGI("CppHandle::Cpp_Hand", "当前设备固件序列号 %s:", ToolsClass::getChipSerialNumber().c_str());
lvgl_cpp::AppFactory::registerApp("AI测试", [](lvgl_cpp::Obj &p) {
return std::make_unique<WebSocketVoice>(p);
});
lvgl_cpp::AppFactory::registerApp("长按录音", [](lvgl_cpp::Obj &p) {
return std::make_unique<LongPressButtonAnim>(p);
});
lvgl_cpp::AppFactory::registerApp("宠物样例", [](lvgl_cpp::Obj &p) {
return std::make_unique<PetApp>(p);
});
// 连接wifi
// WifiConnectors::getInstance()->connectWifi("Misaki-2.4G", "88888888", 5);
WifiConnectors::getInstance()->connectWifi("Misaki-2.4G", "88888888", 5);
// 创建WebSocket
// createWebSocket();
createWebSocket();
// 设置OTA回调
// setupOtaCallbacks();
while (true) { // 主线程线程循环
// ThreadManager::print_sys_memory(); // 打印系统内存使用情况
while (true) {
// 主线程线程循环
ThreadManager::print_sys_memory(); // 打印系统内存使用情况
// ThreadManager::stats_task(); // 打印任务统计信息
ESP_LOGI("APP_TASK", "Battery is:%ld", ToolsClass::getInstance()->getBatteryPer());
ESP_LOGI("APP_TASK", "Battery is:%f", ToolsClass::getInstance()->getBatteryVolts());
std::this_thread::sleep_for(sleep_time); // 休眠5
// ESP_LOGI("APP_TASK", "Battery is:%ld", ToolsClass::getInstance()->getBatteryPer());
// ESP_LOGI("APP_TASK", "Battery is:%f", ToolsClass::getInstance()->getBatteryVolts());
std::this_thread::sleep_for(std::chrono::seconds(1)); // 休眠 1
}
}
+108 -139
View File
@@ -47,48 +47,43 @@ PetDAO::PetDAO(SDFileManager* fileManager) : fileManager(fileManager) {
}
bool PetDAO::savePet(const std::shared_ptr<PetBase>& pet, const std::string& filename) {
// 转换为JSON
cJSON* json = petToJson(pet);
if (!json) {
try {
// 转换为JSON
cppjson::Json json = petToJson(pet);
// 序列化为字符串
std::string jsonStr = json.dump();
std::string fullPath = std::string(PET_DATA_DIR) + "/" + filename;
// 保存到文件
const bool success = fileManager->writeFileSync(fullPath.c_str(), jsonStr.c_str(), jsonStr.size(), "w");
return success;
} catch (const std::exception& e) {
std::cerr << "Save pet failed: " << e.what() << std::endl;
return false;
}
// 转换为字符串
char* jsonStr = cJSON_PrintUnformatted(json);
std::string fullPath = std::string(PET_DATA_DIR) + "/" + filename;
// 保存到文件
bool success = fileManager->writeFileSync(fullPath.c_str(), jsonStr);
// 清理资源
free(jsonStr);
cJSON_Delete(json);
return success;
}
std::shared_ptr<PetBase> PetDAO::loadPet(const std::string& filename) {
std::string fullPath = std::string(PET_DATA_DIR) + "/" + filename;
try {
std::string fullPath = std::string(PET_DATA_DIR) + "/" + filename;
// 读取文件内容
std::string content = fileManager->readFileSync(fullPath.c_str());
if (content.empty()) {
// 读取文件内容
std::string content = fileManager->readFileSync(fullPath.c_str());
if (content.empty()) {
return nullptr;
}
// 解析JSON
cppjson::Json json = cppjson::Json::parse(content);
// 创建宠物对象
return petFromJson(json);
} catch (const std::exception& e) {
std::cerr << "Load pet failed: " << e.what() << std::endl;
return nullptr;
}
// 解析JSON
cJSON* json = cJSON_Parse(content.c_str());
if (!json) {
return nullptr;
}
// 创建宠物对象
auto pet = petFromJson(json);
// 清理资源
cJSON_Delete(json);
return pet;
}
std::vector<std::string> PetDAO::listPetFiles() {
@@ -100,204 +95,178 @@ bool PetDAO::deletePetFile(const std::string& filename) {
return fileManager->rmCommand(fullPath.c_str(), false);
}
cJSON* PetDAO::petToJson(const std::shared_ptr<PetBase>& pet) {
cJSON* json = cJSON_CreateObject();
if (!json) return nullptr;
cppjson::Json PetDAO::petToJson(const std::shared_ptr<PetBase>& pet) {
auto json = cppjson::Json::object();
// 添加基本信息
cJSON_AddStringToObject(json, "name", pet->pet_info.pet_name.c_str());
cJSON_AddNumberToObject(json, "hp", pet->pet_info.pet_hp);
cJSON_AddNumberToObject(json, "density", pet->pet_info.pet_density);
cJSON_AddStringToObject(json, "identity", pet->pet_info.pet_identity.c_str());
json.set("name", cppjson::Json(pet->pet_info.pet_name))
.set("hp", cppjson::Json(pet->pet_info.pet_hp))
.set("density", cppjson::Json(pet->pet_info.pet_density))
.set("identity", cppjson::Json(pet->pet_info.pet_identity));
// 添加阶段策略
cJSON* stageJson = stageStrategyToJson(pet->pet_stage_strategy);
if (stageJson) {
cJSON_AddItemToObject(json, "stage_strategy", stageJson);
auto stageJson = stageStrategyToJson(pet->pet_stage_strategy);
if (!stageJson.isNull()) {
json.set("stage_strategy", stageJson);
}
// 添加动作策略
cJSON* actionJson = actionStrategyToJson(pet->pet_action_strategy);
if (actionJson) {
cJSON_AddItemToObject(json, "action_strategy", actionJson);
auto actionJson = actionStrategyToJson(pet->pet_action_strategy);
if (!actionJson.isNull()) {
json.set("action_strategy", actionJson);
}
return json;
}
std::shared_ptr<PetBase> PetDAO::petFromJson(cJSON* json) {
if (!json) return nullptr;
std::shared_ptr<PetBase> PetDAO::petFromJson(const cppjson::Json& json) {
if (json.isNull()) return nullptr;
// 创建宠物基本信息
PetBaseInfo info;
cJSON* nameItem = cJSON_GetObjectItemCaseSensitive(json, "name");
if (cJSON_IsString(nameItem)) {
info.pet_name = nameItem->valuestring;
if (json["name"].isString()) {
info.pet_name = json["name"].asString();
}
cJSON* hpItem = cJSON_GetObjectItemCaseSensitive(json, "hp");
if (cJSON_IsNumber(hpItem)) {
info.pet_hp = hpItem->valueint;
if (json["hp"].isNumber()) {
info.pet_hp = json["hp"].asInt();
}
cJSON* densityItem = cJSON_GetObjectItemCaseSensitive(json, "density");
if (cJSON_IsNumber(densityItem)) {
info.pet_density = densityItem->valueint;
if (json["density"].isNumber()) {
info.pet_density = json["density"].asInt();
}
cJSON* identityItem = cJSON_GetObjectItemCaseSensitive(json, "identity");
if (cJSON_IsString(identityItem)) {
info.pet_identity = identityItem->valuestring;
if (json["identity"].isString()) {
info.pet_identity = json["identity"].asString();
}
// 创建阶段策略
cJSON* stageJson = cJSON_GetObjectItemCaseSensitive(json, "stage_strategy");
auto stageStrategy = stageStrategyFromJson(stageJson);
auto stageStrategy = stageStrategyFromJson(json["stage_strategy"]);
// 创建动作策略
cJSON* actionJson = cJSON_GetObjectItemCaseSensitive(json, "action_strategy");
auto actionStrategy = actionStrategyFromJson(actionJson);
auto actionStrategy = actionStrategyFromJson(json["action_strategy"]);
// 创建宠物对象
return std::make_shared<PetBase>(info, stageStrategy, actionStrategy);
}
cJSON* PetDAO::stageStrategyToJson(const std::shared_ptr<PetStageStrategy>& strategy) {
if (!strategy) return nullptr;
cJSON* json = cJSON_CreateObject();
if (!json) return nullptr;
cppjson::Json PetDAO::stageStrategyToJson(const std::shared_ptr<PetStageStrategy>& strategy) {
if (!strategy) return {};
auto json = cppjson::Json::object();
// 添加当前阶段
cJSON_AddStringToObject(json, "current_stage",
stageTypeToString(strategy->getCurrentStageType()).c_str());
json.set("current_stage", cppjson::Json(stageTypeToString(strategy->getCurrentStageType())));
// 添加阶段模型映射
cJSON* modelMap = cJSON_CreateObject();
auto modelMap = cppjson::Json::object();
for (const auto& pair : strategy->getStageModelMap()) {
cJSON_AddStringToObject(modelMap,
stageTypeToString(pair.first).c_str(),
pair.second.c_str());
modelMap.set(stageTypeToString(pair.first), cppjson::Json(pair.second));
}
cJSON_AddItemToObject(json, "stage_model_map", modelMap);
json.set("stage_model_map", modelMap);
// 添加阶段音频映射
cJSON* audioMap = cJSON_CreateObject();
auto audioMap = cppjson::Json::object();
for (const auto& pair : strategy->getStageAudioMap()) {
cJSON_AddStringToObject(audioMap,
stageTypeToString(pair.first).c_str(),
pair.second.c_str());
audioMap.set(stageTypeToString(pair.first), cppjson::Json(pair.second));
}
cJSON_AddItemToObject(json, "stage_audio_map", audioMap);
json.set("stage_audio_map", audioMap);
return json;
}
std::shared_ptr<PetStageStrategy> PetDAO::stageStrategyFromJson(cJSON* json) {
if (!json) return nullptr;
std::shared_ptr<PetStageStrategy> PetDAO::stageStrategyFromJson(const cppjson::Json& json) {
if (json.isNull()) return nullptr;
auto strategy = std::make_shared<PetStageStrategy>();
// 获取当前阶段
cJSON* currentStageItem = cJSON_GetObjectItemCaseSensitive(json, "current_stage");
if (cJSON_IsString(currentStageItem)) {
strategy->current_stage = stringToStageType(currentStageItem->valuestring);
if (json["current_stage"].isString()) {
strategy->current_stage = stringToStageType(json["current_stage"].asString());
}
// 获取阶段模型映射
cJSON* modelMapItem = cJSON_GetObjectItemCaseSensitive(json, "stage_model_map");
if (cJSON_IsObject(modelMapItem)) {
cJSON* child = modelMapItem->child;
while (child) {
if (cJSON_IsString(child)) {
PetStageType stage = stringToStageType(child->string);
strategy->stage_model_map[stage] = child->valuestring;
auto modelMapJson = json["stage_model_map"];
if (modelMapJson.isObject()) {
for (const auto& item : modelMapJson.items()) {
if (item.second.isString()) {
PetStageType stage = stringToStageType(item.first);
strategy->stage_model_map[stage] = item.second.asString();
}
child = child->next;
}
}
// 获取阶段音频映射
cJSON* audioMapItem = cJSON_GetObjectItemCaseSensitive(json, "stage_audio_map");
if (cJSON_IsObject(audioMapItem)) {
cJSON* child = audioMapItem->child;
while (child) {
if (cJSON_IsString(child)) {
PetStageType stage = stringToStageType(child->string);
strategy->stage_audio_map[stage] = child->valuestring;
auto audioMapJson = json["stage_audio_map"];
if (audioMapJson.isObject()) {
for (const auto& item : audioMapJson.items()) {
if (item.second.isString()) {
PetStageType stage = stringToStageType(item.first);
strategy->stage_audio_map[stage] = item.second.asString();
}
child = child->next;
}
}
return strategy;
}
cJSON* PetDAO::actionStrategyToJson(const std::shared_ptr<PetActionStrategy>& strategy) {
if (!strategy) return nullptr;
cppjson::Json PetDAO::actionStrategyToJson(const std::shared_ptr<PetActionStrategy>& strategy) {
if (!strategy) return {};
cJSON* json = cJSON_CreateObject();
if (!json) return nullptr;
auto json = cppjson::Json::object();
// 添加当前动作
cJSON_AddStringToObject(json, "current_action",
actionTypeToString(strategy->getCurrentActionType()).c_str());
json.set("current_action", cppjson::Json(actionTypeToString(strategy->getCurrentActionType())));
// 添加动作模型映射
cJSON* modelMap = cJSON_CreateObject();
auto modelMap = cppjson::Json::object();
for (const auto& pair : strategy->getActionModelMap()) {
cJSON_AddStringToObject(modelMap,
actionTypeToString(pair.first).c_str(),
pair.second.c_str());
modelMap.set(actionTypeToString(pair.first), cppjson::Json(pair.second));
}
cJSON_AddItemToObject(json, "action_model_map", modelMap);
json.set("action_model_map", modelMap);
// 添加动作音频映射
cJSON* audioMap = cJSON_CreateObject();
auto audioMap = cppjson::Json::object();
for (const auto& pair : strategy->getActionAudioMap()) {
cJSON_AddStringToObject(audioMap,
actionTypeToString(pair.first).c_str(),
pair.second.c_str());
audioMap.set(actionTypeToString(pair.first), cppjson::Json(pair.second));
}
cJSON_AddItemToObject(json, "action_audio_map", audioMap);
json.set("action_audio_map", audioMap);
return json;
}
std::shared_ptr<PetActionStrategy> PetDAO::actionStrategyFromJson(cJSON* json) {
if (!json) return nullptr;
std::shared_ptr<PetActionStrategy> PetDAO::actionStrategyFromJson(const cppjson::Json& json) {
if (json.isNull()) return nullptr;
auto strategy = std::make_shared<PetActionStrategy>();
// 获取当前动作
cJSON* currentActionItem = cJSON_GetObjectItemCaseSensitive(json, "current_action");
if (cJSON_IsString(currentActionItem)) {
strategy->current_action = stringToActionType(currentActionItem->valuestring);
if (json["current_action"].isString()) {
strategy->current_action = stringToActionType(json["current_action"].asString());
}
// 获取动作模型映射
cJSON* modelMapItem = cJSON_GetObjectItemCaseSensitive(json, "action_model_map");
if (cJSON_IsObject(modelMapItem)) {
cJSON* child = modelMapItem->child;
while (child) {
if (cJSON_IsString(child)) {
PetActionType action = stringToActionType(child->string);
strategy->action_model_map[action] = child->valuestring;
auto modelMapJson = json["action_model_map"];
if (modelMapJson.isObject()) {
for (const auto& item : modelMapJson.items()) {
if (item.second.isString()) {
PetActionType action = stringToActionType(item.first);
strategy->action_model_map[action] = item.second.asString();
}
child = child->next;
}
}
// 获取动作音频映射
cJSON* audioMapItem = cJSON_GetObjectItemCaseSensitive(json, "action_audio_map");
if (cJSON_IsObject(audioMapItem)) {
cJSON* child = audioMapItem->child;
while (child) {
if (cJSON_IsString(child)) {
PetActionType action = stringToActionType(child->string);
strategy->action_audio_map[action] = child->valuestring;
auto audioMapJson = json["action_audio_map"];
if (audioMapJson.isObject()) {
for (const auto& item : audioMapJson.items()) {
if (item.second.isString()) {
PetActionType action = stringToActionType(item.first);
strategy->action_audio_map[action] = item.second.asString();
}
child = child->next;
}
}
+16 -17
View File
@@ -5,62 +5,61 @@
#include "PetBaseClass.h"
#include "SDFileManager.h"
#include "cJSON.h"
#include "cpp_json.h"
#include <string>
// 辅助函数:枚举类型与字符串的转换
namespace PetEnumConverter {
// PetStageType 转换
std::string stageTypeToString(PetStageType stage);
PetStageType stringToStageType(const std::string& str);
PetStageType stringToStageType(const std::string &str);
// PetActionType 转换
std::string actionTypeToString(PetActionType action);
PetActionType stringToActionType(const std::string& str);
PetActionType stringToActionType(const std::string &str);
}
// PetDAO 类 - 负责宠物的数据持久化
class PetDAO {
public:
// 构造函数,需要SDFileManager实例
explicit PetDAO(SDFileManager* fileManager);
explicit PetDAO(SDFileManager *fileManager);
// 保存宠物数据到文件
bool savePet(const std::shared_ptr<PetBase>& pet, const std::string& filename);
bool savePet(const std::shared_ptr<PetBase> &pet, const std::string &filename);
// 从文件加载宠物数据
std::shared_ptr<PetBase> loadPet(const std::string& filename);
std::shared_ptr<PetBase> loadPet(const std::string &filename);
// 获取所有保存的宠物文件列表
std::vector<std::string> listPetFiles();
// 删除宠物文件
bool deletePetFile(const std::string& filename);
bool deletePetFile(const std::string &filename);
private:
// 将宠物数据转换为JSON对象
cJSON* petToJson(const std::shared_ptr<PetBase>& pet);
cppjson::Json petToJson(const std::shared_ptr<PetBase> &pet); // 返回 cppjson::Json
// 从JSON对象创建宠物
std::shared_ptr<PetBase> petFromJson(cJSON* json);
std::shared_ptr<PetBase> petFromJson(const cppjson::Json &json); // 参数改为 cppjson::Json
// 将阶段策略转换为JSON对象
cJSON* stageStrategyToJson(const std::shared_ptr<PetStageStrategy>& strategy);
cppjson::Json stageStrategyToJson(const std::shared_ptr<PetStageStrategy> &strategy);
// 从JSON对象创建阶段策略
std::shared_ptr<PetStageStrategy> stageStrategyFromJson(cJSON* json);
std::shared_ptr<PetStageStrategy> stageStrategyFromJson(const cppjson::Json &json);
// 将动作策略转换为JSON对象
cJSON* actionStrategyToJson(const std::shared_ptr<PetActionStrategy>& strategy);
cppjson::Json actionStrategyToJson(const std::shared_ptr<PetActionStrategy> &strategy);
// 从JSON对象创建动作策略
std::shared_ptr<PetActionStrategy> actionStrategyFromJson(cJSON* json);
std::shared_ptr<PetActionStrategy> actionStrategyFromJson(const cppjson::Json &json);
// 文件管理器实例
SDFileManager* fileManager;
SDFileManager *fileManager;
// 宠物数据存储目录
static constexpr const char* PET_DATA_DIR = "/sdcard/pet_data";
static constexpr const char *PET_DATA_DIR = "/sdcard/pet_data";
};
/**
@@ -105,4 +104,4 @@ private:
}
}
}
*/
*/
+14 -11
View File
@@ -3,10 +3,13 @@
//
#pragma once
#include "PetInterface.h"
// 用于回调函数传递回调类型,以区分回调的是宠物动作还是宠物阶段
enum class PetType : uint8_t {Action, Stage};
// 宠物音频播放观察者类,继承自宠物观察者
class PetAudioStrategy : public PetObserver, public std::enable_shared_from_this<PetAudioStrategy> {
public:
using AudioCallback = std::function<void(const std::string&)>;
using AudioCallback = std::function<void(PetType petType, const std::string&)>;
/**
* 构造时候就将“事件→音频”两张表填好
* @param actionAudios 动作→音频
@@ -66,7 +69,7 @@ public:
if (!audio_callback) return;
auto it = action_audio.find(action);
if (it != action_audio.end()) {
audio_callback(it->second); // 播放对应音频
audio_callback(PetType::Action, it->second); // 播放对应音频
}
}
/**
@@ -79,7 +82,7 @@ public:
if (!audio_callback) return;
auto it = stage_audio.find(newStage); // 注意:播“新阶段”的音频
if (it != stage_audio.end()) {
audio_callback(it->second);
audio_callback(PetType::Stage, it->second);
}
}
private:
@@ -95,7 +98,7 @@ private:
// 渲染器观察者类,继承自PetObserver
class PetRendererStrategy : public PetObserver, public std::enable_shared_from_this<PetRendererStrategy> {
public:
using RenderCallback = std::function<void(const std::string&)>;
using RenderCallback = std::function<void(PetType petType, const std::string&)>;
/**
* 构造函数,可以传入动作到模型路径和阶段到模型路径的映射表
* @param actionModels 动作→模型路径映射
@@ -120,7 +123,7 @@ public:
}
~PetRendererStrategy() override {
// 自动取消注册
if (auto subject = pet_subject.lock()) {
if (const auto subject = pet_subject.lock()) {
subject->removeObserver(shared_from_this());
}
}
@@ -148,11 +151,11 @@ public:
* 宠物动作时触发[Observer接口实现]
* @param action 动作类型
*/
void onPetAction(PetActionType action) override {
void onPetAction(const PetActionType action) override {
if (!render_callback) return;
auto it = action_models.find(action);
const auto it = action_models.find(action);
if (it != action_models.end()) {
render_callback(it->second); // 渲染对应动作模型
render_callback(PetType::Action, it->second); // 渲染对应动作模型
}
}
/**
@@ -160,11 +163,11 @@ public:
* @param oldStage 旧阶段
* @param newStage 新阶段
*/
void onPetStageChange(PetStageType oldStage, PetStageType newStage) override {
void onPetStageChange(PetStageType oldStage, const PetStageType newStage) override {
if (!render_callback) return;
auto it = stage_models.find(newStage); // 注意:渲染"新阶段"的模型
const auto it = stage_models.find(newStage); // 注意:渲染"新阶段"的模型,实际上并没有使用到旧阶段,但还是保留,留一手
if (it != stage_models.end()) {
render_callback(it->second);
render_callback(PetType::Stage, it->second);
}
}
/**
@@ -1,7 +1,6 @@
//
// Created by misaki on 2025/9/9.
//
#include "AudioOutput.h"
#include "esp_log.h"
#include <memory>
@@ -81,8 +80,8 @@ bool AudioOutput::playSync(const char* directory, const char* fileName) {
return false;
}
void AudioOutput::playAsync(const char* directory, const char* fileName, AudioCallback callback) {
ThreadConfig config = getThreadConfig("play_async");
void AudioOutput::playAsync(const char* directory, const char* fileName, const AudioCallback& callback) {
const ThreadConfig config = getThreadConfig("play_async");
ThreadManager::createThread(config, [this, directory = std::string(directory),
fileName = std::string(fileName), callback]() {
@@ -90,9 +89,9 @@ void AudioOutput::playAsync(const char* directory, const char* fileName, AudioCa
}).detach();
}
void AudioOutput::playInternal(const char* directory, const char* fileName, AudioCallback callback) {
void AudioOutput::playInternal(const char* directory, const char* fileName, const AudioCallback& callback) {
bool success = false;
AudioState finalState = AudioState::ERROR;
auto finalState = AudioState::ERROR;
{
std::lock_guard<std::mutex> lock(stateMutex);
@@ -245,4 +244,122 @@ ThreadConfig AudioOutput::getThreadConfig(const char* operation) {
void AudioOutput::setState(AudioState newState) {
std::lock_guard<std::mutex> lock(stateMutex);
currentState = newState;
}
bool AudioOutput::playPcmFile(const char* filePath,
uint32_t sampleRate,
i2s_data_bit_width_t bits,
i2s_slot_mode_t ch)
{
// 简单文件尺寸获取
FILE* f = fopen(filePath, "rb");
if (!f) return false;
fseek(f, 0, SEEK_END);
const size_t bytes = ftell(f);
fclose(f);
playPcmCommon(filePath, bytes, true, sampleRate, bits, ch, nullptr);
return getState() == AudioState::PLAYING;
}
bool AudioOutput::playPcmStream(const uint8_t* pcmData,
size_t dataBytes,
uint32_t sampleRate,
i2s_data_bit_width_t bits,
i2s_slot_mode_t ch)
{
playPcmCommon(pcmData, dataBytes, false, sampleRate, bits, ch, nullptr);
return getState() == AudioState::PLAYING;
}
void AudioOutput::playPcmFileAsync(const char* filePath,
uint32_t sampleRate,
i2s_data_bit_width_t bits,
i2s_slot_mode_t ch,
const AudioCallback& cb)
{
ThreadConfig cfg = getThreadConfig("pcm_file");
std::thread([=](){
playPcmCommon(filePath, 0, true, sampleRate, bits, ch, cb);
}).detach();
}
void AudioOutput::playPcmStreamAsync(const uint8_t* pcmData,
size_t dataBytes,
uint32_t sampleRate,
i2s_data_bit_width_t bits,
i2s_slot_mode_t ch,
const AudioCallback& cb)
{
ThreadConfig cfg = getThreadConfig("pcm_stream");
std::thread([=](){
playPcmCommon(pcmData, dataBytes, false, sampleRate, bits, ch, cb);
}).detach();
}
void AudioOutput::playPcmCommon(const void* source,
size_t bytes,
bool isFile,
uint32_t sampleRate,
i2s_data_bit_width_t bits,
i2s_slot_mode_t ch,
const AudioCallback& cb)
{
// 停止旧播放
stop();
// 重新配置 I2S 时钟/位宽/声道
bsp_i2s_reconfig_clk(sampleRate, bits, ch);
// 打开“文件”或“内存”数据源
FILE* f = nullptr;
const uint8_t* mem = nullptr;
size_t memLeft = 0;
if (isFile) {
f = fopen(static_cast<const char *>(source), "rb");
if (!f) {
if (cb) cb(AudioState::ERROR, static_cast<const char *>(source));
return;
}
} else {
mem = static_cast<const uint8_t *>(source);
memLeft = bytes;
}
// 状态置为 PLAYING
{
std::lock_guard<std::mutex> lk(stateMutex);
currentState = AudioState::PLAYING;
currentFilePath = isFile ? static_cast<const char *>(source) : "<stream>";
}
if (cb) cb(AudioState::PLAYING, currentFilePath.c_str());
// 循环送 PCM 数据到 I2S
constexpr size_t CHUNK = 512; // 任意 2 的幂
int16_t buf[CHUNK];
size_t bw;
while (true) {
size_t rd = 0;
if (isFile) {
rd = fread(buf, 1, sizeof(buf), f);
} else {
rd = memLeft > sizeof(buf) ? sizeof(buf) : memLeft;
memcpy(buf, mem, rd);
mem += rd;
memLeft -= rd;
}
if (rd == 0) break;
// 音量实时缩放(复用已有逻辑)
const float vf = currentVolume / 100.0f;
for (size_t i = 0; i < rd / 2; ++i) buf[i] = static_cast<int16_t>(buf[i] * vf);
// 写 I2S
i2s_channel_write(i2s_tx_chan, buf, rd, &bw, portMAX_DELAY);
}
// 播放结束
if (f) fclose(f);
{
std::lock_guard<std::mutex> lk(stateMutex);
currentState = AudioState::STOPPED;
}
if (cb) cb(AudioState::STOPPED, currentFilePath.c_str());
}
@@ -1,14 +1,12 @@
//
// Created by misaki on 2025/9/9.
//
#pragma once
#include <mutex>
#include <functional>
#include <string>
#include <hal/i2s_types.h>
#include "ThreadManager.h"
#include "SDFileManager.h"
@@ -88,7 +86,7 @@ public:
* @param fileName 文件名
* @param callback 回调函数
*/
void playAsync(const char* directory, const char* fileName, AudioCallback callback = nullptr);
void playAsync(const char* directory, const char* fileName, const AudioCallback& callback = nullptr);
/**
* 暂停播放
@@ -175,6 +173,58 @@ public:
*/
bool isFinished() const;
/**
* 播放 PCM 文件(阻塞)
* @param filePath PCM 文件路径
* @param sampleRate 采样率
* @param bits 数据位宽
* @param ch 插槽模式
* @return 是否成功
*/
bool playPcmFile(const char* filePath,
uint32_t sampleRate = 16000,
i2s_data_bit_width_t bits = I2S_DATA_BIT_WIDTH_16BIT,
i2s_slot_mode_t ch = I2S_SLOT_MODE_MONO);
// 异步播放 PCM 文件
void playPcmFileAsync(const char* filePath,
uint32_t sampleRate = 16000,
i2s_data_bit_width_t bits = I2S_DATA_BIT_WIDTH_16BIT,
i2s_slot_mode_t ch = I2S_SLOT_MODE_MONO,
const AudioCallback& cb = nullptr);
/**
* 播放内存 PCM 流(阻塞)
* @param pcmData PCM 数据
* @param dataBytes 数据字节数
* @param sampleRate 采样率
* @param bits 数据位宽
* @param ch 插槽模式
* @return 是否成功
*/
bool playPcmStream(const uint8_t* pcmData,
size_t dataBytes,
uint32_t sampleRate = 16000,
i2s_data_bit_width_t bits = I2S_DATA_BIT_WIDTH_16BIT,
i2s_slot_mode_t ch = I2S_SLOT_MODE_MONO);
// 异步播放 PCM 流
void playPcmStreamAsync(const uint8_t* pcmData,
size_t dataBytes,
uint32_t sampleRate = 16000,
i2s_data_bit_width_t bits = I2S_DATA_BIT_WIDTH_16BIT,
i2s_slot_mode_t ch = I2S_SLOT_MODE_MONO,
const AudioCallback& cb = nullptr);
private:
// 通用 PCM 播放实现
void playPcmCommon(const void* source,
size_t bytes,
bool isFile,
uint32_t sampleRate,
i2s_data_bit_width_t bits,
i2s_slot_mode_t ch,
const AudioCallback& cb);
private:
// 私有构造函数
AudioOutput();
@@ -184,7 +234,7 @@ private:
ThreadConfig getThreadConfig(const char* operation);
// 内部播放实现
void playInternal(const char* directory, const char* fileName, AudioCallback callback);
void playInternal(const char* directory, const char* fileName, const AudioCallback& callback);
// 状态转换辅助方法
void setState(AudioState newState);
+152 -17
View File
@@ -32,14 +32,15 @@
std::cout << "\n";\n
*/
// cpp_json.hpp
// cpp_json.h
#pragma once
#include <cJSON.h>
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <stdexcept>
#include <utility>
namespace cppjson {
@@ -152,42 +153,176 @@ public:
cJSON_AddItemToArray(ptr_, cJSON_Duplicate(v.ptr_, 1));
return *this;
}
// 便捷的 append 方法重载
Json& append(int value) {
return append(Json(value));
}
Json& append(double value) {
return append(Json(value));
}
Json& append(bool value) {
return append(Json(value));
}
Json& append(const char* value) {
return append(Json(value));
}
Json& append(const std::string& value) {
return append(Json(value));
}
Json& set(const std::string& key, const Json& v) {
if (!isObject()) throw std::runtime_error("not object");
cJSON_AddItemToObject(ptr_, key.c_str(), cJSON_Duplicate(v.ptr_, 1));
return *this;
}
// 便捷的 set 方法重载
Json& set(const std::string& key, int value) {
return set(key, Json(value));
}
Json& set(const std::string& key, double value) {
return set(key, Json(value));
}
Json& set(const std::string& key, bool value) {
return set(key, Json(value));
}
Json& set(const std::string& key, const char* value) {
return set(key, Json(value));
}
Json& set(const std::string& key, const std::string& value) {
return set(key, Json(value));
}
// 迭代器(只读)
// 获取对象的所有键
[[nodiscard]] std::vector<std::string> keys() const {
if (!isObject()) throw std::runtime_error("not object");
std::vector<std::string> result;
cJSON* child = ptr_->child;
while (child) {
if (child->string) {
result.emplace_back(child->string);
}
child = child->next;
}
return result;
}
// 数组迭代器(只读)
template <bool IsConst>
struct iterator_impl {
struct array_iterator_impl {
using iterator_category = std::forward_iterator_tag;
using value_type = Json;
using difference_type = std::ptrdiff_t;
using pointer = typename std::conditional<IsConst, const Json, Json>::type*;
using reference = typename std::conditional<IsConst, const Json, Json>::type&;
iterator_impl(cJSON* h, cJSON* c) : head_(h), cur_(c) {}
array_iterator_impl(cJSON* head, cJSON* c) : head_(head), cur_(c) {}
reference operator*() {
tmp = std::make_unique<Json>(cur_, false);
return *tmp;
}
pointer operator->() { return &(operator*()); }
iterator_impl& operator++() { cur_ = cur_ ? cur_->next : nullptr; return *this; }
friend bool operator==(const iterator_impl& a, const iterator_impl& b) { return a.cur_ == b.cur_; }
friend bool operator!=(const iterator_impl& a, const iterator_impl& b) { return !(a == b); }
array_iterator_impl& operator++() { cur_ = cur_ ? cur_->next : nullptr; return *this; }
friend bool operator==(const array_iterator_impl& a, const array_iterator_impl& b) { return a.cur_ == b.cur_; }
friend bool operator!=(const array_iterator_impl& a, const array_iterator_impl& b) { return !(a == b); }
private:
cJSON *head_, *cur_;
std::unique_ptr<Json> tmp; // 改为智能指针
std::unique_ptr<Json> tmp;
};
using iterator = iterator_impl<false>;
using const_iterator = iterator_impl<true>;
iterator begin() { return iterator(ptr_, ptr_ ? ptr_->child : nullptr); }
iterator end() { return iterator(ptr_, nullptr); }
[[nodiscard]] const_iterator begin() const { return cbegin(); }
[[nodiscard]] const_iterator end() const { return cend(); }
[[nodiscard]] const_iterator cbegin() const { return const_iterator(ptr_, ptr_ ? ptr_->child : nullptr); }
[[nodiscard]] const_iterator cend() const { return const_iterator(ptr_, nullptr); }
using array_iterator = array_iterator_impl<false>;
using const_array_iterator = array_iterator_impl<true>;
// 对象键值对迭代器
template <bool IsConst>
struct object_iterator_impl {
using iterator_category = std::forward_iterator_tag;
using value_type = std::pair<std::string, Json>;
using difference_type = std::ptrdiff_t;
using pointer = typename std::conditional<IsConst, const value_type, value_type>::type*;
using reference = typename std::conditional<IsConst, const value_type, value_type>::type&;
object_iterator_impl(cJSON* c) : cur_(c) {
if (cur_ && cur_->string) {
updateValue();
}
}
reference operator*() {
tmp = std::make_unique<value_type>(cur_->string ? cur_->string : "", Json(cur_, false));
return *tmp;
}
pointer operator->() { return &(operator*()); }
object_iterator_impl& operator++() {
cur_ = cur_ ? cur_->next : nullptr;
if (cur_) {
updateValue();
}
return *this;
}
friend bool operator==(const object_iterator_impl& a, const object_iterator_impl& b) { return a.cur_ == b.cur_; }
friend bool operator!=(const object_iterator_impl& a, const object_iterator_impl& b) { return !(a == b); }
private:
void updateValue() {
if (cur_ && cur_->string) {
current_key = cur_->string;
}
}
cJSON* cur_ = nullptr;
std::string current_key;
std::unique_ptr<value_type> tmp;
};
using object_iterator = object_iterator_impl<false>;
using const_object_iterator = object_iterator_impl<true>;
// 统一的迭代器接口(用于数组)
array_iterator begin() {
if (!isArray()) throw std::runtime_error("not array");
return {ptr_, ptr_ ? ptr_->child : nullptr};
}
array_iterator end() {
if (!isArray()) throw std::runtime_error("not array");
return {ptr_, nullptr};
}
[[nodiscard]] const_array_iterator begin() const { return cbegin(); }
[[nodiscard]] const_array_iterator end() const { return cend(); }
[[nodiscard]] const_array_iterator cbegin() const {
if (!isArray()) throw std::runtime_error("not array");
return {ptr_, ptr_ ? ptr_->child : nullptr};
}
[[nodiscard]] const_array_iterator cend() const {
if (!isArray()) throw std::runtime_error("not array");
return {ptr_, nullptr};
}
// 对象项迭代器
object_iterator begin_object() {
if (!isObject()) throw std::runtime_error("not object");
return {ptr_ ? ptr_->child : nullptr};
}
object_iterator end_object() {
if (!isObject()) throw std::runtime_error("not object");
return {nullptr};
}
[[nodiscard]] const_object_iterator begin_object() const { return cbegin_object(); }
[[nodiscard]] const_object_iterator end_object() const { return cend_object(); }
[[nodiscard]] const_object_iterator cbegin_object() const {
if (!isObject()) throw std::runtime_error("not object");
return {ptr_ ? ptr_->child : nullptr};
}
[[nodiscard]] const_object_iterator cend_object() const {
if (!isObject()) throw std::runtime_error("not object");
return {nullptr};
}
// 便利的 items() 方法,用于结构化绑定
class ItemsProxy {
public:
explicit ItemsProxy(Json* json) : json_(json) {}
object_iterator begin() { return json_->begin_object(); }
object_iterator end() { return json_->end_object(); }
[[nodiscard]] const_object_iterator begin() const { return json_->cbegin_object(); }
[[nodiscard]] const_object_iterator end() const { return json_->cend_object(); }
private:
Json* json_;
};
ItemsProxy items() { return ItemsProxy(this); }
[[nodiscard]] ItemsProxy items() const { return ItemsProxy(const_cast<Json*>(this)); }
/*-------- 工具 ------------------------------------------------*/
void swap(Json& rhs) noexcept { std::swap(ptr_, rhs.ptr_); std::swap(owner_, rhs.owner_); }
@@ -45,6 +45,8 @@ LVGLRender::LVGLRender() {
I2C_Init();
LCD_Init();
LVGL_Init();
// std::this_thread::sleep_for(std::chrono::milliseconds(2000)); // 延时2秒 确保所有 LVGL 对象已创建完成
ESP_LOGI("LVGL_Render", "LVGL_Render构造函数...初始化媒体驱动成功...");
ESP_LOGI("LVGL_Render", "LVGL_Render构造函数...创建LVGL心跳...");
@@ -53,7 +55,7 @@ LVGLRender::LVGLRender() {
trickConfig.core_id = 1; // 渲染分配给核0
trickConfig.name = "LVGL_Render";
trickConfig.priority = 5; //
trickConfig.stack_size = 4096; // 给LVGL一个较大的堆栈,避免栈溢出
trickConfig.stack_size = 8192; // 给LVGL一个较大的堆栈,避免栈溢出
std::thread tick_thread = ThreadManager::createMemberThread(trickConfig, this, &LVGLRender::LVGL_Update);
@@ -74,96 +76,7 @@ uint16_t LVGLRender::getFps() {
return fps;
}
void LVGLRender::tryToInitRenderGif() {
ESP_LOGI("LVGL_Render", "尝试初始化 LVGL 底层驱动...");
}
void LVGLRender::log() {
ESP_LOGI("LVGL_Render", "LVGL_Render log...");
}
#include "SDFileManager.h"
std::vector<uint8_t> LVGLRender::readWholeFile(const std::string& path)
{
ESP_LOGI("LVGLRender", "开始读取文件: %s", path.c_str());
// 直接用 SDFileManager 同步读整个文件 TODO: 考虑修改为异步读
std::string content = SDFileManager::getInstance()->readFileSync(path.c_str());
if (content.empty()) {
ESP_LOGE("LVGLRender", "readFileSync 失败或文件为空");
return {};
}
// string -> vector,零拷贝 move
return {content.begin(), content.end()};
}
bool LVGLRender::getGifWH(const uint8_t* raw, uint32_t& w, uint32_t& h)
{
if (!raw || memcmp(raw, "GIF", 3) != 0) {
ESP_LOGE("LVGLRender", "不是合法 GIF 文件头");
return false;
}
// GIF87a/89a 宽高偏移 6~9 字节,小端
w = raw[6] | (raw[7] << 8);
h = raw[8] | (raw[9] << 8);
ESP_LOGI("LVGLRender", "GIF 尺寸: %lu x %lu", w, h);
return true;
}
void LVGLRender::renderGifInternal(const std::vector<uint8_t>& data,
uint32_t w, uint32_t h)
{
// 删除旧对象
if (current_gif_obj != nullptr) {
lv_obj_del(current_gif_obj);
current_gif_obj = nullptr;
}
// 保存数据,防止被释放
current_gif_data = data;
// 构造新的描述符(不要 static)
lv_img_dsc_t gif_desc = {};
gif_desc.header.cf = LV_IMG_CF_RAW_CHROMA_KEYED;
gif_desc.header.always_zero = 0;
gif_desc.header.reserved = 0;
gif_desc.header.w = static_cast<lv_coord_t>(w);
gif_desc.header.h = static_cast<lv_coord_t>(h);
gif_desc.data_size = current_gif_data.size();
gif_desc.data = current_gif_data.data();
// 创建新的 GIF 对象
current_gif_obj = lv_gif_create(lv_scr_act()); // copy到当前gif对象
lv_gif_set_src(current_gif_obj, &gif_desc); // 设置源
lv_obj_center(current_gif_obj); // 居中
ESP_LOGI("LVGLRender", "GIF 已渲染并循环播放");
}
void LVGLRender::RenderGif(const std::string &filename) {
if (filename == last_gif_filename) {
ESP_LOGW("LVGLRender", "重复加载同一 GIF,忽略");
return;
}
last_gif_filename = filename;
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), 0); // 背景黑色
lv_obj_set_style_bg_opa(lv_scr_act(), LV_OPA_COVER, 0); // 透明度
std::string fullPath = ToolsClass::makeFullPath(filename);
std::vector<uint8_t> gifBin = readWholeFile(fullPath);
if (gifBin.empty()) return;
uint32_t w = 0, h = 0;
if (!getGifWH(gifBin.data(), w, h)) return;
renderGifInternal(gifBin, w, h);
}
@@ -4,7 +4,7 @@
/**
* 本类为单例类,用于实现LVGL的渲染
* 封装了一整套的LVGL渲染流
* 同时兼顾了底层的显示驱动
* 同时兼顾了底层的显示驱动初始化
*/
#pragma once
@@ -23,33 +23,12 @@ public:
public:
static LVGLRender* getInstance();
/**
* 全屏渲染gif动画
* @brief 渲染GIF文件
* @param filename GIF文件路径
*/
void RenderGif(const std::string &filename);
static void setFps(uint16_t fps_);
static uint16_t getFps();
void tryToInitRenderGif();
void log();
// gif渲染
private:
/* 同步读整个文件到 vector */
std::vector<uint8_t> readWholeFile(const std::string& path);
/* 从原始数据解析 GIF 宽高 */
bool getGifWH(const uint8_t* raw, uint32_t& w, uint32_t& h);
/* 真正的渲染实现(空壳,先打印日志) */
void renderGifInternal(const std::vector<uint8_t>& data,
uint32_t w, uint32_t h);
private:
explicit LVGLRender(); // 构造函数私有化
~LVGLRender();
@@ -60,10 +39,6 @@ private:
static std::mutex instance_mutex; /// 单例锁
static uint16_t fps; /// 帧率
lv_obj_t* current_gif_obj = nullptr; /// 当前GIF对象
std::vector<uint8_t> current_gif_data; /// 当前GIF数据
std::string last_gif_filename; /// 最后一次渲染的GIF文件名
std::mutex mtx;
};
+505 -45
View File
@@ -2,18 +2,17 @@
// Created by misaki on 2025/9/26.
//
#pragma once
#include <atomic>
#include <esp_heap_caps.h>
#include <esp_log.h>
#include <lvgl.h>
#include <font/lv_font.h>
#include <functional>
#include <optional>
#include <utility>
#include "SDFileManager.h"
#include "ToolsClass.h"
LV_FONT_DECLARE(SiYuanHeiTiGoogleBan); // 思源黑体 Google版
namespace lvgl_cpp {
// 前向声明
class Obj;
class Screen;
@@ -28,13 +27,18 @@ class List;
class TextArea;
class Image;
class IconButton;
// 基础封装
class Obj {
public:
Obj() = default;
explicit Obj(lv_obj_t* raw) : ptr_(raw) {}
virtual ~Obj() { if (ptr_) lv_obj_del(ptr_); }
virtual ~Obj() {
if (ptr_ && lv_obj_is_valid(ptr_)) {
// 先移除所有事件回调
lv_obj_remove_event_cb_with_user_data(ptr_, event_trampoline, nullptr);
lv_obj_del(ptr_);
}
}
Obj(Obj&& o) noexcept : ptr_(std::exchange(o.ptr_, nullptr)) {}
Obj& operator=(Obj&& o) noexcept {
@@ -48,9 +52,9 @@ public:
void reset() { if (ptr_) { lv_obj_del(ptr_); ptr_ = nullptr; } }
// 通用链式
Obj& size(const lv_coord_t w, const lv_coord_t h) { lv_obj_set_size(ptr_, w, h); return *this; }
Obj& pos(const lv_coord_t x, const lv_coord_t y) { lv_obj_set_pos(ptr_, x, y); return *this; }
Obj& center() { lv_obj_center(ptr_); return *this; }
virtual Obj& size(const lv_coord_t w, const lv_coord_t h) { lv_obj_set_size(ptr_, w, h); return *this; }
virtual Obj& pos(const lv_coord_t x, const lv_coord_t y) { lv_obj_set_pos(ptr_, x, y); return *this; }
virtual Obj& center() { lv_obj_center(ptr_); return *this; }
Obj& align(const lv_align_t align, const lv_obj_t* base = nullptr, const lv_coord_t x = 0, const lv_coord_t y = 0) {
if (base) { // 如果有 base
lv_obj_align_to(ptr_, base, align, x, y);
@@ -70,6 +74,10 @@ public:
Obj& on(const lv_event_code_t code, EventCb cb) {
auto* ctx = new EventCb(std::move(cb));
lv_obj_add_event_cb(ptr_, event_trampoline, code, ctx);
// 保存回调上下文以便后续清理
std::lock_guard<std::mutex> lock(event_mutex_);
event_contexts_.push_back(ctx);
return *this;
}
protected: // 改为 protected 以允许派生类访问
@@ -77,8 +85,16 @@ protected: // 改为 protected 以允许派生类访问
private:
static void event_trampoline(lv_event_t* e) {
const auto* ctx = static_cast<EventCb*>(lv_event_get_user_data(e));
lv_obj_t* obj = lv_event_get_target(e); // 获取事件对象
// 安全检查:确保对象仍然有效
if (!obj || !lv_obj_is_valid(obj) || !ctx) {
return;
}
(*ctx)(e);
}
std::vector<EventCb*> event_contexts_;
std::mutex event_mutex_;
};
// 样式构造器
@@ -333,7 +349,7 @@ private:
}
};
// Toast 消息泡泡
// Toast 消息泡泡 TODO: 有严重空指针异常问题,需要fix
class Toast {
public:
enum class Type : uint8_t { INFO, WARN, ERROR };
@@ -539,8 +555,8 @@ private:
grad.stops[0].frac = 0;
grad.stops[1].color = mainColor_;
grad.stops[1].frac = 128;
grad.stops[2].color = lv_color_darken(mainColor_, LV_OPA_30);
grad.stops[2].frac = 255;
// grad.stops[2].color = lv_color_darken(mainColor_, LV_OPA_30);
// grad.stops[2].frac = 255;
lv_obj_set_style_bg_grad(fill_, &grad, 0);
}
@@ -587,11 +603,154 @@ private:
char buf_[64] = {0};
};
class LongPressButton : public Obj {
public:
explicit LongPressButton(const Obj& parent)
: Obj(lv_btn_create(parent.raw()))
{
// 基础事件
on(LV_EVENT_PRESSED, [this](lv_event_t*){ onPress(); });
on(LV_EVENT_RELEASED, [this](lv_event_t*){ onRelease(); });
on(LV_EVENT_PRESS_LOST,[this](lv_event_t*){ onRelease(); });
}
// 链式外观
LongPressButton& size(const lv_coord_t w, const lv_coord_t h)
{ lv_obj_set_size(raw(), w, h); return *this; }
// 短按回调(主线程)
LongPressButton& onShort(std::function<void()> cb)
{ short_cb_ = std::move(cb); return *this; }
// 长按回调(工作线程循环,参数为停止标志)
LongPressButton& onLong(std::function<void(std::atomic<bool>&)> cb)
{ long_cb_ = std::move(cb); return *this; }
// 设置判定长按的超时时间,默认 400 ms
LongPressButton& longPressTimeout(const uint32_t ms)
{ long_timeout_ms_ = ms; return *this; }
~LongPressButton() override
{
stopThread();
}
private:
// 按下
void onPress()
{
pressed_ = true;
stop_flag_ = false;
// 启动“长按判定定时器”
long_timer_ = lv_timer_create([](lv_timer_t* t){
auto* self = static_cast<LongPressButton*>(t->user_data);
self->onLongTimeout();
}, long_timeout_ms_, this);
lv_timer_set_repeat_count(long_timer_, 1); // 一次性
}
// 释放
void onRelease()
{
if (!pressed_) return;
pressed_ = false;
if (long_timer_) { // 还在跑 → 短按
lv_timer_del(long_timer_);
long_timer_ = nullptr;
if (short_cb_) short_cb_();
}
else { // 已进入长按模式
stopThread(); // 请求停止 + join
}
}
// 长按超时 → 启动工作线程
void onLongTimeout()
{
long_timer_ = nullptr; // 定时器自毁
if (!long_cb_) return;
// 启动工作线程
stop_flag_ = false;
thread_ = ThreadManager::createThread(
ThreadConfig{
.name = "lpbtn_worker",
.core_id = 1, // 可改
.stack_size = 4096,
.priority = 5
},
&LongPressButton::workerEntry, this);
}
// 工作线程入口
static void workerEntry(LongPressButton* self)
{
self->long_cb_(self->stop_flag_);
}
// 请求停止并等待线程结束
void stopThread()
{
if (thread_.joinable()) {
stop_flag_ = true;
thread_.join();
}
}
std::function<void()> short_cb_;
std::function<void(std::atomic<bool>&)> long_cb_;
uint32_t long_timeout_ms_ = 300; /// 默认 300 ms
lv_timer_t* long_timer_ = nullptr;
std::atomic<bool> pressed_{false};
std::atomic<bool> stop_flag_{false};
std::thread thread_;
};
// GIF 显示控件
class Gif final : public Obj {
public:
explicit Gif(const Obj& parent) : Obj(lv_gif_create(parent.raw())) {}
~Gif() override {
// drop();
if (raw() && lv_obj_is_valid(raw()))
lv_gif_set_src(raw(), nullptr);
}
// 仅把 lv_obj 从树上摘下来,但不 delete 任何数据
void detach() {
if (raw() && lv_obj_is_valid(raw())) {
lv_obj_remove_style_all(raw()); // 清掉所有样式,防止刷新
lv_obj_clear_flag(raw(), LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK);
lv_obj_move_foreground(raw()); // 移到最前,避免树遍历卡住
lv_obj_del_async(raw()); // 让 LVGL 在下一轮把 obj 删掉
ptr_ = nullptr; // 把基类保存的指针清零,防止再访问
}
}
void stopTimer() {
if (raw() && lv_obj_is_valid(raw())) {
lv_gif_set_src(raw(), nullptr); // 再清解码器
}
}
// 异步释放 GIF 资源
void drop_async() {
if (!dsc_) return;
// 先让 LVGL 关闭解码器(需要 dsc_ 有效)
if (raw() && lv_obj_is_valid(raw()))
lv_gif_set_src(raw(), nullptr);
// 把 dsc_ 移出来(裸指针)
auto* keep = dsc_.release();
// 脱钩 obj
detach();
// 异步释放“纯数据”
lv_async_call([](void* p) {
auto* raw_dsc = static_cast<lv_img_dsc_t*>(p);
if (raw_dsc) {
if (raw_dsc->data) heap_caps_free(const_cast<uint8_t*>(raw_dsc->data));
delete raw_dsc;
}
}, keep);
}
// 主动释放解码缓冲区(必须在对象还活着时调用)
void drop() {
if (raw() && lv_obj_is_valid(raw())) {
lv_gif_set_src(raw(), nullptr); // 停定时器 gd_close_gif()
}
// 把内部指针清零,防止重复关闭
if (dsc_) {
dsc_.reset(); // 释放 dsc_ + PSRAM
}
}
bool getGifWH(const uint8_t* raw, uint32_t& w, uint32_t& h)
{
if (!raw || memcmp(raw, "GIF", 3) != 0) {
@@ -607,8 +766,12 @@ public:
// 从 SD 卡加载 GIF 文件(完整路径)
Gif& src(const char* full_path) {
if (raw() && lv_obj_is_valid(raw())) {
lv_gif_set_src(raw(), nullptr); // 停止旧解码器
}
// 读整个文件到 PSRAM
std::string content = SDFileManager::getInstance()->readFileSync(ToolsClass::makeFullPath(full_path));
const std::string content = SDFileManager::getInstance()->readFileSync(ToolsClass::makeFullPath(full_path));
if (content.empty()) {
ESP_LOGE("Gif", "read %s fail", full_path);
return *this;
@@ -631,7 +794,7 @@ public:
// 构造一次性描述符(跟随 Gif 对象生命周期)
dsc_ = std::unique_ptr<lv_img_dsc_t, DscDeleter>(new lv_img_dsc_t{});
dsc_->header.cf = LV_IMG_CF_RAW_CHROMA_KEYED;
dsc_->header.cf = LV_IMG_CF_RAW_CHROMA_KEYED/*LV_IMG_CF_TRUE_COLOR_ALPHA*/;
dsc_->header.always_zero = 0;
dsc_->header.reserved = 0;
dsc_->header.w = static_cast<lv_coord_t>(w);
@@ -641,6 +804,9 @@ public:
// 交给 LVGL
lv_gif_set_src(raw(), dsc_.get());
lv_obj_clear_flag(raw(), LV_OBJ_FLAG_SCROLLABLE); // 禁止滚动
lv_obj_set_scroll_dir(raw(), LV_DIR_NONE);
return *this;
}
@@ -659,47 +825,275 @@ private:
std::unique_ptr<lv_img_dsc_t, DscDeleter> dsc_;
};
// GIF 播放控件
class GifPlayer : public Obj {
public:
explicit GifPlayer(const Obj& parent) : Obj(lv_obj_create(parent.raw())) {
lv_obj_set_size(raw(), LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_clear_flag(raw(), LV_OBJ_FLAG_SCROLLABLE);
lv_obj_center(raw());
}
~GifPlayer() override { stop(); }
// 设置/切换轮播图 TODO: 切换轮播图的时候存在定时器空指针重复释放问题
GifPlayer& loop(const char* path, const uint32_t duration = 5000) {
loop_path_ = path ? path : "";
loop_duration_ = duration;
if (!in_burst_) show_loop();
return *this;
}
// 插播一张图;播完自动回到轮播
GifPlayer& burst(const char* path, const uint32_t duration = 5000) {
if (!path || !*path) return *this;
in_burst_ = true;
show_burst(path); // 创建并显示突发图
burst_timer_ = lv_timer_create(
[](lv_timer_t* t){
auto* self = static_cast<GifPlayer*>(t->user_data);
self->in_burst_ = false;
if (self->burst_gif_) self->burst_gif_->drop_async();
self->burst_gif_->drop_async(); // 内部已把 obj 和数据都处理完
self->burst_gif_.reset(); // 只把 unique_ptr 置空,不再访问 obj
if (!self->loop_path_.empty()) self->show_loop();
lv_timer_del(t);
self->burst_timer_ = nullptr;
}, duration, this);
return *this;
}
// 停止并释放所有资源
void stop() {
if (burst_timer_) {
lv_timer_del(burst_timer_);
burst_timer_ = nullptr;
}
burst_gif_.reset();
loop_gif_.reset();
in_burst_ = false;
}
private:
void show_loop() {
if (burst_gif_) lv_obj_add_flag(burst_gif_->raw(), LV_OBJ_FLAG_HIDDEN);
if (!loop_gif_) {
loop_gif_ = std::make_unique<Gif>(*this);
(void)loop_gif_->raw();
}
lv_obj_clear_flag(loop_gif_->raw(), LV_OBJ_FLAG_HIDDEN);
loop_gif_->src(loop_path_.c_str());
}
void show_burst(const char* path) {
if (!burst_gif_) {
burst_gif_ = std::make_unique<Gif>(*this);
(void)burst_gif_->raw();
}
lv_obj_clear_flag(burst_gif_->raw(), LV_OBJ_FLAG_HIDDEN);
if (loop_gif_) lv_obj_add_flag(loop_gif_->raw(), LV_OBJ_FLAG_HIDDEN);
burst_gif_->src(path);
}
bool in_burst_ = false;
std::string loop_path_;
uint32_t loop_duration_ = 5000;
lv_timer_t* burst_timer_ = nullptr;
std::unique_ptr<Gif> loop_gif_;
std::unique_ptr<Gif> burst_gif_;
};
// 纯文字透明浮层
class TextOverlay : public Obj {
public:
explicit TextOverlay(const Obj& parent)
: Obj(lv_label_create(parent.raw()))
{
// 初始化为透明背景
lv_obj_set_style_bg_opa(raw(), LV_OPA_TRANSP, 0);
lv_obj_set_style_pad_all(raw(), 0, 0); // 去掉内边距,真正的“裸文字”
lv_obj_clear_flag(raw(), LV_OBJ_FLAG_SCROLLABLE); // 不需要滚动
lv_label_set_long_mode(raw(), LV_LABEL_LONG_WRAP); // 自动换行
}
// 文字内容
TextOverlay& text(const char* txt) {
lv_label_set_text(raw(), txt);
return *this;
}
TextOverlay& text_fmt(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
// 先用栈缓冲格式化,再交给 LVGL
char buf[128];
vsnprintf(buf, sizeof(buf), fmt, args);
lv_label_set_text(raw(), buf);
va_end(args);
return *this;
}
// 文字颜色,默认白色
TextOverlay& textColor(const lv_color_t c) {
lv_obj_set_style_text_color(raw(), c, 0);
return *this;
}
// 字体,默认 &SiYuanHeiTiGoogleBan
TextOverlay& font(const lv_font_t* fnt) {
lv_obj_set_style_text_font(raw(), fnt, 0);
return *this;
}
// 对齐方式:LEFT / CENTER / RIGHT
TextOverlay& alignText(const lv_text_align_t align) {
lv_obj_set_style_text_align(raw(), align, 0);
return *this;
}
// 快速定位(沿用 Obj 的 align 链式)
TextOverlay& place(const lv_align_t align,
const lv_obj_t* base = nullptr,
const lv_coord_t x = 0,
const lv_coord_t y = 0)
{
this->align(align, base, x, y);
return *this;
}
// 是否让文字区域可点击(默认不可点击)
TextOverlay& clickable(const bool en = true) {
if (en) lv_obj_add_flag(raw(), LV_OBJ_FLAG_CLICKABLE);
else lv_obj_clear_flag(raw(), LV_OBJ_FLAG_CLICKABLE);
return *this;
}
};
// 子应用抽象
class BaseApp : public Obj {
public:
explicit BaseApp(const Obj& parent) : Obj(lv_obj_create(parent.raw())), btn_exit_(parent) {
explicit BaseApp(const Obj& parent) : Obj(lv_obj_create(parent.raw())) {
lv_obj_set_size(raw(), 360, 360);
// 退出按钮
btn_exit_.size(40, 40)
.align(LV_ALIGN_CENTER, nullptr, 0, -130) // 居中
.on(LV_EVENT_CLICKED, [this](lv_event_t *) { this->exit(); });
label_.align(LV_ALIGN_CENTER, nullptr, 0, 0);
label_.text(LV_SYMBOL_CLOSE);
// 创建退出按钮
btn_exit_ = std::make_unique<Button>(*this);
label_ = std::make_unique<Label>(*btn_exit_);
// 设置按钮位置和样式
btn_exit_->size(40, 40)
.align(LV_ALIGN_CENTER, nullptr, 0, -100)
.add_style(&getExitButtonStyle());
label_->text(LV_SYMBOL_CLOSE);
label_->center();
lv_obj_set_style_text_color(label_->raw(), lv_color_white(), 0);
lv_obj_set_style_text_font(label_->raw(), &lv_font_montserrat_16, 0);
// 使用更安全的事件绑定方式
setupExitButton();
}
// 子类重写:界面内容
virtual void onShow() {} // 进入时调用
virtual void onHide() {} // 退出时调用
~BaseApp() override {
// 标记为正在销毁
is_destroying_ = true;
// 先清理子对象
label_.reset();
btn_exit_.reset();
// 如果ptr_仍然有效,安全删除
if (ptr_ && lv_obj_is_valid(ptr_)) {
// 先隐藏对象,停止所有交互
lv_obj_add_flag(ptr_, LV_OBJ_FLAG_HIDDEN);
// 延迟删除,确保所有事件处理完成
lv_timer_create([](lv_timer_t* timer) {
lv_obj_t* obj = static_cast<lv_obj_t*>(timer->user_data);
if (obj && lv_obj_is_valid(obj)) {
lv_obj_del(obj);
}
lv_timer_del(timer);
}, 100, ptr_); // 延迟100ms删除
}
}
// 主动退出
void exit() {
if (is_exiting_) return;
is_exiting_ = true;
onCleanup();
onHide();
// 禁止自己再被点击
lv_obj_clear_flag(raw(), LV_OBJ_FLAG_CLICKABLE);
// 异步自毁:让 LVGL 在下一轮循环再删我们
lv_async_call([](void* self) {
lv_obj_del(static_cast<lv_obj_t*>(self));
}, raw());
// 通知工厂回到主页 → 由工厂/菜单负责
if (exit_cb_) exit_cb_();
// 立即隐藏并禁用
if (ptr_ && lv_obj_is_valid(ptr_)) {
lv_obj_add_flag(ptr_, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(ptr_, LV_OBJ_FLAG_CLICKABLE);
}
// 通知退出回调
if (exit_cb_) {
exit_cb_();
}
// 延迟自毁
auto self = this;
lv_timer_create([](lv_timer_t* timer) {
const auto* app = static_cast<BaseApp*>(timer->user_data);
if (app && app->ptr_ && lv_obj_is_valid(app->ptr_)) {
lv_obj_del(app->ptr_);
}
lv_timer_del(timer);
}, 50, this); // 50ms后删除
}
// 注册退出通知回调(由 AppFactory 设置)
void onExit(std::function<void()> cb) { exit_cb_ = std::move(cb); }
virtual void onShow() {}
virtual void onHide() {}
void onExit(std::function<void()> cb) { exit_cb_ = std::move(cb); }
protected:
Button btn_exit_{*this}; // 退出按钮
Label label_{btn_exit_}; // 退出图标
// 子类有需要就重写, 用于释放资源
virtual void onCleanup() {}
protected:
std::unique_ptr<Button> btn_exit_;
std::unique_ptr<Label> label_;
private:
std::function<void()> exit_cb_;
std::atomic<bool> is_exiting_{false};
std::atomic<bool> is_destroying_{false};
void setupExitButton() {
// 使用原始LVGL事件,避免C++回调问题
lv_obj_add_event_cb(btn_exit_->raw(), [](lv_event_t* e) {
lv_obj_t* btn = lv_event_get_target(e);
if (!btn || !lv_obj_is_valid(btn)) return;
lv_obj_t* parent = lv_obj_get_parent(btn);
if (!parent || !lv_obj_is_valid(parent)) return;
// 通过用户数据找到BaseApp实例
auto* app = static_cast<BaseApp*>(lv_obj_get_user_data(parent));
if (app && !app->is_exiting_ && !app->is_destroying_) {
app->exit();
}
}, LV_EVENT_CLICKED, this);
// 保存this指针到用户数据
lv_obj_set_user_data(raw(), this);
}
static lv_style_t& getExitButtonStyle() {
static lv_style_t style;
static bool style_initialized = false;
if (!style_initialized) {
lv_style_init(&style);
lv_style_set_bg_color(&style, lv_color_hex(0xFF3B30));
lv_style_set_bg_opa(&style, LV_OPA_COVER);
lv_style_set_radius(&style, 20);
lv_style_set_border_width(&style, 0);
style_initialized = true;
}
return style;
}
};
// 子应用工厂
@@ -731,11 +1125,12 @@ public:
lv_obj_set_style_bg_opa(raw(), LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(raw(), 0, 0);
lv_obj_clear_flag(raw(), LV_OBJ_FLAG_SCROLLABLE); // 圆形屏建议不要滚动
lv_obj_set_style_pad_top(raw(), 60, 0); // ← 新
lv_obj_set_style_pad_top(raw(), 100, 0); // 增加顶部内边距为返回按钮留空间
lv_obj_set_style_pad_bottom(raw(),60, 0); // ← 新增
lv_obj_set_style_pad_left(raw(), 20, 0);
lv_obj_set_style_pad_right(raw(), 20, 0);
// 创建返回主页按钮(放在顶部)
createBackButton();
// 横向 2 列,居中排列
lv_obj_set_flex_flow(raw(), LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(raw(), LV_FLEX_ALIGN_SPACE_EVENLY,
@@ -775,9 +1170,81 @@ public:
click_cb_ = std::move(cb);
return *this;
}
// 注册返回主页回调
AppMenu& onBack(std::function<void()> cb) {
back_cb_ = std::move(cb);
return *this;
}
private:
void createBackButton() {
// 创建返回按钮容器(固定在顶部)
back_btn_ = std::make_unique<Button>(*this);
back_label_ = std::make_unique<Label>(*back_btn_);
// 设置返回按钮样式
back_btn_->size(120, 40)
.align(LV_ALIGN_TOP_MID, nullptr, 0, 20) // 顶部中间,向下偏移20px
.add_style(&getBackButtonStyle());
back_label_->text("返回主页");
back_label_->center();
lv_obj_set_style_text_color(back_label_->raw(), lv_color_white(), 0);
lv_obj_set_style_text_font(back_label_->raw(), &SiYuanHeiTiGoogleBan, LV_PART_MAIN);
// 返回按钮点击事件
lv_obj_add_event_cb(back_btn_->raw(), [](lv_event_t* e) {
// lv_obj_t* target = lv_event_get_target(e);
// ESP_LOGI("BackButton", "收到事件: %d, 对象: %p", code, target);
switch(lv_event_get_code(e)) {
case LV_EVENT_PRESSED: {
ESP_LOGI("BackButton", "按钮按下");
break;
}
case LV_EVENT_RELEASED: {
ESP_LOGI("BackButton", "按钮释放");
break;
}
case LV_EVENT_CLICKED: {
ESP_LOGI("BackButton", "按钮点击!!!");
// 处理点击事件
lv_obj_t* btn = lv_event_get_target(e);
lv_obj_t* menu_obj = lv_obj_get_parent(btn);
auto* menu = static_cast<AppMenu*>(lv_obj_get_user_data(menu_obj));
if (menu && menu->back_cb_) {
ESP_LOGI("BackButton", "执行返回回调");
menu->back_cb_();
}
break;
}
default: {
break;
}
}
}, LV_EVENT_CLICKED, nullptr);
// 确保设置用户数据
lv_obj_set_user_data(raw(), this);
// ESP_LOGI("AppMenu", "返回按钮创建完成, 按钮地址: %p", back_btn_->raw());
}
static lv_style_t& getBackButtonStyle() {
static lv_style_t style;
static bool style_initialized = false;
if (!style_initialized) {
lv_style_init(&style);
lv_style_set_bg_color(&style, lv_color_hex(0x4CAF50)); // 绿色背景
lv_style_set_bg_opa(&style, LV_OPA_COVER);
lv_style_set_radius(&style, 20);
lv_style_set_border_width(&style, 0);
style_initialized = true;
}
return style;
}
private:
std::function<void(const char*)> click_cb_;
std::function<void()> back_cb_;
std::unique_ptr<Button> back_btn_;
std::unique_ptr<Label> back_label_;
};
// 主页
@@ -794,44 +1261,37 @@ public:
// 背景图片(默认空,可热切换)
bg_img_ = std::make_unique<Image>(*this);
// 顶栏电池
battery_ = std::make_unique<Battery>(*this);
battery_->size(60, 30)
.percent(true)
.align(LV_ALIGN_CENTER, -10, -150);
// 底栏时间
datetime_ = std::make_unique<DateTime>(*this);
datetime_->format("%m/%d %a %H:%M")
.align(LV_ALIGN_BOTTOM_MID, nullptr, 0, -10);
// 长按识别:按住 500 ms 即进入应用菜单
lv_obj_add_flag(raw(), LV_OBJ_FLAG_CLICKABLE); // 必须置位,否则收不到输入事件
on(LV_EVENT_LONG_PRESSED, [this](lv_event_t*) {
if (menu_open_cb_) menu_open_cb_();
});
}
// 热切换背景
HomePage& bg(const char* bin_path, const uint32_t w, const uint32_t h) {
bg_img_->bin(bin_path, w, h);
bg_img_->center();
return *this;
}
// 注册电量回调
HomePage& onBattery(std::function<uint8_t()> cb) {
battery_->onRead(std::move(cb));
return *this;
}
// 注册时间回调
HomePage& onDateTime(std::function<void(char*, size_t)> cb) {
datetime_->onRead(std::move(cb));
return *this;
}
// 注册右滑 → 打开菜单的回调
HomePage& onOpenMenu(std::function<void()> cb) {
menu_open_cb_ = std::move(cb);
@@ -0,0 +1,5 @@
//
// Created by misaki on 2025/9/28.
//
#include "BaseApp.h"
@@ -0,0 +1,415 @@
//
// Created by misaki on 2025/9/28.
//
#pragma once
#include <optional>
#include <iostream>
#include "lvpp.h"
#include "cpp_json.h"
#include "CommClass.h"
LV_FONT_DECLARE(SiYuanHeiTiGoogleBan); // 引入字体
struct AppCalc : lvgl_cpp::BaseApp {
using BaseApp::BaseApp;
void onShow() override {
lvgl_cpp::Label(*this).text("Calculator").center();
}
};
struct AppMusic : lvgl_cpp::BaseApp {
using BaseApp::BaseApp;
void onShow() override {
btn_.emplace(*this);
gif.emplace(*this);
btn_->size(180, 60)
.align(LV_ALIGN_CENTER, nullptr, 0, 80)
.on(LV_EVENT_CLICKED, [&](lv_event_t*) {
// 居中 GIF,背景黑
lv_obj_set_style_bg_color(this->raw(), lv_color_black(), 0);
lv_obj_clear_flag(this->raw(), LV_OBJ_FLAG_SCROLLABLE); // 禁止滚动
lv_obj_set_scroll_dir(this->raw(), LV_DIR_NONE);
lv_obj_set_style_bg_opa(this->raw(), LV_OPA_COVER, 0);
gif->src("sequence02mmm.gif")
.center();
});
// 按钮文字
lv_obj_t* label = lv_label_create(btn_->raw());
lv_obj_set_style_text_font(label, &SiYuanHeiTiGoogleBan, LV_PART_MAIN);
lv_label_set_text(label, "Gif测试");
lv_obj_center(label);
}
void onCleanup() override {
if (gif) gif->drop(); // 对象还活着,立即释放
}
~AppMusic() override{
gif.reset();
btn_.reset();
}
private:
std::optional<lvgl_cpp::Button> btn_; // c++17 轻量 RAII
std::optional<lvgl_cpp::Gif> gif;
};
class ButtonApp : public lvgl_cpp::BaseApp {
public:
using BaseApp::BaseApp; // 继承 exit 按钮机制
void onShow() override {
/* 居中按钮:180×60 px,圆角,现代蓝 */
btn_.emplace(*this);
btn_->size(180, 60)
.align(LV_ALIGN_CENTER, nullptr, 0, 80)
.on(LV_EVENT_CLICKED, [](lv_event_t*) {
lvgl_cpp::Toast::show("咕咕嘎嘎!",
lvgl_cpp::Toast::Type::INFO,
1000);
});
/* 按钮文字 */
lv_obj_t* label = lv_label_create(btn_->raw());
lv_obj_set_style_text_font(label, &SiYuanHeiTiGoogleBan, LV_PART_MAIN);
lv_label_set_text(label, "按我");
lv_obj_center(label);
}
private:
std::optional<lvgl_cpp::Button> btn_; // c++17 轻量 RAII
};
class WebSocketVoice : public lvgl_cpp::BaseApp {
public:
using BaseApp::BaseApp; // 继承 exit 按钮机制
void onShow() override {
/* 居中按钮:180×60 px,圆角,现代蓝 */
btn_.emplace(*this);
btn_->size(180, 60)
.align(LV_ALIGN_CENTER, nullptr, 0, 80)
.on(LV_EVENT_CLICKED, [](lv_event_t*) {
lvgl_cpp::Toast::show("测试!",
lvgl_cpp::Toast::Type::ERROR,
1000);
});
/* 按钮文字 */
lv_obj_t* label = lv_label_create(btn_->raw());
lv_obj_set_style_text_font(label, &SiYuanHeiTiGoogleBan, LV_PART_MAIN);
lv_label_set_text(label, "按我");
lv_obj_center(label);
}
private:
std::optional<lvgl_cpp::Button> btn_; // c++17 轻量 RAII
};
#include "SDFileManager.h"
#include "SimpleI2SForwarder.h"
#include <mbedtls/base64.h> // base64 编解码
class LongPressButtonAnim : public lvgl_cpp::BaseApp {
public:
using BaseApp::BaseApp; // 继承 exit 按钮机制
void onShow() override {
/* 居中按钮:180×60 px,圆角,现代蓝 */
btn_.emplace(*this);
btn_->size(180, 60)
.align(LV_ALIGN_CENTER, nullptr, 0, 80);
btn_->onLong([](const std::atomic<bool>& stop) { // 长按循环按钮
std::vector<int16_t> audio_data;
std::vector<int16_t> audio_data_sum;
constexpr int SHIFT_AVE = 14; // 你喂 AFE 时右移的位数
constexpr int GAIN_SHIFT = 14 - 9; // 想拉回 0 dB 需要左移多少
ESP_LOGI("LP","开始录音");
while(!stop){
// 获取所有可用的最新数据,并累加到 audio_data_sum 当中
if (LatestDataForwarder::getInstance()->retrieveLatestData(audio_data, 100)) {
// 放大到正常幅度再累加(放大声音)
for (auto &s : audio_data) {
int32_t tmp = static_cast<int32_t>(s) << GAIN_SHIFT; // 能量拉回 0 dB
if (tmp > 32767) tmp = 32767;
if (tmp < -32768) tmp = -32768;
audio_data_sum.push_back(static_cast<int16_t>(tmp));
}
// ESP_LOGI("LP", "got %zu samples, total now %zu",
// audio_data.size(), audio_data_sum.size());
} else {
ESP_LOGW("LP", "no data within 100 ms");
}
// vTaskDelay(pdMS_TO_TICKS(5));
}
ESP_LOGI("LP","结束录音");
// 在SD卡根目录创建一个pcm文件,向其中写入数据
// ESP_LOGI("LP","开始写入文件");
// SDFileManager::getInstance()->writeFileSync(
// ToolsClass::makeFullPath("temp_little_endian_16bit_16khz.pcm").c_str(),
// reinterpret_cast<const char *>(audio_data_sum.data()),
// audio_data_sum.size() * sizeof(int16_t),
// "wb");
// ESP_LOGI("LP","写入文件成功");
// 将数据封装成 json 后通过 websocket 发送给服务器
ESP_LOGI("LP","开始发送数据");
size_t pcm_bytes = audio_data_sum.size() * sizeof(int16_t);
size_t b64_len = 0;
mbedtls_base64_encode(nullptr, 0, &b64_len,
reinterpret_cast<const unsigned char*>(audio_data_sum.data()),
pcm_bytes);
/* 再真正编码 */
std::vector<unsigned char> b64_buf(b64_len);
mbedtls_base64_encode(b64_buf.data(), b64_len, &b64_len,
reinterpret_cast<const unsigned char*>(audio_data_sum.data()),
pcm_bytes);
/* 转成 std::string(不含 \0 */
std::string b64_str(reinterpret_cast<char*>(b64_buf.data()), b64_len);
cppjson::Json audio_json = cppjson::Json::object(); // 创建 json 对象
cppjson::Json audio_json_body = cppjson::Json::object();
audio_json.set("type", cppjson::Json("audio"));
audio_json_body
.set("data", cppjson::Json(b64_str))
.set("size", cppjson::Json(audio_data_sum.size()));
audio_json.set("body", audio_json_body);
WebSocketManager::getInstance()->sendJson(audio_json);
ESP_LOGI("LP","发送数据 OVER!");
ESP_LOGI("LP","long exit");
});
btn_->onShort([]() { // 短按(点一下)
ESP_LOGI("Btn", "short click");
});
/* 按钮文字 */
lv_obj_t* label = lv_label_create(btn_->raw());
lv_obj_set_style_text_font(label, &SiYuanHeiTiGoogleBan, LV_PART_MAIN);
lv_label_set_text(label, "长按录音");
lv_obj_center(label);
}
private:
std::optional<lvgl_cpp::LongPressButton> btn_; // c++17 轻量 RAII
};
#include "SpeechRecognizer.h"
#include "AudioOutput.h"
#include "PetBaseClass.h"
#include "PetDao.h"
class PetApp : public lvgl_cpp::BaseApp {
public:
using BaseApp::BaseApp; // 继承 exit 按钮机制
// 打印宠物当前状态
static void printPet(const PetBase& pet)
{
const auto& info = pet.getPetInfo();
std::cout << "【状态】"
<< " 名称:" << info.pet_name
<< " HP:" << info.pet_hp
<< " 亲密度:" << info.pet_density
<< " 身份:" << info.pet_identity
<< " 阶段:" << static_cast<int>(pet.getCurrentStage())
<< " 动作:" << static_cast<int>(pet.getCurrentAction())
<< std::endl;
}
// 初始化测试宠物信息
void initPet() {
// 创建雪豹
PetBaseInfo info{
.pet_name = "芝士雪豹",
.pet_hp = 100,
.pet_density = 45, // 故意设低,方便看进化
.pet_identity = "我是顶真,来自妈妈省"
};
const auto stageStrategy = std::make_shared<PetStageStrategy>();
const auto actionStrategy = std::make_shared<PetActionStrategy>();
// 填阶段资源(模型/音频)
stageStrategy->addStage(PetStageType::PET_STAGE_YOUNG, "pet_data/cheese_snow_leopard/models/setdown30.gif");
stageStrategy->addStage(PetStageType::PET_STAGE_ADULT, "pet_data/cheese_snow_leopard/models/setdown10.gif");
stageStrategy->addStage(PetStageType::PET_STAGE_OLD, "pet_data/cheese_snow_leopard/models/setdown20.gif");
stageStrategy->addStageAudio(PetStageType::PET_STAGE_YOUNG, "pet_data/cheese_snow_leopard/audio/dog.pcm");
stageStrategy->addStageAudio(PetStageType::PET_STAGE_ADULT, "/audio/snow_adult.mp3");
stageStrategy->addStageAudio(PetStageType::PET_STAGE_OLD, "/audio/snow_old.mp3");
// 填动作资源
actionStrategy->addAction(PetActionType::PET_ACTION_EAT, "pet_data/cheese_snow_leopard/models/eat1.gif");
actionStrategy->addActionAudio(PetActionType::PET_ACTION_EAT, "pet_data/cheese_snow_leopard/audio/cat.pcm");
// 创建宠物
pet = std::make_shared<PetBase>(info, stageStrategy, actionStrategy);
// 4. 构造观察者
audioObserver = std::make_shared<PetAudioStrategy>(stageStrategy, actionStrategy);
audioObserver->setAudioCallback([&](PetType petType, const std::string& path){
std::cout << "🔊 播放音频: " << path << std::endl;
if (petType == PetType::Action) { // 如果播放的是动作
AudioOutput::getInstance()->playPcmFile(ToolsClass::makeFullPath(path).c_str());
}
if (petType == PetType::Stage) { // 如果播放的是阶段
// 暂时nothing to do
}
});
renderObserver = std::make_shared<PetRendererStrategy>(stageStrategy, actionStrategy);
renderObserver->setRenderCallback([&](PetType petType, const std::string& path){
std::cout << "🖼️ 渲染模型: " << path << std::endl;
if (petType == PetType::Action) { // 如果播放的是动作,则突发播放
gif_->burst(path.c_str(), 7000);
}
if (petType == PetType::Stage) { // 如果播放的是阶段,则持久循环播放
std::cout << "渲染模型路径: " << path << std::endl;
gif_->loop(path.c_str());
}
});
audioObserver->subscribe(pet);
renderObserver->subscribe(pet);
// 触发初始渲染
pet->notifyStageChange(PetStageType::PET_STAGE_YOUNG, pet->getCurrentStage());
printPet(*pet);
}
// 初始化语音识别
void initSpeech() {
// 获取 SpeechRecognizer 全局单例实例
recognizer = SpeechRecognizer::getInstance();
// 初始化
recognizer->init(false, VAD_MODE_3, "/sdcard/srmodels");
// 添加自定义命令
std::vector<std::pair<int, std::string> > commands = {
{0, "mo tou"}, // 摸头
{1, "wei shi"}, // 喂食
{2, "jiao liang sheng"}, // 叫两声
};
// 添加命令
recognizer->addCommands(commands);
// 注册回调函数
recognizer->registerCommandCallback([this](int command_id, const std::string& phrase, float probability) {
this->commandCallback(command_id, phrase, probability);
});
recognizer->registerStateCallback([this](const std::string& state) {
this->stateCallback(state);
});
recognizer->start(); // 启动识别
}
// 状态回调函数
void stateCallback(const std::string &state) {
ESP_LOGI("Example", "状态改变到: %s", state.c_str());
}
// 命令回调函数
void commandCallback(int command_id, const std::string &phrase, float probability) {
ESP_LOGI("Example", "Received command: ID=%d, Phrase='%s', Probability=%.2f",
command_id, phrase.c_str(), probability);
// 根据命令执行相应操作
switch (command_id) {
case 0:
pet->play();
info_->text_fmt("HP: %d \n Dens: %d", pet->getPetInfo().pet_hp, pet->getPetInfo().pet_density);
printPet(*pet);
break;
case 1:
pet->feed();
info_->text_fmt("HP: %d \n Dens: %d", pet->getPetInfo().pet_hp, pet->getPetInfo().pet_density);
printPet(*pet);
break;
case 2:
pet->play();
info_->text_fmt("HP: %d \n Dens: %d", pet->getPetInfo().pet_hp, pet->getPetInfo().pet_density);
printPet(*pet);
break;
default:
ESP_LOGI("Example", "未知的命令ID: %d", command_id);
break;
}
}
void onShow() override {
lv_obj_set_style_bg_color(this->raw(), lv_color_black(), 0); // 背景
lv_obj_clear_flag(this->raw(), LV_OBJ_FLAG_SCROLLABLE); // 禁止滚动
gif_ = std::make_unique<lvgl_cpp::GifPlayer>(*this); // 注意初始化顺序
gif_->size(360, 360);
initPet(); // 初始化测试宠物信息
initSpeech(); // 初始化语音识别
// 居中按钮:180×60 px,圆角,现代蓝
btn_.emplace(*this);
btn_->size(120, 40)
.align(LV_ALIGN_CENTER, nullptr, 0, 80);
// 按钮文字
lv_obj_t* label = lv_label_create(btn_->raw());
lv_obj_set_style_text_font(label, &SiYuanHeiTiGoogleBan, LV_PART_MAIN);
lv_label_set_text(label, "长按交流");
lv_obj_center(label);
btn_->onShort([]() { // 短按事件(点一下)
ESP_LOGI("Btn", "short click");
});
btn_->onLong([](const std::atomic<bool>& stop) { // 长按循环按钮
std::vector<int16_t> audio_data;
std::vector<int16_t> audio_data_sum;
constexpr int SHIFT_AVE = 14; // 喂 AFE 时右移的位数
constexpr int GAIN_SHIFT = 14 - 9; // 想拉回 0 dB 需要左移多少
ESP_LOGI("LP","开始录音");
while(!stop){
// 获取所有可用的最新数据,并累加到 audio_data_sum 当中
if (LatestDataForwarder::getInstance()->retrieveLatestData(audio_data, 100)) {
// 放大到正常幅度再累加(放大声音)
for (auto &s : audio_data) {
int32_t tmp = static_cast<int32_t>(s) << GAIN_SHIFT; // 能量拉回 0 dB
if (tmp > 32767) tmp = 32767;
if (tmp < -32768) tmp = -32768;
audio_data_sum.push_back(static_cast<int16_t>(tmp));
}
// ESP_LOGI("LP", "got %zu samples, total now %zu",
// audio_data.size(), audio_data_sum.size());
} else {
ESP_LOGW("LP", "no data within 100 ms");
}
}
ESP_LOGI("LP","结束录音");
// 将数据封装成 json 后通过 websocket 发送给服务器
ESP_LOGI("LP","开始发送数据");
size_t pcm_bytes = audio_data_sum.size() * sizeof(int16_t);
size_t b64_len = 0;
mbedtls_base64_encode(nullptr, 0, &b64_len,
reinterpret_cast<const unsigned char*>(audio_data_sum.data()),
pcm_bytes);
// 再真正编码
std::vector<unsigned char> b64_buf(b64_len);
mbedtls_base64_encode(b64_buf.data(), b64_len, &b64_len,
reinterpret_cast<const unsigned char*>(audio_data_sum.data()),
pcm_bytes);
// 转成 std::string(不含 \0
std::string b64_str(reinterpret_cast<char*>(b64_buf.data()), b64_len);
cppjson::Json audio_json = cppjson::Json::object(); // 创建 json 对象
cppjson::Json audio_json_body = cppjson::Json::object();
audio_json.set("type", "audio");
audio_json_body
.set("data", b64_str)
.set("size", cppjson::Json(audio_data_sum.size()));
audio_json.set("body", audio_json_body);
WebSocketManager::getInstance()->sendJson(audio_json);
ESP_LOGI("LP","发送数据 OVER!");
ESP_LOGI("LP","long exit");
});
// 透明文字浮层(初始提示)
info_.emplace(*this);
info_->text_fmt("HP: %d \n Dens: %d", pet->getPetInfo().pet_hp, pet->getPetInfo().pet_density)
.textColor(lv_color_black())
.font(&SiYuanHeiTiGoogleBan)
.alignText(LV_TEXT_ALIGN_CENTER)
.place(LV_ALIGN_CENTER, nullptr, 0, -120); // 屏幕正中央
}
void onCleanup() override {
if (gif_) gif_->stop(); // 对象还活着,立即释放
}
~PetApp() override = default; // unique_ptr 自动析构
private:
std::shared_ptr<PetBase> pet;
std::shared_ptr<PetAudioStrategy> audioObserver;
std::shared_ptr<PetRendererStrategy> renderObserver;
private:
SpeechRecognizer *recognizer; // 语音识别
std::unique_ptr<lvgl_cpp::GifPlayer> gif_; // gif 播放器
std::optional<lvgl_cpp::TextOverlay> info_; // 透明文字
std::optional<lvgl_cpp::LongPressButton> btn_; // 长按按钮
};
@@ -47,7 +47,7 @@ void SDFileManager::tryInitSDCard() {
}
bool SDFileManager::writeFileSync(const char* path, const char* data) {
bool SDFileManager::writeFileSync(const char* path, const char* data, const size_t len, const char* type) {
std::lock_guard<std::mutex> lock(file_operation_mutex);
if (!is_initialized) {
@@ -55,8 +55,20 @@ bool SDFileManager::writeFileSync(const char* path, const char* data) {
return false;
}
esp_err_t result = s_example_write_file(path, const_cast<char*>(data));
return result == ESP_OK;
ESP_LOGI("SDFileManager", "Opening file %s", path);
FILE *f = fopen(path, type);
if (f == nullptr) {
ESP_LOGE("SDFileManager", "Failed to open file for writing");
return ESP_FAIL;
}
const size_t written = fwrite(data, 1, len, f);
fclose(f);
if (written != len) {
ESP_LOGE("SDFileManager", "Only %zu/%zu bytes written", written, len);
return ESP_FAIL;
}
ESP_LOGI("SDFileManager", "File written (%zu bytes)", written);
return true;
}
std::string SDFileManager::readFileSync(const char* path) {
@@ -133,9 +145,9 @@ std::vector<std::string> SDFileManager::listFilesSync(const char* directory, con
return {};
}
const int max_files = 50;
constexpr int max_files = 50;
char file_names[max_files][100];
uint16_t file_count = Folder_retrieval(directory, extension, file_names, max_files);
const uint16_t file_count = Folder_retrieval(directory, extension, file_names, max_files);
std::vector<std::string> files;
for (uint16_t i = 0; i < file_count; ++i) {
@@ -163,12 +175,12 @@ bool SDFileManager::closeFileSync(FILE* file) {
return false;
}
void SDFileManager::asyncWriteFile(const char* path, const char* data, WriteCallback callback) {
void SDFileManager::asyncWriteFile(const char* path, const char* data, const size_t len, const char* type, WriteCallback callback) {
ThreadConfig config = getThreadConfig("write_file");
ThreadManager::createThread(config, [this, path = std::string(path),
data = std::string(data), callback]() {
bool success = this->writeFileSync(path.c_str(), data.c_str());
data = std::string(data), callback, type, len]() {
const bool success = this->writeFileSync(path.c_str(), data.c_str(), len, type);
if (callback) {
callback(success, path.c_str());
}
@@ -34,9 +34,11 @@ public:
* 同步写入文件
* @param path 文件路径
* @param data 数据
* @param len 数据长度
* @param type 文件类型
* @return 是否成功
*/
bool writeFileSync(const char* path, const char* data);
bool writeFileSync(const char* path, const char* data, const size_t len, const char* type);
/**
* 同步读取文件
* @param path 文件路径
@@ -79,9 +81,11 @@ public:
* 异步写入文件
* @param path 文件路径
* @param data 数据
* @param len 数据长度
* @param type 文件类型
* @param callback 回调函数
*/
void asyncWriteFile(const char* path, const char* data, WriteCallback callback = nullptr);
void asyncWriteFile(const char* path, const char* data, const size_t len, const char* type, WriteCallback callback = nullptr);
/**
* 异步读取文件
* @param path 文件路径
@@ -0,0 +1,9 @@
//
// Created by misaki on 2025/9/29.
//
#include "SimpleI2SForwarder.h"
// 静态成员初始化
LatestDataForwarder* LatestDataForwarder::instance = nullptr;
std::mutex LatestDataForwarder::instance_mutex;
@@ -0,0 +1,124 @@
//
// Created by misaki on 2025/9/29.
//
/**
* 音频数据转发器 单生产者单消费者模型
* 单纯只作为数据转发器,不进行任何处理
*/
#pragma once
#include <atomic>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <deque>
class LatestDataForwarder {
private:
static LatestDataForwarder* instance;
static std::mutex instance_mutex;
std::deque<std::vector<int16_t>> queue_;
size_t max_size_;
std::mutex queue_mutex_;
std::condition_variable data_available_;
std::atomic<bool> is_running_;
public:
static LatestDataForwarder* getInstance() {
std::lock_guard<std::mutex> lock(instance_mutex);
if (!instance) {
instance = new LatestDataForwarder();
}
return instance;
}
void initialize(const size_t max_size = 500) {
std::lock_guard<std::mutex> lock(queue_mutex_);
max_size_ = max_size;
is_running_ = true;
}
// 生产者:总是注入最新数据,队列满时丢弃最旧数据
void injectData(const int16_t* data, const size_t length) {
if (!is_running_ || !data || length == 0) return;
std::lock_guard<std::mutex> lock(queue_mutex_);
// 创建新数据
std::vector<int16_t> new_data(data, data + length);
// 如果队列已满,移除最旧的数据
if (queue_.size() >= max_size_) {
queue_.pop_front();
}
// 添加最新数据
queue_.push_back(std::move(new_data));
data_available_.notify_one();
}
// 消费者:获取所有可用的最新数据
bool retrieveLatestData(std::vector<int16_t>& output, const int timeout_ms = 0) {
if (!is_running_) return false;
std::unique_lock<std::mutex> lock(queue_mutex_);
// 如果队列当中数据不足,则等待数据可用
if (queue_.empty()) {
if (timeout_ms <= 0) return false;
if (data_available_.wait_for(lock,
std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) {
return false;
}
if (queue_.empty()) return false;
}
if (!is_running_) return false;
// 合并队列中的所有数据(最新的数据)
output.clear();
for (const auto& chunk : queue_) {
output.insert(output.end(), chunk.begin(), chunk.end());
}
// 清空队列,准备接收新的实时数据
queue_.clear();
return true;
}
// 消费者:只获取最新的N帧数据
bool retrieveRecentData(std::vector<int16_t>& output, const size_t recent_frames = 10, const int timeout_ms = 0) {
if (!is_running_) return false;
std::unique_lock<std::mutex> lock(queue_mutex_);
// 等待数据可用
if (queue_.empty()) {
if (timeout_ms <= 0) return false;
if (data_available_.wait_for(lock,
std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) {
return false;
}
if (queue_.empty()) return false;
}
if (!is_running_) return false;
// 只取最新的recent_frames帧数据
output.clear();
const size_t start_index = queue_.size() > recent_frames ? queue_.size() - recent_frames : 0;
for (size_t i = start_index; i < queue_.size(); ++i) {
output.insert(output.end(), queue_[i].begin(), queue_[i].end());
}
// 移除已取出的旧数据,保留最新的数据
if (start_index > 0) {
std::deque<std::vector<int16_t>> new_queue(queue_.begin() + start_index, queue_.end());
queue_.swap(new_queue);
}
return true;
}
size_t getQueueSize() {
std::lock_guard<std::mutex> lock(queue_mutex_);
return queue_.size();
}
void clear() {
std::lock_guard<std::mutex> lock(queue_mutex_);
queue_.clear();
}
void stop() {
is_running_ = false;
data_available_.notify_all();
}
void start() {
is_running_ = true;
}
private:
LatestDataForwarder() : max_size_(500), is_running_(false) {}
};
@@ -2,20 +2,22 @@
// Created by misaki on 2025/9/15.
//
#include "SpeechRecognizer.h"
#include "esp_afe_sr_models.h"
#include "esp_mn_models.h"
#include "esp_wn_iface.h"
#include "esp_mn_speech_commands.h"
#include "model_path.h"
#include "driver/gpio.h"
#include "soc/soc_caps.h"
#include "esp_err.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "VadSlidingWindow.h"
#include "SimpleI2SForwarder.h"
#include <esp_afe_sr_models.h>
#include <esp_mn_models.h>
#include <esp_wn_iface.h>
#include <esp_mn_speech_commands.h>
#include <model_path.h>
#include <driver/gpio.h>
#include <soc/soc_caps.h>
#include <esp_err.h>
#include <nvs_flash.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <atomic>
#include <cstring>
#include <memory>
#include <utility>
// 初始化静态成员变量
@@ -40,8 +42,8 @@ SpeechRecognizer::SpeechRecognizer()
models(nullptr),
multinet(nullptr),
model_data(nullptr),
tasksRunning(false) {
}
vad_state_(AFE_VAD_SILENCE),
tasksRunning(false){}
SpeechRecognizer::~SpeechRecognizer() {
deinit();
@@ -68,6 +70,29 @@ bool SpeechRecognizer::init(const SpeechRecognizerConfig& config) {
return true;
}
bool SpeechRecognizer::init(const bool enable_vad, const vad_mode_t vad_mode, std::string model_path) {
if (initialized) {
ESP_LOGI("SpeechRecognizer", "Already initialized");
return true;
}
this->config.enable_vad = enable_vad;
this->config.vad_mode = vad_mode;
this->config.model_path = std::move(model_path);
// 初始化I2S
if (!initI2S()) {
ESP_LOGE("SpeechRecognizer", "I2S initialization failed");
return false;
}
// 初始化ESP-SR
if (!initESP_SR()) {
ESP_LOGE("SpeechRecognizer", "ESP-SR initialization failed");
return false;
}
initialized = true;
ESP_LOGI("SpeechRecognizer", "Initialization completed successfully");
return true;
}
void SpeechRecognizer::deinit() {
if (!initialized) {
return;
@@ -88,8 +113,8 @@ void SpeechRecognizer::deinit() {
}
// 释放I2S资源
if (rx_handle) {
i2s_channel_disable(rx_handle);
i2s_del_channel(rx_handle);
i2s_channel_disable(rx_handle); // 删除通道之前必须先禁用通道
i2s_del_channel(rx_handle); // 删除该句柄以释放通道资源
rx_handle = nullptr;
}
initialized = false;
@@ -98,30 +123,33 @@ void SpeechRecognizer::deinit() {
bool SpeechRecognizer::initI2S() {
esp_err_t ret = ESP_OK;
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_1, I2S_ROLE_MASTER);
// 通过辅助宏获取默认的通道配置, 它可以帮助指定 I2S 角色和端口 ID
constexpr i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_1, I2S_ROLE_MASTER);
// 分配新的 TX 通道并获取该通道的句柄
ret = i2s_new_channel(&chan_cfg, nullptr, &rx_handle);
if (ret != ESP_OK) {
ESP_LOGE("SpeechRecognizer", "Failed to create I2S channel: %s", esp_err_to_name(ret));
return false;
}
// 进行配置,通过宏生成声道配置和时钟配置, 这两个辅助宏在 'i2s_std.h' 中定义,只能用于 STD 模式
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO),
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000), // 16KHz采样率
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO), // 32位单声道
.gpio_cfg = {
.mclk = GPIO_NUM_NC,
.bclk = config.bclk_pin,
.ws = config.ws_pin,
.dout = GPIO_NUM_NC,
.din = config.din_pin,
.invert_flags = {
.mclk = GPIO_NUM_NC, // 不使用MCLK
.bclk = config.bclk_pin, // BCLK引脚
.ws = config.ws_pin, // WS引脚
.dout = GPIO_NUM_NC, // 不使用DOUT
.din = config.din_pin, // DIN引脚
.invert_flags = { // 不使用倒置
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
};
std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_RIGHT;
ret = i2s_channel_init_std_mode(rx_handle, &std_cfg);
std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_RIGHT; // 右声道
ret = i2s_channel_init_std_mode(rx_handle, &std_cfg); // 初始化STD标准模式
if (ret != ESP_OK) {
ESP_LOGE("SpeechRecognizer", "Failed to init I2S standard mode: %s", esp_err_to_name(ret));
return false;
@@ -177,7 +205,7 @@ bool SpeechRecognizer::initESP_SR() {
ESP_LOGE("SpeechRecognizer", "Failed to create AFE data from config");
return false;
}
// 加载MultiNet模型(采用esp-sr提供的宏来处理不同语种的模型的处理问题)
// 加载MultiNet模型 (采用esp-sr提供的宏来处理不同语种的模型的处理问题)
#if defined(CONFIG_SR_MN_CN_MULTINET5_RECOGNITION_QUANT8) || defined(CONFIG_SR_MN_CN_MULTINET6_QUANT) || defined(CONFIG_SR_MN_CN_MULTINET6_AC_QUANT)
char *mn_name = esp_srmodel_filter(models, ESP_MN_PREFIX, ESP_MN_CHINESE);
#else
@@ -211,7 +239,7 @@ bool SpeechRecognizer::start() {
return true;
}
// 启用I2S通道
esp_err_t ret = i2s_channel_enable(rx_handle);
esp_err_t ret = i2s_channel_enable(rx_handle); // 在读取数据之前,先启动 RX 通道
if (ret != ESP_OK) {
ESP_LOGE("SpeechRecognizer", "Failed to enable I2S channel: %s", esp_err_to_name(ret));
return false;
@@ -253,29 +281,51 @@ void SpeechRecognizer::stop() {
void SpeechRecognizer::feedTask() {
ThreadManager::printThreadInfo("Feed task started");
int audio_chunksize = afe_handle->get_feed_chunksize(afe_data);
int nch = afe_handle->get_channel_num(afe_data);
size_t samp_len = audio_chunksize;
size_t samp_len_bytes = samp_len * sizeof(int32_t); // 单声道32位
auto *i2s_buff = static_cast<int32_t *>(malloc(samp_len_bytes));
if (!i2s_buff) {
ESP_LOGE("SpeechRecognizer", "Failed to allocate memory for I2S buffer");
const int audio_chunksize = afe_handle->get_feed_chunksize(afe_data);
ESP_LOGW("SpeechRecognizer", "Feed task: audio_chunksize=%d", audio_chunksize);
int nch = afe_handle->get_channel_num(afe_data); // 获取I2S通道的声道数, 此处为1, 因此并没有被下面所使用
const size_t samp_len = audio_chunksize;
const size_t samp_len_bytes = samp_len * sizeof(int32_t); // 单声道32位
// 分配I2S缓冲区 放在PSRAM堆内存中
auto *i2s_buff = static_cast<int32_t *>(heap_caps_malloc((samp_len_bytes), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM));
// 创建I2S转发副本 放在PSRAM堆内存中
auto *raw_pcm16 = static_cast<int16_t *>(heap_caps_malloc(samp_len * sizeof(int16_t), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM));
if (!i2s_buff || !raw_pcm16) {
ESP_LOGE("SpeechRecognizer", "Failed to allocate memory for buffers");
if (i2s_buff) free(i2s_buff);
if (raw_pcm16) free(raw_pcm16);
return;
}
size_t bytes_read;
LatestDataForwarder::getInstance()->initialize(200); // 初始化转发队列,最多缓存 200 帧 I2S 数据
size_t bytes_read; // 读取的字节数
while (tasksRunning) {
esp_err_t ret = i2s_channel_read(rx_handle, i2s_buff, samp_len_bytes, &bytes_read, portMAX_DELAY);
// 读取I2S数据
const esp_err_t ret = i2s_channel_read(rx_handle, i2s_buff, samp_len_bytes, &bytes_read, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE("SpeechRecognizer", "I2S read error: %s", esp_err_to_name(ret));
vTaskDelay(pdMS_TO_TICKS(10));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
// 处理音频数据(32位转16位)
// 一次性处理所有数据转换
for (int i = 0; i < samp_len; ++i) {
i2s_buff[i] = i2s_buff[i] >> 14; // 32:8是有效位,转换为16位音频数据
// 转发数据转换:32位转16位(取高16位)
raw_pcm16[i] = static_cast<int16_t>(i2s_buff[i] >> 16);
// AFE数据转换:右移14位(在原始数据上操作)
i2s_buff[i] = i2s_buff[i] >> 14; // 32:8 是有效位,8:0 是低 8 位,全部为 0,AFE 输入是 16 位语音数据,29:13 位用于放大语音信号。
}
// 转发原始数据
LatestDataForwarder::getInstance()->injectData(raw_pcm16, samp_len);
// 喂数据给AFE
afe_handle->feed(afe_data, reinterpret_cast<int16_t *>(i2s_buff));
// 复制一份到滑动窗口人声检测区 (给网络) 注入音频帧到管理器
// AudioBufferManager::getInstance()->injectAudioFrame(
// reinterpret_cast<int16_t*>(i2s_buff),
// samp_len,
// this->vad_state_
// );
// std::this_thread::sleep_for(std::chrono::milliseconds(5)); // 休眠5ms
}
free(i2s_buff);
ESP_LOGI("SpeechRecognizer", "Feed task exited");
@@ -293,6 +343,8 @@ void SpeechRecognizer::detectTask() {
ESP_LOGI("SpeechRecognizer", "Ready for speech recognition");
while (tasksRunning) {
afe_fetch_result_t* res = afe_handle->fetch(afe_data);
// 从res中取出 vad 状态
this->vad_state_ = res->vad_state;
if (!res || res->ret_value == ESP_FAIL) {
ESP_LOGE("SpeechRecognizer", "AFE fetch error");
vTaskDelay(pdMS_TO_TICKS(10));
@@ -364,10 +416,6 @@ bool SpeechRecognizer::addCommand(int command_id, const std::string& phrase) {
}
// 打印缓存的指令
ESP_LOGI("SpeechRecognizer", "Added command: ID=%d, Phrase=%s", command_id, phrase.c_str());
ESP_LOGI("SpeechRecognizer", "下面是当前已经缓存的指令:");
esp_mn_commands_print();
ESP_LOGI("SpeechRecognizer", "下面是当前已经应用的指令:");
esp_mn_active_commands_print();
return true;
}
@@ -376,6 +424,7 @@ bool SpeechRecognizer::addCommands(const std::vector<std::pair<int, std::string>
for (const auto& cmd : commands) {
if (!addCommand(cmd.first, cmd.second)) {
success = false;
ESP_LOGE("main", "Failed to add some commands");
}
}
ESP_LOGI("SpeechRecognizer", "下面是当前已经缓存的指令:");
@@ -459,6 +508,11 @@ std::string SpeechRecognizer::getCurrentState() const {
return currentState;
}
afe_vad_state_t SpeechRecognizer::getVadState() const {
return vad_state_;
}
bool SpeechRecognizer::isRunning() const {
return running;
}
@@ -63,7 +63,8 @@ public:
// 初始化语音识别系统
bool init(const SpeechRecognizerConfig& config = SpeechRecognizerConfig());
// 重载版本
bool init(const bool enable_vad, const vad_mode_t vad_mode, std::string model_path);
// 反初始化
void deinit();
@@ -106,6 +107,8 @@ public:
// 获取当前识别状态
std::string getCurrentState() const;
// 获取当前 VAD 识别状态(噪音、静音 or 人声) 需要开启 VAD
afe_vad_state_t getVadState() const;
private:
SpeechRecognizer();
~SpeechRecognizer();
@@ -149,7 +152,8 @@ private:
esp_afe_sr_data_t* afe_data;
srmodel_list_t* models;
esp_mn_iface_t* multinet;
model_iface_data_t* model_data;
model_iface_data_t* model_data; /// 模型数据
afe_vad_state_t vad_state_; /// 语音活动检测状态
// 命令回调
SpeechCommandCallback commandCallback;
@@ -0,0 +1,9 @@
//
// Created by misaki on 2025/9/29.
//
#include "VadSlidingWindow.h"
// 静态成员初始化
AudioBufferManager* AudioBufferManager::instance = nullptr;
std::mutex AudioBufferManager::instance_mutex;
@@ -0,0 +1,377 @@
//
// Created by misaki on 2025/9/29.
//
/**
* 本模块用于处理音频数据,使用滑动窗口和VAD算法进行人声语音段过滤
* 依赖于VAD人声检测数据,并通过滑动窗口管理区间数据,以精确过滤出人声音频数据
* @author Misaki
* @date 2025/9/29
*/
#pragma once
#include <vector>
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>
#include <atomic>
// PCM帧数据结构
struct PCMFrame {
std::vector<int16_t> audio_data; // PCM音频数据
size_t data_length; // 数据长度(样本数)
bool vad_status; // VAD检测状态
uint64_t timestamp; // 时间戳(可选,用于调试)
PCMFrame() : data_length(0), vad_status(false), timestamp(0) {}
PCMFrame(const int16_t* data, const size_t len, const bool vad, const uint64_t ts = 0)
: data_length(len), vad_status(vad), timestamp(ts) {
audio_data.assign(data, data + len);
}
};
// 滑动窗口结构
struct SlidingWindow {
std::vector<PCMFrame> frames; // 窗口内的所有帧
size_t total_frames; // 总帧数
size_t voice_frames; // 人声帧数
double voice_ratio; // 人声占比
bool is_active; // 窗口是否处于活跃状态
SlidingWindow() : total_frames(0), voice_frames(0), voice_ratio(0.0), is_active(false) {}
// 计算人声占比
void calculateVoiceRatio() {
if (total_frames > 0) {
voice_ratio = static_cast<double>(voice_frames) / total_frames;
} else {
voice_ratio = 0.0;
}
}
};
class AudioBufferManager {
private:
// 单例实例
static AudioBufferManager* instance;
static std::mutex instance_mutex;
// 配置参数
struct Config {
size_t max_window_frames; // 单个窗口最大帧数
size_t max_queue_size; // 队列最大长度
size_t silence_threshold_frames; // 静音阈值帧数
double voice_ratio_threshold; // 人声占比阈值
size_t pre_voice_frames; // 人声开始前预保留帧数
size_t post_voice_frames; // 人声结束后保留帧数
} config;
// 内部状态
std::unique_ptr<SlidingWindow> current_window;
std::queue<std::unique_ptr<SlidingWindow>> completed_windows;
std::vector<PCMFrame> pre_voice_buffer; // 人声开始前的预缓存
// 状态跟踪
std::atomic<bool> in_voice_segment;
size_t consecutive_silence_frames;
size_t current_frame_count;
// 线程同步
std::mutex data_mutex;
std::condition_variable data_condition;
// 内存使用跟踪
size_t estimated_memory_usage;
const size_t MAX_MEMORY_BYTES = 512 * 1024; // 512KB
private:
AudioBufferManager() {
initializeDefaultConfig();
resetState();
}
void initializeDefaultConfig() {
// 默认配置:基于16kHz采样率,每帧20ms(320样本)
config.max_window_frames = 500; // 10秒音频(500 * 20ms
config.max_queue_size = 8; // 队列最多8个窗口
config.silence_threshold_frames = 15; // 300ms静音判定结束(15 * 20ms
config.voice_ratio_threshold = 0.3; // 30%人声占比阈值
config.pre_voice_frames = 5; // 人声开始前保留100ms
config.post_voice_frames = 10; // 人声结束后保留200ms
estimated_memory_usage = 0;
}
void resetState() {
current_window = std::make_unique<SlidingWindow>();
in_voice_segment = false;
consecutive_silence_frames = 0;
current_frame_count = 0;
pre_voice_buffer.clear();
pre_voice_buffer.reserve(config.pre_voice_frames);
}
// 估算单个帧的内存使用
size_t estimateFrameMemory(const PCMFrame& frame) const {
return sizeof(PCMFrame) + (frame.audio_data.capacity() * sizeof(int16_t));
}
// 估算窗口内存使用
size_t estimateWindowMemory(const SlidingWindow& window) const {
size_t memory = sizeof(SlidingWindow);
for (const auto& frame : window.frames) {
memory += estimateFrameMemory(frame);
}
return memory;
}
// 检查内存限制
bool checkMemoryConstraints() const {
return estimated_memory_usage < MAX_MEMORY_BYTES;
}
public:
// 删除拷贝构造函数和赋值运算符
AudioBufferManager(const AudioBufferManager&) = delete;
AudioBufferManager& operator=(const AudioBufferManager&) = delete;
// 获取单例实例
static AudioBufferManager* getInstance() {
std::lock_guard<std::mutex> lock(instance_mutex);
if (!instance) {
instance = new AudioBufferManager();
}
return instance;
}
/**
* @brief 配置管理器参数
* @param max_window_frames 单个窗口最大帧数
* @param max_queue_size 队列最大长度
* @param silence_threshold 静音阈值帧数
* @param voice_ratio_threshold 人声占比阈值
* @param pre_voice_frames 人声开始前预保留帧数
* @param post_voice_frames 人声结束后保留帧数
*/
void configure(const size_t max_window_frames = 500,
const size_t max_queue_size = 8,
const size_t silence_threshold = 15,
const double voice_ratio_threshold = 0.2,
const size_t pre_voice_frames = 5,
const size_t post_voice_frames = 10) {
std::lock_guard<std::mutex> lock(data_mutex);
config.max_window_frames = max_window_frames;
config.max_queue_size = max_queue_size;
config.silence_threshold_frames = silence_threshold;
config.voice_ratio_threshold = voice_ratio_threshold;
config.pre_voice_frames = pre_voice_frames;
config.post_voice_frames = post_voice_frames;
// 重新初始化状态
resetState();
}
/**
* @brief 注入新的音频帧数据
* @param audio_data PCM音频数据指针
* @param data_length 数据长度(样本数)
* @param vad_status 当前帧的VAD状态
*/
void injectAudioFrame(const int16_t* audio_data, size_t data_length, bool vad_status) {
std::lock_guard<std::mutex> lock(data_mutex);
// 创建新帧
PCMFrame new_frame(audio_data, data_length, vad_status, current_frame_count++);
size_t frame_memory = estimateFrameMemory(new_frame);
// 检查内存限制
if (!checkMemoryConstraints()) {
// 内存不足,采取清理策略
if (!completed_windows.empty()) {
auto old_window = std::move(completed_windows.front());
completed_windows.pop();
estimated_memory_usage -= estimateWindowMemory(*old_window);
}
}
// 更新预缓存
updatePreVoiceBuffer(new_frame);
// 状态机处理
if (!in_voice_segment) {
handleNonVoiceState(new_frame, frame_memory);
} else {
handleVoiceState(new_frame, frame_memory);
}
estimated_memory_usage += frame_memory;
}
/**
* @brief 获取可用的音频窗口数据
* @param timeout_ms 超时时间(毫秒)
* @return 滑动窗口指针,如果没有可用数据则返回nullptr
*/
std::unique_ptr<SlidingWindow> getAudioWindow(int timeout_ms = 0) {
std::unique_lock<std::mutex> lock(data_mutex);
if (completed_windows.empty()) {
if (timeout_ms <= 0) {
return nullptr;
}
// 等待数据可用
if (data_condition.wait_for(lock,
std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) {
return nullptr;
}
if (completed_windows.empty()) {
return nullptr;
}
}
auto window = std::move(completed_windows.front());
completed_windows.pop();
estimated_memory_usage -= estimateWindowMemory(*window);
return window;
}
/**
* @brief 检查是否有可用的音频数据
*/
bool hasAvailableData() {
std::lock_guard<std::mutex> lock(data_mutex);
return !completed_windows.empty();
}
/**
* @brief 获取当前队列大小
*/
size_t getQueueSize() {
std::lock_guard<std::mutex> lock(data_mutex);
return completed_windows.size();
}
/**
* @brief 获取估计的内存使用量
*/
size_t getEstimatedMemoryUsage() const {
return estimated_memory_usage;
}
/**
* @brief 强制结束当前语音段(如果有)
*/
void forceEndCurrentSegment() {
std::lock_guard<std::mutex> lock(data_mutex);
if (in_voice_segment && current_window->total_frames > 0) {
finalizeCurrentWindow();
}
}
/**
* @brief 清空所有缓存数据
*/
void clearAllData() {
std::lock_guard<std::mutex> lock(data_mutex);
resetState();
std::queue<std::unique_ptr<SlidingWindow>> empty_queue;
std::swap(completed_windows, empty_queue);
estimated_memory_usage = 0;
}
private:
// 更新人声开始前的预缓存
void updatePreVoiceBuffer(const PCMFrame& frame) {
pre_voice_buffer.push_back(frame);
// 保持预缓存大小不超过配置值
if (pre_voice_buffer.size() > config.pre_voice_frames) {
pre_voice_buffer.erase(pre_voice_buffer.begin());
}
}
// 处理非人声状态
void handleNonVoiceState(const PCMFrame& frame, size_t frame_memory) {
if (frame.vad_status) {
// 检测到人声开始
in_voice_segment = true;
consecutive_silence_frames = 0;
// 将预缓存数据加入当前窗口
for (const auto& pre_frame : pre_voice_buffer) {
current_window->frames.push_back(pre_frame);
current_window->total_frames++;
if (pre_frame.vad_status) {
current_window->voice_frames++;
}
}
// 添加当前帧
addFrameToCurrentWindow(frame);
}
// 非人声状态下,不进行其他处理
}
// 处理人声状态
void handleVoiceState(const PCMFrame& frame, size_t frame_memory) {
if (frame.vad_status) {
// 仍然是人声,重置静音计数
consecutive_silence_frames = 0;
} else {
// 静音帧
consecutive_silence_frames++;
}
// 添加当前帧到窗口
addFrameToCurrentWindow(frame);
// 检查是否需要结束当前语音段
if (consecutive_silence_frames >= config.silence_threshold_frames ||
current_window->frames.size() >= config.max_window_frames) {
// 添加人声结束后的保留帧
addPostVoiceFrames();
// 完成当前窗口
finalizeCurrentWindow();
}
}
// 添加帧到当前窗口
void addFrameToCurrentWindow(const PCMFrame& frame) {
current_window->frames.push_back(frame);
current_window->total_frames++;
if (frame.vad_status) {
current_window->voice_frames++;
}
current_window->calculateVoiceRatio();
}
// 添加人声结束后的保留帧
void addPostVoiceFrames() {
// 这个函数在实际实现中需要缓存后续的帧
// 简化实现:在当前设计中,我们依赖静音阈值来自然包含结束后的帧
}
// 完成当前窗口的处理
void finalizeCurrentWindow() {
// 计算最终的人声占比
current_window->calculateVoiceRatio();
// 检查人声占比是否达到阈值
if (current_window->voice_ratio >= config.voice_ratio_threshold) {
// 窗口有效,加入队列
if (completed_windows.size() >= config.max_queue_size) {
// 队列已满,移除最旧的数据
auto old_window = std::move(completed_windows.front());
completed_windows.pop();
estimated_memory_usage -= estimateWindowMemory(*old_window);
}
completed_windows.push(std::move(current_window));
data_condition.notify_one(); // 通知等待的消费者
}
// 重置状态,开始新的窗口
resetState();
}
};
+8 -6
View File
@@ -1,8 +1,7 @@
#include "PCM5101.h"
static const char *TAG = "AUDIO PCM5101";
static i2s_chan_handle_t i2s_tx_chan;
i2s_chan_handle_t i2s_tx_chan = NULL;
static i2s_chan_handle_t i2s_rx_chan;
uint8_t Volume = Volume_MAX - 2;
@@ -24,8 +23,8 @@ static esp_err_t bsp_i2s_write(void *audio_buffer, size_t len, size_t *bytes_wri
return i2s_channel_write(i2s_tx_chan, (char *)audio_buffer, len, bytes_written, timeout_ms);
}
static esp_err_t bsp_i2s_reconfig_clk(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch) { // I2S Init
esp_err_t ret = ESP_OK;
esp_err_t bsp_i2s_reconfig_clk(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch) { // I2S Init
esp_err_t ret = ESP_OK;
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(rate),
.slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG((i2s_data_bit_width_t)bits_cfg, ch),
@@ -34,11 +33,11 @@ static esp_err_t bsp_i2s_reconfig_clk(uint32_t rate, uint32_t bits_cfg, i2s_slot
ret |= i2s_channel_disable(i2s_tx_chan);
ret |= i2s_channel_reconfig_std_clock(i2s_tx_chan, &std_cfg.clk_cfg);
ret |= i2s_channel_reconfig_std_slot(i2s_tx_chan, &std_cfg.slot_cfg);
ret |= i2s_channel_enable(i2s_tx_chan);
ret |= i2s_channel_enable(i2s_tx_chan);
return ret;
}
static esp_err_t audio_mute_function(AUDIO_PLAYER_MUTE_SETTING setting) { // audio mute function
static esp_err_t audio_mute_function(AUDIO_PLAYER_MUTE_SETTING setting) { // audio mute function
ESP_LOGI(TAG, "mute setting %d", setting);
return ESP_OK;
}
@@ -214,3 +213,6 @@ void Volume_adjustment(uint8_t Vol) {
Volume = Vol;
ESP_LOGI(TAG, "Volume set to %d", Volume);
}
+9
View File
@@ -57,6 +57,15 @@ uint32_t Music_Elapsed(void);
uint16_t Music_Energy(void);
void Volume_adjustment(uint8_t Volume);
// 供 C++ 层调用的“重新配置时钟”包装
esp_err_t bsp_i2s_reconfig_clk(uint32_t rate,
uint32_t bits_cfg,
i2s_slot_mode_t ch);
// 供 C++ 层直接用的 tx channel 句柄
extern i2s_chan_handle_t i2s_tx_chan;
#ifdef __cplusplus
}
#endif
+5 -5
View File
@@ -239,7 +239,7 @@ int QSPI_Init(void){
.data6_io_num = -1,
.data7_io_num = -1,
.max_transfer_sz = ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE,
.flags = SPICOMMON_BUSFLAG_MASTER,
.flags = SPICOMMON_BUSFLAG_MASTER,
.intr_flags = 0,
};
if(spi_bus_initialize(ESP_PANEL_HOST_SPI_ID_DEFAULT, &host_config, SPI_DMA_CH_AUTO) != ESP_OK){
@@ -252,7 +252,7 @@ int QSPI_Init(void){
.cs_gpio_num = ESP_PANEL_LCD_SPI_IO_CS,
.dc_gpio_num = -1,
.spi_mode = ESP_PANEL_LCD_SPI_MODE,
.pclk_hz = 3 * 1000 * 1000,
.pclk_hz = 3 * 1000 * 1000,
.trans_queue_depth = ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ,
.on_color_trans_done = NULL,
.user_ctx = NULL,
@@ -283,17 +283,17 @@ int QSPI_Init(void){
printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n");
esp_err_t ret;
int lcd_cmd = 0x04;
uint8_t register_data[4];
uint8_t register_data[4];
size_t param_size = sizeof(register_data);
lcd_cmd &= 0xff;
lcd_cmd <<= 8;
lcd_cmd |= LCD_OPCODE_READ_CMD << 24; // Use the read opcode instead of write
ret = esp_lcd_panel_io_rx_param(io_handle, lcd_cmd, register_data, param_size);
ret = esp_lcd_panel_io_rx_param(io_handle, lcd_cmd, register_data, param_size);
if (ret == ESP_OK) {
printf("Register 0x04 data: %02x %02x %02x %02x\n", register_data[0], register_data[1], register_data[2], register_data[3]);
} else {
printf("Failed to read register 0x04, error code: %d\n", ret);
}
}
// panel_io_spi_del(io_handle);
io_config.pclk_hz = ESP_PANEL_LCD_SPI_CLK_HZ;
if(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)ESP_PANEL_HOST_SPI_ID_DEFAULT, &io_config, &io_handle) != ESP_OK){
+3 -3
View File
@@ -33,8 +33,8 @@ extern "C" {
#define ESP_PANEL_HOST_SPI_ID_DEFAULT (SPI2_HOST)
#define ESP_PANEL_LCD_SPI_MODE (0) // 0/1/2/3, typically set to 0
#define ESP_PANEL_LCD_SPI_CLK_HZ (80 * 1000 * 1000) // Should be an integer divisor of 80M, typically set to 40M
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (10) // Typically set to 10
#define ESP_PANEL_LCD_SPI_CLK_HZ (40 * 1000 * 1000) // Should be an integer divisor of 80M, typically set to 40M
#define ESP_PANEL_LCD_SPI_TRANS_QUEUE_SZ (40) // Typically set to 10
#define ESP_PANEL_LCD_SPI_CMD_BITS (32) // Typically set to 32
#define ESP_PANEL_LCD_SPI_PARAM_BITS (8) // Typically set to 8
@@ -51,7 +51,7 @@ extern "C" {
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL (1)
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
#define ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE (2048)
#define ESP_PANEL_HOST_SPI_MAX_TRANSFER_SIZE (8192)
#define LEDC_HS_TIMER LEDC_TIMER_0
#define LEDC_LS_MODE LEDC_LOW_SPEED_MODE
+7 -8
View File
@@ -18,13 +18,12 @@ void example_increase_lvgl_tick(void *arg)
void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
{
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
int offsetx1 = area->x1;
int offsetx2 = area->x2;
int offsety1 = area->y1;
int offsety2 = area->y2;
// copy a buffer's content to a specific area of the display
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 +1, offsety2 + 1, color_map);
// 立即通知LVGL传输开始,使用DMA传输
lv_disp_flush_ready(drv);
// copy a buffer's content to a specific area of the display
// 异步传输数据
esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, color_map);
}
/*Read the touchpad*/
@@ -89,7 +88,7 @@ void LVGL_Init(void)
lv_color_t *buf1 = heap_caps_malloc(LVGL_BUF_LEN * sizeof(lv_color_t), MALLOC_CAP_SPIRAM);
assert(buf1);
lv_color_t *buf2 = heap_caps_malloc(LVGL_BUF_LEN * sizeof(lv_color_t) , MALLOC_CAP_SPIRAM);
lv_color_t *buf2 = heap_caps_malloc(LVGL_BUF_LEN * sizeof(lv_color_t) , MALLOC_CAP_SPIRAM);
assert(buf2);
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, LVGL_BUF_LEN); // initialize LVGL draw buffers
@@ -119,7 +118,7 @@ void LVGL_Init(void)
.callback = &example_increase_lvgl_tick,
.name = "lvgl_tick"
};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
+1 -1
View File
@@ -15,7 +15,7 @@ extern "C" {
#define LVGL_BUF_LEN (EXAMPLE_LCD_WIDTH * EXAMPLE_LCD_HEIGHT / 20)
#define LVGL_BUF_LEN (EXAMPLE_LCD_WIDTH * EXAMPLE_LCD_HEIGHT / 8) // 1 byte per pixel
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
extern lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
+2 -2
View File
@@ -9,10 +9,10 @@ uint32_t Flash_Size = 0;
uint32_t SDCard_Size = 0;
esp_err_t s_example_write_file(const char *path, char *data)
esp_err_t s_example_write_file(const char *path, const char *data, const char *type)
{
ESP_LOGI(SD_TAG, "Opening file %s", path);
FILE *f = fopen(path, "w");
FILE *f = fopen(path, type);
if (f == NULL) {
ESP_LOGE(SD_TAG, "Failed to open file for writing");
return ESP_FAIL;
+1 -1
View File
@@ -30,7 +30,7 @@ extern "C" {
esp_err_t SD_Card_CS_EN(void);
esp_err_t SD_Card_CS_Dis(void);
esp_err_t s_example_write_file(const char *path, char *data);
esp_err_t s_example_write_file(const char *path, const char *data, const char *type);
esp_err_t s_example_read_file(const char *path);
extern uint32_t SDCard_Size;
+2 -2
View File
@@ -102,7 +102,7 @@ uint16_t WIFI_Scan(void)
return ap_count;
}
/*
#define GATTC_TAG "GATTC_TAG"
#define SCAN_DURATION 5
#define MAX_DISCOVERED_DEVICES 100
@@ -266,7 +266,7 @@ uint16_t BLE_Scan(void)
Scan_finish = 1;
return BLE_NUM;
}
*/
// 下面是新增的实现
static EventGroupHandle_t s_wifi_event_group;
+3 -3
View File
@@ -12,9 +12,9 @@ extern "C" {
#include <stdio.h>
#include <string.h> // For memcpy
#include "esp_system.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_bt_main.h"
// #include "esp_bt.h"
// #include "esp_gap_ble_api.h"
// #include "esp_bt_main.h"
// WiFi AP信息结构体
typedef struct {
+85
View File
@@ -306,4 +306,89 @@ extern "C" void app_main() {
}
}
}
```
```c++
// 有关lvgl_cpp的部分控件使用
/* LVGL 已经初始化,屏幕驱动已注册 */
auto scr = lvgl_cpp::Screen{}; // RAII,离开作用域自动 del
lv_scr_load(scr.raw()); // 让 LVGL 把它当活动屏幕
lvgl_cpp::Image img(scr);
img.bin("pic_no_alp_swap.bin", 720, 720)
.center();
/* 1. 创建按钮 */
/* 1. 黑色文字样式 */
static lvgl_cpp::Style txt_style;
txt_style.text_color(lv_color_black());
/* 2. 按钮 */
lvgl_cpp::Button btn{scr};
btn.size(150, 60).pos(40, 40);
/* 3. 先创建 Label 对象并保存,再链式调 */
lvgl_cpp::Label lbl{btn}; // 一定要存实例
lbl.text("Click Me")
.add_style(&txt_style.s, LV_PART_MAIN); // 样式作用到文字本身
/* 3. 注册点击事件 */
btn.on(LV_EVENT_CLICKED, [](lv_event_t*){
lvgl_cpp::Toast::show("Saved successfully !");
/* 2. 警告,3 s,顶部 */
lvgl_cpp::Toast::show("SD card missing", lvgl_cpp::Toast::Type::WARN, 3000, LV_ALIGN_TOP_MID, 20);
/* 3. 错误,1.5 s,底部右侧 */
lvgl_cpp::Toast::show("Network error", lvgl_cpp::Toast::Type::ERROR, 1500, LV_ALIGN_BOTTOM_RIGHT, -30);
ESP_LOGI("BTN", "pressed");
});
/* 1. 消息框 */
const char* btns[] = {"Yes", "No", ""};
auto mbox = lvgl_cpp::MsgBox::create("Hint", "Delete file ?", btns);
/* 3. 进度条(双向 + 动画) */
lvgl_cpp::Bar bar(scr);
bar.range(0, 100)
.start_value(20) // 左端
.value(80, LV_ANIM_ON) // 右端带动画
.anim_time(500)
.size(200, 15)
.align(LV_ALIGN_CENTER, nullptr, 0, 40);
/* 4. 折线:画一个 △ */
std::vector<lv_point_t> triangle = {{0,0}, {40,0}, {20,40}, {0,0}};
lvgl_cpp::Line line(scr);
line.points(triangle)
.y_invert(false)
.align(LV_ALIGN_CENTER, nullptr, 0, 100);
lvgl_cpp::Battery bat(scr);
bat.size(60, 30) // 手机经典尺寸
.percent(true) // 显示 50%
.onRead([]() -> uint8_t { // 替换成你的 ADC/INA219 回调
static uint8_t v = 100;
if (v) --v;
return v;
})
.align(LV_ALIGN_TOP_RIGHT, -10, 10); // 九宫格对齐
/* 3. 日期时间 */
lvgl_cpp::DateTime dt(scr);
dt.format("%m/%d %a %H:%M")
.onRead([](char* buf, size_t len){
/* 这里用 SNTP / RTC 填充,示例直接给假时间 */
snprintf(buf, len, "06/25 Tue 14:30");
})
.align(LV_ALIGN_BOTTOM_MID, nullptr, 0, -10);
lvgl_cpp::ColorPicker cp(scr);
cp.size(120, 120)
.align(LV_ALIGN_BOTTOM_MID, nullptr, 0, -20)
.on(LV_EVENT_VALUE_CHANGED, [&](lv_event_t*){
lv_color_t c = cp.color();
ESP_LOGI("CP", "rgb=%d,%d,%d", c.ch.red, c.ch.green_h, c.ch.blue);
});
```
+11 -4
View File
@@ -1,10 +1,9 @@
#include <stdio.h>
#include <esp_log.h>
#include <nvs.h>
#include <nvs_flash.h>
#include "err_handle.h"
#include "drivers_test.h"
#include "CppHandle.h"
@@ -34,9 +33,17 @@ void app_main(void)
// mic_speech_and_gif_and_music_test();
// 初始化NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
Cpp_Hand();
ESP_GOTO(err);
err:
ESP_LOGI("app_main", "app_main error");
ESP_LOGE("app_main", "app_main error");
}
+4
View File
@@ -38,10 +38,13 @@ idf_component_register(SRCS "Bionic_sphere.c"
"../Bionic_Core/ToolsClass/ToolsClass.cpp" # 工具类库
"../Bionic_Core/ToolsClass/AudioOutput/AudioOutput.cpp" # 音频输出类库
"../Bionic_Core/ToolsClass/LVGL_Render/LVGLRender.cpp" # LVGL渲染类库
"../Bionic_Core/ToolsClass/LVGL_Render/LvppApp/BaseApp.cpp"
"../Bionic_Core/ToolsClass/LVGL_Render/Lvpp/SiYuanHeiTiGoogleBan.c" # 中文字体库
"../Bionic_Core/ToolsClass/LVGL_Render/Lvpp/lvpp.cpp"
"../Bionic_Core/ToolsClass/SDFileManager/SDFileManager.cpp" # SD文件管理类库
"../Bionic_Core/ToolsClass/SpeechRecognizer/SpeechRecognizer.cpp" # 语音识别类库
"../Bionic_Core/ToolsClass/SpeechRecognizer/VadSlidingWindow.cpp"
"../Bionic_Core/ToolsClass/SpeechRecognizer/SimpleI2SForwarder.cpp"
"../Bionic_Core/ToolsClass/WifiConnectors/WifiConnectors.cpp" # WIFI连接类库
"../Bionic_Core/ToolsClass/ThreadManager/ThreadManager.cpp" # 线程管理类库
"../Bionic_Core/ToolsClass/Sys_Config/sys_conf_singleton.cpp" # 系统配置类库
@@ -78,6 +81,7 @@ idf_component_register(SRCS "Bionic_sphere.c"
"../Bionic_Core/ToolsClass"
"../Bionic_Core/ToolsClass/AudioOutput"
"../Bionic_Core/ToolsClass/LVGL_Render"
"../Bionic_Core/ToolsClass/LVGL_Render/LvppApp"
"../Bionic_Core/ToolsClass/LVGL_Render/Lvpp"
"../Bionic_Core/ToolsClass/SDFileManager"
"../Bionic_Core/ToolsClass/SpeechRecognizer"
+36 -549
View File
@@ -766,9 +766,9 @@ CONFIG_CN_SPEECH_COMMAND_ID199=""
#
# Compiler options
#
CONFIG_COMPILER_OPTIMIZATION_DEBUG=y
# CONFIG_COMPILER_OPTIMIZATION_DEBUG is not set
# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set
# CONFIG_COMPILER_OPTIMIZATION_PERF is not set
CONFIG_COMPILER_OPTIMIZATION_PERF=y
# CONFIG_COMPILER_OPTIMIZATION_NONE is not set
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set
@@ -814,334 +814,10 @@ CONFIG_APPTRACE_LOCK_ENABLE=y
#
# Bluetooth
#
CONFIG_BT_ENABLED=y
CONFIG_BT_BLUEDROID_ENABLED=y
# CONFIG_BT_NIMBLE_ENABLED is not set
# CONFIG_BT_CONTROLLER_ONLY is not set
CONFIG_BT_CONTROLLER_ENABLED=y
# CONFIG_BT_CONTROLLER_DISABLED is not set
#
# Bluedroid Options
#
CONFIG_BT_BTC_TASK_STACK_SIZE=3072
CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y
# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set
CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0
CONFIG_BT_BTU_TASK_STACK_SIZE=4352
# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set
CONFIG_BT_BLUEDROID_ESP_COEX_VSC=y
CONFIG_BT_BLE_ENABLED=y
CONFIG_BT_GATTS_ENABLE=y
# CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set
# CONFIG_BT_BLE_BLUFI_ENABLE is not set
CONFIG_BT_GATT_MAX_SR_PROFILES=8
CONFIG_BT_GATT_MAX_SR_ATTRIBUTES=100
# CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set
CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y
CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0
# CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set
# CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set
# CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set
CONFIG_BT_GATTC_ENABLE=y
CONFIG_BT_GATTC_MAX_CACHE_CHAR=40
CONFIG_BT_GATTC_NOTIF_REG_MAX=5
# CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set
CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3
CONFIG_BT_BLE_SMP_ENABLE=y
# CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set
# CONFIG_BT_BLE_SMP_ID_RESET_ENABLE is not set
# CONFIG_BT_STACK_NO_LOG is not set
#
# BT DEBUG LOG LEVEL
#
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_HCI_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_HCI_TRACE_LEVEL=2
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BTM_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BTM_TRACE_LEVEL=2
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_L2CAP_TRACE_LEVEL=2
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL=2
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_SDP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_SDP_TRACE_LEVEL=2
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_GAP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_GAP_TRACE_LEVEL=2
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BNEP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BNEP_TRACE_LEVEL=2
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_PAN_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_PAN_TRACE_LEVEL=2
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_A2D_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_A2D_TRACE_LEVEL=2
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_AVDT_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_AVDT_TRACE_LEVEL=2
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_AVCT_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_AVCT_TRACE_LEVEL=2
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_AVRC_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_AVRC_TRACE_LEVEL=2
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_MCA_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_MCA_TRACE_LEVEL=2
# CONFIG_BT_LOG_HID_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_HID_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_HID_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_HID_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_HID_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_HID_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_HID_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_HID_TRACE_LEVEL=2
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_APPL_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_APPL_TRACE_LEVEL=2
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_GATT_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_GATT_TRACE_LEVEL=2
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_SMP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_SMP_TRACE_LEVEL=2
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BTIF_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BTIF_TRACE_LEVEL=2
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BTC_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BTC_TRACE_LEVEL=2
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_OSI_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_OSI_TRACE_LEVEL=2
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BLUFI_TRACE_LEVEL=2
# end of BT DEBUG LOG LEVEL
CONFIG_BT_ACL_CONNECTIONS=4
CONFIG_BT_MULTI_CONNECTION_ENBALE=y
# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set
# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set
# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set
CONFIG_BT_SMP_ENABLE=y
CONFIG_BT_SMP_MAX_BONDS=15
# CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set
CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30
CONFIG_BT_MAX_DEVICE_NAME_LEN=32
CONFIG_BT_BLE_RPA_TIMEOUT=900
CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
# CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set
# CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set
# end of Bluedroid Options
#
# Controller Options
#
CONFIG_BT_CTRL_MODE_EFF=1
CONFIG_BT_CTRL_BLE_MAX_ACT=6
CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=6
CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0
CONFIG_BT_CTRL_PINNED_TO_CORE_0=y
# CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set
CONFIG_BT_CTRL_PINNED_TO_CORE=0
CONFIG_BT_CTRL_HCI_MODE_VHCI=y
# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set
CONFIG_BT_CTRL_HCI_TL=1
CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30
CONFIG_BT_BLE_CCA_MODE_NONE=y
# CONFIG_BT_BLE_CCA_MODE_HW is not set
# CONFIG_BT_BLE_CCA_MODE_SW is not set
CONFIG_BT_BLE_CCA_MODE=0
CONFIG_BT_CTRL_HW_CCA_VAL=20
CONFIG_BT_CTRL_HW_CCA_EFF=0
CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y
# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set
# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set
CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0
CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y
# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set
CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0
CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y
# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set
CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set
CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9=y
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P20 is not set
CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=11
CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y
CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100
CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20
CONFIG_BT_CTRL_BLE_SCAN_DUPL=y
CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE=y
# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA is not set
# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE is not set
CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0
CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100
CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD=0
# CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN is not set
# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set
CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y
CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0
#
# MODEM SLEEP Options
#
# CONFIG_BT_CTRL_MODEM_SLEEP is not set
# end of MODEM SLEEP Options
CONFIG_BT_CTRL_SLEEP_MODE_EFF=0
CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0
CONFIG_BT_CTRL_HCI_TL_EFF=1
# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set
# CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set
# CONFIG_BT_BLE_ADV_DATA_LENGTH_ZERO_AUX is not set
CONFIG_BT_CTRL_CHAN_ASS_EN=y
CONFIG_BT_CTRL_LE_PING_EN=y
#
# BLE disconnect when instant passed
#
# CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE is not set
# CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE is not set
# CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE is not set
# end of BLE disconnect when instant passed
# CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY is not set
# end of Controller Options
#
# Common Options
#
# CONFIG_BT_ENABLED is not set
CONFIG_BT_ALARM_MAX_NUM=50
# end of Common Options
# CONFIG_BT_HCI_LOG_DEBUG_EN is not set
# end of Bluetooth
# CONFIG_BLE_MESH is not set
#
# Console Library
#
@@ -1248,8 +924,7 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y
# Wireless Coexistence
#
CONFIG_ESP_COEX_ENABLED=y
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y
# CONFIG_ESP_COEX_POWER_MANAGEMENT is not set
# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set
# CONFIG_ESP_COEX_GPIO_DEBUG is not set
# end of Wireless Coexistence
@@ -1257,6 +932,7 @@ CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y
# Common ESP-related
#
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
# end of Common ESP-related
#
@@ -1328,7 +1004,7 @@ CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y
#
# ESP-Driver:SPI Configurations
#
# CONFIG_SPI_MASTER_IN_IRAM is not set
CONFIG_SPI_MASTER_IN_IRAM=y
CONFIG_SPI_MASTER_ISR_IN_IRAM=y
# CONFIG_SPI_SLAVE_IN_IRAM is not set
CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
@@ -1510,6 +1186,7 @@ CONFIG_XTAL_FREQ=40
# end of Main XTAL Config
CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y
CONFIG_ESP_SPI_BUS_LOCK_FUNCS_IN_IRAM=y
# end of Hardware Settings
#
@@ -1597,15 +1274,14 @@ CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_SPEED=80
# CONFIG_SPIRAM_ECC_ENABLE is not set
CONFIG_SPIRAM_BOOT_INIT=y
# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
# CONFIG_SPIRAM_USE_MEMMAP is not set
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
# end of SPI RAM config
# end of ESP PSRAM
@@ -1637,13 +1313,12 @@ CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8
CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y
CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32
# CONFIG_ESP32S3_DATA_CACHE_16KB is not set
CONFIG_ESP32S3_DATA_CACHE_32KB=y
# CONFIG_ESP32S3_DATA_CACHE_64KB is not set
CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000
# CONFIG_ESP32S3_DATA_CACHE_32KB is not set
CONFIG_ESP32S3_DATA_CACHE_64KB=y
CONFIG_ESP32S3_DATA_CACHE_SIZE=0x10000
# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set
CONFIG_ESP32S3_DATA_CACHE_8WAYS=y
CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8
# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set
CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y
# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set
CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32
@@ -1758,11 +1433,11 @@ CONFIG_ESP_TIMER_IMPL_SYSTIMER=y
# Wi-Fi
#
CONFIG_ESP_WIFI_ENABLED=y
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=2
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=4
CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=32
CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y
# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set
@@ -1770,9 +1445,9 @@ CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0
CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5
# CONFIG_ESP_WIFI_CSI_ENABLED is not set
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP_WIFI_TX_BA_WIN=6
CONFIG_ESP_WIFI_TX_BA_WIN=2
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP_WIFI_RX_BA_WIN=6
CONFIG_ESP_WIFI_RX_BA_WIN=2
# CONFIG_ESP_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP_WIFI_NVS_ENABLED=y
CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y
@@ -1916,7 +1591,6 @@ CONFIG_FREERTOS_RUN_TIME_COUNTER_TYPE_U32=y
#
# Port
#
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y
# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set
@@ -2077,6 +1751,7 @@ CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4
CONFIG_LWIP_TCP_OVERSIZE_MSS=y
# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set
# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set
# CONFIG_LWIP_WND_SCALE is not set
CONFIG_LWIP_TCP_RTO_TIME=1500
# end of TCP
@@ -2608,10 +2283,6 @@ CONFIG_WL_SECTOR_SIZE=4096
#
CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16
CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30
# CONFIG_WIFI_PROV_BLE_BONDING is not set
# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set
# CONFIG_WIFI_PROV_BLE_NOTIFY is not set
# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set
CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y
# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set
# end of Wi-Fi Provisioning Manager
@@ -2680,8 +2351,8 @@ CONFIG_LV_MEM_BUF_MAX_NUM=16
#
# HAL Settings
#
CONFIG_LV_DISP_DEF_REFR_PERIOD=30
CONFIG_LV_INDEV_DEF_READ_PERIOD=30
CONFIG_LV_DISP_DEF_REFR_PERIOD=10
CONFIG_LV_INDEV_DEF_READ_PERIOD=10
# CONFIG_LV_TICK_CUSTOM is not set
CONFIG_LV_DPI_DEF=130
# end of HAL Settings
@@ -2694,10 +2365,10 @@ CONFIG_LV_DPI_DEF=130
# Drawing
#
CONFIG_LV_DRAW_COMPLEX=y
CONFIG_LV_SHADOW_CACHE_SIZE=0
CONFIG_LV_SHADOW_CACHE_SIZE=4
CONFIG_LV_CIRCLE_CACHE_SIZE=4
CONFIG_LV_LAYER_SIMPLE_BUF_SIZE=24576
CONFIG_LV_IMG_CACHE_DEF_SIZE=0
CONFIG_LV_LAYER_SIMPLE_BUF_SIZE=10240
CONFIG_LV_IMG_CACHE_DEF_SIZE=128
CONFIG_LV_GRADIENT_MAX_STOPS=2
CONFIG_LV_GRAD_CACHE_DEF_SIZE=0
# CONFIG_LV_DITHER_GRADIENT is not set
@@ -2727,9 +2398,9 @@ CONFIG_LV_DISP_ROT_MAX_BUF=10240
#
CONFIG_LV_USE_ASSERT_NULL=y
CONFIG_LV_USE_ASSERT_MALLOC=y
# CONFIG_LV_USE_ASSERT_STYLE is not set
CONFIG_LV_USE_ASSERT_STYLE=y
# CONFIG_LV_USE_ASSERT_MEM_INTEGRITY is not set
# CONFIG_LV_USE_ASSERT_OBJ is not set
CONFIG_LV_USE_ASSERT_OBJ=y
CONFIG_LV_ASSERT_HANDLER_INCLUDE="assert.h"
# end of Asserts
@@ -2990,9 +2661,9 @@ CONFIG_LOG_BOOTLOADER_LEVEL=3
CONFIG_FLASHMODE_DIO=y
# CONFIG_FLASHMODE_DOUT is not set
CONFIG_MONITOR_BAUD=115200
CONFIG_OPTIMIZATION_LEVEL_DEBUG=y
CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y
CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y
# CONFIG_OPTIMIZATION_LEVEL_DEBUG is not set
# CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set
# CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set
# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set
# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set
CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
@@ -3009,192 +2680,8 @@ CONFIG_STACK_CHECK_NONE=y
# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set
CONFIG_ESP32_APPTRACE_DEST_NONE=y
CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
CONFIG_BLUEDROID_ENABLED=y
# CONFIG_NIMBLE_ENABLED is not set
CONFIG_BTC_TASK_STACK_SIZE=3072
CONFIG_BLUEDROID_PINNED_TO_CORE_0=y
# CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set
CONFIG_BLUEDROID_PINNED_TO_CORE=0
CONFIG_BTU_TASK_STACK_SIZE=4352
# CONFIG_BLUEDROID_MEM_DEBUG is not set
CONFIG_GATTS_ENABLE=y
# CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set
CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y
CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0
CONFIG_GATTC_ENABLE=y
# CONFIG_GATTC_CACHE_NVS_FLASH is not set
CONFIG_BLE_SMP_ENABLE=y
# CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set
# CONFIG_HCI_TRACE_LEVEL_NONE is not set
# CONFIG_HCI_TRACE_LEVEL_ERROR is not set
CONFIG_HCI_TRACE_LEVEL_WARNING=y
# CONFIG_HCI_TRACE_LEVEL_API is not set
# CONFIG_HCI_TRACE_LEVEL_EVENT is not set
# CONFIG_HCI_TRACE_LEVEL_DEBUG is not set
# CONFIG_HCI_TRACE_LEVEL_VERBOSE is not set
CONFIG_HCI_INITIAL_TRACE_LEVEL=2
# CONFIG_BTM_TRACE_LEVEL_NONE is not set
# CONFIG_BTM_TRACE_LEVEL_ERROR is not set
CONFIG_BTM_TRACE_LEVEL_WARNING=y
# CONFIG_BTM_TRACE_LEVEL_API is not set
# CONFIG_BTM_TRACE_LEVEL_EVENT is not set
# CONFIG_BTM_TRACE_LEVEL_DEBUG is not set
# CONFIG_BTM_TRACE_LEVEL_VERBOSE is not set
CONFIG_BTM_INITIAL_TRACE_LEVEL=2
# CONFIG_L2CAP_TRACE_LEVEL_NONE is not set
# CONFIG_L2CAP_TRACE_LEVEL_ERROR is not set
CONFIG_L2CAP_TRACE_LEVEL_WARNING=y
# CONFIG_L2CAP_TRACE_LEVEL_API is not set
# CONFIG_L2CAP_TRACE_LEVEL_EVENT is not set
# CONFIG_L2CAP_TRACE_LEVEL_DEBUG is not set
# CONFIG_L2CAP_TRACE_LEVEL_VERBOSE is not set
CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2
# CONFIG_RFCOMM_TRACE_LEVEL_NONE is not set
# CONFIG_RFCOMM_TRACE_LEVEL_ERROR is not set
CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y
# CONFIG_RFCOMM_TRACE_LEVEL_API is not set
# CONFIG_RFCOMM_TRACE_LEVEL_EVENT is not set
# CONFIG_RFCOMM_TRACE_LEVEL_DEBUG is not set
# CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE is not set
CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2
# CONFIG_SDP_TRACE_LEVEL_NONE is not set
# CONFIG_SDP_TRACE_LEVEL_ERROR is not set
CONFIG_SDP_TRACE_LEVEL_WARNING=y
# CONFIG_SDP_TRACE_LEVEL_API is not set
# CONFIG_SDP_TRACE_LEVEL_EVENT is not set
# CONFIG_SDP_TRACE_LEVEL_DEBUG is not set
# CONFIG_SDP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BTH_LOG_SDP_INITIAL_TRACE_LEVEL=2
# CONFIG_GAP_TRACE_LEVEL_NONE is not set
# CONFIG_GAP_TRACE_LEVEL_ERROR is not set
CONFIG_GAP_TRACE_LEVEL_WARNING=y
# CONFIG_GAP_TRACE_LEVEL_API is not set
# CONFIG_GAP_TRACE_LEVEL_EVENT is not set
# CONFIG_GAP_TRACE_LEVEL_DEBUG is not set
# CONFIG_GAP_TRACE_LEVEL_VERBOSE is not set
CONFIG_GAP_INITIAL_TRACE_LEVEL=2
CONFIG_BNEP_INITIAL_TRACE_LEVEL=2
# CONFIG_PAN_TRACE_LEVEL_NONE is not set
# CONFIG_PAN_TRACE_LEVEL_ERROR is not set
CONFIG_PAN_TRACE_LEVEL_WARNING=y
# CONFIG_PAN_TRACE_LEVEL_API is not set
# CONFIG_PAN_TRACE_LEVEL_EVENT is not set
# CONFIG_PAN_TRACE_LEVEL_DEBUG is not set
# CONFIG_PAN_TRACE_LEVEL_VERBOSE is not set
CONFIG_PAN_INITIAL_TRACE_LEVEL=2
# CONFIG_A2D_TRACE_LEVEL_NONE is not set
# CONFIG_A2D_TRACE_LEVEL_ERROR is not set
CONFIG_A2D_TRACE_LEVEL_WARNING=y
# CONFIG_A2D_TRACE_LEVEL_API is not set
# CONFIG_A2D_TRACE_LEVEL_EVENT is not set
# CONFIG_A2D_TRACE_LEVEL_DEBUG is not set
# CONFIG_A2D_TRACE_LEVEL_VERBOSE is not set
CONFIG_A2D_INITIAL_TRACE_LEVEL=2
# CONFIG_AVDT_TRACE_LEVEL_NONE is not set
# CONFIG_AVDT_TRACE_LEVEL_ERROR is not set
CONFIG_AVDT_TRACE_LEVEL_WARNING=y
# CONFIG_AVDT_TRACE_LEVEL_API is not set
# CONFIG_AVDT_TRACE_LEVEL_EVENT is not set
# CONFIG_AVDT_TRACE_LEVEL_DEBUG is not set
# CONFIG_AVDT_TRACE_LEVEL_VERBOSE is not set
CONFIG_AVDT_INITIAL_TRACE_LEVEL=2
# CONFIG_AVCT_TRACE_LEVEL_NONE is not set
# CONFIG_AVCT_TRACE_LEVEL_ERROR is not set
CONFIG_AVCT_TRACE_LEVEL_WARNING=y
# CONFIG_AVCT_TRACE_LEVEL_API is not set
# CONFIG_AVCT_TRACE_LEVEL_EVENT is not set
# CONFIG_AVCT_TRACE_LEVEL_DEBUG is not set
# CONFIG_AVCT_TRACE_LEVEL_VERBOSE is not set
CONFIG_AVCT_INITIAL_TRACE_LEVEL=2
# CONFIG_AVRC_TRACE_LEVEL_NONE is not set
# CONFIG_AVRC_TRACE_LEVEL_ERROR is not set
CONFIG_AVRC_TRACE_LEVEL_WARNING=y
# CONFIG_AVRC_TRACE_LEVEL_API is not set
# CONFIG_AVRC_TRACE_LEVEL_EVENT is not set
# CONFIG_AVRC_TRACE_LEVEL_DEBUG is not set
# CONFIG_AVRC_TRACE_LEVEL_VERBOSE is not set
CONFIG_AVRC_INITIAL_TRACE_LEVEL=2
# CONFIG_MCA_TRACE_LEVEL_NONE is not set
# CONFIG_MCA_TRACE_LEVEL_ERROR is not set
CONFIG_MCA_TRACE_LEVEL_WARNING=y
# CONFIG_MCA_TRACE_LEVEL_API is not set
# CONFIG_MCA_TRACE_LEVEL_EVENT is not set
# CONFIG_MCA_TRACE_LEVEL_DEBUG is not set
# CONFIG_MCA_TRACE_LEVEL_VERBOSE is not set
CONFIG_MCA_INITIAL_TRACE_LEVEL=2
# CONFIG_HID_TRACE_LEVEL_NONE is not set
# CONFIG_HID_TRACE_LEVEL_ERROR is not set
CONFIG_HID_TRACE_LEVEL_WARNING=y
# CONFIG_HID_TRACE_LEVEL_API is not set
# CONFIG_HID_TRACE_LEVEL_EVENT is not set
# CONFIG_HID_TRACE_LEVEL_DEBUG is not set
# CONFIG_HID_TRACE_LEVEL_VERBOSE is not set
CONFIG_HID_INITIAL_TRACE_LEVEL=2
# CONFIG_APPL_TRACE_LEVEL_NONE is not set
# CONFIG_APPL_TRACE_LEVEL_ERROR is not set
CONFIG_APPL_TRACE_LEVEL_WARNING=y
# CONFIG_APPL_TRACE_LEVEL_API is not set
# CONFIG_APPL_TRACE_LEVEL_EVENT is not set
# CONFIG_APPL_TRACE_LEVEL_DEBUG is not set
# CONFIG_APPL_TRACE_LEVEL_VERBOSE is not set
CONFIG_APPL_INITIAL_TRACE_LEVEL=2
# CONFIG_GATT_TRACE_LEVEL_NONE is not set
# CONFIG_GATT_TRACE_LEVEL_ERROR is not set
CONFIG_GATT_TRACE_LEVEL_WARNING=y
# CONFIG_GATT_TRACE_LEVEL_API is not set
# CONFIG_GATT_TRACE_LEVEL_EVENT is not set
# CONFIG_GATT_TRACE_LEVEL_DEBUG is not set
# CONFIG_GATT_TRACE_LEVEL_VERBOSE is not set
CONFIG_GATT_INITIAL_TRACE_LEVEL=2
# CONFIG_SMP_TRACE_LEVEL_NONE is not set
# CONFIG_SMP_TRACE_LEVEL_ERROR is not set
CONFIG_SMP_TRACE_LEVEL_WARNING=y
# CONFIG_SMP_TRACE_LEVEL_API is not set
# CONFIG_SMP_TRACE_LEVEL_EVENT is not set
# CONFIG_SMP_TRACE_LEVEL_DEBUG is not set
# CONFIG_SMP_TRACE_LEVEL_VERBOSE is not set
CONFIG_SMP_INITIAL_TRACE_LEVEL=2
# CONFIG_BTIF_TRACE_LEVEL_NONE is not set
# CONFIG_BTIF_TRACE_LEVEL_ERROR is not set
CONFIG_BTIF_TRACE_LEVEL_WARNING=y
# CONFIG_BTIF_TRACE_LEVEL_API is not set
# CONFIG_BTIF_TRACE_LEVEL_EVENT is not set
# CONFIG_BTIF_TRACE_LEVEL_DEBUG is not set
# CONFIG_BTIF_TRACE_LEVEL_VERBOSE is not set
CONFIG_BTIF_INITIAL_TRACE_LEVEL=2
# CONFIG_BTC_TRACE_LEVEL_NONE is not set
# CONFIG_BTC_TRACE_LEVEL_ERROR is not set
CONFIG_BTC_TRACE_LEVEL_WARNING=y
# CONFIG_BTC_TRACE_LEVEL_API is not set
# CONFIG_BTC_TRACE_LEVEL_EVENT is not set
# CONFIG_BTC_TRACE_LEVEL_DEBUG is not set
# CONFIG_BTC_TRACE_LEVEL_VERBOSE is not set
CONFIG_BTC_INITIAL_TRACE_LEVEL=2
# CONFIG_OSI_TRACE_LEVEL_NONE is not set
# CONFIG_OSI_TRACE_LEVEL_ERROR is not set
CONFIG_OSI_TRACE_LEVEL_WARNING=y
# CONFIG_OSI_TRACE_LEVEL_API is not set
# CONFIG_OSI_TRACE_LEVEL_EVENT is not set
# CONFIG_OSI_TRACE_LEVEL_DEBUG is not set
# CONFIG_OSI_TRACE_LEVEL_VERBOSE is not set
CONFIG_OSI_INITIAL_TRACE_LEVEL=2
# CONFIG_BLUFI_TRACE_LEVEL_NONE is not set
# CONFIG_BLUFI_TRACE_LEVEL_ERROR is not set
CONFIG_BLUFI_TRACE_LEVEL_WARNING=y
# CONFIG_BLUFI_TRACE_LEVEL_API is not set
# CONFIG_BLUFI_TRACE_LEVEL_EVENT is not set
# CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set
# CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set
CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2
# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set
CONFIG_SMP_ENABLE=y
# CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY is not set
CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30
# CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EN is not set
CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS=y
CONFIG_SW_COEXIST_ENABLE=y
CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y
CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y
# CONFIG_EXTERNAL_COEX_ENABLE is not set
# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set
# CONFIG_MCPWM_ISR_IN_IRAM is not set
# CONFIG_EVENT_LOOP_PROFILING is not set
CONFIG_POST_EVENTS_FROM_ISR=y
@@ -3267,19 +2754,19 @@ CONFIG_ESP32S3_BROWNOUT_DET_LVL=7
CONFIG_IPC_TASK_STACK_SIZE=1280
CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_ESP32_WIFI_ENABLED=y
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=2
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=4
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_CSI_ENABLED is not set
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=6
CONFIG_ESP32_WIFI_TX_BA_WIN=2
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_RX_BA_WIN=6
CONFIG_ESP32_WIFI_RX_BA_WIN=6
CONFIG_ESP32_WIFI_RX_BA_WIN=2
CONFIG_ESP32_WIFI_RX_BA_WIN=2
# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
+34 -547
View File
@@ -766,9 +766,9 @@ CONFIG_CN_SPEECH_COMMAND_ID199=""
#
# Compiler options
#
CONFIG_COMPILER_OPTIMIZATION_DEBUG=y
# CONFIG_COMPILER_OPTIMIZATION_DEBUG is not set
# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set
# CONFIG_COMPILER_OPTIMIZATION_PERF is not set
CONFIG_COMPILER_OPTIMIZATION_PERF=y
# CONFIG_COMPILER_OPTIMIZATION_NONE is not set
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set
@@ -814,334 +814,10 @@ CONFIG_APPTRACE_LOCK_ENABLE=y
#
# Bluetooth
#
CONFIG_BT_ENABLED=y
CONFIG_BT_BLUEDROID_ENABLED=y
# CONFIG_BT_NIMBLE_ENABLED is not set
# CONFIG_BT_CONTROLLER_ONLY is not set
CONFIG_BT_CONTROLLER_ENABLED=y
# CONFIG_BT_CONTROLLER_DISABLED is not set
#
# Bluedroid Options
#
CONFIG_BT_BTC_TASK_STACK_SIZE=3072
CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y
# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set
CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0
CONFIG_BT_BTU_TASK_STACK_SIZE=4352
# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set
CONFIG_BT_BLUEDROID_ESP_COEX_VSC=y
CONFIG_BT_BLE_ENABLED=y
CONFIG_BT_GATTS_ENABLE=y
# CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set
# CONFIG_BT_BLE_BLUFI_ENABLE is not set
CONFIG_BT_GATT_MAX_SR_PROFILES=8
CONFIG_BT_GATT_MAX_SR_ATTRIBUTES=100
# CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set
CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y
CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0
# CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set
# CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set
# CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set
CONFIG_BT_GATTC_ENABLE=y
CONFIG_BT_GATTC_MAX_CACHE_CHAR=40
CONFIG_BT_GATTC_NOTIF_REG_MAX=5
# CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set
CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3
CONFIG_BT_BLE_SMP_ENABLE=y
# CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set
# CONFIG_BT_BLE_SMP_ID_RESET_ENABLE is not set
# CONFIG_BT_STACK_NO_LOG is not set
#
# BT DEBUG LOG LEVEL
#
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_HCI_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_HCI_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_HCI_TRACE_LEVEL=2
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BTM_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BTM_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BTM_TRACE_LEVEL=2
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_L2CAP_TRACE_LEVEL=2
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL=2
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_SDP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_SDP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_SDP_TRACE_LEVEL=2
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_GAP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_GAP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_GAP_TRACE_LEVEL=2
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BNEP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BNEP_TRACE_LEVEL=2
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_PAN_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_PAN_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_PAN_TRACE_LEVEL=2
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_A2D_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_A2D_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_A2D_TRACE_LEVEL=2
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_AVDT_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_AVDT_TRACE_LEVEL=2
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_AVCT_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_AVCT_TRACE_LEVEL=2
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_AVRC_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_AVRC_TRACE_LEVEL=2
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_MCA_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_MCA_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_MCA_TRACE_LEVEL=2
# CONFIG_BT_LOG_HID_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_HID_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_HID_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_HID_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_HID_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_HID_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_HID_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_HID_TRACE_LEVEL=2
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_APPL_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_APPL_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_APPL_TRACE_LEVEL=2
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_GATT_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_GATT_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_GATT_TRACE_LEVEL=2
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_SMP_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_SMP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_SMP_TRACE_LEVEL=2
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BTIF_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BTIF_TRACE_LEVEL=2
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BTC_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BTC_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BTC_TRACE_LEVEL=2
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_OSI_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_OSI_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_OSI_TRACE_LEVEL=2
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_NONE is not set
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_ERROR is not set
CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_WARNING=y
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_API is not set
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_EVENT is not set
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG is not set
# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE is not set
CONFIG_BT_LOG_BLUFI_TRACE_LEVEL=2
# end of BT DEBUG LOG LEVEL
CONFIG_BT_ACL_CONNECTIONS=4
CONFIG_BT_MULTI_CONNECTION_ENBALE=y
# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set
# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set
# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set
CONFIG_BT_SMP_ENABLE=y
CONFIG_BT_SMP_MAX_BONDS=15
# CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set
CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30
CONFIG_BT_MAX_DEVICE_NAME_LEN=32
CONFIG_BT_BLE_RPA_TIMEOUT=900
CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
# CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set
# CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set
# end of Bluedroid Options
#
# Controller Options
#
CONFIG_BT_CTRL_MODE_EFF=1
CONFIG_BT_CTRL_BLE_MAX_ACT=6
CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=6
CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0
CONFIG_BT_CTRL_PINNED_TO_CORE_0=y
# CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set
CONFIG_BT_CTRL_PINNED_TO_CORE=0
CONFIG_BT_CTRL_HCI_MODE_VHCI=y
# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set
CONFIG_BT_CTRL_HCI_TL=1
CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30
CONFIG_BT_BLE_CCA_MODE_NONE=y
# CONFIG_BT_BLE_CCA_MODE_HW is not set
# CONFIG_BT_BLE_CCA_MODE_SW is not set
CONFIG_BT_BLE_CCA_MODE=0
CONFIG_BT_CTRL_HW_CCA_VAL=20
CONFIG_BT_CTRL_HW_CCA_EFF=0
CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y
# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set
# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set
CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0
CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y
# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set
CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0
CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y
# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set
CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set
CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9=y
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P20 is not set
CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=11
CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y
CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100
CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20
CONFIG_BT_CTRL_BLE_SCAN_DUPL=y
CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE=y
# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA is not set
# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE is not set
CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0
CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100
CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD=0
# CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN is not set
# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set
CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y
CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0
#
# MODEM SLEEP Options
#
# CONFIG_BT_CTRL_MODEM_SLEEP is not set
# end of MODEM SLEEP Options
CONFIG_BT_CTRL_SLEEP_MODE_EFF=0
CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0
CONFIG_BT_CTRL_HCI_TL_EFF=1
# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set
# CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set
# CONFIG_BT_BLE_ADV_DATA_LENGTH_ZERO_AUX is not set
CONFIG_BT_CTRL_CHAN_ASS_EN=y
CONFIG_BT_CTRL_LE_PING_EN=y
#
# BLE disconnect when instant passed
#
# CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE is not set
# CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE is not set
# CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE is not set
# end of BLE disconnect when instant passed
# CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY is not set
# end of Controller Options
#
# Common Options
#
# CONFIG_BT_ENABLED is not set
CONFIG_BT_ALARM_MAX_NUM=50
# end of Common Options
# CONFIG_BT_HCI_LOG_DEBUG_EN is not set
# end of Bluetooth
# CONFIG_BLE_MESH is not set
#
# Console Library
#
@@ -1248,8 +924,7 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y
# Wireless Coexistence
#
CONFIG_ESP_COEX_ENABLED=y
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y
# CONFIG_ESP_COEX_POWER_MANAGEMENT is not set
# CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE is not set
# CONFIG_ESP_COEX_GPIO_DEBUG is not set
# end of Wireless Coexistence
@@ -1328,7 +1003,7 @@ CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y
#
# ESP-Driver:SPI Configurations
#
# CONFIG_SPI_MASTER_IN_IRAM is not set
CONFIG_SPI_MASTER_IN_IRAM=y
CONFIG_SPI_MASTER_ISR_IN_IRAM=y
# CONFIG_SPI_SLAVE_IN_IRAM is not set
CONFIG_SPI_SLAVE_ISR_IN_IRAM=y
@@ -1510,6 +1185,7 @@ CONFIG_XTAL_FREQ=40
# end of Main XTAL Config
CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y
CONFIG_ESP_SPI_BUS_LOCK_FUNCS_IN_IRAM=y
# end of Hardware Settings
#
@@ -1602,9 +1278,9 @@ CONFIG_SPIRAM_BOOT_INIT=y
# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096
CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=65536
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
# CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY is not set
# end of SPI RAM config
@@ -1637,13 +1313,12 @@ CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8
CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y
CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32
# CONFIG_ESP32S3_DATA_CACHE_16KB is not set
CONFIG_ESP32S3_DATA_CACHE_32KB=y
# CONFIG_ESP32S3_DATA_CACHE_64KB is not set
CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000
# CONFIG_ESP32S3_DATA_CACHE_32KB is not set
CONFIG_ESP32S3_DATA_CACHE_64KB=y
CONFIG_ESP32S3_DATA_CACHE_SIZE=0x10000
# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set
CONFIG_ESP32S3_DATA_CACHE_8WAYS=y
CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8
# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set
CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y
# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set
CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32
@@ -1758,11 +1433,11 @@ CONFIG_ESP_TIMER_IMPL_SYSTIMER=y
# Wi-Fi
#
CONFIG_ESP_WIFI_ENABLED=y
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=2
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=4
CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=32
CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y
# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set
@@ -1770,9 +1445,9 @@ CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0
CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5
# CONFIG_ESP_WIFI_CSI_ENABLED is not set
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP_WIFI_TX_BA_WIN=6
CONFIG_ESP_WIFI_TX_BA_WIN=2
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP_WIFI_RX_BA_WIN=6
CONFIG_ESP_WIFI_RX_BA_WIN=2
# CONFIG_ESP_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP_WIFI_NVS_ENABLED=y
CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y
@@ -1916,7 +1591,6 @@ CONFIG_FREERTOS_RUN_TIME_COUNTER_TYPE_U32=y
#
# Port
#
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set
CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y
# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set
@@ -2077,6 +1751,7 @@ CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4
CONFIG_LWIP_TCP_OVERSIZE_MSS=y
# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set
# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set
# CONFIG_LWIP_WND_SCALE is not set
CONFIG_LWIP_TCP_RTO_TIME=1500
# end of TCP
@@ -2608,10 +2283,6 @@ CONFIG_WL_SECTOR_SIZE=4096
#
CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16
CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30
# CONFIG_WIFI_PROV_BLE_BONDING is not set
# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set
# CONFIG_WIFI_PROV_BLE_NOTIFY is not set
# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set
CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y
# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set
# end of Wi-Fi Provisioning Manager
@@ -2680,8 +2351,8 @@ CONFIG_LV_MEM_BUF_MAX_NUM=16
#
# HAL Settings
#
CONFIG_LV_DISP_DEF_REFR_PERIOD=30
CONFIG_LV_INDEV_DEF_READ_PERIOD=30
CONFIG_LV_DISP_DEF_REFR_PERIOD=10
CONFIG_LV_INDEV_DEF_READ_PERIOD=10
# CONFIG_LV_TICK_CUSTOM is not set
CONFIG_LV_DPI_DEF=130
# end of HAL Settings
@@ -2694,10 +2365,10 @@ CONFIG_LV_DPI_DEF=130
# Drawing
#
CONFIG_LV_DRAW_COMPLEX=y
CONFIG_LV_SHADOW_CACHE_SIZE=0
CONFIG_LV_SHADOW_CACHE_SIZE=4
CONFIG_LV_CIRCLE_CACHE_SIZE=4
CONFIG_LV_LAYER_SIMPLE_BUF_SIZE=24576
CONFIG_LV_IMG_CACHE_DEF_SIZE=0
CONFIG_LV_LAYER_SIMPLE_BUF_SIZE=10240
CONFIG_LV_IMG_CACHE_DEF_SIZE=128
CONFIG_LV_GRADIENT_MAX_STOPS=2
CONFIG_LV_GRAD_CACHE_DEF_SIZE=0
# CONFIG_LV_DITHER_GRADIENT is not set
@@ -2727,9 +2398,9 @@ CONFIG_LV_DISP_ROT_MAX_BUF=10240
#
CONFIG_LV_USE_ASSERT_NULL=y
CONFIG_LV_USE_ASSERT_MALLOC=y
# CONFIG_LV_USE_ASSERT_STYLE is not set
CONFIG_LV_USE_ASSERT_STYLE=y
# CONFIG_LV_USE_ASSERT_MEM_INTEGRITY is not set
# CONFIG_LV_USE_ASSERT_OBJ is not set
CONFIG_LV_USE_ASSERT_OBJ=y
CONFIG_LV_ASSERT_HANDLER_INCLUDE="assert.h"
# end of Asserts
@@ -2990,9 +2661,9 @@ CONFIG_LOG_BOOTLOADER_LEVEL=3
CONFIG_FLASHMODE_DIO=y
# CONFIG_FLASHMODE_DOUT is not set
CONFIG_MONITOR_BAUD=115200
CONFIG_OPTIMIZATION_LEVEL_DEBUG=y
CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y
CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y
# CONFIG_OPTIMIZATION_LEVEL_DEBUG is not set
# CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set
# CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set
# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set
# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set
CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
@@ -3009,192 +2680,8 @@ CONFIG_STACK_CHECK_NONE=y
# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set
CONFIG_ESP32_APPTRACE_DEST_NONE=y
CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
CONFIG_BLUEDROID_ENABLED=y
# CONFIG_NIMBLE_ENABLED is not set
CONFIG_BTC_TASK_STACK_SIZE=3072
CONFIG_BLUEDROID_PINNED_TO_CORE_0=y
# CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set
CONFIG_BLUEDROID_PINNED_TO_CORE=0
CONFIG_BTU_TASK_STACK_SIZE=4352
# CONFIG_BLUEDROID_MEM_DEBUG is not set
CONFIG_GATTS_ENABLE=y
# CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set
CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y
CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0
CONFIG_GATTC_ENABLE=y
# CONFIG_GATTC_CACHE_NVS_FLASH is not set
CONFIG_BLE_SMP_ENABLE=y
# CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set
# CONFIG_HCI_TRACE_LEVEL_NONE is not set
# CONFIG_HCI_TRACE_LEVEL_ERROR is not set
CONFIG_HCI_TRACE_LEVEL_WARNING=y
# CONFIG_HCI_TRACE_LEVEL_API is not set
# CONFIG_HCI_TRACE_LEVEL_EVENT is not set
# CONFIG_HCI_TRACE_LEVEL_DEBUG is not set
# CONFIG_HCI_TRACE_LEVEL_VERBOSE is not set
CONFIG_HCI_INITIAL_TRACE_LEVEL=2
# CONFIG_BTM_TRACE_LEVEL_NONE is not set
# CONFIG_BTM_TRACE_LEVEL_ERROR is not set
CONFIG_BTM_TRACE_LEVEL_WARNING=y
# CONFIG_BTM_TRACE_LEVEL_API is not set
# CONFIG_BTM_TRACE_LEVEL_EVENT is not set
# CONFIG_BTM_TRACE_LEVEL_DEBUG is not set
# CONFIG_BTM_TRACE_LEVEL_VERBOSE is not set
CONFIG_BTM_INITIAL_TRACE_LEVEL=2
# CONFIG_L2CAP_TRACE_LEVEL_NONE is not set
# CONFIG_L2CAP_TRACE_LEVEL_ERROR is not set
CONFIG_L2CAP_TRACE_LEVEL_WARNING=y
# CONFIG_L2CAP_TRACE_LEVEL_API is not set
# CONFIG_L2CAP_TRACE_LEVEL_EVENT is not set
# CONFIG_L2CAP_TRACE_LEVEL_DEBUG is not set
# CONFIG_L2CAP_TRACE_LEVEL_VERBOSE is not set
CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2
# CONFIG_RFCOMM_TRACE_LEVEL_NONE is not set
# CONFIG_RFCOMM_TRACE_LEVEL_ERROR is not set
CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y
# CONFIG_RFCOMM_TRACE_LEVEL_API is not set
# CONFIG_RFCOMM_TRACE_LEVEL_EVENT is not set
# CONFIG_RFCOMM_TRACE_LEVEL_DEBUG is not set
# CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE is not set
CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2
# CONFIG_SDP_TRACE_LEVEL_NONE is not set
# CONFIG_SDP_TRACE_LEVEL_ERROR is not set
CONFIG_SDP_TRACE_LEVEL_WARNING=y
# CONFIG_SDP_TRACE_LEVEL_API is not set
# CONFIG_SDP_TRACE_LEVEL_EVENT is not set
# CONFIG_SDP_TRACE_LEVEL_DEBUG is not set
# CONFIG_SDP_TRACE_LEVEL_VERBOSE is not set
CONFIG_BTH_LOG_SDP_INITIAL_TRACE_LEVEL=2
# CONFIG_GAP_TRACE_LEVEL_NONE is not set
# CONFIG_GAP_TRACE_LEVEL_ERROR is not set
CONFIG_GAP_TRACE_LEVEL_WARNING=y
# CONFIG_GAP_TRACE_LEVEL_API is not set
# CONFIG_GAP_TRACE_LEVEL_EVENT is not set
# CONFIG_GAP_TRACE_LEVEL_DEBUG is not set
# CONFIG_GAP_TRACE_LEVEL_VERBOSE is not set
CONFIG_GAP_INITIAL_TRACE_LEVEL=2
CONFIG_BNEP_INITIAL_TRACE_LEVEL=2
# CONFIG_PAN_TRACE_LEVEL_NONE is not set
# CONFIG_PAN_TRACE_LEVEL_ERROR is not set
CONFIG_PAN_TRACE_LEVEL_WARNING=y
# CONFIG_PAN_TRACE_LEVEL_API is not set
# CONFIG_PAN_TRACE_LEVEL_EVENT is not set
# CONFIG_PAN_TRACE_LEVEL_DEBUG is not set
# CONFIG_PAN_TRACE_LEVEL_VERBOSE is not set
CONFIG_PAN_INITIAL_TRACE_LEVEL=2
# CONFIG_A2D_TRACE_LEVEL_NONE is not set
# CONFIG_A2D_TRACE_LEVEL_ERROR is not set
CONFIG_A2D_TRACE_LEVEL_WARNING=y
# CONFIG_A2D_TRACE_LEVEL_API is not set
# CONFIG_A2D_TRACE_LEVEL_EVENT is not set
# CONFIG_A2D_TRACE_LEVEL_DEBUG is not set
# CONFIG_A2D_TRACE_LEVEL_VERBOSE is not set
CONFIG_A2D_INITIAL_TRACE_LEVEL=2
# CONFIG_AVDT_TRACE_LEVEL_NONE is not set
# CONFIG_AVDT_TRACE_LEVEL_ERROR is not set
CONFIG_AVDT_TRACE_LEVEL_WARNING=y
# CONFIG_AVDT_TRACE_LEVEL_API is not set
# CONFIG_AVDT_TRACE_LEVEL_EVENT is not set
# CONFIG_AVDT_TRACE_LEVEL_DEBUG is not set
# CONFIG_AVDT_TRACE_LEVEL_VERBOSE is not set
CONFIG_AVDT_INITIAL_TRACE_LEVEL=2
# CONFIG_AVCT_TRACE_LEVEL_NONE is not set
# CONFIG_AVCT_TRACE_LEVEL_ERROR is not set
CONFIG_AVCT_TRACE_LEVEL_WARNING=y
# CONFIG_AVCT_TRACE_LEVEL_API is not set
# CONFIG_AVCT_TRACE_LEVEL_EVENT is not set
# CONFIG_AVCT_TRACE_LEVEL_DEBUG is not set
# CONFIG_AVCT_TRACE_LEVEL_VERBOSE is not set
CONFIG_AVCT_INITIAL_TRACE_LEVEL=2
# CONFIG_AVRC_TRACE_LEVEL_NONE is not set
# CONFIG_AVRC_TRACE_LEVEL_ERROR is not set
CONFIG_AVRC_TRACE_LEVEL_WARNING=y
# CONFIG_AVRC_TRACE_LEVEL_API is not set
# CONFIG_AVRC_TRACE_LEVEL_EVENT is not set
# CONFIG_AVRC_TRACE_LEVEL_DEBUG is not set
# CONFIG_AVRC_TRACE_LEVEL_VERBOSE is not set
CONFIG_AVRC_INITIAL_TRACE_LEVEL=2
# CONFIG_MCA_TRACE_LEVEL_NONE is not set
# CONFIG_MCA_TRACE_LEVEL_ERROR is not set
CONFIG_MCA_TRACE_LEVEL_WARNING=y
# CONFIG_MCA_TRACE_LEVEL_API is not set
# CONFIG_MCA_TRACE_LEVEL_EVENT is not set
# CONFIG_MCA_TRACE_LEVEL_DEBUG is not set
# CONFIG_MCA_TRACE_LEVEL_VERBOSE is not set
CONFIG_MCA_INITIAL_TRACE_LEVEL=2
# CONFIG_HID_TRACE_LEVEL_NONE is not set
# CONFIG_HID_TRACE_LEVEL_ERROR is not set
CONFIG_HID_TRACE_LEVEL_WARNING=y
# CONFIG_HID_TRACE_LEVEL_API is not set
# CONFIG_HID_TRACE_LEVEL_EVENT is not set
# CONFIG_HID_TRACE_LEVEL_DEBUG is not set
# CONFIG_HID_TRACE_LEVEL_VERBOSE is not set
CONFIG_HID_INITIAL_TRACE_LEVEL=2
# CONFIG_APPL_TRACE_LEVEL_NONE is not set
# CONFIG_APPL_TRACE_LEVEL_ERROR is not set
CONFIG_APPL_TRACE_LEVEL_WARNING=y
# CONFIG_APPL_TRACE_LEVEL_API is not set
# CONFIG_APPL_TRACE_LEVEL_EVENT is not set
# CONFIG_APPL_TRACE_LEVEL_DEBUG is not set
# CONFIG_APPL_TRACE_LEVEL_VERBOSE is not set
CONFIG_APPL_INITIAL_TRACE_LEVEL=2
# CONFIG_GATT_TRACE_LEVEL_NONE is not set
# CONFIG_GATT_TRACE_LEVEL_ERROR is not set
CONFIG_GATT_TRACE_LEVEL_WARNING=y
# CONFIG_GATT_TRACE_LEVEL_API is not set
# CONFIG_GATT_TRACE_LEVEL_EVENT is not set
# CONFIG_GATT_TRACE_LEVEL_DEBUG is not set
# CONFIG_GATT_TRACE_LEVEL_VERBOSE is not set
CONFIG_GATT_INITIAL_TRACE_LEVEL=2
# CONFIG_SMP_TRACE_LEVEL_NONE is not set
# CONFIG_SMP_TRACE_LEVEL_ERROR is not set
CONFIG_SMP_TRACE_LEVEL_WARNING=y
# CONFIG_SMP_TRACE_LEVEL_API is not set
# CONFIG_SMP_TRACE_LEVEL_EVENT is not set
# CONFIG_SMP_TRACE_LEVEL_DEBUG is not set
# CONFIG_SMP_TRACE_LEVEL_VERBOSE is not set
CONFIG_SMP_INITIAL_TRACE_LEVEL=2
# CONFIG_BTIF_TRACE_LEVEL_NONE is not set
# CONFIG_BTIF_TRACE_LEVEL_ERROR is not set
CONFIG_BTIF_TRACE_LEVEL_WARNING=y
# CONFIG_BTIF_TRACE_LEVEL_API is not set
# CONFIG_BTIF_TRACE_LEVEL_EVENT is not set
# CONFIG_BTIF_TRACE_LEVEL_DEBUG is not set
# CONFIG_BTIF_TRACE_LEVEL_VERBOSE is not set
CONFIG_BTIF_INITIAL_TRACE_LEVEL=2
# CONFIG_BTC_TRACE_LEVEL_NONE is not set
# CONFIG_BTC_TRACE_LEVEL_ERROR is not set
CONFIG_BTC_TRACE_LEVEL_WARNING=y
# CONFIG_BTC_TRACE_LEVEL_API is not set
# CONFIG_BTC_TRACE_LEVEL_EVENT is not set
# CONFIG_BTC_TRACE_LEVEL_DEBUG is not set
# CONFIG_BTC_TRACE_LEVEL_VERBOSE is not set
CONFIG_BTC_INITIAL_TRACE_LEVEL=2
# CONFIG_OSI_TRACE_LEVEL_NONE is not set
# CONFIG_OSI_TRACE_LEVEL_ERROR is not set
CONFIG_OSI_TRACE_LEVEL_WARNING=y
# CONFIG_OSI_TRACE_LEVEL_API is not set
# CONFIG_OSI_TRACE_LEVEL_EVENT is not set
# CONFIG_OSI_TRACE_LEVEL_DEBUG is not set
# CONFIG_OSI_TRACE_LEVEL_VERBOSE is not set
CONFIG_OSI_INITIAL_TRACE_LEVEL=2
# CONFIG_BLUFI_TRACE_LEVEL_NONE is not set
# CONFIG_BLUFI_TRACE_LEVEL_ERROR is not set
CONFIG_BLUFI_TRACE_LEVEL_WARNING=y
# CONFIG_BLUFI_TRACE_LEVEL_API is not set
# CONFIG_BLUFI_TRACE_LEVEL_EVENT is not set
# CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set
# CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set
CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2
# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set
CONFIG_SMP_ENABLE=y
# CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY is not set
CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30
# CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EN is not set
CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS=y
CONFIG_SW_COEXIST_ENABLE=y
CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y
CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y
# CONFIG_EXTERNAL_COEX_ENABLE is not set
# CONFIG_ESP_WIFI_EXTERNAL_COEXIST_ENABLE is not set
# CONFIG_MCPWM_ISR_IN_IRAM is not set
# CONFIG_EVENT_LOOP_PROFILING is not set
CONFIG_POST_EVENTS_FROM_ISR=y
@@ -3267,19 +2754,19 @@ CONFIG_ESP32S3_BROWNOUT_DET_LVL=7
CONFIG_IPC_TASK_STACK_SIZE=1280
CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_ESP32_WIFI_ENABLED=y
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=2
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=4
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_CSI_ENABLED is not set
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=6
CONFIG_ESP32_WIFI_TX_BA_WIN=2
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_RX_BA_WIN=6
CONFIG_ESP32_WIFI_RX_BA_WIN=6
CONFIG_ESP32_WIFI_RX_BA_WIN=2
CONFIG_ESP32_WIFI_RX_BA_WIN=2
# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
+1 -1
View File
@@ -91,7 +91,7 @@ void sd_card_module_test(void)
printf("3. 测试文件写入...\n");
char test_file_path[] = MOUNT_POINT"/test.txt";
char test_data[] = "这是一段测试数据,用于验证SD卡写入功能。";
esp_err_t write_result = s_example_write_file(test_file_path, test_data);
esp_err_t write_result = s_example_write_file(test_file_path, test_data, "w");
if(write_result == ESP_OK) {
printf(" 文件写入成功: %s\n", test_file_path);
} else {
+29
View File
@@ -268,3 +268,32 @@
- [x] 3. 修复和优化了一些地方
#### Day19 2025.9.29
##### 主要目标:完成具体业务开发&各种优化
实际完成任务:
- [x] 1. 完成了客户端服务端语音相关的交互,涉及内容较多,看代码改动即可
#### Day20 2025.10.9(考研复习)
##### 主要目标:完成具体业务开发&各种优化
实际完成任务:
- [x] 1. 应用界面增加了返回主页的按钮
#### Day20 2025.10.12(考研复习)
##### 主要目标:完成具体业务开发&各种优化
实际完成任务:
- [x] 1. 修复了gif渲染内存泄漏的严重bug
#### Day20 2025.10.13(考研复习)
##### 主要目标:完成具体业务开发&各种优化
实际完成任务:
- [x] 1. 将PetDao当中的cJSON API替换为cpp_json,完美通过测试
#### Day20 2025.10.14(考研复习)
##### 主要目标:完成具体业务开发&各种优化
实际完成任务:
- [x] 1. 整合已经实现的各种上层建筑,实现了一个宠物对话基本业务应用,用于样品测试展示用
- [x] 2. 重构了音频播放类,使其更modern,更加便于移植和拓展