Implement dynamic hardware auto-detection in board_config.py to support both Hosyond and Waveshare RLCD boards out-of-the-box
This commit is contained in:
@@ -1,41 +1,34 @@
|
|||||||
# This file is executed on every boot (including wake-boot from deepsleep)
|
# This file is executed on every boot (including wake-boot from deepsleep)
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
|
import board_config
|
||||||
|
import wifi_config
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import network
|
import network
|
||||||
has_network = True
|
has_network = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
has_network = False
|
has_network = False
|
||||||
if sys.platform == 'rp2':
|
|
||||||
import st7796 as display_module
|
|
||||||
else:
|
|
||||||
import ili9341 as display_module
|
|
||||||
from machine import Pin, SPI
|
|
||||||
import wifi_config
|
|
||||||
|
|
||||||
def connect_wifi():
|
def connect_wifi():
|
||||||
if sys.platform == 'rp2':
|
if sys.platform == 'rp2':
|
||||||
# Skip display and connection setup on RP2 (no network/Wi-Fi hardware)
|
# Skip display and connection setup on RP2 (no network/Wi-Fi hardware)
|
||||||
# Keep the sleep window to make REPL interruption easy
|
|
||||||
time.sleep(1.5)
|
time.sleep(1.5)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Initialize display to show connection progress
|
# Use the pre-initialized display from board_config
|
||||||
display = None
|
display = board_config.display_instance
|
||||||
try:
|
if display:
|
||||||
# ESP32-S3 configuration for Hosyond Board
|
try:
|
||||||
spi = SPI(1, baudrate=40000000, polarity=0, phase=0, sck=Pin(12), mosi=Pin(11), miso=Pin(13))
|
display.clear(0)
|
||||||
display = display_module.ILI9341(spi, cs=Pin(10), dc=Pin(46), bl=Pin(45), rst=None)
|
board_name = "ESP32-S3 " + str(board_config.BOARD_TYPE)
|
||||||
display.clear(0)
|
display.text(board_name, 10, 10, 1)
|
||||||
|
display.line(10, 20, display.width - 10, 20, 1)
|
||||||
display.text("Hosyond ESP32-S3", 10, 10, 1)
|
display.text("Connecting to Wi-Fi...", 10, 35, 1)
|
||||||
display.line(10, 20, 310, 20, 1)
|
display.text(f"SSID: {wifi_config.WIFI_SSID}", 10, 50, 1)
|
||||||
display.text("Connecting to Wi-Fi...", 10, 35, 1)
|
display.show()
|
||||||
display.text(f"SSID: {wifi_config.WIFI_SSID}", 10, 50, 1)
|
except Exception as e:
|
||||||
display.show()
|
print("Display setup failed in boot.py:", e)
|
||||||
except Exception as e:
|
|
||||||
print("Display init failed in boot.py:", e)
|
|
||||||
|
|
||||||
# Initialize Wi-Fi Station
|
# Initialize Wi-Fi Station
|
||||||
if not has_network:
|
if not has_network:
|
||||||
@@ -62,34 +55,45 @@ def connect_wifi():
|
|||||||
timeout -= 1
|
timeout -= 1
|
||||||
print("Connecting...")
|
print("Connecting...")
|
||||||
if display:
|
if display:
|
||||||
display.text(".", dot_x, 70, 1)
|
try:
|
||||||
dot_x += 10
|
display.text(".", dot_x, 70, 1)
|
||||||
display.show()
|
dot_x += 10
|
||||||
|
display.show()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
if wlan.isconnected():
|
if wlan.isconnected():
|
||||||
ip = wlan.ifconfig()[0]
|
ip = wlan.ifconfig()[0]
|
||||||
print(f"Wi-Fi Connected! IP Address: {ip}")
|
print(f"Wi-Fi Connected! IP Address: {ip}")
|
||||||
if display:
|
if display:
|
||||||
display.clear(0)
|
try:
|
||||||
display.text("Hosyond ESP32-S3", 10, 10, 1)
|
display.clear(0)
|
||||||
display.line(10, 20, 310, 20, 1)
|
board_name = "ESP32-S3 " + str(board_config.BOARD_TYPE)
|
||||||
display.text("Wi-Fi Status: Connected!", 10, 35, 1)
|
display.text(board_name, 10, 10, 1)
|
||||||
display.text(f"SSID: {wifi_config.WIFI_SSID}", 10, 50, 1)
|
display.line(10, 20, display.width - 10, 20, 1)
|
||||||
display.text(f"IP: {ip}", 10, 65, 1)
|
display.text("Wi-Fi Status: Connected!", 10, 35, 1)
|
||||||
display.text("Starting MCP Server...", 10, 90, 1)
|
display.text(f"SSID: {wifi_config.WIFI_SSID}", 10, 50, 1)
|
||||||
display.show()
|
display.text(f"IP: {ip}", 10, 65, 1)
|
||||||
time.sleep(1.5)
|
display.text("Starting MCP Server...", 10, 90, 1)
|
||||||
|
display.show()
|
||||||
|
time.sleep(1.5)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
print("Wi-Fi Connection Failed.")
|
print("Wi-Fi Connection Failed.")
|
||||||
if display:
|
if display:
|
||||||
display.clear(0)
|
try:
|
||||||
display.text("Hosyond ESP32-S3", 10, 10, 1)
|
display.clear(0)
|
||||||
display.line(10, 20, 310, 20, 1)
|
board_name = "ESP32-S3 " + str(board_config.BOARD_TYPE)
|
||||||
display.text("Wi-Fi Status: Failed!", 10, 35, 1)
|
display.text(board_name, 10, 10, 1)
|
||||||
display.text("Check credentials in:", 10, 55, 1)
|
display.line(10, 20, display.width - 10, 20, 1)
|
||||||
display.text("wifi_config.py", 20, 70, 1)
|
display.text("Wi-Fi Status: Failed!", 10, 35, 1)
|
||||||
display.text("Starting offline...", 10, 95, 1)
|
display.text("Check credentials in:", 10, 55, 1)
|
||||||
display.show()
|
display.text("wifi_config.py", 20, 70, 1)
|
||||||
time.sleep(2)
|
display.text("Starting offline...", 10, 95, 1)
|
||||||
|
display.show()
|
||||||
|
time.sleep(2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
connect_wifi()
|
connect_wifi()
|
||||||
|
|||||||
+73
-50
@@ -1,6 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
import machine
|
import machine
|
||||||
from machine import Pin, I2C, I2S
|
from machine import Pin, I2C, I2S
|
||||||
|
import board_config
|
||||||
|
|
||||||
class ES7210:
|
class ES7210:
|
||||||
"""MicroPython driver for the ES7210 4-Channel Audio ADC (Microphone Array).
|
"""MicroPython driver for the ES7210 4-Channel Audio ADC (Microphone Array).
|
||||||
@@ -79,32 +80,41 @@ def record_audio(duration_seconds=5, filename='recording.pcm'):
|
|||||||
duration_seconds (int): How long to record in seconds.
|
duration_seconds (int): How long to record in seconds.
|
||||||
filename (str): Name of output raw PCM file on the device.
|
filename (str): Name of output raw PCM file on the device.
|
||||||
"""
|
"""
|
||||||
# 1. Start I2C Control Bus (SDA=16, SCL=15)
|
# 1. Use I2C Control Bus from board_config
|
||||||
i2c = I2C(0, sda=Pin(16), scl=Pin(15))
|
i2c = board_config.i2c_bus
|
||||||
|
|
||||||
# 1a. Setup Master Clock (MCLK) on GPIO 4 using PWM (needed for ES8311 ADC)
|
# 1a. Setup Master Clock (MCLK) using PWM if configured
|
||||||
mclk_pin = Pin(4, Pin.OUT)
|
mclk_pwm = None
|
||||||
mclk_pwm = machine.PWM(mclk_pin)
|
if board_config.audio_mclk_pin is not None:
|
||||||
mclk_pwm.freq(6144000)
|
mclk_pin = Pin(board_config.audio_mclk_pin, Pin.OUT)
|
||||||
mclk_pwm.duty_u16(32768)
|
mclk_pwm = machine.PWM(mclk_pin)
|
||||||
|
mclk_pwm.freq(board_config.audio_mclk_freq)
|
||||||
|
mclk_pwm.duty_u16(32768)
|
||||||
|
|
||||||
# 2. Configure I2S Receiver
|
# 2. Configure I2S Receiver
|
||||||
# Pins: sck=BCLK (GPIO 5), ws=WS/LRCK (GPIO 7), sd=DIN (GPIO 6)
|
|
||||||
i2s = I2S(1,
|
i2s = I2S(1,
|
||||||
sck=Pin(5),
|
sck=Pin(board_config.audio_i2s_sck),
|
||||||
ws=Pin(7),
|
ws=Pin(board_config.audio_i2s_ws),
|
||||||
sd=Pin(6),
|
sd=Pin(board_config.audio_i2s_rx_sd),
|
||||||
mode=I2S.RX,
|
mode=I2S.RX,
|
||||||
ibuf=16000,
|
ibuf=16000,
|
||||||
rate=16000,
|
rate=16000,
|
||||||
bits=16,
|
bits=16,
|
||||||
format=I2S.STEREO)
|
format=I2S.STEREO)
|
||||||
|
|
||||||
# 3. Wake up and configure the ES8311 codec chip
|
# 3. Wake up and configure the microphone chip (ES7210 vs ES8311)
|
||||||
mic_adc = ES8311(i2c)
|
if board_config.audio_mic_codec == "ES7210":
|
||||||
if not mic_adc.init(sample_rate=16000):
|
mic_adc = ES7210(i2c)
|
||||||
i2s.deinit()
|
if not mic_adc.init(sample_rate=16000, bit_width=16):
|
||||||
return False
|
i2s.deinit()
|
||||||
|
if mclk_pwm: mclk_pwm.deinit()
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
mic_adc = ES8311(i2c)
|
||||||
|
if not mic_adc.init(sample_rate=16000):
|
||||||
|
i2s.deinit()
|
||||||
|
if mclk_pwm: mclk_pwm.deinit()
|
||||||
|
return False
|
||||||
|
|
||||||
print(f"Recording {duration_seconds} seconds of audio...")
|
print(f"Recording {duration_seconds} seconds of audio...")
|
||||||
|
|
||||||
@@ -130,8 +140,15 @@ def record_audio(duration_seconds=5, filename='recording.pcm'):
|
|||||||
return False
|
return False
|
||||||
finally:
|
finally:
|
||||||
# Always release the I2S peripheral resources
|
# Always release the I2S peripheral resources
|
||||||
i2s.deinit()
|
try:
|
||||||
mclk_pwm.deinit()
|
i2s.deinit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if mclk_pwm:
|
||||||
|
try:
|
||||||
|
mclk_pwm.deinit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
print("I2S receiver and MCLK deinitialized.")
|
print("I2S receiver and MCLK deinitialized.")
|
||||||
|
|
||||||
|
|
||||||
@@ -226,37 +243,40 @@ def play_tone(frequency=440, duration_ms=1000, volume=50):
|
|||||||
|
|
||||||
print(f"Playing tone: {frequency}Hz for {duration_ms}ms (vol={volume})...")
|
print(f"Playing tone: {frequency}Hz for {duration_ms}ms (vol={volume})...")
|
||||||
|
|
||||||
# 1. Setup Master Clock (MCLK) on GPIO 4 using PWM
|
# 1. Setup Master Clock (MCLK) using PWM if configured
|
||||||
mclk_pin = Pin(4, Pin.OUT)
|
mclk_pwm = None
|
||||||
mclk_pwm = machine.PWM(mclk_pin)
|
if board_config.audio_mclk_pin is not None:
|
||||||
mclk_pwm.freq(6144000)
|
mclk_pin = Pin(board_config.audio_mclk_pin, Pin.OUT)
|
||||||
mclk_pwm.duty_u16(32768)
|
mclk_pwm = machine.PWM(mclk_pin)
|
||||||
|
mclk_pwm.freq(board_config.audio_mclk_freq)
|
||||||
|
mclk_pwm.duty_u16(32768)
|
||||||
|
|
||||||
# 2. Start I2C Control Bus (SDA=16, SCL=15)
|
# 2. Use dynamic I2C Control Bus from board_config
|
||||||
i2c = I2C(0, sda=Pin(16), scl=Pin(15))
|
i2c = board_config.i2c_bus
|
||||||
|
|
||||||
# 3. Initialize the ES8311 DAC
|
# 3. Initialize the ES8311 DAC
|
||||||
dac = ES8311(i2c)
|
dac = ES8311(i2c)
|
||||||
if not dac.init(sample_rate=16000):
|
if not dac.init(sample_rate=16000):
|
||||||
mclk_pwm.deinit()
|
if mclk_pwm: mclk_pwm.deinit()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
dac.set_volume(volume)
|
dac.set_volume(volume)
|
||||||
|
|
||||||
# 4. Configure I2S TX
|
# 4. Configure I2S TX
|
||||||
# Pins: sck=BCLK (GPIO 5), ws=WS/LRCK (GPIO 7), sd=DOUT (GPIO 8)
|
|
||||||
i2s = I2S(1,
|
i2s = I2S(1,
|
||||||
sck=Pin(5),
|
sck=Pin(board_config.audio_i2s_sck),
|
||||||
ws=Pin(7),
|
ws=Pin(board_config.audio_i2s_ws),
|
||||||
sd=Pin(8),
|
sd=Pin(board_config.audio_i2s_tx_sd),
|
||||||
mode=I2S.TX,
|
mode=I2S.TX,
|
||||||
ibuf=8000,
|
ibuf=8000,
|
||||||
rate=16000,
|
rate=16000,
|
||||||
bits=16,
|
bits=16,
|
||||||
format=I2S.STEREO)
|
format=I2S.STEREO)
|
||||||
|
|
||||||
# 5. Enable Speaker Amplifier (GPIO 1, Active Low)
|
# 5. Enable Speaker Amplifier
|
||||||
amp_pin = Pin(1, Pin.OUT, value=0)
|
on_val = 0 if board_config.audio_amp_active_level == 0 else 1
|
||||||
|
off_val = 1 if board_config.audio_amp_active_level == 0 else 0
|
||||||
|
amp_pin = Pin(board_config.audio_amp_pin, Pin.OUT, value=on_val)
|
||||||
|
|
||||||
# 6. Generate sine wave cycle
|
# 6. Generate sine wave cycle
|
||||||
# Approximate frequency to make integer number of samples per cycle
|
# Approximate frequency to make integer number of samples per cycle
|
||||||
@@ -284,9 +304,9 @@ def play_tone(frequency=440, duration_ms=1000, volume=50):
|
|||||||
|
|
||||||
# 7. Clean up
|
# 7. Clean up
|
||||||
time.sleep_ms(100) # Let the remaining buffer play out
|
time.sleep_ms(100) # Let the remaining buffer play out
|
||||||
amp_pin.value(1) # Disable amp
|
amp_pin.value(off_val) # Disable amp
|
||||||
i2s.deinit()
|
i2s.deinit()
|
||||||
mclk_pwm.deinit()
|
if mclk_pwm: mclk_pwm.deinit()
|
||||||
print("Tone playback complete.")
|
print("Tone playback complete.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -344,39 +364,42 @@ def play_wav(filename, volume=50):
|
|||||||
|
|
||||||
print(f"WAV Info: {sample_rate}Hz, {bits} bits, {'Mono' if channels == 1 else 'Stereo'}")
|
print(f"WAV Info: {sample_rate}Hz, {bits} bits, {'Mono' if channels == 1 else 'Stereo'}")
|
||||||
|
|
||||||
# 2. Setup Master Clock (MCLK) on GPIO 4 using PWM
|
# 2. Setup Master Clock (MCLK) using PWM if configured
|
||||||
mclk_pin = Pin(4, Pin.OUT)
|
mclk_pwm = None
|
||||||
mclk_pwm = machine.PWM(mclk_pin)
|
if board_config.audio_mclk_pin is not None:
|
||||||
mclk_pwm.freq(6144000)
|
mclk_pin = Pin(board_config.audio_mclk_pin, Pin.OUT)
|
||||||
mclk_pwm.duty_u16(32768)
|
mclk_pwm = machine.PWM(mclk_pin)
|
||||||
|
mclk_pwm.freq(board_config.audio_mclk_freq)
|
||||||
|
mclk_pwm.duty_u16(32768)
|
||||||
|
|
||||||
# 3. Start I2C Control Bus (SDA=16, SCL=15)
|
# 3. Use dynamic I2C Control Bus from board_config
|
||||||
i2c = I2C(0, sda=Pin(16), scl=Pin(15))
|
i2c = board_config.i2c_bus
|
||||||
|
|
||||||
# 4. Initialize the ES8311 DAC
|
# 4. Initialize the ES8311 DAC
|
||||||
dac = ES8311(i2c)
|
dac = ES8311(i2c)
|
||||||
if not dac.init(sample_rate=16000):
|
if not dac.init(sample_rate=16000):
|
||||||
mclk_pwm.deinit()
|
if mclk_pwm: mclk_pwm.deinit()
|
||||||
f.close()
|
f.close()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
dac.set_volume(volume)
|
dac.set_volume(volume)
|
||||||
|
|
||||||
# 5. Configure I2S TX
|
# 5. Configure I2S TX
|
||||||
# Pins: sck=BCLK (GPIO 5), ws=WS/LRCK (GPIO 7), sd=DOUT (GPIO 8)
|
|
||||||
i2s_format = I2S.MONO if channels == 1 else I2S.STEREO
|
i2s_format = I2S.MONO if channels == 1 else I2S.STEREO
|
||||||
i2s = I2S(1,
|
i2s = I2S(1,
|
||||||
sck=Pin(5),
|
sck=Pin(board_config.audio_i2s_sck),
|
||||||
ws=Pin(7),
|
ws=Pin(board_config.audio_i2s_ws),
|
||||||
sd=Pin(8),
|
sd=Pin(board_config.audio_i2s_tx_sd),
|
||||||
mode=I2S.TX,
|
mode=I2S.TX,
|
||||||
ibuf=4096,
|
ibuf=4096,
|
||||||
rate=sample_rate,
|
rate=sample_rate,
|
||||||
bits=bits,
|
bits=bits,
|
||||||
format=i2s_format)
|
format=i2s_format)
|
||||||
|
|
||||||
# 6. Enable Speaker Amplifier (GPIO 1, Active Low)
|
# 6. Enable Speaker Amplifier
|
||||||
amp_pin = Pin(1, Pin.OUT, value=0)
|
on_val = 0 if board_config.audio_amp_active_level == 0 else 1
|
||||||
|
off_val = 1 if board_config.audio_amp_active_level == 0 else 0
|
||||||
|
amp_pin = Pin(board_config.audio_amp_pin, Pin.OUT, value=on_val)
|
||||||
|
|
||||||
# 7. Read and stream chunks to I2S
|
# 7. Read and stream chunks to I2S
|
||||||
buf = bytearray(2048)
|
buf = bytearray(2048)
|
||||||
@@ -388,9 +411,9 @@ def play_wav(filename, volume=50):
|
|||||||
|
|
||||||
# 8. Clean up
|
# 8. Clean up
|
||||||
time.sleep_ms(100) # Let the remaining buffer play out
|
time.sleep_ms(100) # Let the remaining buffer play out
|
||||||
amp_pin.value(1) # Disable amp
|
amp_pin.value(off_val) # Disable amp
|
||||||
i2s.deinit()
|
i2s.deinit()
|
||||||
mclk_pwm.deinit()
|
if mclk_pwm: mclk_pwm.deinit()
|
||||||
f.close()
|
f.close()
|
||||||
print("WAV playback complete.")
|
print("WAV playback complete.")
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -0,0 +1,191 @@
|
|||||||
|
import sys
|
||||||
|
import machine
|
||||||
|
from machine import Pin, I2C, SPI
|
||||||
|
|
||||||
|
# Global configuration variables
|
||||||
|
BOARD_TYPE = None # 'HOSYOND', 'WAVESHARE_RLCD', or 'RP2'
|
||||||
|
DISPLAY_TYPE = None # 'ILI9341', 'RLCD', or 'ST7796'
|
||||||
|
DISPLAY_WIDTH = 320
|
||||||
|
DISPLAY_HEIGHT = 240
|
||||||
|
|
||||||
|
# Bus and display references
|
||||||
|
spi_bus = None
|
||||||
|
i2c_bus = None
|
||||||
|
display_instance = None
|
||||||
|
touch = None
|
||||||
|
|
||||||
|
# Component support flags
|
||||||
|
has_sensor = False
|
||||||
|
has_rtc = False
|
||||||
|
|
||||||
|
# WS2812 NeoPixel pin
|
||||||
|
led_pin = None
|
||||||
|
|
||||||
|
# Audio pins, clocks, and codecs config
|
||||||
|
audio_mclk_pin = None
|
||||||
|
audio_mclk_freq = 6144000
|
||||||
|
audio_i2c_sda = None
|
||||||
|
audio_i2c_scl = None
|
||||||
|
audio_i2s_sck = None
|
||||||
|
audio_i2s_ws = None
|
||||||
|
audio_i2s_tx_sd = None
|
||||||
|
audio_i2s_rx_sd = None
|
||||||
|
audio_amp_pin = None
|
||||||
|
audio_amp_active_level = 0 # 0 = Active Low, 1 = Active High
|
||||||
|
audio_mic_codec = "ES8311" # "ES7210" or "ES8311"
|
||||||
|
|
||||||
|
def detect_board():
|
||||||
|
global BOARD_TYPE, DISPLAY_TYPE, DISPLAY_WIDTH, DISPLAY_HEIGHT
|
||||||
|
global spi_bus, i2c_bus, display_instance, touch
|
||||||
|
global has_sensor, has_rtc, led_pin
|
||||||
|
global audio_mclk_pin, audio_mclk_freq, audio_i2c_sda, audio_i2c_scl
|
||||||
|
global audio_i2s_sck, audio_i2s_ws, audio_i2s_tx_sd, audio_i2s_rx_sd
|
||||||
|
global audio_amp_pin, audio_amp_active_level, audio_mic_codec
|
||||||
|
|
||||||
|
# 1. Check if running on RP2 platform (e.g. Raspberry Pi Pico / RP2350)
|
||||||
|
if sys.platform == 'rp2':
|
||||||
|
print("Auto-detected: Raspberry Pi RP2 platform")
|
||||||
|
BOARD_TYPE = 'RP2'
|
||||||
|
DISPLAY_TYPE = 'ST7796'
|
||||||
|
DISPLAY_WIDTH = 480
|
||||||
|
DISPLAY_HEIGHT = 320
|
||||||
|
led_pin = 25
|
||||||
|
|
||||||
|
# Setup SPI
|
||||||
|
spi_bus = SPI(1, baudrate=32000000, polarity=0, phase=0, sck=Pin(10), mosi=Pin(11))
|
||||||
|
|
||||||
|
# Setup Display: ST7796
|
||||||
|
import st7796
|
||||||
|
display_instance = st7796.ST7796(spi_bus, cs=Pin(7), dc=Pin(4), rst=Pin(9), bl=Pin(6))
|
||||||
|
|
||||||
|
# Setup Touch: FT6336U on I2C(1)
|
||||||
|
try:
|
||||||
|
touch_i2c = I2C(1, sda=Pin(2), scl=Pin(3), freq=400000)
|
||||||
|
from ft6336u import FT6336U
|
||||||
|
touch = FT6336U(touch_i2c, rst_pin=28, int_pin=25)
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to initialize touch on RP2:", e)
|
||||||
|
return
|
||||||
|
|
||||||
|
# 2. We are on ESP32 platform.
|
||||||
|
# Try scanning I2C(0) on Hosyond pins (SDA=16, SCL=15)
|
||||||
|
try:
|
||||||
|
test_i2c = I2C(0, sda=Pin(16), scl=Pin(15))
|
||||||
|
devices = test_i2c.scan()
|
||||||
|
# FT6336U touchscreen is at 0x38 on Hosyond
|
||||||
|
if 0x38 in devices:
|
||||||
|
print("Auto-detected: Hosyond ESP32-S3 Touchscreen board")
|
||||||
|
BOARD_TYPE = 'HOSYOND'
|
||||||
|
DISPLAY_TYPE = 'ILI9341'
|
||||||
|
DISPLAY_WIDTH = 320
|
||||||
|
DISPLAY_HEIGHT = 240
|
||||||
|
has_sensor = False
|
||||||
|
has_rtc = False
|
||||||
|
led_pin = 48
|
||||||
|
|
||||||
|
i2c_bus = test_i2c
|
||||||
|
|
||||||
|
# Setup SPI
|
||||||
|
spi_bus = SPI(1, baudrate=40000000, polarity=0, phase=0, sck=Pin(12), mosi=Pin(11), miso=Pin(13))
|
||||||
|
|
||||||
|
# Setup Display: ILI9341
|
||||||
|
import ili9341
|
||||||
|
display_instance = ili9341.ILI9341(spi_bus, cs=Pin(10), dc=Pin(46), bl=Pin(45), rst=None)
|
||||||
|
|
||||||
|
# Setup Touch: FT6336U
|
||||||
|
try:
|
||||||
|
from ft6336u import FT6336U
|
||||||
|
touch = FT6336U(i2c_bus, rst_pin=18, int_pin=17, width=320, height=240, swap_xy=True, invert_x=False, invert_y=True)
|
||||||
|
except Exception as te:
|
||||||
|
print("Failed to initialize touchscreen:", te)
|
||||||
|
|
||||||
|
# Audio pins & clocks configuration
|
||||||
|
audio_mclk_pin = 4
|
||||||
|
audio_mclk_freq = 6144000
|
||||||
|
audio_i2c_sda = 16
|
||||||
|
audio_i2c_scl = 15
|
||||||
|
audio_i2s_sck = 5
|
||||||
|
audio_i2s_ws = 7
|
||||||
|
audio_i2s_tx_sd = 8
|
||||||
|
audio_i2s_rx_sd = 6
|
||||||
|
audio_amp_pin = 1
|
||||||
|
audio_amp_active_level = 0 # Active Low (0 = enabled)
|
||||||
|
audio_mic_codec = "ES8311"
|
||||||
|
return
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("I2C scan on Hosyond pins failed:", e)
|
||||||
|
|
||||||
|
# 3. Try scanning I2C(0) on Waveshare RLCD pins (SDA=13, SCL=14)
|
||||||
|
try:
|
||||||
|
test_i2c = I2C(0, sda=Pin(13), scl=Pin(14))
|
||||||
|
devices = test_i2c.scan()
|
||||||
|
# SHTC3 is at 0x70, PCF85063 RTC is at 0x51
|
||||||
|
if 0x70 in devices or 0x51 in devices:
|
||||||
|
print("Auto-detected: Waveshare ESP32-S3-RLCD-4.2 board")
|
||||||
|
BOARD_TYPE = 'WAVESHARE_RLCD'
|
||||||
|
DISPLAY_TYPE = 'RLCD'
|
||||||
|
DISPLAY_WIDTH = 400
|
||||||
|
DISPLAY_HEIGHT = 300
|
||||||
|
has_sensor = True
|
||||||
|
has_rtc = True
|
||||||
|
led_pin = 38
|
||||||
|
|
||||||
|
i2c_bus = test_i2c
|
||||||
|
|
||||||
|
# Setup SPI
|
||||||
|
spi_bus = SPI(1, baudrate=20000000, polarity=0, phase=0, sck=Pin(11), mosi=Pin(12))
|
||||||
|
|
||||||
|
# Setup Display: RLCD
|
||||||
|
import rlcd
|
||||||
|
display_instance = rlcd.RLCD(spi_bus, cs=Pin(40), dc=Pin(5), rst=Pin(41))
|
||||||
|
|
||||||
|
# Audio pins & clocks configuration
|
||||||
|
audio_mclk_pin = 16
|
||||||
|
audio_mclk_freq = 12288000
|
||||||
|
audio_i2c_sda = 13
|
||||||
|
audio_i2c_scl = 14
|
||||||
|
audio_i2s_sck = 9
|
||||||
|
audio_i2s_ws = 45
|
||||||
|
audio_i2s_tx_sd = 8
|
||||||
|
audio_i2s_rx_sd = 10
|
||||||
|
audio_amp_pin = 46
|
||||||
|
audio_amp_active_level = 1 # Active High (1 = enabled)
|
||||||
|
audio_mic_codec = "ES7210"
|
||||||
|
return
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("I2C scan on Waveshare RLCD pins failed:", e)
|
||||||
|
|
||||||
|
# 4. Fallback default if auto-detection failed completely
|
||||||
|
print("Auto-detection failed. Falling back to Hosyond ESP32-S3 defaults...")
|
||||||
|
BOARD_TYPE = 'HOSYOND'
|
||||||
|
DISPLAY_TYPE = 'ILI9341'
|
||||||
|
DISPLAY_WIDTH = 320
|
||||||
|
DISPLAY_HEIGHT = 240
|
||||||
|
led_pin = 48
|
||||||
|
|
||||||
|
try:
|
||||||
|
i2c_bus = I2C(0, sda=Pin(16), scl=Pin(15))
|
||||||
|
spi_bus = SPI(1, baudrate=40000000, polarity=0, phase=0, sck=Pin(12), mosi=Pin(11), miso=Pin(13))
|
||||||
|
import ili9341
|
||||||
|
display_instance = ili9341.ILI9341(spi_bus, cs=Pin(10), dc=Pin(46), bl=Pin(45), rst=None)
|
||||||
|
from ft6336u import FT6336U
|
||||||
|
touch = FT6336U(i2c_bus, rst_pin=18, int_pin=17, width=320, height=240, swap_xy=True, invert_x=False, invert_y=True)
|
||||||
|
except Exception as e:
|
||||||
|
print("Fallback hardware setup failed:", e)
|
||||||
|
|
||||||
|
audio_mclk_pin = 4
|
||||||
|
audio_mclk_freq = 6144000
|
||||||
|
audio_i2c_sda = 16
|
||||||
|
audio_i2c_scl = 15
|
||||||
|
audio_i2s_sck = 5
|
||||||
|
audio_i2s_ws = 7
|
||||||
|
audio_i2s_tx_sd = 8
|
||||||
|
audio_i2s_rx_sd = 6
|
||||||
|
audio_amp_pin = 1
|
||||||
|
audio_amp_active_level = 0
|
||||||
|
audio_mic_codec = "ES8311"
|
||||||
|
|
||||||
|
# Run dynamic detection immediately on module load
|
||||||
|
detect_board()
|
||||||
@@ -8,11 +8,7 @@ try:
|
|||||||
has_network = True
|
has_network = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
has_network = False
|
has_network = False
|
||||||
|
import board_config
|
||||||
if sys.platform == 'rp2':
|
|
||||||
import st7796 as display_module
|
|
||||||
else:
|
|
||||||
import ili9341 as display_module
|
|
||||||
|
|
||||||
class DummyMCP:
|
class DummyMCP:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -74,61 +70,45 @@ local_led_mode_idx = 1 # Green breathing
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
global local_led_mode_idx
|
global local_led_mode_idx
|
||||||
print("=== Starting ESP32-S3-RLCD-4.2 Main Boot ===")
|
import board_config
|
||||||
|
|
||||||
# 1. Initialize shared buses and peripherals
|
print("=== Starting MCP Server Main Boot (Type: {}) ===".format(board_config.BOARD_TYPE))
|
||||||
i2c = None
|
|
||||||
if sys.platform != 'rp2':
|
|
||||||
try:
|
|
||||||
i2c = I2C(0, sda=Pin(16), scl=Pin(15))
|
|
||||||
except Exception as e:
|
|
||||||
print("Failed to initialize I2C0:", e)
|
|
||||||
|
|
||||||
if sys.platform == 'rp2':
|
# 1. Use pre-initialized display and buses from board_config
|
||||||
spi = SPI(1, baudrate=32000000, polarity=0, phase=0, sck=Pin(10), mosi=Pin(11))
|
i2c = board_config.i2c_bus
|
||||||
display = display_module.ST7796(spi, cs=Pin(7), dc=Pin(4), rst=Pin(9), bl=Pin(6))
|
spi = board_config.spi_bus
|
||||||
|
display = board_config.display_instance
|
||||||
# Touch controller
|
touch = board_config.touch
|
||||||
touch = None
|
|
||||||
try:
|
|
||||||
touch_i2c = I2C(1, sda=Pin(2), scl=Pin(3), freq=400000)
|
|
||||||
from ft6336u import FT6336U
|
|
||||||
touch = FT6336U(touch_i2c, rst_pin=28, int_pin=25)
|
|
||||||
except Exception as te:
|
|
||||||
print("Failed to initialize touch:", te)
|
|
||||||
else:
|
|
||||||
spi = SPI(1, baudrate=40000000, polarity=0, phase=0, sck=Pin(12), mosi=Pin(11), miso=Pin(13))
|
|
||||||
display = display_module.ILI9341(spi, cs=Pin(10), dc=Pin(46), bl=Pin(45), rst=None)
|
|
||||||
touch = None
|
|
||||||
try:
|
|
||||||
from ft6336u import FT6336U
|
|
||||||
touch = FT6336U(i2c, rst_pin=18, int_pin=17, width=320, height=240, swap_xy=True, invert_x=False, invert_y=True)
|
|
||||||
except Exception as te:
|
|
||||||
print("Failed to initialize touch:", te)
|
|
||||||
|
|
||||||
if sys.platform != 'rp2':
|
# Configure Audio Amp control pin to save power
|
||||||
# Configure Audio Amp control pin (GPIO 1, Active Low) to save power
|
if sys.platform != 'rp2' and board_config.audio_amp_pin is not None:
|
||||||
amp_pin = Pin(1, Pin.OUT, value=1)
|
# Turn OFF amplifier on boot (active-low vs active-high)
|
||||||
|
off_val = 1 if board_config.audio_amp_active_level == 0 else 0
|
||||||
|
amp_pin = Pin(board_config.audio_amp_pin, Pin.OUT, value=off_val)
|
||||||
|
|
||||||
# 2. Initialize utility objects
|
# 2. Initialize utility objects
|
||||||
sensor = None
|
sensor = None
|
||||||
rtc_chip = None
|
rtc_chip = None
|
||||||
if i2c is not None:
|
if i2c is not None:
|
||||||
try:
|
if board_config.has_sensor:
|
||||||
sensor = SHTC3(i2c)
|
try:
|
||||||
except Exception as e:
|
sensor = SHTC3(i2c)
|
||||||
print("Failed to initialize SHTC3:", e)
|
except Exception as e:
|
||||||
try:
|
print("Failed to initialize SHTC3:", e)
|
||||||
rtc_chip = PCF85063(i2c)
|
if board_config.has_rtc:
|
||||||
except Exception as e:
|
try:
|
||||||
print("Failed to initialize PCF85063:", e)
|
rtc_chip = PCF85063(i2c)
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to initialize PCF85063:", e)
|
||||||
|
|
||||||
battery = BatteryMonitor()
|
battery = BatteryMonitor()
|
||||||
led = BoardLED()
|
led = BoardLED(board_config.led_pin)
|
||||||
buttons = None
|
buttons = None
|
||||||
if sys.platform != 'rp2':
|
if sys.platform != 'rp2':
|
||||||
buttons = BoardButtons()
|
buttons = BoardButtons()
|
||||||
ble_uart = BLEUART(name="ESP32-S3-TFT")
|
|
||||||
|
ble_name = "ESP32-S3-" + ("RLCD" if board_config.BOARD_TYPE == "WAVESHARE_RLCD" else "Touch")
|
||||||
|
ble_uart = BLEUART(name=ble_name)
|
||||||
|
|
||||||
# Sync system clock from RTC chip
|
# Sync system clock from RTC chip
|
||||||
if rtc_chip:
|
if rtc_chip:
|
||||||
@@ -229,9 +209,10 @@ def main():
|
|||||||
print("Touch detected! Starting Hermes Voice Assistant...")
|
print("Touch detected! Starting Hermes Voice Assistant...")
|
||||||
|
|
||||||
def draw_status_bar(text):
|
def draw_status_bar(text):
|
||||||
display.line(0, 215, 320, 215, 1)
|
y_bar = display.height - 25
|
||||||
display.fill_rect(0, 216, 320, 24, 0)
|
display.line(0, y_bar, display.width, y_bar, 1)
|
||||||
display.text(text, 10, 222, 1)
|
display.fill_rect(0, y_bar + 1, display.width, 24, 0)
|
||||||
|
display.text(text, 10, y_bar + 7, 1)
|
||||||
display.show()
|
display.show()
|
||||||
|
|
||||||
def clear_status_bar():
|
def clear_status_bar():
|
||||||
@@ -454,10 +435,10 @@ def main():
|
|||||||
|
|
||||||
# Draw standard status dashboard layout
|
# Draw standard status dashboard layout
|
||||||
display.clear(0)
|
display.clear(0)
|
||||||
title_text = "RP2350-TFT MCP SERVER" if sys.platform == 'rp2' else "Hosyond ESP32-S3 Server"
|
line_w = display.width - 10
|
||||||
line_w = 470 if sys.platform == 'rp2' else 310
|
|
||||||
|
|
||||||
if sys.platform == 'rp2':
|
if board_config.BOARD_TYPE == 'WAVESHARE_RLCD' or sys.platform == 'rp2':
|
||||||
|
title_text = "RP2350-TFT MCP SERVER" if sys.platform == 'rp2' else "Waveshare ESP32-S3-RLCD Server"
|
||||||
display.text(title_text, 10, 10, 1)
|
display.text(title_text, 10, 10, 1)
|
||||||
display.line(10, 20, line_w, 20, 1)
|
display.line(10, 20, line_w, 20, 1)
|
||||||
display.text_large("ENVIRONMENT", 15, 30, scale=2, c=1)
|
display.text_large("ENVIRONMENT", 15, 30, scale=2, c=1)
|
||||||
@@ -467,7 +448,7 @@ def main():
|
|||||||
display.text_large("MCP NET CONNECTION", 15, 105, scale=2, c=1)
|
display.text_large("MCP NET CONNECTION", 15, 105, scale=2, c=1)
|
||||||
display.text(f"IP Address : {ip_addr}", 25, 130, 1)
|
display.text(f"IP Address : {ip_addr}", 25, 130, 1)
|
||||||
display.text(f"Port / Path : 80 /api/mcp", 25, 145, 1)
|
display.text(f"Port / Path : 80 /api/mcp", 25, 145, 1)
|
||||||
display.text(f"BLE Name : ESP32-S3-RLCD", 25, 160, 1)
|
display.text(f"BLE Name : {ble_name}", 25, 160, 1)
|
||||||
display.line(10, 185, line_w, 185, 1)
|
display.line(10, 185, line_w, 185, 1)
|
||||||
display.text_large("SYSTEM STATUS", 15, 195, scale=2, c=1)
|
display.text_large("SYSTEM STATUS", 15, 195, scale=2, c=1)
|
||||||
display.text(f"Battery : {bat_str}", 25, 220, 1)
|
display.text(f"Battery : {bat_str}", 25, 220, 1)
|
||||||
@@ -475,6 +456,7 @@ def main():
|
|||||||
display.line(10, 255, line_w, 255, 1)
|
display.line(10, 255, line_w, 255, 1)
|
||||||
display.text(f"Status: {last_action_str}", 15, 265, 1)
|
display.text(f"Status: {last_action_str}", 15, 265, 1)
|
||||||
else:
|
else:
|
||||||
|
title_text = "Hosyond ESP32-S3 Server"
|
||||||
display.text(title_text, 10, 8, 1)
|
display.text(title_text, 10, 8, 1)
|
||||||
display.line(10, 18, line_w, 18, 1)
|
display.line(10, 18, line_w, 18, 1)
|
||||||
# Left Column (System & Environment)
|
# Left Column (System & Environment)
|
||||||
@@ -490,7 +472,7 @@ def main():
|
|||||||
display.line(170, 38, line_w, 38, 1)
|
display.line(170, 38, line_w, 38, 1)
|
||||||
display.text(f"IP : {ip_addr}", 170, 46, 1)
|
display.text(f"IP : {ip_addr}", 170, 46, 1)
|
||||||
display.text("Port: 80/api/mcp", 170, 58, 1)
|
display.text("Port: 80/api/mcp", 170, 58, 1)
|
||||||
display.text("BLE : S3-TFT", 170, 70, 1)
|
display.text(f"BLE : {ble_name[-6:]}", 170, 70, 1)
|
||||||
# Bottom Status
|
# Bottom Status
|
||||||
display.line(10, 115, line_w, 115, 1)
|
display.line(10, 115, line_w, 115, 1)
|
||||||
display.text(f"Status: {last_action_str}", 10, 125, 1)
|
display.text(f"Status: {last_action_str}", 10, 125, 1)
|
||||||
|
|||||||
@@ -54,8 +54,10 @@ def main():
|
|||||||
|
|
||||||
# Upload new drivers, utilities, and updated scripts
|
# Upload new drivers, utilities, and updated scripts
|
||||||
files_to_upload = [
|
files_to_upload = [
|
||||||
|
("lib/board_config.py", "lib/board_config.py"),
|
||||||
("lib/st7796.py", "lib/st7796.py"),
|
("lib/st7796.py", "lib/st7796.py"),
|
||||||
("lib/ft6336u.py", "lib/ft6336u.py"),
|
("lib/ft6336u.py", "lib/ft6336u.py"),
|
||||||
|
("lib/rlcd.py", "lib/rlcd.py"),
|
||||||
("lib/battery_util.py", "lib/battery_util.py"),
|
("lib/battery_util.py", "lib/battery_util.py"),
|
||||||
("lib/rgb_led_util.py", "lib/rgb_led_util.py"),
|
("lib/rgb_led_util.py", "lib/rgb_led_util.py"),
|
||||||
("lib/audio_util.py", "lib/audio_util.py"),
|
("lib/audio_util.py", "lib/audio_util.py"),
|
||||||
|
|||||||
Reference in New Issue
Block a user