added support fo guition board

This commit is contained in:
2026-03-13 16:39:27 +00:00
parent 0203682200
commit c5233cf15c
16 changed files with 1293 additions and 4 deletions

189
GUITION_SETUP.md Normal file
View File

@@ -0,0 +1,189 @@
# Guition JC4827W543C Board Setup Guide
This guide explains how to configure and build squeezelite-esp32 for the Guition JC4827W543C development board.
## Board Features
- **Processor**: ESP32-S3-WROOM-1 (dual-core, 240MHz)
- **Display**: 4.3" ILI9488 LCD (480x272 pixels)
- **Touch**: GT911 capacitive touch controller
- **Interface**: QSPI display interface
- **Memory**: 4MB Flash, 4MB PSRAM
- **Connectivity**: WiFi, Bluetooth
## Hardware Configuration
### Display Connections (QSPI)
- **CLK**: GPIO47
- **DATA0**: GPIO21
- **DATA1**: GPIO48
- **DATA2**: GPIO40
- **DATA3**: GPIO39
- **CS**: GPIO45
- **DC**: Not used with QSPI
- **RST**: GPIO38 (if available)
### I2C Connections (Touch)
- **SDA**: GPIO8
- **SCL**: GPIO4
- **Touch INT**: GPIO3
- **Touch RST**: GPIO38
### Audio I2S (External DAC Required)
- **BCK**: GPIO15
- **WS**: GPIO16
- **DO**: GPIO17
- **DI**: (not used for output only)
### Other GPIO
- **Backlight**: GPIO1 (PWM controlled)
## Software Configuration
### 1. Build Configuration
Use the provided build script:
```bash
# Make the script executable
chmod +x build-guition.sh
# Configure and build
./build-guition.sh
```
Or manually:
```bash
# Set ESP32-S3 target
export IDF_TARGET=esp32s3
# Copy Guition configuration
cp squeezelite-esp32-Guition-sdkconfig.defaults sdkconfig.defaults
# Configure project
idf.py menuconfig
# Build
idf.py build
```
### 2. Menuconfig Settings
In `idf.py menuconfig`, select:
**Target Configuration**:
- `Squeezelite-ESP32``Guition JC4827W543C`
**Audio Settings**:
- Configure I2S GPIO pins for your external DAC
- Default: BCK=15, WS=16, DO=17
**Display Settings**:
- Should be automatically configured as:
- Type: QSPI
- Driver: ILI9488
- Width: 480
- Height: 272
- CS: 45
- Speed: 20MHz
**I2C Settings**:
- SDA: 8
- SCL: 4
- Speed: 400kHz
- Port: 0
### 3. External Audio DAC
The Guition board does not have a built-in audio DAC. You must connect an external I2S DAC such as:
- PCM5102
- TAS575x series
- ES8388
- AC101
Connect the DAC to the I2S pins and configure it in the NVS settings or through the web UI.
## Flashing the Firmware
```bash
# Flash to the board
idf.py -p /dev/ttyUSB0 flash
# Monitor output (optional)
idf.py -p /dev/ttyUSB0 monitor
```
## First Boot Configuration
1. Connect to the WiFi AP created by the device (SSID: SqueezeESP32-XXXXXX)
2. Open the web configuration interface
3. Configure your WiFi network
4. Set up your audio DAC if needed
5. Configure LMS server connection
## Display Features
The ILI9488 driver supports:
- 16-bit RGB565 color
- Hardware acceleration
- Shadow buffering for performance
- Automatic dirty region tracking
- Rotation and flip options
## Touch Support
Touch functionality is planned but not yet implemented. The GT911 touch controller is connected via I2C.
## Troubleshooting
### Display Not Working
- Check QSPI GPIO connections
- Verify CS pin is correctly set to GPIO45
- Ensure proper power supply (3.3V for display logic)
### Audio Not Working
- Verify external DAC is properly connected
- Check I2S GPIO assignments
- Configure DAC model in web UI if using a supported DAC
### Build Issues
- Ensure ESP-IDF supports ESP32-S3
- Check that all required components are included
- Verify GPIO pin assignments don't conflict
## Performance Notes
- The 480x272 display requires significant memory bandwidth
- PSRAM is used for display framebuffer (≈260KB)
- Audio performance may be affected at high display refresh rates
- Consider reducing display update rate if audio issues occur
## GPIO Map Summary
| GPIO | Function | Direction |
|------|----------|-----------|
| 1 | Backlight PWM | Out |
| 3 | Touch INT | In |
| 4 | I2C SCL | Out |
| 8 | I2C SDA | I/O |
| 15 | I2S BCK | Out |
| 16 | I2S WS | Out |
| 17 | I2S DO | Out |
| 21 | QSPI DATA0 | Out |
| 39 | QSPI DATA3 | Out |
| 40 | QSPI DATA2 | Out |
| 45 | QSPI CS | Out |
| 47 | QSPI CLK | Out |
| 48 | QSPI DATA1 | Out |
| 38 | Touch RST | Out |
## Support
For issues specific to the Guition board implementation:
1. Check this README first
2. Review the squeezelite-esp32 documentation
3. Open an issue on the GitHub repository
For general squeezelite-esp32 questions, refer to the main project documentation and forums.

216
WINDOWS_BUILD_GUIDE.md Normal file
View File

