diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 538f7cb..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Build examples IDF4.4 -on: - push: - branches: - - master - pull_request: - -jobs: - Build-examples: - runs-on: ubuntu-latest - env: - PROJECT_PATH: examples/factory_demo - BIN_FILE: ESP-Box_Demo_V0.3.0.bin - container: espressif/idf:release-v4.4 - steps: - - name: Checkout repo - uses: actions/checkout@v2 - with: - submodules: 'recursive' - - - name: esp-idf build - run: | - pwd - ls -al - cd /opt/esp/idf - git checkout c8ce38e60c - git submodule update --init --recursive - tools/idf_tools.py --non-interactive install cmake - ./install.sh - source ./export.sh - cd $GITHUB_WORKSPACE/$PROJECT_PATH - idf.py build - cd build - esptool.py --chip ESP32-S3 merge_bin -o $BIN_FILE @flash_args - shell: bash - - - name: Upload a Build Artifact - uses: actions/upload-artifact@v3.0.0 - with: - # Artifact name - name: factory-firmware_IDF4.4 - # A file, directory or wildcard pattern that describes what to upload - path: | - examples/factory_demo/build/ESP-*.bin - retention-days: 90 diff --git a/.github/workflows/build idf5.0.yml b/.github/workflows/build_IDF5.1.yml similarity index 84% rename from .github/workflows/build idf5.0.yml rename to .github/workflows/build_IDF5.1.yml index aa4bf50..256aa71 100644 --- a/.github/workflows/build idf5.0.yml +++ b/.github/workflows/build_IDF5.1.yml @@ -1,4 +1,4 @@ -name: Build examples IDF5.0 +name: Build examples IDF5.1 on: push: branches: @@ -10,8 +10,8 @@ jobs: runs-on: ubuntu-latest env: PROJECT_PATH: examples/factory_demo - BIN_FILE: ESP-Box_Demo_V0.3.0.bin - container: espressif/idf:release-v5.0 + BIN_FILE: ESP-Box_Demo_V0.5.0.bin + container: espressif/idf:release-v5.1 steps: - name: Checkout repo uses: actions/checkout@v2 @@ -23,7 +23,7 @@ jobs: pwd ls -al cd /opt/esp/idf - git checkout 94d9c529f3 + git checkout 22cfbf30c3 git submodule update --init --recursive tools/idf_tools.py --non-interactive install cmake ./install.sh @@ -38,7 +38,7 @@ jobs: uses: actions/upload-artifact@v3.0.0 with: # Artifact name - name: factory-firmware_IDF5.0 + name: factory-firmware_IDF5.1 # A file, directory or wildcard pattern that describes what to upload path: | examples/factory_demo/build/ESP-*.bin diff --git a/README.md b/README.md index af50d4e..d8e5705 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@
-
-
+
+
@@ -32,7 +32,8 @@ The ESP-BOX is a new generation AIoT development platform released by Espressif
| ESP-BOX | Dependent ESP-IDF | Branch Note | Support State |
| :--------------: | :---------------: | :----------------------------------------------------: | -------------- |
-| master | >= release/v5.0
commit id: 96119acc8b | Latest developing firmware
esp-sr version: v1.3.3 | Compatible with ESP32-S3-BOX and ESP32-S3-BOX-Lite
Use menuconfig to select board |
+| master | >= release/v5.1
commit id: 22cfbf30c3 | Latest developing firmware
esp-sr components version: v1.3.4 | Compatible with ESP32-S3-BOX and ESP32-S3-BOX-Lite
Use menuconfig to select board |
+| Tag 0.5.0 | release/v5.1
commit id: 22cfbf30c3 | esp-sr components version: v1.3.4 | Compatible with ESP32-S3-BOX and ESP32-S3-BOX-Lite
Use menuconfig to select board |
| Tag 0.3.0 | release/v4.4
commit id: 2bdea81b2a | esp-sr version: dev/v2.0
commit id: c873a35 | Compatible with ESP32-S3-BOX and ESP32-S3-BOX-Lite |
| Tag 0.2.1 | release/v4.4 with [patch](https://github.com/espressif/esp-box/tree/v0.2.1/idf_patch) | esp-sr version: close v1.0
commit id: 3ce34fe | Support ESP32-S3-BOX only |
| Tag 0.1.1 | release/v4.4 with [patch](https://github.com/espressif/esp-box/tree/v0.1.1/idf_patch) | esp-sr version: v0.9.6
commit id: 3ce34fe | Support ESP32-S3-BOX only |
@@ -62,24 +63,24 @@ The ESP-BOX is a new generation AIoT development platform released by Espressif
* For getting start of BOX serial development boards, please refer to the [Getting Started](./docs/getting_started.md).
* For experiencing voice assistant, please refer to the [Voice Assistance Control and Customization](./docs/getting_started.md#offline-voice-assistant-with-your-device).
* For experiencing a more humanized interactive experience, please refer to the [Continuous Speech Recognition](./docs/getting_started.md#continuous-recognition).
-* For defining the speech commands by mobile APP, please refer to the [ESP-BOX APP User Guide](./docs/getting_started.md#voice-command-customization).
+* For defining the speech commands by mobile APP, please refer to the [ESP BOX APP User Guide](./docs/getting_started.md#voice-command-customization).
* For product exploded-view and disassembly tutorial, please refer to [Disassembly Tutorial](docs/disassembly_tutorial.md).
* For more details of hardware information, please refer to the [Hardware Overview](./docs/hardware_overview).
* For latest version firmware, please refer to the [Firmware Update](./docs/firmware_update.md).
## Developer Guide
-ESP-BOX integrates components commonly used in AIOT development that you can leverage to build your own applications.
+ESP-BOX integrates components commonly used in AIoT development that you can leverage to build your own applications. Read more development guide [here](./docs/development_guide.md) (Updates in Progress).
### Quick Start
-* **Step 1**. ESP-IDF (Espressif IoT Development Framework) is required to build the application. If this is your first time using the ESP-IDF, please refer to [ESP-IDF development guide](https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32s3/index.html) to understand the open-source drivers and components provided by Espressif.
-* **Step 2**. Next, setting up development environment. Please refer to [ESP-IDF(release/v4.4 or release/v5.0) Installation Step by Step](https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32s3/get-started/index.html#installation-step-by-step).
+* **Step 1**. ESP-IDF (Espressif IoT Development Framework) is required to build the application. If this is your first time using the ESP-IDF, please refer to [ESP-IDF development guide](https://docs.espressif.com/projects/esp-idf/en/release-v5.1/esp32s3/index.html) to understand the open-source drivers and components provided by Espressif.
+* **Step 2**. Next, setting up development environment. Please refer to [ESP-IDF(release/v5.1) Installation Step by Step](https://docs.espressif.com/projects/esp-idf/en/release-v5.1/esp32s3/get-started/index.html).
* **Step 3**. Run command `git clone --recursive https://github.com/espressif/esp-box.git` to download the code of this project and then switch the ESP-IDF version to [specified version](#versions);
* **Step 4**. Take a small step, you can [build and flash a simple example](./examples/image_display).
* **Step 5**. Moving further, please read [ESP-BOX technical architecture](./docs/technical_architecture.md) to understand the technical details.
-* **Step 6**. Going deeper, please read [ESP Speech Recognition Application Guide](https://github.com/espressif/esp-sr), [ESP RainMaker Programming Guide](https://docs.espressif.com/projects/esp-rainmaker/en/latest/), [LVGL GUI Quick overview](https://docs.lvgl.io/8.1/get-started/index.html).
-* **Step 7**. For extended function, please read [Pmod™ compatible headers](./docs/hardware_overview) and [ESP-IDF API reference](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32s3/api-reference/index.html), to develop drivers for more extended devices.
+* **Step 6**. Going deeper, please read [ESP Speech Recognition Application Guide](https://github.com/espressif/esp-sr), [ESP RainMaker Programming Guide](https://docs.espressif.com/projects/esp-rainmaker/en/latest/), [LVGL GUI Quick overview](https://docs.lvgl.io/8.3/).
+* **Step 7**. For extended function, please read [Pmod™ compatible headers](./docs/hardware_overview) and [ESP-IDF API reference](https://docs.espressif.com/projects/esp-idf/en/release-v5.1/esp32s3/api-reference/index.html), to develop drivers for more extended devices.
## Contact Us
diff --git a/README_cn.md b/README_cn.md
index 15de6ce..a66afe3 100644
--- a/README_cn.md
+++ b/README_cn.md
@@ -6,8 +6,8 @@
-
-
+
+
@@ -32,8 +32,9 @@ ESP-BOX 是乐鑫信息科技发布的新一代 AIoT 应用开发平台。ESP32-
| ESP-BOX | 依赖的 ESP-IDF | 分支信息 | 支持状态 |
| :-------: | :----------------------------------------------------------: | :----------------------------------------------------------: | ------------------------------------------------------- |
-| master | >= release/v5.0
commit id: 96119acc8b | Latest developing firmware
esp-sr version: v1.3.3 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite
使用 menuconfig 选择开发板 |
-| Tag 0.3.0 | release/v4.4
commit id: 2bdea81b2a | esp-sr version: dev/v2.0
commit id: c873a35 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite |
+| master | >= release/v5.1
commit id: 22cfbf30c3 | Latest developing firmware
esp-sr components version: v1.3.4 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite
使用 menuconfig 选择开发板 |
+| Tag 0.5.0 | release/v5.1
commit id: 22cfbf30c3 | esp-sr components version: v1.3.4 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite
使用 menuconfig 选择开发板 |
+| Tag 0.3.0 | release/v4.4
commit id: 22cfbf30c3 | esp-sr version: dev/v2.0
commit id: c873a35 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite |
| Tag 0.2.1 | release/v4.4 with [patch](https://github.com/espressif/esp-box/tree/v0.2.1/idf_patch) | esp-sr version: close v1.0
commit id: 3ce34fe | 仅支持 ESP32-S3-BOX |
| Tag 0.1.1 | Release/v4.4 with [patch](https://github.com/espressif/esp-box/tree/v0.1.1/idf_patch) | esp-sr version: v0.9.6
commit id: 3ce34fe | 仅支持 ESP32-S3-BOX |
@@ -62,24 +63,24 @@ ESP-BOX 是乐鑫信息科技发布的新一代 AIoT 应用开发平台。ESP32-
* 首次拿到 BOX 系列开发板,您可以查看 [首次使用操作指引](./docs/getting_started_cn.md#给设备供电);
* 想要体验离线语音助手功能,您可以查看 [离线语音识别](./docs/getting_started_cn.md#体验离线语音识别);
* 体验更人性化的语音交互,可查看 [连续语音识别](./docs/getting_started_cn.md#连续语音识别);
-* 想要通过手机 APP 设置独特的语音命令词,请查看 [ESP-BOX APP 操作指引](./docs/getting_started_cn.md#语音命令词自定义);
+* 想要通过手机 APP 设置独特的语音命令词,请查看 [ESP BOX APP 操作指引](./docs/getting_started_cn.md#语音命令词自定义);
* 想要了解产品爆炸图和拆机说明,请查看 [拆机教程](docs/disassembly_tutorial.md);
* 想要了解开发板硬件和接口细节,请查看 [硬件总览](./docs/hardware_overview);
* 想要使用最新版本固件,请查看 [固件更新说明](./docs/firmware_update_cn.md)。
## 开发指引
-esp-box 集成了 AIOT 开发中常用的组件,您可以利用这些组件构建自己的应用。
+ESP-BOX 调用乐鑫包管理器 ESP Registry 中常用的组件,您可以利用这些组件构建自己的应用。点击了解更多[开发指南](./docs/development_guide_cn.md)(持续更新中)。
### 快速开始
-* **Step 1**. 如果您首次接触 ESP-IDF 开发,建议先浏览 [ESP-IDF 编程指南](https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32s3/index.html),了解乐鑫已经提供的开源驱动和组件;
-* **Step 2**. 接下来您可以详细阅读 [ESP-IDF(release/v4.4 或者 release/v5.0) 环境搭建指引](https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32s3/get-started/index.html#installation-step-by-step),一步一步完成开发环境搭建;
+* **Step 1**. 如果您首次接触 ESP-IDF 开发,建议先浏览 [ESP-IDF 编程指南](https://docs.espressif.com/projects/esp-idf/zh_CN/release-v5.1/esp32s3/index.html),了解乐鑫已经提供的开源驱动和组件;
+* **Step 2**. 接下来您可以详细阅读 [ESP-IDF(release/v5.1) 环境搭建指引](https://docs.espressif.com/projects/esp-idf/en/release-v5.1/esp32s3/get-started/index.html),一步一步完成开发环境搭建;
* **Step 3**. 使用指令 `git clone --recursive https://github.com/espressif/esp-box.git` 下载本项目的代码,然后需要将 esp-idf 版本切换到[指定的版本](#版本信息);
* **Step 4**. 小试牛刀,您可以尝试 [构建并烧录一个新的示例程序](./examples/image_display);
* **Step 5**. 更进一步,您可以阅读 [ESP-BOX 技术架构说明](./docs/technical_architecture_cn.md),了解更多技术细节;
-* **Step 6**. 深入开发,您可以阅读 [ESP 语音识别应用开发指南](https://github.com/espressif/esp-sr),[ESP RainMaker 编程指南](https://docs.espressif.com/projects/esp-rainmaker/en/latest/),[LVGL UI 界面开发快速总览](https://docs.lvgl.io/8.1/get-started/index.html);
-* **Step 7**. 扩展功能,您可以阅读 [开发板 Pmod™ 兼容接口介绍](./docs/hardware_overview) 和 [ESP-IDF API 参考手册](https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32s3/api-reference/index.html),为更多扩展设备开发驱动。
+* **Step 6**. 深入开发,您可以阅读 [ESP 语音识别应用开发指南](https://github.com/espressif/esp-sr),[ESP RainMaker 编程指南](https://docs.espressif.com/projects/esp-rainmaker/en/latest/),[LVGL UI 界面开发快速总览](https://docs.lvgl.io/8.3/);
+* **Step 7**. 扩展功能,您可以阅读 [开发板 Pmod™ 兼容接口介绍](./docs/hardware_overview) 和 [ESP-IDF API 参考手册](https://docs.espressif.com/projects/esp-idf/en/release-v5.1/esp32s3/api-reference/index.html),为更多扩展设备开发驱动。
## 联系我们
diff --git a/components/bsp/include/bsp_board.h b/components/bsp/include/bsp_board.h
index 25a70dc..8d714ba 100644
--- a/components/bsp/include/bsp_board.h
+++ b/components/bsp/include/bsp_board.h
@@ -186,6 +186,8 @@ esp_err_t bsp_btn_register_callback(bsp_button_id_t btn, button_event_t event, b
*/
esp_err_t bsp_btn_rm_all_callback(bsp_button_id_t btn);
+esp_err_t bsp_btn_rm_event_callback(bsp_button_id_t btn, size_t event);
+
#ifdef __cplusplus
}
#endif
diff --git a/components/bsp/src/boards/esp32_s3_box.c b/components/bsp/src/boards/esp32_s3_box.c
index f9cfd2d..2b2ec36 100644
--- a/components/bsp/src/boards/esp32_s3_box.c
+++ b/components/bsp/src/boards/esp32_s3_box.c
@@ -121,6 +121,7 @@ esp_err_t bsp_btn_init(void)
g_btn_handle[i] = iot_button_create(&BOARD_BTN_ID_config[i]);
assert(g_btn_handle[i]);
}
+
return ESP_OK;
}
@@ -151,6 +152,15 @@ esp_err_t bsp_btn_rm_all_callback(bsp_button_id_t btn)
return ESP_OK;
}
+esp_err_t bsp_btn_rm_event_callback(bsp_button_id_t btn, size_t event)
+{
+ assert((g_btn_handle) && "button not initialized");
+ assert((btn < BOARD_BTN_ID_NUM) && "button id incorrect");
+
+ iot_button_unregister_cb(g_btn_handle[btn], event);
+ return ESP_OK;
+}
+
static esp_err_t bsp_i2s_read(void *audio_buffer, size_t len, size_t *bytes_read, uint32_t timeout_ms)
{
esp_err_t ret = ESP_OK;
@@ -189,8 +199,6 @@ static esp_err_t bsp_codec_volume_set(int volume, int *volume_set)
{
esp_err_t ret = ESP_OK;
float v = volume;
- v *= 0.6f;
- v = -0.01f * (v * v) + 2.0f * v;
ret = esp_codec_dev_set_out_vol(play_dev_handle, (int)v);
return ret;
}
@@ -213,6 +221,14 @@ static esp_err_t bsp_codec_es7210_set()
};
assert(record_dev_handle);
+
+ if (play_dev_handle) {
+ ret = esp_codec_dev_close(play_dev_handle);
+ }
+
+ if (record_dev_handle) {
+ ret = esp_codec_dev_close(record_dev_handle);
+ }
ret = esp_codec_dev_open(record_dev_handle, &fs);
esp_codec_dev_set_in_gain(record_dev_handle, ES7210_ADC_VOLUME);
return ret;
@@ -227,6 +243,7 @@ static void bsp_codec_init()
assert((record_dev_handle) && "record_dev_handle not initialized");
bsp_codec_es7210_set();
+ bsp_codec_es8311_set(ES7210_SAMPLE_RATE, ES7210_BIT_WIDTH, ES7210_CHANNEL);
bsp_codec_config_t *codec_config = bsp_board_get_codec_handle();
codec_config->volume_set_fn = bsp_codec_volume_set;
diff --git a/components/bsp/src/boards/esp32_s3_box_lite.c b/components/bsp/src/boards/esp32_s3_box_lite.c
index 2644c5c..b3191e7 100644
--- a/components/bsp/src/boards/esp32_s3_box_lite.c
+++ b/components/bsp/src/boards/esp32_s3_box_lite.c
@@ -130,6 +130,15 @@ esp_err_t bsp_btn_rm_all_callback(bsp_button_id_t btn)
return ESP_OK;
}
+esp_err_t bsp_btn_rm_event_callback(bsp_button_id_t btn, size_t event)
+{
+ assert((g_btn_handle) && "button not initialized");
+ assert((btn < BOARD_BTN_ID_NUM) && "button id incorrect");
+
+ iot_button_unregister_cb(g_btn_handle[btn], event);
+ return ESP_OK;
+}
+
static esp_err_t bsp_i2s_read(void *audio_buffer, size_t len, size_t *bytes_read, uint32_t timeout_ms)
{
esp_err_t ret = ESP_OK;
@@ -168,8 +177,6 @@ static esp_err_t bsp_codec_volume_set(int volume, int *volume_set)
{
esp_err_t ret = ESP_OK;
float v = volume;
- v *= 0.6f;
- v = -0.01f * (v * v) + 2.0f * v;
ret = esp_codec_dev_set_out_vol(play_dev_handle, (int)v);
return ret;
}
@@ -206,6 +213,7 @@ static void bsp_codec_init()
assert((record_dev_handle) && "record_dev_handle not initialized");
bsp_codec_es7243_set();
+ bsp_codec_es8156_set(ES7243_SAMPLE_RATE, ES7243_BIT_WIDTH, ES7243_CHANNEL);
bsp_codec_config_t *codec_config = bsp_board_get_codec_handle();
codec_config->volume_set_fn = bsp_codec_volume_set;
diff --git a/docs/_static/development_guide_picture/LVGL_porting.png b/docs/_static/development_guide_picture/LVGL_porting.png
index ac27ad3..51804d2 100644
Binary files a/docs/_static/development_guide_picture/LVGL_porting.png and b/docs/_static/development_guide_picture/LVGL_porting.png differ
diff --git a/docs/_static/development_guide_picture/LVGL_porting_EN.png b/docs/_static/development_guide_picture/LVGL_porting_EN.png
new file mode 100644
index 0000000..1e79766
Binary files /dev/null and b/docs/_static/development_guide_picture/LVGL_porting_EN.png differ
diff --git a/docs/development_guide.md b/docs/development_guide.md
index 79a9975..5018def 100644
--- a/docs/development_guide.md
+++ b/docs/development_guide.md
@@ -1 +1,272 @@
# Development Guide
+* [中文版本](./development_guide_cn.md)
+
+This document aims to assist users in setting up the development environment and application development using Espressif's ESP32-S3 chip for AIoT application.
+
+## Preparation
+
+- Installation of Development Environment
+
+ Follow the instructions in the [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/get-started/index.html#get-started-get-prerequisites) to install the esp-idf development environment. Despite the availability of graphical IDEs and plugins, we recommend manual installation and compilation using the command-line interface.
+
+ The installation completed following the above instructions may not necessarily be the version of ESP-IDF that esp-box's dependencies require. In this case, it's necessary to switch the esp-idf to the specified version according to the [version notes](https://github.com/espressif/esp-box#versions). Using commit id 22cfbf30c3 as an example, the following command will accomplish the switch.
+
+ ```shell
+ cd esp-idf
+ git fetch
+ git checkout 22cfbf30c3
+ git submodule update --init --recursive
+ ./install.sh
+ ```
+
+- Clone esp-box
+
+ In the command-line interface, navigate to your working directory and run the following command to clone the repository.
+
+ ```shell
+ git clone --recursive https://github.com/espressif/esp-box.git
+ ```
+
+## Compiling and Running Your First Application
+Once you have successfully completed the preparation, you can start compiling your first application. You can begin with the `examples/factory_demo` project.
+
+### Set Up ESP-IDF Environment Variables
+You need to do this step every time you open a new command-line interface for compilation.
+
+```shell
+cd esp-idf
+. ./export.sh
+```
+
+### Start Compilation
+
+After navigating to the project directory, initiate the compilation.
+
+```shell
+cd esp-box/examples/factory_demo
+idf.py build
+```
+
+You will see log outputs similar to the following:
+
+```
+Executing action: all (aliases: build)
+Running cmake in directory /home/user/esp-box/examples/factory_demo/build
+Executing "cmake -G Ninja -DPYTHON_DEPS_CHECKED=1 -DESP_PLATFORM=1 -DIDF_TARGET=esp32s3 -DCCACHE_ENABLE=0 /home/user/work/esp-box/examples/factory_demo"...
+-- Found Git: /usr/bin/git (found version "2.36.0")
+-- Not find RMAKER_PATH, default is /home/user/work/esp-box/examples/factory_demo/../../components/esp-rainmaker
+-- Component directory /home/user/work/esp-box/components/esp-rainmaker does not contain a CMakeLists.txt file. No component will be added
+-- Component directory /home/user/work/esp-box/components/esp-rainmaker/components/esp-insights does not contain a CMakeLists.txt file. No component will be added
+-- The C compiler identification is GNU 8.4.0
+-- The CXX compiler identification is GNU 8.4.0
+-- The ASM compiler identification is GNU
+-- Found assembler: /home/user/esp/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-8.4.0/xtensa-esp32s3-elf/bin/xtensa-esp32s3-elf-gcc
+
+......
+
+Project build complete. To flash, run this command:
+/home/user/esp/.espressif/python_env/idf4.4_py3.8_env/bin/python ../../../../esp/esp-idf/components/esptool_py/esptool/esptool.py -p (PORT) -b 460800 --before default_reset --after hard_reset --chip esp32s3 --no-stub write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x16000 build/ota_data_initial.bin 0x20000 build/factory_demo.bin 0x3bd000 build/storage.bin 0x647000 build/model.bin
+```
+
+### Flashing Firmware and Running
+
+All BOX development boards can download firmware directly via the USB interface. Before downloading, make sure that the computer correctly recognizes the device.
+
+- Linux and MacOS usually do not require driver installation to recognize the device.
+- For Windows systems, we recommend using `Windows 10` and above. In this system, the `USB-Serial-Jtag` driver will be automatically downloaded. If using the `Windows 7` system, please manually download the [USB-Serial-JTAG driver](https://dl.espressif.com/dl/idf-driver/idf-driver-esp32-usb-jtag-2021-07-15.zip) and install it.
+
+Download the firmware and open the monitor using the following command:
+
+```shell
+idf.py -p PORT flash monitor
+```
+
+Replace PORT with the port name recognized by your computer. Typically, it is `/dev/ttyACM0` on Linux systems.
+
+The firmware will automatically start running after the download is complete.
+
+## Debugging Applications
+
+- JTAG Debugging: See [here](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/api-guides/jtag-debugging/index.html)
+- Application Layer Tracing: See [here](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/api-guides/app_trace.html)
+
+## Components
+
+Includes the following components:
+
+| Component | Description |
+| ------------ | ------------------------------------------- |
+| bsp | Includes supported development board info and onboard peripheral drivers |
+| esp-rainmaker | Connects with Rainmaker cloud |
+| esp-sr | Espressif speech recognition library |
+| i2c_bus | I2C driver |
+| i2c_devices | Drivers for common I2C devices |
+| iot_button | Button driver |
+| lvgl | LVGL graphics library |
+| audio | Playback/file management/decoding library |
+
+
+### BSP Component
+- boards
+
+ **bsp_board.c** is the system call file used to be compatible with different hardware platforms. Currently, the box project supports two hardware platforms: [BOARD_S3_BOX](./hardware_overview/esp32_s3_box/hardware_overview_for_box.md) and [BOARD_S3_BOX_LITE](./hardware_overview/esp32_s3_box_lite/hardware_overview_for_lite.md). After the system initialization, based on the different device addresses detected by IIC, it determines the current hardware platform and calls different hardware initialization interfaces accordingly.
+
+ **esp32_s3_box.c** and **esp32_s3_box_lite.c** are the specific hardware pin configurations and initialization implementations for `BOARD_S3_BOX` and `BOARD_S3_BOX_LITE`, respectively. Users need to manually select the hardware platform they are running on in menuconfig to invoke the corresponding hardware initialization interface.
+
+- codec
+
+ The **codec** directory contains the driver interfaces for the Micphoone and Speaker that the hardware requires.
+
+ |`BOARD_S3_BOX_LITE`| |
+ | ------------- | -------|
+ | ADC Module | ES7243 |
+ | Codec Module | ES8153 |
+
+ |`BOARD_S3_BOX `| |
+ | ------------- | -------|
+ | ADC Module | ES7210 |
+ | Codec Module | ES8311 |
+
+- peripherals
+
+ **bsp_btn.c** is the interface for handling buttons in the box, which works in conjunction with the **iot button** component. **iot button** maintains a registered list of button events and establishes a 1ms button query mechanism `button_create_com`.
+
+ The timer will sequentially poll the button events registered by `bsp_btn_register_callback`, and trigger the callback functions registered by the application layer according to the event of the button through `CALL_EVENT_CB(ev)`.
+
+ - `BOARD_S3_BOX` has 1 physical button named `boot` , and the middle red dot is a virtual TP button.
+ The `boot` button handles functions such as restoring Wi-Fi settings to factory defaults and switching between Chinese and English languages.
+
+ - `BOARD_S3_BOX_LITE` has 1 physical button named `boot` and 3 ADC buttons named `prev`, `enter`, and `next`.
+ The `boot` function is the same as described above, and the 3 ADC buttons act as navigation keys for function switching.
+ The ADC buttons are designed using a single [`ADC`](../hardware/esp32_s3_box_lite_Button_V1.1/schematic/SCH_ESP32-S3-BOX-Lite_Button_V1.1_20211125.pdf) line, connected to different resistors to distinguish which button is pressed based on the ADC value. This approach saves IO port resources.
+
+ **bsp_codec.c** provides an interface middleware for the above codecs, unifying the calls to different codecs and ADC chips.
+ **bsp_i2c.c** provides an interface middleware for the i2c_bus.
+ **bsp_i2s.c** provides an interface middleware for i2s.
+ **bsp_lcd.c** provides an interface middleware for displaying hardware interfaces.
+
+
+
+ - `bsp_spi_lcd_init`initializes the LCD's SPI interface based on the board's pin definition.
+
+ - `lcd_trans_done_cb` is the callback function for SPI data transmission completion, ensuring synchronization with LVGL's graphics rendering logic. `p_on_trans_done_cb(p_user_data) `-> `lv_port_flush_ready` notifies the display to clear the `flushing` flag.
+ - `bsp_lcd_flush` is an LVGL interface that notifies the driver to prepare for screen refresh. If the interface has finished sending data from the previous frame, this function calls `esp_lcd_panel_ops.c/esp_lcd_panel_draw_bitmap` to send the display data to the SPI interface.
+
+
+### ESP-SR Component
+This section focuses on introducing some application interfaces of SR.
+
+ * Configuration File Introduction
+ ```
+ #define AFE_CONFIG_DEFAULT() { \
+ .aec_init = true, \ //Enable AEC algorithm
+ .se_init = true, \ //Enable BSS/NS algorithm
+ .vad_init = true, \ //Enable VAD (only usable in speech recognition scenes)
+ .wakenet_init = true, \ //Enable wake word detection.
+ .voice_communication_init = false, \ //Enable voice communication. Cannot be enabled at the same time as wakenet_init.
+ .voice_communication_agc_init = false, \ //Enable AGC in voice communication.
+ .voice_communication_agc_gain = 15, \ //AGC gain value in voice communication, in dB.
+ .vad_mode = VAD_MODE_3, \ //VAD detection mode, higher value is more aggressive.
+ .wakenet_model_name = NULL, \ //Select wake word model.
+ .wakenet_mode = DET_MODE_2CH_90, \ //Wake word detection mode. Corresponds to the number of mic channels, choose according to mic channel count.
+ .afe_mode = SR_MODE_LOW_COST, \ //SR_MODE_LOW_COST: Quantized version with less resource consumption.
+ //SR_MODE_HIGH_PERF: Non-quantized version with higher resource consumption.
+ .afe_perferred_core = 0, \ //The CPU core on which internal AFE BSS/NS/MISO algorithms run.
+ .afe_perferred_priority = 5, \ //Task priority for internal AFE BSS/NS/MISO algorithms.
+ .afe_ringbuf_size = 50, \ //Internal ring buffer size configuration.
+ .memory_alloc_mode = \
+ AFE_MEMORY_ALLOC_MORE_PSRAM, \ //Allocate most of the memory from external psram
+ .agc_mode = AFE_MN_PEAK_AGC_MODE_2, \ //Linear amplification of audio fed to multinet, peak value at -4dB.
+ .pcm_config.total_ch_num = 3, \ //total_ch_num = mic_num + ref_num
+ .pcm_config.mic_num = 2, \ //Number of microphone channels in the audio. Currently, only configurations of 1 or 2 are supported.
+ .pcm_config.ref_num = 1, \ //Number of reference loop channels in the audio. Currently, only configurations of 0 or 1 are supported.
+ }
+ ```
+ * Model Initialization and Configuration
+ ```
+ /* ESP_AFE_SR_HANDLE: Voice recognition model
+ * ESP_AFE_VC_HANDLE: Voice communication model
+ */
+ afe_handle = &ESP_AFE_SR_HANDLE;
+ afe_config_t afe_config = AFE_CONFIG_DEFAULT();
+
+ /* Wake word model naming format: wm*
+ * Command word model naming format: mn*
+ * esp_srmodel_filter is an interface encapsulating model partition searching
+ */
+ afe_config.wakenet_model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL);
+ afe_config.aec_init = false; // Disable AEC
+
+ esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(&afe_config);
+
+ ```
+ * Switching Wake Word and Command Word Models
+ ```
+ /* Switching wake word model */
+ wn_name = esp_srmodel_filter(models, ESP_WN_PREFIX, (SR_LANG_EN == g_sr_data->lang ? "hiesp" : "hilexin"));
+ g_sr_data->afe_handle->set_wakenet(g_sr_data->afe_data, wn_name); // Set wake word model
+
+ /* Switching command word model */
+ mn_name = esp_srmodel_filter(models, ESP_MN_PREFIX, ((SR_LANG_EN == g_sr_data->lang) ? ESP_MN_ENGLISH : ESP_MN_CHINESE));
+ esp_mn_iface_t *multinet = esp_mn_handle_from_name(mn_name);
+ model_iface_data_t *model_data = multinet->create(mn_name, 5760); // Set command word model
+ ```
+ * Command Word Configuration Interface
+ ```
+ /* Load built-in command word model from the model
+ * Command word model can be modified from the menuconfig path: TOP -> ESP_SPEECH_RECOGNITION -> commands
+ */
+ esp_mn_commands_update_from_sdkconfig(*multinet, *model_data);
+
+ /* Manual manipulation of command words in code
+ * Users can use the following APIs to manipulate command words
+ */
+ esp_err_t esp_mn_commands_add(command_id, *phoneme_string);
+ esp_err_t esp_mn_commands_remove(*phoneme_string);
+ esp_err_t esp_mn_commands_modify(*old_phoneme_string, *new_phoneme_string);
+ esp_mn_error_t *esp_mn_commands_update(*multinet, *model_data);
+
+ ```
+ * Rainmaker and SR Interface
+ `cmd_write_to_sr(&cmd)` is the interface through which Rainmaker sends voice commands to the BOX for modification.
+ SR control commands follow these rules:
+
+ Each control command can correspond to a maximum of `8` command words. If there are more than `8` command words, adding a new command word will replace the last one in the table.
+
+ The same voice command words cannot be added more than once.
+### LVGL Component
+ Here, we will introduce the porting interface of LVGL on BOX_S3.
+
+- Input Devices
+
+ * Input device hardware initialization, `indev_init_default()`
+ Depending on the type of input device, different initializations are performed. As mentioned in the `bsp_btn` section above, `BOARD_S3_BOX_LITE` uses 3 navigation key buttons, while `BOARD_S3_BOX` uses a TP (Touch Panel) in addition to 1 virtual TP button.
+
+ TP: Currently, the project has ported two touch panel chips, `tt21100` and `ft5x06`. After power-on, the `tp_prob` function detects different IIC addresses to identify the specific chip and performs different initialization actions through `indev_tp_init`.
+
+ Buttons: Initialized during the `bsp_btn` button initialization.
+
+ * Registering Input Devices `lv_port_indev_init()` -> `lv_indev_drv_register()`
+ Registering a device requires the `type` and `read_cb` parameters. Upon registration, an internal timer with a period of `LV_INDEV_DEF_READ_PERIOD` is created to poll external input events.
+
+
+- File System
+
+ * Redirecting File Operation APIs
+
+ This primarily involves redirecting APIs like `fopen`, `fclose`, `fwrite` based on the platform. LVGL provides encapsulations like `lv_fs_fatfs`, `lv_fs_posix`, `lv_fs_sdio`,`v_fs_win32` for reference and configuration. Users can configure this in menuconfig or implement their own.
+
+ * File Drive Letter Configuration
+
+ Espressif's file system drive letter is `'S'`. Users need to be aware that when `lv_fs` performs any file operation, it first checks if the drive letter matches. Drive letters that don't match will receive a return value of `LV_FS_RES_NOT_EX`, which affects normal file operations.
+
+- Display Interface
+Display initialization is mainly divided into two parts: hardware interface initialization and registration of display devices. The following diagram provides a simple overview of the initialization modules used in BOX and their interconnections.
+
+
| [Disassembly Tutorial for ESP32-S3-BOX V1](hardware_overview/esp32_s3_box/disassembly_tutorial_v1.md) | Not available |
-| ESP32-S3-BOX V2
| [Disassembly Tutorial for ESP32-S3-BOX V2](hardware_overview/esp32_s3_box/disassembly_tutorial_v2.md) |On sale now|
+| ESP32-S3-BOX V2
| [Disassembly Tutorial for ESP32-S3-BOX V2](hardware_overview/esp32_s3_box/disassembly_tutorial_v2.md) |Not available|
| ESP32-S3-BOX-Lite
| Please refer to ESP32-S3-BOX V2 as they are similar in structure.|On sale now|
\ No newline at end of file
diff --git a/docs/firmware_update.md b/docs/firmware_update.md
index 96e991f..d5a8ead 100644
--- a/docs/firmware_update.md
+++ b/docs/firmware_update.md
@@ -2,13 +2,16 @@
# Updating Firmware
+**Warning:**
+> The firmware released in the latest Tag branch (Version v0.5.0) is only applicable to ESP32-S3-BOX and ESP32-S3-BOX-Lite. We suggest that users update the firmware via Espressif's online firmware flashing tool **[ESP Launchpad](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://raw.githubusercontent.com/espressif/esp-box/master/launch.toml)**.
+
The BOX series development boards support updating firmware through USB. To update firmware, you only need:
1. A USB Type-C cable
2. Latest firmware (bin file)
**Important Note:**
-> If the downloading through USB fails, please hold down the `Boot` button and then press the `Reset` button to initiate Firmware Download mode.
+> If the downloading through USB fails, please hold down the `Boot` button and then press the `Reset` button to initiate Firmware Download mode manually.
## Downloading Latest Firmware
@@ -30,7 +33,7 @@ Please follow the link below corresponding to your OS to update the firmware.
|:----:|:----:|:----:|:----:|
|
| [
](#Updating-Firmware-for-Windows) | [
](#Updating-Firmware-for-Linux) | [
](#Updating-Firmware-for-macOS) |
-### Updating Firmware with ESP-Launchpad
+### Updating Firmware with ESP-Launchpad (Recommended)
ESP Launchpad is a web based tool, available for flashing firmware application to the ESP32 device connected via USB serial port. You can just click [here](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://raw.githubusercontent.com/espressif/esp-box/master/launch.toml) to start.
@@ -54,7 +57,7 @@ We recommend using `Windows 10` and above. Under `Windows 10` system, the driver
-4. Download [Windows download tool](https://www.espressif.com/sites/default/files/tools/flash_download_tool_3.9.2_0.zip) and unzip it to any folder. Then double-click to run the executable file `flash_download_tool_x.x.x.exe`.
+4. Download [Windows download tool](https://www.espressif.com/en/support/download/other-tools?keys=&field_type_tid%5B%5D=842), Flash Download Tools, and unzip it to any folder. Then double-click to run the executable file `flash_download_tool_x.x.x.exe`.
5. Please set `chipType` to `ESP32S3`, `workMode` to `develop`, `loadMode` to `usb`. Then, click `OK` to enter the download tool configuration interface.
@@ -137,7 +137,7 @@ More interestingly, the device supports continuous speech recognition after waki
## Voice Command Customization
-The BOX series of development boards are equipped with Espressif proprietary AI Speech Recognition System, which allows you to customize commands through our ESP BOX app. We will take the LED light on the module as an example, to show how to create your own voice commands. For algorithm details, please refer to [Technical Architecture](https://github.com/espressif/esp-box/blob/master/docs/technical_architecture.md).
+The BOX series of development boards are equipped with Espressif proprietary AI Speech Recognition System, which allows you to customize commands through our ESP BOX app. We will take the LED light on the module as an example, to show how to create your own voice commands. For algorithm details, please refer to [Technical Architecture](./technical_architecture.md).
**1. Connect to the ESP BOX mobile app**
@@ -219,7 +219,7 @@ The BOX series of development boards are equipped with Espressif proprietary AI
@@ -232,7 +232,7 @@ The BOX series of development boards are equipped with Espressif proprietary AI
**3. switch CN and EN voice model:**
-3.1. Click on your ESP-BOX `About Us` device icon to enter the `About Us` details page. In this page, press `Boot` button, the device will enter `factory Mode` language setting page, and then you can select the voice wake-up model by yourself.
+3.1. Click on your ESP-BOX `About Us` device icon to enter the `About Us` details page. In this page, press `Boot` button, the device will enter `factory Mode` language setting page, and then you can select the voice wake-up model by yourself. After switching the model, the device will reset and restart automatically.
diff --git a/docs/getting_started_cn.md b/docs/getting_started_cn.md
index 88b8c2a..8191bed 100644
--- a/docs/getting_started_cn.md
+++ b/docs/getting_started_cn.md
@@ -88,14 +88,14 @@
@@ -125,7 +125,7 @@
**使用方式**
-- 使用“hi,乐鑫”唤醒设备,唤醒后设备播放提示音“我在”。
+- 使用“Hi,乐鑫”唤醒设备,唤醒后设备播放提示音“我在”。
- 说出命令词。如设备识别出命令词,则会播放提示音“好的”,然后将继续识别其他命令词。
- 如设备未识别命令词则会继续等待,6 秒内没有新命令将自动退出语音控制界面,使用语音识别功能需要再次唤醒设备。
@@ -168,7 +168,7 @@
> 上述命令词仅供演示,由于没有接入相关智能设备,所以无法实现命令词功能。
## 语音命令词自定义
-BOX 系列开发板配备乐鑫专有的 AI 语音识别系统,您可以通过 ESP BOX 应用程序自定义任意命令词。我们将以模块上的 LED 灯为例,介绍如何自定义语音命令词。如需了解算法详细信息,请参阅[技术架构](https://github.com/espressif/esp-box/blob/master/docs/technical_architecture_cn.md)。
+BOX 系列开发板配备乐鑫专有的 AI 语音识别系统,您可以通过 ESP BOX 应用程序自定义任意命令词。我们将以模块上的 LED 灯为例,介绍如何自定义语音命令词。如需了解算法详细信息,请参阅[技术架构](./technical_architecture_cn.md)。
**1. 连接 ESP BOX 手机应用程序**
@@ -253,7 +253,7 @@ BOX 系列开发板配备乐鑫专有的 AI 语音识别系统,您可以通过
@@ -266,7 +266,7 @@ BOX 系列开发板配备乐鑫专有的 AI 语音识别系统,您可以通过
**3. 中英文语音模型切换:**
-3.1. 点按您的 ESP-BOX `About Us` 设备图标,进入 `About Us` 详情页。在此界面,按下 `Boot` 按键,设备会快速进入 `factory Mode` 语言设置页面,用户可以自行设置语音的唤醒模型。
+3.1. 点按您的 ESP-BOX `About Us` 设备图标,进入 `About Us` 详情页。在此界面,按下 `Boot` 按键,设备会快速进入 `factory Mode` 语言设置页面,用户可以自行设置语音的唤醒模型。模型切换后设备将自动重置重启。
diff --git a/docs/technical_architecture.md b/docs/technical_architecture.md
index c9b5510..28aff16 100644
--- a/docs/technical_architecture.md
+++ b/docs/technical_architecture.md
@@ -14,7 +14,7 @@ ESP-IDF is the open-source development framework for Espressif SoCs including ES
1. System-level basic components, mainly including multi-tasking, multi-core support based on FreeRTOS, and memory heap allocator with external expansion of PSRAM; a uniform operation interface support for LL, HAL, Driver, and VFS layers of multiple ESP chips; multiple standard network protocol stacks like TCP/IP, HTTP, MQTT, WebSocket, etc.
2. Set of development tools, mainly including GCC cross-toolchain for code building, JTAG debugging tool based on OpenOCD, real-time tracking based on Segger SystemView, Flash and eFuse programmers, etc.
-3. Development guidance documents, API references, guidelines, and notes of Espressif’s various chip platforms and software versions. Developers can view these documents [Online](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/).
+3. Development guidance documents, API references, guidelines, and notes of Espressif’s various chip platforms and software versions. Developers can view these documents [online](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/).
### Framework Layer
@@ -25,7 +25,7 @@ In addition to system-level support, ESP-BOX also integrates several excellent s
ESP-SR is a speech recognition framework developed by Espressif for the field of intelligent speech. ESP-SR can provide high-performance and high-reliability speech recognition functions for developers by using ESP32-S3 AI extension instructions. Now, this framework has three modules:
1. Espressif's acoustic algorithm ([Audio Front-End, AFE](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/acoustic_algorithm)), which is specially designed to improve speech recognition performance in far-field or noisy environments to enable developers to obtain high-quality and stable audio data. It mainly includes AEC (Acoustic Echo Cancellation), BSS (Blind Source Separation), NS (Noise Suppression). ESP-SR encapsulates the above algorithms into simple APIs. Without undersatanding details of these algorithms, developers only need to arrange and combine the algorithms that need to be used for specific application scenarios, and input the voice data to be processed according to the API format requirements and can get the results.
-2. Espressif wake-up word engine ([WakeNet](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/README.md)), which is used to monitor specific language fragments in real-time in a continuous audio streaming, and wake up the smart device from the standby state to the voice interaction state. WakeNet uses MFC (Mel-frequency Cepstrum) to obtain the features of the input audio clip, then classifies the characteristic signals by the neural network algorithm optimized for ESP32-S3. That can trigger the wake-up signal when analyzed the command word, and the [Effective recognition rate](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/README.md#performance-test) is more than 80% in a noisy environment. ESP-BOX provides different offline wake words like "Hi, ESP" or "Hi, Lexin". And also allows [customized wake word](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/ESP_Wake_Words_Customization.md).
+2. Espressif wake-up word engine ([WakeNet](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/README.md)), which is used to monitor specific language fragments in real-time in a continuous audio streaming, and wake up the smart device from the standby state to the voice interaction state. WakeNet uses MFC (Mel-frequency Cepstrum) to obtain the features of the input audio clip, then classifies the characteristic signals by the neural network algorithm optimized for ESP32-S3. That can trigger the wake-up signal when analyzed the command word, and the [effective recognition rate](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/README.md#performance-test) is more than 80% in a noisy environment. ESP-BOX provides different offline wake words like "Hi, ESP" or "Hi, Lexin". And also allows [customized wake word](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/ESP_Wake_Words_Customization.md).
3. Espressif multi-command recognization model ([MultiNet](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/speech_command_recognition/README.md)), which is designed to provide a flexible command recognition after the device is awakened. MultiNet supports both Chinese and English speech commands, like "Guan Bi Dian Deng", "Turn on the air conditioner" through a lightweight model specially designed based on CRNN and CTC, and supports up to 200 offline customized speech commands. The command words can be added and modified simply through configuring [Chinese Pinyin string](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/speech_command_recognition/README.md#modify-speech-commands) or [English Phonetic String](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/speech_command_recognition/README.md#modify-speech-commands) and the corresponding ID. Developers do not need to understand the details of the MultiNet nor re-train the model. the event will be triggered after the command words are recognized.
**ESP-HMI**
diff --git a/docs/technical_architecture_cn.md b/docs/technical_architecture_cn.md
index abadbe5..5bbdfcc 100644
--- a/docs/technical_architecture_cn.md
+++ b/docs/technical_architecture_cn.md
@@ -24,7 +24,7 @@ ESP-IDF 是乐鑫官方开源操作系统框架,同时兼容 ESP32、ESP32-S
ESP-SR 是乐鑫面向智能语音领域开发的语音识别框架,该框架可利用 ESP32-S3 AI 扩展指令进行运算加速,为开发者提供开箱即用的高性能、高可靠性的语音识别功能,它包括:
1. 声学前端([Audio Front-End, AFE](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/acoustic_algorithm))算法集,用于提升智能语音设备在远场噪声环境中的交互能力,使开发者获得高质量且稳定的音频数据。它主要包括可以有效滤除扬声器回声的回声消除算法(Acoustic Echo Cancellation,AEC), 用于强化麦克风阵列方向性的盲源分离算法(Blind Source Separation,BSS),和用于处理环境噪声的噪声抑制算法(Noise Suppression,NS)。ESP-SR 将以上算法封装成简单的 API,开发者无需关心这些算法的具体细节,只需要针对具体的应用场景,对需要使用的算法排列组合,并按照 API 的格式要求输入待处理的语音数据,即可得到声学前端算法的处理结果。
-2. 唤醒词识别模型([WakeNet](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/README.md)),用于在连续的音频流中实时监测出特定的语言片段,将智能设备从待机状态唤醒至语音交互状态。WakeNet 通过计算音频片段的梅尔倒频谱(Mel-Frequency Cepstrum, MFC)作为输入特征,使用针对 ESP32-S3 优化的神经网络算法对特征信号进行分类,在监测到命令词时触发唤醒信号,可在噪声环境下获得不小于 80% 的[有效识别率](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/README.md#performance-test)。ESP-BOX 提供了开箱即用的离线唤醒词 “Hi, ESP” 和 “Hi, 乐鑫”,开发者无需额外的开发工作即可使用,同时乐鑫也支持为开发者[定制独特的唤醒词](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/ESP_Wake_Words_Customization.md)。
+2. 唤醒词识别模型([WakeNet](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/README.md)),用于在连续的音频流中实时监测出特定的语言片段,将智能设备从待机状态唤醒至语音交互状态。WakeNet 通过计算音频片段的梅尔倒频谱(Mel-Frequency Cepstrum, MFC)作为输入特征,使用针对 ESP32-S3 优化的神经网络算法对特征信号进行分类,在监测到命令词时触发唤醒信号,可在噪声环境下获得不小于 80% 的[有效识别率](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/README.md#performance-test)。ESP-BOX 提供了开箱即用的离线唤醒词 “Hi, ESP” 和 “Hi, 乐鑫”,开发者无需额外的开发工作即可使用,同时乐鑫也支持为开发者[定制独特的唤醒词](https://github.com/espressif/esp-sr/blob/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/wake_word_engine/%E4%B9%90%E9%91%AB%E8%AF%AD%E9%9F%B3%E5%94%A4%E9%86%92%E8%AF%8D%E5%AE%9A%E5%88%B6%E6%B5%81%E7%A8%8B.md)。
3. 命令词识别模型([MultiNet](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/speech_command_recognition/README.md)),用于在设备唤醒后,识别用户特定的中英文语音命令,例如 “Turn on the air conditioner”,“关闭电灯” 等。MultiNet 通过基于 CRNN 和 CTC 的卷积循环神经网络,对输入音频片段进行多命令词识别,可同时支持最多 200 个离线命令词。 开发者不需要了解识别模型细节,也无需重新进行模型训练,通过简单配置[中文拼音字符串](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/speech_command_recognition/README.md#modify-speech-commands)或[英文音标字符串](https://github.com/espressif/esp-sr/tree/3ce34fe340af15e3bfb354c21c1ec2e6e31a37e8/docs/speech_command_recognition/README.md#modify-speech-commands)以及对应 ID,即可添加或修改命令词,模型在识别到语音命令词后将触发包含 ID 信息的事件。
**ESP-HMI**
diff --git a/examples/factory_demo/main/app/app_sr.c b/examples/factory_demo/main/app/app_sr.c
index 72cdd60..efd1b7c 100644
--- a/examples/factory_demo/main/app/app_sr.c
+++ b/examples/factory_demo/main/app/app_sr.c
@@ -31,6 +31,7 @@
#include "model_path.h"
#include "bsp_board.h"
#include "settings.h"
+#include "ui_mute.h"
static const char *TAG = "app_sr";
@@ -214,6 +215,11 @@ static void audio_feed_task(void *arg)
vTaskDelete(NULL);
}
+ if (false == get_mute_play_flag()) {
+ vTaskDelay(pdMS_TO_TICKS(500));
+ continue;
+ }
+
/* Read audio data from I2S bus */
bsp_codec_config_t *codec_handle = bsp_board_get_codec_handle();
codec_handle->i2s_read_fn((char *)audio_buffer, audio_chunksize * I2S_CHANNEL_NUM * sizeof(int16_t), &bytes_read, portMAX_DELAY);
diff --git a/examples/factory_demo/main/app/app_sr_handler.c b/examples/factory_demo/main/app/app_sr_handler.c
index a9c857f..ace2c70 100644
--- a/examples/factory_demo/main/app/app_sr_handler.c
+++ b/examples/factory_demo/main/app/app_sr_handler.c
@@ -25,7 +25,7 @@ static const char *TAG = "sr_handler";
static bool b_audio_playing = false;
-extern file_iterator_instance_t* file_iterator;
+extern file_iterator_instance_t *file_iterator;
typedef enum {
AUDIO_WAKE,
@@ -69,6 +69,7 @@ static esp_err_t sr_echo_play(audio_segment_t audio)
uint8_t *p = g_audio_data[audio].audio_buffer;
wav_header_t *wav_head = (wav_header_t *)p;
+
if (NULL == strstr((char *)wav_head->Subchunk1ID, "fmt") &&
NULL == strstr((char *)wav_head->Subchunk2ID, "data")) {
ESP_LOGE(TAG, "Header of wav format error");
@@ -80,22 +81,20 @@ static esp_err_t sr_echo_play(audio_segment_t audio)
ESP_LOGD(TAG, "frame_rate=%d, ch=%d, width=%d", wav_head->SampleRate, wav_head->NumChannels, wav_head->BitsPerSample);
codec_handle->i2s_reconfig_clk_fn(wav_head->SampleRate, wav_head->BitsPerSample, I2S_SLOT_MODE_STEREO);
- vTaskDelay(pdMS_TO_TICKS(500));
+ codec_handle->mute_set_fn(true);
codec_handle->mute_set_fn(false);
- codec_handle->volume_set_fn(85, NULL);
-
- sys_param_t *param = settings_get_parameter();
- codec_handle->volume_set_fn(param->volume, NULL);
- codec_handle->mute_set_fn(false);
- ESP_LOGD(TAG, "bsp_codec_set_voice_volume=%d", param->volume);
+ codec_handle->volume_set_fn(100, NULL);
+ size_t bytes_written = 0;
vTaskDelay(pdMS_TO_TICKS(50));
- size_t bytes_written = 0;
b_audio_playing = true;
codec_handle->i2s_write_fn((char *)p, len, &bytes_written, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(20));
b_audio_playing = false;
+
+ sys_param_t *param = settings_get_parameter();
+ codec_handle->volume_set_fn(param->volume, NULL);
return ESP_OK;
}
@@ -109,9 +108,9 @@ sr_language_t sr_detect_language()
static sr_language_t sr_current_lang = SR_LANG_MAX;
esp_err_t ret;
FILE *fp = NULL;
- const sys_param_t * param = settings_get_parameter();
+ const sys_param_t *param = settings_get_parameter();
- if(param->sr_lang^sr_current_lang){
+ if (param->sr_lang ^ sr_current_lang) {
sr_current_lang = param->sr_lang;
ESP_LOGI(TAG, "boardcast language change to = %s", (SR_LANG_EN == param->sr_lang ? "EN" : "CN"));
@@ -127,7 +126,7 @@ sr_language_t sr_detect_language()
ESP_GOTO_ON_FALSE(NULL != fp, ESP_ERR_NOT_FOUND, err, TAG, "Open file %s failed", audio_file);
size_t file_size = fm_get_file_size(audio_file);
- if(g_audio_data[i].audio_buffer){
+ if (g_audio_data[i].audio_buffer) {
heap_caps_free(g_audio_data[i].audio_buffer);
g_audio_data[i].len = 0;
}
@@ -141,19 +140,22 @@ sr_language_t sr_detect_language()
return sr_current_lang;
err:
- if(fp){
+ if (fp) {
fclose(fp);
}
return sr_current_lang;
}
void sr_handler_task(void *pvParam)
{
+ FILE *fp;
+ char filename[128];
+
sr_language_t sr_current_lang;
audio_player_state_t last_player_state = AUDIO_PLAYER_STATE_IDLE;
+
while (true) {
sr_result_t result;
app_sr_get_result(&result, portMAX_DELAY);
- char audio_file[48] = {0};
sr_current_lang = sr_detect_language();
@@ -163,6 +165,9 @@ void sr_handler_task(void *pvParam)
} else {
sr_anim_set_text("超时");
}
+ if (AUDIO_PLAYER_STATE_PLAYING == last_player_state) {
+ audio_player_pause();
+ }
#if !SR_RUN_TEST
sr_echo_play(AUDIO_END);
#endif
@@ -177,7 +182,6 @@ void sr_handler_task(void *pvParam)
sr_anim_start();
last_player_state = audio_player_get_state();
audio_player_pause();
-
if (SR_LANG_EN == sr_current_lang) {
sr_anim_set_text("Say command");
} else {
@@ -200,6 +204,13 @@ void sr_handler_task(void *pvParam)
}
#endif
+#if !SR_RUN_TEST
+ if (AUDIO_PLAYER_STATE_PLAYING == last_player_state) {
+ audio_player_pause();
+ }
+ sr_echo_play(AUDIO_OK);
+#endif
+
switch (cmd->cmd) {
case SR_CMD_SET_RED:
app_pwm_led_set_all(128, 0, 0);
@@ -224,9 +235,29 @@ void sr_handler_task(void *pvParam)
} break;
case SR_CMD_NEXT:
file_iterator_next(file_iterator);
+ file_iterator_get_full_path_from_index(file_iterator, file_iterator_get_index(file_iterator), filename, sizeof(filename));
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ ESP_LOGE(TAG, "unable to open '%s'", filename);
+ } else {
+ audio_player_play(fp);
+ }
+ last_player_state = AUDIO_PLAYER_STATE_PLAYING;
break;
case SR_CMD_PLAY:
- audio_player_resume();
+ ESP_LOGW(TAG, "SR_CMD_PLAY:%d, last_player_state:%d", audio_player_get_state(), last_player_state);
+
+ if(AUDIO_PLAYER_STATE_IDLE == audio_player_get_state()){
+ file_iterator_get_full_path_from_index(file_iterator, file_iterator_get_index(file_iterator), filename, sizeof(filename));
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ ESP_LOGE(TAG, "unable to open '%s'", filename);
+ } else {
+ audio_player_play(fp);
+ }
+ } else if(AUDIO_PLAYER_STATE_PAUSE == audio_player_get_state()){
+ audio_player_resume();
+ }
last_player_state = AUDIO_PLAYER_STATE_PLAYING;
break;
case SR_CMD_PAUSE:
@@ -237,14 +268,6 @@ void sr_handler_task(void *pvParam)
ESP_LOGE(TAG, "Unknow cmd");
break;
}
-#if !SR_RUN_TEST
- if (SR_LANG_EN == sr_current_lang) {
- strncpy(audio_file, "/spiffs/echo_en_ok.wav", sizeof(audio_file));
- } else {
- strncpy(audio_file, "/spiffs/echo_cn_ok.wav", sizeof(audio_file));
- }
- sr_echo_play(AUDIO_OK);
-#endif
}
}
vTaskDelete(NULL);
diff --git a/examples/factory_demo/main/gui/ui_about_us.c b/examples/factory_demo/main/gui/ui_about_us.c
index be08809..7d10b15 100644
--- a/examples/factory_demo/main/gui/ui_about_us.c
+++ b/examples/factory_demo/main/gui/ui_about_us.c
@@ -27,10 +27,10 @@ static void ui_about_us_page_return_click_cb(lv_event_t *e)
lv_group_remove_all_objs(ui_get_btn_op_group());
}
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
- bsp_btn_rm_all_callback(BOARD_BTN_ID_HOME);
+ bsp_btn_rm_event_callback(BOARD_BTN_ID_BOOT, BUTTON_SINGLE_CLICK);
#endif
lv_obj_del(obj);
- bsp_btn_rm_all_callback(BOARD_BTN_ID_BOOT);
+ bsp_btn_rm_event_callback(BOARD_BTN_ID_BOOT, BUTTON_SINGLE_CLICK);
if (g_about_us_end_cb) {
g_about_us_end_cb();
}
@@ -60,7 +60,7 @@ static void btn_factory_cb(void *handle, void *arg)
lv_group_remove_all_objs(ui_get_btn_op_group());
}
lv_obj_del(obj);
- bsp_btn_rm_all_callback(BOARD_BTN_ID_BOOT);
+ bsp_btn_rm_event_callback(BOARD_BTN_ID_BOOT, BUTTON_SINGLE_CLICK);
ui_factory_start(factory_end_cb);
ui_release();
diff --git a/examples/factory_demo/main/gui/ui_factory_mode.c b/examples/factory_demo/main/gui/ui_factory_mode.c
index 4e111c7..f82e7cd 100644
--- a/examples/factory_demo/main/gui/ui_factory_mode.c
+++ b/examples/factory_demo/main/gui/ui_factory_mode.c
@@ -60,6 +60,7 @@ static void ui_factory_page_save_click_cb(lv_event_t *e)
lv_task_handler(); vTaskDelay(50);
lv_obj_del(page);
ui_factory_page_return_click_cb(e);
+ esp_restart();
}
static void radio_event_handler(lv_event_t *e)
@@ -74,6 +75,11 @@ static void radio_event_handler(lv_event_t *e)
return;
}
+#if CONFIG_BSP_BOARD_ESP32_S3_BOX_Lite
+ lv_group_t *btn_op_group = ui_get_btn_op_group();
+ btn_op_group->editing = false;
+#endif
+
lv_obj_clear_state(old_cb, LV_STATE_CHECKED); /*Uncheck the previous radio button*/
lv_obj_add_state(act_cb, LV_STATE_CHECKED); /*Uncheck the current radio button*/
diff --git a/examples/factory_demo/main/gui/ui_main.c b/examples/factory_demo/main/gui/ui_main.c
index 84e032a..2161f74 100644
--- a/examples/factory_demo/main/gui/ui_main.c
+++ b/examples/factory_demo/main/gui/ui_main.c
@@ -437,6 +437,9 @@ static void ui_main_menu(int32_t index_id)
lv_obj_t *btn_prev = lv_btn_create(obj);
lv_obj_add_style(btn_prev, &ui_button_styles()->style_pr, LV_STATE_PRESSED);
+#if CONFIG_BSP_BOARD_ESP32_S3_BOX_Lite
+ lv_obj_remove_style(btn_prev, NULL, LV_STATE_PRESSED);
+#endif
lv_obj_add_style(btn_prev, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUS_KEY);
lv_obj_add_style(btn_prev, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUSED);
@@ -470,6 +473,9 @@ static void ui_main_menu(int32_t index_id)
lv_obj_t *btn_next = lv_btn_create(obj);
lv_obj_add_style(btn_next, &ui_button_styles()->style_pr, LV_STATE_PRESSED);
+#if CONFIG_BSP_BOARD_ESP32_S3_BOX_Lite
+ lv_obj_remove_style(btn_next, NULL, LV_STATE_PRESSED);
+#endif
lv_obj_add_style(btn_next, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUS_KEY);
lv_obj_add_style(btn_next, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUSED);
diff --git a/examples/factory_demo/main/gui/ui_mute.c b/examples/factory_demo/main/gui/ui_mute.c
index 22e5b95..66aa872 100644
--- a/examples/factory_demo/main/gui/ui_mute.c
+++ b/examples/factory_demo/main/gui/ui_mute.c
@@ -18,6 +18,12 @@ LV_FONT_DECLARE(font_en_16)
static int32_t mute_disp_count = 15;
static const int32_t disp_time = 15;
static bool mute_state = false;
+static bool mute_play_flag = true;
+
+bool get_mute_play_flag()
+{
+ return mute_play_flag;
+}
static void mute_timer_cb(lv_timer_t *timer)
{
@@ -37,6 +43,7 @@ static void mute_timer_cb(lv_timer_t *timer)
if ((mute_disp_count == 2) && (!mute_state)) {
bsp_codec_config_t *bsp_codec_config = bsp_board_get_codec_handle();
bsp_codec_config->codec_reconfig_fn();
+ mute_play_flag = true;
}
} else {
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
@@ -80,6 +87,9 @@ void ui_mute_init(void)
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
static void ui_mute_set_state(bool mute)
{
+ if (mute_state) {
+ mute_play_flag = false;
+ }
mute_state = mute;
mute_disp_count = 0;
}
diff --git a/examples/factory_demo/main/gui/ui_mute.h b/examples/factory_demo/main/gui/ui_mute.h
index fc4112c..e834c19 100644
--- a/examples/factory_demo/main/gui/ui_mute.h
+++ b/examples/factory_demo/main/gui/ui_mute.h
@@ -14,6 +14,7 @@ extern "C" {
#endif
void ui_mute_init(void);
+bool get_mute_play_flag();
#ifdef __cplusplus
}
diff --git a/examples/factory_demo/main/gui/ui_net_config.c b/examples/factory_demo/main/gui/ui_net_config.c
index 47dd310..ef39c9f 100644
--- a/examples/factory_demo/main/gui/ui_net_config.c
+++ b/examples/factory_demo/main/gui/ui_net_config.c
@@ -21,9 +21,12 @@ static lv_obj_t *g_qr = NULL;
static lv_obj_t *g_img = NULL;
static lv_obj_t *g_page = NULL;
static ui_net_state_t g_net_state = UI_NET_EVT_LOARDING;
+static lv_obj_t *g_btn_return = NULL;
static void (*g_net_config_end_cb)(void) = NULL;
+static void btn_return_down_cb(void *handle, void *arg);
+
static void ui_app_page_return_click_cb(lv_event_t *e)
{
lv_obj_t *obj = lv_event_get_user_data(e);
@@ -32,6 +35,7 @@ static void ui_app_page_return_click_cb(lv_event_t *e)
}
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
bsp_btn_rm_all_callback(BOARD_BTN_ID_HOME);
+ bsp_btn_register_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP, btn_return_down_cb, (void *)g_btn_return);
#endif
lv_obj_del(obj);
}
@@ -72,6 +76,7 @@ static void ui_net_config_page_app_click_cb(lv_event_t *e)
lv_obj_center(lab_btn_text);
lv_obj_add_event_cb(btn_return, ui_app_page_return_click_cb, LV_EVENT_CLICKED, page);
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
+ bsp_btn_rm_event_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP);
bsp_btn_register_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP, btn_return_down_cb, (void *)btn_return);
#endif
if (ui_get_btn_op_group()) {
@@ -112,6 +117,7 @@ static void ui_net_config_page_return_click_cb(lv_event_t *e)
#endif
lv_obj_del(obj);
g_page = NULL;
+ g_qr = NULL;
if (g_net_config_end_cb) {
g_net_config_end_cb();
}
@@ -211,24 +217,24 @@ void ui_net_config_start(void (*fn)(void))
lv_obj_set_style_shadow_opa(g_page, LV_OPA_30, LV_PART_MAIN);
lv_obj_align(g_page, LV_ALIGN_TOP_MID, 0, 40);
- lv_obj_t *btn_return = lv_btn_create(g_page);
- lv_obj_set_size(btn_return, 24, 24);
- lv_obj_add_style(btn_return, &ui_button_styles()->style, 0);
- lv_obj_add_style(btn_return, &ui_button_styles()->style_pr, LV_STATE_PRESSED);
- lv_obj_add_style(btn_return, &ui_button_styles()->style_focus, LV_STATE_FOCUS_KEY);
- lv_obj_add_style(btn_return, &ui_button_styles()->style_focus, LV_STATE_FOCUSED);
- lv_obj_align(btn_return, LV_ALIGN_TOP_LEFT, 0, 0);
- lv_obj_t *lab_btn_text = lv_label_create(btn_return);
+ g_btn_return = lv_btn_create(g_page);
+ lv_obj_set_size(g_btn_return, 24, 24);
+ lv_obj_add_style(g_btn_return, &ui_button_styles()->style, 0);
+ lv_obj_add_style(g_btn_return, &ui_button_styles()->style_pr, LV_STATE_PRESSED);
+ lv_obj_add_style(g_btn_return, &ui_button_styles()->style_focus, LV_STATE_FOCUS_KEY);
+ lv_obj_add_style(g_btn_return, &ui_button_styles()->style_focus, LV_STATE_FOCUSED);
+ lv_obj_align(g_btn_return, LV_ALIGN_TOP_LEFT, 0, 0);
+ lv_obj_t *lab_btn_text = lv_label_create(g_btn_return);
lv_label_set_text_static(lab_btn_text, LV_SYMBOL_LEFT);
lv_obj_set_style_text_color(lab_btn_text, lv_color_make(158, 158, 158), LV_STATE_DEFAULT);
lv_obj_center(lab_btn_text);
- lv_obj_add_event_cb(btn_return, ui_net_config_page_return_click_cb, LV_EVENT_CLICKED, g_page);
+ lv_obj_add_event_cb(g_btn_return, ui_net_config_page_return_click_cb, LV_EVENT_CLICKED, g_page);
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
- bsp_btn_register_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP, btn_return_down_cb, (void *)btn_return);
+ bsp_btn_register_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP, btn_return_down_cb, (void *)g_btn_return);
#endif
if (ui_get_btn_op_group()) {
- lv_group_add_obj(ui_get_btn_op_group(), btn_return);
+ lv_group_add_obj(ui_get_btn_op_group(), g_btn_return);
}
/* **************** APP NOT INSTALLED **************** */
diff --git a/examples/factory_demo/main/gui/ui_player.c b/examples/factory_demo/main/gui/ui_player.c
index ef4c293..74ce445 100644
--- a/examples/factory_demo/main/gui/ui_player.c
+++ b/examples/factory_demo/main/gui/ui_player.c
@@ -17,8 +17,15 @@ static const char *TAG = "ui_player";
static bool g_media_is_playing = false;
lv_obj_t *g_lab_file = NULL;
static void (*g_player_end_cb)(void) = NULL;
+lv_obj_t *lab_play_pause = NULL;
extern file_iterator_instance_t *file_iterator;
+lv_obj_t *player_page = NULL;
+
+lv_obj_t* get_player_page()
+{
+ return player_page;
+}
static void ui_player_page_vol_inc_click_cb(lv_event_t *e)
{
@@ -113,6 +120,7 @@ static void ui_player_page_return_click_cb(lv_event_t *e)
audio_player_callback_register(NULL, NULL);
settings_write_parameter_to_nvs(); // save volume to nvs
lv_obj_del(obj);
+ player_page = NULL;
if (g_player_end_cb) {
g_player_end_cb();
}
@@ -131,15 +139,34 @@ static void btn_return_down_cb(void *handle, void *arg)
static void audio_cb(audio_player_cb_ctx_t *ctx)
{
if (AUDIO_PLAYER_CALLBACK_EVENT_IDLE == ctx->audio_event) {
+ g_media_is_playing = false;
ui_acquire();
lv_label_set_text_static(g_lab_file, file_iterator_get_name_from_index(file_iterator, file_iterator_get_index(file_iterator)));
+ if(lab_play_pause) {
+ lv_label_set_text_static(lab_play_pause, LV_SYMBOL_PLAY);
+ }
ui_release();
- g_media_is_playing = false;
}
if ((AUDIO_PLAYER_CALLBACK_EVENT_PLAYING == ctx->audio_event) ||
(AUDIO_PLAYER_CALLBACK_EVENT_COMPLETED_PLAYING_NEXT == ctx->audio_event)) {
g_media_is_playing = true;
+ ui_acquire();
+ lv_label_set_text_static(g_lab_file, file_iterator_get_name_from_index(file_iterator, file_iterator_get_index(file_iterator)));
+ if(lab_play_pause) {
+ lv_label_set_text_static(lab_play_pause, LV_SYMBOL_PAUSE);
+ }
+ ui_release();
+ }
+
+ if (AUDIO_PLAYER_CALLBACK_EVENT_PAUSE == ctx->audio_event) {
+ g_media_is_playing = false;
+ ui_acquire();
+ lv_label_set_text_static(g_lab_file, file_iterator_get_name_from_index(file_iterator, file_iterator_get_index(file_iterator)));
+ if(lab_play_pause) {
+ lv_label_set_text_static(lab_play_pause, LV_SYMBOL_PLAY);
+ }
+ ui_release();
}
}
@@ -147,6 +174,7 @@ void ui_media_player(void (*fn)(void))
{
g_player_end_cb = fn;
lv_obj_t *page = lv_obj_create(lv_scr_act());
+ player_page = page;
lv_obj_set_size(page, lv_obj_get_width(lv_obj_get_parent(page)), lv_obj_get_height(lv_obj_get_parent(page)) - lv_obj_get_height(ui_main_get_status_bar()));
lv_obj_set_style_border_width(page, 0, LV_PART_MAIN);
lv_obj_set_style_bg_color(page, lv_obj_get_style_bg_color(lv_scr_act(), LV_STATE_DEFAULT), LV_PART_MAIN);
@@ -196,7 +224,7 @@ void ui_media_player(void (*fn)(void))
lv_obj_add_style(btn_play_pause, &ui_button_styles()->style_focus, LV_STATE_FOCUSED);
lv_obj_set_style_radius(btn_play_pause, 18, LV_STATE_DEFAULT);
lv_obj_align(btn_play_pause, LV_ALIGN_CENTER, 0, 0);
- lv_obj_t *lab_play_pause = lv_label_create(btn_play_pause);
+ lab_play_pause = lv_label_create(btn_play_pause);
g_media_is_playing = (audio_player_get_state() == AUDIO_PLAYER_STATE_PLAYING);
if (g_media_is_playing) {
lv_label_set_text_static(lab_play_pause, LV_SYMBOL_PAUSE);
diff --git a/examples/factory_demo/main/gui/ui_player.h b/examples/factory_demo/main/gui/ui_player.h
index 2379d8e..82dbe0d 100644
--- a/examples/factory_demo/main/gui/ui_player.h
+++ b/examples/factory_demo/main/gui/ui_player.h
@@ -14,6 +14,7 @@ extern "C" {
#endif
void ui_media_player(void (*fn)(void));
+lv_obj_t* get_player_page();
#ifdef __cplusplus
}
diff --git a/examples/factory_demo/main/gui/ui_sr.c b/examples/factory_demo/main/gui/ui_sr.c
index 2d71041..b1a8ce0 100644
--- a/examples/factory_demo/main/gui/ui_sr.c
+++ b/examples/factory_demo/main/gui/ui_sr.c
@@ -8,6 +8,7 @@
#include "bsp_board.h"
#include "lvgl.h"
#include "ui_main.h"
+#include "ui_player.h"
static const char *TAG = "ui_sr";
@@ -20,6 +21,8 @@ static lv_obj_t *g_sr_label = NULL;
static lv_obj_t *g_sr_mask = NULL;
static lv_obj_t *g_sr_bar[8] = {NULL};
+lv_timer_t * sr_timer;
+
static int int16_sin(int32_t deg)
{
static const int16_t sin_0_90_table[] = {
@@ -59,14 +62,17 @@ static void sr_label_event_handler(lv_event_t *event)
static void sr_mask_event_handler(lv_event_t *event)
{
bool active = (bool) event->param;
+ lv_obj_t * player_page = get_player_page();
if (active) {
+ if(player_page){
+ lv_obj_add_flag(player_page, LV_OBJ_FLAG_HIDDEN);
+ }
lv_indev_t *indev = lv_indev_get_next(NULL);
lv_indev_enable(indev, false);
g_sr_anim_count = 0;
g_sr_anim_active = true;
- lv_obj_clear_flag(g_sr_mask, LV_OBJ_FLAG_HIDDEN);
- lv_obj_move_foreground(g_sr_mask);
+ lv_timer_resume(sr_timer);
} else {
lv_indev_t *indev = lv_indev_get_next(NULL);
lv_indev_enable(indev, true);
@@ -77,6 +83,7 @@ static void sr_mask_event_handler(lv_event_t *event)
static void ui_speech_anim_cb(lv_timer_t *timer)
{
const int32_t step = 40;
+ lv_obj_t * player_page = get_player_page();
if (g_sr_anim_active) {
// /* Will hide hint message after wakeup */
@@ -92,6 +99,10 @@ static void ui_speech_anim_cb(lv_timer_t *timer)
lv_obj_move_foreground(g_sr_mask);
}
+ if(player_page){
+ lv_obj_add_flag(player_page, LV_OBJ_FLAG_HIDDEN);
+ }
+
/* Set bar value */
int32_t sr_val[4] = {
abs(int16_sin(g_sr_anim_count * step + step * 0)) / (32768 >> 7),
@@ -120,6 +131,10 @@ static void ui_speech_anim_cb(lv_timer_t *timer)
if (!lv_obj_has_flag(g_sr_mask, LV_OBJ_FLAG_HIDDEN)) {
lv_obj_add_flag(g_sr_mask, LV_OBJ_FLAG_HIDDEN);
}
+
+ if(player_page){
+ lv_obj_clear_flag(player_page, LV_OBJ_FLAG_HIDDEN);
+ }
}
}
}
@@ -178,7 +193,8 @@ void ui_sr_anim_init(void)
g_sr_anim_count = 0;
g_sr_anim_active = false;
- lv_timer_create(ui_speech_anim_cb, 500, NULL);
+ sr_timer = lv_timer_create(ui_speech_anim_cb, 500, NULL);
+ lv_timer_pause(sr_timer);
}
void sr_anim_start(void)
@@ -193,5 +209,8 @@ void sr_anim_stop(void)
void sr_anim_set_text(char *text)
{
- lv_event_send(g_sr_label, LV_EVENT_VALUE_CHANGED, (void *) text);
+ ui_acquire();
+ lv_label_set_text_static(g_sr_label, text);
+ ui_release();
}
+
diff --git a/examples/factory_demo/main/main.c b/examples/factory_demo/main/main.c
index 38dde5a..0d4b9ba 100644
--- a/examples/factory_demo/main/main.c
+++ b/examples/factory_demo/main/main.c
@@ -115,9 +115,9 @@ void app_main(void)
file_iterator = file_iterator_new("/spiffs/mp3");
assert(file_iterator != NULL);
audio_player_config_t config = { .mute_fn = audio_mute_function,
- .write_fn = codec_handle->i2s_write_fn,
- .clk_set_fn = codec_handle->i2s_reconfig_clk_fn,
- .priority = 5
+ .write_fn = codec_handle->i2s_write_fn,
+ .clk_set_fn = codec_handle->i2s_reconfig_clk_fn,
+ .priority = 5
};
ESP_ERROR_CHECK(audio_player_new(config));
diff --git a/examples/factory_demo/main/settings.c b/examples/factory_demo/main/settings.c
index 43aed1d..2795402 100644
--- a/examples/factory_demo/main/settings.c
+++ b/examples/factory_demo/main/settings.c
@@ -24,7 +24,7 @@ static sys_param_t g_sys_param = {0};
static const sys_param_t g_default_sys_param = {
.need_hint = 1,
.sr_lang = SR_LANG_EN,
- .volume = 70, // default volume is 70%
+ .volume = 100, // default volume is 100%
};
static esp_err_t settings_check(sys_param_t *param)
diff --git a/examples/image_display/README.md b/examples/image_display/README.md
index d84bc85..12ab7ca 100644
--- a/examples/image_display/README.md
+++ b/examples/image_display/README.md
@@ -11,7 +11,7 @@ Display PNG image with LVGL.
### Hardware Required
-* A ESP32-S3-Box
+* A ESP32-S3-Box or ESP32-S3-BOX-Lite
* An USB-C cable for power supply and programming
Follow detailed instructions provided specifically for this example.
diff --git a/examples/matter_switch/README.md b/examples/matter_switch/README.md
index ae8590e..8feb8a5 100644
--- a/examples/matter_switch/README.md
+++ b/examples/matter_switch/README.md
@@ -42,7 +42,7 @@ After flash the firmware, then use the chip-tool to pairing the matter network,
After pairing successfully, the s3 box will start displaying splash screen.
-
+
## 2.3 Open commissioning window and pairing using Homekit
@@ -61,16 +61,16 @@ After pairing using chip-tool, you can send below command to open commissioning
```
Then we can use the ***SetupQRCode: [MT:MH5B4BFN00KCTW7I200]*** or ***Manual pairing code: [36478701899]*** to paring to Homekit, as below show:
-
-
-
-
-
-
+
+
+
+
+
+
## 3. Post Commissioning Setup
-After Commissioning, we can bind threee matter on-off devices to the box switch and control them via touch screen and speech recognition.
+After Commissioning, we can bind three matter on-off devices to the box switch and control them via touch screen and speech recognition.
### 3.1 Bind on-off devices to switch
Using the chip-tool, commission 4 devices, the box matter-switch and 3 on-off devices, such as onoff light, fan, onoff plug.
@@ -118,8 +118,9 @@ After binding successfully, we can control the three onoff devices via touch scr
Enter the device control interface, click the *Light*, *Fan*, *Switch* buttons respectively to control the onoff light, fan and onoff plug.
-
-
+
+
+
#### Speech recognition control
@@ -136,8 +137,8 @@ Turn off the switch
to control the three onoff devices.
-
-
+
+
## 4 Factory Reset Matter Switch
diff --git a/examples/matter_switch/main/app/app_sr.c b/examples/matter_switch/main/app/app_sr.c
index 29c61a6..e7fd2fb 100644
--- a/examples/matter_switch/main/app/app_sr.c
+++ b/examples/matter_switch/main/app/app_sr.c
@@ -31,6 +31,7 @@
#include "model_path.h"
#include "bsp_board.h"
#include "settings.h"
+#include "ui_mute.h"
static const char *TAG = "app_sr";
@@ -218,6 +219,11 @@ static void audio_feed_task(void *arg)
vTaskDelete(NULL);
}
+ if (false == get_mute_play_flag()) {
+ vTaskDelay(pdMS_TO_TICKS(500));
+ continue;
+ }
+
/* Read audio data from I2S bus */
bsp_codec_config_t *codec_handle = bsp_board_get_codec_handle();
codec_handle->i2s_read_fn((char *)audio_buffer, audio_chunksize * I2S_CHANNEL_NUM * sizeof(int16_t), &bytes_read, portMAX_DELAY);
diff --git a/examples/matter_switch/main/app/app_sr_handler.c b/examples/matter_switch/main/app/app_sr_handler.c
index e009ec2..c6bc410 100644
--- a/examples/matter_switch/main/app/app_sr_handler.c
+++ b/examples/matter_switch/main/app/app_sr_handler.c
@@ -72,6 +72,8 @@ static esp_err_t sr_echo_play(audio_segment_t audio)
bsp_codec_config_t *codec_handle = bsp_board_get_codec_handle();
uint8_t *p = g_audio_data[audio].audio_buffer;
wav_header_t *wav_head = (wav_header_t *)p;
+
+
if (NULL == strstr((char *)wav_head->Subchunk1ID, "fmt") &&
NULL == strstr((char *)wav_head->Subchunk2ID, "data")) {
ESP_LOGE(TAG, "Header of wav format error");
@@ -83,22 +85,20 @@ static esp_err_t sr_echo_play(audio_segment_t audio)
ESP_LOGD(TAG, "frame_rate=%ld, ch=%d, width=%d", wav_head->SampleRate, wav_head->NumChannels, wav_head->BitsPerSample);
codec_handle->i2s_reconfig_clk_fn(wav_head->SampleRate, wav_head->BitsPerSample, I2S_SLOT_MODE_STEREO);
- vTaskDelay(pdMS_TO_TICKS(500));
+ codec_handle->mute_set_fn(true);
codec_handle->mute_set_fn(false);
- codec_handle->volume_set_fn(85, NULL);
-
- sys_param_t *param = settings_get_parameter();
- codec_handle->volume_set_fn(param->volume, NULL);
- codec_handle->mute_set_fn(false);
- ESP_LOGD(TAG, "bsp_codec_set_voice_volume=%d", param->volume);
+ codec_handle->volume_set_fn(100, NULL);
+ size_t bytes_written = 0;
vTaskDelay(pdMS_TO_TICKS(50));
- size_t bytes_written = 0;
b_audio_playing = true;
codec_handle->i2s_write_fn((char *)p, len, &bytes_written, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(20));
b_audio_playing = false;
+
+ sys_param_t *param = settings_get_parameter();
+ codec_handle->volume_set_fn(param->volume, NULL);
return ESP_OK;
}
@@ -114,7 +114,7 @@ sr_language_t sr_detect_language()
FILE *fp = NULL;
const sys_param_t * param = settings_get_parameter();
- if(param->sr_lang^sr_current_lang){
+ if (param->sr_lang ^ sr_current_lang) {
sr_current_lang = param->sr_lang;
ESP_LOGI(TAG, "boardcast language change to = %s", (SR_LANG_EN == param->sr_lang ? "EN" : "CN"));
@@ -151,12 +151,15 @@ err:
}
void sr_handler_task(void *pvParam)
{
+ FILE *fp;
+ char filename[128];
+
sr_language_t sr_current_lang;
audio_player_state_t last_player_state = AUDIO_PLAYER_STATE_IDLE;
+
while (true) {
sr_result_t result;
app_sr_get_result(&result, portMAX_DELAY);
- char audio_file[48] = {0};
sr_current_lang = sr_detect_language();
@@ -166,6 +169,9 @@ void sr_handler_task(void *pvParam)
} else {
sr_anim_set_text("超时");
}
+ if (AUDIO_PLAYER_STATE_PLAYING == last_player_state) {
+ audio_player_pause();
+ }
#if !SR_RUN_TEST
sr_echo_play(AUDIO_END);
#endif
@@ -203,6 +209,13 @@ void sr_handler_task(void *pvParam)
}
#endif
+#if !SR_RUN_TEST
+ if (AUDIO_PLAYER_STATE_PLAYING == last_player_state) {
+ audio_player_pause();
+ }
+ sr_echo_play(AUDIO_OK);
+#endif
+
switch (cmd->cmd) {
case SR_CMD_SET_RED:
app_pwm_led_set_all(128, 0, 0);
@@ -245,9 +258,29 @@ void sr_handler_task(void *pvParam)
} break;
case SR_CMD_NEXT:
file_iterator_next(file_iterator);
+ file_iterator_get_full_path_from_index(file_iterator, file_iterator_get_index(file_iterator), filename, sizeof(filename));
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ ESP_LOGE(TAG, "unable to open '%s'", filename);
+ } else {
+ audio_player_play(fp);
+ }
+ last_player_state = AUDIO_PLAYER_STATE_PLAYING;
break;
case SR_CMD_PLAY:
- audio_player_resume();
+ ESP_LOGW(TAG, "SR_CMD_PLAY:%d, last_player_state:%d", audio_player_get_state(), last_player_state);
+
+ if(AUDIO_PLAYER_STATE_IDLE == audio_player_get_state()){
+ file_iterator_get_full_path_from_index(file_iterator, file_iterator_get_index(file_iterator), filename, sizeof(filename));
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ ESP_LOGE(TAG, "unable to open '%s'", filename);
+ } else {
+ audio_player_play(fp);
+ }
+ } else if(AUDIO_PLAYER_STATE_PAUSE == audio_player_get_state()){
+ audio_player_resume();
+ }
last_player_state = AUDIO_PLAYER_STATE_PLAYING;
break;
case SR_CMD_PAUSE:
@@ -258,14 +291,6 @@ void sr_handler_task(void *pvParam)
ESP_LOGE(TAG, "Unknow cmd");
break;
}
-#if !SR_RUN_TEST
- if (SR_LANG_EN == sr_current_lang) {
- strncpy(audio_file, "/spiffs/echo_en_ok.wav", sizeof(audio_file));
- } else {
- strncpy(audio_file, "/spiffs/echo_cn_ok.wav", sizeof(audio_file));
- }
- sr_echo_play(AUDIO_OK);
-#endif
}
}
vTaskDelete(NULL);
diff --git a/examples/matter_switch/main/gui/ui_about_us.c b/examples/matter_switch/main/gui/ui_about_us.c
index be08809..7d10b15 100644
--- a/examples/matter_switch/main/gui/ui_about_us.c
+++ b/examples/matter_switch/main/gui/ui_about_us.c
@@ -27,10 +27,10 @@ static void ui_about_us_page_return_click_cb(lv_event_t *e)
lv_group_remove_all_objs(ui_get_btn_op_group());
}
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
- bsp_btn_rm_all_callback(BOARD_BTN_ID_HOME);
+ bsp_btn_rm_event_callback(BOARD_BTN_ID_BOOT, BUTTON_SINGLE_CLICK);
#endif
lv_obj_del(obj);
- bsp_btn_rm_all_callback(BOARD_BTN_ID_BOOT);
+ bsp_btn_rm_event_callback(BOARD_BTN_ID_BOOT, BUTTON_SINGLE_CLICK);
if (g_about_us_end_cb) {
g_about_us_end_cb();
}
@@ -60,7 +60,7 @@ static void btn_factory_cb(void *handle, void *arg)
lv_group_remove_all_objs(ui_get_btn_op_group());
}
lv_obj_del(obj);
- bsp_btn_rm_all_callback(BOARD_BTN_ID_BOOT);
+ bsp_btn_rm_event_callback(BOARD_BTN_ID_BOOT, BUTTON_SINGLE_CLICK);
ui_factory_start(factory_end_cb);
ui_release();
diff --git a/examples/matter_switch/main/gui/ui_factory_mode.c b/examples/matter_switch/main/gui/ui_factory_mode.c
index 4e111c7..f82e7cd 100644
--- a/examples/matter_switch/main/gui/ui_factory_mode.c
+++ b/examples/matter_switch/main/gui/ui_factory_mode.c
@@ -60,6 +60,7 @@ static void ui_factory_page_save_click_cb(lv_event_t *e)
lv_task_handler(); vTaskDelay(50);
lv_obj_del(page);
ui_factory_page_return_click_cb(e);
+ esp_restart();
}
static void radio_event_handler(lv_event_t *e)
@@ -74,6 +75,11 @@ static void radio_event_handler(lv_event_t *e)
return;
}
+#if CONFIG_BSP_BOARD_ESP32_S3_BOX_Lite
+ lv_group_t *btn_op_group = ui_get_btn_op_group();
+ btn_op_group->editing = false;
+#endif
+
lv_obj_clear_state(old_cb, LV_STATE_CHECKED); /*Uncheck the previous radio button*/
lv_obj_add_state(act_cb, LV_STATE_CHECKED); /*Uncheck the current radio button*/
diff --git a/examples/matter_switch/main/gui/ui_main.c b/examples/matter_switch/main/gui/ui_main.c
index 84e032a..2161f74 100644
--- a/examples/matter_switch/main/gui/ui_main.c
+++ b/examples/matter_switch/main/gui/ui_main.c
@@ -437,6 +437,9 @@ static void ui_main_menu(int32_t index_id)
lv_obj_t *btn_prev = lv_btn_create(obj);
lv_obj_add_style(btn_prev, &ui_button_styles()->style_pr, LV_STATE_PRESSED);
+#if CONFIG_BSP_BOARD_ESP32_S3_BOX_Lite
+ lv_obj_remove_style(btn_prev, NULL, LV_STATE_PRESSED);
+#endif
lv_obj_add_style(btn_prev, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUS_KEY);
lv_obj_add_style(btn_prev, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUSED);
@@ -470,6 +473,9 @@ static void ui_main_menu(int32_t index_id)
lv_obj_t *btn_next = lv_btn_create(obj);
lv_obj_add_style(btn_next, &ui_button_styles()->style_pr, LV_STATE_PRESSED);
+#if CONFIG_BSP_BOARD_ESP32_S3_BOX_Lite
+ lv_obj_remove_style(btn_next, NULL, LV_STATE_PRESSED);
+#endif
lv_obj_add_style(btn_next, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUS_KEY);
lv_obj_add_style(btn_next, &ui_button_styles()->style_focus_no_outline, LV_STATE_FOCUSED);
diff --git a/examples/matter_switch/main/gui/ui_mute.c b/examples/matter_switch/main/gui/ui_mute.c
index 22e5b95..66aa872 100644
--- a/examples/matter_switch/main/gui/ui_mute.c
+++ b/examples/matter_switch/main/gui/ui_mute.c
@@ -18,6 +18,12 @@ LV_FONT_DECLARE(font_en_16)
static int32_t mute_disp_count = 15;
static const int32_t disp_time = 15;
static bool mute_state = false;
+static bool mute_play_flag = true;
+
+bool get_mute_play_flag()
+{
+ return mute_play_flag;
+}
static void mute_timer_cb(lv_timer_t *timer)
{
@@ -37,6 +43,7 @@ static void mute_timer_cb(lv_timer_t *timer)
if ((mute_disp_count == 2) && (!mute_state)) {
bsp_codec_config_t *bsp_codec_config = bsp_board_get_codec_handle();
bsp_codec_config->codec_reconfig_fn();
+ mute_play_flag = true;
}
} else {
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
@@ -80,6 +87,9 @@ void ui_mute_init(void)
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
static void ui_mute_set_state(bool mute)
{
+ if (mute_state) {
+ mute_play_flag = false;
+ }
mute_state = mute;
mute_disp_count = 0;
}
diff --git a/examples/matter_switch/main/gui/ui_mute.h b/examples/matter_switch/main/gui/ui_mute.h
index fc4112c..e834c19 100644
--- a/examples/matter_switch/main/gui/ui_mute.h
+++ b/examples/matter_switch/main/gui/ui_mute.h
@@ -14,6 +14,7 @@ extern "C" {
#endif
void ui_mute_init(void);
+bool get_mute_play_flag();
#ifdef __cplusplus
}
diff --git a/examples/matter_switch/main/gui/ui_net_config.c b/examples/matter_switch/main/gui/ui_net_config.c
index 47dd310..ef39c9f 100644
--- a/examples/matter_switch/main/gui/ui_net_config.c
+++ b/examples/matter_switch/main/gui/ui_net_config.c
@@ -21,9 +21,12 @@ static lv_obj_t *g_qr = NULL;
static lv_obj_t *g_img = NULL;
static lv_obj_t *g_page = NULL;
static ui_net_state_t g_net_state = UI_NET_EVT_LOARDING;
+static lv_obj_t *g_btn_return = NULL;
static void (*g_net_config_end_cb)(void) = NULL;
+static void btn_return_down_cb(void *handle, void *arg);
+
static void ui_app_page_return_click_cb(lv_event_t *e)
{
lv_obj_t *obj = lv_event_get_user_data(e);
@@ -32,6 +35,7 @@ static void ui_app_page_return_click_cb(lv_event_t *e)
}
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
bsp_btn_rm_all_callback(BOARD_BTN_ID_HOME);
+ bsp_btn_register_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP, btn_return_down_cb, (void *)g_btn_return);
#endif
lv_obj_del(obj);
}
@@ -72,6 +76,7 @@ static void ui_net_config_page_app_click_cb(lv_event_t *e)
lv_obj_center(lab_btn_text);
lv_obj_add_event_cb(btn_return, ui_app_page_return_click_cb, LV_EVENT_CLICKED, page);
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
+ bsp_btn_rm_event_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP);
bsp_btn_register_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP, btn_return_down_cb, (void *)btn_return);
#endif
if (ui_get_btn_op_group()) {
@@ -112,6 +117,7 @@ static void ui_net_config_page_return_click_cb(lv_event_t *e)
#endif
lv_obj_del(obj);
g_page = NULL;
+ g_qr = NULL;
if (g_net_config_end_cb) {
g_net_config_end_cb();
}
@@ -211,24 +217,24 @@ void ui_net_config_start(void (*fn)(void))
lv_obj_set_style_shadow_opa(g_page, LV_OPA_30, LV_PART_MAIN);
lv_obj_align(g_page, LV_ALIGN_TOP_MID, 0, 40);
- lv_obj_t *btn_return = lv_btn_create(g_page);
- lv_obj_set_size(btn_return, 24, 24);
- lv_obj_add_style(btn_return, &ui_button_styles()->style, 0);
- lv_obj_add_style(btn_return, &ui_button_styles()->style_pr, LV_STATE_PRESSED);
- lv_obj_add_style(btn_return, &ui_button_styles()->style_focus, LV_STATE_FOCUS_KEY);
- lv_obj_add_style(btn_return, &ui_button_styles()->style_focus, LV_STATE_FOCUSED);
- lv_obj_align(btn_return, LV_ALIGN_TOP_LEFT, 0, 0);
- lv_obj_t *lab_btn_text = lv_label_create(btn_return);
+ g_btn_return = lv_btn_create(g_page);
+ lv_obj_set_size(g_btn_return, 24, 24);
+ lv_obj_add_style(g_btn_return, &ui_button_styles()->style, 0);
+ lv_obj_add_style(g_btn_return, &ui_button_styles()->style_pr, LV_STATE_PRESSED);
+ lv_obj_add_style(g_btn_return, &ui_button_styles()->style_focus, LV_STATE_FOCUS_KEY);
+ lv_obj_add_style(g_btn_return, &ui_button_styles()->style_focus, LV_STATE_FOCUSED);
+ lv_obj_align(g_btn_return, LV_ALIGN_TOP_LEFT, 0, 0);
+ lv_obj_t *lab_btn_text = lv_label_create(g_btn_return);
lv_label_set_text_static(lab_btn_text, LV_SYMBOL_LEFT);
lv_obj_set_style_text_color(lab_btn_text, lv_color_make(158, 158, 158), LV_STATE_DEFAULT);
lv_obj_center(lab_btn_text);
- lv_obj_add_event_cb(btn_return, ui_net_config_page_return_click_cb, LV_EVENT_CLICKED, g_page);
+ lv_obj_add_event_cb(g_btn_return, ui_net_config_page_return_click_cb, LV_EVENT_CLICKED, g_page);
#if CONFIG_BSP_BOARD_ESP32_S3_BOX
- bsp_btn_register_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP, btn_return_down_cb, (void *)btn_return);
+ bsp_btn_register_callback(BOARD_BTN_ID_HOME, BUTTON_PRESS_UP, btn_return_down_cb, (void *)g_btn_return);
#endif
if (ui_get_btn_op_group()) {
- lv_group_add_obj(ui_get_btn_op_group(), btn_return);
+ lv_group_add_obj(ui_get_btn_op_group(), g_btn_return);
}
/* **************** APP NOT INSTALLED **************** */
diff --git a/examples/matter_switch/main/gui/ui_player.c b/examples/matter_switch/main/gui/ui_player.c
index ef4c293..74ce445 100644
--- a/examples/matter_switch/main/gui/ui_player.c
+++ b/examples/matter_switch/main/gui/ui_player.c
@@ -17,8 +17,15 @@ static const char *TAG = "ui_player";
static bool g_media_is_playing = false;
lv_obj_t *g_lab_file = NULL;
static void (*g_player_end_cb)(void) = NULL;
+lv_obj_t *lab_play_pause = NULL;
extern file_iterator_instance_t *file_iterator;
+lv_obj_t *player_page = NULL;
+
+lv_obj_t* get_player_page()
+{
+ return player_page;
+}
static void ui_player_page_vol_inc_click_cb(lv_event_t *e)
{
@@ -113,6 +120,7 @@ static void ui_player_page_return_click_cb(lv_event_t *e)
audio_player_callback_register(NULL, NULL);
settings_write_parameter_to_nvs(); // save volume to nvs
lv_obj_del(obj);
+ player_page = NULL;
if (g_player_end_cb) {
g_player_end_cb();
}
@@ -131,15 +139,34 @@ static void btn_return_down_cb(void *handle, void *arg)
static void audio_cb(audio_player_cb_ctx_t *ctx)
{
if (AUDIO_PLAYER_CALLBACK_EVENT_IDLE == ctx->audio_event) {
+ g_media_is_playing = false;
ui_acquire();
lv_label_set_text_static(g_lab_file, file_iterator_get_name_from_index(file_iterator, file_iterator_get_index(file_iterator)));
+ if(lab_play_pause) {
+ lv_label_set_text_static(lab_play_pause, LV_SYMBOL_PLAY);
+ }
ui_release();
- g_media_is_playing = false;
}
if ((AUDIO_PLAYER_CALLBACK_EVENT_PLAYING == ctx->audio_event) ||
(AUDIO_PLAYER_CALLBACK_EVENT_COMPLETED_PLAYING_NEXT == ctx->audio_event)) {
g_media_is_playing = true;
+ ui_acquire();
+ lv_label_set_text_static(g_lab_file, file_iterator_get_name_from_index(file_iterator, file_iterator_get_index(file_iterator)));
+ if(lab_play_pause) {
+ lv_label_set_text_static(lab_play_pause, LV_SYMBOL_PAUSE);
+ }
+ ui_release();
+ }
+
+ if (AUDIO_PLAYER_CALLBACK_EVENT_PAUSE == ctx->audio_event) {
+ g_media_is_playing = false;
+ ui_acquire();
+ lv_label_set_text_static(g_lab_file, file_iterator_get_name_from_index(file_iterator, file_iterator_get_index(file_iterator)));
+ if(lab_play_pause) {
+ lv_label_set_text_static(lab_play_pause, LV_SYMBOL_PLAY);
+ }
+ ui_release();
}
}
@@ -147,6 +174,7 @@ void ui_media_player(void (*fn)(void))
{
g_player_end_cb = fn;
lv_obj_t *page = lv_obj_create(lv_scr_act());
+ player_page = page;
lv_obj_set_size(page, lv_obj_get_width(lv_obj_get_parent(page)), lv_obj_get_height(lv_obj_get_parent(page)) - lv_obj_get_height(ui_main_get_status_bar()));
lv_obj_set_style_border_width(page, 0, LV_PART_MAIN);
lv_obj_set_style_bg_color(page, lv_obj_get_style_bg_color(lv_scr_act(), LV_STATE_DEFAULT), LV_PART_MAIN);
@@ -196,7 +224,7 @@ void ui_media_player(void (*fn)(void))
lv_obj_add_style(btn_play_pause, &ui_button_styles()->style_focus, LV_STATE_FOCUSED);
lv_obj_set_style_radius(btn_play_pause, 18, LV_STATE_DEFAULT);
lv_obj_align(btn_play_pause, LV_ALIGN_CENTER, 0, 0);
- lv_obj_t *lab_play_pause = lv_label_create(btn_play_pause);
+ lab_play_pause = lv_label_create(btn_play_pause);
g_media_is_playing = (audio_player_get_state() == AUDIO_PLAYER_STATE_PLAYING);
if (g_media_is_playing) {
lv_label_set_text_static(lab_play_pause, LV_SYMBOL_PAUSE);
diff --git a/examples/matter_switch/main/gui/ui_player.h b/examples/matter_switch/main/gui/ui_player.h
index 2379d8e..82dbe0d 100644
--- a/examples/matter_switch/main/gui/ui_player.h
+++ b/examples/matter_switch/main/gui/ui_player.h
@@ -14,6 +14,7 @@ extern "C" {
#endif
void ui_media_player(void (*fn)(void));
+lv_obj_t* get_player_page();
#ifdef __cplusplus
}
diff --git a/examples/matter_switch/main/gui/ui_sr.c b/examples/matter_switch/main/gui/ui_sr.c
index 2d71041..145481d 100644
--- a/examples/matter_switch/main/gui/ui_sr.c
+++ b/examples/matter_switch/main/gui/ui_sr.c
@@ -8,6 +8,7 @@
#include "bsp_board.h"
#include "lvgl.h"
#include "ui_main.h"
+#include "ui_player.h"
static const char *TAG = "ui_sr";
@@ -20,6 +21,8 @@ static lv_obj_t *g_sr_label = NULL;
static lv_obj_t *g_sr_mask = NULL;
static lv_obj_t *g_sr_bar[8] = {NULL};
+lv_timer_t * sr_timer;
+
static int int16_sin(int32_t deg)
{
static const int16_t sin_0_90_table[] = {
@@ -59,14 +62,17 @@ static void sr_label_event_handler(lv_event_t *event)
static void sr_mask_event_handler(lv_event_t *event)
{
bool active = (bool) event->param;
+ lv_obj_t * player_page = get_player_page();
if (active) {
+ if(player_page){
+ lv_obj_add_flag(player_page, LV_OBJ_FLAG_HIDDEN);
+ }
lv_indev_t *indev = lv_indev_get_next(NULL);
lv_indev_enable(indev, false);
g_sr_anim_count = 0;
g_sr_anim_active = true;
- lv_obj_clear_flag(g_sr_mask, LV_OBJ_FLAG_HIDDEN);
- lv_obj_move_foreground(g_sr_mask);
+ lv_timer_resume(sr_timer);
} else {
lv_indev_t *indev = lv_indev_get_next(NULL);
lv_indev_enable(indev, true);
@@ -77,6 +83,7 @@ static void sr_mask_event_handler(lv_event_t *event)
static void ui_speech_anim_cb(lv_timer_t *timer)
{
const int32_t step = 40;
+ lv_obj_t * player_page = get_player_page();
if (g_sr_anim_active) {
// /* Will hide hint message after wakeup */
@@ -92,6 +99,10 @@ static void ui_speech_anim_cb(lv_timer_t *timer)
lv_obj_move_foreground(g_sr_mask);
}
+ if(player_page){
+ lv_obj_add_flag(player_page, LV_OBJ_FLAG_HIDDEN);
+ }
+
/* Set bar value */
int32_t sr_val[4] = {
abs(int16_sin(g_sr_anim_count * step + step * 0)) / (32768 >> 7),
@@ -120,6 +131,10 @@ static void ui_speech_anim_cb(lv_timer_t *timer)
if (!lv_obj_has_flag(g_sr_mask, LV_OBJ_FLAG_HIDDEN)) {
lv_obj_add_flag(g_sr_mask, LV_OBJ_FLAG_HIDDEN);
}
+
+ if(player_page){
+ lv_obj_clear_flag(player_page, LV_OBJ_FLAG_HIDDEN);
+ }
}
}
}
@@ -178,7 +193,8 @@ void ui_sr_anim_init(void)
g_sr_anim_count = 0;
g_sr_anim_active = false;
- lv_timer_create(ui_speech_anim_cb, 500, NULL);
+ sr_timer = lv_timer_create(ui_speech_anim_cb, 500, NULL);
+ lv_timer_pause(sr_timer);
}
void sr_anim_start(void)
@@ -193,5 +209,8 @@ void sr_anim_stop(void)
void sr_anim_set_text(char *text)
{
- lv_event_send(g_sr_label, LV_EVENT_VALUE_CHANGED, (void *) text);
+ ui_acquire();
+ lv_label_set_text_static(g_sr_label, text);
+ ui_release();
}
+
diff --git a/examples/mp3_demo/README.md b/examples/mp3_demo/README.md
index cc5e072..990404d 100644
--- a/examples/mp3_demo/README.md
+++ b/examples/mp3_demo/README.md
@@ -3,7 +3,7 @@
| Board | Support Status |
| ----------------- | -------------- |
| ESP32-S3-BOX | YES |
-| ESP32-S3-BOX-Lite | NO |
+| ESP32-S3-BOX-Lite | YES |
Play MP3 music on ESP-BOX.
@@ -15,7 +15,7 @@ We will support switching the sample rate and the number of channels in the next
### Hardware Required
-* A ESP32-S3-Box
+* A ESP32-S3-Box or ESP32-S3-BOX-Lite
* An USB-C cable for power supply and programming
Follow detailed instructions provided specifically for this example.
diff --git a/examples/usb_headset/README.md b/examples/usb_headset/README.md
index ed30003..9e97880 100644
--- a/examples/usb_headset/README.md
+++ b/examples/usb_headset/README.md
@@ -1,4 +1,4 @@
-# MP3 Player Example
+# USB Headset Example
| Board | Support Status |
| ----------------- | -------------- |
@@ -11,7 +11,7 @@ This demo makes ESP32-S3-BOX work as a USB headset that can play music and recor
### Hardware Required
-* A ESP32-S3-Box
+* A ESP32-S3-Box or ESP32-S3-BOX-Lite
* An USB-C cable for power supply and programming
Follow detailed instructions provided specifically for this example.
diff --git a/examples/watering_demo/README.md b/examples/watering_demo/README.md
index fad62e4..8f1f3fd 100644
--- a/examples/watering_demo/README.md
+++ b/examples/watering_demo/README.md
@@ -1,6 +1,12 @@
# Watering System Example
-The example is a prototype that simulates a smart watering system. The example utilizes ESP32-S3-BOX or ESP32-S3-BOX-Lite (both referred to as ESP-BOX in the following text) as a control panel, providing cloud connection capability as well as a voice control function. It also supports remote control from a mobile app using ESP RainMaker.
+| Board | Support Status |
+| ----------------- | -------------- |
+| ESP32-S3-BOX | YES |
+| ESP32-S3-BOX-Lite | YES |
+
+The example is a prototype that simulates a smart watering system. The example utilizes ESP-BOX as a control panel, providing cloud connection capability as well as a voice control function. It also supports remote control from a mobile app using ESP RainMaker.
+
This is the overview of the watering system:
@@ -76,7 +82,7 @@ Then connect your ESP-BOX to your computer and check under which serial port the
On Windows, you can check the port in the Windows Device Manager. For more information, please refer to [Establish Serial Connection with ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/establish-serial-connection.html).
-Please note that the ESP-IDF supported by ESP-BOX is [ESP-IDF v4.4](https://github.com/espressif/esp-idf/tree/release/v4.4), and the corresponding commit ID is 2bdea81b2a. You need to switch to ESP-IDF v4.4 using the following command. For details, please refer to [Readme of ESP-BOX](https://github.com/espressif/esp-box):
+Please note that the ESP-IDF supported by ESP-BOX is [ESP-IDF v5.1](https://docs.espressif.com/projects/esp-idf/en/release-v5.1/esp32s3/index.html), and the corresponding commit ID is 22cfbf30c3. You need to switch to ESP-IDF v5.1 using the following command. For details, please refer to [Readme of ESP-BOX](https://github.com/espressif/esp-box):
```
cd esp-idf
@@ -124,7 +130,7 @@ After powering up the device, you can see the current humidity on the LCD screen
It is recommended to use the ESP RainMaker app available for mobile phones to remotely control the pump. The app can be found here:
-- Android: [Google PlayStore](https://play.google.com/store/apps/details?id=com.espressif.rainmaker), [Direct APK](https://github.com/espressif/esp-rainmaker/wiki)
+- Android: [Google Play Store](https://play.google.com/store/apps/details?id=com.espressif.rainmaker), [Direct APK](https://github.com/espressif/esp-rainmaker/wiki)
- iOS: [Apple APP Store](https://apps.apple.com/app/esp-rainmaker/id1497491540)
Follow the following steps on the phone app:
@@ -159,7 +165,7 @@ You can set the threshold of the humidity in the LowerHumidity. If the real-time
## Voice Control
-ESP-BOX supports voice control, so you can also control this watering system by voice commands. The following commands are available:
+ESP-BOX supports voice control, so you can also control this watering system by voice commands. The following Chinese Pinyin commands are available:
* "hi, lexin" -- wake up the ESP32-S3-BOX
diff --git a/examples/watering_demo/images/connection_diagram.png b/examples/watering_demo/images/connection_diagram.png
index 48fa7a7..8418937 100644
Binary files a/examples/watering_demo/images/connection_diagram.png and b/examples/watering_demo/images/connection_diagram.png differ