# 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. - codec The **codec** directory contains the driver interfaces for the Micphoone and Speaker that the hardware requires. |`BOARD_S3_BOX_LITE`| | | ------------- | -------| | ADC Module | ES7243 | | Codec Module | ES8153 | |`BOARD_S3_BOX `| | | ------------- | -------| | ADC Module | ES7210 | | Codec Module | ES8311 | - peripherals **bsp_btn.c** is the interface for handling buttons in the box, which works in conjunction with the **iot button** component. **iot button** maintains a registered list of button events and establishes a 1ms button query mechanism `button_create_com`. The timer will sequentially poll the button events registered by `bsp_btn_register_callback`, and trigger the callback functions registered by the application layer according to the event of the button through `CALL_EVENT_CB(ev)`. - `BOARD_S3_BOX` has 1 physical button named `boot` , and the middle red dot is a virtual TP button. The `boot` button handles functions such as restoring Wi-Fi settings to factory defaults and switching between Chinese and English languages. - `BOARD_S3_BOX_LITE` has 1 physical button named `boot` and 3 ADC buttons named `prev`, `enter`, and `next`. The `boot` function is the same as described above, and the 3 ADC buttons act as navigation keys for function switching. The ADC buttons are designed using a single [`ADC`](../hardware/esp32_s3_box_lite_Button_V1.1/schematic/SCH_ESP32-S3-BOX-Lite_Button_V1.1_20211125.pdf) line, connected to different resistors to distinguish which button is pressed based on the ADC value. This approach saves IO port resources. **bsp_codec.c** provides an interface middleware for the above codecs, unifying the calls to different codecs and ADC chips.
**bsp_i2c.c** provides an interface middleware for the i2c_bus.
**bsp_i2s.c** provides an interface middleware for i2s.
**bsp_lcd.c** provides an interface middleware for displaying hardware interfaces. - `bsp_spi_lcd_init`initializes the LCD's SPI interface based on the board's pin definition. - `lcd_trans_done_cb` is the callback function for SPI data transmission completion, ensuring synchronization with LVGL's graphics rendering logic. `p_on_trans_done_cb(p_user_data) `-> `lv_port_flush_ready` notifies the display to clear the `flushing` flag. - `bsp_lcd_flush` is an LVGL interface that notifies the driver to prepare for screen refresh. If the interface has finished sending data from the previous frame, this function calls `esp_lcd_panel_ops.c/esp_lcd_panel_draw_bitmap` to send the display data to the SPI interface. ### ESP-SR Component This section focuses on introducing some application interfaces of SR. * Configuration File Introduction ``` #define AFE_CONFIG_DEFAULT() { \ .aec_init = true, \ //Enable AEC algorithm .se_init = true, \ //Enable BSS/NS algorithm .vad_init = true, \ //Enable VAD (only usable in speech recognition scenes) .wakenet_init = true, \ //Enable wake word detection. .voice_communication_init = false, \ //Enable voice communication. Cannot be enabled at the same time as wakenet_init. .voice_communication_agc_init = false, \ //Enable AGC in voice communication. .voice_communication_agc_gain = 15, \ //AGC gain value in voice communication, in dB. .vad_mode = VAD_MODE_3, \ //VAD detection mode, higher value is more aggressive. .wakenet_model_name = NULL, \ //Select wake word model. .wakenet_mode = DET_MODE_2CH_90, \ //Wake word detection mode. Corresponds to the number of mic channels, choose according to mic channel count. .afe_mode = SR_MODE_LOW_COST, \ //SR_MODE_LOW_COST: Quantized version with less resource consumption. //SR_MODE_HIGH_PERF: Non-quantized version with higher resource consumption. .afe_perferred_core = 0, \ //The CPU core on which internal AFE BSS/NS/MISO algorithms run. .afe_perferred_priority = 5, \ //Task priority for internal AFE BSS/NS/MISO algorithms. .afe_ringbuf_size = 50, \ //Internal ring buffer size configuration. .memory_alloc_mode = \ AFE_MEMORY_ALLOC_MORE_PSRAM, \ //Allocate most of the memory from external psram .agc_mode = AFE_MN_PEAK_AGC_MODE_2, \ //Linear amplification of audio fed to multinet, peak value at -4dB. .pcm_config.total_ch_num = 3, \ //total_ch_num = mic_num + ref_num .pcm_config.mic_num = 2, \ //Number of microphone channels in the audio. Currently, only configurations of 1 or 2 are supported. .pcm_config.ref_num = 1, \ //Number of reference loop channels in the audio. Currently, only configurations of 0 or 1 are supported. } ``` * Model Initialization and Configuration ``` /* ESP_AFE_SR_HANDLE: Voice recognition model * ESP_AFE_VC_HANDLE: Voice communication model */ afe_handle = &ESP_AFE_SR_HANDLE; afe_config_t afe_config = AFE_CONFIG_DEFAULT(); /* Wake word model naming format: wm* * Command word model naming format: mn* * esp_srmodel_filter is an interface encapsulating model partition searching */ afe_config.wakenet_model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL); afe_config.aec_init = false; // Disable AEC esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(&afe_config); ``` * Switching Wake Word and Command Word Models ``` /* Switching wake word model */ wn_name = esp_srmodel_filter(models, ESP_WN_PREFIX, (SR_LANG_EN == g_sr_data->lang ? "hiesp" : "hilexin")); g_sr_data->afe_handle->set_wakenet(g_sr_data->afe_data, wn_name); // Set wake word model /* Switching command word model */ mn_name = esp_srmodel_filter(models, ESP_MN_PREFIX, ((SR_LANG_EN == g_sr_data->lang) ? ESP_MN_ENGLISH : ESP_MN_CHINESE)); esp_mn_iface_t *multinet = esp_mn_handle_from_name(mn_name); model_iface_data_t *model_data = multinet->create(mn_name, 5760); // Set command word model ``` * Command Word Configuration Interface ``` /* Load built-in command word model from the model * Command word model can be modified from the menuconfig path: TOP -> ESP_SPEECH_RECOGNITION -> commands */ esp_mn_commands_update_from_sdkconfig(*multinet, *model_data); /* Manual manipulation of command words in code * Users can use the following APIs to manipulate command words */ esp_err_t esp_mn_commands_add(command_id, *phoneme_string); esp_err_t esp_mn_commands_remove(*phoneme_string); esp_err_t esp_mn_commands_modify(*old_phoneme_string, *new_phoneme_string); esp_mn_error_t *esp_mn_commands_update(*multinet, *model_data); ``` * Rainmaker and SR Interface `cmd_write_to_sr(&cmd)` is the interface through which Rainmaker sends voice commands to the BOX for modification. SR control commands follow these rules: Each control command can correspond to a maximum of `8` command words. If there are more than `8` command words, adding a new command word will replace the last one in the table. The same voice command words cannot be added more than once. ### LVGL Component Here, we will introduce the porting interface of LVGL on BOX_S3. - Input Devices * Input device hardware initialization, `indev_init_default()` Depending on the type of input device, different initializations are performed. As mentioned in the `bsp_btn` section above, `BOARD_S3_BOX_LITE` uses 3 navigation key buttons, while `BOARD_S3_BOX` uses a TP (Touch Panel) in addition to 1 virtual TP button. TP: Currently, the project has ported two touch panel chips, `tt21100` and `ft5x06`. After power-on, the `tp_prob` function detects different IIC addresses to identify the specific chip and performs different initialization actions through `indev_tp_init`. Buttons: Initialized during the `bsp_btn` button initialization. * Registering Input Devices `lv_port_indev_init()` -> `lv_indev_drv_register()` Registering a device requires the `type` and `read_cb` parameters. Upon registration, an internal timer with a period of `LV_INDEV_DEF_READ_PERIOD` is created to poll external input events. - File System * Redirecting File Operation APIs This primarily involves redirecting APIs like `fopen`, `fclose`, `fwrite` based on the platform. LVGL provides encapsulations like `lv_fs_fatfs`, `lv_fs_posix`, `lv_fs_sdio`,`v_fs_win32` for reference and configuration. Users can configure this in menuconfig or implement their own. * File Drive Letter Configuration Espressif's file system drive letter is `'S'`. Users need to be aware that when `lv_fs` performs any file operation, it first checks if the drive letter matches. Drive letters that don't match will receive a return value of `LV_FS_RES_NOT_EX`, which affects normal file operations. - Display Interface Display initialization is mainly divided into two parts: hardware interface initialization and registration of display devices. The following diagram provides a simple overview of the initialization modules used in BOX and their interconnections.