@@ -0,0 +1,216 @@
# Windows Build Guide for Guition JC4827W543C
This guide explains how to build squeezelite-esp32 for the Guition board on Windows.
## Prerequisites
1. **ESP-IDF for Windows**
- Download and install ESP-IDF from: https://dl.espressif.com/dl/esp-idf/
- Run the installer and follow the setup instructions
- Make sure to install the required tools (Git, Python, CMake)
2. **Visual Studio Build Tools** (if not already installed by ESP-IDF)
- Install from Visual Studio Installer
- Select "C++ build tools"
3. **Hardware**
- Guition JC4827W543C board
- USB cable for power and programming
- External I2S audio DAC (required)
## Setup Instructions
### 1. Install ESP-IDF
```cmd
# Run the ESP-IDF installer
# Launch ESP-IDF Command Prompt from Start Menu
```
### 2. Initialize ESP-IDF Environment
```cmd
# In ESP-IDF Command Prompt
cd C:\Espressif\esp-idf
export.bat
```
### 3. Clone and Setup Project
```cmd
# Navigate to your workspace
cd C:\Users\YourName\Projects
# Clone the repository (if not already done)
git clone <repository-url> squeezelite-esp32-gronod
cd squeezelite-esp32-gronod
```
### 4. Set Environment for Project
```cmd
# Set ESP-IDF environment for this project
C:\Espressif\esp-idf\export.bat
```
## Build Methods
### Method 1: PowerShell Script (Recommended)
```powershell
# Open PowerShell as Administrator
# Navigate to project directory
cd C:\Users\YourName\Projects\squeezelite-esp32-gronod
# Run the build script
.\build-guition.ps1
# For clean build
.\build-guition.ps1 -Clean
```
**Note:** If you get execution policy errors, run:
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
### Method 2: Batch File (Simple)
```cmd
# Open Command Prompt
# Navigate to project directory
cd C:\Users\YourName\Projects\squeezelite-esp32-gronod
# Run the build script
build-guition.bat
# For clean build
build-guition.bat clean
```
### Method 3: Manual Commands
```cmd
# Set ESP-IDF environment
C:\Espressif\esp-idf\export.bat
# Set target
set IDF_TARGET=esp32s3
# Copy Guition config
copy /Y squeezelite-esp32-Guition-sdkconfig.defaults sdkconfig.defaults
# Configure (opens menu interface)
idf.py menuconfig
# Build
idf.py build
```
## Menuconfig Configuration
When `idf.py menuconfig` runs:
1. **Select Target Hardware**:
- Navigate to: `Squeezelite-ESP32``Guition JC4827W543C`
2. **Configure Audio** (if needed):
- Navigate to: `Audio settings``DAC settings`
- Set I2S GPIO pins for your external DAC
- Default: BCK=15, WS=16, DO=17
3. **Save and Exit**:
- Press `S` to save
- Press `Q` to exit
## Flashing the Firmware
### Find Your COM Port
```cmd
# List all COM ports
mode
# Or check Device Manager under "Ports (COM & LPT)"
```
### Flash and Monitor
```cmd
# Flash firmware
idf.py -p COM3 flash
# Flash and monitor (recommended)
idf.py -p COM3 flash monitor
# Just monitor (if already flashed)
idf.py -p COM3 monitor
```
### Using the Scripts
Both PowerShell and batch scripts will ask if you want to flash after building.
## Troubleshooting
### Common Issues
1. **"ESP-IDF environment not found"**
- Make sure you're running from ESP-IDF Command Prompt
- Or run `C:\Espressif\esp-idf\export.bat` first
2. **"Python not found"**
- ESP-IDF installer should include Python
- Check that Python is in your PATH
3. **"Build tools not found"**
- Install Visual Studio Build Tools
- Make sure C++ tools are selected
4. **"Permission denied" (PowerShell)**
- Run PowerShell as Administrator
- Or set execution policy: `Set-ExecutionPolicy RemoteSigned`
5. **"COM port not found"**
- Check device connections
- Install USB drivers if needed (CH340/CP210x)
- Check Device Manager
### Clean Build
If you encounter build issues:
```cmd
# Using batch file
build-guition.bat clean
# Or manually
idf.py fullclean
idf.py build
```
### Verifying Installation
```cmd
# Check ESP-IDF version
idf.py --version
# Check target
echo %IDF_TARGET%
# List available targets
idf.py --help | findstr target
```
## Development Workflow
1. **Initial Setup**: Run the build script once to configure
2. **Code Changes**: Make your modifications
3. **Build**: Run `.\build-guition.ps1` or `build-guition.bat`
4. **Flash**: Let the script flash automatically, or use `idf.py -p COMX flash`
5. **Monitor**: Use `idf.py -p COMX monitor` to view logs
## Performance Tips
- **SSD Storage**: Build on SSD for much faster compilation
- **RAM**: 8GB+ recommended for large projects
- **CPU**: Multi-core CPU helps with parallel compilation
- **Antivirus**: Exclude project directory from real-time scanning
## Next Steps
After successful build and flash:
1. Connect to WiFi AP created by device
2. Configure your network settings
3. Set up audio DAC configuration
4. Connect to your Logitech Media Server
For more detailed configuration, see `GUITION_SETUP.md`.

80
build-guition.bat Normal file
View File

@@ -0,0 +1,80 @@
@echo off
REM Build script for Guition JC4827W543C board - Batch file version
REM Usage: build-guition.bat [clean]
echo Building Squeezelite-ESP32 for Guition JC4827W543C
REM Check if ESP-IDF environment is set up
if "%IDF_PATH%"=="" (
echo Error: ESP-IDF environment not found!
echo Please run esp-idf\export.bat first
pause
exit /b 1
)
REM Set target to ESP32-S3
set IDF_TARGET=esp32s3
echo Target set to: %IDF_TARGET%
REM Copy Guition-specific configuration
if exist "squeezelite-esp32-Guition-sdkconfig.defaults" (
echo Using Guition configuration...
copy /Y "squeezelite-esp32-Guition-sdkconfig.defaults" "sdkconfig.defaults"
) else (
echo Warning: Guition configuration file not found
)
REM Clean if requested
if /i "%1"=="clean" (
echo Cleaning build...
idf.py fullclean
if errorlevel 1 (
echo Clean failed!
pause
exit /b 1
)
)
REM Configure the project
echo Configuring project...
echo Running: idf.py menuconfig
echo Select: Squeezelite-ESP32 -^> Guition JC4827W543C
echo.
echo Press any key to continue to menuconfig...
pause > nul
idf.py menuconfig
if errorlevel 1 (
echo Configuration failed!
pause
exit /b 1
)
REM Build the project
echo Building firmware...
idf.py build
if errorlevel 1 (
echo Build failed!
pause
exit /b 1
)
echo Build complete!
echo Firmware location: build\squeezelite.bin
echo.
echo To flash the firmware:
echo idf.py -p ^<PORT^> flash
echo.
echo To monitor output:
echo idf.py -p ^<PORT^> monitor
REM Ask if user wants to flash
echo.
set /p flash="Do you want to flash the firmware now? (y/n) "
if /i "%flash%"=="y" (
set /p port="Enter COM port (e.g., COM3): "
echo Flashing to %port%...
idf.py -p %port% flash monitor
)
pause

