v2.4.0: Migrate to IDF 6.0 (#2120)

* Migrate board builds to ESP-IDF 6.0.1

* Document upstream IDF 6 CI blockers

* Use IDF 6 patched registry components

* Fix board-specific ESP-IDF 6 build errors

* Fix remaining ESP-IDF 6 board builds

* Document final ESP-IDF 6 matrix results [skip ci]

* update IDF 6 component releases

* rebase IDF 6 migration and use upstream SSCMA

* Enhance audio input management in AudioService

- Introduced AS_EVENT_AUDIO_INPUT_STOP_REQUEST to manage audio input stopping more effectively.
- Updated AudioService::Start() to clear the new stop request event.
- Modified AudioService::AudioInputTask() to handle the stop request and ensure proper input disabling.
- Adjusted AdcPdmAudioCodec::Start() to reflect lazy input opening, ensuring start/stop operations run in the same task.

* Refactor audio codec management and configuration

- Added output_device_opened_ flag to track the state of the output device in Es8388 and Es8389 codecs.
- Updated EnableOutput method to prevent unnecessary device reopening and added mute functionality to manage audio output more effectively.
- Enhanced error handling in Es8311AudioCodec by ensuring proper closure and deletion of the codec device.
- Adjusted sample rates in board configurations for atk-dnesp32s3-box2 to 24000 Hz and introduced AUDIO_CODEC_USE_MCLK for improved clock management.

* Update build configurations and documentation for ESP-IDF 6 compatibility

- Added container specification for the build workflow using espressif/idf:v6.0.1.
- Updated the version of the espressif/esp_video component to ^2.3.0.
- Enhanced documentation to clarify the support status of ESP32-P4 variants, specifying that legacy Rev < 3 variants are excluded from the IDF 6 matrix.
- Adjusted board configurations to include IDF version constraints and necessary SDK configurations for legacy support.
- Improved handling of YUV formats in EspVideo to maintain compatibility with previous versions.

* Implement playback drained event handling in Application

- Added MAIN_EVENT_PLAYBACK_DRAINED to manage playback state transitions.
- Introduced callbacks for playback drained events in AudioService to trigger listening state changes.
- Refactored Application::Run() to handle deferred listening start based on playback queue status.
- Enhanced audio processing logic to prevent audio truncation during state changes.
- Updated related methods to ensure proper wake word detection configuration during listening mode.

* Fix variant selection shell in CI

* Update project version to 2.4.0 and adjust component dependencies

- Bump project version in CMakeLists.txt to 2.4.0.
- Change espressif/esp_video component version to ^2.0.1 in idf_component.yml.
- Modify AUDIO_INPUT_REFERENCE setting in config.h to false for m5stack-core-s3.
- Remove unnecessary infinite loops in xmini_c3_board.cc during initialization.

---------

Co-authored-by: Xiaoxia <terrence.huang@tenclass.com>
This commit is contained in:
Xiaoxia
2026-07-17 13:41:52 +08:00
committed by GitHub
co-authored by Xiaoxia
parent 2b8e1f34b0
commit 3e78cd73bd
119 changed files with 1374 additions and 649 deletions
+5 -2
View File
@@ -16,6 +16,8 @@ jobs:
prepare:
name: Determine variants to build
runs-on: ubuntu-latest
container:
image: espressif/idf:v6.0.1
outputs:
variants: ${{ steps.select.outputs.variants }}
steps:
@@ -25,7 +27,7 @@ jobs:
fetch-depth: 0
- name: Install jq
run: sudo apt-get update && sudo apt-get install -y jq
run: apt-get update && apt-get install -y jq
- id: list
name: Get all variant list
@@ -34,6 +36,7 @@ jobs:
- id: select
name: Select variants based on changes
shell: bash
env:
ALL_VARIANTS: ${{ steps.list.outputs.all_variants }}
run: |
@@ -92,7 +95,7 @@ jobs:
include: ${{ fromJson(needs.prepare.outputs.variants) }}
runs-on: ubuntu-latest
container:
image: espressif/idf:v5.5.2
image: espressif/idf:v6.0.1
steps:
- name: Checkout
uses: actions/checkout@v4
+1 -1
View File
@@ -9,5 +9,5 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
set(PROJECT_VER "2.3.0")
set(PROJECT_VER "2.4.0")
project(xiaozhi)
+262
View File
@@ -0,0 +1,262 @@
# ESP-IDF 6.0 Migration and Board Compatibility Status
> Last updated: 2026-07-16
> Validated SDK: ESP-IDF v6.0.1
> Scope: 137 board directories and 157 supported build variants defined by `main/boards/**/config.json`.
## Current Status
The migration baseline is reproducible from committed project files and published Component Registry packages. All 157 IDF 6 variants are now build-compatible with ESP-IDF 6.0.1: 156 passed the last complete GitHub Actions matrix, and `esp-vocat` subsequently passed a local full build after rebasing onto upstream commit `467b96a` and fixing two IDF 6/C++26 ST77916 initialization errors. A new complete matrix is pending. Fourteen legacy ESP32-P4 Rev < 3 variants are excluded from the IDF 6 matrix but remain available when building with ESP-IDF < 6.
| Status | Variants | Meaning |
|---|---:|---|
| ✅ Build-compatible | 157 | 156 clean full builds completed in GitHub Actions and `esp-vocat` completed locally with ESP-IDF 6.0.1; this does not imply hardware or complete peripheral validation |
| 🟡 Feature-degraded subset | 1 | `esp-vocat` builds on IDF 6, but its PCB capacitive slider/button support is disabled pending compatible touch-sensor components |
| 🔴 Build-blocked | 0 | No supported release variant remains blocked at compile or link time |
There are no remaining IDF 6 build blockers. [`78/esp_lcd_nv3023 1.0.1`](https://components.espressif.com/components/78/esp_lcd_nv3023/versions/1.0.1) and [`wvirgil123/sscma_client 1.0.3`](https://components.espressif.com/components/wvirgil123/sscma_client/versions/1.0.3/readme) are consumed directly from the Component Registry, so local copies under the ignored `components/` directory are not required. ESP32-P4 Rev < 3 remains on the ESP-IDF 5.5 legacy build path, while the IDF 6 matrix supports ESP32-P4 v3.x.
Representative local full-build results are shown below. Firmware size and free space are reported by ESP-IDF 6.0.1 `check_sizes.py`. The authoritative per-variant compatibility result is the full GitHub Actions matrix in the next section.
| Chip | Build variant | Application size | Free space in smallest app partition |
|---|---|---:|---:|
| ESP32 | `bread-compact-esp32` | `0x240560` | 23% |
| ESP32-C3 | `esp-hi` | `0x20ef10` | 30% |
| ESP32-C3 | `xmini-c3` | `0x2370f0` | 44% |
| ESP32-C5 | `waveshare-esp32-c5-touch-lcd-1.69` | `0x27cd30` | 37% |
| ESP32-C6 | `waveshare-esp32-c6-lcd-0.85` | `0x280ee0` | 15% |
| ESP32-S3 | `doit-s3-aibox` | `0x21edf0` | 46% |
| ESP32-S3 | `lilygo-t-display-s3-pro-mvsrlora` | `0x2adce0` | 32% |
| ESP32-S3 | `lilygo-t-circle-s3` | `0x2a32f0` | 33% |
| ESP32-S3 | `zhengchen-1.54tft-wifi` | `0x2abdc0` | 32% |
| ESP32-S3 | `kevin-yuying-313lcd` | `0x2c4990` | 30% |
| ESP32-S3 | `otto-robot` | `0x37ff70` | 11% |
| ESP32-S3 | `esp-vocat` | `0x2742f0` | 38% |
| ESP32-S3 | `sensecap-watcher` | `0x2faff0` | 25% |
| ESP32-P4 v3.x | `esp-p4-function-ev-board-p4x` | `0x385420` | 11% |
| ESP32-P4 v3.x | `m5stack-tab5-p4x` | `0x380790` | 11% |
As a negative test, `esp-p4-function-ev-board` (legacy P4 Rev < 3) was rejected as expected by `esp-sr 2.4.6` during IDF 6.0.1 configuration. Legacy P4 variants are therefore version-gated to ESP-IDF < 6 instead of being carried as permanent IDF 6 blockers.
For backward-compatibility regression coverage, `xmini-c3` also completed a full build with ESP-IDF 5.5.4 (application size `0x234920`, 44% free in the smallest app partition). This confirms that the compatibility changes for I2S port numbering, LCD I2C configuration, and the UHCI DMA dependency did not break the existing 5.5 build chain.
## Full-Matrix CI Validation
GitHub Actions run [29477593880](https://github.com/78/xiaozhi-esp32/actions/runs/29477593880) built the complete matrix with the `espressif/idf:v6.0.1` container and only committed files plus published registry components. The matrix-generation job and 156 board jobs passed; exactly 1 board job failed at the then-current configure-time guard for unsupported touch-sensor components. The table below records that historical run; `esp-vocat` has since passed locally and the replacement full-matrix run is pending.
Results by chip target:
| Chip target | Variants | Passed | Blocked |
|---|---:|---:|---:|
| ESP32 | 7 | 7 | 0 |
| ESP32-C3 | 9 | 9 | 0 |
| ESP32-C5 | 4 | 4 | 0 |
| ESP32-C6 | 9 | 9 | 0 |
| ESP32-S3 | 114 | 113 | 1 |
| ESP32-P4 v3.x | 14 | 14 | 0 |
| **Total** | **157** | **156** | **1** |
The failure in that run and its current resolution are:
| Build variant | Failure in run 29477593880 | Current resolution |
|---|---|---|
| `esp-vocat` | `touch_slider_sensor` and `touch_button_sensor` require IDF < 6.0 | IDF 6 builds omit the PCB capacitive slider/button path; CST816 display touch remains enabled. A local full build passed after the mainline change and ST77916 compatibility fixes |
## ESP32-P4 Silicon Scope and Naming
The IDF 6 release matrix supports only ESP32-P4 v3.x silicon. Each legacy Rev < 3 build keeps its original name and contains `idf_version: "<6.0"`. Variant selection behaves as follows:
| SDK | ESP32-P4 Rev < 3 | ESP32-P4 Rev >= 3 |
|---|---|---|
| ESP-IDF < 6 | Original name without a suffix; adds `CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y` and `CONFIG_ESP32P4_REV_MIN_100=y` | Original name plus `-p4x` |
| ESP-IDF >= 6 | Not listed or built | `-p4x` |
This restores the historical artifact names and keeps the IDF 6 matrix at 157 variants. The IDF 5.5 selection contains 171 variants: 14 P4 `-p4x` artifacts, 14 legacy-P4 artifacts with their original unsuffixed names, and 143 non-P4 variants.
Espressif's current chip-identification table lists v0.0, v1.0, v1.3, v3.0, v3.1, and v3.2, with no v4.0 revision. The public errata history added v3.0/v3.1 information on 2026-02-12 and v3.2 information on 2026-04-20. ESP-IDF 6.0 release notes explicitly describe support for "ESP32-P4 Version3 silicon." See the official [chip revision identification](https://docs.espressif.com/projects/esp-chip-errata/en/latest/esp32p4/01-chip-identification/index.html), [errata revision history](https://docs.espressif.com/projects/esp-chip-errata/en/latest/esp32p4/revision-history/index.html), and [ESP-IDF releases](https://github.com/espressif/esp-idf/releases).
## Component Compatibility
| Component/module | Version or approach for IDF 6 | Status | Notes |
|---|---|---|---|
| `78/uart-uhci` | `0.3.2` | ✅ Upstream support | The registry release compiles under IDF 6.0.1 in GitHub Actions |
| `78/uart-eth-modem` | `0.6.1` | ✅ Upstream support | Updated for the new event callback and depends on `uart-uhci 0.3.x` |
| `espressif/mqtt` | `1.0.0` | ✅ Upstream support | MQTT moved from a built-in SDK component to a Component Manager dependency in IDF 6 |
| `78/esp-ml307` | `3.6.6` + project-level `espressif/mqtt` | ✅ Builds in CI | The upstream source compiles under IDF 6.0.1 when the project supplies the MQTT component moved out of IDF |
| `espressif/esp_hosted` / `esp_wifi_remote` | `2.12.11` / `1.6.2` | ✅ Upstream support | Used for ESP32-P4 Hosted Wi-Fi |
| `espressif/esp_video` | `^2.0.1` | ✅ Upstream support | Currently resolves to 2.3.0 on S3 and 2.0.1 on P4 due to BSP constraints |
| P4 BSP / LCD drivers | BSP `5.2.3`, EK79007/ST7701 `2.0.x` | ✅ Upstream support | Resolves IDF 6 DPI, color-field, and split-driver-component issues |
| `espressif/esp_lcd_st77916` | `2.0.2` | ✅ Upstream support | Major version 2 uses the IDF 6 panel I/O definitions |
| `espressif/esp_lcd_spd2010` | `^2.0.0` (resolved `2.0.0~1`) | ✅ Upstream support | Major version 2 declares ESP-IDF 6 compatibility |
| `espressif/esp_lcd_co5300` | `2.1.0` | ✅ Upstream support | Used with explicit IDF 6-compatible QSPI I/O configuration in board code |
| `esp_emote_expression` | `1.0.2` | ✅ Upstream support | Replaces the previous dependency on the built-in `json` component |
| `wvirgil123/sscma_client` | [`1.0.3`](https://components.espressif.com/components/wvirgil123/sscma_client/versions/1.0.3/readme) | ✅ Upstream support | Uses `espressif/cjson` and the split driver components on IDF 6 while retaining the legacy component names on older IDF releases |
| `espressif/servo` / `espfriends/servo_dog_ctrl` | `1.0.0` / `0.2.0` | ✅ Upstream support | Uses official registry releases; compilation and linking were validated in the full IDF 6.0.1 build of `esp-hi`, with no local override required |
| `78/esp_lcd_nv3023` | [`1.0.1`](https://components.espressif.com/components/78/esp_lcd_nv3023/versions/1.0.1) | ✅ Upstream-based registry release | Mirrors MakerM0 upstream commit `15dae953`; adds IDF 6 color-order and GPIO compatibility while retaining older IDF branches; validated through the registry in a clean `magiclick-c3` full build |
| `llgok/cpp_bus_driver` | Excluded from the IDF 6 baseline | ⚪ Waiting for upstream | Version `2.1.0` still requires local patches for IDF 6. It is used only by the `LILYGO T-Display-P4` source, and that board has no release `config.json`, so the component has been removed until upstream support is available |
| MQTT protocol AES-CTR | PSA Crypto | ✅ Ported | Replaces the legacy AES context API removed by IDF 6 / Mbed TLS 4 |
| BluFi security negotiation (conditional path) | Legacy Mbed TLS DHM/AES API | ⚪ Not yet migrated | None of the 157 supported release variants enables it. IDF 6 removed `mbedtls/dhm.h`; compatibility of the official PSA FFDH + AES-CTR approach with the existing mobile-client protocol must be evaluated |
| `espressif/bmi270_sensor` | [`0.1.2`](https://components.espressif.com/components/espressif/bmi270_sensor/versions/0.1.2/readme?language=en) | ✅ Upstream support | Provides IDF 6.0 prebuilt libraries for ESP32-C5 and ESP32-S3; validated by a full `esp-spot-c5` build |
| `touch_slider_sensor` / `touch_button_sensor` | Disabled for IDF 6 | 🟡 Feature gap | Their manifests require IDF < 6.0, so ESP Vocat omits its PCB capacitive slider/button path on IDF 6. CST816 display touch is unaffected |
| ESP32-P4 Rev < 3 / `espressif/esp-sr` | Version-gated to IDF < 6 | 🟡 Legacy SDK path | The 14 legacy variants are restored for IDF 5.5 builds. They remain excluded from IDF 6 because `esp-sr 2.4.6` rejects the old-silicon configuration; ESP32-P4 v3.x is unaffected |
## Per-Board Progress
In the table below, "Board" is the source directory and "Build variant" is the firmware name used by the release script. Different chip revisions of the same board may have different status, so they are split into separate rows when necessary.
| Chip | Board | Build variant | IDF 6.0 status | Current validation | Blocker/next step |
|---|---|---|---|---|---|
| `esp32` | `atommatrix-echo-base` | `atommatrix-echo-base` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32` | `bread-compact-esp32` | `bread-compact-esp32` | ✅ Full build passed | IDF 6.0.1 `idf.py build` | Hardware smoke/peripheral regression pending |
| `esp32` | `bread-compact-esp32` | `bread-compact-esp32-128x32` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32` | `bread-compact-esp32-lcd` | `bread-compact-esp32-lcd` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32` | `esp32-cgc` | `esp32-cgc` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32` | `esp32-cgc-144` | `esp32-cgc-144` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32` | `waveshare/esp32-touch-lcd-3.5` | `waveshare-esp32-touch-lcd-3.5` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c3` | `esp-hi` | `esp-hi` | ✅ Full build passed | IDF 6.0.1 `idf.py build`; `servo_dog_ctrl 0.2.0` | Hardware smoke, servo, and audio peripheral regression pending |
| `esp32c3` | `kevin-c3` | `kevin-c3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c3` | `lichuang-c3-dev` | `lichuang-c3-dev` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c3` | `magiclick-c3` | `magiclick-c3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c3` | `magiclick-c3-v2` | `magiclick-c3-v2` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c3` | `surfer-c3-1.14tft` | `surfer-c3-1.14tft` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c3` | `xmini-c3` | `xmini-c3` | ✅ Full build passed | IDF 6.0.1 `idf.py build` | Hardware smoke/peripheral regression pending |
| `esp32c3` | `xmini-c3-4g` | `xmini-c3-4g` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c3` | `xmini-c3-v3` | `xmini-c3-v3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c5` | `esp-sensairshuttle` | `esp-sensairshuttle` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c5` | `esp-spot` | `esp-spot-c5` | ✅ Full build passed | IDF 6.0.1 `idf.py build`; `bmi270_sensor 0.1.2` | Hardware smoke, BMI270, audio, and power-management regression pending |
| `esp32c5` | `movecall-moji2-esp32c5` | `movecall-moji2-esp32c5` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c5` | `waveshare/esp32-c5-touch-lcd-1.69` | `waveshare-esp32-c5-touch-lcd-1.69` | ✅ Full build passed | IDF 6.0.1 `idf.py build` | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-lcd-0.85` | `waveshare-esp32-c6-lcd-0.85` | ✅ Full build passed | IDF 6.0.1 `idf.py build` | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-lcd-1.69` | `waveshare-esp32-c6-lcd-1.69` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-touch-amoled-1.32` | `waveshare-esp32-c6-touch-amoled-1.32` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-touch-amoled-1.43` | `waveshare-esp32-c6-touch-amoled-1.43` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-touch-amoled-1.8` | `waveshare-esp32-c6-touch-amoled-1.8` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-touch-amoled-2.06` | `waveshare-esp32-c6-touch-amoled-2.06` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-touch-amoled-2.16` | `waveshare-esp32-c6-touch-amoled-2.16` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-touch-lcd-1.54` | `waveshare-esp32-c6-touch-lcd-1.54` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32c6` | `waveshare/esp32-c6-touch-lcd-1.83` | `waveshare-esp32-c6-touch-lcd-1.83` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `aipi-lite` | `aipi-lite` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atk-dnesp32s3` | `atk-dnesp32s3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atk-dnesp32s3-box` | `atk-dnesp32s3-box` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atk-dnesp32s3-box0` | `atk-dnesp32s3-box0` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atk-dnesp32s3-box2-4g` | `atk-dnesp32s3-box2-4g` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atk-dnesp32s3-box2-wifi` | `atk-dnesp32s3-box2-wifi` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atk-dnesp32s3-box3` | `atk-dnesp32s3-box3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atom-echos3r` | `atom-echos3r` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atoms3-echo-base` | `atoms3-echo-base` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atoms3r-cam-m12-echo-base` | `atoms3r-cam-m12-echo-base` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atoms3r-echo-base` | `atoms3r-echo-base` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `atoms3r-echo-pyramid` | `atoms3r-echo-pyramid` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `bread-compact-ml307` | `bread-compact-ml307`<br>`bread-compact-ml307-128x64` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `bread-compact-nt26` | `bread-compact-nt26` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `bread-compact-wifi` | `bread-compact-wifi`<br>`bread-compact-wifi-128x64` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `df-k10` | `df-k10` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `df-s3-ai-cam` | `df-s3-ai-cam` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `doit-s3-aibox` | `doit-s3-aibox` | ✅ Full build passed | IDF 6.0.1 `idf.py build` | Hardware smoke/peripheral regression pending |
| `esp32s3` | `du-chatx` | `du-chatx` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `electron-bot` | `electron-bot` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `esp-box` | `esp-box` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `esp-box-3` | `esp-box-3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `esp-box-lite` | `esp-box-lite` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `esp-s3-lcd-ev-board` | `esp-s3-lcd-ev-board-1p4`<br>`esp-s3-lcd-ev-board-1p5` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `esp-s3-lcd-ev-board-2` | `esp-s3-lcd-ev-board-2` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `esp-sparkbot` | `esp-sparkbot` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `esp-vocat` | `esp-vocat` | 🟡 Full build passed; feature-degraded | Local ESP-IDF 6.0.1 full build after rebasing onto `origin/main` | PCB capacitive slider/button disabled on IDF 6; CST816 display touch remains enabled; hardware regression pending |
| `esp32s3` | `esp32s3-korvo2-v3` | `esp32s3-korvo2-v3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `esp32s3-korvo2-v3-rndis` | `esp32s3-korvo2-v3-rndis` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `freenove-esp32s3-display-2.8-lcd` | `freenove-esp32s3-display-2.8-lcd` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `genjutech-s3-1.54tft` | `genjutech-s3-1.54tft` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `hu-087` | `hu-087` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `jiuchuan-s3` | `jiuchuan-s3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `kevin-box-2` | `kevin-box-2` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `kevin-sp-v4-dev` | `kevin-sp-v4-dev` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `kevin-yuying-313lcd` | `kevin-yuying-313lcd` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `labplus-ledong-v2` | `labplus-ledong-v2` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `labplus-mpython-v3` | `labplus-mpython-v3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `lceda-course-examples/eda-robot-pro` | `lceda-course-examples-eda-robot-pro` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `lceda-course-examples/eda-super-bear` | `lceda-course-examples-eda-super-bear` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `lceda-course-examples/eda-tv-pro` | `lceda-course-examples-eda-tv-pro` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `lichuang-dev` | `lichuang-dev` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `lilygo-t-cameraplus-s3` | `lilygo-t-cameraplus-s3`<br>`lilygo-t-cameraplus-s3_v1_2` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `lilygo-t-circle-s3` | `lilygo-t-circle-s3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `lilygo-t-display-s3-pro-mvsrlora` | `lilygo-t-display-s3-pro-mvsrlora` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `m5stack-cardputer-adv` | `m5stack-cardputer-adv` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `m5stack-core-s3` | `m5stack-core-s3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `m5stack-stick-s3` | `m5stack-stick-s3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `m5stack-stopwatch` | `m5stack-stopwatch` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `magiclick-2p4` | `magiclick-2p4` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `magiclick-2p5` | `magiclick-2p5` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `minsi-k08-dual` | `minsi-k08-dual` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `mixgo-nova` | `mixgo-nova` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `movecall-cuican-esp32s3` | `movecall-cuican-esp32s3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `movecall-moji-esp32s3` | `movecall-moji-esp32s3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `nulllab-ai-vox-v3` | `nulllab-ai-vox-v3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `otto-robot` | `otto-robot` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `quandong-s3-dev` | `quandong-s3-dev` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `rymcu/bigsmart` | `rymcu-bigsmart` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `sensecap-watcher` | `sensecap-watcher` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `sp-esp32-s3-1.28-box` | `sp-esp32-s3-1.28-box` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `sp-esp32-s3-1.54-muma` | `sp-esp32-s3-1.54-muma` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `taiji-pi-s3` | `taiji-pi-s3`<br>`taiji-pi-s3-pdm` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `tudouzi` | `tudouzi` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-audio-board` | `waveshare-esp32-s3-audio-board` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-cam` | `waveshare-esp32-s3-cam-2`<br>`waveshare-esp32-s3-cam-2.8`<br>`waveshare-esp32-s3-cam-3.5`<br>`waveshare-esp32-s3-cam-1.83` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-epaper-1.54` | `waveshare-esp32-s3-epaper-1.54-v2`<br>`waveshare-esp32-s3-epaper-1.54-v1` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-epaper-3.97` | `waveshare-esp32-s3-epaper-3.97` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-lcd-0.85` | `waveshare-esp32-s3-lcd-0.85` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-rgb-matrix` | `waveshare-esp32-s3-rgb-matrix` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-rlcd-4.2` | `waveshare-esp32-s3-rlcd-4.2` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-amoled-1.32` | `waveshare-esp32-s3-touch-amoled-1.32` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-amoled-1.43c` | `waveshare-esp32-s3-touch-amoled-1.43c` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-amoled-1.75` | `waveshare-esp32-s3-touch-amoled-1.75`<br>`waveshare-esp32-s3-touch-amoled-1.75c` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-amoled-1.8` | `waveshare-esp32-s3-touch-amoled-1.8` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-amoled-1.8-v2` | `waveshare-esp32-s3-touch-amoled-1.8-v2` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-amoled-2.06` | `waveshare-esp32-s3-touch-amoled-2.06` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-amoled-2.16` | `waveshare-esp32-s3-touch-amoled-2.16` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-1.46` | `waveshare-esp32-s3-touch-lcd-1.46` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-1.54` | `waveshare-esp32-s3-touch-lcd-1.54` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-1.83` | `waveshare-esp32-s3-touch-lcd-1.83` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-1.85` | `waveshare-esp32-s3-touch-lcd-1.85` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-1.85b` | `waveshare-esp32-s3-touch-lcd-1.85b` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-1.85c` | `waveshare-esp32-s3-touch-lcd-1.85c` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-3.49` | `waveshare-esp32-s3-touch-lcd-3.49` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-3.5` | `waveshare-esp32-s3-touch-lcd-3.5` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-3.5b` | `waveshare-esp32-s3-touch-lcd-3.5b` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-4.3c` | `waveshare-esp32-s3-touch-lcd-4.3c` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-4b` | `waveshare-esp32-s3-touch-lcd-4b` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `waveshare/esp32-s3-touch-lcd-7c` | `waveshare-esp32-s3-touch-lcd-7c` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `xingzhi-abs-2.0` | `xingzhi-abs-2.0` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `xingzhi-cube-0.85tft-ml307` | `xingzhi-cube-0.85tft-ml307` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `xingzhi-cube-0.85tft-wifi` | `xingzhi-cube-0.85tft-wifi` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `xingzhi-cube-0.96oled-ml307` | `xingzhi-cube-0.96oled-ml307` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `xingzhi-cube-0.96oled-wifi` | `xingzhi-cube-0.96oled-wifi` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `xingzhi-cube-1.54tft-ml307` | `xingzhi-cube-1.54tft-ml307`<br>`xingzhi-cube-1.54tft-ml307-wechatui` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `xingzhi-cube-1.54tft-wifi` | `xingzhi-cube-1.54tft-wifi` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `xingzhi-metal-1.54-wifi` | `xingzhi-metal-1.54-wifi` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `yunliao-s3` | `yunliao-s3` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `zhengchen-1.54tft-ml307` | `zhengchen-1.54tft-ml307` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `zhengchen-1.54tft-wifi` | `zhengchen-1.54tft-wifi` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `zhengchen-cam` | `zhengchen-cam` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32s3` | `zhengchen-cam-ml307` | `zhengchen-cam-ml307` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32p4` | `esp-p4-function-ev-board` | `esp-p4-function-ev-board-p4x` | ✅ Full build passed | IDF 6.0.1 `idf.py build` | Hardware smoke/peripheral regression pending |
| `esp32p4` | `m5stack-tab5` | `m5stack-tab5-p4x` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32p4` | `waveshare/esp32-p4-nano` | `waveshare-esp32-p4-nano-10.1-a-p4x` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32p4` | `waveshare/esp32-p4-wifi6-touch-lcd` | `waveshare-esp32-p4-wifi6-touch-lcd-4b-p4x`<br>`waveshare-esp32-p4-wifi6-touch-lcd-4.3-p4x`<br>`waveshare-esp32-p4-wifi6-touch-lcd-5-p4x`<br>`waveshare-esp32-p4-wifi6-touch-lcd-7b-p4x`<br>`waveshare-esp32-p4-wifi6-touch-lcd-3.4c-p4x`<br>`waveshare-esp32-p4-wifi6-touch-lcd-4c-p4x`<br>`waveshare-esp32-p4-wifi6-touch-lcd-7-p4x`<br>`waveshare-esp32-p4-wifi6-touch-lcd-8-p4x`<br>`waveshare-esp32-p4-wifi6-touch-lcd-10.1-p4x` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32p4` | `waveshare/esp32-p4-wifi6-touch-lcd-3.5` | `waveshare-esp32-p4-wifi6-touch-lcd-3.5-p4x` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
| `esp32p4` | `wireless-tag-wtp4c5mp07s` | `wireless-tag-wtp4c5mp07s-p4x` | ✅ Full build passed | GitHub Actions IDF 6.0.1 full build | Hardware smoke/peripheral regression pending |
## Next Steps and Acceptance Criteria
1. Run the complete 157-variant IDF 6 GitHub Actions matrix on the rebased branch, and add an IDF 5.5 legacy job to build and hardware-test at least one P4 v1.3 device. When IDF 6-compatible releases of `touch_slider_sensor` and `touch_button_sensor` become available, re-enable and hardware-test the ESP Vocat PCB capacitive slider/button path.
2. For every green variant, complete a minimal hardware smoke test covering boot, networking, audio input/output, display/touch when present, camera when present, and 4G/Ethernet when present.
3. Perform a physical negative test for the `xmini-c3`/`xmini-c3-v3` firmware guard. CI proves that both images compile; it does not prove that a wrong image is safely rejected. Acceptance requires flashing each wrong image to a sacrificial or recoverable board and verifying that startup stops before any board-specific power or peripheral initialization can cause damage.
4. Keep third-party experiments under the ignored `components/` directory out of the migration branch. The reproducible baseline must use the published `78/esp_lcd_nv3023 1.0.1` and `wvirgil123/sscma_client 1.0.3` packages. `espfriends/servo_dog_ctrl 0.2.0` is an upstream registry dependency and needs no local override.
## Reproduction
```bash
source ~/.espressif/v6.0.1/esp-idf/export.sh
python scripts/release.py <board> --name <variant>
```
This document is a migration-status snapshot. Build compatibility and hardware compatibility are tracked separately. Add "hardware validated" to a board only after validation on physical hardware is complete.
+9 -2
View File
@@ -1040,13 +1040,17 @@ if(BOARD_TYPE STREQUAL "m5stack-stick-s3")
m5stack__m5pm1
)
endif()
if(CONFIG_BOARD_TYPE_ESP_VOCAT)
if(CONFIG_BOARD_TYPE_ESP_SPOT_S3 OR CONFIG_BOARD_TYPE_ESP_SPOT_C5 OR CONFIG_BOARD_TYPE_ESP_VOCAT)
list(APPEND MAIN_PRIV_REQUIRES_EXTRA
espressif__bmi270_sensor
)
endif()
if(CONFIG_BOARD_TYPE_ESP_VOCAT AND IDF_VERSION_MAJOR LESS 6)
list(APPEND MAIN_PRIV_REQUIRES_EXTRA
espressif__touch_slider_sensor
espressif__touch_button_sensor
)
endif()
idf_component_register(SRCS ${SOURCES}
EMBED_FILES ${LANG_SOUNDS} ${COMMON_SOUNDS}
INCLUDE_DIRS ${INCLUDE_DIRS}
@@ -1061,11 +1065,14 @@ idf_component_register(SRCS ${SOURCES}
esp_driver_spi
esp_driver_i2c
esp_driver_i2s
esp_driver_ledc
esp_driver_jpeg
esp_driver_ppa
esp_driver_tsens
esp_app_format
app_update
spi_flash
mbedtls
console
efuse
bt
+65 -23
View File
@@ -83,6 +83,9 @@ void Application::Initialize() {
callbacks.on_vad_change = [this](bool speaking) {
xEventGroupSetBits(event_group_, MAIN_EVENT_VAD_CHANGE);
};
callbacks.on_playback_drained = [this]() {
xEventGroupSetBits(event_group_, MAIN_EVENT_PLAYBACK_DRAINED);
};
audio_service_.SetCallbacks(callbacks);
// Add state change listeners
@@ -179,7 +182,8 @@ void Application::Run() {
MAIN_EVENT_START_LISTENING |
MAIN_EVENT_STOP_LISTENING |
MAIN_EVENT_ACTIVATION_DONE |
MAIN_EVENT_STATE_CHANGED;
MAIN_EVENT_STATE_CHANGED |
MAIN_EVENT_PLAYBACK_DRAINED;
while (true) {
auto bits = xEventGroupWaitBits(event_group_, ALL_EVENTS, pdTRUE, pdFALSE, portMAX_DELAY);
@@ -205,6 +209,16 @@ void Application::Run() {
HandleStateChangedEvent();
}
if (bits & MAIN_EVENT_PLAYBACK_DRAINED) {
// Deferred listening start (auto mode): the playback queue has
// drained, so it is now safe to enable voice processing.
if (pending_listening_start_ && GetDeviceState() == kDeviceStateListening &&
audio_service_.IsPlaybackIdle()) {
pending_listening_start_ = false;
StartListeningAudio();
}
}
if (bits & MAIN_EVENT_TOGGLE_CHAT) {
HandleToggleChatEvent();
}
@@ -220,6 +234,11 @@ void Application::Run() {
if (bits & MAIN_EVENT_SEND_AUDIO) {
while (auto packet = audio_service_.PopPacketFromSendQueue()) {
if (protocol_ && !protocol_->SendAudio(std::move(packet))) {
// Drop the remaining packets. Leaving them in the queue would
// stall the Opus codec task (it waits for queue space), which in
// turn deadlocks the whole audio input pipeline, as no new
// MAIN_EVENT_SEND_AUDIO event would ever be triggered again.
while (audio_service_.PopPacketFromSendQueue());
break;
}
}
@@ -253,6 +272,8 @@ void Application::Run() {
// Print debug info every 10 seconds
if (clock_ticks_ % 10 == 0) {
SystemInfo::PrintHeapStats();
// SystemInfo::PrintTaskList();
// SystemInfo::PrintTaskCpuUsage(pdMS_TO_TICKS(1000));
}
}
}
@@ -860,6 +881,9 @@ void Application::ContinueWakeWordInvoke(const std::string& wake_word) {
void Application::HandleStateChangedEvent() {
DeviceState new_state = state_machine_.GetState();
clock_ticks_ = 0;
// Any state change invalidates a pending deferred listening start;
// the Listening case below re-arms it when needed.
pending_listening_start_ = false;
auto& board = Board::GetInstance();
auto display = board.GetDisplay();
@@ -886,29 +910,17 @@ void Application::HandleStateChangedEvent() {
// Make sure the audio processor is running
if (play_popup_on_listening_ || !audio_service_.IsAudioProcessorRunning()) {
// For auto mode, wait for playback queue to be empty before enabling voice processing
// This prevents audio truncation when STOP arrives late due to network jitter
if (listening_mode_ == kListeningModeAutoStop) {
audio_service_.WaitForPlaybackQueueEmpty();
// For auto mode, wait for the playback queue to drain before enabling
// voice processing. This prevents audio truncation when STOP arrives
// late due to network jitter. Instead of blocking the main loop here,
// defer the start until MAIN_EVENT_PLAYBACK_DRAINED arrives.
if (listening_mode_ == kListeningModeAutoStop && !audio_service_.IsPlaybackIdle()) {
pending_listening_start_ = true;
} else {
StartListeningAudio();
}
// Send the start listening command
protocol_->SendStartListening(listening_mode_);
audio_service_.EnableVoiceProcessing(true);
}
#ifdef CONFIG_WAKE_WORD_DETECTION_IN_LISTENING
// Enable wake word detection in listening mode (configured via Kconfig)
audio_service_.EnableWakeWordDetection(audio_service_.IsAfeWakeWord());
#else
// Disable wake word detection in listening mode
audio_service_.EnableWakeWordDetection(false);
#endif
// Play popup sound after ResetDecoder (in EnableVoiceProcessing) has been called
if (play_popup_on_listening_) {
play_popup_on_listening_ = false;
audio_service_.PlaySound(Lang::Sounds::OGG_POPUP);
} else {
ConfigureWakeWordForListening();
}
break;
case kDeviceStateSpeaking:
@@ -931,6 +943,36 @@ void Application::HandleStateChangedEvent() {
}
}
void Application::StartListeningAudio() {
// Runs in the main loop, either directly from HandleStateChangedEvent or
// deferred via MAIN_EVENT_PLAYBACK_DRAINED once the playback queue drains.
if (GetDeviceState() != kDeviceStateListening) {
return;
}
// Send the start listening command
protocol_->SendStartListening(listening_mode_);
audio_service_.EnableVoiceProcessing(true);
ConfigureWakeWordForListening();
// Play popup sound after ResetDecoder (in EnableVoiceProcessing) has been called
if (play_popup_on_listening_) {
play_popup_on_listening_ = false;
audio_service_.PlaySound(Lang::Sounds::OGG_POPUP);
}
}
void Application::ConfigureWakeWordForListening() {
#ifdef CONFIG_WAKE_WORD_DETECTION_IN_LISTENING
// Enable wake word detection in listening mode (configured via Kconfig)
audio_service_.EnableWakeWordDetection(audio_service_.IsAfeWakeWord());
#else
// Disable wake word detection in listening mode
audio_service_.EnableWakeWordDetection(false);
#endif
}
void Application::Schedule(std::function<void()>&& callback) {
{
std::lock_guard<std::mutex> lock(mutex_);
+4
View File
@@ -32,6 +32,7 @@
#define MAIN_EVENT_START_LISTENING (1 << 10)
#define MAIN_EVENT_STOP_LISTENING (1 << 11)
#define MAIN_EVENT_STATE_CHANGED (1 << 12)
#define MAIN_EVENT_PLAYBACK_DRAINED (1 << 13)
enum AecMode {
@@ -144,6 +145,7 @@ private:
bool aborted_ = false;
bool assets_version_checked_ = false;
bool play_popup_on_listening_ = false; // Flag to play popup sound after state changes to listening
bool pending_listening_start_ = false; // Waiting for playback to drain before starting listening (auto mode)
int clock_ticks_ = 0;
TaskHandle_t activation_task_handle_ = nullptr;
@@ -159,6 +161,8 @@ private:
void HandleWakeWordDetectedEvent();
void ContinueOpenAudioChannel(ListeningMode mode);
void ContinueWakeWordInvoke(const std::string& wake_word);
void StartListeningAudio();
void ConfigureWakeWordForListening();
// Activation task (runs in background)
void ActivationTask();
+10
View File
@@ -4,6 +4,7 @@
#include <freertos/FreeRTOS.h>
#include <freertos/event_groups.h>
#include <driver/i2s_std.h>
#include <esp_idf_version.h>
#include <vector>
#include <string>
@@ -14,6 +15,15 @@
#define AUDIO_CODEC_DMA_DESC_NUM 6
#define AUDIO_CODEC_DMA_FRAME_NUM 240
// ESP-IDF 6 removed i2s_port_t and changed i2s_chan_config_t::id to an integer.
// Keep numeric I2S controller IDs usable on targets where IDF 5 does not expose
// every value through the target-specific i2s_port_t enum (for example ESP32-C3).
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
#define XIAOZHI_I2S_PORT(port) (port)
#else
#define XIAOZHI_I2S_PORT(port) static_cast<i2s_port_t>(port)
#endif
class AudioCodec {
public:
AudioCodec();
+108 -39
View File
@@ -121,7 +121,8 @@ void AudioService::Initialize(AudioCodec* codec) {
void AudioService::Start() {
service_stopped_ = false;
xEventGroupClearBits(event_group_, AS_EVENT_AUDIO_TESTING_RUNNING | AS_EVENT_WAKE_WORD_RUNNING | AS_EVENT_AUDIO_PROCESSOR_RUNNING);
xEventGroupClearBits(event_group_, AS_EVENT_AUDIO_TESTING_RUNNING | AS_EVENT_WAKE_WORD_RUNNING |
AS_EVENT_AUDIO_PROCESSOR_RUNNING | AS_EVENT_AUDIO_INPUT_STOP_REQUEST);
esp_timer_start_periodic(audio_power_timer_, 1000000);
@@ -170,12 +171,17 @@ void AudioService::Stop() {
AS_EVENT_WAKE_WORD_RUNNING |
AS_EVENT_AUDIO_PROCESSOR_RUNNING);
std::lock_guard<std::mutex> lock(audio_queue_mutex_);
audio_encode_queue_.clear();
audio_decode_queue_.clear();
audio_playback_queue_.clear();
audio_testing_queue_.clear();
audio_queue_cv_.notify_all();
{
std::lock_guard<std::mutex> lock(audio_queue_mutex_);
audio_encode_queue_.clear();
audio_decode_queue_.clear();
audio_playback_queue_.clear();
audio_testing_queue_.clear();
audio_queue_cv_.notify_all();
}
if (callbacks_.on_playback_drained) {
callbacks_.on_playback_drained();
}
}
bool AudioService::ReadAudioData(std::vector<int16_t>& data, int sample_rate, int samples) {
@@ -225,14 +231,34 @@ bool AudioService::ReadAudioData(std::vector<int16_t>& data, int sample_rate, in
}
void AudioService::AudioInputTask() {
constexpr EventBits_t kAudioInputActiveBits = AS_EVENT_AUDIO_TESTING_RUNNING |
AS_EVENT_WAKE_WORD_RUNNING | AS_EVENT_AUDIO_PROCESSOR_RUNNING;
while (true) {
EventBits_t bits = xEventGroupWaitBits(event_group_, AS_EVENT_AUDIO_TESTING_RUNNING |
AS_EVENT_WAKE_WORD_RUNNING | AS_EVENT_AUDIO_PROCESSOR_RUNNING,
EventBits_t bits = xEventGroupWaitBits(event_group_, kAudioInputActiveBits |
AS_EVENT_AUDIO_INPUT_STOP_REQUEST,
pdFALSE, pdFALSE, portMAX_DELAY);
if (service_stopped_) {
// ADC continuous mode keeps its hardware mutex from start until stop,
// so the input task that started it must also stop it before exiting.
if (codec_->input_enabled()) {
codec_->EnableInput(false);
}
break;
}
if (bits & AS_EVENT_AUDIO_INPUT_STOP_REQUEST) {
xEventGroupClearBits(event_group_, AS_EVENT_AUDIO_INPUT_STOP_REQUEST);
// Recheck the active state in this task. Audio capture may have been
// enabled after the timer posted the stop request.
if ((xEventGroupGetBits(event_group_) & kAudioInputActiveBits) == 0 &&
codec_->input_enabled()) {
codec_->EnableInput(false);
}
}
if (audio_input_need_warmup_) {
audio_input_need_warmup_ = false;
vTaskDelay(pdMS_TO_TICKS(120));
@@ -289,6 +315,7 @@ void AudioService::AudioOutputTask() {
auto task = std::move(audio_playback_queue_.front());
audio_playback_queue_.pop_front();
const bool playback_drained = audio_playback_queue_.empty() && audio_decode_queue_.empty();
audio_queue_cv_.notify_all();
lock.unlock();
@@ -304,6 +331,10 @@ void AudioService::AudioOutputTask() {
last_output_time_ = std::chrono::steady_clock::now();
debug_statistics_.playback_count++;
if (playback_drained && callbacks_.on_playback_drained) {
callbacks_.on_playback_drained();
}
#if CONFIG_USE_SERVER_AEC
/* Record the timestamp for server AEC */
if (task->timestamp > 0) {
@@ -321,7 +352,7 @@ void AudioService::OpusCodecTask() {
std::unique_lock<std::mutex> lock(audio_queue_mutex_);
audio_queue_cv_.wait(lock, [this]() {
return service_stopped_ ||
(!audio_encode_queue_.empty() && audio_send_queue_.size() < MAX_SEND_PACKETS_IN_QUEUE) ||
!audio_encode_queue_.empty() ||
(!audio_decode_queue_.empty() && audio_playback_queue_.size() < MAX_PLAYBACK_TASKS_IN_QUEUE);
});
if (service_stopped_) {
@@ -382,9 +413,15 @@ void AudioService::OpusCodecTask() {
lock.lock();
}
debug_statistics_.decode_count++;
/* If decoding failed and nothing is left to play, report the drain
* here since AudioOutputTask will not see this packet. */
if (audio_decode_queue_.empty() && audio_playback_queue_.empty() &&
callbacks_.on_playback_drained) {
callbacks_.on_playback_drained();
}
}
/* Encode the audio to send queue */
if (!audio_encode_queue_.empty() && audio_send_queue_.size() < MAX_SEND_PACKETS_IN_QUEUE) {
if (!audio_encode_queue_.empty()) {
auto task = std::move(audio_encode_queue_.front());
audio_encode_queue_.pop_front();
audio_queue_cv_.notify_all();
@@ -413,6 +450,11 @@ void AudioService::OpusCodecTask() {
if (task->type == kAudioTaskTypeEncodeToSendQueue) {
{
std::lock_guard<std::mutex> lock2(audio_queue_mutex_);
/* Never let a full send queue stall encoding: stale realtime
* audio is useless to the server, so drop the oldest packet. */
if (audio_send_queue_.size() >= MAX_SEND_PACKETS_IN_QUEUE) {
audio_send_queue_.pop_front();
}
audio_send_queue_.push_back(std::move(packet));
}
if (callbacks_.on_send_queue_available) {
@@ -477,22 +519,44 @@ void AudioService::PushTaskToEncodeQueue(AudioTaskType type, std::vector<int16_t
auto task = std::make_unique<AudioTask>();
task->type = type;
task->pcm = std::move(pcm);
/* Push the task to the encode queue */
std::unique_lock<std::mutex> lock(audio_queue_mutex_);
/* If the task is to send queue, we need to set the timestamp */
if (type == kAudioTaskTypeEncodeToSendQueue && !timestamp_queue_.empty()) {
if (timestamp_queue_.size() <= MAX_TIMESTAMPS_IN_QUEUE) {
task->timestamp = timestamp_queue_.front();
} else {
ESP_LOGW(TAG, "Timestamp queue (%u) is full, dropping timestamp", timestamp_queue_.size());
uint32_t dropped_total = 0;
{
/* Push the task to the encode queue */
std::unique_lock<std::mutex> lock(audio_queue_mutex_);
/* If the task is to send queue, we need to set the timestamp */
if (type == kAudioTaskTypeEncodeToSendQueue && !timestamp_queue_.empty()) {
if (timestamp_queue_.size() <= MAX_TIMESTAMPS_IN_QUEUE) {
task->timestamp = timestamp_queue_.front();
} else {
ESP_LOGW(TAG, "Timestamp queue (%u) is full, dropping timestamp", timestamp_queue_.size());
}
timestamp_queue_.pop_front();
}
timestamp_queue_.pop_front();
/* Microphone audio is realtime, so drop the oldest frame instead of blocking.
* Blocking here would stall the audio engine task (AFE fetch) and deadlock the
* whole input pipeline when the send queue stops being drained (e.g. network
* congestion or a failed UDP send). */
if (audio_encode_queue_.size() >= MAX_ENCODE_TASKS_IN_QUEUE) {
audio_encode_queue_.pop_front();
dropped_total = ++debug_statistics_.encode_drop_count;
}
audio_encode_queue_.push_back(std::move(task));
audio_queue_cv_.notify_all();
}
audio_queue_cv_.wait(lock, [this]() { return audio_encode_queue_.size() < MAX_ENCODE_TASKS_IN_QUEUE; });
audio_encode_queue_.push_back(std::move(task));
audio_queue_cv_.notify_all();
/* Log outside the lock (UART writes are slow and would starve the codec task),
* at most once per second. */
if (dropped_total > 0) {
int64_t now = esp_timer_get_time();
if (now - last_encode_drop_log_time_ >= 1000000) {
last_encode_drop_log_time_ = now;
ESP_LOGW(TAG, "Encode queue is full, dropping oldest frame (dropped %lu so far)",
(unsigned long)dropped_total);
}
}
}
bool AudioService::PushPacketToDecodeQueue(std::unique_ptr<AudioStreamPacket> packet, bool wait) {
@@ -643,25 +707,28 @@ bool AudioService::IsIdle() {
return audio_encode_queue_.empty() && audio_decode_queue_.empty() && audio_playback_queue_.empty() && audio_testing_queue_.empty();
}
void AudioService::WaitForPlaybackQueueEmpty() {
std::unique_lock<std::mutex> lock(audio_queue_mutex_);
audio_queue_cv_.wait(lock, [this]() {
return service_stopped_ || (audio_decode_queue_.empty() && audio_playback_queue_.empty());
});
bool AudioService::IsPlaybackIdle() {
std::lock_guard<std::mutex> lock(audio_queue_mutex_);
return audio_decode_queue_.empty() && audio_playback_queue_.empty();
}
void AudioService::ResetDecoder() {
std::lock_guard<std::mutex> lock(audio_queue_mutex_);
std::unique_lock<std::mutex> decoder_lock(decoder_mutex_);
if (opus_decoder_ != nullptr) {
esp_opus_dec_reset(opus_decoder_);
{
std::lock_guard<std::mutex> lock(audio_queue_mutex_);
std::unique_lock<std::mutex> decoder_lock(decoder_mutex_);
if (opus_decoder_ != nullptr) {
esp_opus_dec_reset(opus_decoder_);
}
decoder_lock.unlock();
timestamp_queue_.clear();
audio_decode_queue_.clear();
audio_playback_queue_.clear();
audio_testing_queue_.clear();
audio_queue_cv_.notify_all();
}
if (callbacks_.on_playback_drained) {
callbacks_.on_playback_drained();
}
decoder_lock.unlock();
timestamp_queue_.clear();
audio_decode_queue_.clear();
audio_playback_queue_.clear();
audio_testing_queue_.clear();
audio_queue_cv_.notify_all();
}
void AudioService::CheckAndUpdateAudioPowerState() {
@@ -669,7 +736,9 @@ void AudioService::CheckAndUpdateAudioPowerState() {
auto input_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_input_time_).count();
auto output_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_output_time_).count();
if (input_elapsed > AUDIO_POWER_TIMEOUT_MS && codec_->input_enabled()) {
codec_->EnableInput(false);
// ADC continuous start/stop must run in the same task. Wake the audio
// input task instead of closing the codec from the esp_timer task.
xEventGroupSetBits(event_group_, AS_EVENT_AUDIO_INPUT_STOP_REQUEST);
}
if (output_elapsed > AUDIO_POWER_TIMEOUT_MS && codec_->output_enabled()) {
// Keep TX clock when duplex RX is active; otherwise RX may stall on some boards.
+6 -1
View File
@@ -50,6 +50,7 @@
#define AS_EVENT_WAKE_WORD_RUNNING (1 << 1)
#define AS_EVENT_AUDIO_PROCESSOR_RUNNING (1 << 2)
#define AS_EVENT_PLAYBACK_NOT_EMPTY (1 << 3)
#define AS_EVENT_AUDIO_INPUT_STOP_REQUEST (1 << 4)
#define AS_OPUS_GET_FRAME_DRU_ENUM(duration_ms) \
((duration_ms) == 5 ? ESP_OPUS_ENC_FRAME_DURATION_5_MS : \
@@ -79,6 +80,8 @@ struct AudioServiceCallbacks {
std::function<void(const std::string&)> on_wake_word_detected;
std::function<void(bool)> on_vad_change;
std::function<void(void)> on_audio_testing_queue_full;
// Fired when both the decode and playback queues become empty
std::function<void(void)> on_playback_drained;
};
@@ -99,6 +102,7 @@ struct DebugStatistics {
uint32_t decode_count = 0;
uint32_t encode_count = 0;
uint32_t playback_count = 0;
uint32_t encode_drop_count = 0;
};
class AudioService {
@@ -114,7 +118,7 @@ public:
const std::string& GetLastWakeWord() const;
bool IsVoiceDetected() const { return voice_detected_; }
bool IsIdle();
void WaitForPlaybackQueueEmpty();
bool IsPlaybackIdle();
bool IsWakeWordRunning() const { return xEventGroupGetBits(event_group_) & AS_EVENT_WAKE_WORD_RUNNING; }
bool IsAudioProcessorRunning() const { return xEventGroupGetBits(event_group_) & AS_EVENT_AUDIO_PROCESSOR_RUNNING; }
bool IsAfeWakeWord();
@@ -154,6 +158,7 @@ private:
int decoder_duration_ms_ = OPUS_FRAME_DURATION_MS;
int decoder_frame_size_ = 0;
DebugStatistics debug_statistics_;
int64_t last_encode_drop_log_time_ = 0;
srmodel_list_t* models_list_ = nullptr;
EventGroupHandle_t event_group_;
+3 -2
View File
@@ -88,7 +88,8 @@ void Es8311AudioCodec::UpdateDeviceState() {
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(dev_, input_gain_));
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(dev_, output_volume_));
} else if (!input_enabled_ && !output_enabled_ && dev_ != nullptr) {
esp_codec_dev_close(dev_);
ESP_ERROR_CHECK(esp_codec_dev_close(dev_));
esp_codec_dev_delete(dev_);
dev_ = nullptr;
}
if (pa_pin_ != GPIO_NUM_NC) {
@@ -199,4 +200,4 @@ int Es8311AudioCodec::Write(const int16_t* data, int samples) {
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(dev_, (void*)data, samples * sizeof(int16_t)));
}
return samples;
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
#include "audio_codec.h"
#include <driver/i2c.h>
#include <driver/i2c_master.h>
#include <driver/gpio.h>
#include <esp_codec_dev.h>
#include <esp_codec_dev_defaults.h>
+18 -9
View File
@@ -176,14 +176,17 @@ void Es8388AudioCodec::EnableOutput(bool enable) {
return;
}
if (enable) {
esp_codec_dev_sample_info_t fs = {
.bits_per_sample = 16,
.channel = 1,
.channel_mask = 0,
.sample_rate = (uint32_t)output_sample_rate_,
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs));
if (!output_device_opened_) {
esp_codec_dev_sample_info_t fs = {
.bits_per_sample = 16,
.channel = 1,
.channel_mask = 0,
.sample_rate = (uint32_t)output_sample_rate_,
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs));
output_device_opened_ = true;
}
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_));
// Set analog output volume to 0dB, default is -45dB
@@ -193,11 +196,17 @@ void Es8388AudioCodec::EnableOutput(bool enable) {
ctrl_if_->write_reg(ctrl_if_, reg, 1, &reg_val, 1);
}
ESP_ERROR_CHECK(esp_codec_dev_set_out_mute(output_dev_, false));
if (pa_pin_ != GPIO_NUM_NC) {
gpio_set_level(pa_pin_, 1);
}
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_));
// Keep TX open because the paired RX channel may use it as the clock
// source. Reopening the shared duplex interface after WiFi provisioning
// can otherwise leave playback silent on ESP-IDF 6.
if (output_device_opened_) {
ESP_ERROR_CHECK(esp_codec_dev_set_out_mute(output_dev_, true));
}
if (pa_pin_ != GPIO_NUM_NC) {
gpio_set_level(pa_pin_, 0);
}
+1
View File
@@ -18,6 +18,7 @@ private:
esp_codec_dev_handle_t output_dev_ = nullptr;
esp_codec_dev_handle_t input_dev_ = nullptr;
bool output_device_opened_ = false;
gpio_num_t pa_pin_ = GPIO_NUM_NC;
std::mutex data_if_mutex_;
+22 -11
View File
@@ -169,21 +169,32 @@ void Es8389AudioCodec::EnableOutput(bool enable) {
return;
}
if (enable) {
// Play 16bit 1 channel
esp_codec_dev_sample_info_t fs = {
.bits_per_sample = 16,
.channel = 1,
.channel_mask = 0,
.sample_rate = (uint32_t)output_sample_rate_,
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs));
if (!output_device_opened_) {
// Play 16bit 1 channel
esp_codec_dev_sample_info_t fs = {
.bits_per_sample = 16,
.channel = 1,
.channel_mask = 0,
.sample_rate = (uint32_t)output_sample_rate_,
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs));
output_device_opened_ = true;
}
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_));
ESP_ERROR_CHECK(esp_codec_dev_set_out_mute(output_dev_, false));
if (pa_pin_ != GPIO_NUM_NC) {
gpio_set_level(pa_pin_, 1);
}
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_));
// Keep the ES8389 TX data interface open. On ESP32-S3 the RX channel
// uses the paired TX channel as its clock source, and reopening TX via
// esp_codec_dev after it has been closed can leave the IDF 6 duplex
// channel silent even though esp_codec_dev_open reports success.
// Muting preserves the logical power state without reconfiguring I2S.
if (output_device_opened_) {
ESP_ERROR_CHECK(esp_codec_dev_set_out_mute(output_dev_, true));
}
if (pa_pin_ != GPIO_NUM_NC) {
gpio_set_level(pa_pin_, 0);
}
@@ -203,4 +214,4 @@ int Es8389AudioCodec::Write(const int16_t* data, int samples) {
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t)));
}
return samples;
}
}
+2 -1
View File
@@ -3,7 +3,7 @@
#include "audio_codec.h"
#include <driver/i2c.h>
#include <driver/i2c_master.h>
#include <driver/gpio.h>
#include <esp_codec_dev.h>
#include <esp_codec_dev_defaults.h>
@@ -18,6 +18,7 @@ private:
esp_codec_dev_handle_t output_dev_ = nullptr;
esp_codec_dev_handle_t input_dev_ = nullptr;
bool output_device_opened_ = false;
gpio_num_t pa_pin_ = GPIO_NUM_NC;
std::mutex data_if_mutex_;
+7 -7
View File
@@ -22,7 +22,7 @@ NoAudioCodecDuplex::NoAudioCodecDuplex(int input_sample_rate, int output_sample_
output_sample_rate_ = output_sample_rate;
i2s_chan_config_t chan_cfg = {
.id = I2S_NUM_0,
.id = XIAOZHI_I2S_PORT(0),
.role = I2S_ROLE_MASTER,
.dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM,
.dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM,
@@ -83,7 +83,7 @@ NoAudioCodecSimplex::NoAudioCodecSimplex(int input_sample_rate, int output_sampl
// Create a new channel for speaker
i2s_chan_config_t chan_cfg = {
.id = (i2s_port_t)0,
.id = XIAOZHI_I2S_PORT(0),
.role = I2S_ROLE_MASTER,
.dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM,
.dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM,
@@ -134,7 +134,7 @@ NoAudioCodecSimplex::NoAudioCodecSimplex(int input_sample_rate, int output_sampl
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg));
// Create a new channel for MIC
chan_cfg.id = (i2s_port_t)1;
chan_cfg.id = XIAOZHI_I2S_PORT(1);
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, nullptr, &rx_handle_));
std_cfg.clk_cfg.sample_rate_hz = (uint32_t)input_sample_rate_;
std_cfg.gpio_cfg.bclk = mic_sck;
@@ -152,7 +152,7 @@ NoAudioCodecSimplex::NoAudioCodecSimplex(int input_sample_rate, int output_sampl
// Create a new channel for speaker
i2s_chan_config_t chan_cfg = {
.id = (i2s_port_t)0,
.id = XIAOZHI_I2S_PORT(0),
.role = I2S_ROLE_MASTER,
.dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM,
.dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM,
@@ -203,7 +203,7 @@ NoAudioCodecSimplex::NoAudioCodecSimplex(int input_sample_rate, int output_sampl
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg));
// Create a new channel for MIC
chan_cfg.id = (i2s_port_t)1;
chan_cfg.id = XIAOZHI_I2S_PORT(1);
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, nullptr, &rx_handle_));
std_cfg.clk_cfg.sample_rate_hz = (uint32_t)input_sample_rate_;
std_cfg.slot_cfg.slot_mask = mic_slot_mask;
@@ -293,7 +293,7 @@ NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output
output_sample_rate_ = output_sample_rate;
// Create a new channel for speaker
i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG((i2s_port_t)1, I2S_ROLE_MASTER);
i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(XIAOZHI_I2S_PORT(1), I2S_ROLE_MASTER);
tx_chan_cfg.dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM;
tx_chan_cfg.dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM;
tx_chan_cfg.auto_clear_after_cb = true;
@@ -343,7 +343,7 @@ NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &tx_std_cfg));
#if SOC_I2S_SUPPORTS_PDM_RX
// Create a new channel for MIC in PDM mode
i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG((i2s_port_t)0, I2S_ROLE_MASTER);
i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(XIAOZHI_I2S_PORT(0), I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&rx_chan_cfg, NULL, &rx_handle_));
i2s_pdm_rx_config_t pdm_rx_cfg = {
.clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG((uint32_t)input_sample_rate_),
+54 -16
View File
@@ -217,18 +217,16 @@ void AfeAudioEngine::EnableWakeWordDetection(bool enable) {
return;
}
// WakeNet enable/disable on the AFE instance is applied by ProcessingTask
// (see ApplyAfeControls), driven by the kWakeWordEnabled bit.
if (enable) {
if (wake_detector_ == WakeDetector::kWakeNet) {
afe_iface_->enable_wakenet(afe_data_);
} else {
if (wake_detector_ == WakeDetector::kMultiNet) {
custom_wake_word_->Start();
}
xEventGroupSetBits(event_group_, kWakeWordEnabled);
} else {
xEventGroupClearBits(event_group_, kWakeWordEnabled);
if (wake_detector_ == WakeDetector::kWakeNet) {
afe_iface_->disable_wakenet(afe_data_);
} else {
if (wake_detector_ == WakeDetector::kMultiNet) {
custom_wake_word_->Stop();
}
}
@@ -293,32 +291,65 @@ void AfeAudioEngine::UpdateActiveState() {
std::lock_guard<std::mutex> lock(input_buffer_mutex_);
input_buffer_.clear();
if (afe_data_ != nullptr) {
afe_iface_->reset_buffer(afe_data_);
// Don't call reset_buffer() here: this runs in the main task while
// ProcessingTask may be inside fetch_with_delay() on the same AFE
// instance, and a concurrent reset corrupts the ring buffer state.
// Defer the reset to ProcessingTask, which owns the fetch side.
reset_pending_ = true;
}
}
if ((bits & kVoiceProcessingEnabled) == 0) {
output_buffer_.clear();
// output_buffer_ is owned by the task that produces output frames,
// so let that task clear it instead of racing with it here.
output_reset_pending_ = true;
}
UpdateAecState();
afe_control_dirty_ = true;
}
void AfeAudioEngine::UpdateAecState() {
if (afe_data_ == nullptr || codec_ == nullptr || !codec_->input_reference()) {
return;
}
afe_control_dirty_ = true;
}
void AfeAudioEngine::ApplyAfeControls() {
EventBits_t bits = xEventGroupGetBits(event_group_);
const bool enable = (bits & kWakeWordEnabled) ||
(device_aec_enabled_ && (bits & kVoiceProcessingEnabled));
if (enable) {
afe_iface_->enable_aec(afe_data_);
} else {
afe_iface_->disable_aec(afe_data_);
if (wake_detector_ == WakeDetector::kWakeNet) {
if (bits & kWakeWordEnabled) {
afe_iface_->enable_wakenet(afe_data_);
} else {
afe_iface_->disable_wakenet(afe_data_);
}
}
if (codec_->input_reference()) {
const bool enable_aec = (bits & kWakeWordEnabled) ||
(device_aec_enabled_ && (bits & kVoiceProcessingEnabled));
if (enable_aec) {
afe_iface_->enable_aec(afe_data_);
} else {
afe_iface_->disable_aec(afe_data_);
}
}
}
void AfeAudioEngine::ProcessingTask() {
while (true) {
xEventGroupWaitBits(event_group_, kAfeActive, pdFALSE, pdTRUE, portMAX_DELAY);
if (reset_pending_.exchange(false)) {
// Discard audio recorded before (re)activation. Holding
// input_buffer_mutex_ serializes the reset against Feed(); the
// fetch side cannot race as it only runs in this task.
std::lock_guard<std::mutex> lock(input_buffer_mutex_);
input_buffer_.clear();
afe_iface_->reset_buffer(afe_data_);
continue;
}
if (afe_control_dirty_.exchange(false)) {
// WakeNet/AEC toggles are not safe against a concurrent fetch,
// so they are applied here, in the task that owns the fetch side.
ApplyAfeControls();
}
auto* result = afe_iface_->fetch_with_delay(afe_data_, portMAX_DELAY);
if ((xEventGroupGetBits(event_group_) & kAfeActive) == 0) {
continue;
@@ -362,7 +393,8 @@ void AfeAudioEngine::HandleWakeWordResult(const afe_fetch_result_t* result) {
last_detected_wake_word_ = wake_words_[model_index];
xEventGroupClearBits(event_group_, kWakeWordEnabled);
afe_iface_->disable_wakenet(afe_data_);
// UpdateActiveState marks the AFE controls dirty; the next loop iteration
// of ProcessingTask disables WakeNet via ApplyAfeControls.
UpdateActiveState();
if (wake_word_detected_callback_) {
wake_word_detected_callback_(last_detected_wake_word_);
@@ -370,6 +402,9 @@ void AfeAudioEngine::HandleWakeWordResult(const afe_fetch_result_t* result) {
}
void AfeAudioEngine::HandleVoiceResult(const afe_fetch_result_t* result) {
if (output_reset_pending_.exchange(false)) {
output_buffer_.clear();
}
if (vad_state_change_callback_) {
if (result->vad_state == VAD_SPEECH && !is_speaking_) {
is_speaking_ = true;
@@ -402,6 +437,9 @@ void AfeAudioEngine::OutputRawAudio(const std::vector<int16_t>& data) {
if (!output_callback_ || codec_ == nullptr) {
return;
}
if (output_reset_pending_.exchange(false)) {
output_buffer_.clear();
}
const size_t channels = codec_->input_channels();
if (channels <= 1) {
output_buffer_.insert(output_buffer_.end(), data.begin(), data.end());
+8
View File
@@ -1,6 +1,7 @@
#ifndef AFE_AUDIO_ENGINE_H
#define AFE_AUDIO_ENGINE_H
#include <atomic>
#include <condition_variable>
#include <deque>
#include <functional>
@@ -66,6 +67,12 @@ private:
int frame_samples_ = 0;
bool is_speaking_ = false;
bool device_aec_enabled_ = false;
// Deferred AFE buffer reset, performed by ProcessingTask (see UpdateActiveState)
std::atomic<bool> reset_pending_{false};
// Deferred WakeNet/AEC toggles, applied by ProcessingTask (see ApplyAfeControls)
std::atomic<bool> afe_control_dirty_{false};
// Deferred output_buffer_ clear, performed by the output-producing task
std::atomic<bool> output_reset_pending_{false};
WakeDetector wake_detector_ = WakeDetector::kNone;
std::unique_ptr<CustomWakeWord> custom_wake_word_;
@@ -90,6 +97,7 @@ private:
void ProcessingTask();
void UpdateActiveState();
void UpdateAecState();
void ApplyAfeControls();
void OutputRawAudio(const std::vector<int16_t>& data);
void HandleWakeWordResult(const afe_fetch_result_t* result);
void HandleVoiceResult(const afe_fetch_result_t* result);
+2
View File
@@ -2,6 +2,8 @@
#define CUSTOM_WAKE_WORD_H
#include <esp_attr.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_mn_iface.h>
#include <esp_mn_models.h>
#include <model_path.h>
@@ -192,8 +192,7 @@ private:
},
.bus_width = 8,
.max_transfer_bytes = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t),
.psram_trans_align = 64,
.sram_trans_align = 4,
.dma_burst_size = 64,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
@@ -217,11 +216,10 @@ private:
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &panel_io));
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = LCD_NUM_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
panel_config.reset_gpio_num = LCD_NUM_RST;
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
@@ -347,8 +347,7 @@ private:
},
.bus_width = 8,
.max_transfer_bytes = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t),
.psram_trans_align = 64,
.sram_trans_align = 4,
.dma_burst_size = 64,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
@@ -374,11 +373,10 @@ private:
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &panel_io));
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = LCD_PIN_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
panel_config.reset_gpio_num = LCD_PIN_RST;
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
@@ -437,7 +435,8 @@ public:
AUDIO_I2S_GPIO_DOUT,
AUDIO_I2S_GPIO_DIN,
GPIO_NUM_NC,
AUDIO_CODEC_ES8389_ADDR
AUDIO_CODEC_ES8389_ADDR,
AUDIO_CODEC_USE_MCLK
);
return &audio_codec;
}
+3 -3
View File
@@ -9,8 +9,8 @@ enum PowerSupply {
kDeviceBatterySupply,
};
#define AUDIO_INPUT_SAMPLE_RATE 16000
#define AUDIO_OUTPUT_SAMPLE_RATE 16000
#define AUDIO_INPUT_SAMPLE_RATE 24000
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_38
#define AUDIO_I2S_GPIO_WS GPIO_NUM_42
@@ -21,6 +21,7 @@ enum PowerSupply {
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_48
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_47
#define AUDIO_CODEC_ES8389_ADDR ES8389_CODEC_DEFAULT_ADDR
#define AUDIO_CODEC_USE_MCLK true
#define SPISD_PIN_MOSI GPIO_NUM_16
#define SPISD_PIN_MISO GPIO_NUM_18
@@ -77,4 +78,3 @@ enum PowerSupply {
#define Module_4G_TX_PIN GPIO_NUM_43
#endif // _BOARD_CONFIG_H_
@@ -327,8 +327,7 @@ private:
},
.bus_width = 8,
.max_transfer_bytes = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t),
.psram_trans_align = 64,
.sram_trans_align = 4,
.dma_burst_size = 64,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
@@ -354,11 +353,10 @@ private:
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &panel_io));
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = LCD_PIN_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
panel_config.reset_gpio_num = LCD_PIN_RST;
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
@@ -417,7 +415,7 @@ public:
AUDIO_I2S_GPIO_DIN,
GPIO_NUM_NC,
AUDIO_CODEC_ES8389_ADDR,
false);
AUDIO_CODEC_USE_MCLK);
return &audio_codec;
}
+3 -3
View File
@@ -8,8 +8,8 @@ enum PowerSupply {
kDeviceBatterySupply,
};
#define AUDIO_INPUT_SAMPLE_RATE 16000
#define AUDIO_OUTPUT_SAMPLE_RATE 16000
#define AUDIO_INPUT_SAMPLE_RATE 24000
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_38
#define AUDIO_I2S_GPIO_WS GPIO_NUM_42
@@ -20,6 +20,7 @@ enum PowerSupply {
#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_48
#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_47
#define AUDIO_CODEC_ES8389_ADDR ES8389_CODEC_DEFAULT_ADDR
#define AUDIO_CODEC_USE_MCLK true
#define R_BUTTON_GPIO GPIO_NUM_0
@@ -68,4 +69,3 @@ enum PowerSupply {
#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false
#endif // _BOARD_CONFIG_H_
@@ -9,6 +9,7 @@
#include <driver/gpio.h>
#include <esp_log.h>
#include <esp_idf_version.h>
#include <driver/i2c_master.h>
#include <driver/spi_master.h>
#include <esp_lcd_panel_vendor.h>
@@ -292,7 +293,11 @@ private:
esp_lcd_panel_handle_t panel_handle = nullptr;
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = LCD_RST_GPIO; // Set to -1 if not use
panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#else
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#endif
panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18)
if (config.type == LcdPanelType::kGc9107) {
@@ -9,6 +9,7 @@
#include <driver/gpio.h>
#include <esp_log.h>
#include <esp_idf_version.h>
#include <driver/i2c_master.h>
#include <driver/spi_master.h>
#include <esp_lcd_panel_vendor.h>
@@ -370,7 +371,11 @@ private:
esp_lcd_panel_handle_t panel_handle = nullptr;
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = LCD_RST_GPIO; // Set to -1 if not use
panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#else
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#endif
panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18)
if (config.type == LcdPanelType::kGc9107) {
@@ -816,7 +816,7 @@ private:
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#else
panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR;
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#endif
panel_config.bits_per_pixel = 16;
@@ -47,24 +47,24 @@ private:
// SSD1306 config
esp_lcd_panel_io_i2c_config_t io_config = {
.dev_addr = 0x3C,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.scl_speed_hz = 400 * 1000,
.control_phase_bytes = 1,
.dc_bit_offset = 6,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.flags = {
.dc_low_on_data = 0,
.disable_control_phase = 0,
},
.scl_speed_hz = 400 * 1000,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_));
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(display_i2c_bus_, &io_config, &panel_io_));
ESP_LOGI(TAG, "Install SSD1306 driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = -1;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 1;
esp_lcd_panel_ssd1306_config_t ssd1306_config = {
@@ -48,24 +48,24 @@ private:
// SSD1306 config
esp_lcd_panel_io_i2c_config_t io_config = {
.dev_addr = 0x3C,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.scl_speed_hz = 400 * 1000,
.control_phase_bytes = 1,
.dc_bit_offset = 6,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.flags = {
.dc_low_on_data = 0,
.disable_control_phase = 0,
},
.scl_speed_hz = 400 * 1000,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_));
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(display_i2c_bus_, &io_config, &panel_io_));
ESP_LOGI(TAG, "Install SSD1306 driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = -1;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 1;
esp_lcd_panel_ssd1306_config_t ssd1306_config = {
@@ -47,24 +47,24 @@ private:
// SSD1306 config
esp_lcd_panel_io_i2c_config_t io_config = {
.dev_addr = 0x3C,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.scl_speed_hz = 400 * 1000,
.control_phase_bytes = 1,
.dc_bit_offset = 6,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.flags = {
.dc_low_on_data = 0,
.disable_control_phase = 0,
},
.scl_speed_hz = 400 * 1000,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_));
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(display_i2c_bus_, &io_config, &panel_io_));
ESP_LOGI(TAG, "Install SSD1306 driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = -1;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 1;
esp_lcd_panel_ssd1306_config_t ssd1306_config = {
@@ -52,24 +52,24 @@ private:
// SSD1306 config
esp_lcd_panel_io_i2c_config_t io_config = {
.dev_addr = 0x3C,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.scl_speed_hz = 400 * 1000,
.control_phase_bytes = 1,
.dc_bit_offset = 6,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.flags = {
.dc_low_on_data = 0,
.disable_control_phase = 0,
},
.scl_speed_hz = 400 * 1000,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_));
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(display_i2c_bus_, &io_config, &panel_io_));
ESP_LOGI(TAG, "Install SSD1306 driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = -1;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 1;
esp_lcd_panel_ssd1306_config_t ssd1306_config = {
+17 -6
View File
@@ -57,8 +57,7 @@
#define TAG "EspVideo"
#if defined(CONFIG_CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER) || defined(CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP)
#warning \
"CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER or CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP is enabled, which may cause image corruption in YUV422 format!"
#pragma message("CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER or CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP is enabled; verify YUV422 image integrity")
#endif
#if CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE
@@ -191,7 +190,8 @@ EspVideo::EspVideo(const esp_video_init_config_t& config) {
uint32_t best_fmt = 0;
int best_rank = 1 << 30; // large number
// 注: 当前版本 esp_video 中 YUV422P 实际输出为 YUYV。
// esp_video 2.x uses the packed YUYV/UYVY FOURCC values. Keep YUV422P
// for compatibility with esp_video 1.x, where it was used for YUYV data.
#if defined(CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE) && defined(CONFIG_SOC_PPA_SUPPORTED)
auto get_rank = [](uint32_t fmt) -> int {
switch (fmt) {
@@ -203,6 +203,9 @@ EspVideo::EspVideo(const esp_video_init_config_t& config) {
case V4L2_PIX_FMT_YUV420: // 软件 JPEG 编码器不支持 YUV420 格式
return 2;
#endif // CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
return 3;
case V4L2_PIX_FMT_GREY:
case V4L2_PIX_FMT_YUV422P:
default:
@@ -212,6 +215,8 @@ EspVideo::EspVideo(const esp_video_init_config_t& config) {
#else
auto get_rank = [](uint32_t fmt) -> int {
switch (fmt) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_YUV422P:
return 10;
case V4L2_PIX_FMT_RGB565:
@@ -433,6 +438,7 @@ bool EspVideo::Capture() {
case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_GREY:
#ifdef CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT
@@ -517,6 +523,9 @@ bool EspVideo::Capture() {
rotate_cfg.in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565_LE;
break;
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
// Rotate packed YUV422 as opaque 16-bit pixels. The rotation
// operation only needs the pixel size and does not convert color.
rotate_cfg.in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565_LE;
break;
case V4L2_PIX_FMT_GREY:
@@ -584,8 +593,9 @@ bool EspVideo::Capture() {
rotate_src = (uint8_t*)frame_.data;
ppa_color_mode = PPA_SRM_COLOR_MODE_RGB888;
break;
case V4L2_PIX_FMT_YUYV: {
ESP_LOGW(TAG, "YUYV format is not supported for PPA rotation, using software conversion to RGB888");
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY: {
ESP_LOGW(TAG, "YUV422 format is not supported for PPA rotation, using software conversion to RGB888");
rotate_src = (uint8_t*)heap_caps_malloc(frame_.width * frame_.height * 3,
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if (rotate_src == nullptr) {
@@ -598,7 +608,7 @@ bool EspVideo::Capture() {
esp_imgfx_color_convert_cfg_t convert_cfg = {
.in_res = {.width = static_cast<int16_t>(frame_.width),
.height = static_cast<int16_t>(frame_.height)},
.in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_YUYV,
.in_pixel_fmt = static_cast<esp_imgfx_pixel_fmt_t>(frame_.format),
.out_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888,
};
esp_imgfx_color_convert_handle_t convert_handle = nullptr;
@@ -746,6 +756,7 @@ bool EspVideo::Capture() {
switch (frame_.format) {
// LVGL 显示 YUV 系的图像似乎都有问题,暂时转换为 RGB565 显示
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_RGB24: {
color_format = LV_COLOR_FORMAT_RGB565;
+5 -2
View File
@@ -79,7 +79,7 @@ void Nt26Board::StartNetwork() {
modem_ = std::make_unique<UartEthModem>(config);
modem_->SetDebug(false);
modem_->SetNetworkEventCallback([this](UartEthModem::UartEthModemEvent event) {
modem_->SetNetworkEventCallback([this](UartEthModem::UartEthModemEvent event, const std::string& detail) {
switch (event) {
case UartEthModem::UartEthModemEvent::Connected:
esp_timer_stop(network_ready_timer_);
@@ -105,11 +105,14 @@ void Nt26Board::StartNetwork() {
case UartEthModem::UartEthModemEvent::ErrorNoCarrier:
esp_timer_stop(network_ready_timer_);
ScheduleAsyncStop();
OnNetworkEvent(NetworkEvent::ModemErrorInitFailed);
OnNetworkEvent(NetworkEvent::ModemErrorInitFailed, detail);
break;
case UartEthModem::UartEthModemEvent::InFlightMode:
ESP_LOGW(TAG, "Modem in flight mode");
break;
case UartEthModem::UartEthModemEvent::RfTestReady:
ESP_LOGI(TAG, "Modem RF test mode ready");
break;
case UartEthModem::UartEthModemEvent::RequestingPdpContext:
break;
}
+12
View File
@@ -7,6 +7,8 @@
#include <esp_log.h>
#include <esp_sleep.h>
#include <esp_lvgl_port.h>
#include <esp_idf_version.h>
#include <inttypes.h>
#define TAG "SleepTimer"
@@ -99,11 +101,21 @@ void SleepTimer::CheckTimer() {
esp_light_sleep_start();
lvgl_port_resume();
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
// IDF 6 deprecates esp_sleep_get_wakeup_cause() in favor of
// the bitmap-based API that can report simultaneous sources.
auto wakeup_causes = esp_sleep_get_wakeup_causes();
ESP_LOGI(TAG, "Wake up from light sleep, wakeup_causes: 0x%" PRIx32, wakeup_causes);
if (!(wakeup_causes & (1UL << ESP_SLEEP_WAKEUP_TIMER))) {
break;
}
#else
auto wakeup_reason = esp_sleep_get_wakeup_cause();
ESP_LOGI(TAG, "Wake up from light sleep, wakeup_reason: %d", wakeup_reason);
if (wakeup_reason != ESP_SLEEP_WAKEUP_TIMER) {
break;
}
#endif
}
WakeUp();
});
+5
View File
@@ -12,6 +12,7 @@
#include "assets/lang_config.h"
#include <esp_log.h>
#include <esp_idf_version.h>
#include <esp_lcd_panel_vendor.h>
#include <driver/i2c_master.h>
#include <driver/spi_common.h>
@@ -233,7 +234,11 @@ private:
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 16;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#else
panel_config.color_space = ESP_LCD_COLOR_SPACE_BGR;
#endif
ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel));
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel));
+6 -1
View File
@@ -5,6 +5,7 @@
#include <esp_lcd_panel_ops.h>
#include <esp_lcd_panel_vendor.h>
#include <esp_log.h>
#include <esp_idf_version.h>
#include "application.h"
#include "codecs/no_audio_codec.h"
@@ -59,7 +60,11 @@ private:
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; // Set to -1 if not use
panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; // LCD_RGB_ENDIAN_RGB;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#else
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#endif
panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18)
ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle));
+2 -1
View File
@@ -236,7 +236,8 @@ void AdcPdmAudioCodec::Start() {
output_volume_ = 10;
}
EnableInput(true);
// Input is opened lazily by AudioService::AudioInputTask. ESP-IDF's ADC
// continuous driver requires start and stop to run in the same task.
EnableOutput(true);
ESP_LOGI(TAG, "Audio codec started");
}
@@ -3,6 +3,7 @@
"builds": [
{
"name": "esp-p4-function-ev-board",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SLAVE_IDF_TARGET_ESP32C6=y",
"CONFIG_ESP_HOSTED_P4_DEV_BOARD_FUNC_BOARD=y",
@@ -69,7 +69,8 @@ private:
//add support ev board
.timings = GC9503_800_480_PANEL_60HZ_RGB_TIMING(),
.data_width = 16, // RGB565 in parallel mode, thus 16bit in width
.bits_per_pixel = 16,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = GC9503V_LCD_RGB_BUFFER_NUMS,
.bounce_buffer_size_px = GC9503V_LCD_H_RES * GC9503V_LCD_RGB_BOUNCE_BUFFER_HEIGHT,
.dma_burst_size = 64,
@@ -110,14 +111,12 @@ private:
.auto_del_panel_io = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
// .bits_per_pixel = 16,
//add surpport ev board
.bits_per_pixel = 18,
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
// The GC9503V accepts 18-bit panel data while the RGB framebuffer is RGB565.
panel_config.bits_per_pixel = 18;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.vendor_config = &vendor_config;
(esp_lcd_new_panel_gc9503(panel_io, &panel_config, &panel_handle));
(esp_lcd_panel_reset(panel_handle));
(esp_lcd_panel_init(panel_handle));
@@ -45,7 +45,7 @@
#define GC9503V_PIN_NUM_DATA14 GPIO_NUM_2 // R3
#define GC9503V_PIN_NUM_DATA15 GPIO_NUM_1 // R4
#define GC9503V_PIN_NUM_DISP_EN -1
#define GC9503V_PIN_NUM_DISP_EN GPIO_NUM_NC
#define GC9503V_LCD_IO_SPI_CS_1 (IO_EXPANDER_PIN_NUM_1)
#define GC9503V_LCD_IO_SPI_SCL_1 (IO_EXPANDER_PIN_NUM_2)
@@ -68,7 +68,8 @@ private:
//add support ev board
.timings = GC9503_480_480_PANEL_60HZ_RGB_TIMING(),
.data_width = 16, // RGB565 in parallel mode, thus 16bit in width
.bits_per_pixel = 16,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = GC9503V_LCD_RGB_BUFFER_NUMS,
.bounce_buffer_size_px = GC9503V_LCD_H_RES * GC9503V_LCD_RGB_BOUNCE_BUFFER_HEIGHT,
.dma_burst_size = 64,
@@ -109,14 +110,12 @@ private:
.auto_del_panel_io = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
// .bits_per_pixel = 16,
//add surpport ev board
.bits_per_pixel = 18,
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
// The GC9503V accepts 18-bit panel data while the RGB framebuffer is RGB565.
panel_config.bits_per_pixel = 18;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.vendor_config = &vendor_config;
(esp_lcd_new_panel_gc9503(panel_io, &panel_config, &panel_handle));
(esp_lcd_panel_reset(panel_handle));
(esp_lcd_panel_init(panel_handle));
+2 -2
View File
@@ -55,8 +55,8 @@
#define GC9503V_PIN_NUM_DATA14 GPIO_NUM_2 // R3
#define GC9503V_PIN_NUM_DATA15 GPIO_NUM_1 // R4
#define GC9503V_PIN_NUM_DISP_EN -1
#define GC9503V_PIN_NUM_DISP_EN GPIO_NUM_NC
#define GC9503V_LCD_IO_SPI_CS_1 (IO_EXPANDER_PIN_NUM_1)
#define GC9503V_LCD_IO_SPI_SCL_1 (IO_EXPANDER_PIN_NUM_2)
#define GC9503V_LCD_IO_SPI_SDO_1 (IO_EXPANDER_PIN_NUM_3)
#define GC9503V_LCD_IO_SPI_SDO_1 (IO_EXPANDER_PIN_NUM_3)
@@ -236,7 +236,8 @@ void AdcPdmAudioCodec::Start() {
output_volume_ = 10;
}
EnableInput(true);
// Input is opened lazily by AudioService::AudioInputTask. ESP-IDF's ADC
// continuous driver requires start and stop to run in the same task.
EnableOutput(true);
ESP_LOGI(TAG, "Audio codec started");
}
+15 -12
View File
@@ -914,8 +914,15 @@ private:
esp_lcd_panel_io_handle_t panel_io = nullptr;
esp_lcd_panel_handle_t panel = nullptr;
const esp_lcd_panel_io_spi_config_t io_config =
ST77916_PANEL_IO_QSPI_CONFIG(QSPI_PIN_NUM_LCD_CS, NULL, NULL);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = QSPI_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST,
&io_config, &panel_io));
st77916_vendor_config_t vendor_config = {
@@ -926,16 +933,12 @@ private:
.use_qspi_interface = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = QSPI_PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL,
.flags =
{
.reset_active_high = pcb_version,
},
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = QSPI_PIN_NUM_LCD_RST;
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL;
panel_config.flags.reset_active_high = pcb_version;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
+5 -5
View File
@@ -46,26 +46,26 @@ class Hu087Board : public WifiBoard {
// SSD1306 config
esp_lcd_panel_io_i2c_config_t io_config = {
.dev_addr = 0x3C,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.scl_speed_hz = 400 * 1000,
.control_phase_bytes = 1,
.dc_bit_offset = 6,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.flags =
{
.dc_low_on_data = 0,
.disable_control_phase = 0,
},
.scl_speed_hz = 400 * 1000,
};
ESP_ERROR_CHECK(
esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_));
esp_lcd_new_panel_io_i2c(display_i2c_bus_, &io_config, &panel_io_));
ESP_LOGI(TAG, "Install SSD1306 driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = -1;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 1;
esp_lcd_panel_ssd1306_config_t ssd1306_config = {
@@ -311,7 +311,7 @@ private:
ESP_LOGI(TAG, "Install LCD driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.rgb_ele_order = LCD_RGB_ENDIAN_BGR;
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
panel_config.bits_per_pixel = 16;
esp_lcd_new_panel_gc9309na(panel_io, &panel_config, &panel);
+6 -6
View File
@@ -99,24 +99,24 @@ private:
// SSD1306 config
esp_lcd_panel_io_i2c_config_t io_config = {
.dev_addr = 0x3C,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.scl_speed_hz = 400 * 1000,
.control_phase_bytes = 1,
.dc_bit_offset = 6,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.flags = {
.dc_low_on_data = 0,
.disable_control_phase = 0,
},
.scl_speed_hz = 400 * 1000,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_));
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(display_i2c_bus_, &io_config, &panel_io_));
ESP_LOGI(TAG, "Install SSD1306 driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = -1;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 1;
esp_lcd_panel_ssd1306_config_t ssd1306_config = {
@@ -267,4 +267,4 @@ public:
}
};
DECLARE_BOARD(KevinBoxBoard);
DECLARE_BOARD(KevinBoxBoard);
@@ -46,7 +46,8 @@ private:
.clk_src = LCD_CLK_SRC_PLL160M,
.timings = GC9503_376_960_PANEL_60HZ_RGB_TIMING(),
.data_width = 16, // RGB565 in parallel mode, thus 16bit in width
.bits_per_pixel = 16,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = GC9503V_LCD_RGB_BUFFER_NUMS,
.bounce_buffer_size_px = GC9503V_LCD_H_RES * GC9503V_LCD_RGB_BOUNCE_BUFFER_HEIGHT,
.dma_burst_size = 64,
@@ -87,12 +88,11 @@ private:
.auto_del_panel_io = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.vendor_config = &vendor_config;
(esp_lcd_new_panel_gc9503(panel_io, &panel_config, &panel_handle));
(esp_lcd_panel_reset(panel_handle));
(esp_lcd_panel_init(panel_handle));
+22 -22
View File
@@ -16,32 +16,32 @@
#define GC9503V_LCD_BK_LIGHT_ON_LEVEL 1
#define GC9503V_LCD_BK_LIGHT_OFF_LEVEL !GC9503V_LCD_BK_LIGHT_ON_LEVEL
#define GC9503V_PIN_NUM_BK_LIGHT GPIO_NUM_4
#define GC9503V_PIN_NUM_HSYNC 6
#define GC9503V_PIN_NUM_VSYNC 5
#define GC9503V_PIN_NUM_DE 15
#define GC9503V_PIN_NUM_PCLK 7
#define GC9503V_PIN_NUM_HSYNC GPIO_NUM_6
#define GC9503V_PIN_NUM_VSYNC GPIO_NUM_5
#define GC9503V_PIN_NUM_DE GPIO_NUM_15
#define GC9503V_PIN_NUM_PCLK GPIO_NUM_7
#define GC9503V_PIN_NUM_DATA0 47 // B0
#define GC9503V_PIN_NUM_DATA1 21 // B1
#define GC9503V_PIN_NUM_DATA2 14 // B2
#define GC9503V_PIN_NUM_DATA3 13 // B3
#define GC9503V_PIN_NUM_DATA4 12 // B4
#define GC9503V_PIN_NUM_DATA0 GPIO_NUM_47 // B0
#define GC9503V_PIN_NUM_DATA1 GPIO_NUM_21 // B1
#define GC9503V_PIN_NUM_DATA2 GPIO_NUM_14 // B2
#define GC9503V_PIN_NUM_DATA3 GPIO_NUM_13 // B3
#define GC9503V_PIN_NUM_DATA4 GPIO_NUM_12 // B4
#define GC9503V_PIN_NUM_DATA5 11 // G0
#define GC9503V_PIN_NUM_DATA6 10 // G1
#define GC9503V_PIN_NUM_DATA7 9 // G2
#define GC9503V_PIN_NUM_DATA8 46 // G3
#define GC9503V_PIN_NUM_DATA9 3 // G4
#define GC9503V_PIN_NUM_DATA10 20 // G5
#define GC9503V_PIN_NUM_DATA5 GPIO_NUM_11 // G0
#define GC9503V_PIN_NUM_DATA6 GPIO_NUM_10 // G1
#define GC9503V_PIN_NUM_DATA7 GPIO_NUM_9 // G2
#define GC9503V_PIN_NUM_DATA8 GPIO_NUM_46 // G3
#define GC9503V_PIN_NUM_DATA9 GPIO_NUM_3 // G4
#define GC9503V_PIN_NUM_DATA10 GPIO_NUM_20 // G5
#define GC9503V_PIN_NUM_DATA11 19 // R0
#define GC9503V_PIN_NUM_DATA12 8 // R1
#define GC9503V_PIN_NUM_DATA13 18 // R2
#define GC9503V_PIN_NUM_DATA14 17 // R3
#define GC9503V_PIN_NUM_DATA15 16 // R4
#define GC9503V_PIN_NUM_DATA11 GPIO_NUM_19 // R0
#define GC9503V_PIN_NUM_DATA12 GPIO_NUM_8 // R1
#define GC9503V_PIN_NUM_DATA13 GPIO_NUM_18 // R2
#define GC9503V_PIN_NUM_DATA14 GPIO_NUM_17 // R3
#define GC9503V_PIN_NUM_DATA15 GPIO_NUM_16 // R4
#define GC9503V_PIN_NUM_DISP_EN -1
#define GC9503V_PIN_NUM_DISP_EN GPIO_NUM_NC
#define GC9503V_LCD_IO_SPI_CS_1 (GPIO_NUM_48)
#define GC9503V_LCD_IO_SPI_SCL_1 (GPIO_NUM_17)
#define GC9503V_LCD_IO_SPI_SDO_1 (GPIO_NUM_16)
#define GC9503V_LCD_IO_SPI_SDO_1 (GPIO_NUM_16)
@@ -45,24 +45,24 @@ private:
// SSD1306 config
esp_lcd_panel_io_i2c_config_t io_config = {
.dev_addr = 0x3C,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.scl_speed_hz = 400 * 1000,
.control_phase_bytes = 1,
.dc_bit_offset = 6,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.flags = {
.dc_low_on_data = 0,
.disable_control_phase = 0,
},
.scl_speed_hz = 400 * 1000,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_));
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(display_i2c_bus_, &io_config, &panel_io_));
ESP_LOGI(TAG, "Install SSD1306 driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = -1;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 1;
esp_lcd_panel_ssd1306_config_t ssd1306_config = {
@@ -130,4 +130,4 @@ public:
}
};
DECLARE_BOARD(EDARobotPro);
DECLARE_BOARD(EDARobotPro);
@@ -10,6 +10,7 @@
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_idf_version.h"
#include "esp_lcd_gc9d01n.h"
@@ -66,7 +67,7 @@ esp_err_t esp_lcd_new_panel_gc9d01n(const esp_lcd_panel_io_handle_t io, const es
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
break;
}
#else
#elif ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0)
switch (panel_dev_config->rgb_endian){
case LCD_RGB_ENDIAN_RGB:
gc9d01n->madctl_val = 0;
@@ -78,6 +79,18 @@ esp_err_t esp_lcd_new_panel_gc9d01n(const esp_lcd_panel_io_handle_t io, const es
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian");
break;
}
#else
switch (panel_dev_config->rgb_ele_order){
case LCD_RGB_ELEMENT_ORDER_RGB:
gc9d01n->madctl_val = 0;
break;
case LCD_RGB_ELEMENT_ORDER_BGR:
gc9d01n->madctl_val |= LCD_CMD_BGR_BIT;
break;
default:
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported RGB element order");
break;
}
#endif
switch (panel_dev_config->bits_per_pixel){
@@ -156,8 +156,8 @@ private:
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = DISPLAY_CS;
io_config.dc_gpio_num = DISPLAY_DC;
io_config.cs_gpio_num = static_cast<gpio_num_t>(DISPLAY_CS);
io_config.dc_gpio_num = static_cast<gpio_num_t>(DISPLAY_DC);
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
@@ -167,7 +167,7 @@ private:
ESP_LOGD(TAG, "Install LCD driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = DISPLAY_RST;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
ESP_ERROR_CHECK(esp_lcd_new_panel_gc9d01n(panel_io, &panel_config, &panel));
@@ -46,9 +46,9 @@ Tcircles3AudioCodec::~Tcircles3AudioCodec() {
void Tcircles3AudioCodec::CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data,
gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data) {
i2s_chan_config_t mic_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port_t(0), I2S_ROLE_MASTER);
i2s_chan_config_t mic_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(XIAOZHI_I2S_PORT(0), I2S_ROLE_MASTER);
mic_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer
i2s_chan_config_t spkr_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port_t(1), I2S_ROLE_MASTER);
i2s_chan_config_t spkr_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(XIAOZHI_I2S_PORT(1), I2S_ROLE_MASTER);
spkr_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer
ESP_ERROR_CHECK(i2s_new_channel(&mic_chan_config, NULL, &rx_handle_));
@@ -206,7 +206,7 @@ public:
},
};
esp_lcd_panel_dev_config_t dev_config = {
.reset_gpio_num = -1,
.reset_gpio_num = GPIO_NUM_NC,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = SCREEN_BITS_PER_PIXEL,
.vendor_config = &vendor_config,
@@ -220,7 +220,7 @@ public:
},
};
esp_lcd_panel_dev_config_t dev_config = {
.reset_gpio_num = -1,
.reset_gpio_num = GPIO_NUM_NC,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = SCREEN_BITS_PER_PIXEL,
.vendor_config = &vendor_config,
@@ -180,8 +180,8 @@ private:
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = DISPLAY_CS;
io_config.dc_gpio_num = DISPLAY_DC;
io_config.cs_gpio_num = static_cast<gpio_num_t>(DISPLAY_CS);
io_config.dc_gpio_num = static_cast<gpio_num_t>(DISPLAY_DC);
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
@@ -191,7 +191,7 @@ private:
ESP_LOGD(TAG, "Install LCD driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = DISPLAY_RST;
panel_config.reset_gpio_num = static_cast<gpio_num_t>(DISPLAY_RST);
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
panel_config.bits_per_pixel = 16;
ESP_ERROR_CHECK(esp_lcd_new_panel_st7796(panel_io, &panel_config, &panel));
@@ -60,9 +60,9 @@ Tdisplays3promvsrloraAudioCodec::~Tdisplays3promvsrloraAudioCodec() {
void Tdisplays3promvsrloraAudioCodec::CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data,
gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data) {
i2s_chan_config_t mic_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port_t(0), I2S_ROLE_MASTER);
i2s_chan_config_t mic_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(XIAOZHI_I2S_PORT(0), I2S_ROLE_MASTER);
mic_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer
i2s_chan_config_t spkr_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port_t(1), I2S_ROLE_MASTER);
i2s_chan_config_t spkr_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(XIAOZHI_I2S_PORT(1), I2S_ROLE_MASTER);
spkr_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer
ESP_ERROR_CHECK(i2s_new_channel(&mic_chan_config, NULL, &rx_handle_));
+1 -1
View File
@@ -5,7 +5,7 @@
#include <driver/gpio.h>
#define AUDIO_INPUT_REFERENCE true
#define AUDIO_INPUT_REFERENCE false
#define AUDIO_INPUT_SAMPLE_RATE 24000
#define AUDIO_OUTPUT_SAMPLE_RATE 24000
@@ -167,8 +167,15 @@ private:
esp_lcd_panel_io_handle_t panel_io = nullptr;
esp_lcd_panel_handle_t panel = nullptr;
esp_lcd_panel_io_spi_config_t io_config = CO5300_PANEL_IO_QSPI_CONFIG(
DISPLAY_QSPI_CS, nullptr, nullptr);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = DISPLAY_QSPI_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(DISPLAY_QSPI_HOST, &io_config, &panel_io));
co5300_vendor_config_t vendor_config = {
+4 -4
View File
@@ -12,12 +12,12 @@
* No dependency override needed — the project already specifies the correct `esp_video` and `esp_ipa` versions in `main/idf_component.yml`. Do NOT change the dependency versions unless you are also modifying the source code to match the older API.
针对 ESP32-P4 Rev <3.0 用户:
确保你的 sdkconfig.defaults 包含:
`release.py` 会根据当前 ESP-IDF 版本选择芯片版本:
CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y
- ESP-IDF < 6`m5stack-tab5` 面向 Rev < 3,并包含 `CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y``CONFIG_ESP32P4_REV_MIN_100=y``m5stack-tab5-p4x` 面向 Rev >= 3。
- ESP-IDF >= 6:只提供面向 Rev >= 3 的 `m5stack-tab5-p4x`
否则烧写的时候会出现:'bootloader/bootloader.bin' requires chip revision in range [v3.0 - v3.99] (this chip is revision v1.x)
不要把 IDF 6 生成的固件强制刷入 Rev 1.x 芯片;正常情况下烧录工具会报告:`bootloader/bootloader.bin requires chip revision in range [v3.0 - v3.99] (this chip is revision v1.x)`
1. 使用 release.py 编译
+1
View File
@@ -3,6 +3,7 @@
"builds": [
{
"name": "m5stack-tab5",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_BOARD_TYPE_M5STACK_CORE_TAB5=y",
"CONFIG_CAMERA_SC202CS=y",
+13 -17
View File
@@ -228,7 +228,8 @@ private:
.virtual_channel = 0,
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 60,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 2,
.video_timing = {
.h_size = DISPLAY_WIDTH,
@@ -240,9 +241,6 @@ private:
.vsync_back_porch = 20,
.vsync_front_porch = 20,
},
.flags = {
.use_dma2d = false,
},
};
ili9881c_vendor_config_t vendor_config = {
@@ -257,7 +255,7 @@ private:
esp_lcd_panel_dev_config_t lcd_dev_config = {};
lcd_dev_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
lcd_dev_config.reset_gpio_num = -1;
lcd_dev_config.reset_gpio_num = GPIO_NUM_NC;
lcd_dev_config.bits_per_pixel = 16;
lcd_dev_config.vendor_config = &vendor_config;
@@ -317,7 +315,8 @@ private:
dpi_config.virtual_channel = 0;
dpi_config.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT;
dpi_config.dpi_clock_freq_mhz = 70; // ST7123 DPI clock frequency
dpi_config.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565;
dpi_config.in_color_format = LCD_COLOR_FMT_RGB565;
dpi_config.out_color_format = LCD_COLOR_FMT_RGB565;
dpi_config.num_fbs = 1;
dpi_config.video_timing.h_size = 720;
dpi_config.video_timing.v_size = 1280;
@@ -327,7 +326,6 @@ private:
dpi_config.video_timing.vsync_pulse_width = 2;
dpi_config.video_timing.vsync_back_porch = 8;
dpi_config.video_timing.vsync_front_porch = 220;
dpi_config.flags.use_dma2d = true;
vendor_config.init_cmds = st7123_vendor_specific_init_default;
vendor_config.init_cmds_size = sizeof(st7123_vendor_specific_init_default) / sizeof(st7123_vendor_specific_init_default[0]);
@@ -335,7 +333,7 @@ private:
vendor_config.mipi_config.dpi_config = &dpi_config;
vendor_config.mipi_config.lane_num = 2;
lcd_dev_config.reset_gpio_num = -1;
lcd_dev_config.reset_gpio_num = GPIO_NUM_NC;
lcd_dev_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
lcd_dev_config.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE;
lcd_dev_config.bits_per_pixel = 24;
@@ -407,14 +405,13 @@ private:
},
};
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = {
.dev_addr = 0x55,
.control_phase_bytes = 1,
.dc_bit_offset = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.scl_speed_hz = 100000,
};
esp_lcd_panel_io_i2c_config_t tp_io_config = {};
tp_io_config.dev_addr = 0x55;
tp_io_config.scl_speed_hz = 100000;
tp_io_config.control_phase_bytes = 1;
tp_io_config.dc_bit_offset = 0;
tp_io_config.lcd_cmd_bits = 8;
tp_io_config.lcd_param_bits = 8;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle));
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_st7123(tp_io_handle, &tp_cfg, &touch_));
}
@@ -571,4 +568,3 @@ public:
DECLARE_BOARD(M5StackTab5Board);
@@ -7,6 +7,7 @@
#include "led/single_led.h"
#include <esp_log.h>
#include <esp_idf_version.h>
#include <esp_efuse_table.h>
#include <driver/i2c_master.h>
@@ -64,7 +65,11 @@ private:
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; // Set to -1 if not use
panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; //LCD_RGB_ENDIAN_RGB;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#else
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#endif
panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18)
ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle));
@@ -7,6 +7,7 @@
#include "led/single_led.h"
#include <esp_log.h>
#include <esp_idf_version.h>
#include <esp_efuse_table.h>
#include <driver/i2c_master.h>
@@ -91,7 +92,11 @@ private:
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; // Set to -1 if not use
panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; //LCD_RGB_ENDIAN_RGB;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#else
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#endif
panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18)
ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle));
@@ -285,8 +285,15 @@ private:
esp_lcd_panel_handle_t panel = nullptr;
ESP_LOGI(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = ST77916_PANEL_IO_QSPI_CONFIG(DISPLAY_QSPI_CS_PIN, NULL, NULL);
// io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ;
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = DISPLAY_QSPI_CS_PIN;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)DISPLAY_QSPI_HOST, &io_config, &panel_io));
@@ -298,12 +305,11 @@ private:
.use_qspi_interface = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = DISPLAY_QSPI_RESET_PIN,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = DISPLAY_QSPI_BIT_PER_PIXEL,
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = DISPLAY_QSPI_BIT_PER_PIXEL;
panel_config.reset_gpio_num = DISPLAY_QSPI_RESET_PIN;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef _BOARD_CONFIG_H_
#define _BOARD_CONFIG_H_
#include <driver/adc.h>
#include <esp_adc/adc_oneshot.h>
#include <driver/gpio.h>
#define OTTO_VERSION_AUTO 0
@@ -334,7 +334,7 @@ private:
ESP_LOGI(TAG, "Install panel IO");
const esp_lcd_panel_io_spi_config_t io_config = {
.cs_gpio_num = BSP_LCD_SPI_CS,
.dc_gpio_num = -1,
.dc_gpio_num = GPIO_NUM_NC,
.spi_mode = 3,
.pclk_hz = DRV_LCD_PIXEL_CLK_HZ,
.trans_queue_depth = 2,
@@ -352,12 +352,11 @@ private:
esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &panel_io_);
ESP_LOGD(TAG, "Install LCD driver");
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = BSP_LCD_GPIO_RST, // Shared with Touch reset
.rgb_ele_order = DRV_LCD_RGB_ELEMENT_ORDER,
.bits_per_pixel = DRV_LCD_BITS_PER_PIXEL,
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = DRV_LCD_RGB_ELEMENT_ORDER;
panel_config.bits_per_pixel = DRV_LCD_BITS_PER_PIXEL;
panel_config.reset_gpio_num = BSP_LCD_GPIO_RST; // Shared with Touch reset
panel_config.vendor_config = &vendor_config;
esp_lcd_new_panel_spd2010(panel_io_, &panel_config, &panel_);
esp_lcd_panel_reset(panel_);
@@ -5,7 +5,6 @@
#include <esp_timer.h>
#include <driver/gpio.h>
#include <esp_adc/adc_oneshot.h>
#include <driver/adc.h>
#include <esp_log.h>
class PowerManager {
@@ -186,4 +185,4 @@ public:
void OnChargingStatusChanged(std::function<void(bool)> callback) {
on_charging_status_changed_ = callback;
}
};
};
@@ -7,6 +7,7 @@
#include "led/single_led.h"
#include "assets/lang_config.h"
#include <esp_log.h>
#include <esp_idf_version.h>
#include <esp_efuse_table.h>
#include <driver/i2c_master.h>
@@ -335,7 +336,11 @@ private:
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; // Set to -1 if not use
panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; //LCD_RGB_ENDIAN_RGB;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#else
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR;
#endif
panel_config.bits_per_pixel = 16;
ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle));
+14 -7
View File
@@ -562,7 +562,15 @@ private:
ESP_LOGI(TAG, "Install panel IO");
const esp_lcd_panel_io_spi_config_t io_config = ST77916_PANEL_IO_QSPI_CONFIG(QSPI_PIN_NUM_LCD_CS, NULL, NULL);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = QSPI_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io));
ESP_LOGI(TAG, "Install ST77916 panel driver");
@@ -574,12 +582,11 @@ private:
.use_qspi_interface = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = QSPI_PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h`
.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18)
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; // Implemented by LCD command `36h`
panel_config.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL; // Implemented by LCD command `3Ah` (16/18)
panel_config.reset_gpio_num = QSPI_PIN_NUM_LCD_RST;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
+6 -6
View File
@@ -102,24 +102,24 @@ private:
// SSD1306 config
esp_lcd_panel_io_i2c_config_t io_config = {
.dev_addr = 0x3C,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.scl_speed_hz = 400 * 1000,
.control_phase_bytes = 1,
.dc_bit_offset = 6,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
.on_color_trans_done = nullptr,
.user_ctx = nullptr,
.flags = {
.dc_low_on_data = 0,
.disable_control_phase = 0,
},
.scl_speed_hz = 400 * 1000,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_));
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(display_i2c_bus_, &io_config, &panel_io_));
ESP_LOGI(TAG, "Install SSD1306 driver");
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.reset_gpio_num = -1;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.bits_per_pixel = 1;
esp_lcd_panel_ssd1306_config_t ssd1306_config = {
@@ -252,4 +252,4 @@ public:
}
};
DECLARE_BOARD(KevinBoxBoard);
DECLARE_BOARD(KevinBoxBoard);
@@ -141,7 +141,7 @@ class CustomBoard : public WifiBoard {
void InitializeLcdDisplay() {
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = LCD_CS;
io_config.dc_gpio_num = -1;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 8;
@@ -122,7 +122,7 @@ private:
void InitializeLcdDisplay() {
const esp_lcd_panel_io_spi_config_t io_config = {
.cs_gpio_num = LCD_CS,
.dc_gpio_num = -1,
.dc_gpio_num = GPIO_NUM_NC,
.spi_mode = 0,
.pclk_hz = 40 * 1000 * 1000,
.trans_queue_depth = 4,
@@ -143,12 +143,11 @@ private:
.use_qspi_interface = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h`
.bits_per_pixel = 16, // Implemented by LCD command `3Ah` (16/18)
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; // Implemented by LCD command `36h`
panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18)
panel_config.reset_gpio_num = LCD_RST;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_sh8601(io_handle, &panel_config, &panel_handle));
esp_lcd_panel_set_gap(panel_handle,0x06,0x00);
ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
@@ -289,4 +288,4 @@ public:
};
DECLARE_BOARD(CustomBoard);
DECLARE_BOARD(CustomBoard);
@@ -210,11 +210,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = SH8601_PANEL_IO_QSPI_CONFIG(
EXAMPLE_PIN_NUM_LCD_CS,
nullptr,
nullptr
);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -216,10 +216,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = SH8601_PANEL_IO_QSPI_CONFIG(
EXAMPLE_PIN_NUM_LCD_CS,
nullptr,
nullptr);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -230,8 +230,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config =
SH8601_PANEL_IO_QSPI_CONFIG(LCD_CS, nullptr, nullptr);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -121,21 +121,14 @@ private:
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = {
.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS,
.on_color_trans_done = 0,
.user_ctx = 0,
.control_phase_bytes = 1,
.dc_bit_offset = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 0,
.flags =
{
.dc_low_on_data = 0,
.disable_control_phase = 1,
},
};
esp_lcd_panel_io_i2c_config_t tp_io_config = {};
tp_io_config.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS;
tp_io_config.scl_speed_hz = 100000;
tp_io_config.control_phase_bytes = 1;
tp_io_config.dc_bit_offset = 0;
tp_io_config.lcd_cmd_bits = 8;
tp_io_config.lcd_param_bits = 0;
tp_io_config.flags.disable_control_phase = 1;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle));
esp_lcd_touch_config_t tp_cfg = {
@@ -171,21 +171,14 @@ private:
},
};
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = {
.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS,
.on_color_trans_done = 0,
.user_ctx = 0,
.control_phase_bytes = 1,
.dc_bit_offset = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 0,
.flags =
{
.dc_low_on_data = 0,
.disable_control_phase = 1,
},
};
tp_io_config.scl_speed_hz = 400* 1000;
esp_lcd_panel_io_i2c_config_t tp_io_config = {};
tp_io_config.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS;
tp_io_config.scl_speed_hz = 400 * 1000;
tp_io_config.control_phase_bytes = 1;
tp_io_config.dc_bit_offset = 0;
tp_io_config.lcd_cmd_bits = 8;
tp_io_config.lcd_param_bits = 0;
tp_io_config.flags.disable_control_phase = 1;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle));
ESP_LOGI(TAG, "Initialize touch controller");
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp));
@@ -4,6 +4,7 @@
"builds": [
{
"name": "esp32-p4-nano-10.1-a",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_USE_WECHAT_MESSAGE_STYLE=y",
"CONFIG_CAMERA_OV5647=y",
@@ -151,7 +151,8 @@ private:
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 80,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 1,
.video_timing = {
.h_size = 800,
@@ -163,9 +164,6 @@ private:
.vsync_back_porch = 4,
.vsync_front_porch = 30,
},
.flags = {
.use_dma2d = true,
},
};
jd9365_vendor_config_t vendor_config = {
@@ -179,9 +177,9 @@ private:
};
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
.vendor_config = &vendor_config,
};
esp_lcd_new_panel_jd9365(io, &lcd_dev_config, &disp_panel);
@@ -4,6 +4,7 @@
"builds": [
{
"name": "esp32-p4-wifi6-touch-lcd-3.5",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -10,6 +10,7 @@
#include "esp_lcd_st7796.h"
#include "config.h"
#include <esp_log.h>
#include <esp_idf_version.h>
#include <driver/i2c_master.h>
#include <esp_lvgl_port.h>
#include "esp_lcd_touch_ft5x06.h"
@@ -66,9 +67,13 @@ private:
io_config.trans_queue_depth = 10;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI2_HOST, &io_config, &io));
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR,
#else
.color_space = ESP_LCD_COLOR_SPACE_BGR,
#endif
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7796(io, &lcd_dev_config, &disp_panel));
ESP_ERROR_CHECK(esp_lcd_panel_reset(disp_panel));
@@ -4,6 +4,7 @@
"builds": [
{
"name": "esp32-p4-wifi6-touch-lcd-4b",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -34,6 +35,7 @@
},
{
"name": "esp32-p4-wifi6-touch-lcd-4.3",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -64,6 +66,7 @@
},
{
"name": "esp32-p4-wifi6-touch-lcd-5",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -94,6 +97,7 @@
},
{
"name": "esp32-p4-wifi6-touch-lcd-7b",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -130,6 +134,7 @@
},
{
"name": "esp32-p4-wifi6-touch-lcd-3.4c",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -160,6 +165,7 @@
},
{
"name": "esp32-p4-wifi6-touch-lcd-4c",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -190,6 +196,7 @@
},
{
"name": "esp32-p4-wifi6-touch-lcd-7",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -220,6 +227,7 @@
},
{
"name": "esp32-p4-wifi6-touch-lcd-8",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -250,6 +258,7 @@
},
{
"name": "esp32-p4-wifi6-touch-lcd-10.1",
"idf_version": "<6.0",
"sdkconfig_append": [
"CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0",
"CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y",
@@ -106,7 +106,8 @@ private:
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 46,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 1,
.video_timing = {
.h_size = 720,
@@ -118,9 +119,6 @@ private:
.vsync_back_porch = 12,
.vsync_front_porch = 30,
},
.flags = {
.use_dma2d = true,
},
};
st7703_vendor_config_t vendor_config = {
@@ -134,9 +132,9 @@ private:
};
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
.vendor_config = &vendor_config,
};
esp_lcd_new_panel_st7703(io, &lcd_dev_config, &disp_panel);
@@ -144,7 +142,8 @@ private:
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 30,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 1,
.video_timing = {
.h_size = 480,
@@ -156,9 +155,6 @@ private:
.vsync_back_porch = 2,
.vsync_front_porch = 60,
},
.flags = {
.use_dma2d = true,
},
};
st7701_vendor_config_t vendor_config = {
.init_cmds = vendor_specific_init_default,
@@ -174,9 +170,9 @@ private:
};
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
.vendor_config = &vendor_config,
};
esp_lcd_new_panel_st7701(io, &lcd_dev_config, &disp_panel);
@@ -184,7 +180,8 @@ private:
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 58,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 1,
.video_timing = {
.h_size = DISPLAY_WIDTH,
@@ -196,9 +193,6 @@ private:
.vsync_back_porch = 10,
.vsync_front_porch = 24,
},
.flags = {
.use_dma2d = true,
},
};
hx8394_vendor_config_t vendor_config = {
.mipi_config = {
@@ -209,20 +203,21 @@ private:
};
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
.vendor_config = &vendor_config,
.flags = {
.reset_active_high = true,
},
.vendor_config = &vendor_config,
};
esp_lcd_new_panel_hx8394(io, &lcd_dev_config, &disp_panel);
#elif CONFIG_BOARD_TYPE_WAVESHARE_ESP32_P4_WIFI6_TOUCH_LCD_7B
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 52,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 1,
.video_timing = {
.h_size = 1024,
@@ -234,9 +229,6 @@ private:
.vsync_back_porch = 23,
.vsync_front_porch = 12,
},
.flags = {
.use_dma2d = true,
},
};
ek79007_vendor_config_t vendor_config = {
.mipi_config = {
@@ -246,9 +238,9 @@ private:
};
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
.vendor_config = &vendor_config,
};
esp_lcd_new_panel_ek79007(io, &lcd_dev_config, &disp_panel);
@@ -256,7 +248,8 @@ private:
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 46,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 1,
.video_timing = {
.h_size = DISPLAY_WIDTH,
@@ -268,9 +261,6 @@ private:
.vsync_back_porch = 12,
.vsync_front_porch = 24,
},
.flags = {
.use_dma2d = true,
},
};
jd9365_vendor_config_t vendor_config = {
.init_cmds = lcd_init_cmds,
@@ -283,9 +273,9 @@ private:
};
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
.vendor_config = &vendor_config,
};
esp_lcd_new_panel_jd9365(io, &lcd_dev_config, &disp_panel);
@@ -293,7 +283,8 @@ private:
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 52,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 1,
.video_timing = {
.h_size = DISPLAY_WIDTH,
@@ -305,9 +296,6 @@ private:
.vsync_back_porch = 10,
.vsync_front_porch = 30,
},
.flags = {
.use_dma2d = true,
},
};
jd9365_vendor_config_t vendor_config = {
.init_cmds = lcd_init_cmds,
@@ -320,9 +308,9 @@ private:
};
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
.vendor_config = &vendor_config,
};
esp_lcd_new_panel_jd9365(io, &lcd_dev_config, &disp_panel);
@@ -330,7 +318,8 @@ private:
esp_lcd_dpi_panel_config_t dpi_config = {
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = 80,
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
.in_color_format = LCD_COLOR_FMT_RGB565,
.out_color_format = LCD_COLOR_FMT_RGB565,
.num_fbs = 1,
.video_timing = {
.h_size = DISPLAY_WIDTH,
@@ -342,9 +331,6 @@ private:
.vsync_back_porch = 20,
.vsync_front_porch = 2,
},
.flags = {
.use_dma2d = true,
},
};
ili9881c_vendor_config_t vendor_config = {
.init_cmds = lcd_init_cmds,
@@ -357,9 +343,9 @@ private:
};
const esp_lcd_panel_dev_config_t lcd_dev_config = {
.reset_gpio_num = PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.reset_gpio_num = PIN_NUM_LCD_RST,
.vendor_config = &vendor_config,
};
esp_lcd_new_panel_ili9881c(io, &lcd_dev_config, &disp_panel);
@@ -18,6 +18,7 @@
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_idf_version.h"
static const char *TAG = "JD9853";
@@ -76,7 +77,7 @@ esp_err_t esp_lcd_new_panel_jd9853(const esp_lcd_panel_io_handle_t io, const esp
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
break;
}
#else
#elif ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0)
switch (panel_dev_config->rgb_endian)
{
case LCD_RGB_ENDIAN_RGB:
@@ -89,6 +90,19 @@ esp_err_t esp_lcd_new_panel_jd9853(const esp_lcd_panel_io_handle_t io, const esp
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian");
break;
}
#else
switch (panel_dev_config->rgb_ele_order)
{
case LCD_RGB_ELEMENT_ORDER_RGB:
jd9853->madctl_val = 0;
break;
case LCD_RGB_ELEMENT_ORDER_BGR:
jd9853->madctl_val |= LCD_CMD_BGR_BIT;
break;
default:
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported RGB element order");
break;
}
#endif
switch (panel_dev_config->bits_per_pixel)
@@ -62,8 +62,8 @@ height_(height)
ret = spi_bus_initialize(spi_host, &buscfg, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.dc_gpio_num = dc_;
io_config.cs_gpio_num = cs_;
io_config.dc_gpio_num = static_cast<gpio_num_t>(dc_);
io_config.cs_gpio_num = static_cast<gpio_num_t>(cs_);
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.lcd_cmd_bits = 8;
io_config.lcd_param_bits = 8;
@@ -141,7 +141,7 @@ class CustomBoard : public WifiBoard {
void InitializeLcdDisplay() {
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = LCD_CS;
io_config.dc_gpio_num = -1;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 8;
@@ -132,7 +132,7 @@ class CustomBoard : public WifiBoard {
void InitializeLcdDisplay() {
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = LCD_CS_PIN;
io_config.dc_gpio_num = -1;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 8;
@@ -229,10 +229,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = CO5300_PANEL_IO_QSPI_CONFIG(
EXAMPLE_PIN_NUM_LCD_CS,
nullptr,
nullptr);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -288,10 +288,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = CO5300_PANEL_IO_QSPI_CONFIG(
EXAMPLE_PIN_NUM_LCD_CS,
nullptr,
nullptr);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -338,21 +343,14 @@ private:
},
};
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = {
.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS,
.on_color_trans_done = 0,
.user_ctx = 0,
.control_phase_bytes = 1,
.dc_bit_offset = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 0,
.flags =
{
.dc_low_on_data = 0,
.disable_control_phase = 1,
},
};
tp_io_config.scl_speed_hz = 400* 1000;
esp_lcd_panel_io_i2c_config_t tp_io_config = {};
tp_io_config.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS;
tp_io_config.scl_speed_hz = 400 * 1000;
tp_io_config.control_phase_bytes = 1;
tp_io_config.dc_bit_offset = 0;
tp_io_config.lcd_cmd_bits = 8;
tp_io_config.lcd_param_bits = 0;
tp_io_config.flags.disable_control_phase = 1;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(codec_i2c_bus_, &tp_io_config, &tp_io_handle));
ESP_LOGI(TAG, "Initialize touch controller");
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp));
@@ -282,11 +282,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = SH8601_PANEL_IO_QSPI_CONFIG(
EXAMPLE_PIN_NUM_LCD_CS,
nullptr,
nullptr
);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -216,10 +216,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = SH8601_PANEL_IO_QSPI_CONFIG(
EXAMPLE_PIN_NUM_LCD_CS,
nullptr,
nullptr);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -230,10 +230,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGD(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = CO5300_PANEL_IO_QSPI_CONFIG(
EXAMPLE_PIN_NUM_LCD_CS,
nullptr,
nullptr);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = EXAMPLE_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 0;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -120,7 +120,15 @@ private:
ESP_LOGI(TAG, "Install panel IO");
const esp_lcd_panel_io_spi_config_t io_config = SPD2010_PANEL_IO_QSPI_CONFIG(QSPI_PIN_NUM_LCD_CS, NULL, NULL);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = QSPI_PIN_NUM_LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 3;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io));
ESP_LOGI(TAG, "Install SPD2010 panel driver");
@@ -130,12 +138,11 @@ private:
.use_qspi_interface = 1,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = QSPI_PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h`
.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18)
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL;
panel_config.reset_gpio_num = QSPI_PIN_NUM_LCD_RST;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_spd2010(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
@@ -122,21 +122,14 @@ private:
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = {
.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS,
.on_color_trans_done = 0,
.user_ctx = 0,
.control_phase_bytes = 1,
.dc_bit_offset = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 0,
.flags =
{
.dc_low_on_data = 0,
.disable_control_phase = 1,
},
};
esp_lcd_panel_io_i2c_config_t tp_io_config = {};
tp_io_config.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS;
tp_io_config.scl_speed_hz = 100000;
tp_io_config.control_phase_bytes = 1;
tp_io_config.dc_bit_offset = 0;
tp_io_config.lcd_cmd_bits = 8;
tp_io_config.lcd_param_bits = 0;
tp_io_config.flags.disable_control_phase = 1;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle));
esp_lcd_touch_config_t tp_cfg = {
@@ -172,21 +172,14 @@ private:
},
};
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
esp_lcd_panel_io_i2c_config_t tp_io_config = {
.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS,
.on_color_trans_done = 0,
.user_ctx = 0,
.control_phase_bytes = 1,
.dc_bit_offset = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 0,
.flags =
{
.dc_low_on_data = 0,
.disable_control_phase = 1,
},
};
tp_io_config.scl_speed_hz = 400* 1000;
esp_lcd_panel_io_i2c_config_t tp_io_config = {};
tp_io_config.dev_addr = ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS;
tp_io_config.scl_speed_hz = 400 * 1000;
tp_io_config.control_phase_bytes = 1;
tp_io_config.dc_bit_offset = 0;
tp_io_config.lcd_cmd_bits = 8;
tp_io_config.lcd_param_bits = 0;
tp_io_config.flags.disable_control_phase = 1;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle));
ESP_LOGI(TAG, "Initialize touch controller");
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp));
@@ -276,7 +276,7 @@ private:
esp_lcd_panel_io_spi_config_t io_config = {
.cs_gpio_num = QSPI_PIN_NUM_LCD_CS,
.dc_gpio_num = -1,
.dc_gpio_num = GPIO_NUM_NC,
.spi_mode = 0,
.pclk_hz = 3 * 1000 * 1000,
.trans_queue_depth = 10,
@@ -338,12 +338,11 @@ private:
}
printf("------------------------------------- End of version selection------------------------------------- \r\n");
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = QSPI_PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h`
.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18)
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL;
panel_config.reset_gpio_num = QSPI_PIN_NUM_LCD_RST;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
@@ -495,7 +495,7 @@ private:
esp_lcd_panel_io_spi_config_t io_config = {
.cs_gpio_num = QSPI_PIN_NUM_LCD_CS,
.dc_gpio_num = -1,
.dc_gpio_num = GPIO_NUM_NC,
.spi_mode = 0,
.pclk_hz = 3 * 1000 * 1000,
.trans_queue_depth = 10,
@@ -558,12 +558,11 @@ private:
}
printf("------------------------------------- End of version selection------------------------------------- \r\n");
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = QSPI_PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h`
.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18)
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL;
panel_config.reset_gpio_num = QSPI_PIN_NUM_LCD_RST;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
@@ -275,7 +275,7 @@ private:
esp_lcd_panel_io_spi_config_t io_config = {
.cs_gpio_num = QSPI_PIN_NUM_LCD_CS,
.dc_gpio_num = -1,
.dc_gpio_num = GPIO_NUM_NC,
.spi_mode = 0,
.pclk_hz = 3 * 1000 * 1000,
.trans_queue_depth = 10,
@@ -337,12 +337,11 @@ private:
}
printf("------------------------------------- End of version selection------------------------------------- \r\n");
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = QSPI_PIN_NUM_LCD_RST,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h`
.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18)
.vendor_config = &vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL;
panel_config.reset_gpio_num = QSPI_PIN_NUM_LCD_RST;
panel_config.vendor_config = &vendor_config;
ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel));
esp_lcd_panel_reset(panel);
@@ -96,10 +96,15 @@ private:
// 液晶屏控制IO初始化
ESP_LOGI(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = AXS15231B_PANEL_IO_QSPI_CONFIG(
LCD_CS,
NULL,
NULL);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = LCD_CS;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 3;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -111,12 +116,11 @@ private:
.use_qspi_interface = 1,
},
};
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = -1,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.vendor_config = (void *)&vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
panel_config.reset_gpio_num = GPIO_NUM_NC;
panel_config.vendor_config = (void *)&vendor_config;
esp_lcd_new_panel_axs15231b(panel_io, &panel_config, &panel);
gpio_set_level(LCD_RST,1);
@@ -250,4 +254,4 @@ public:
}
};
DECLARE_BOARD(CustomBoard);
DECLARE_BOARD(CustomBoard);
@@ -221,10 +221,15 @@ private:
esp_lcd_panel_handle_t panel = nullptr;
// 液晶屏控制IO初始化
ESP_LOGI(TAG, "Install panel IO");
esp_lcd_panel_io_spi_config_t io_config = AXS15231B_PANEL_IO_QSPI_CONFIG(
DISPLAY_CS_PIN,
NULL,
NULL);
esp_lcd_panel_io_spi_config_t io_config = {};
io_config.cs_gpio_num = DISPLAY_CS_PIN;
io_config.dc_gpio_num = GPIO_NUM_NC;
io_config.spi_mode = 3;
io_config.pclk_hz = 40 * 1000 * 1000;
io_config.trans_queue_depth = 10;
io_config.lcd_cmd_bits = 32;
io_config.lcd_param_bits = 8;
io_config.flags.quad_mode = true;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io));
// 初始化液晶屏驱动芯片
@@ -236,12 +241,11 @@ private:
.use_qspi_interface = 1,
},
};
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = DISPLAY_RST_PIN,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.bits_per_pixel = 16,
.vendor_config = (void *)&vendor_config,
};
esp_lcd_panel_dev_config_t panel_config = {};
panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB;
panel_config.bits_per_pixel = 16;
panel_config.reset_gpio_num = DISPLAY_RST_PIN;
panel_config.vendor_config = (void *)&vendor_config;
esp_lcd_new_panel_axs15231b(panel_io, &panel_config, &panel);
esp_lcd_panel_reset(panel);

Some files were not shown because too many files have changed in this diff Show More