adding flasher
This commit is contained in:
13
.claude/settings.local.json
Normal file
13
.claude/settings.local.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(idf.py build:*)",
|
||||
"Bash(grep:*)",
|
||||
"Bash(git add:*)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(pip install:*)",
|
||||
"Bash(build_from_spec.bat)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
}
|
||||
141
docker.md
Normal file
141
docker.md
Normal file
@@ -0,0 +1,141 @@
|
||||
Perfect! Below is the updated `README.md` section with **complete instructions** for setting up the Dockerized ESP-IDF environment on **Windows**, **including installation of the official Espressif VS Code extension**.
|
||||
|
||||
You can paste this into your repo’s `README.md`. It’s ready to go and designed to guide teammates or collaborators through cloning, launching, and building the project with confidence.
|
||||
|
||||
---
|
||||
|
||||
## 🐳 ESP-IDF Dockerized Development Environment (Windows)
|
||||
|
||||
This project includes a fully containerized [ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/index.html) development environment using **Docker** and **Visual Studio Code**.
|
||||
|
||||
Follow these instructions to set up, build, and flash the firmware inside a VS Code **Dev Container** on **Windows**.
|
||||
|
||||
---
|
||||
|
||||
### ✅ Prerequisites
|
||||
|
||||
Ensure the following are installed on your system:
|
||||
|
||||
1. [**Docker Desktop for Windows**](https://www.docker.com/products/docker-desktop)
|
||||
|
||||
* Enable **WSL 2 backend** during installation.
|
||||
2. [**Visual Studio Code**](https://code.visualstudio.com/)
|
||||
3. [**Dev Containers Extension**](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
|
||||
|
||||
* In VS Code: `Extensions → Search "Dev Containers" → Install`
|
||||
4. [**Espressif IDF Extension** for VS Code](https://marketplace.visualstudio.com/items?itemName=espressif.esp-idf-extension)
|
||||
|
||||
* In VS Code: `Extensions → Search "ESP-IDF" → Install`
|
||||
|
||||
> 💡 **Optional (recommended):** Install [WSL 2 with Ubuntu](https://learn.microsoft.com/en-us/windows/wsl/install) for improved Linux compatibility inside Docker.
|
||||
|
||||
---
|
||||
|
||||
### 🚀 Getting Started
|
||||
|
||||
#### 1. Clone this repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-username/your-esp-idf-project.git
|
||||
cd your-esp-idf-project
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. Open in Visual Studio Code
|
||||
|
||||
From the project root:
|
||||
|
||||
```bash
|
||||
code .
|
||||
```
|
||||
|
||||
> Ensure you're opening the folder that contains `.devcontainer/`.
|
||||
|
||||
---
|
||||
|
||||
#### 3. Reopen in Dev Container
|
||||
|
||||
In VS Code:
|
||||
|
||||
* Press `F1` or `Ctrl+Shift+P`
|
||||
* Run: **Dev Containers: Reopen in Container**
|
||||
|
||||
VS Code will:
|
||||
|
||||
* Build the Docker image (based on the provided `Dockerfile`)
|
||||
* Set up the ESP-IDF environment
|
||||
* Install extensions automatically
|
||||
|
||||
---
|
||||
|
||||
#### 4. Verify Environment
|
||||
|
||||
Once setup is complete:
|
||||
|
||||
* A terminal should launch inside the container
|
||||
* Run:
|
||||
|
||||
```bash
|
||||
idf.py --version
|
||||
```
|
||||
|
||||
to confirm ESP-IDF is active and available.
|
||||
|
||||
---
|
||||
|
||||
#### 5. Build the Firmware
|
||||
|
||||
Inside the container’s terminal:
|
||||
|
||||
```bash
|
||||
idf.py build
|
||||
```
|
||||
|
||||
You should see standard ESP-IDF build output and a `.bin` firmware file in the `build/` directory.
|
||||
|
||||
---
|
||||
|
||||
### 🔌 Flashing the ESP32 (Optional)
|
||||
|
||||
If you want to flash from inside the container:
|
||||
|
||||
1. Connect your ESP32 via USB.
|
||||
2. Identify the COM port on Windows (e.g., `COM3`).
|
||||
3. Pass the USB device into the container (this may require configuration).
|
||||
4. Then run:
|
||||
|
||||
```bash
|
||||
idf.py -p COM3 flash monitor
|
||||
```
|
||||
|
||||
> ⚠️ **Note:** Docker Desktop for Windows doesn’t always expose serial ports to containers directly. You can build firmware inside the container and flash it from your host as a fallback.
|
||||
|
||||
---
|
||||
|
||||
### 🧰 Notes
|
||||
|
||||
* The ESP-IDF version is pinned in the Dockerfile (e.g., `espressif/idf:v5.2.1`)
|
||||
* The container automatically runs `source $IDF_PATH/export.sh` to prepare the environment.
|
||||
* VS Code extensions (`.devcontainer.json`) include:
|
||||
|
||||
* `ms-vscode.cpptools`
|
||||
* `ms-vscode.cmake-tools`
|
||||
* `espressif.esp-idf-extension`
|
||||
|
||||
---
|
||||
|
||||
### 🛠 Troubleshooting
|
||||
|
||||
* If `idf.py` is not found, make sure the container terminal sources `export.sh`
|
||||
* If USB flashing fails, flash from host or use WSL serial forwarding tools like `socat` or `usbip`
|
||||
|
||||
---
|
||||
|
||||
Would you like this `README.md` version to be packaged with:
|
||||
|
||||
* A **starter repo structure**
|
||||
* A prebuilt `.devcontainer/` directory
|
||||
* A sample `Dockerfile`, `main.c`, and `CMakeLists.txt`?
|
||||
|
||||
If yes, I can bundle that up for you — just say the word.
|
||||
4
flash_gui.bat
Normal file
4
flash_gui.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
echo Starting ESP32 Firmware Flash GUI...
|
||||
python flash_tool/gui_flasher.py
|
||||
pause
|
||||
43
flash_tool/ESP32_Flasher.spec
Normal file
43
flash_tool/ESP32_Flasher.spec
Normal file
@@ -0,0 +1,43 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
a = Analysis(
|
||||
['gui_flasher.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[('requirements.txt', '.')],
|
||||
hiddenimports=['serial.tools.list_ports'],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='ESP32_Flasher',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True, # Set to False for windowed mode
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
7
flash_tool/build_exe.bat
Normal file
7
flash_tool/build_exe.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
echo Building ESP32 Flasher Executable...
|
||||
cd /d "%~dp0"
|
||||
python build_executable.py
|
||||
echo.
|
||||
echo Build complete! Check the 'dist' folder for ESP32_Flasher.exe
|
||||
pause
|
||||
49
flash_tool/build_executable.py
Normal file
49
flash_tool/build_executable.py
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Build script to create standalone executable for ESP32 Flash GUI
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
def install_requirements():
|
||||
"""Install required packages"""
|
||||
print("Installing requirements...")
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"])
|
||||
|
||||
def build_executable():
|
||||
"""Build standalone executable using PyInstaller"""
|
||||
print("Building standalone executable...")
|
||||
|
||||
# PyInstaller command
|
||||
cmd = [
|
||||
sys.executable, "-m", "PyInstaller",
|
||||
"--onefile", # Single executable file
|
||||
"--windowed", # No console window (remove if you want console)
|
||||
"--name", "ESP32_Flasher",
|
||||
"--icon", "icon.ico" if Path("icon.ico").exists() else None,
|
||||
"--add-data", "requirements.txt;.", # Include requirements file
|
||||
"gui_flasher.py"
|
||||
]
|
||||
|
||||
# Remove None values
|
||||
cmd = [arg for arg in cmd if arg is not None]
|
||||
|
||||
subprocess.check_call(cmd)
|
||||
print("\nExecutable built successfully!")
|
||||
print("Find it in the 'dist' folder as 'ESP32_Flasher.exe'")
|
||||
|
||||
def main():
|
||||
os.chdir(Path(__file__).parent)
|
||||
|
||||
try:
|
||||
install_requirements()
|
||||
build_executable()
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
11
flash_tool/build_from_spec.bat
Normal file
11
flash_tool/build_from_spec.bat
Normal file
@@ -0,0 +1,11 @@
|
||||
@echo off
|
||||
echo Installing dependencies...
|
||||
pip install pyinstaller esptool pyserial
|
||||
|
||||
echo.
|
||||
echo Building executable from spec file...
|
||||
pyinstaller ESP32_Flasher.spec
|
||||
|
||||
echo.
|
||||
echo Build complete! Find ESP32_Flasher.exe in the dist folder.
|
||||
pause
|
||||
14
flash_tool/build_with_auto_py_to_exe.bat
Normal file
14
flash_tool/build_with_auto_py_to_exe.bat
Normal file
@@ -0,0 +1,14 @@
|
||||
@echo off
|
||||
echo Installing auto-py-to-exe...
|
||||
pip install auto-py-to-exe esptool pyserial
|
||||
|
||||
echo.
|
||||
echo Starting auto-py-to-exe GUI...
|
||||
echo.
|
||||
echo Configure the following settings:
|
||||
echo - Script Location: gui_flasher.py
|
||||
echo - Onefile: One File
|
||||
echo - Console Window: Console Based (or Window Based if you prefer no console)
|
||||
echo - Additional Files: Add requirements.txt
|
||||
echo.
|
||||
auto-py-to-exe
|
||||
271
flash_tool/gui_flasher.py
Normal file
271
flash_tool/gui_flasher.py
Normal file
@@ -0,0 +1,271 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
ESP32 Firmware Flash GUI Tool
|
||||
Simple GUI interface for flashing firmware packages to ESP32 devices
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import ttk, filedialog, messagebox, scrolledtext
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
import zipfile
|
||||
import tempfile
|
||||
import os
|
||||
from pathlib import Path
|
||||
import serial.tools.list_ports
|
||||
|
||||
class ESP32FlasherGUI:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("ESP32 Firmware Flasher")
|
||||
self.root.geometry("600x500")
|
||||
|
||||
# Variables
|
||||
self.port_var = tk.StringVar()
|
||||
self.firmware_path_var = tk.StringVar()
|
||||
self.temp_dir = None
|
||||
|
||||
self.setup_ui()
|
||||
self.refresh_ports()
|
||||
|
||||
def setup_ui(self):
|
||||
# Main frame
|
||||
main_frame = ttk.Frame(self.root, padding="10")
|
||||
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# Configure grid weights
|
||||
self.root.columnconfigure(0, weight=1)
|
||||
self.root.rowconfigure(0, weight=1)
|
||||
main_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# Port selection
|
||||
ttk.Label(main_frame, text="Serial Port:").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||
port_frame = ttk.Frame(main_frame)
|
||||
port_frame.grid(row=0, column=1, sticky=(tk.W, tk.E), pady=5)
|
||||
port_frame.columnconfigure(0, weight=1)
|
||||
|
||||
self.port_combo = ttk.Combobox(port_frame, textvariable=self.port_var, state="readonly")
|
||||
self.port_combo.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=(0, 5))
|
||||
|
||||
ttk.Button(port_frame, text="Refresh", command=self.refresh_ports).grid(row=0, column=1)
|
||||
|
||||
# Firmware package selection
|
||||
ttk.Label(main_frame, text="Firmware Package:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||
firmware_frame = ttk.Frame(main_frame)
|
||||
firmware_frame.grid(row=1, column=1, sticky=(tk.W, tk.E), pady=5)
|
||||
firmware_frame.columnconfigure(0, weight=1)
|
||||
|
||||
self.firmware_entry = ttk.Entry(firmware_frame, textvariable=self.firmware_path_var, state="readonly")
|
||||
self.firmware_entry.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=(0, 5))
|
||||
|
||||
ttk.Button(firmware_frame, text="Browse", command=self.browse_firmware).grid(row=0, column=1)
|
||||
|
||||
# Flash settings frame
|
||||
settings_frame = ttk.LabelFrame(main_frame, text="Flash Settings", padding="5")
|
||||
settings_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=10)
|
||||
settings_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# Flash settings
|
||||
ttk.Label(settings_frame, text="Chip:").grid(row=0, column=0, sticky=tk.W, pady=2)
|
||||
self.chip_var = tk.StringVar(value="esp32")
|
||||
ttk.Entry(settings_frame, textvariable=self.chip_var, width=15).grid(row=0, column=1, sticky=tk.W, pady=2)
|
||||
|
||||
ttk.Label(settings_frame, text="Baud Rate:").grid(row=1, column=0, sticky=tk.W, pady=2)
|
||||
self.baud_var = tk.StringVar(value="460800")
|
||||
ttk.Entry(settings_frame, textvariable=self.baud_var, width=15).grid(row=1, column=1, sticky=tk.W, pady=2)
|
||||
|
||||
ttk.Label(settings_frame, text="Flash Mode:").grid(row=2, column=0, sticky=tk.W, pady=2)
|
||||
self.flash_mode_var = tk.StringVar(value="dio")
|
||||
ttk.Entry(settings_frame, textvariable=self.flash_mode_var, width=15).grid(row=2, column=1, sticky=tk.W, pady=2)
|
||||
|
||||
ttk.Label(settings_frame, text="Flash Freq:").grid(row=3, column=0, sticky=tk.W, pady=2)
|
||||
self.flash_freq_var = tk.StringVar(value="40m")
|
||||
ttk.Entry(settings_frame, textvariable=self.flash_freq_var, width=15).grid(row=3, column=1, sticky=tk.W, pady=2)
|
||||
|
||||
ttk.Label(settings_frame, text="Flash Size:").grid(row=4, column=0, sticky=tk.W, pady=2)
|
||||
self.flash_size_var = tk.StringVar(value="2MB")
|
||||
ttk.Entry(settings_frame, textvariable=self.flash_size_var, width=15).grid(row=4, column=1, sticky=tk.W, pady=2)
|
||||
|
||||
# Flash button
|
||||
self.flash_button = ttk.Button(main_frame, text="Flash Firmware", command=self.flash_firmware)
|
||||
self.flash_button.grid(row=3, column=0, columnspan=2, pady=10)
|
||||
|
||||
# Progress bar
|
||||
self.progress = ttk.Progressbar(main_frame, mode='indeterminate')
|
||||
self.progress.grid(row=4, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)
|
||||
|
||||
# Log output
|
||||
ttk.Label(main_frame, text="Output:").grid(row=5, column=0, sticky=tk.W, pady=(10, 0))
|
||||
self.log_text = scrolledtext.ScrolledText(main_frame, height=15, width=70)
|
||||
self.log_text.grid(row=6, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=5)
|
||||
main_frame.rowconfigure(6, weight=1)
|
||||
|
||||
def refresh_ports(self):
|
||||
"""Refresh the list of available serial ports"""
|
||||
ports = [port.device for port in serial.tools.list_ports.comports()]
|
||||
self.port_combo['values'] = ports
|
||||
if ports and not self.port_var.get():
|
||||
self.port_var.set(ports[0])
|
||||
|
||||
def browse_firmware(self):
|
||||
"""Browse for firmware package (.zip file)"""
|
||||
filename = filedialog.askopenfilename(
|
||||
title="Select Firmware Package",
|
||||
filetypes=[("ZIP files", "*.zip"), ("All files", "*.*")]
|
||||
)
|
||||
if filename:
|
||||
self.firmware_path_var.set(filename)
|
||||
self.validate_firmware_package(filename)
|
||||
|
||||
def validate_firmware_package(self, zip_path):
|
||||
"""Validate that the ZIP contains required firmware files"""
|
||||
required_files = [
|
||||
"bootloader.bin",
|
||||
"soundshot.bin",
|
||||
"ota_data_initial.bin",
|
||||
"partition-table.bin"
|
||||
]
|
||||
|
||||
try:
|
||||
with zipfile.ZipFile(zip_path, 'r') as zip_file:
|
||||
zip_contents = zip_file.namelist()
|
||||
missing_files = []
|
||||
|
||||
for required_file in required_files:
|
||||
if required_file not in zip_contents:
|
||||
missing_files.append(required_file)
|
||||
|
||||
if missing_files:
|
||||
messagebox.showwarning(
|
||||
"Invalid Package",
|
||||
f"Missing required files:\n{', '.join(missing_files)}"
|
||||
)
|
||||
return False
|
||||
else:
|
||||
self.log_message(f"✓ Valid firmware package: {Path(zip_path).name}")
|
||||
return True
|
||||
|
||||
except zipfile.BadZipFile:
|
||||
messagebox.showerror("Error", "Invalid ZIP file")
|
||||
return False
|
||||
|
||||
def log_message(self, message):
|
||||
"""Add message to log output"""
|
||||
self.log_text.insert(tk.END, message + "\n")
|
||||
self.log_text.see(tk.END)
|
||||
self.root.update()
|
||||
|
||||
def extract_firmware_package(self, zip_path):
|
||||
"""Extract firmware package to temporary directory"""
|
||||
if self.temp_dir:
|
||||
# Clean up previous temp dir
|
||||
import shutil
|
||||
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
||||
|
||||
self.temp_dir = tempfile.mkdtemp(prefix="esp32_flash_")
|
||||
|
||||
with zipfile.ZipFile(zip_path, 'r') as zip_file:
|
||||
zip_file.extractall(self.temp_dir)
|
||||
|
||||
return self.temp_dir
|
||||
|
||||
def flash_firmware(self):
|
||||
"""Flash the firmware to ESP32"""
|
||||
# Validate inputs
|
||||
if not self.port_var.get():
|
||||
messagebox.showerror("Error", "Please select a serial port")
|
||||
return
|
||||
|
||||
if not self.firmware_path_var.get():
|
||||
messagebox.showerror("Error", "Please select a firmware package")
|
||||
return
|
||||
|
||||
# Disable flash button and start progress
|
||||
self.flash_button.config(state="disabled")
|
||||
self.progress.start()
|
||||
self.log_text.delete(1.0, tk.END)
|
||||
|
||||
# Run flash in separate thread to prevent UI freezing
|
||||
thread = threading.Thread(target=self._flash_worker)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
def _flash_worker(self):
|
||||
"""Worker thread for flashing firmware"""
|
||||
try:
|
||||
# Extract firmware package
|
||||
self.log_message("Extracting firmware package...")
|
||||
temp_dir = self.extract_firmware_package(self.firmware_path_var.get())
|
||||
|
||||
# Define file paths
|
||||
bootloader = os.path.join(temp_dir, "bootloader.bin")
|
||||
firmware = os.path.join(temp_dir, "soundshot.bin")
|
||||
ota_initial = os.path.join(temp_dir, "ota_data_initial.bin")
|
||||
partition = os.path.join(temp_dir, "partition-table.bin")
|
||||
|
||||
# Build esptool command
|
||||
cmd = [
|
||||
sys.executable, "-m", "esptool",
|
||||
"--chip", self.chip_var.get(),
|
||||
"--port", self.port_var.get(),
|
||||
"--baud", self.baud_var.get(),
|
||||
"--before", "default_reset",
|
||||
"--after", "hard_reset",
|
||||
"write-flash",
|
||||
"--flash-mode", self.flash_mode_var.get(),
|
||||
"--flash-freq", self.flash_freq_var.get(),
|
||||
"--flash-size", self.flash_size_var.get(),
|
||||
"0x1000", bootloader,
|
||||
"0x20000", firmware,
|
||||
"0x11000", ota_initial,
|
||||
"0x8000", partition
|
||||
]
|
||||
|
||||
self.log_message(f"Running: {' '.join(cmd)}\n")
|
||||
|
||||
# Run esptool
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True,
|
||||
bufsize=1,
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
# Stream output
|
||||
for line in process.stdout:
|
||||
self.root.after(0, self.log_message, line.rstrip())
|
||||
|
||||
process.wait()
|
||||
|
||||
if process.returncode == 0:
|
||||
self.root.after(0, self.log_message, "\n✓ Flash completed successfully!")
|
||||
self.root.after(0, messagebox.showinfo, "Success", "Firmware flashed successfully!")
|
||||
else:
|
||||
self.root.after(0, self.log_message, f"\n✗ Flash failed with return code {process.returncode}")
|
||||
self.root.after(0, messagebox.showerror, "Error", "Flash operation failed!")
|
||||
|
||||
except Exception as e:
|
||||
self.root.after(0, self.log_message, f"\n✗ Error: {str(e)}")
|
||||
self.root.after(0, messagebox.showerror, "Error", f"Flash operation failed: {str(e)}")
|
||||
|
||||
finally:
|
||||
# Re-enable UI
|
||||
self.root.after(0, self.progress.stop)
|
||||
self.root.after(0, lambda: self.flash_button.config(state="normal"))
|
||||
|
||||
# Clean up temp directory
|
||||
if self.temp_dir:
|
||||
import shutil
|
||||
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
||||
self.temp_dir = None
|
||||
|
||||
def main():
|
||||
root = tk.Tk()
|
||||
app = ESP32FlasherGUI(root)
|
||||
root.mainloop()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
3
flash_tool/requirements.txt
Normal file
3
flash_tool/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
esptool>=4.0
|
||||
pyserial>=3.5
|
||||
pyinstaller>=5.0
|
||||
225
main/bt_app.c
225
main/bt_app.c
@@ -109,24 +109,11 @@ static void bt_app_av_sm_hdlr(uint16_t event, void *param);
|
||||
/* utils for transfer BLuetooth Deveice Address into string form */
|
||||
static char *bda2str(esp_bd_addr_t bda, char *str, size_t size);
|
||||
|
||||
/* NVS storage functions for paired devices */
|
||||
typedef struct {
|
||||
esp_bd_addr_t bda;
|
||||
char name[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
|
||||
uint32_t last_connected;
|
||||
} paired_device_t;
|
||||
|
||||
static esp_err_t nvs_save_paired_device(const paired_device_t *device);
|
||||
static esp_err_t nvs_load_paired_devices(paired_device_t *devices, size_t *count);
|
||||
static esp_err_t nvs_remove_paired_device(esp_bd_addr_t bda);
|
||||
static bool nvs_is_device_known(esp_bd_addr_t bda);
|
||||
static esp_err_t nvs_get_known_device_count(size_t *count);
|
||||
static esp_err_t nvs_try_connect_known_devices(void);
|
||||
static void nvs_debug_print_known_devices(void);
|
||||
static esp_err_t nvs_add_discovered_device(esp_bd_addr_t bda, const char *name);
|
||||
static esp_err_t nvs_update_connection_timestamp(esp_bd_addr_t bda);
|
||||
static esp_err_t nvs_try_connect_all_known_devices(void);
|
||||
static esp_err_t nvs_try_next_known_device(void);
|
||||
static esp_err_t bt_try_connect_known_devices(void);
|
||||
static void bt_debug_print_known_devices(void);
|
||||
static esp_err_t bt_add_discovered_device(esp_bd_addr_t bda, const char *name);
|
||||
static esp_err_t bt_try_connect_all_known_devices(void);
|
||||
static esp_err_t bt_try_next_known_device(void);
|
||||
|
||||
/* A2DP application state machine handler for each state */
|
||||
static void bt_app_av_state_unconnected_hdlr(uint16_t event, void *param);
|
||||
@@ -167,145 +154,18 @@ static bool s_volume_control_available = false; /* Whether AVRC vo
|
||||
* NVS STORAGE FUNCTION DEFINITIONS
|
||||
********************************/
|
||||
|
||||
static esp_err_t nvs_save_paired_device(const paired_device_t *device)
|
||||
{
|
||||
nvs_handle_t nvs_handle;
|
||||
esp_err_t ret;
|
||||
size_t count = 0;
|
||||
char key[32];
|
||||
// This function is no longer used - replaced by system_savePairedDevice
|
||||
|
||||
if (!device) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
// This function is no longer used - replaced by system_loadPairedDevices
|
||||
|
||||
ret = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(BT_AV_TAG, "Error opening NVS handle: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
// This function is no longer used - replaced by system_isDeviceKnown
|
||||
|
||||
// Get current device count
|
||||
size_t required_size = sizeof(size_t);
|
||||
nvs_get_blob(nvs_handle, NVS_KEY_COUNT, &count, &required_size);
|
||||
|
||||
// Check if device already exists
|
||||
paired_device_t existing_devices[MAX_PAIRED_DEVICES];
|
||||
size_t existing_count = MAX_PAIRED_DEVICES;
|
||||
nvs_load_paired_devices(existing_devices, &existing_count);
|
||||
|
||||
int device_index = -1;
|
||||
for (int i = 0; i < existing_count; i++) {
|
||||
if (memcmp(existing_devices[i].bda, device->bda, ESP_BD_ADDR_LEN) == 0) {
|
||||
device_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If device not found and we have space, add it
|
||||
if (device_index == -1) {
|
||||
if (count >= MAX_PAIRED_DEVICES) {
|
||||
ESP_LOGW(BT_AV_TAG, "Maximum paired devices reached");
|
||||
nvs_close(nvs_handle);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
device_index = count;
|
||||
count++;
|
||||
}
|
||||
|
||||
// Save device data
|
||||
snprintf(key, sizeof(key), "%s%d", NVS_KEY_PREFIX, device_index);
|
||||
ret = nvs_set_blob(nvs_handle, key, device, sizeof(paired_device_t));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(BT_AV_TAG, "Error saving device: %s", esp_err_to_name(ret));
|
||||
nvs_close(nvs_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Save device count
|
||||
ret = nvs_set_blob(nvs_handle, NVS_KEY_COUNT, &count, sizeof(size_t));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(BT_AV_TAG, "Error saving device count: %s", esp_err_to_name(ret));
|
||||
nvs_close(nvs_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nvs_commit(nvs_handle);
|
||||
nvs_close(nvs_handle);
|
||||
|
||||
char bda_str[18];
|
||||
ESP_LOGI(BT_AV_TAG, "Saved paired device: %s (%s)",
|
||||
device->name, bda2str(device->bda, bda_str, sizeof(bda_str)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t nvs_load_paired_devices(paired_device_t *devices, size_t *count)
|
||||
{
|
||||
nvs_handle_t nvs_handle;
|
||||
esp_err_t ret;
|
||||
size_t device_count = 0;
|
||||
char key[32];
|
||||
|
||||
if (!devices || !count || *count == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ret = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGD(BT_AV_TAG, "NVS namespace not found (first run): %s", esp_err_to_name(ret));
|
||||
*count = 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Get device count
|
||||
size_t required_size = sizeof(size_t);
|
||||
ret = nvs_get_blob(nvs_handle, NVS_KEY_COUNT, &device_count, &required_size);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGD(BT_AV_TAG, "No paired devices found");
|
||||
nvs_close(nvs_handle);
|
||||
*count = 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Load each device
|
||||
size_t loaded = 0;
|
||||
for (int i = 0; i < device_count && loaded < *count; i++) {
|
||||
snprintf(key, sizeof(key), "%s%d", NVS_KEY_PREFIX, i);
|
||||
required_size = sizeof(paired_device_t);
|
||||
ret = nvs_get_blob(nvs_handle, key, &devices[loaded], &required_size);
|
||||
if (ret == ESP_OK) {
|
||||
loaded++;
|
||||
}
|
||||
}
|
||||
|
||||
nvs_close(nvs_handle);
|
||||
*count = loaded;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static bool nvs_is_device_known(esp_bd_addr_t bda)
|
||||
static esp_err_t bt_try_connect_known_devices(void)
|
||||
{
|
||||
paired_device_t devices[MAX_PAIRED_DEVICES];
|
||||
size_t count = MAX_PAIRED_DEVICES;
|
||||
|
||||
if (nvs_load_paired_devices(devices, &count) != ESP_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (memcmp(devices[i].bda, bda, ESP_BD_ADDR_LEN) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static esp_err_t nvs_try_connect_known_devices(void)
|
||||
{
|
||||
paired_device_t devices[MAX_PAIRED_DEVICES];
|
||||
size_t count = MAX_PAIRED_DEVICES;
|
||||
|
||||
esp_err_t ret = nvs_load_paired_devices(devices, &count);
|
||||
esp_err_t ret = system_loadPairedDevices(devices, &count);
|
||||
if (ret != ESP_OK || count == 0) {
|
||||
ESP_LOGI(BT_AV_TAG, "No known devices to connect to");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
@@ -355,14 +215,14 @@ static esp_err_t nvs_try_connect_known_devices(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nvs_debug_print_known_devices(void)
|
||||
static void bt_debug_print_known_devices(void)
|
||||
{
|
||||
paired_device_t devices[MAX_PAIRED_DEVICES];
|
||||
size_t count = MAX_PAIRED_DEVICES;
|
||||
const paired_device_t* devices;
|
||||
size_t count = 0;
|
||||
|
||||
esp_err_t ret = nvs_load_paired_devices(devices, &count);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(BT_AV_TAG, "Failed to load devices for debug: %s", esp_err_to_name(ret));
|
||||
devices = system_getPairedDevices(&count);
|
||||
if (!devices) {
|
||||
ESP_LOGE(BT_AV_TAG, "Failed to load devices for debug");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -377,12 +237,12 @@ static void nvs_debug_print_known_devices(void)
|
||||
ESP_LOGI(BT_AV_TAG, "=== End Device List ===");
|
||||
}
|
||||
|
||||
static esp_err_t nvs_remove_paired_device(esp_bd_addr_t bda)
|
||||
static esp_err_t __attribute__((unused)) nvs_remove_paired_device(esp_bd_addr_t bda)
|
||||
{
|
||||
paired_device_t devices[MAX_PAIRED_DEVICES];
|
||||
size_t count = MAX_PAIRED_DEVICES;
|
||||
|
||||
esp_err_t ret = nvs_load_paired_devices(devices, &count);
|
||||
esp_err_t ret = system_loadPairedDevices(devices, &count);
|
||||
if (ret != ESP_OK || count == 0) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
@@ -438,7 +298,7 @@ static esp_err_t nvs_remove_paired_device(esp_bd_addr_t bda)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t nvs_get_known_device_count(size_t *count)
|
||||
static esp_err_t __attribute__((unused)) nvs_get_known_device_count(size_t *count)
|
||||
{
|
||||
if (!count) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -462,14 +322,14 @@ static esp_err_t nvs_get_known_device_count(size_t *count)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t nvs_add_discovered_device(esp_bd_addr_t bda, const char *name)
|
||||
static esp_err_t bt_add_discovered_device(esp_bd_addr_t bda, const char *name)
|
||||
{
|
||||
if (!bda || !name) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Check if device is already known
|
||||
if (nvs_is_device_known(bda)) {
|
||||
if (system_isDeviceKnown(bda)) {
|
||||
char bda_str[18];
|
||||
ESP_LOGD(BT_AV_TAG, "Device %s (%s) already known, skipping",
|
||||
name, bda2str(bda, bda_str, sizeof(bda_str)));
|
||||
@@ -479,12 +339,12 @@ static esp_err_t nvs_add_discovered_device(esp_bd_addr_t bda, const char *name)
|
||||
// Create paired_device_t structure for discovered device
|
||||
paired_device_t device;
|
||||
memcpy(device.bda, bda, ESP_BD_ADDR_LEN);
|
||||
strncpy(device.name, name, ESP_BT_GAP_MAX_BDNAME_LEN);
|
||||
device.name[ESP_BT_GAP_MAX_BDNAME_LEN] = '\0';
|
||||
strncpy(device.name, name, DEVICE_NAME_MAX_LEN - 1);
|
||||
device.name[DEVICE_NAME_MAX_LEN - 1] = '\0';
|
||||
device.last_connected = 0; // Never connected, set to 0
|
||||
|
||||
// Save to NVS
|
||||
esp_err_t ret = nvs_save_paired_device(&device);
|
||||
esp_err_t ret = system_savePairedDevice(&device);
|
||||
if (ret == ESP_OK) {
|
||||
char bda_str[18];
|
||||
ESP_LOGI(BT_AV_TAG, "Added discovered device to NVS: %s (%s)",
|
||||
@@ -496,7 +356,7 @@ static esp_err_t nvs_add_discovered_device(esp_bd_addr_t bda, const char *name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t nvs_update_connection_timestamp(esp_bd_addr_t bda)
|
||||
static esp_err_t __attribute__((unused)) nvs_update_connection_timestamp(esp_bd_addr_t bda)
|
||||
{
|
||||
if (!bda) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -505,7 +365,7 @@ static esp_err_t nvs_update_connection_timestamp(esp_bd_addr_t bda)
|
||||
paired_device_t devices[MAX_PAIRED_DEVICES];
|
||||
size_t count = MAX_PAIRED_DEVICES;
|
||||
|
||||
esp_err_t ret = nvs_load_paired_devices(devices, &count);
|
||||
esp_err_t ret = system_loadPairedDevices(devices, &count);
|
||||
if (ret != ESP_OK || count == 0) {
|
||||
ESP_LOGW(BT_AV_TAG, "No devices found to update timestamp");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
@@ -529,7 +389,7 @@ static esp_err_t nvs_update_connection_timestamp(esp_bd_addr_t bda)
|
||||
devices[device_index].last_connected = (uint32_t)(esp_timer_get_time() / 1000000); // Convert to seconds
|
||||
|
||||
// Save updated device
|
||||
ret = nvs_save_paired_device(&devices[device_index]);
|
||||
ret = system_savePairedDevice(&devices[device_index]);
|
||||
if (ret == ESP_OK) {
|
||||
char bda_str[18];
|
||||
ESP_LOGI(BT_AV_TAG, "Updated connection timestamp for device: %s (%s)",
|
||||
@@ -541,11 +401,11 @@ static esp_err_t nvs_update_connection_timestamp(esp_bd_addr_t bda)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t nvs_try_connect_all_known_devices(void)
|
||||
static esp_err_t bt_try_connect_all_known_devices(void)
|
||||
{
|
||||
// Load all known devices into cache
|
||||
s_known_device_count = MAX_PAIRED_DEVICES;
|
||||
esp_err_t ret = nvs_load_paired_devices(s_known_devices, &s_known_device_count);
|
||||
esp_err_t ret = system_loadPairedDevices(s_known_devices, &s_known_device_count);
|
||||
if (ret != ESP_OK || s_known_device_count == 0) {
|
||||
ESP_LOGI(BT_AV_TAG, "No known devices to connect to");
|
||||
s_current_device_index = -1;
|
||||
@@ -587,7 +447,7 @@ static esp_err_t nvs_try_connect_all_known_devices(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t nvs_try_next_known_device(void)
|
||||
static esp_err_t bt_try_next_known_device(void)
|
||||
{
|
||||
if (s_current_device_index < 0 || s_known_device_count == 0) {
|
||||
ESP_LOGI(BT_AV_TAG, "No more devices to try");
|
||||
@@ -714,7 +574,7 @@ static void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param)
|
||||
get_name_from_eir(eir, s_peer_bdname, NULL);
|
||||
|
||||
// Save discovered audio device to NVS (but don't connect to it)
|
||||
nvs_add_discovered_device(param->disc_res.bda, (char *)s_peer_bdname);
|
||||
bt_add_discovered_device(param->disc_res.bda, (char *)s_peer_bdname);
|
||||
|
||||
// Add to device list for GUI
|
||||
add_device_to_list(param->disc_res.bda, (char *)s_peer_bdname, false, rssi);
|
||||
@@ -754,7 +614,8 @@ static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
||||
} else {
|
||||
/* not discovered, continue to discover */
|
||||
ESP_LOGI(BT_AV_TAG, "Device discovery failed, continue to discover...");
|
||||
esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
|
||||
s_a2d_state = APP_AV_STATE_UNCONNECTED;
|
||||
//esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
|
||||
}
|
||||
} else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) {
|
||||
ESP_LOGI(BT_AV_TAG, "Discovery started.");
|
||||
@@ -854,10 +715,10 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
|
||||
esp_bt_gap_get_device_name();
|
||||
|
||||
// Print list of saved devices from NVS
|
||||
nvs_debug_print_known_devices();
|
||||
bt_debug_print_known_devices();
|
||||
|
||||
// Try to connect to all known devices sequentially
|
||||
esp_err_t connect_ret = nvs_try_connect_all_known_devices();
|
||||
esp_err_t connect_ret = bt_try_connect_all_known_devices();
|
||||
if (connect_ret != ESP_OK) {
|
||||
// No known devices found, start discovery to find new devices
|
||||
ESP_LOGI(BT_AV_TAG, "No known devices found, starting discovery...");
|
||||
@@ -1222,7 +1083,8 @@ static void bt_app_av_state_unconnected_hdlr(uint16_t event, void *param)
|
||||
break;
|
||||
case BT_APP_HEART_BEAT_EVT: {
|
||||
// Try to connect to known devices, or start discovery if none available
|
||||
esp_err_t connect_ret = nvs_try_connect_all_known_devices();
|
||||
esp_err_t connect_ret = bt_try_connect_all_known_devices();
|
||||
|
||||
if (connect_ret != ESP_OK) {
|
||||
// No known devices, start discovery
|
||||
ESP_LOGI(BT_AV_TAG, "No known devices available, starting discovery...");
|
||||
@@ -1257,14 +1119,17 @@ static void bt_app_av_state_connecting_hdlr(uint16_t event, void *param)
|
||||
s_media_state = APP_AV_MEDIA_STATE_IDLE;
|
||||
|
||||
// Update connection timestamp for this device
|
||||
nvs_update_connection_timestamp(s_peer_bda);
|
||||
system_updateConnectionTimestamp(s_peer_bda);
|
||||
} else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
|
||||
ESP_LOGI(BT_AV_TAG, "Connection failed, trying next device...");
|
||||
// Try next known device before giving up
|
||||
esp_err_t next_ret = nvs_try_next_known_device();
|
||||
esp_err_t next_ret = bt_try_next_known_device();
|
||||
if (next_ret != ESP_OK) {
|
||||
// No more devices to try, go to unconnected state
|
||||
s_a2d_state = APP_AV_STATE_UNCONNECTED;
|
||||
//s_a2d_state = APP_AV_STATE_UNCONNECTED;
|
||||
ESP_LOGI(BT_AV_TAG, "No known devices available, starting discovery...");
|
||||
s_a2d_state = APP_AV_STATE_DISCOVERING;
|
||||
esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1281,7 +1146,7 @@ static void bt_app_av_state_connecting_hdlr(uint16_t event, void *param)
|
||||
if (++s_connecting_intv >= 2) {
|
||||
ESP_LOGI(BT_AV_TAG, "Connection timeout, trying next device...");
|
||||
// Try next known device before giving up
|
||||
esp_err_t next_ret = nvs_try_next_known_device();
|
||||
esp_err_t next_ret = bt_try_next_known_device();
|
||||
if (next_ret != ESP_OK) {
|
||||
// No more devices to try, go to unconnected state
|
||||
s_a2d_state = APP_AV_STATE_UNCONNECTED;
|
||||
@@ -1834,7 +1699,7 @@ static void load_paired_devices_to_list(void) {
|
||||
size_t count = MAX_PAIRED_DEVICES;
|
||||
|
||||
ESP_LOGI(BT_AV_TAG, "Attempting to load paired devices from NVS");
|
||||
esp_err_t err = nvs_load_paired_devices(paired_devices, &count);
|
||||
esp_err_t err = system_loadPairedDevices(paired_devices, &count);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(BT_AV_TAG, "Successfully loaded %d paired devices from NVS", (int)count);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
|
||||
101
main/gui.c
101
main/gui.c
@@ -72,6 +72,13 @@ static lv_obj_t* create_volume_page(void);
|
||||
static void update_volume_display(int volume);
|
||||
static void ensure_menu_styles(void);
|
||||
|
||||
// Menu stack management functions
|
||||
static void menu_stack_push(lv_obj_t *page);
|
||||
static lv_obj_t* menu_stack_pop(void);
|
||||
static void menu_stack_clear(void);
|
||||
static bool menu_stack_is_empty(void);
|
||||
static void menu_go_back(void);
|
||||
|
||||
#define MAX_ITEMS 10
|
||||
#define VISIBLE_ITEMS 3
|
||||
#define MENU_MAX_STRING_LENGTH 30
|
||||
@@ -91,6 +98,15 @@ static lv_obj_t *_currentPage = NULL;
|
||||
|
||||
static GuiMode_t _mode = GUI_BUBBLE;
|
||||
|
||||
// Menu navigation stack
|
||||
#define MAX_MENU_STACK_SIZE 8
|
||||
typedef struct {
|
||||
lv_obj_t *pages[MAX_MENU_STACK_SIZE];
|
||||
int count;
|
||||
} menu_stack_t;
|
||||
|
||||
static menu_stack_t _menuStack = {0};
|
||||
|
||||
/* 1. Prepare a default (unfocused) style */
|
||||
static lv_style_t _styleUnfocusedBtn;
|
||||
|
||||
@@ -135,6 +151,9 @@ static void show_menu(void) {
|
||||
lv_obj_t* menu = create_menu_container();
|
||||
lv_obj_t* main_page = create_main_page();
|
||||
|
||||
// Clear the menu stack when starting fresh menu navigation
|
||||
menu_stack_clear();
|
||||
|
||||
lv_menu_set_page(menu, main_page);
|
||||
_currentPage = main_page;
|
||||
|
||||
@@ -180,7 +199,8 @@ static void lcd_init(void)
|
||||
.miso_io_num = -1,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = LCD_H_RES * LCD_V_RES * 2
|
||||
//.max_transfer_sz = LCD_H_RES * LCD_V_RES * 2
|
||||
.max_transfer_sz = LCD_H_RES * 25 * (LCD_BITS_PER_PIXEL/8),
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(LCD_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
@@ -236,7 +256,8 @@ static void lvgl_init(void)
|
||||
const lvgl_port_display_cfg_t disp_cfg = {
|
||||
.io_handle = io_handle,
|
||||
.panel_handle = panel_handle,
|
||||
.buffer_size = LCD_H_RES * LCD_V_RES * 2,
|
||||
// .buffer_size = LCD_H_RES * LCD_V_RES * 2,
|
||||
.buffer_size = LCD_H_RES * 25 * (LCD_BITS_PER_PIXEL/8), // was full screen
|
||||
.double_buffer = false,
|
||||
.hres = LCD_H_RES,
|
||||
.vres = LCD_V_RES,
|
||||
@@ -347,12 +368,20 @@ static void btn_click_cb(lv_event_t * e) {
|
||||
// Handle specific menu items
|
||||
if (strcmp(txt, "Bluetooth") == 0) {
|
||||
LOCK();
|
||||
// Push current page onto stack before navigating
|
||||
menu_stack_push(_currentPage);
|
||||
show_bt_device_list();
|
||||
UNLOCK();
|
||||
} else if (strcmp(txt, "Volume") == 0) {
|
||||
LOCK();
|
||||
// Push current page onto stack before navigating
|
||||
menu_stack_push(_currentPage);
|
||||
show_volume_control();
|
||||
UNLOCK();
|
||||
} else if (strcmp(txt, "Back") == 0) {
|
||||
LOCK();
|
||||
menu_go_back();
|
||||
UNLOCK();
|
||||
} else if (strcmp(txt, "Exit") == 0) {
|
||||
LOCK();
|
||||
_mode = GUI_BUBBLE;
|
||||
@@ -609,8 +638,7 @@ static void bt_device_click_cb(lv_event_t * e) {
|
||||
if (strcmp(txt, "Back") == 0) {
|
||||
LOCK();
|
||||
bt_stop_discovery();
|
||||
_mode = GUI_MENU;
|
||||
show_menu();
|
||||
menu_go_back();
|
||||
UNLOCK();
|
||||
return;
|
||||
} else if (strcmp(txt, "Refresh") == 0) {
|
||||
@@ -803,6 +831,10 @@ static lv_obj_t* create_volume_page(void) {
|
||||
lv_obj_align(instr2, LV_ALIGN_BOTTOM_MID, 0, -10);
|
||||
#endif
|
||||
|
||||
// Add Back button
|
||||
lv_obj_t* back_btn = addMenuItem(_volume_page, "Back");
|
||||
lv_obj_add_event_cb(back_btn, btn_click_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
return _volume_page;
|
||||
}
|
||||
|
||||
@@ -831,6 +863,64 @@ static void show_volume_control(void) {
|
||||
ESP_LOGI(TAG, "Volume control displayed");
|
||||
}
|
||||
|
||||
// Menu stack management functions
|
||||
static void menu_stack_push(lv_obj_t *page) {
|
||||
if (_menuStack.count < MAX_MENU_STACK_SIZE && page != NULL) {
|
||||
_menuStack.pages[_menuStack.count++] = page;
|
||||
ESP_LOGI(TAG, "Menu stack push: page=%p, count=%d", page, _menuStack.count);
|
||||
} else if (_menuStack.count >= MAX_MENU_STACK_SIZE) {
|
||||
ESP_LOGW(TAG, "Menu stack overflow, cannot push more pages");
|
||||
}
|
||||
}
|
||||
|
||||
static lv_obj_t* menu_stack_pop(void) {
|
||||
if (_menuStack.count > 0) {
|
||||
lv_obj_t *page = _menuStack.pages[--_menuStack.count];
|
||||
ESP_LOGI(TAG, "Menu stack pop: page=%p, count=%d", page, _menuStack.count);
|
||||
return page;
|
||||
}
|
||||
ESP_LOGI(TAG, "Menu stack is empty, cannot pop");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void menu_stack_clear(void) {
|
||||
_menuStack.count = 0;
|
||||
ESP_LOGI(TAG, "Menu stack cleared");
|
||||
}
|
||||
|
||||
static bool menu_stack_is_empty(void) {
|
||||
return (_menuStack.count == 0);
|
||||
}
|
||||
|
||||
static void menu_go_back(void) {
|
||||
ESP_LOGI(TAG, "Menu go back requested");
|
||||
|
||||
if (menu_stack_is_empty()) {
|
||||
ESP_LOGI(TAG, "Menu stack empty, returning to bubble mode");
|
||||
_mode = GUI_BUBBLE;
|
||||
show_bubble();
|
||||
return;
|
||||
}
|
||||
|
||||
lv_obj_t *previous_page = menu_stack_pop();
|
||||
if (previous_page != NULL) {
|
||||
ESP_LOGI(TAG, "Returning to previous menu page");
|
||||
lv_obj_t* menu = create_menu_container();
|
||||
if (menu) {
|
||||
lv_menu_set_page(menu, previous_page);
|
||||
_currentPage = previous_page;
|
||||
_mode = GUI_MENU;
|
||||
|
||||
lv_obj_remove_flag(menu, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "No previous page found, returning to bubble mode");
|
||||
_mode = GUI_BUBBLE;
|
||||
show_bubble();
|
||||
}
|
||||
}
|
||||
|
||||
static void update_volume_display(int volume) {
|
||||
if (_volume_bar && _volume_label) {
|
||||
LOCK();
|
||||
@@ -1029,8 +1119,7 @@ static void gui_task(void *pvParameters)
|
||||
LOCK();
|
||||
if (_mode == GUI_MENU)
|
||||
{
|
||||
_mode = GUI_BUBBLE;
|
||||
show_bubble(); // Cleanup menu and show bubble
|
||||
menu_go_back(); // Use menu stack navigation
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -325,7 +325,8 @@ void app_main(void)
|
||||
#else
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
system_processNvsRequests();
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
281
main/system.c
281
main/system.c
@@ -1,20 +1,34 @@
|
||||
#include "system.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
#include "esp_timer.h"
|
||||
#include <string.h>
|
||||
|
||||
static SystemState_t _systemState;
|
||||
|
||||
static EventGroupHandle_t _systemEvent;
|
||||
static EventManager_t _eventManager;
|
||||
|
||||
static QueueHandle_t _nvsRequestQueue;
|
||||
static const char* NVS_NAMESPACE = "bt_devices";
|
||||
static const char* NVS_KEY_COUNT = "count";
|
||||
|
||||
static esp_err_t nvs_load_devices_internal(paired_device_t *devices, size_t *count);
|
||||
static esp_err_t nvs_save_devices_internal(const paired_device_t *devices, size_t count);
|
||||
|
||||
void system_init(void)
|
||||
{
|
||||
_systemState.zeroAngle = 0.0f;
|
||||
_systemState.primaryAxis = PRIMARY_AXIS;
|
||||
_systemState.pairedDeviceCount = 0;
|
||||
|
||||
_systemEvent = xEventGroupCreate();
|
||||
|
||||
_eventManager.count = 0;
|
||||
_eventManager.mutex = xSemaphoreCreateMutex();
|
||||
|
||||
system_initNvsService();
|
||||
}
|
||||
|
||||
int system_getPrimaryAxis(void)
|
||||
@@ -199,3 +213,270 @@ void system_requestVolumeDown(void) {
|
||||
ESP_LOGI("system", "Volume Down requested");
|
||||
system_notifyAll(EM_EVENT_VOLUME_DOWN);
|
||||
}
|
||||
|
||||
void system_initNvsService(void) {
|
||||
_nvsRequestQueue = xQueueCreate(10, sizeof(nvs_request_t));
|
||||
if (_nvsRequestQueue == NULL) {
|
||||
ESP_LOGE("system", "Failed to create NVS request queue");
|
||||
}
|
||||
|
||||
memset(_systemState.pairedDevices, 0, sizeof(_systemState.pairedDevices));
|
||||
_systemState.pairedDeviceCount = 0;
|
||||
|
||||
paired_device_t devices[MAX_PAIRED_DEVICES];
|
||||
size_t count = 0;
|
||||
if (nvs_load_devices_internal(devices, &count) == ESP_OK) {
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
memcpy(_systemState.pairedDevices, devices, count * sizeof(paired_device_t));
|
||||
_systemState.pairedDeviceCount = count;
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
ESP_LOGI("system", "Loaded %d paired devices from NVS", count);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t nvs_load_devices_internal(paired_device_t *devices, size_t *count) {
|
||||
nvs_handle_t nvs_handle;
|
||||
esp_err_t ret;
|
||||
|
||||
ret = nvs_open(NVS_NAMESPACE, NVS_READONLY, &nvs_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE("system", "Failed to open NVS namespace: %s", esp_err_to_name(ret));
|
||||
*count = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t device_count = 0;
|
||||
size_t required_size = sizeof(size_t);
|
||||
ret = nvs_get_blob(nvs_handle, NVS_KEY_COUNT, &device_count, &required_size);
|
||||
if (ret != ESP_OK) {
|
||||
nvs_close(nvs_handle);
|
||||
*count = 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
device_count = (device_count > MAX_PAIRED_DEVICES) ? MAX_PAIRED_DEVICES : device_count;
|
||||
|
||||
for (size_t i = 0; i < device_count; i++) {
|
||||
char key[16];
|
||||
snprintf(key, sizeof(key), "device_%zu", i);
|
||||
required_size = sizeof(paired_device_t);
|
||||
ret = nvs_get_blob(nvs_handle, key, &devices[i], &required_size);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW("system", "Failed to load device %zu", i);
|
||||
device_count = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nvs_close(nvs_handle);
|
||||
*count = device_count;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t nvs_save_devices_internal(const paired_device_t *devices, size_t count) {
|
||||
nvs_handle_t nvs_handle;
|
||||
esp_err_t ret;
|
||||
|
||||
ret = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs_handle);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE("system", "Failed to open NVS namespace for write: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nvs_set_blob(nvs_handle, NVS_KEY_COUNT, &count, sizeof(size_t));
|
||||
if (ret != ESP_OK) {
|
||||
nvs_close(nvs_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
char key[16];
|
||||
snprintf(key, sizeof(key), "device_%zu", i);
|
||||
ret = nvs_set_blob(nvs_handle, key, &devices[i], sizeof(paired_device_t));
|
||||
if (ret != ESP_OK) {
|
||||
nvs_close(nvs_handle);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = nvs_commit(nvs_handle);
|
||||
nvs_close(nvs_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void system_processNvsRequests(void) {
|
||||
nvs_request_t request;
|
||||
|
||||
while (xQueueReceive(_nvsRequestQueue, &request, 0) == pdTRUE) {
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
switch (request.operation) {
|
||||
case NVS_OP_SAVE_DEVICE:
|
||||
request.result = nvs_save_devices_internal(_systemState.pairedDevices, _systemState.pairedDeviceCount);
|
||||
break;
|
||||
|
||||
case NVS_OP_LOAD_DEVICES:
|
||||
request.result = nvs_load_devices_internal(_systemState.pairedDevices, &_systemState.pairedDeviceCount);
|
||||
break;
|
||||
|
||||
case NVS_OP_REMOVE_DEVICE: {
|
||||
size_t removed_index = SIZE_MAX;
|
||||
for (size_t i = 0; i < _systemState.pairedDeviceCount; i++) {
|
||||
if (memcmp(_systemState.pairedDevices[i].bda, request.bda, ESP_BD_ADDR_LEN) == 0) {
|
||||
removed_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed_index != SIZE_MAX) {
|
||||
for (size_t i = removed_index; i < _systemState.pairedDeviceCount - 1; i++) {
|
||||
_systemState.pairedDevices[i] = _systemState.pairedDevices[i + 1];
|
||||
}
|
||||
_systemState.pairedDeviceCount--;
|
||||
request.result = nvs_save_devices_internal(_systemState.pairedDevices, _systemState.pairedDeviceCount);
|
||||
} else {
|
||||
request.result = ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NVS_OP_UPDATE_TIMESTAMP: {
|
||||
for (size_t i = 0; i < _systemState.pairedDeviceCount; i++) {
|
||||
if (memcmp(_systemState.pairedDevices[i].bda, request.bda, ESP_BD_ADDR_LEN) == 0) {
|
||||
_systemState.pairedDevices[i].last_connected = (uint32_t)(esp_timer_get_time() / 1000000);
|
||||
request.result = nvs_save_devices_internal(_systemState.pairedDevices, _systemState.pairedDeviceCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
request.result = ESP_ERR_INVALID_ARG;
|
||||
break;
|
||||
}
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
|
||||
request.response_ready = true;
|
||||
if (request.requestor) {
|
||||
xTaskNotify(request.requestor, (uint32_t)&request, eSetValueWithOverwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t system_savePairedDevice(const paired_device_t *device) {
|
||||
if (!device) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
|
||||
size_t existing_index = SIZE_MAX;
|
||||
for (size_t i = 0; i < _systemState.pairedDeviceCount; i++) {
|
||||
if (memcmp(_systemState.pairedDevices[i].bda, device->bda, ESP_BD_ADDR_LEN) == 0) {
|
||||
existing_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (existing_index != SIZE_MAX) {
|
||||
_systemState.pairedDevices[existing_index] = *device;
|
||||
} else if (_systemState.pairedDeviceCount < MAX_PAIRED_DEVICES) {
|
||||
_systemState.pairedDevices[_systemState.pairedDeviceCount++] = *device;
|
||||
} else {
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
|
||||
nvs_request_t request = {
|
||||
.operation = NVS_OP_SAVE_DEVICE,
|
||||
.device = *device,
|
||||
.requestor = xTaskGetCurrentTaskHandle()
|
||||
};
|
||||
|
||||
if (xQueueSend(_nvsRequestQueue, &request, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
uint32_t notification;
|
||||
if (xTaskNotifyWait(0, UINT32_MAX, ¬ification, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
nvs_request_t *response = (nvs_request_t*)notification;
|
||||
return response->result;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
esp_err_t system_loadPairedDevices(paired_device_t *devices, size_t *count) {
|
||||
if (!devices || !count) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
size_t copy_count = (*count < _systemState.pairedDeviceCount) ? *count : _systemState.pairedDeviceCount;
|
||||
memcpy(devices, _systemState.pairedDevices, copy_count * sizeof(paired_device_t));
|
||||
*count = copy_count;
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t system_removePairedDevice(esp_bd_addr_t bda) {
|
||||
nvs_request_t request = {
|
||||
.operation = NVS_OP_REMOVE_DEVICE,
|
||||
.requestor = xTaskGetCurrentTaskHandle()
|
||||
};
|
||||
memcpy(request.bda, bda, ESP_BD_ADDR_LEN);
|
||||
|
||||
if (xQueueSend(_nvsRequestQueue, &request, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
uint32_t notification;
|
||||
if (xTaskNotifyWait(0, UINT32_MAX, ¬ification, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
nvs_request_t *response = (nvs_request_t*)notification;
|
||||
return response->result;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
bool system_isDeviceKnown(esp_bd_addr_t bda) {
|
||||
bool known = false;
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
for (size_t i = 0; i < _systemState.pairedDeviceCount; i++) {
|
||||
if (memcmp(_systemState.pairedDevices[i].bda, bda, ESP_BD_ADDR_LEN) == 0) {
|
||||
known = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
return known;
|
||||
}
|
||||
|
||||
esp_err_t system_getKnownDeviceCount(size_t *count) {
|
||||
if (!count) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
*count = _systemState.pairedDeviceCount;
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t system_updateConnectionTimestamp(esp_bd_addr_t bda) {
|
||||
nvs_request_t request = {
|
||||
.operation = NVS_OP_UPDATE_TIMESTAMP,
|
||||
.requestor = xTaskGetCurrentTaskHandle()
|
||||
};
|
||||
memcpy(request.bda, bda, ESP_BD_ADDR_LEN);
|
||||
|
||||
if (xQueueSend(_nvsRequestQueue, &request, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
uint32_t notification;
|
||||
if (xTaskNotifyWait(0, UINT32_MAX, ¬ification, pdMS_TO_TICKS(NVS_TIMEOUT_MS)) == pdTRUE) {
|
||||
nvs_request_t *response = (nvs_request_t*)notification;
|
||||
return response->result;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
const paired_device_t* system_getPairedDevices(size_t *count) {
|
||||
if (!count) return NULL;
|
||||
|
||||
xSemaphoreTake(_eventManager.mutex, portMAX_DELAY);
|
||||
*count = _systemState.pairedDeviceCount;
|
||||
xSemaphoreGive(_eventManager.mutex);
|
||||
|
||||
return (const paired_device_t*)_systemState.pairedDevices;
|
||||
}
|
||||
@@ -4,9 +4,22 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_bt_defs.h"
|
||||
|
||||
#define DISABLE_GUI
|
||||
|
||||
#define MAX_PAIRED_DEVICES 10
|
||||
#define DEVICE_NAME_MAX_LEN 32
|
||||
|
||||
// Forward declaration of paired_device_t
|
||||
typedef struct {
|
||||
char name[DEVICE_NAME_MAX_LEN];
|
||||
esp_bd_addr_t bda;
|
||||
uint32_t last_connected;
|
||||
bool is_connected;
|
||||
} paired_device_t;
|
||||
|
||||
enum
|
||||
{
|
||||
ANGLE_XY = 0,
|
||||
@@ -35,6 +48,10 @@ typedef struct SystemState_s
|
||||
// BT event data
|
||||
int btDeviceIndex;
|
||||
|
||||
// NVS cached data
|
||||
paired_device_t pairedDevices[MAX_PAIRED_DEVICES];
|
||||
size_t pairedDeviceCount;
|
||||
|
||||
} SystemState_t;
|
||||
|
||||
|
||||
@@ -88,5 +105,36 @@ int system_getBtDeviceIndex(void);
|
||||
void system_requestVolumeUp(void);
|
||||
void system_requestVolumeDown(void);
|
||||
|
||||
// NVS Service
|
||||
typedef enum {
|
||||
NVS_OP_SAVE_DEVICE,
|
||||
NVS_OP_LOAD_DEVICES,
|
||||
NVS_OP_REMOVE_DEVICE,
|
||||
NVS_OP_IS_DEVICE_KNOWN,
|
||||
NVS_OP_GET_DEVICE_COUNT,
|
||||
NVS_OP_UPDATE_TIMESTAMP
|
||||
} nvs_operation_type_t;
|
||||
|
||||
typedef struct {
|
||||
nvs_operation_type_t operation;
|
||||
paired_device_t device;
|
||||
esp_bd_addr_t bda;
|
||||
TaskHandle_t requestor;
|
||||
esp_err_t result;
|
||||
bool response_ready;
|
||||
} nvs_request_t;
|
||||
|
||||
void system_initNvsService(void);
|
||||
void system_processNvsRequests(void);
|
||||
esp_err_t system_savePairedDevice(const paired_device_t *device);
|
||||
esp_err_t system_loadPairedDevices(paired_device_t *devices, size_t *count);
|
||||
esp_err_t system_removePairedDevice(esp_bd_addr_t bda);
|
||||
bool system_isDeviceKnown(esp_bd_addr_t bda);
|
||||
esp_err_t system_getKnownDeviceCount(size_t *count);
|
||||
esp_err_t system_updateConnectionTimestamp(esp_bd_addr_t bda);
|
||||
const paired_device_t* system_getPairedDevices(size_t *count);
|
||||
|
||||
|
||||
#define NVS_TIMEOUT_MS 5000
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
set(PROJECT_NAME "soundshot")
|
||||
set(CHIP "esp32")
|
||||
set(PORT "COM3")
|
||||
set(PORT "COM14")
|
||||
set(BAUD "460800")
|
||||
|
||||
@@ -449,7 +449,7 @@ CONFIG_BT_CONTROLLER_ENABLED=y
|
||||
#
|
||||
# Bluedroid Options
|
||||
#
|
||||
CONFIG_BT_BTC_TASK_STACK_SIZE=3072
|
||||
CONFIG_BT_BTC_TASK_STACK_SIZE=8192
|
||||
CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y
|
||||
# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set
|
||||
CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0
|
||||
@@ -2275,7 +2275,7 @@ CONFIG_LV_FONT_UNSCII_8=y
|
||||
CONFIG_LV_FONT_UNSCII_16=y
|
||||
# end of Enable built-in fonts
|
||||
|
||||
CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8=y
|
||||
# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8 is not set
|
||||
# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_10 is not set
|
||||
# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12 is not set
|
||||
# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14 is not set
|
||||
@@ -2300,7 +2300,7 @@ CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8=y
|
||||
# CONFIG_LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW is not set
|
||||
# CONFIG_LV_FONT_DEFAULT_SIMSUN_14_CJK is not set
|
||||
# CONFIG_LV_FONT_DEFAULT_SIMSUN_16_CJK is not set
|
||||
# CONFIG_LV_FONT_DEFAULT_UNSCII_8 is not set
|
||||
CONFIG_LV_FONT_DEFAULT_UNSCII_8=y
|
||||
# CONFIG_LV_FONT_DEFAULT_UNSCII_16 is not set
|
||||
# CONFIG_LV_FONT_FMT_TXT_LARGE is not set
|
||||
# CONFIG_LV_USE_FONT_COMPRESSED is not set
|
||||
@@ -2515,7 +2515,7 @@ CONFIG_ESP32_APPTRACE_DEST_NONE=y
|
||||
CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
|
||||
CONFIG_BLUEDROID_ENABLED=y
|
||||
# CONFIG_NIMBLE_ENABLED is not set
|
||||
CONFIG_BTC_TASK_STACK_SIZE=3072
|
||||
CONFIG_BTC_TASK_STACK_SIZE=8192
|
||||
CONFIG_BLUEDROID_PINNED_TO_CORE_0=y
|
||||
# CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set
|
||||
CONFIG_BLUEDROID_PINNED_TO_CORE=0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"project_name": "soundshot",
|
||||
"chip": "esp32",
|
||||
"port": "COM3",
|
||||
"port": "COM14",
|
||||
"monitor_baud": 115200,
|
||||
"flash_baud": 460800,
|
||||
"flash_mode": "dio",
|
||||
|
||||
Reference in New Issue
Block a user