76
build-guition.ps1 Normal file
View File

@@ -0,0 +1,76 @@
# Build script for Guition JC4827W543C board - PowerShell version
# Usage: .\build-guition.ps1 [-Clean]
param(
[switch]$Clean
)
Write-Host "Building Squeezelite-ESP32 for Guition JC4827W543C" -ForegroundColor Green
# Check if ESP-IDF environment is set up
if (-not $env:IDF_PATH) {
Write-Host "Error: ESP-IDF environment not found!" -ForegroundColor Red
Write-Host "Please run esp-idf/export.bat first" -ForegroundColor Yellow
exit 1
}
# Set target to ESP32-S3
$env:IDF_TARGET = "esp32s3"
Write-Host "Target set to: $env:IDF_TARGET" -ForegroundColor Cyan
# Copy Guition-specific configuration
if (Test-Path "squeezelite-esp32-Guition-sdkconfig.defaults") {
Write-Host "Using Guition configuration..." -ForegroundColor Cyan
Copy-Item "squeezelite-esp32-Guition-sdkconfig.defaults" "sdkconfig.defaults" -Force
} else {
Write-Host "Warning: Guition configuration file not found" -ForegroundColor Yellow
}
# Clean if requested
if ($Clean) {
Write-Host "Cleaning build..." -ForegroundColor Cyan
idf.py fullclean
if ($LASTEXITCODE -ne 0) {
Write-Host "Clean failed!" -ForegroundColor Red
exit 1
}
}
# Configure the project
Write-Host "Configuring project..." -ForegroundColor Cyan
Write-Host "Running: idf.py menuconfig" -ForegroundColor White
Write-Host "Select: Squeezelite-ESP32 -> Guition JC4827W543C" -ForegroundColor Yellow
Write-Host "Press Enter to continue to menuconfig..." -ForegroundColor White
Read-Host
idf.py menuconfig
if ($LASTEXITCODE -ne 0) {
Write-Host "Configuration failed!" -ForegroundColor Red
exit 1
}
# Build the project
Write-Host "Building firmware..." -ForegroundColor Cyan
idf.py build
if ($LASTEXITCODE -ne 0) {
Write-Host "Build failed!" -ForegroundColor Red
exit 1
}
Write-Host "Build complete!" -ForegroundColor Green
Write-Host "Firmware location: build\squeezelite.bin" -ForegroundColor Cyan
Write-Host ""
Write-Host "To flash the firmware:" -ForegroundColor White
Write-Host "idf.py -p <PORT> flash" -ForegroundColor Yellow
Write-Host ""
Write-Host "To monitor output:" -ForegroundColor White
Write-Host "idf.py -p <PORT> monitor" -ForegroundColor Yellow
# Ask if user wants to flash
Write-Host ""
$flash = Read-Host "Do you want to flash the firmware now? (y/n)"
if ($flash -eq 'y' -or $flash -eq 'Y') {
$port = Read-Host "Enter COM port (e.g., COM3)"
Write-Host "Flashing to $port..." -ForegroundColor Cyan
idf.py -p $port flash monitor
}

40
build-guition.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Build script for Guition JC4827W543C board
# Usage: ./build-guition.sh [clean]
set -e
echo "Building Squeezelite-ESP32 for Guition JC4827W543C"
# Set target to ESP32-S3
export IDF_TARGET=esp32s3
# Copy Guition-specific configuration
if [ -f "squeezelite-esp32-Guition-sdkconfig.defaults" ]; then
echo "Using Guition configuration..."
cp squeezelite-esp32-Guition-sdkconfig.defaults sdkconfig.defaults
fi
# Clean if requested
if [ "$1" == "clean" ]; then
echo "Cleaning build..."
idf.py fullclean
fi
# Configure with Guition target
echo "Configuring project..."
idf.py menuconfig
# Build the project
echo "Building firmware..."
idf.py build
echo "Build complete!"
echo "Firmware location: build/squeezelite.bin"
echo ""
echo "To flash the firmware:"
echo "idf.py -p <PORT> flash"
echo ""
echo "To monitor output:"
echo "idf.py -p <PORT> monitor"

View File

