Merge branch 'bugfix/fix_all_demo' into 'master'

examples: fix some bugs; update docs.

See merge request ae_group/esp-box!72
This commit is contained in:
Xu Xin
2023-08-17 14:51:54 +08:00
48 changed files with 700 additions and 221 deletions
-45
View File
@@ -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
@@ -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
+10 -9
View File
@@ -5,8 +5,8 @@
<p align="left">
<a href="https://github.com/espressif/esp-box/blob/master/LICENSE" alt="Build examples">
<img alt="GitHub" src="https://img.shields.io/github/license/espressif/esp-box"></a>
<a href="https://github.com/espressif/esp-box/actions/workflows/build.yml" alt="Build examples">
<img src="https://github.com/espressif/esp-box/actions/workflows/build.yml/badge.svg" /></a>
<a href="https://github.com/espressif/esp-box/actions/workflows/build_IDF5.1.yml" alt="Build examples">
<img src="https://github.com/espressif/esp-box/actions/workflows/build_IDF5.1.yml/badge.svg" /></a>
<a href="https://github.com/espressif/esp-box/graphs/contributors" alt="Contributors">
<img src="https://img.shields.io/github/contributors/espressif/esp-box" /></a>
<a href="https://github.com/espressif/esp-box/releases" alt="GitHub all releases">
@@ -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<br/>commit id: 96119acc8b | Latest developing firmware <br/>esp-sr version: v1.3.3 | Compatible with ESP32-S3-BOX and ESP32-S3-BOX-Lite <br/>Use menuconfig to select board |
| master | >= release/v5.1<br/>commit id: 22cfbf30c3 | Latest developing firmware <br/>esp-sr components version: v1.3.4 | Compatible with ESP32-S3-BOX and ESP32-S3-BOX-Lite <br/>Use menuconfig to select board |
| Tag 0.5.0 | release/v5.1<br>commit id: 22cfbf30c3 | esp-sr components version: v1.3.4 | Compatible with ESP32-S3-BOX and ESP32-S3-BOX-Lite <br/>Use menuconfig to select board |
| Tag 0.3.0 | release/v4.4<br>commit id: 2bdea81b2a | esp-sr version: dev/v2.0<br>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<br/>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<br/>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
+11 -10
View File
@@ -6,8 +6,8 @@
<p align="left">
<a href="https://github.com/espressif/esp-box/blob/master/LICENSE" alt="Build examples">
<img alt="GitHub" src="https://img.shields.io/github/license/espressif/esp-box"></a>
<a href="https://github.com/espressif/esp-box/actions/workflows/build.yml" alt="Build examples">
<img src="https://github.com/espressif/esp-box/actions/workflows/build.yml/badge.svg" /></a>
<a href="https://github.com/espressif/esp-box/actions/workflows/build_IDF5.1.yml" alt="Build examples">
<img src="https://github.com/espressif/esp-box/actions/workflows/build_IDF5.1.yml/badge.svg" /></a>
<a href="https://github.com/espressif/esp-box/graphs/contributors" alt="Contributors">
<img src="https://img.shields.io/github/contributors/espressif/esp-box" /></a>
<a href="https://github.com/espressif/esp-box/releases" alt="GitHub all releases">
@@ -32,8 +32,9 @@ ESP-BOX 是乐鑫信息科技发布的新一代 AIoT 应用开发平台。ESP32-
| ESP-BOX | 依赖的 ESP-IDF | 分支信息 | 支持状态 |
| :-------: | :----------------------------------------------------------: | :----------------------------------------------------------: | ------------------------------------------------------- |
| master | >= release/v5.0<br/>commit id: 96119acc8b | Latest developing firmware <br/>esp-sr version: v1.3.3 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite<br/>使用 menuconfig 选择开发板 |
| Tag 0.3.0 | release/v4.4<br/>commit id: 2bdea81b2a | esp-sr version: dev/v2.0<br/>commit id: c873a35 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite |
| master | >= release/v5.1<br/>commit id: 22cfbf30c3 | Latest developing firmware <br/>esp-sr components version: v1.3.4 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite<br/>使用 menuconfig 选择开发板 |
| Tag 0.5.0 | release/v5.1<br/>commit id: 22cfbf30c3 | esp-sr components version: v1.3.4 | 兼容 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite<br/>使用 menuconfig 选择开发板 |
| Tag 0.3.0 | release/v4.4<br/>commit id: 22cfbf30c3 | esp-sr version: dev/v2.0<br/>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<br/>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<br/>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-IDFrelease/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-IDFrelease/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),为更多扩展设备开发驱动。
## 联系我们
+2
View File
@@ -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
+19 -2
View File
@@ -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;
+10 -2
View File
@@ -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;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

