From 4b7f82c38f40223ab7b71d478d6fdc6a9c372209 Mon Sep 17 00:00:00 2001 From: Adolfo Reyna Date: Fri, 11 Sep 2026 23:59:03 -0400 Subject: [PATCH] feat(es3c28p,es3c35p): restore ES8311 42dB mic gain, font size, flash script - Re-apply input-gain-percent (100 = no digital boost) + 42dB HW max mapping lost in the upstream merge (was 340953b1/7788415e) - es3c35p: lvgl.fontSize=16 (text 12/16/22, launcher icons 42) - Add flash-es3c.sh build+flash helper for 28p/35p --- Devices/es3c28p/es3c28p.dts | 1 + Devices/es3c35p/device.properties | 1 + Devices/es3c35p/es3c35p.dts | 1 + .../bindings/everest,es8311.yaml | 4 + .../es8311-module/include/drivers/es8311.h | 8 ++ Drivers/es8311-module/source/es8311.cpp | 23 +++++- flash-es3c.sh | 77 +++++++++++++++++++ 7 files changed, 111 insertions(+), 4 deletions(-) create mode 100755 flash-es3c.sh diff --git a/Devices/es3c28p/es3c28p.dts b/Devices/es3c28p/es3c28p.dts index ab0baee6..87d20953 100644 --- a/Devices/es3c28p/es3c28p.dts +++ b/Devices/es3c28p/es3c28p.dts @@ -90,6 +90,7 @@ compatible = "everest,es8311"; reg = <0x18>; i2s = <&i2s0>; + input-gain-percent = <100>; }; }; diff --git a/Devices/es3c35p/device.properties b/Devices/es3c35p/device.properties index 233a86b9..25b6f420 100644 --- a/Devices/es3c35p/device.properties +++ b/Devices/es3c35p/device.properties @@ -16,6 +16,7 @@ display.shape=rectangle display.dpi=165 lvgl.colorDepth=16 +lvgl.fontSize=16 storage.userDataLocation=SD diff --git a/Devices/es3c35p/es3c35p.dts b/Devices/es3c35p/es3c35p.dts index e8b79d4d..368fca09 100644 --- a/Devices/es3c35p/es3c35p.dts +++ b/Devices/es3c35p/es3c35p.dts @@ -86,6 +86,7 @@ compatible = "everest,es8311"; reg = <0x18>; i2s = <&i2s0>; + input-gain-percent = <100>; }; }; diff --git a/Drivers/es8311-module/bindings/everest,es8311.yaml b/Drivers/es8311-module/bindings/everest,es8311.yaml index dbcbc3e1..7c8c36ed 100644 --- a/Drivers/es8311-module/bindings/everest,es8311.yaml +++ b/Drivers/es8311-module/bindings/everest,es8311.yaml @@ -9,3 +9,7 @@ properties: type: phandle required: true description: "I2S controller device that carries audio data" + input-gain-percent: + type: int + default: 100 + description: "Extra digital gain multiplier applied by audio_stream on top of the ES8311's own 42dB hardware ADC gain, as an integer percentage (100 = 1.0x / no extra boost). For quiet MEMS mic capsules that are still quiet even at max hardware gain." diff --git a/Drivers/es8311-module/include/drivers/es8311.h b/Drivers/es8311-module/include/drivers/es8311.h index f51e1827..a1e0b91d 100644 --- a/Drivers/es8311-module/include/drivers/es8311.h +++ b/Drivers/es8311-module/include/drivers/es8311.h @@ -25,6 +25,14 @@ struct Es8311Config { uint8_t address; /** I2S controller device that carries audio data */ struct Device* i2s_device; + /** + * Extra fixed digital gain multiplier applied by audio_stream on top of the ES8311's + * own hardware ADC gain (0..42dB), as an integer percentage (100 = 1.0x / no extra boost). + * Small MEMS mic capsules can still sound quiet even near max hardware gain; this is for + * boards where 42dB hardware gain alone isn't enough. devicetree has no float property type, + * hence the x100 integer encoding. + */ + uint16_t input_gain_percent; }; #ifdef __cplusplus diff --git a/Drivers/es8311-module/source/es8311.cpp b/Drivers/es8311-module/source/es8311.cpp index 6b3c0ebc..6afdfd03 100644 --- a/Drivers/es8311-module/source/es8311.cpp +++ b/Drivers/es8311-module/source/es8311.cpp @@ -31,6 +31,7 @@ struct Es8311Data { bool is_open = false; AudioCodecDirection open_direction = AUDIO_CODEC_DIR_BOTH; esp_codec_dev_sample_info_t open_sample_info = {}; + float input_gain = 1.0f; }; #define GET_CONFIG(device) (static_cast((device)->config)) @@ -144,8 +145,8 @@ error_t set_volume(Device* device, AudioCodecDirection direction, float volume_p } if (direction == AUDIO_CODEC_DIR_INPUT) { - // ES8311 ADC gain range is roughly 0..24 dB; map 0..100% linearly onto it. - float db = (volume_percent / 100.0f) * 24.0f; + // ES8311 ADC gain supports 0..42dB (0,6,12,18,24,30,36,42) in 6dB steps + float db = (volume_percent / 100.0f) * 42.0f; return (esp_codec_dev_set_in_gain(data->codec_device, db) == ESP_CODEC_DEV_OK) ? ERROR_NONE : ERROR_RESOURCE; } @@ -172,7 +173,8 @@ error_t get_volume(Device* device, AudioCodecDirection direction, float* volume_ if (esp_codec_dev_get_in_gain(data->codec_device, &db) != ESP_CODEC_DEV_OK) { return ERROR_RESOURCE; } - *volume_percent = (db / 24.0f) * 100.0f; + *volume_percent = (db / 42.0f) * 100.0f; + if (*volume_percent > 100.0f) *volume_percent = 100.0f; return ERROR_NONE; } @@ -235,6 +237,12 @@ error_t get_capabilities(Device* device, AudioCodecDirection* supported_directio return ERROR_NONE; } +error_t get_input_gain_multiplier(Device* device, float* gain) { + auto* data = GET_DATA(device); + *gain = data->input_gain; + return ERROR_NONE; +} + static const struct AudioCodecApi API = { .open = open, .close = close, @@ -247,7 +255,7 @@ static const struct AudioCodecApi API = { .get_native_sample_rate = get_native_sample_rate, .get_native_channels = get_native_channels, .get_capabilities = get_capabilities, - .get_input_gain_multiplier = nullptr, + .get_input_gain_multiplier = get_input_gain_multiplier, }; // endregion @@ -257,6 +265,11 @@ static const struct AudioCodecApi API = { error_t start_device(Device* device) { const auto* config = GET_CONFIG(device); + if (config->input_gain_percent > 2000) { + LOG_E(TAG, "Invalid input_gain_percent %u (must be 0..2000)", config->input_gain_percent); + return ERROR_RESOURCE; + } + auto* i2c_controller = device_get_parent(device); if (i2c_controller == nullptr || device_get_type(i2c_controller) != &I2C_CONTROLLER_TYPE) { LOG_E(TAG, "Parent is not an I2C controller"); @@ -270,6 +283,8 @@ error_t start_device(Device* device) { } auto* data = new Es8311Data(); + data->input_gain = (float) config->input_gain_percent / 100.0f; + if (config->input_gain_percent == 0) data->input_gain = 1.0f; // 0 means unset data->ctrl_if = audio_codec_adapter_new_i2c_ctrl(i2c_controller, config->address); data->data_if = audio_codec_adapter_new_i2s_data(i2s_controller); diff --git a/flash-es3c.sh b/flash-es3c.sh new file mode 100755 index 00000000..068e9032 --- /dev/null +++ b/flash-es3c.sh @@ -0,0 +1,77 @@ +#!/bin/zsh +# Build and flash LCDWIKI ES3C28P / ES3C35P firmware. +# +# Usage: +# ./flash-es3c.sh 35p [port] [--build-only] +# ./flash-es3c.sh 28p [port] [--build-only] +# +# If port is omitted, the single /dev/cu.usbmodem* device is used. +# Each board keeps its own build dir (build-es3c28p / build-es3c35p), +# so switching boards only rewrites sdkconfig via device.py. +set -eu -o pipefail + +FIRMWARE_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$FIRMWARE_DIR" +SCRIPT_NAME="$(basename "$0")" + +usage() { + echo "Usage: ${SCRIPT_NAME} <28p|35p> [port] [--build-only]" + echo " port defaults to the single /dev/cu.usbmodem* device" +} + +if (( $# == 0 )); then + usage + exit 1 +fi + +case "$1" in + 28p|es3c28p) DEVICE_ID="es3c28p" ;; + 35p|es3c35p) DEVICE_ID="es3c35p" ;; + -h|--help|help) usage; exit 0 ;; + *) echo "Unknown device '$1' (expected 28p or 35p)"; usage; exit 1 ;; +esac +shift + +PORT="" +BUILD_ONLY=0 +for arg in "$@"; do + case "$arg" in + --build-only) BUILD_ONLY=1 ;; + *) PORT="$arg" ;; + esac +done + +if (( ! BUILD_ONLY )) && [[ -z "$PORT" ]]; then + candidates=(/dev/cu.usbmodem*(N)) + if (( ${#candidates} == 0 )); then + echo "No /dev/cu.usbmodem* device found. Connect the board or pass the port explicitly." + exit 1 + fi + if (( ${#candidates} > 1 )); then + echo "Multiple USB modem devices found:" + printf ' %s\n' "${candidates[@]}" + echo "Unplug one board or pass the port explicitly." + exit 1 + fi + PORT="${candidates[1]}" +fi + +# IDF 5.5 environment (host venvs corrupt IDF tooling, so pin the IDF python env) +unset VIRTUAL_ENV PYTHONPATH PYTHONHOME +export IDF_PYTHON_ENV_PATH=/Users/adolforeyna/.espressif/python_env/idf5.5_py3.9_env +source /Users/adolforeyna/esp/esp-idf/export.sh + +BUILD_DIR="build-${DEVICE_ID}" +"$IDF_PYTHON_ENV_PATH/bin/python" device.py "$DEVICE_ID" +idf.py -B "$BUILD_DIR" reconfigure build + +if (( BUILD_ONLY )); then + echo "Build done (${BUILD_DIR}/Tactility.bin). Skipping flash (--build-only)." + exit 0 +fi + +echo "=== Confirming board on ${PORT} ===" +"$IDF_PYTHON_ENV_PATH/bin/python" -m esptool --chip esp32s3 -p "$PORT" chip_id | grep -E "Chip is|MAC:" + +idf.py -B "$BUILD_DIR" -p "$PORT" -b 460800 flash +echo "Flashed ${DEVICE_ID} on ${PORT}."