@@ -0,0 +1,297 @@
/**
* ILI9488 Display Driver for Guition JC4827W543C
* Supports QSPI interface for 480x272 resolution
* Based on ILI9341 driver adapted for ILI9488
*
* (c) Guition Support 2026
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <esp_heap_caps.h>
#include <esp_log.h>
#include "gds.h"
#include "gds_private.h"
#define SHADOW_BUFFER
#define USE_IRAM
#define PAGE_BLOCK 4096
#define ENABLE_WRITE 0x2c
#define min(a,b) (((a) < (b)) ? (a) : (b))
static char TAG[] = "ILI9488";
struct PrivateSpace {
uint8_t *iRAM, *Shadowbuffer;
struct {
uint16_t Height, Width;
} Offset;
uint8_t MADCtl, PageSize;
uint8_t Model;
};
// ILI9488 Commands
static const uint8_t ILI9488_INIT_SEQUENCE[] = {
// Software reset
0x01, 0x80, 150, // SWRESET, delay 150ms
// Power control
0xD0, 3, 0x07, 0x42, 0x18, // Power Control
0xD1, 3, 0x00, 0x07, 0x10, // VCOM Control
0xD2, 1, 0x01, // Power Control for Normal Mode
0xC0, 2, 0x10, 0x3B, // Panel Driving Setting
0xC1, 1, 0x10, // Frame Rate Control
0xC5, 5, 0x0A, 0x3A, 0x28, 0x28, 0x02, // MCU Control
0xC6, 1, 0x00, // Frame Rate Control
0xB1, 2, 0x00, 0x1B, // Display Function Control
0xB4, 1, 0x02, // Inversion Control
0xB6, 3, 0x02, 0x02, 0x3B, // Display Function Control
0xB7, 1, 0xC6, // Entry Mode Set
0xE0, 16, 0x00, 0x07, 0x10, 0x0E, 0x09, 0x16, 0x06, 0x0A,
0x0E, 0x09, 0x15, 0x0D, 0x0E, 0x11, 0x0F, 0x12, // Positive Gamma Control
0xE1, 16, 0x00, 0x17, 0x1A, 0x04, 0x0E, 0x06, 0x2F, 0x24,
0x1B, 0x1B, 0x22, 0x1F, 0x1E, 0x37, 0x3F, 0x00, // Negative Gamma Control
0x36, 1, 0xE8, // Memory Access Control (MX, MY, RGB mode)
0x3A, 1, 0x55, // Interface Pixel Format (16bpp)
0x11, 0x80, 150, // Sleep Out, delay 150ms
0x29, 0x80, 50, // Display On, delay 50ms
0xFF, 0x00 // End of sequence
};
static void WriteByte( struct GDS_Device* Device, uint8_t Data ) {
Device->WriteData( Device, &Data, 1 );
}
static void SetColumnAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) {
uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16);
Device->WriteCommand( Device, 0x2A );
Device->WriteData( Device, (uint8_t*) &Addr, 4 );
}
static void SetRowAddress( struct GDS_Device* Device, uint16_t Start, uint16_t End ) {
uint32_t Addr = __builtin_bswap16(Start) | (__builtin_bswap16(End) << 16);
Device->WriteCommand( Device, 0x2B );
Device->WriteData( Device, (uint8_t*) &Addr, 4 );
}
static void Update16( struct GDS_Device* Device ) {
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
#ifdef SHADOW_BUFFER
uint32_t *optr = (uint32_t*) Private->Shadowbuffer, *iptr = (uint32_t*) Device->Framebuffer;
int FirstCol = Device->Width / 2, LastCol = 0, FirstRow = -1, LastRow = 0;
for (int r = 0; r < Device->Height; r++) {
// look for change and update shadow (cheap optimization = width is always a multiple of 2)
for (int c = 0; c < Device->Width / 2; c++, iptr++, optr++) {
if (*optr != *iptr) {
*optr = *iptr;
if (c < FirstCol) FirstCol = c;
if (c > LastCol) LastCol = c;
if (FirstRow < 0) FirstRow = r;
LastRow = r;
}
}
// wait for a large enough window - careful that window size might increase by more than a line at once !
if (FirstRow < 0 || ((LastCol - FirstCol + 1) * (r - FirstRow + 1) * 4 < PAGE_BLOCK && r != Device->Height - 1)) continue;
FirstCol *= 2;
LastCol = LastCol * 2 + 1;
SetRowAddress( Device, FirstRow + Private->Offset.Height, LastRow + Private->Offset.Height);
SetColumnAddress( Device, FirstCol + Private->Offset.Width, LastCol + Private->Offset.Width );
Device->WriteCommand( Device, ENABLE_WRITE );
int ChunkSize = (LastCol - FirstCol + 1) * 2;
// own use of IRAM has not proven to be much better than letting SPI do its copy
if (Private->iRAM) {
uint8_t *optr = Private->iRAM;
for (int i = FirstRow; i <= LastRow; i++) {
memcpy(optr, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize);
optr += ChunkSize;
if (optr - Private->iRAM <= (PAGE_BLOCK - ChunkSize) && i < LastRow) continue;
Device->WriteData(Device, Private->iRAM, optr - Private->iRAM);
optr = Private->iRAM;
}
} else for (int i = FirstRow; i <= LastRow; i++) {
Device->WriteData( Device, Private->Shadowbuffer + (i * Device->Width + FirstCol) * 2, ChunkSize );
}
FirstCol = Device->Width / 2;
LastCol = 0;
FirstRow = -1;
}
#endif
}
static void Clear( struct GDS_Device* Device ) {
memset( Device->Framebuffer, 0, Device->Width * Device->Height * 2 );
Device->Update( Device);
}
static void SetPixel( struct GDS_Device* Device, int X, int Y, uint32_t Color ) {
if( X < 0 || X >= Device->Width || Y < 0 || Y >= Device->Height) return;
*((uint16_t*) Device->Framebuffer + (Y * Device->Width) + X) = (uint16_t) Color;
}
static uint32_t GetPixel( struct GDS_Device* Device, int X, int Y ) {
if( X < 0 || X >= Device->Width || Y < 0 || Y >= Device->Height) return 0;
return *((uint16_t*) Device->Framebuffer + (Y * Device->Width) + X);
}
static void DrawPixel( struct GDS_Device* Device, int X, int Y, uint32_t Color ) {
SetPixel( Device, X, Y, Color );
}
static void DrawPixelFast( struct GDS_Device* Device, int X, int Y, uint32_t Color ) {
*((uint16_t*) Device->Framebuffer + (Y * Device->Width) + X) = (uint16_t) Color;
}
static void DrawCBR( struct GDS_Device* Device, int X, int Y, int Width, int Height, uint32_t Color ) {
uint16_t *fb = (uint16_t*) Device->Framebuffer + Y * Device->Width + X;
for( int y = 0; y < Height; y++) {
for( int x = 0; x < Width; x++) {
fb[x] = (uint16_t) Color;
}
fb += Device->Width;
}
}
static void DrawHLine( struct GDS_Device* Device, int X0, int X1, int Y, uint32_t Color ) {
if( Y < 0 || Y >= Device->Height) return;
if( X0 > X1) {
int Temp = X0;
X0 = X1;
X1 = Temp;
}
if( X0 < 0) X0 = 0;
if( X1 >= Device->Width) X1 = Device->Width - 1;
uint16_t *fb = (uint16_t*) Device->Framebuffer + Y * Device->Width + X0;
for( int x = X0; x <= X1; x++) {
*fb++ = (uint16_t) Color;
}
}
static void DrawVLine( struct GDS_Device* Device, int X, int Y0, int Y1, uint32_t Color ) {
if( X < 0 || X >= Device->Width) return;
if( Y0 > Y1) {
int Temp = Y0;
Y0 = Y1;
Y1 = Temp;
}
if( Y0 < 0) Y0 = 0;
if( Y1 >= Device->Height) Y1 = Device->Height - 1;
uint16_t *fb = (uint16_t*) Device->Framebuffer + Y0 * Device->Width + X;
for( int y = Y0; y <= Y1; y++) {
*fb = (uint16_t) Color;
fb += Device->Width;
}
}
static bool Init( struct GDS_Device* Device ) {
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
const uint8_t *p = ILI9488_INIT_SEQUENCE;
ESP_LOGI(TAG, "Initializing ILI9488 display %dx%d", Device->Width, Device->Height);
// Allocate IRAM buffer if available
Private->iRAM = (uint8_t*) heap_caps_malloc(PAGE_BLOCK, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
if (!Private->iRAM) {
ESP_LOGW(TAG, "Could not allocate IRAM buffer, using direct write");
}
#ifdef SHADOW_BUFFER
Private->Shadowbuffer = (uint8_t*) heap_caps_malloc(Device->Width * Device->Height * 2, MALLOC_CAP_DMA);
if (!Private->Shadowbuffer) {
ESP_LOGE(TAG, "Could not allocate shadow buffer");
if (Private->iRAM) free(Private->iRAM);
return false;
}
memset(Private->Shadowbuffer, 0, Device->Width * Device->Height * 2);
#endif
// Send initialization sequence
while(*p != 0xFF) {
uint8_t cmd = *p++;
uint8_t len = (*p & 0x7F);
bool delay = (*p++ & 0x80);
Device->WriteCommand(Device, cmd);
if(len) Device->WriteData(Device, (uint8_t*)p, len);
p += len;
if(delay) {
uint8_t ms = *p++;
vTaskDelay(ms / portTICK_PERIOD_MS);
}
}
// Set orientation and layout
Private->MADCtl = 0xE8; // MX=1, MY=1, RGB=1, BGR=0
Device->WriteCommand(Device, 0x36);
Device->WriteData(Device, &Private->MADCtl, 1);
// Set pixel format to 16-bit
uint8_t fmt = 0x55;
Device->WriteCommand(Device, 0x3A);
Device->WriteData(Device, &fmt, 1);
// Turn on display
Device->WriteCommand(Device, 0x29);
ESP_LOGI(TAG, "ILI9488 initialization complete");
return true;
}
static void Deinit( struct GDS_Device* Device ) {
struct PrivateSpace *Private = (struct PrivateSpace*) Device->Private;
if (Private->iRAM) free(Private->iRAM);
#ifdef SHADOW_BUFFER
if (Private->Shadowbuffer) free(Private->Shadowbuffer);
#endif
}
struct GDS_Device* ILI9488_Detect( char *Driver, struct GDS_Device *Device ) {
if(strcasecmp(Driver, "ILI9488") != 0) return NULL;
Device->Private = calloc(1, sizeof(struct PrivateSpace));
if(!Device->Private) {
ESP_LOGE(TAG, "Cannot allocate private data");
return NULL;
}
Device->Mode = GDS_RGB565;
Device->Depth = 16;
Device->Update = Update16;
Device->Clear = Clear;
Device->SetPixel = SetPixel;
Device->GetPixel = GetPixel;
Device->DrawPixel = DrawPixel;
Device->DrawPixelFast = DrawPixelFast;
Device->DrawCBR = DrawCBR;
Device->DrawHLine = DrawHLine;
Device->DrawVLine = DrawVLine;
Device->Init = Init;
Device->Deinit = Deinit;
ESP_LOGI(TAG, "ILI9488 driver loaded");
return Device;
}

View File

@@ -13,6 +13,10 @@ bool GDS_I2CAttachDevice( struct GDS_Device* Device, int Width, int Height, int
bool GDS_SPIInit( int SPI, int DC );
bool GDS_SPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed, int BacklightPin, int Mode );
bool GDS_QSPIInit( int QSPI, int DC );
bool GDS_QSPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int Speed, int BacklightPin, int Mode );
bool GDS_QSPIBusInit( int MOSIPin, int MISOPin, int CLKPin, int Host );
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,161 @@
/**
* QSPI Interface for Guition JC4827W543C ILI9488 Display
* Supports ESP32-S3 QSPI peripheral
*
* (c) Guition Support 2026
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include <freertos/task.h>
#include "gds.h"
#include "gds_err.h"
#include "gds_private.h"
#include "gds_default_if.h"
static const int GDS_QSPI_Command_Mode = 0;
static const int GDS_QSPI_Data_Mode = 1;
static spi_host_device_t QSPIHost;
static int DCPin;
static bool QSPIDefaultWriteBytes( spi_device_handle_t QSPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength );
static bool QSPIDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command );
static bool QSPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength );
bool GDS_QSPIInit( int QSPI, int DC ) {
QSPIHost = QSPI;
DCPin = DC;
return true;
}
bool GDS_QSPIAttachDevice( struct GDS_Device* Device, int Width, int Height, int CSPin, int RSTPin, int BackLightPin, int Speed, int Mode ) {
spi_device_interface_config_t QSPIDeviceConfig = { };
spi_device_handle_t QSPIDevice;
NullCheck( Device, return false );
if (CSPin >= 0) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( CSPin, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( CSPin, 0 ), return false );
}
QSPIDeviceConfig.clock_speed_hz = Speed > 0 ? Speed : SPI_MASTER_FREQ_20M;
QSPIDeviceConfig.spics_io_num = CSPin;
QSPIDeviceConfig.queue_size = 4;
QSPIDeviceConfig.mode = Mode;
QSPIDeviceConfig.flags = SPI_DEVICE_HALFDUPLEX;
QSPIDeviceConfig.duty_cycle_pos = 128; // 50% duty cycle
// QSPI specific configuration for ESP32-S3
QSPIDeviceConfig.command_bits = 8;
QSPIDeviceConfig.address_bits = 24;
QSPIDeviceConfig.address_len = 3;
if( spi_bus_add_device( QSPIHost, &QSPIDeviceConfig, &QSPIDevice ) != ESP_OK ) {
GDS_LOG_ERROR( "Failed to add QSPI device to host" );
return false;
}
if( DCPin >= 0 ) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( DCPin, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( DCPin, 1 ), return false );
}
if( RSTPin >= 0 ) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( RSTPin, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( RSTPin, 1 ), return false );
}
if( BackLightPin >= 0 ) {
ESP_ERROR_CHECK_NONFATAL( gpio_set_direction( BackLightPin, GPIO_MODE_OUTPUT ), return false );
ESP_ERROR_CHECK_NONFATAL( gpio_set_level( BackLightPin, 1 ), return false );
}
Device->WriteCommand = QSPIDefaultWriteCommand;
Device->WriteData = QSPIDefaultWriteData;
Device->DeviceHandle = QSPIDevice;
// Hardware reset if pin is available
if( RSTPin >= 0 ) {
gpio_set_level( RSTPin, 0 );
vTaskDelay( pdMS_TO_TICKS( 10 ) );
gpio_set_level( RSTPin, 1 );
vTaskDelay( pdMS_TO_TICKS( 120 ) );
}
return true;
}
static bool QSPIDefaultWriteCommand( struct GDS_Device* Device, uint8_t Command ) {
return QSPIDefaultWriteBytes( Device->DeviceHandle, GDS_QSPI_Command_Mode, &Command, 1 );
}
static bool QSPIDefaultWriteData( struct GDS_Device* Device, const uint8_t* Data, size_t DataLength ) {
if( DCPin >= 0 ) {
gpio_set_level( DCPin, 1 );
}
bool Result = QSPIDefaultWriteBytes( Device->DeviceHandle, GDS_QSPI_Data_Mode, Data, DataLength );
if( DCPin >= 0 ) {
gpio_set_level( DCPin, 0 );
}
return Result;
}
static bool QSPIDefaultWriteBytes( spi_device_handle_t QSPIHandle, int WriteMode, const uint8_t* Data, size_t DataLength ) {
spi_transaction_ext_t SPITransaction = { };
SPITransaction.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
SPITransaction.base.cmd = 0;
SPITransaction.base.addr = 0;
SPITransaction.base.length = DataLength * 8;
SPITransaction.base.tx_buffer = Data;
SPITransaction.base.rx_buffer = NULL;
SPITransaction.command_bits = 8;
SPITransaction.address_bits = 0;
SPITransaction.dummy_bits = 0;
if( WriteMode == GDS_QSPI_Command_Mode ) {
SPITransaction.command_bits = 8;
SPITransaction.base.cmd = Data[0];
SPITransaction.base.length = 0;
SPITransaction.base.tx_buffer = NULL;
}
if( spi_device_transmit( QSPIHandle, (spi_transaction_t*) &SPITransaction ) != ESP_OK ) {
GDS_LOG_ERROR( "QSPI transaction failed" );
return false;
}
return true;
}
bool GDS_QSPIBusInit( int MOSIPin, int MISOPin, int CLKPin, int Host ) {
spi_bus_config_t BusConfig = { };
NullCheck( Host >= SPI2_HOST && Host <= SPI3_HOST, return false );
// QSPI pin configuration for ESP32-S3
BusConfig.mosi_io_num = MOSIPin;
BusConfig.miso_io_num = MISOPin;
BusConfig.sclk_io_num = CLKPin;
BusConfig.quadwp_io_num = -1; // Not used for ILI9488
BusConfig.quadhd_io_num = -1; // Not used for ILI9488
BusConfig.max_transfer_sz = 65536;
BusConfig.flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_NATIVE_PINS;
if( spi_bus_initialize( Host, &BusConfig, DMA_CH_AUTO ) != ESP_OK ) {
GDS_LOG_ERROR( "Failed to initialize QSPI bus" );
return false;
}
return true;
}

View File

@@ -73,6 +73,7 @@ static const char *known_drivers[] = {"SH1106",
"ST7735",
"ST7789",
"ILI9341",
"ILI9488",
NULL
};
@@ -80,8 +81,8 @@ static void displayer_task(void *args);
static void display_sleep(void);
struct GDS_Device *display;
extern GDS_DetectFunc SSD1306_Detect, SSD132x_Detect, SH1106_Detect, SH1122_Detect, SSD1675_Detect, SSD1322_Detect, SSD1351_Detect, ST77xx_Detect, ILI9341_Detect;
GDS_DetectFunc *drivers[] = { SH1106_Detect, SH1122_Detect, SSD1306_Detect, SSD132x_Detect, SSD1675_Detect, SSD1322_Detect, SSD1351_Detect, ST77xx_Detect, ILI9341_Detect, NULL };
extern GDS_DetectFunc SSD1306_Detect, SSD132x_Detect, SH1106_Detect, SH1122_Detect, SSD1675_Detect, SSD1322_Detect, SSD1351_Detect, ST77xx_Detect, ILI9341_Detect, ILI9488_Detect;
GDS_DetectFunc *drivers[] = { SH1106_Detect, SH1122_Detect, SSD1306_Detect, SSD132x_Detect, SSD1675_Detect, SSD1322_Detect, SSD1351_Detect, ST77xx_Detect, ILI9341_Detect, ILI9488_Detect, NULL };
/****************************************************************************************
*
@@ -134,6 +135,31 @@ void display_init(char *welcome) {
GDS_SPIAttachDevice( display, width, height, CS_pin, RST_pin, backlight_pin, speed, mode );
ESP_LOGI(TAG, "Display is SPI host %u with cs:%d", spi_system_host, CS_pin);
} else if (strcasestr(config, "QSPI") && spi_system_host != -1) {
int CS_pin = -1, speed = 0, mode = 0;
PARSE_PARAM(config, "cs", '=', CS_pin);
PARSE_PARAM(config, "speed", '=', speed);
PARSE_PARAM(config, "mode", '=', mode);
// Parse QSPI data pins
int data_pins[4] = {-1, -1, -1, -1};
char *data_str = strstr(config, "data=");
if (data_str) {
sscanf(data_str + 5, "%d,%d,%d,%d", &data_pins[0], &data_pins[1], &data_pins[2], &data_pins[3]);
}
init = true;
// Initialize QSPI bus with data pins
if (data_pins[0] != -1 && data_pins[1] != -1 && data_pins[2] != -1 && data_pins[3] != -1) {
GDS_QSPIBusInit( data_pins[0], data_pins[1], spi_system_clk_gpio, spi_system_host );
}
GDS_QSPIInit( spi_system_host, spi_system_dc_gpio );
GDS_QSPIAttachDevice( display, width, height, CS_pin, RST_pin, backlight_pin, speed, mode );
ESP_LOGI(TAG, "Display is QSPI host %u with cs:%d", spi_system_host, CS_pin);
} else {
display = NULL;
ESP_LOGI(TAG, "Unsupported display interface or serial link not configured");

View File

@@ -1,4 +1,4 @@
idf_component_register( SRC_DIRS . muse
idf_component_register( SRC_DIRS . muse guition
INCLUDE_DIRS .
PRIV_REQUIRES services
)

View File

@@ -0,0 +1,5 @@
idf_component_register(
SRCS "guition.c"
INCLUDE_DIRS "."
REQUIRES driver esp_common
)

View File

@@ -0,0 +1,43 @@
/*
* Guition JC4827W543C board support for squeezelite-esp32
*
* (c) Guition Board Support 2026
* Based on squeezelite-esp32 architecture
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include <string.h>
#include <esp_log.h>
#include <esp_types.h>
#include <esp_system.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "globdefs.h"
#include "monitor.h"
#include "targets.h"
static const char TAG[] = "guition";
static bool init(void);
const struct target_s target_guition = {
.model = "guition",
.init = init
};
static bool init(void) {
ESP_LOGI(TAG, "Initializing Guition JC4827W543C board");
ESP_LOGI(TAG, "Board features:");
ESP_LOGI(TAG, " - ESP32-S3-WROOM-1 processor");
ESP_LOGI(TAG, " - 4.3\" ILI9488 display (480x272)");
ESP_LOGI(TAG, " - GT911 capacitive touch");
ESP_LOGI(TAG, " - QSPI display interface");
ESP_LOGI(TAG, " - I2C touch interface (GPIO8/4)");
// No board-specific hardware initialization required
// All configuration is handled through NVS parameters
return true;
}

View File

@@ -1,7 +1,7 @@
#include "string.h"
#include "targets.h"
const struct target_s *target_set[] = { &target_muse, NULL };
const struct target_s *target_set[] = { &target_muse, &target_guition, NULL };
void target_init(char *target) {
for (int i = 0; *target && target_set[i]; i++) if (strcasestr(target_set[i]->model, target)) {

View File

@@ -20,3 +20,4 @@ struct target_s {
};
extern const struct target_s target_muse;
extern const struct target_s target_guition;

View File

@@ -73,6 +73,10 @@ menu "Squeezelite-ESP32"
bool "T-WATCH2020 by LilyGo"
select I2C_LOCKED
select TARGET_LOCKED
config GUITION
bool "Guition JC4827W543C"
select I2C_LOCKED
select TARGET_LOCKED
endchoice
config RELEASE_API
string "Software update URL"
@@ -91,12 +95,14 @@ menu "Squeezelite-ESP32"
default "SqueezeAMP" if SQUEEZEAMP
default "Squeezelite-TWATCH" if TWATCH2020
default "Muse" if MUSE
default "Squeezelite-Guition" if GUITION
default "Squeezelite-ESP32"
config FW_PLATFORM_NAME
string
default "SqueezeAmp" if SQUEEZEAMP
default "TWATCH" if TWATCH2020
default "Muse" if MUSE
default "Guition" if GUITION
default "ESP32"
# AGGREGATES - begin
# these parameters are "aggregates" that take precedence. They must have a default value
@@ -105,6 +111,7 @@ menu "Squeezelite-ESP32"
default "model=TAS57xx,bck=33,ws=25,do=32,sda=27,scl=26,mute=14:0" if SQUEEZEAMP
default "model=I2S,bck=26,ws=25,do=33,i2c=53,sda=21,scl=22" if TWATCH2020
default "model=I2S,bck=5,ws=25,do=26,di=35,i2c=16,sda=18,scl=23,mck" if MUSE
default "model=I2S,bck=15,ws=16,do=17" if GUITION
default ""
config SPDIF_CONFIG
string
@@ -117,10 +124,12 @@ menu "Squeezelite-ESP32"
string
default "dc=27,data=19,clk=18" if TWATCH2020
default "mosi=15,miso=2,clk=14" if MUSE
default "clk=47,data=21,48,40,39,cs=45,host=2" if GUITION
default ""
config DISPLAY_CONFIG
string
default "SPI,driver=ST7789,width=240,height=240,cs=5,back=12,speed=16000000,HFlip,VFlip" if TWATCH2020
default "QSPI,driver=ILI9488,width=480,height=272,cs=45,speed=20000000,invert,rotate" if GUITION
default ""
config ETH_CONFIG
string
@@ -143,6 +152,7 @@ menu "Squeezelite-ESP32"
config TARGET
string
default "muse" if MUSE
default "guition" if GUITION
default ""
config AMP_GPIO
int
@@ -176,6 +186,7 @@ menu "Squeezelite-ESP32"
string
default "0=ir" if SQUEEZEAMP
default "" if TWATCH2020
default "1=backlight" if GUITION
endmenu
menu "Audio settings"
@@ -344,6 +355,7 @@ menu "Squeezelite-ESP32"
visible if !TWATCH2020
config I2C_CONFIG
string "I2C system configuration"
default "sda=8,scl=4,speed=400000,port=0" if GUITION
default ""
help
Set parameters of shared I2C interface

View File

@@ -0,0 +1,139 @@
#
# Guition JC4827W543C ESP32-S3 configuration
# Based on I2S-S3-sdkconfig with Guition-specific settings
#
# ESP32-S3 Target Configuration
CONFIG_IDF_TARGET="esp32s3"
CONFIG_IDF_TARGET_ESP32S3=y
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009
# ESP32-S3 specific settings
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_TYPE_AUTO=y
CONFIG_SPIRAM_SIZE_AUTO=y
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_USE_CAPS_ALLOC=y
CONFIG_SPIRAM_USE_HEAP=y
CONFIG_SPIRAM_CACHE_WR=y
CONFIG_SPIRAM_CACHE_WR=y
# PSRAM Configuration
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_IGNORE_NOTFOUND=n
CONFIG_SPIRAM_USE_MEMMAP=y
CONFIG_SPIRAM_USE_NOINIT=n
CONFIG_SPIRAM_USE_EMBEDDED_MEM=n
CONFIG_SPIRAM_USE_CAPS_ALLOC=y
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_USE_HEAP=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=n
# Performance Settings
CONFIG_ESP32S3_RTOS_INT_NUM=0
CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0
# Flash Configuration
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
# Partition Table
CONFIG_PARTITION_TABLE_SINGLE_APP=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_single_app.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions_single_app.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
# UART Configuration
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
CONFIG_ESP_CONSOLE_UART_NUM=0
CONFIG_ESP_CONSOLE_UART_TX_GPIO=43
CONFIG_ESP_CONSOLE_UART_RX_GPIO=44
# GPIO Configuration
CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y
# FreeRTOS Configuration
CONFIG_FREERTOS_HZ=1000
# Log Configuration
CONFIG_LOG_DEFAULT_LEVEL_INFO=y
CONFIG_LOG_MAXIMUM_LEVEL=3
# Component Configuration
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32
CONFIG_LWIP_UDP_RECVMBOX_SIZE=6
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072
# WiFi Configuration
CONFIG_ESP32_WIFI_ENABLED=y
CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y
CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
# Bluetooth Configuration (ESP32-S3 doesn't have Bluetooth Audio)
CONFIG_BT_ENABLED=y
CONFIG_BT_BLUEDROID_ENABLED=y
CONFIG_BT_CLASSIC_ENABLED=y
CONFIG_BT_SCO_ENABLED=y
CONFIG_BT_A2DP_ENABLE=y
CONFIG_BT_BLE_ENABLED=y
# ADC Configuration
CONFIG_ADC_CAL_EFUSE_TP_ENABLE=n
CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=n
CONFIG_ADC_CAL_LUT_ENABLE=n
# I2C Configuration
CONFIG_I2C_ENABLE_DEBUG_LOG=n
# SPI Configuration
CONFIG_SPI_MASTER_IN_IRAM=y
CONFIG_SPI_SLAVE_IN_IRAM=y
# Touch Configuration
CONFIG_TOUCH_PAD_SLEEP_CYCLE=2000
# FAT Filesystem
CONFIG_FATFS_LAZY_LOCK=y
CONFIG_FATFS_API_IN_IRAM=y
# Event Loop Library
CONFIG_EVENT_LOOP_PROFILING=n
# Ethernet
CONFIG_ETH_USE_ESP32_EMAC=n
# HTTP Server
CONFIG_HTTPD_WS_SUPPORT=y
# JSON Parser
CONFIG_JSON_ENABLE_DEBUG=n
# MDNS
CONFIG_MDNS_ENABLE_DEBUG=n
# MQTT
CONFIG_MQTT_PROTOCOL_311=y
CONFIG_MQTT_TRANSPORT_SSL=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET=y
# OpenSSL
CONFIG_OPENSSL_DEBUG=n
# Protobuf-c
CONFIG_PROTOBUF_C_ENABLE_DEBUG=n
# WebSockets
CONFIG_WS_BUFFER_SIZE=1024
# NVS
CONFIG_NVS_ENCRYPTION=n
CONFIG_NVS_ASSERT_ERROR_CHECK=n