+271
View File
@@ -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.<br>
**bsp_i2c.c** provides an interface middleware for the i2c_bus.<br>
**bsp_i2s.c** provides an interface middleware for i2s.<br>
**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.
<div align="center">
<img src="./_static/development_guide_picture/LVGL_porting_EN.png">
</div>
+18 -19
View File
@@ -1,4 +1,5 @@
# 开发指南
* [English Version](./development_guide.md)
本文档旨在对用户从设置开发环境到应用开发提供帮助,以便使用基于 Espressif 的 ESP32-S3 芯片进行 AIoT 应用开发。
@@ -6,14 +7,14 @@
- 开发环境的安装
按照 [ESP-IDF 编程指南](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/get-started/index.html#get-started-get-prerequisites)的指引完成 esp-idf 开发环境的安装,尽管有图形化的IDE和插件,但是我们推荐您手动安装并使用命令提示行进行编译。
按照 [ESP-IDF 编程指南](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/get-started/index.html#get-started-get-prerequisites)的指引完成 esp-idf 开发环境的安装,尽管有图形化的 IDE和插件,但是我们推荐您手动安装并使用命令提示行进行编译。
按照以上指引完成的安装很可能并不是编译 esp-box 依赖的 esp-idf 版本,此时需要根据[版本说明](https://github.com/espressif/esp-box#versions)来切换 esp-idf 到指定的版本。以 commit id 为 2bdea81b2a 为例子,下面的命令将完成切换
按照以上指引完成的安装很可能并不是编译 esp-box 依赖的 esp-idf 版本,此时需要根据[版本说明](https://github.com/espressif/esp-box#versions)来切换 esp-idf 到指定的版本。以 commit id 为 22cfbf30c3 为例子,下面的命令将完成切换
```shell
cd esp-idf
git fetch
git checkout 2bdea81b2a
git checkout 22cfbf30c3
git submodule update --init --recursive
./install.sh
```
@@ -84,7 +85,7 @@ idf.py -p PORT flash monitor
请替换 PORT 为电脑识别到的端口名称,Linux 系统下通常为 `/dev/ttyACM0`
下载固件完成将会自动开始运行
固件下载完成将会自动开始运行
## 调试应用程序
@@ -111,13 +112,11 @@ idf.py -p PORT flash monitor
### bsp 组件
- boards
**bsp_board.c** 是系统调用文件,用以兼容不同硬件平台,目前 box 工程支持 [BOARD_S3_BOX](hardware_overview/esp32_s3_box/hardware_overview_for_box.md)[BOARD_S3_BOX_LITE](hardware_overview/esp32_s3_box_lite/hardware_overview_for_lite.md) 两个硬件平台。系统初始化后,根据 iic detect 到的不同器件地址判断当前运行在哪个硬件平台,以分别调用不同的硬件初始化接口。
**esp32_s3_box.c** 和 **esp32_s3_box_lite.c** 分别是 `BOARD_S3_BOX` 和 `BOARD_S3_BOX_LITE` 的具体硬件管脚配置和初始化实现。
**esp32_s3_box.c** 和 **esp32_s3_box_lite.c** 分别是 `BOARD_S3_BOX``BOARD_S3_BOX_LITE` 的具体硬件管脚配置和初始化实现。用户需要在 menuconfig 中手动选择当前运行在哪个硬件平台,以分别调用不同的硬件初始化接口。
- codec
**codec** 目录下为硬件所需要用到的 Micphoone 和 Speaker 驱动接口
**codec** 目录下为硬件所需要用到的 Microphone 和 Speaker 驱动接口
|`BOARD_S3_BOX_LITE`| |
| ------------- | -------|
| ADC Module | ES7243 |
@@ -132,10 +131,10 @@ idf.py -p PORT flash monitor
**bsp_btn.c** 是 box 的按键处理接口,该接口和 **iot button** 组件协同工作。**iot button** 维护 button 事件注册链表,并建立 1ms 按键查询机制 `button_create_com` 。
定时器会依次轮询 `bsp_btn_register_callback` 注册的按键事件,并根据按键的事件匹配触发应用层注册的回调函数 `CALL_EVENT_CB(ev)` 。
- `BOARD_S3_BOX` 有 `boot` 1 个物理按键, 中间红色小圆点为TP虚拟按键。
- `BOARD_S3_BOX` 有 1 个 `boot` 物理按键, 中间红色小圆点为 TP 虚拟按键。
boot 处理 wifi 的恢复出厂和中英文语言切换的触发功能。
- `BOARD_S3_BOX_LITE` 有 `boot` 1 个物理按键, `prev` `enter` `next` 3 个 ADC 按键。
- `BOARD_S3_BOX_LITE` 有 1 个 `boot` 物理按键, `prev` `enter` `next` 3 个 ADC 按键。
boot 功能同上,3 个 ADC 按键作为功能切换的导航键。
ADC 按键设计使用一路 [ADC](../hardware/esp32_s3_box_lite_Button_V1.1/schematic/SCH_ESP32-S3-BOX-Lite_Button_V1.1_20211125.pdf),分别接上不同电阻,用 ADC 值来区分哪一路按键被按下,这种方式节省了 IO 口资源。
@@ -153,8 +152,8 @@ idf.py -p PORT flash monitor
- `bsp_lcd_flush` 为 LVGL 通知驱动准备刷新接口,如果接口已经完成上一帧数据发送,接口会在此处调用 `esp_lcd_panel_ops.c/esp_lcd_panel_draw_bitmap` 将显示数据送至 SPI 接口。
### esp-sr 组件</br>
这里主要针对 SR 的一些应用接口展开介绍。</br>
### esp-sr 组件
这里主要针对 SR 的一些应用接口展开介绍。
* 配置文件介绍
```
@@ -198,7 +197,7 @@ idf.py -p PORT flash monitor
esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(&afe_config);
```
* 切换唤醒词和命令词模型</br>
* 切换唤醒词和命令词模型
```
/* 唤醒词模型切换 */
wn_name = esp_srmodel_filter(models, ESP_WN_PREFIX, (SR_LANG_EN == g_sr_data->lang ? "hiesp" : "hilexin"));
@@ -209,7 +208,7 @@ idf.py -p PORT flash monitor
esp_mn_iface_t *multinet = esp_mn_handle_from_name(mn_name);
model_iface_data_t *model_data = multinet->create(mn_name, 5760); //设置命令词模型
```
* 命令词设置接口</br>
* 命令词设置接口
```
/* 加载模型自带命令词模型
* 命令词模型可从 menuconfig 如下路径进行修改: TOP -> ESP_SPEECH_RECOGNITION -> commands
@@ -224,10 +223,10 @@ idf.py -p PORT flash monitor
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 与 sr 的接口</br>
`cmd_write_to_sr(&cmd)` 是 rainmaker 下发至 BOX 的语音指令修改接口。</br>
SR 控制命令按照如下规则:</br>
- 同一个控制命令最多对应 `8` 条命令词,如果超过 8 条,新增命令词将替换表中最后 1 条。
* rainmaker 与 sr 的接口
`cmd_write_to_sr(&cmd)` 是 rainmaker 下发至 BOX 的语音指令修改接口。
SR 控制命令按照如下规则:
- 同一个控制命令最多对应 `8` 条命令词,如果超过 `8` 条,新增命令词将替换表中最后 `1` 条。
- 相同语音命令词不允许重复添加。
### lvgl 组件
@@ -251,7 +250,7 @@ idf.py -p PORT flash monitor
* 重定向文件操作 API
主要是根据平台重定向 fopenfclosefwrite 等接口。LVGL 封装了 lv_fs_fatfs , lv_fs_posix , lv_fs_sdio , lv_fs_win32 可供参考和配置,用户可在 menuconfig 进行配置,也可以自己实现。
主要是根据平台重定向 `fopen``fclose``fwrite` 等接口。LVGL 封装了 `lv_fs_fatfs`, `lv_fs_posix`, `lv_fs_sdio`,`v_fs_win32` 可供参考和配置,用户可在 menuconfig 进行配置,也可以自己实现。
* 文件盘符配置
+1 -1
View File
@@ -5,5 +5,5 @@ The case of the BOX series products have three different versions. Please match
| Version | Tutorial |Note|
| :-----: | :---------------------: |:---------------------: |
| ESP32-S3-BOX V1 <img src="_static/disassembly_pictures/figure_10.png" width="350px"/> | [Disassembly Tutorial for ESP32-S3-BOX V1](hardware_overview/esp32_s3_box/disassembly_tutorial_v1.md) | Not available |
| ESP32-S3-BOX V2 <img src="_static/disassembly_pictures_v2/figure_10.png" width="350px"/> | [Disassembly Tutorial for ESP32-S3-BOX V2](hardware_overview/esp32_s3_box/disassembly_tutorial_v2.md) |On sale now|
| ESP32-S3-BOX V2 <img src="_static/disassembly_pictures_v2/figure_10.png" width="350px"/> | [Disassembly Tutorial for ESP32-S3-BOX V2](hardware_overview/esp32_s3_box/disassembly_tutorial_v2.md) |Not available|
| ESP32-S3-BOX-Lite <img src="_static/lite_back.png" width="350px"/> | Please refer to ESP32-S3-BOX V2 as they are similar in structure.|On sale now|
+6 -3
View File
@@ -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.
|:----:|:----:|:----:|:----:|
|<img alt="Try it with ESP Launchpad" src="https://espressif.github.io/esp-launchpad/assets/try_with_launchpad.png" width="200" height="56"> | [<img src="_static/windows-logo.png" width="40" align="center" />](#Updating-Firmware-for-Windows) | [<img src="_static/linux-logo.png" width="40" align="center" />](#Updating-Firmware-for-Linux) | [<img src="_static/macos-logo.jpg" width="40" align="center" />](#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
<img src="_static/device_manager_usb_serial_jtag.png" width="450">
</div>
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.
<div align="center">
+4 -3
View File
@@ -1,14 +1,15 @@
* [English Version](./firmware_update.md)
# 更新固件
**警告:**
> 当前 Tag 分支 (最新 Tag v0.5.0)发布的固件仅适用于 ESP32-S3-BOX 和 ESP32-S3-BOX-Lite。我们推荐用户通过乐鑫在线固件烧录工具 **[ESP Launchpad](https://espressif.github.io/esp-launchpad/?flashConfigURL=https://raw.githubusercontent.com/espressif/esp-box/master/launch.toml)** 来更新固件。
BOX 系列开发板支持使用 USB 接口更新固件,您仅需要准备:
1. 一根 USB Type-C 数据线
2. 最新版本固件(bin 文件)
**需要提醒:**
> 如遇 USB 下载失败,请按住 `Boot` 按键的同时按一下 `Reset` 按键进入“固件下载”模式。
> 如遇 USB 下载失败,请按住 `Boot` 按键的同时按一下 `Reset` 按键手动进入“固件下载”模式。
## 下载最新版本固件
@@ -54,7 +55,7 @@ ESP Launchpad 是一个基于 web 的 ESP32 固件下载工具,用户可以通
<img src="_static/device_manager_usb_serial_jtag_cn.png" width="450">
</div>
4. 下载 [Windows download tool](https://www.espressif.com/sites/default/files/tools/flash_download_tool_3.9.2_0.zip),并解压到任意文件夹,然后请双击打开下载工具可执行文件 `flash_download_tool_x.x.x.exe`
4. 下载 [Windows download tool](https://www.espressif.com/en/support/download/other-tools?keys=&field_type_tid%5B%5D=842)Flash Download Tools,并解压到任意文件夹,然后请双击打开下载工具可执行文件 `flash_download_tool_x.x.x.exe`
5. 请选择 `chipType``ESP32S3`, `workMode``develop`, `loadMode``usb`,之后点击 `OK` 进入下载工具界面:
<div align="center">
+5 -5
View File
@@ -86,14 +86,14 @@ Please refer to the pin definition below, and connect the RGB LED module to the
<img src="_static/_get_started_static/hardware_mute_button.jpg" width="350px">
</div>
5. Tap the red circle below the screen to return to the last page.
5. Tap the red circle located below the screen to go back to the previous page. This red circle serves as a customizable touch region, allowing users to customize extra touch capabilities according to their preferences.
<div align="center">
<img src="./_static/_get_started_static/hardware_home.png" width="350px">
</div>
## Offline Voice Assistant
1. You may say "hi E. S. P." at any screen to wake up your device. When it wakes up, the screen will display the wake word you just used. If the wake word is not displayed, give it another shot. The screen below indicates your device is listening.
1. You may say "Hi E. S. P." at any screen to wake up your device. When it wakes up, the screen will display the wake word you just used. If the wake word is not displayed, give it another shot. The screen below indicates your device is listening.
<div align="center">
<img src="./_static/_get_started_static/17.png">
@@ -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
<img src="_static/_get_started_static/12.jpeg"width="300" />
</div>
2.5 Now, you can try out your new command! First, say "hi E. S. P." to wake up your device. Then say "good morning" within 6 seconds to turn on the light. The new command will show on the screen with the module light turned on.
2.5 Now, you can try out your new command! First, say "Hi E. S. P." to wake up your device. Then say "good morning" within 6 seconds to turn on the light. The new command will show on the screen with the module light turned on.
<div align="center">
<img src="_static/_get_started_static/15.png">
@@ -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.
<div align="center">
<img src="_static/_get_started_static/language_select.png"width="300" />
+6 -6
View File
@@ -88,14 +88,14 @@
<img src="_static/_get_started_static/hardware_mute_button.jpg" width="350px">
</div>
5. 轻触屏幕下方的“小红圈”可返回上一页
5. 轻触屏幕下方的红色圆圈以返回上一页。红圈是一块可自定义的触摸区域,允许用户根据自己的喜好配置额外的触摸功能
<div align="center">
<img src="./_static/_get_started_static/hardware_home.png" width="350px">
</div>
## 离线语音识别
1. 您可以在任意界面使用唤醒词来唤醒设备,唤醒词为“hi 乐鑫”。设备唤醒后,唤醒词将显示在屏幕上并伴有提示音“我在”。如果唤醒词未出现,请再次尝试。出现如下界面表示您的设备正在倾听。
1. 您可以在任意界面使用唤醒词来唤醒设备,唤醒词为“Hi 乐鑫”。设备唤醒后,唤醒词将显示在屏幕上并伴有提示音“我在”。如果唤醒词未出现,请再次尝试。出现如下界面表示您的设备正在倾听。
<div align="center">
<img src="./_static/_get_started_static/16.png">
@@ -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 语音识别系统,您可以通过
<img src="_static/_get_started_static/12.jpeg"width="300" />
</div>
2.5. 现在,您可以体验新命令词了!请先使用“hi 乐鑫”唤醒设备,然后在 6 秒内说出打开电灯的新命令词“早上好”,新命令词将显示在屏幕上,同时模块上的 LED 灯会亮起。
2.5. 现在,您可以体验新命令词了!请先使用“Hi 乐鑫”唤醒设备,然后在 6 秒内说出打开电灯的新命令词“早上好”,新命令词将显示在屏幕上,同时模块上的 LED 灯会亮起。
<div align="center">
<img src="_static/_get_started_static/14.png"width="300" />
@@ -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` 语言设置页面,用户可以自行设置语音的唤醒模型。模型切换后设备将自动重置重启。
<div align="center">
<img src="_static/_get_started_static/language_select.png"width="300" />
+2 -2
View File
@@ -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 Espressifs 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 Espressifs 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**
+1 -1
View File
@@ -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 CancellationAEC), 用于强化麦克风阵列方向性的盲源分离算法(Blind Source SeparationBSS),和用于处理环境噪声的噪声抑制算法(Noise SuppressionNS)。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**
+6
View File
@@ -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);
+47 -24
View File
@@ -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);
+3 -3
View File
@@ -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();
@@ -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*/
+6
View File
@@ -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);
+10
View File
@@ -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;
}
+1
View File
@@ -14,6 +14,7 @@ extern "C" {
#endif
void ui_mute_init(void);
bool get_mute_play_flag();
#ifdef __cplusplus
}
+17 -11
View File
@@ -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 **************** */
+30 -2
View File
@@ -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);
@@ -14,6 +14,7 @@ extern "C" {
#endif
void ui_media_player(void (*fn)(void));
lv_obj_t* get_player_page();
#ifdef __cplusplus
}
+23 -4
View File
@@ -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();
}
+3 -3
View File
@@ -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));
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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.
+13 -12
View File
@@ -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.
<img src="docs/_static/_get_started_static/boot_animation.png" width="200px" />
<img src="../../docs/_static/_get_started_static/boot_animation.png" width="200px" />
## 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:
<img src="docs/_static/matter/apple1.png" width="200px" />
<img src="docs/_static/matter/apple2.png" width="200px" />
<img src="docs/_static/matter/apple3.png" width="200px" />
<img src="docs/_static/matter/apple4.png" width="200px" />
<img src="docs/_static/matter/apple5.png" width="200px" />
<img src="docs/_static/matter/apple6.png" width="200px" />
<img src="../../docs/_static/matter/apple1.png" width="200px" />
<img src="../../docs/_static/matter/apple2.png" width="200px" />
<img src="../../docs/_static/matter/apple3.png" width="200px" />
<img src="../../docs/_static/matter/apple4.png" width="200px" />
<img src="../../docs/_static/matter/apple5.png" width="200px" />
<img src="../../docs/_static/matter/apple6.png" width="200px" />
## 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.
<img src="docs/_static/_get_started_static/4.png" width="200px" />
<img src="docs/_static/_get_started_static/4.1.png" width="200px" />
<img src="../../docs/_static/_get_started_static/4.png" width="200px" />
<img src="../../docs/_static/_get_started_static/4.1.png" width="200px" />
#### Speech recognition control
@@ -136,8 +137,8 @@ Turn off the switch
to control the three onoff devices.
<img src="docs/_static/_get_started_static/17.png" width="200px" />
<img src="docs/_static/_get_started_static/21.png" width="200px" />
<img src="../../docs/_static/_get_started_static/17.png" width="200px" />
<img src="../../docs/_static/_get_started_static/21.png" width="200px" />
## 4 Factory Reset Matter Switch
+6
View File
@@ -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);
@@ -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);
@@ -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();
@@ -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*/
@@ -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);
+10
View File
@@ -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;
}
@@ -14,6 +14,7 @@ extern "C" {
#endif
void ui_mute_init(void);
bool get_mute_play_flag();
#ifdef __cplusplus
}
+17 -11
View File
@@ -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 **************** */
+30 -2
View File
@@ -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);
@@ -14,6 +14,7 @@ extern "C" {
#endif
void ui_media_player(void (*fn)(void));
lv_obj_t* get_player_page();
#ifdef __cplusplus
}
+23 -4
View File
@@ -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();
}
+2 -2
View File
@@ -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.
+2 -2
View File
@@ -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.
+10 -4
View File
@@ -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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 458 KiB