Skip to content

Commit 78d7b40

Browse files
committed
将项目版本更新至1.5.9,优化内存使用,增加主任务栈大小至8192,优化固件升级流程,重构主循环为MainEventLoop,添加新版本检查功能,更新音频编解码器的DMA配置常量。
1 parent 4ef6ef3 commit 78d7b40

File tree

20 files changed

+127
-115
lines changed

20 files changed

+127
-115
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# CMakeLists in this exact order for cmake to work correctly
55
cmake_minimum_required(VERSION 3.16)
66

7-
set(PROJECT_VER "1.5.8")
7+
set(PROJECT_VER "1.5.9")
88

99
# Add this line to disable the specific warning
1010
add_compile_options(-Wno-missing-field-initializers)

main/application.cc

Lines changed: 78 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Application::Application() {
4848
.skip_unhandled_events = true
4949
};
5050
esp_timer_create(&clock_timer_args, &clock_timer_handle_);
51+
esp_timer_start_periodic(clock_timer_handle_, 1000000);
5152
}
5253

5354
Application::~Application() {
@@ -81,58 +82,49 @@ void Application::CheckNewVersion() {
8182

8283
if (ota_.HasNewVersion()) {
8384
Alert(Lang::Strings::OTA_UPGRADE, Lang::Strings::UPGRADING, "happy", Lang::Sounds::P3_UPGRADE);
84-
// Wait for the chat state to be idle
85-
do {
86-
vTaskDelay(pdMS_TO_TICKS(3000));
87-
} while (GetDeviceState() != kDeviceStateIdle);
88-
89-
// Use main task to do the upgrade, not cancelable
90-
Schedule([this, display]() {
91-
SetDeviceState(kDeviceStateUpgrading);
92-
93-
display->SetIcon(FONT_AWESOME_DOWNLOAD);
94-
std::string message = std::string(Lang::Strings::NEW_VERSION) + ota_.GetFirmwareVersion();
95-
display->SetChatMessage("system", message.c_str());
9685

97-
auto& board = Board::GetInstance();
98-
board.SetPowerSaveMode(false);
99-
#if CONFIG_USE_WAKE_WORD_DETECT
100-
wake_word_detect_.StopDetection();
101-
#endif
102-
// 预先关闭音频输出,避免升级过程有音频操作
103-
auto codec = board.GetAudioCodec();
104-
codec->EnableInput(false);
105-
codec->EnableOutput(false);
106-
{
107-
std::lock_guard<std::mutex> lock(mutex_);
108-
audio_decode_queue_.clear();
109-
}
110-
background_task_->WaitForCompletion();
111-
delete background_task_;
112-
background_task_ = nullptr;
113-
vTaskDelay(pdMS_TO_TICKS(1000));
86+
vTaskDelay(pdMS_TO_TICKS(3000));
11487

115-
ota_.StartUpgrade([display](int progress, size_t speed) {
116-
char buffer[64];
117-
snprintf(buffer, sizeof(buffer), "%d%% %zuKB/s", progress, speed / 1024);
118-
display->SetChatMessage("system", buffer);
119-
});
88+
SetDeviceState(kDeviceStateUpgrading);
89+
90+
display->SetIcon(FONT_AWESOME_DOWNLOAD);
91+
std::string message = std::string(Lang::Strings::NEW_VERSION) + ota_.GetFirmwareVersion();
92+
display->SetChatMessage("system", message.c_str());
12093

121-
// If upgrade success, the device will reboot and never reach here
122-
display->SetStatus(Lang::Strings::UPGRADE_FAILED);
123-
ESP_LOGI(TAG, "Firmware upgrade failed...");
124-
vTaskDelay(pdMS_TO_TICKS(3000));
125-
Reboot();
94+
auto& board = Board::GetInstance();
95+
board.SetPowerSaveMode(false);
96+
#if CONFIG_USE_WAKE_WORD_DETECT
97+
wake_word_detect_.StopDetection();
98+
#endif
99+
// 预先关闭音频输出,避免升级过程有音频操作
100+
auto codec = board.GetAudioCodec();
101+
codec->EnableInput(false);
102+
codec->EnableOutput(false);
103+
{
104+
std::lock_guard<std::mutex> lock(mutex_);
105+
audio_decode_queue_.clear();
106+
}
107+
background_task_->WaitForCompletion();
108+
delete background_task_;
109+
background_task_ = nullptr;
110+
vTaskDelay(pdMS_TO_TICKS(1000));
111+
112+
ota_.StartUpgrade([display](int progress, size_t speed) {
113+
char buffer[64];
114+
snprintf(buffer, sizeof(buffer), "%d%% %zuKB/s", progress, speed / 1024);
115+
display->SetChatMessage("system", buffer);
126116
});
127117

118+
// If upgrade success, the device will reboot and never reach here
119+
display->SetStatus(Lang::Strings::UPGRADE_FAILED);
120+
ESP_LOGI(TAG, "Firmware upgrade failed...");
121+
vTaskDelay(pdMS_TO_TICKS(3000));
122+
Reboot();
128123
return;
129124
}
130125

131126
// No new version, mark the current version as valid
132127
ota_.MarkCurrentVersionValid();
133-
std::string message = std::string(Lang::Strings::VERSION) + ota_.GetCurrentVersion();
134-
display->ShowNotification(message.c_str());
135-
136128
if (ota_.HasActivationCode()) {
137129
// Activation code is valid
138130
SetDeviceState(kDeviceStateActivating);
@@ -148,11 +140,8 @@ void Application::CheckNewVersion() {
148140
continue;
149141
}
150142

151-
SetDeviceState(kDeviceStateIdle);
152-
display->SetChatMessage("system", "");
153-
ResetDecoder();
154-
PlaySound(Lang::Sounds::P3_SUCCESS);
155-
// Exit the loop if upgrade or idle
143+
xEventGroupSetBits(event_group_, CHECK_NEW_VERSION_DONE_EVENT);
144+
// Exit the loop if done checking new version
156145
break;
157146
}
158147
}
@@ -180,8 +169,6 @@ void Application::ShowActivationCode() {
180169

181170
// This sentence uses 9KB of SRAM, so we need to wait for it to finish
182171
Alert(Lang::Strings::ACTIVATION, message.c_str(), "happy", Lang::Sounds::P3_ACTIVATION);
183-
vTaskDelay(pdMS_TO_TICKS(1000));
184-
background_task_->WaitForCompletion();
185172

186173
for (const auto& digit : code) {
187174
auto it = std::find_if(digit_sounds.begin(), digit_sounds.end(),
@@ -214,6 +201,15 @@ void Application::DismissAlert() {
214201
}
215202

216203
void Application::PlaySound(const std::string_view& sound) {
204+
// Wait for the previous sound to finish
205+
{
206+
std::unique_lock<std::mutex> lock(mutex_);
207+
audio_decode_cv_.wait(lock, [this]() {
208+
return audio_decode_queue_.empty();
209+
});
210+
}
211+
background_task_->WaitForCompletion();
212+
217213
// The assets are encoded at 16000Hz, 60ms frame duration
218214
SetDecodeSampleRate(16000, 60);
219215
const char* data = sound.data();
@@ -295,6 +291,16 @@ void Application::StartListening() {
295291
}
296292

297293
void Application::StopListening() {
294+
const std::array<int, 3> valid_states = {
295+
kDeviceStateListening,
296+
kDeviceStateSpeaking,
297+
kDeviceStateIdle,
298+
};
299+
// If not valid, do nothing
300+
if (std::find(valid_states.begin(), valid_states.end(), device_state_) == valid_states.end()) {
301+
return;
302+
}
303+
298304
Schedule([this]() {
299305
if (device_state_ == kDeviceStateListening) {
300306
protocol_->SendStopListening();
@@ -337,16 +343,13 @@ void Application::Start() {
337343
vTaskDelete(NULL);
338344
}, "audio_loop", 4096 * 2, this, 8, &audio_loop_task_handle_, realtime_chat_enabled_ ? 1 : 0);
339345

340-
/* Start the main loop */
341-
xTaskCreatePinnedToCore([](void* arg) {
342-
Application* app = (Application*)arg;
343-
app->MainLoop();
344-
vTaskDelete(NULL);
345-
}, "main_loop", 4096 * 2, this, 4, &main_loop_task_handle_, 0);
346-
347346
/* Wait for the network to be ready */
348347
board.StartNetwork();
349348

349+
// Check for new firmware version or get the MQTT broker address
350+
display->SetStatus(Lang::Strings::CHECKING_NEW_VERSION);
351+
CheckNewVersion();
352+
350353
// Initialize the protocol
351354
display->SetStatus(Lang::Strings::LOADING_PROTOCOL);
352355
#ifdef CONFIG_CONNECTION_TYPE_WEBSOCKET
@@ -444,13 +447,6 @@ void Application::Start() {
444447
});
445448
protocol_->Start();
446449

447-
// Check for new firmware version or get the MQTT broker address
448-
xTaskCreate([](void* arg) {
449-
Application* app = (Application*)arg;
450-
app->CheckNewVersion();
451-
vTaskDelete(NULL);
452-
}, "check_new_version", 4096 * 2, this, 2, nullptr);
453-
454450
#if CONFIG_USE_AUDIO_PROCESSOR
455451
audio_processor_.Initialize(codec, realtime_chat_enabled_);
456452
audio_processor_.OnOutput([this](std::vector<int16_t>&& data) {
@@ -509,15 +505,18 @@ void Application::Start() {
509505
wake_word_detect_.StartDetection();
510506
#endif
511507

508+
// Wait for the new version check to finish
509+
xEventGroupWaitBits(event_group_, CHECK_NEW_VERSION_DONE_EVENT, pdTRUE, pdFALSE, portMAX_DELAY);
512510
SetDeviceState(kDeviceStateIdle);
513-
esp_timer_start_periodic(clock_timer_handle_, 1000000);
514-
515-
#if 0
516-
while (true) {
517-
SystemInfo::PrintRealTimeStats(pdMS_TO_TICKS(1000));
518-
vTaskDelay(pdMS_TO_TICKS(10000));
519-
}
520-
#endif
511+
std::string message = std::string(Lang::Strings::VERSION) + ota_.GetCurrentVersion();
512+
display->ShowNotification(message.c_str());
513+
display->SetChatMessage("system", "");
514+
// Play the success sound to indicate the device is ready
515+
ResetDecoder();
516+
PlaySound(Lang::Sounds::P3_SUCCESS);
517+
518+
// Enter the main event loop
519+
MainEventLoop();
521520
}
522521

523522
void Application::OnClockTimer() {
@@ -553,10 +552,10 @@ void Application::Schedule(std::function<void()> callback) {
553552
xEventGroupSetBits(event_group_, SCHEDULE_EVENT);
554553
}
555554

556-
// The Main Loop controls the chat state and websocket connection
555+
// The Main Event Loop controls the chat state and websocket connection
557556
// If other tasks need to access the websocket or chat state,
558557
// they should use Schedule to call this function
559-
void Application::MainLoop() {
558+
void Application::MainEventLoop() {
560559
while (true) {
561560
auto bits = xEventGroupWaitBits(event_group_, SCHEDULE_EVENT, pdTRUE, pdFALSE, portMAX_DELAY);
562561

@@ -601,12 +600,14 @@ void Application::OnAudioOutput() {
601600

602601
if (device_state_ == kDeviceStateListening) {
603602
audio_decode_queue_.clear();
603+
audio_decode_cv_.notify_all();
604604
return;
605605
}
606606

607607
auto opus = std::move(audio_decode_queue_.front());
608608
audio_decode_queue_.pop_front();
609609
lock.unlock();
610+
audio_decode_cv_.notify_all();
610611

611612
background_task_->Schedule([this, codec, opus = std::move(opus)]() mutable {
612613
if (aborted_) {
@@ -630,23 +631,24 @@ void Application::OnAudioOutput() {
630631
}
631632

632633
void Application::OnAudioInput() {
633-
std::vector<int16_t> data;
634-
635634
#if CONFIG_USE_WAKE_WORD_DETECT
636635
if (wake_word_detect_.IsDetectionRunning()) {
636+
std::vector<int16_t> data;
637637
ReadAudio(data, 16000, wake_word_detect_.GetFeedSize());
638638
wake_word_detect_.Feed(data);
639639
return;
640640
}
641641
#endif
642642
#if CONFIG_USE_AUDIO_PROCESSOR
643643
if (audio_processor_.IsRunning()) {
644+
std::vector<int16_t> data;
644645
ReadAudio(data, 16000, audio_processor_.GetFeedSize());
645646
audio_processor_.Feed(data);
646647
return;
647648
}
648649
#else
649650
if (device_state_ == kDeviceStateListening) {
651+
std::vector<int16_t> data;
650652
ReadAudio(data, 16000, 30 * 16000 / 1000);
651653
background_task_->Schedule([this, data = std::move(data)]() mutable {
652654
opus_encoder_->Encode(std::move(data), [this](std::vector<uint8_t>&& opus) {
@@ -792,6 +794,7 @@ void Application::ResetDecoder() {
792794
std::lock_guard<std::mutex> lock(mutex_);
793795
opus_decoder_->ResetState();
794796
audio_decode_queue_.clear();
797+
audio_decode_cv_.notify_all();
795798
last_output_time_ = std::chrono::steady_clock::now();
796799

797800
auto codec = Board::GetInstance().GetAudioCodec();

main/application.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <string>
1010
#include <mutex>
1111
#include <list>
12+
#include <vector>
13+
#include <condition_variable>
1214

1315
#include <opus_encoder.h>
1416
#include <opus_decoder.h>
@@ -28,6 +30,7 @@
2830
#define SCHEDULE_EVENT (1 << 0)
2931
#define AUDIO_INPUT_READY_EVENT (1 << 1)
3032
#define AUDIO_OUTPUT_READY_EVENT (1 << 2)
33+
#define CHECK_NEW_VERSION_DONE_EVENT (1 << 3)
3134

3235
enum DeviceState {
3336
kDeviceStateUnknown,
@@ -97,14 +100,14 @@ class Application {
97100
bool aborted_ = false;
98101
bool voice_detected_ = false;
99102
int clock_ticks_ = 0;
100-
TaskHandle_t main_loop_task_handle_ = nullptr;
101103
TaskHandle_t check_new_version_task_handle_ = nullptr;
102104

103105
// Audio encode / decode
104106
TaskHandle_t audio_loop_task_handle_ = nullptr;
105107
BackgroundTask* background_task_ = nullptr;
106108
std::chrono::steady_clock::time_point last_output_time_;
107109
std::list<std::vector<uint8_t>> audio_decode_queue_;
110+
std::condition_variable audio_decode_cv_;
108111

109112
std::unique_ptr<OpusEncoderWrapper> opus_encoder_;
110113
std::unique_ptr<OpusDecoderWrapper> opus_decoder_;
@@ -113,7 +116,7 @@ class Application {
113116
OpusResampler reference_resampler_;
114117
OpusResampler output_resampler_;
115118

116-
void MainLoop();
119+
void MainEventLoop();
117120
void OnAudioInput();
118121
void OnAudioOutput();
119122
void ReadAudio(std::vector<int16_t>& data, int sample_rate, int samples);

main/assets/en-US/language.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"INFO": "Information",
88
"ERROR": "Error",
99
"VERSION": "Ver ",
10-
"LOADING_PROTOCOL": "Loading Protocol...",
10+
"LOADING_PROTOCOL": "Logging in...",
11+
"CHECKING_NEW_VERSION": "Checking for new version...",
1112
"INITIALIZING": "Initializing...",
1213
"PIN_ERROR": "Please insert SIM card",
1314
"REG_ERROR": "Unable to access network, please check SIM card status",

main/assets/ja-JP/language.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
"INFO": "情報",
88
"ERROR": "エラー",
99
"VERSION": "バージョン ",
10-
"LOADING_PROTOCOL": "プロトコルを読み込み中...",
10+
"LOADING_PROTOCOL": "サーバーにログイン中...",
1111
"INITIALIZING": "初期化中...",
1212
"PIN_ERROR": "SIMカードを挿入してください",
1313
"REG_ERROR": "ネットワークに接続できません。ネットワーク状態を確認してください",
1414
"DETECTING_MODULE": "モジュールを検出中...",
1515
"REGISTERING_NETWORK": "ネットワーク接続待機中...",
16+
"CHECKING_NEW_VERSION": "新しいバージョンを確認中...",
1617

1718
"STANDBY": "待機中",
1819
"CONNECT_TO": "接続先 ",

main/assets/zh-CN/language.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
"INFO":"信息",
88
"ERROR":"错误",
99
"VERSION": "版本 ",
10-
"LOADING_PROTOCOL":"加载协议...",
10+
"LOADING_PROTOCOL":"登录服务器...",
1111
"INITIALIZING":"正在初始化...",
1212
"PIN_ERROR":"请插入 SIM 卡",
1313
"REG_ERROR":"无法接入网络,请检查流量卡状态",
1414
"DETECTING_MODULE":"检测模组...",
1515
"REGISTERING_NETWORK":"等待网络...",
16+
"CHECKING_NEW_VERSION":"检查新版本...",
1617

1718
"STANDBY":"待命",
1819
"CONNECT_TO":"连接 ",

main/assets/zh-TW/language.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
"INFO": "資訊",
88
"ERROR": "錯誤",
99
"VERSION": "版本 ",
10-
"LOADING_PROTOCOL": "加載協議...",
10+
"LOADING_PROTOCOL": "登入伺服器...",
1111
"INITIALIZING": "正在初始化...",
1212
"PIN_ERROR": "請插入 SIM 卡",
1313
"REG_ERROR": "無法接入網絡,請檢查網路狀態",
1414
"DETECTING_MODULE": "檢測模組...",
1515
"REGISTERING_NETWORK": "等待網絡...",
16+
"CHECKING_NEW_VERSION": "檢查新版本...",
1617

1718
"STANDBY": "待命",
1819
"CONNECT_TO": "連接 ",

main/audio_codecs/audio_codec.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
#include "board.h"
1313

14+
#define AUDIO_CODEC_DMA_DESC_NUM 6
15+
#define AUDIO_CODEC_DMA_FRAME_NUM 240
16+
1417
class AudioCodec {
1518
public:
1619
AudioCodec();

0 commit comments

Comments
 (0)