diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8d3238..311b66a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: run: compote component pack --name waveshare_boards build: - name: ${{ matrix.board }} / ${{ matrix.idf }} / BMGR ${{ matrix.bmgr }} + name: ${{ matrix.board }} / ${{ matrix.idf }} / BMGR ${{ matrix.bmgr }} / ${{ matrix.integration }} needs: validate if: needs.validate.outputs.has_builds == 'true' runs-on: ubuntu-latest @@ -82,6 +82,7 @@ jobs: set -eu python -m pip install '${{ matrix.component_manager }}' '${{ matrix.bmgr_assist }}' python ../scripts/board_pack.py pin '${{ matrix.bmgr }}' + python ../scripts/board_pack.py integration '${{ matrix.integration }}' idf.py bmgr -l idf.py bmgr -b '${{ matrix.board }}' idf.py build diff --git a/CMakeLists.txt b/CMakeLists.txt index a96dced..992f49d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1 +1 @@ -idf_component_register() +idf_component_register(INCLUDE_DIRS "include" REQUIRES esp_lcd) diff --git a/README.md b/README.md index 7eede04..838c61c 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,8 @@ or a passing packaging check does not by itself mean that version is published. ```text boards// Board metadata, peripherals, devices, and setup code +include/ Framework-independent AMOLED brightness helper +integrations/ Optional framework adapters, shared across boards idf_component.yml Component metadata and managed dependencies CMakeLists.txt Board-pack component registration ci/test_app/ Board Manager integration compile test @@ -114,6 +116,7 @@ unique `board` value. The catalog is regenerated from the definitions. ## 📚 Documentation - [Board organization, hardware revisions, and migration](docs/BOARDS.md) +- [AMOLED brightness and optional Brookesia integration](docs/INTEGRATIONS.md) - [CI coverage and local validation](docs/CI.md) - [Registry credentials and publication](docs/PUBLISHING.md) - [Contributing](CONTRIBUTING.md) diff --git a/README_ZH.md b/README_ZH.md index 8066de7..ee98892 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -78,6 +78,8 @@ idf.py bmgr -l ```text boards/<完整型号>/ 板卡信息、外设、设备与初始化代码 +include/ 不依赖应用框架的 AMOLED 调光函数 +integrations/ 跨板卡共用的可选框架适配 idf_component.yml 组件元数据与托管依赖 CMakeLists.txt 板卡包组件注册 ci/test_app/ Board Manager 集成编译测试 @@ -105,6 +107,7 @@ python -m unittest discover -s ci/scripts -p 'test_*.py' -v ## 📚 文档 - [板卡组织、硬件版本与迁移说明](docs/BOARDS_ZH.md) +- [AMOLED 调光与可选 Brookesia 集成](docs/INTEGRATIONS_ZH.md) - [CI 覆盖范围与本地验证](docs/CI_ZH.md) - [组件库凭据与发布](docs/PUBLISHING_ZH.md) - [贡献指南](CONTRIBUTING_ZH.md) diff --git a/boards/esp32_s3_touch_amoled_1_75c/board_devices.yaml b/boards/esp32_s3_touch_amoled_1_75c/board_devices.yaml index cf56c56..6113f5a 100644 --- a/boards/esp32_s3_touch_amoled_1_75c/board_devices.yaml +++ b/boards/esp32_s3_touch_amoled_1_75c/board_devices.yaml @@ -64,8 +64,6 @@ devices: version: default dependencies: espressif/esp_lcd_co5300: "^2" - brookesia_hal_custom: - override_path: "${BOARD_PATH}/components/brookesia_hal_custom" config: x_max: 466 y_max: 466 diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/CMakeLists.txt b/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/CMakeLists.txt deleted file mode 100644 index e1b1e1b..0000000 --- a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# This optional bridge is only compiled by applications using Brookesia display. -# Plain Board Manager consumers do not require the Brookesia HAL adaptor. -if(NOT CONFIG_BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE) - idf_component_register() - return() -endif() - -set(COMPONENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(COMPONENT_INCLUDE_DIRS ${COMPONENT_DIR}/include) -set(COMPONENT_PRIVATE_INCLUDE_DIRS ${COMPONENT_DIR}/src) - -file(GLOB_RECURSE COMPONENT_SRCS_CPP ${COMPONENT_DIR}/src/*.cpp) - -# -# Register Component -# -idf_component_register( - SRCS ${COMPONENT_SRCS_C} ${COMPONENT_SRCS_CPP} - INCLUDE_DIRS ${COMPONENT_INCLUDE_DIRS} - PRIV_INCLUDE_DIRS ${COMPONENT_PRIVATE_INCLUDE_DIRS} - REQUIRES brookesia_hal_adaptor esp_board_manager -) - -if(CONFIG_BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE) - set(BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL custom_display_device_plugin_symbol) - target_compile_definitions(${COMPONENT_LIB} PRIVATE - BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL=${BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL} - ) - target_link_libraries(${COMPONENT_LIB} PRIVATE "-u ${BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL}") -endif() diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/idf_component.yml b/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/idf_component.yml deleted file mode 100644 index ae3e08a..0000000 --- a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/idf_component.yml +++ /dev/null @@ -1 +0,0 @@ -version: "0.1.0" diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp b/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp deleted file mode 100644 index b797277..0000000 --- a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file device.hpp - * @brief Singleton HAL device that aggregates codec-based audio playback and recording for board-managed audio hardware. - */ -#pragma once - -#include -#include -#include -#include -#include "brookesia/hal_interface/device.hpp" -#include "brookesia/hal_interface/interfaces/display/backlight.hpp" - -namespace esp_brookesia::hal { - -/** - * @brief Board-backed custom display device - * - * Obtained via get_instance(). Not copyable or movable. - */ -class CustomDisplayDevice : public Device { -public: - /** @brief Logical device name passed to the base @ref Device constructor. */ - static constexpr const char *DEVICE_NAME = "CustomDisplay"; - /** @brief Registry key for the display backlight HAL implementation (`"CustomDisplay:Backlight"`). */ - static constexpr const char *DISPLAY_BACKLIGHT_IMPL_NAME = "CustomDisplay:Backlight"; - - CustomDisplayDevice(const CustomDisplayDevice &) = delete; - CustomDisplayDevice &operator=(const CustomDisplayDevice &) = delete; - CustomDisplayDevice(CustomDisplayDevice &&) = delete; - CustomDisplayDevice &operator=(CustomDisplayDevice &&) = delete; - - /** - * @brief Returns the process-wide singleton custom display device. - * - * @return Reference to the unique @ref CustomDisplayDevice instance. - */ - static CustomDisplayDevice &get_instance() - { - static CustomDisplayDevice instance; - return instance; - } - -private: - CustomDisplayDevice() - : Device(std::string(DEVICE_NAME)) - { - } - ~CustomDisplayDevice() = default; - - bool probe() override; - std::vector get_interface_specs() const override; - bool on_init() override; - void on_deinit() override; - - bool init_backlight(); - void deinit_backlight(); -}; - -} // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h b/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h deleted file mode 100644 index 6659b85..0000000 --- a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include "sdkconfig.h" - -/** - * @brief Default log tag used by the component. - */ -#define BROOKESIA_HAL_CUSTOM_LOG_TAG "HalCustom" - -#if !defined(BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG) -# if defined(CONFIG_BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG) -# define BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG CONFIG_BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG -# else -# define BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG (0) -# endif -#endif diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/backlight_impl.hpp b/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/backlight_impl.hpp deleted file mode 100644 index 25e1f3d..0000000 --- a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/backlight_impl.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include -#include "boost/thread/lock_guard.hpp" -#include "boost/thread/mutex.hpp" -#include "brookesia/hal_interface/interfaces/display/backlight.hpp" - -namespace esp_brookesia::hal { - -/** - * @brief Board-backed backlight HAL interface (holds LEDC handle, not the device object). - */ -class CustomDisplayBacklightImpl : public display::BacklightIface { -public: - CustomDisplayBacklightImpl(); - ~CustomDisplayBacklightImpl() override; - - bool set_brightness(uint8_t percent) override; - bool get_brightness(uint8_t &percent) override; - - bool is_light_on_off_supported() override - { - return false; - } - bool set_light_on_off(bool on) override - { - return false; - } - bool is_light_on() const override - { - return false; - } - - bool is_valid() const - { - boost::lock_guard lock(mutex_); - return is_valid_internal(); - } - -private: - bool is_valid_internal() const - { - return handles_ != nullptr; - } - - bool set_brightness_internal(uint8_t percent, bool force = false); - - mutable boost::mutex mutex_; - void *handles_ = nullptr; - uint8_t brightness_ = 0; -}; - -} // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/device.cpp b/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/device.cpp deleted file mode 100644 index 20061dd..0000000 --- a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/device.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "brookesia/hal_custom/macro_configs.h" -#if !BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG -# define BROOKESIA_LOG_DISABLE_DEBUG_TRACE 1 -#endif -#include "private/utils.hpp" -#include "brookesia/lib_utils/function_guard.hpp" -#include "brookesia/hal_adaptor.hpp" -#include "brookesia/hal_custom/display/device.hpp" -#include "display/backlight_impl.hpp" - -using namespace esp_brookesia; - -namespace esp_brookesia::hal { - -bool CustomDisplayDevice::probe() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - return true; -} - -std::vector CustomDisplayDevice::get_interface_specs() const -{ - return { - {display::BacklightIface::NAME, DISPLAY_BACKLIGHT_IMPL_NAME}, - }; -} - -bool CustomDisplayDevice::on_init() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - BROOKESIA_CHECK_FALSE_EXECUTE(init_backlight(), {}, { BROOKESIA_LOGE("Failed to init display backlight"); }); - - BROOKESIA_CHECK_FALSE_RETURN(!interfaces_.empty(), false, "No valid display interfaces found"); - - return true; -} - -void CustomDisplayDevice::on_deinit() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - deinit_backlight(); -} - -bool CustomDisplayDevice::init_backlight() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - if (is_iface_initialized(DISPLAY_BACKLIGHT_IMPL_NAME)) { - BROOKESIA_LOGD("Backlight is already initialized, skip"); - return true; - } - - std::shared_ptr iface = nullptr; - BROOKESIA_CHECK_EXCEPTION_RETURN( - iface = std::make_shared(), false, - "Failed to create backlight interface" - ); - lib_utils::FunctionGuard iface_delete_guard([this, &iface]() { - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - iface.reset(); - }); - - BROOKESIA_CHECK_FALSE_RETURN(iface->is_valid(), false, "Failed to create backlight interface"); - - interfaces_.emplace(DISPLAY_BACKLIGHT_IMPL_NAME, iface); - - iface_delete_guard.release(); - - return true; -} - -void CustomDisplayDevice::deinit_backlight() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - if (!is_iface_initialized(DISPLAY_BACKLIGHT_IMPL_NAME)) { - BROOKESIA_LOGD("Backlight is not initialized, skip"); - return; - } - - interfaces_.erase(DISPLAY_BACKLIGHT_IMPL_NAME); -} - -#if BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE -BROOKESIA_PLUGIN_REGISTER_SINGLETON_WITH_SYMBOL( - Device, CustomDisplayDevice, CustomDisplayDevice::DEVICE_NAME, CustomDisplayDevice::get_instance(), - BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL -); -#endif - -} // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_1_8/board_devices.yaml b/boards/esp32_s3_touch_amoled_1_8/board_devices.yaml index d1faf80..586cfdb 100644 --- a/boards/esp32_s3_touch_amoled_1_8/board_devices.yaml +++ b/boards/esp32_s3_touch_amoled_1_8/board_devices.yaml @@ -6,8 +6,6 @@ devices: version: default dependencies: espressif/esp_io_expander_tca9554: "^2" - brookesia_hal_custom: - override_path: "${BOARD_PATH}/components/brookesia_hal_custom" config: max_pins: 8 # Maximum number of GPIO pins supported output_io_mask: [0, 1, 2, 7] # List of pins configured as output diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/CMakeLists.txt b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/CMakeLists.txt deleted file mode 100644 index e1b1e1b..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# This optional bridge is only compiled by applications using Brookesia display. -# Plain Board Manager consumers do not require the Brookesia HAL adaptor. -if(NOT CONFIG_BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE) - idf_component_register() - return() -endif() - -set(COMPONENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(COMPONENT_INCLUDE_DIRS ${COMPONENT_DIR}/include) -set(COMPONENT_PRIVATE_INCLUDE_DIRS ${COMPONENT_DIR}/src) - -file(GLOB_RECURSE COMPONENT_SRCS_CPP ${COMPONENT_DIR}/src/*.cpp) - -# -# Register Component -# -idf_component_register( - SRCS ${COMPONENT_SRCS_C} ${COMPONENT_SRCS_CPP} - INCLUDE_DIRS ${COMPONENT_INCLUDE_DIRS} - PRIV_INCLUDE_DIRS ${COMPONENT_PRIVATE_INCLUDE_DIRS} - REQUIRES brookesia_hal_adaptor esp_board_manager -) - -if(CONFIG_BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE) - set(BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL custom_display_device_plugin_symbol) - target_compile_definitions(${COMPONENT_LIB} PRIVATE - BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL=${BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL} - ) - target_link_libraries(${COMPONENT_LIB} PRIVATE "-u ${BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL}") -endif() diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/Kconfig b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/Kconfig deleted file mode 100644 index 080ba23..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -menu "ESP-Brookesia: Hal Custom Configurations" - menuconfig BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG - bool "Enable debug or lower level logs" - default n -endmenu diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/idf_component.yml b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/idf_component.yml deleted file mode 100644 index 58888ee..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/idf_component.yml +++ /dev/null @@ -1 +0,0 @@ -version: "0.1.1" diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/include/brookesia/hal_custom.hpp b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/include/brookesia/hal_custom.hpp deleted file mode 100644 index 201d3a1..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/include/brookesia/hal_custom.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "hal_custom/macro_configs.h" -#include "hal_custom/display/device.hpp" diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp deleted file mode 100644 index 2a5f458..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file device.hpp - * @brief Singleton HAL device that aggregates codec-based audio playback and recording for board-managed audio hardware. - */ -#pragma once - -#include -#include -#include -#include "brookesia/hal_interface/device.hpp" - -namespace esp_brookesia::hal { - -/** - * @brief Board-backed custom display device - * - * Obtained via get_instance(). Not copyable or movable. - */ -class CustomDisplayDevice : public Device { -public: - /** @brief Logical device name passed to the base @ref Device constructor. */ - static constexpr const char *DEVICE_NAME = "CustomDisplay"; - /** @brief Registry key for the display backlight HAL implementation (`"CustomDisplay:Backlight"`). */ - static constexpr const char *DISPLAY_BACKLIGHT_IMPL_NAME = "CustomDisplay:Backlight"; - - CustomDisplayDevice(const CustomDisplayDevice &) = delete; - CustomDisplayDevice &operator=(const CustomDisplayDevice &) = delete; - CustomDisplayDevice(CustomDisplayDevice &&) = delete; - CustomDisplayDevice &operator=(CustomDisplayDevice &&) = delete; - - /** - * @brief Returns the process-wide singleton custom display device. - * - * @return Reference to the unique @ref CustomDisplayDevice instance. - */ - static CustomDisplayDevice &get_instance() - { - static CustomDisplayDevice instance; - return instance; - } - -private: - CustomDisplayDevice() - : Device(std::string(DEVICE_NAME)) - { - } - ~CustomDisplayDevice() = default; - - bool probe() override; - std::vector get_interface_specs() const override; - bool on_init() override; - void on_deinit() override; - - bool init_backlight(); - void deinit_backlight(); -}; - -} // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/backlight_impl.cpp b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/backlight_impl.cpp deleted file mode 100644 index 5425e1a..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/backlight_impl.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include "brookesia/hal_custom/macro_configs.h" -#if !BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG -# define BROOKESIA_LOG_DISABLE_DEBUG_TRACE 1 -#endif -#include "private/utils.hpp" -#include "esp_lcd_panel_ops.h" -#include "esp_board_device.h" -#include "esp_board_manager_includes.h" -#include "backlight_impl.hpp" -#include "brookesia/hal_adaptor/display/device.hpp" - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) - -namespace esp_brookesia::hal { - -constexpr uint8_t BRIGHTNESS_DEFAULT = 0; -constexpr uint8_t BRIGHTNESS_MIN = 0; -constexpr uint8_t BRIGHTNESS_MAX = 100; - -namespace { -esp_lcd_panel_io_handle_t get_io_handle(void *handles) -{ - return reinterpret_cast(handles)->io_handle; -} -} // namespace - -CustomDisplayBacklightImpl::CustomDisplayBacklightImpl() - : display::BacklightIface(display::BacklightIface::Info{ - .group_id = DisplayDevice::LCD_GROUP_ID, -}) -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - boost::lock_guard lock(mutex_); - - auto ret = esp_board_manager_init_device_by_name(ESP_BOARD_DEVICE_NAME_DISPLAY_LCD); - BROOKESIA_CHECK_ESP_ERR_EXIT(ret, "Failed to init display LCD"); - - ret = esp_board_manager_get_device_handle(ESP_BOARD_DEVICE_NAME_DISPLAY_LCD, &handles_); - BROOKESIA_CHECK_ESP_ERR_EXIT(ret, "Failed to get handles"); - BROOKESIA_CHECK_NULL_EXIT(handles_, "Failed to get handles"); - - BROOKESIA_CHECK_FALSE_EXIT(set_brightness_internal(BRIGHTNESS_DEFAULT, true), "Failed to set default brightness"); -} - -CustomDisplayBacklightImpl::~CustomDisplayBacklightImpl() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); -} - -bool CustomDisplayBacklightImpl::set_brightness(uint8_t percent) -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - BROOKESIA_LOGD("Params: percent(%1%)", percent); - - boost::lock_guard lock(mutex_); - - return set_brightness_internal(percent, false); -} - -bool CustomDisplayBacklightImpl::get_brightness(uint8_t &percent) -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - boost::lock_guard lock(mutex_); - - BROOKESIA_CHECK_FALSE_RETURN(is_valid_internal(), false, "LCD brightness is not initialized"); - - percent = brightness_; - - return true; -} - -bool CustomDisplayBacklightImpl::set_brightness_internal(uint8_t percent, bool force) -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - BROOKESIA_LOGD("Params: percent(%1%), force(%2%)", percent, force); - - BROOKESIA_CHECK_FALSE_RETURN(is_valid_internal(), false, "LCD brightness is not initialized"); - - auto percent_clamped = std::clamp(percent, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - if (percent_clamped != percent) { - BROOKESIA_LOGW( - "Target brightness(%1%) is out of range [%2%, %3%], clamp to %4%", percent, BRIGHTNESS_MIN, BRIGHTNESS_MAX, - percent_clamped - ); - } - - if (!force && (percent_clamped == brightness_)) { - BROOKESIA_LOGD("Brightness is already %1%, skip", percent_clamped); - return true; - } - - uint8_t data[1] = {static_cast((255 * percent_clamped) / 100)}; - int lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; - auto ret = esp_lcd_panel_io_tx_param(get_io_handle(handles_), lcd_cmd, data, sizeof(data)); - BROOKESIA_CHECK_ESP_ERR_RETURN(ret, false, "Failed to transmit brightness command"); - - brightness_ = percent_clamped; - - BROOKESIA_LOGI("Set brightness: %1%", brightness_); - - return true; -} - -} // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/backlight_impl.hpp b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/backlight_impl.hpp deleted file mode 100644 index 25e1f3d..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/backlight_impl.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include -#include "boost/thread/lock_guard.hpp" -#include "boost/thread/mutex.hpp" -#include "brookesia/hal_interface/interfaces/display/backlight.hpp" - -namespace esp_brookesia::hal { - -/** - * @brief Board-backed backlight HAL interface (holds LEDC handle, not the device object). - */ -class CustomDisplayBacklightImpl : public display::BacklightIface { -public: - CustomDisplayBacklightImpl(); - ~CustomDisplayBacklightImpl() override; - - bool set_brightness(uint8_t percent) override; - bool get_brightness(uint8_t &percent) override; - - bool is_light_on_off_supported() override - { - return false; - } - bool set_light_on_off(bool on) override - { - return false; - } - bool is_light_on() const override - { - return false; - } - - bool is_valid() const - { - boost::lock_guard lock(mutex_); - return is_valid_internal(); - } - -private: - bool is_valid_internal() const - { - return handles_ != nullptr; - } - - bool set_brightness_internal(uint8_t percent, bool force = false); - - mutable boost::mutex mutex_; - void *handles_ = nullptr; - uint8_t brightness_ = 0; -}; - -} // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/device.cpp b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/device.cpp deleted file mode 100644 index 20061dd..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/display/device.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "brookesia/hal_custom/macro_configs.h" -#if !BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG -# define BROOKESIA_LOG_DISABLE_DEBUG_TRACE 1 -#endif -#include "private/utils.hpp" -#include "brookesia/lib_utils/function_guard.hpp" -#include "brookesia/hal_adaptor.hpp" -#include "brookesia/hal_custom/display/device.hpp" -#include "display/backlight_impl.hpp" - -using namespace esp_brookesia; - -namespace esp_brookesia::hal { - -bool CustomDisplayDevice::probe() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - return true; -} - -std::vector CustomDisplayDevice::get_interface_specs() const -{ - return { - {display::BacklightIface::NAME, DISPLAY_BACKLIGHT_IMPL_NAME}, - }; -} - -bool CustomDisplayDevice::on_init() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - BROOKESIA_CHECK_FALSE_EXECUTE(init_backlight(), {}, { BROOKESIA_LOGE("Failed to init display backlight"); }); - - BROOKESIA_CHECK_FALSE_RETURN(!interfaces_.empty(), false, "No valid display interfaces found"); - - return true; -} - -void CustomDisplayDevice::on_deinit() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - deinit_backlight(); -} - -bool CustomDisplayDevice::init_backlight() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - if (is_iface_initialized(DISPLAY_BACKLIGHT_IMPL_NAME)) { - BROOKESIA_LOGD("Backlight is already initialized, skip"); - return true; - } - - std::shared_ptr iface = nullptr; - BROOKESIA_CHECK_EXCEPTION_RETURN( - iface = std::make_shared(), false, - "Failed to create backlight interface" - ); - lib_utils::FunctionGuard iface_delete_guard([this, &iface]() { - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - iface.reset(); - }); - - BROOKESIA_CHECK_FALSE_RETURN(iface->is_valid(), false, "Failed to create backlight interface"); - - interfaces_.emplace(DISPLAY_BACKLIGHT_IMPL_NAME, iface); - - iface_delete_guard.release(); - - return true; -} - -void CustomDisplayDevice::deinit_backlight() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - if (!is_iface_initialized(DISPLAY_BACKLIGHT_IMPL_NAME)) { - BROOKESIA_LOGD("Backlight is not initialized, skip"); - return; - } - - interfaces_.erase(DISPLAY_BACKLIGHT_IMPL_NAME); -} - -#if BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE -BROOKESIA_PLUGIN_REGISTER_SINGLETON_WITH_SYMBOL( - Device, CustomDisplayDevice, CustomDisplayDevice::DEVICE_NAME, CustomDisplayDevice::get_instance(), - BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL -); -#endif - -} // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/private/utils.hpp b/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/private/utils.hpp deleted file mode 100644 index 89e5260..0000000 --- a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/src/private/utils.hpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#undef BROOKESIA_LOG_TAG -#define BROOKESIA_LOG_TAG "HalAdptExtra" -#include "brookesia/lib_utils/log.hpp" -#include "brookesia/lib_utils/check.hpp" diff --git a/boards/esp32_s3_touch_amoled_2_16/board_devices.yaml b/boards/esp32_s3_touch_amoled_2_16/board_devices.yaml index 2a2d3cb..79d8e7e 100644 --- a/boards/esp32_s3_touch_amoled_2_16/board_devices.yaml +++ b/boards/esp32_s3_touch_amoled_2_16/board_devices.yaml @@ -67,8 +67,6 @@ devices: version: default dependencies: espressif/esp_lcd_co5300: "^2" - brookesia_hal_custom: - override_path: "${BOARD_PATH}/components/brookesia_hal_custom" config: x_max: 480 y_max: 480 diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/CMakeLists.txt b/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/CMakeLists.txt deleted file mode 100644 index e1b1e1b..0000000 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# This optional bridge is only compiled by applications using Brookesia display. -# Plain Board Manager consumers do not require the Brookesia HAL adaptor. -if(NOT CONFIG_BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE) - idf_component_register() - return() -endif() - -set(COMPONENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(COMPONENT_INCLUDE_DIRS ${COMPONENT_DIR}/include) -set(COMPONENT_PRIVATE_INCLUDE_DIRS ${COMPONENT_DIR}/src) - -file(GLOB_RECURSE COMPONENT_SRCS_CPP ${COMPONENT_DIR}/src/*.cpp) - -# -# Register Component -# -idf_component_register( - SRCS ${COMPONENT_SRCS_C} ${COMPONENT_SRCS_CPP} - INCLUDE_DIRS ${COMPONENT_INCLUDE_DIRS} - PRIV_INCLUDE_DIRS ${COMPONENT_PRIVATE_INCLUDE_DIRS} - REQUIRES brookesia_hal_adaptor esp_board_manager -) - -if(CONFIG_BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE) - set(BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL custom_display_device_plugin_symbol) - target_compile_definitions(${COMPONENT_LIB} PRIVATE - BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL=${BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL} - ) - target_link_libraries(${COMPONENT_LIB} PRIVATE "-u ${BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL}") -endif() diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/Kconfig b/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/Kconfig deleted file mode 100644 index 080ba23..0000000 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -menu "ESP-Brookesia: Hal Custom Configurations" - menuconfig BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG - bool "Enable debug or lower level logs" - default n -endmenu diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/idf_component.yml b/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/idf_component.yml deleted file mode 100644 index ae3e08a..0000000 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/idf_component.yml +++ /dev/null @@ -1 +0,0 @@ -version: "0.1.0" diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom.hpp b/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom.hpp deleted file mode 100644 index 201d3a1..0000000 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "hal_custom/macro_configs.h" -#include "hal_custom/display/device.hpp" diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h b/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h deleted file mode 100644 index 6659b85..0000000 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include "sdkconfig.h" - -/** - * @brief Default log tag used by the component. - */ -#define BROOKESIA_HAL_CUSTOM_LOG_TAG "HalCustom" - -#if !defined(BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG) -# if defined(CONFIG_BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG) -# define BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG CONFIG_BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG -# else -# define BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG (0) -# endif -#endif diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/backlight_impl.cpp b/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/backlight_impl.cpp deleted file mode 100644 index 5425e1a..0000000 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/backlight_impl.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include "brookesia/hal_custom/macro_configs.h" -#if !BROOKESIA_HAL_CUSTOM_ENABLE_DEBUG_LOG -# define BROOKESIA_LOG_DISABLE_DEBUG_TRACE 1 -#endif -#include "private/utils.hpp" -#include "esp_lcd_panel_ops.h" -#include "esp_board_device.h" -#include "esp_board_manager_includes.h" -#include "backlight_impl.hpp" -#include "brookesia/hal_adaptor/display/device.hpp" - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) - -namespace esp_brookesia::hal { - -constexpr uint8_t BRIGHTNESS_DEFAULT = 0; -constexpr uint8_t BRIGHTNESS_MIN = 0; -constexpr uint8_t BRIGHTNESS_MAX = 100; - -namespace { -esp_lcd_panel_io_handle_t get_io_handle(void *handles) -{ - return reinterpret_cast(handles)->io_handle; -} -} // namespace - -CustomDisplayBacklightImpl::CustomDisplayBacklightImpl() - : display::BacklightIface(display::BacklightIface::Info{ - .group_id = DisplayDevice::LCD_GROUP_ID, -}) -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - boost::lock_guard lock(mutex_); - - auto ret = esp_board_manager_init_device_by_name(ESP_BOARD_DEVICE_NAME_DISPLAY_LCD); - BROOKESIA_CHECK_ESP_ERR_EXIT(ret, "Failed to init display LCD"); - - ret = esp_board_manager_get_device_handle(ESP_BOARD_DEVICE_NAME_DISPLAY_LCD, &handles_); - BROOKESIA_CHECK_ESP_ERR_EXIT(ret, "Failed to get handles"); - BROOKESIA_CHECK_NULL_EXIT(handles_, "Failed to get handles"); - - BROOKESIA_CHECK_FALSE_EXIT(set_brightness_internal(BRIGHTNESS_DEFAULT, true), "Failed to set default brightness"); -} - -CustomDisplayBacklightImpl::~CustomDisplayBacklightImpl() -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); -} - -bool CustomDisplayBacklightImpl::set_brightness(uint8_t percent) -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - BROOKESIA_LOGD("Params: percent(%1%)", percent); - - boost::lock_guard lock(mutex_); - - return set_brightness_internal(percent, false); -} - -bool CustomDisplayBacklightImpl::get_brightness(uint8_t &percent) -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - boost::lock_guard lock(mutex_); - - BROOKESIA_CHECK_FALSE_RETURN(is_valid_internal(), false, "LCD brightness is not initialized"); - - percent = brightness_; - - return true; -} - -bool CustomDisplayBacklightImpl::set_brightness_internal(uint8_t percent, bool force) -{ - BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); - - BROOKESIA_LOGD("Params: percent(%1%), force(%2%)", percent, force); - - BROOKESIA_CHECK_FALSE_RETURN(is_valid_internal(), false, "LCD brightness is not initialized"); - - auto percent_clamped = std::clamp(percent, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - if (percent_clamped != percent) { - BROOKESIA_LOGW( - "Target brightness(%1%) is out of range [%2%, %3%], clamp to %4%", percent, BRIGHTNESS_MIN, BRIGHTNESS_MAX, - percent_clamped - ); - } - - if (!force && (percent_clamped == brightness_)) { - BROOKESIA_LOGD("Brightness is already %1%, skip", percent_clamped); - return true; - } - - uint8_t data[1] = {static_cast((255 * percent_clamped) / 100)}; - int lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; - auto ret = esp_lcd_panel_io_tx_param(get_io_handle(handles_), lcd_cmd, data, sizeof(data)); - BROOKESIA_CHECK_ESP_ERR_RETURN(ret, false, "Failed to transmit brightness command"); - - brightness_ = percent_clamped; - - BROOKESIA_LOGI("Set brightness: %1%", brightness_); - - return true; -} - -} // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/private/utils.hpp b/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/private/utils.hpp deleted file mode 100644 index 89e5260..0000000 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/private/utils.hpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#undef BROOKESIA_LOG_TAG -#define BROOKESIA_LOG_TAG "HalAdptExtra" -#include "brookesia/lib_utils/log.hpp" -#include "brookesia/lib_utils/check.hpp" diff --git a/ci/markdown-audit.json b/ci/markdown-audit.json index 62f83f2..2f84179 100644 --- a/ci/markdown-audit.json +++ b/ci/markdown-audit.json @@ -34,7 +34,7 @@ { "category": "embedded_upstream", "patterns": [ - "boards/*/components/brookesia_hal_custom/CHANGELOG.md" + "integrations/brookesia_hal_custom/CHANGELOG.md" ] } ] diff --git a/ci/scripts/board_pack.py b/ci/scripts/board_pack.py index eab73ac..28fe910 100644 --- a/ci/scripts/board_pack.py +++ b/ci/scripts/board_pack.py @@ -15,7 +15,7 @@ ROOT = Path(__file__).resolve().parents[2] EXCLUDED = {"ci", "scripts", "docs", "firmware", "examples", "build", - "managed_components", "components", "third_party", "libraries", "dist"} + "managed_components", "components", "third_party", "libraries", "dist", "integrations"} STABLE = re.compile(r"\d+\.\d+\.\d+(?:~\d+)?") @@ -94,7 +94,7 @@ def route(boards, paths): selected.update(direct) else: selected.update(b["board"] for b in boards) - if not (value.startswith(("ci/", "scripts/", ".github/workflows/")) + if not (value.startswith(("ci/", "scripts/", ".github/workflows/", "integrations/", "include/")) or value in {"CMakeLists.txt", "idf_component.yml"}): unknown.append(value) return {"boards": [b for b in boards if b["board"] in selected], @@ -113,10 +113,40 @@ def registry_versions(root): def matrix(root, boards, versions): config = json.loads((root / "ci/versions.json").read_text(encoding="utf-8")) - return {"include": [dict(board=b["board"], target=b["target"], idf=idf, bmgr=v, - component_manager=config["component_manager"][idf], - bmgr_assist=config["bmgr_assist"]) - for b in boards for idf in config["idf"] for v in versions]} + if not set(config.get("brookesia_idf", [])).issubset(config["idf"]): + raise ValueError("Brookesia test versions must be in the main IDF matrix") + cells = [] + profiles = root / "integrations/brookesia_hal_custom/profiles" + for board in boards: + modes = ["none"] + if (profiles / board["board"] / "sdkconfig.defaults").is_file(): + modes.append("brookesia") + for idf in config["idf"]: + for version in versions: + for mode in modes: + if mode == "brookesia" and idf not in config.get("brookesia_idf", []): + continue + cells.append(dict(board=board["board"], target=board["target"], + idf=idf, bmgr=version, integration=mode, + component_manager=config["component_manager"][idf], + bmgr_assist=config["bmgr_assist"])) + return {"include": cells} + + +def configure_integration(root, name): + path = root / "ci/test_app/main/idf_component.yml" + data = load_yaml(path) + if name == "brookesia": + component = root / "integrations/brookesia_hal_custom" + if not (component / "CMakeLists.txt").is_file(): + raise ValueError("Brookesia integration component is missing") + data["dependencies"]["brookesia_hal_custom"] = { + "override_path": "../../../integrations/brookesia_hal_custom"} + elif name == "none": + data["dependencies"].pop("brookesia_hal_custom", None) + else: + raise ValueError("unknown integration") + path.write_text(yaml.safe_dump(data, sort_keys=False), encoding="utf-8") def pin(root, version): @@ -135,6 +165,8 @@ def main(): sub.add_parser("check") pin_parser = sub.add_parser("pin") pin_parser.add_argument("version") + integration = sub.add_parser("integration") + integration.add_argument("name", choices=("none", "brookesia")) plan = sub.add_parser("matrix") scope = plan.add_mutually_exclusive_group(required=True) scope.add_argument("--all", action="store_true") @@ -146,6 +178,9 @@ def main(): if args.command == "pin": pin(args.root, args.version) return 0 + if args.command == "integration": + configure_integration(args.root, args.name) + return 0 boards = discover(args.root) if args.command == "check": print(json.dumps(boards, indent=2)) diff --git a/ci/scripts/test_amoled_brightness.py b/ci/scripts/test_amoled_brightness.py new file mode 100644 index 0000000..1f5166e --- /dev/null +++ b/ci/scripts/test_amoled_brightness.py @@ -0,0 +1,62 @@ +"""Exercise the public brightness command without physical LCD hardware.""" +import pathlib +import subprocess +import tempfile +import unittest + +ROOT = pathlib.Path(__file__).resolve().parents[2] + + +class AmoledBrightnessTests(unittest.TestCase): + def test_qspi_command_scaling_clamping_and_errors(self): + with tempfile.TemporaryDirectory() as directory: + path = pathlib.Path(directory) + (path / 'esp_err.h').write_text('''#pragma once +typedef int esp_err_t; +#define ESP_ERR_INVALID_ARG 258 +''') + (path / 'esp_lcd_panel_io.h').write_text('''#pragma once +#include +#include "esp_err.h" +typedef void *esp_lcd_panel_io_handle_t; +esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t, int, const void *, size_t); +''') + (path / 'test.c').write_text('''#include +#include "waveshare_amoled.h" +static int device, calls, command, result; +static uint8_t value; +esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int cmd, const void *data, size_t size) +{ + assert(io == &device); + assert(size == 1); + calls++; + command = cmd; + value = *(const uint8_t *)data; + return result; +} +int main(void) +{ + assert(waveshare_amoled_set_brightness(NULL, 50) == ESP_ERR_INVALID_ARG); + assert(calls == 0); + const uint8_t percent[] = {0, 1, 50, 100, 255}; + const uint8_t expected[] = {0, 2, 127, 255, 255}; + for (size_t i = 0; i < sizeof(percent); i++) { + assert(waveshare_amoled_set_brightness(&device, percent[i]) == 0); + assert(command == 0x02005100); + assert(value == expected[i]); + } + assert(calls == 5); + result = 73; + assert(waveshare_amoled_set_brightness(&device, 50) == 73); + return 0; +} +''') + subprocess.run(['cc', '-std=c11', '-Wall', '-Wextra', '-Werror', + '-I', str(path), '-I', str(ROOT / 'include'), + str(path / 'test.c'), '-o', str(path / 'test')], + check=True, capture_output=True, text=True) + subprocess.run([str(path / 'test')], check=True) + + +if __name__ == '__main__': + unittest.main() diff --git a/ci/scripts/test_board_pack.py b/ci/scripts/test_board_pack.py index 21f28a1..d44593e 100644 --- a/ci/scripts/test_board_pack.py +++ b/ci/scripts/test_board_pack.py @@ -56,7 +56,7 @@ def cli(self, *args): return result, values def test_discovery_excludes_generated_and_upstream(self): - for root in ('ci', 'managed_components', 'components', 'firmware', 'libraries', '.hidden'): + for root in ('ci', 'managed_components', 'components', 'firmware', 'libraries', 'integrations', '.hidden'): self.add_board(f'{root}/ignored') self.assertEqual(['alpha', 'beta'], [b['board'] for b in bp.discover(self.root)]) @@ -110,7 +110,7 @@ def test_docs_beside_source_select_zero(self): def test_direct_shared_global_and_governance(self): selected = bp.route(self.boards, ['alpha/setup_device.c']) self.assertEqual(['alpha'], [b['board'] for b in selected['boards']]) - for path in ('ci/test_app/main/main.c', 'idf_component.yml', 'ci/versions.json', + for path in ('ci/test_app/main/main.c', 'include/waveshare_amoled.h', 'idf_component.yml', 'ci/versions.json', '.github/workflows/ci.yml', 'ci/scripts/test_board_pack.py'): self.assertEqual(self.boards, bp.route(self.boards, [path])['boards']) for path in ('LICENSE', '.gitignore', '.github/ISSUE_TEMPLATE/bug_report.yml'): @@ -183,6 +183,35 @@ def test_full_matrix_cli_records_exact_tooling(self): {c['component_manager'] for c in cells}) self.assertEqual('true', values['has_builds']) + def test_matrix_only_adds_integration_for_declared_profiles(self): + self.write('integrations/brookesia_hal_custom/profiles/alpha/sdkconfig.defaults', '# profile\n') + result, values = self.cli('matrix', '--all', '--bmgr', '0.7.2') + self.assertEqual(0, result.returncode, result.stderr) + cells = json.loads(values['matrix'])['include'] + self.assertEqual(5, len(cells)) + opt_in = [cell for cell in cells if cell['integration'] == 'brookesia'] + self.assertEqual(1, len(opt_in)) + self.assertEqual({'v6.1'}, {cell['idf'] for cell in opt_in}) + self.assertEqual({'alpha'}, {cell['board'] for cell in opt_in}) + self.assertTrue(bp.route(self.boards, ['integrations/brookesia_hal_custom/README.md'])['docs_only']) + self.assertEqual(self.boards, bp.route(self.boards, ['integrations/brookesia_hal_custom/src/plugin.cpp'])['boards']) + + def test_integration_cli_preserves_pack_and_requires_component(self): + self.write('ci/test_app/main/idf_component.yml', + 'dependencies:\n waveshare_boards:\n override_path: ../../../\n') + result, _ = self.cli('integration', 'brookesia') + self.assertEqual(2, result.returncode) + self.write('integrations/brookesia_hal_custom/CMakeLists.txt', 'idf_component_register()\n') + result, _ = self.cli('integration', 'brookesia') + self.assertEqual(0, result.returncode, result.stderr) + path = self.root / 'ci/test_app/main/idf_component.yml' + deps = bp.load_yaml(path)['dependencies'] + self.assertEqual('../../../', deps['waveshare_boards']['override_path']) + self.assertEqual('../../../integrations/brookesia_hal_custom', deps['brookesia_hal_custom']['override_path']) + result, _ = self.cli('integration', 'none') + self.assertEqual(0, result.returncode, result.stderr) + self.assertEqual({'waveshare_boards'}, set(bp.load_yaml(path)['dependencies'])) + def test_pin_is_exact_and_preserves_pack(self): self.write('ci/test_app/main/idf_component.yml', 'dependencies:\n espressif/esp_board_manager:\n version: "*"\n waveshare_boards:\n override_path: ../../../\n') diff --git a/ci/test_app/main/main.c b/ci/test_app/main/main.c index 465e616..ae62d9f 100644 --- a/ci/test_app/main/main.c +++ b/ci/test_app/main/main.c @@ -1,4 +1,5 @@ #include "esp_board_manager.h" +#include "waveshare_amoled.h" #include "esp_err.h" void app_main(void) diff --git a/ci/versions.json b/ci/versions.json index 48940fa..5cb9f0d 100644 --- a/ci/versions.json +++ b/ci/versions.json @@ -7,5 +7,8 @@ "v5.5.5": "idf-component-manager==2.5.0", "v6.1": "idf-component-manager==3.0.3" }, - "bmgr_assist": "esp-bmgr-assist==0.8.3" + "bmgr_assist": "esp-bmgr-assist==0.8.3", + "brookesia_idf": [ + "v6.1" + ] } diff --git a/docs/BOARDS.md b/docs/BOARDS.md index ea8079a..8fb4d09 100644 --- a/docs/BOARDS.md +++ b/docs/BOARDS.md @@ -41,22 +41,25 @@ expander drivers remain registry dependencies. The migration makes these changes to the imported profiles: - Include `dev_custom.h` explicitly for custom-device registration on Board Manager 0.7.2. -- Separate hardware defaults from the Brookesia application settings. The original - profile is retained at `components/brookesia_hal_custom/sdkconfig.defaults` - inside each board, while `sdkconfig.defaults.board` no longer enables an entire - application or requires its `partitions_16m.csv`. -- Compile the optional Brookesia display bridge only when the application enables - `CONFIG_BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE`. A plain Board Manager - application does not need the HAL adaptor. A Brookesia application must supply - that dependency and choose compatible application defaults and partitions; - the retained profile is reference input, not a standalone application. +- Extract the unchanged QSPI brightness command into the public + `waveshare_amoled_set_brightness()` helper. Both ordinary applications and the + optional framework adapter can use it without duplicating the hardware command. +- Keep only hardware defaults in `sdkconfig.defaults.board`. Applications choose + their own feature settings and partition layout. +- Consolidate the three Brookesia brightness plugins into one optional component + under `integrations/brookesia_hal_custom/`, with the original three application + profiles under its `profiles/` directory. Board YAML no longer selects a + framework plugin automatically. See [explicit integration](INTEGRATIONS.md). - Disable automatic SD formatting after mount failure on the 1.8 and 2.16 boards. Mount failure is reported without erasing an existing card. - Remove duplicate YAML keys with identical values and correct stale pin comments. -The imported PMU rail and charging initialization remains unchanged. The optional -Brookesia bridge and application profile preserve integration source, but the -full Brookesia application is not part of this repository's build matrix. +The imported PMU rail and charging initialization remains unchanged. Display, +touch, audio, SD, peripheral configuration, and panel initialization are retained +in each board directory. The shared integration keeps the brightness methods, +plugin/interface names, display group, mutex, command format, and default values. +The AXP2101 implementation remains board-local because the 1.8 setup also uses +its GPIO expander; merging those paths is a separate hardware change. ## Hardware reference checks @@ -112,7 +115,7 @@ physical display/touch test after implementation. Brookesia's board package carries Apache-2.0; individual imported files retain SPDX notices, including CC0-1.0 on setup code. Preserve the original copyright -headers. The upstream bridge changelog remains upstream-owned and untranslated. +headers. The imported integration changelog remains upstream-owned and unchanged. Managed drivers retain their respective licenses; this pack does not relicense them. See [the upstream package license](https://github.com/espressif/esp-brookesia/blob/6a087b6d76e989802b72fdb835928b273af76af8/hal/brookesia_hal_boards/license.txt) and [CC0-1.0 terms](https://creativecommons.org/publicdomain/zero/1.0/legalcode.en). diff --git a/docs/BOARDS_ZH.md b/docs/BOARDS_ZH.md index 687a4c6..3967034 100644 --- a/docs/BOARDS_ZH.md +++ b/docs/BOARDS_ZH.md @@ -37,18 +37,19 @@ boards/ 本次对导入配置做了以下适配: - 显式包含 `dev_custom.h`,适配 Board Manager 0.7.2 的自定义设备注册接口。 -- 分离硬件默认配置与 Brookesia 应用配置。原完整配置保留在各板卡内部的 - `components/brookesia_hal_custom/sdkconfig.defaults`;`sdkconfig.defaults.board` - 不再启用整个应用,也不强制依赖应用的 `partitions_16m.csv`。 -- 仅在应用启用 `CONFIG_BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE` 时编译可选的 - Brookesia 显示适配组件。普通 Board Manager 应用不需要 HAL adaptor。 - Brookesia 应用需自行提供该依赖,并选择配套应用配置及分区表;保留的配置是参考输入, - 不是独立应用。 +- 将原有 QSPI 亮度命令提取为公共函数 `waveshare_amoled_set_brightness()`, + 普通应用与可选框架适配均可调用,硬件命令无需重复实现。 +- `sdkconfig.defaults.board` 仅保留硬件默认配置,由应用自行选择功能配置和分区表。 +- 将三份 Brookesia 调光插件合并到一份可选组件 `integrations/brookesia_hal_custom/`, + 三块板卡的原应用配置分别保存在其 `profiles/` 目录。板卡 YAML 不再自动选择框架插件, + 应用可[显式接入](INTEGRATIONS_ZH.md)。 - 将 1.8、2.16 的 SD 挂载失败自动格式化关闭,挂载失败会报错,不会清空已有卡片。 - 删除值相同的重复 YAML 键,修正过时的引脚注释。 -导入的 PMU 电源轨及充电初始化保持不变。可选的 Brookesia 组件与配置保留了原集成源码, -但完整 Brookesia 应用不属于本仓库编译矩阵。 +导入的 PMU 电源轨及充电初始化保持不变。显示、触摸、音频、SD、外设配置和面板初始化 +继续保存在各板卡目录。共用集成保留原调光方法、插件与接口名称、显示分组、线程互斥、 +命令格式及默认值。AXP2101 实现继续随板卡维护,因为 1.8 的初始化还涉及 GPIO 扩展器, +合并这些路径属于另一项硬件行为修改。 ## 硬件资料核对 @@ -96,7 +97,6 @@ CST816S 是兼容驱动的 API 名称,V2 实际安装的是 CST820。 ## 来源许可证 Brookesia 板卡包采用 Apache-2.0,导入文件保留原 SPDX 声明,包括初始化代码中的 CC0-1.0。 -请保留原版权头。上游显示适配组件的更新日志保持原名和原文。 -托管驱动遵循各自的许可证,本组件包不改变其授权。 +请保留原版权头。导入的集成更新日志保持上游原文。托管驱动遵循各自的许可证,本组件包不改变其授权。 详见[上游板卡包许可证](https://github.com/espressif/esp-brookesia/blob/6a087b6d76e989802b72fdb835928b273af76af8/hal/brookesia_hal_boards/license.txt)及 [CC0-1.0 条款](https://creativecommons.org/publicdomain/zero/1.0/legalcode.en)。 diff --git a/docs/CI.md b/docs/CI.md index 8ad4440..e7bba14 100644 --- a/docs/CI.md +++ b/docs/CI.md @@ -16,7 +16,8 @@ Registry lookup failures fail the job. Each matrix entry records an exact versio The initial Board Manager floor is **0.7.2**, matching the reference board-pack template. The current floor and latest resolve to the same version, giving eight -builds for four boards across the two IDF lines. Keep the floor until a deliberate compatibility change +plain board builds across the two IDF lines plus three optional Brookesia adapter +builds on IDF 6.1, eleven builds in total. Keep the floor until a deliberate compatibility change is tested. Unsupported catalog profiles or generation failures fail CI; they are not counted as successful builds. @@ -34,6 +35,13 @@ Use `boards//` inside the pack: local scanning begins at the application's `components/` root, so adding another chip directory exceeds its three-level search limit. See [layout and source evidence](BOARDS.md). +The optional adapter uses HAL interface/lib_utils 0.8.2. Upstream lib_utils 0.8 +requires IDF 6.0–6.2, so `ci/versions.json` declares its native IDF test line in +`brookesia_idf`. The ordinary board builds still cover both lines. The three +preserved application profiles identify the boards with this additional test; +full application profiles are not applied by the standalone adapter compile test. +See [integration coverage and upstream constraints](INTEGRATIONS.md). + ## Change routing The lightweight metadata, unit-test, navigation, and packaging checks run on every @@ -44,7 +52,7 @@ PR. `Board pack checks` is the stable aggregate status suitable for branch prote | Root or nested Markdown, documentation images | None | | Issue forms, license, ignore rules | None | | Files inside one board directory | That board | -| CI scripts, tests, workflows, root manifest or CMake | All boards | +| CI scripts, tests, workflows, integrations, root manifest or CMake | All boards | | Deleted or renamed board paths | Both sides are considered; removed paths can select all remaining boards | | Firmware documentation, source, binary, archive | Reported separately; no board build | | Unrecognized non-documentation input | All boards; path reported for review | @@ -74,6 +82,7 @@ python scripts/update_supported_boards_table.py --check python ci/scripts/check_docs.py python ci/scripts/board_pack.py matrix --all python ci/scripts/board_pack.py pin 0.7.2 +python ci/scripts/board_pack.py integration none idf.py -C ci/test_app bmgr -l idf.py -C ci/test_app bmgr -b esp32_s3_touch_lcd_7 idf.py -C ci/test_app build @@ -97,7 +106,7 @@ Board Manager-selected I2C address and delegates to the managed driver. Successful compilation proves API and generated-code compatibility, not wiring, PSRAM provisioning, touch reset sequencing, or physical operation. Official schematic links and the AMOLED migration checks are recorded in -[board notes](BOARDS.md). Physical operation and the full Brookesia application +[board notes](BOARDS.md). Physical operation and application-level integration remain separate validation steps. Primary references: [IDF v5.5.5](https://github.com/espressif/esp-idf/releases/tag/v5.5.5), diff --git a/docs/CI_ZH.md b/docs/CI_ZH.md index e38d422..5bb6150 100644 --- a/docs/CI_ZH.md +++ b/docs/CI_ZH.md @@ -13,7 +13,8 @@ 相同版本合并。组件库查询失败会使任务失败,每个矩阵项均记录明确版本。 Board Manager 初始最低版本为 **0.7.2**,与参考板卡包模板一致。 -当前最低版与最新版相同,因此四块板卡在两个 IDF 版本线上共八次编译。 +当前最低版与最新版相同,普通板卡模式在两个 IDF 版本线上共八项编译, +另加三个 AMOLED 型号在 IDF 6.1 下的可选 Brookesia 适配测试,总计十一项。 调整最低版本前需要明确兼容性变更并测试。 不支持的芯片能力配置或生成失败会使 CI 失败,不会被计为编译成功。 @@ -27,6 +28,11 @@ Board Manager 0.7.2 可在托管安装、`components/` 本地克隆和清单 `ov 组件包内采用 `boards/<完整型号>/`:本地扫描从应用的 `components/` 根目录开始, 再增加一层芯片目录会超过其三层搜索限制。详见[目录与源码依据](BOARDS_ZH.md)。 +可选适配使用 HAL interface / lib_utils 0.8.2。上游 lib_utils 0.8 要求 IDF 6.0–6.2, +因此 `ci/versions.json` 通过 `brookesia_idf` 声明其原生支持的测试版本线。 +普通板卡模式仍覆盖两个版本线,三个保留的应用配置标识需要额外适配测试的板卡。 +独立适配编译不会套用完整应用配置。详见[集成覆盖与上游约束](INTEGRATIONS_ZH.md)。 + ## 变更路由 每个 PR 都运行轻量的元数据、单元测试、导航和打包检查。 @@ -37,7 +43,7 @@ Board Manager 0.7.2 可在托管安装、`components/` 本地克隆和清单 `ov | 根目录或嵌套 Markdown、文档图片 | 不编译 | | Issue 表单、许可证、忽略规则 | 不编译 | | 单个板卡目录内的文件 | 对应板卡 | -| CI 脚本、测试、工作流、根清单或 CMake | 全部板卡 | +| CI 脚本、测试、工作流、集成组件、根清单或 CMake | 全部板卡 | | 删除或重命名板卡路径 | 同时考虑新旧路径;已移除路径可能选择全部剩余板卡 | | 固件文档、源码、二进制、归档 | 单独报告,不触发板卡编译 | | 未识别的非文档输入 | 全部板卡,并报告路径供检查 | @@ -64,6 +70,7 @@ python scripts/update_supported_boards_table.py --check python ci/scripts/check_docs.py python ci/scripts/board_pack.py matrix --all python ci/scripts/board_pack.py pin 0.7.2 +python ci/scripts/board_pack.py integration none idf.py -C ci/test_app bmgr -l idf.py -C ci/test_app bmgr -b esp32_s3_touch_lcd_7 idf.py -C ci/test_app build @@ -83,7 +90,7 @@ GT911 驱动继续使用板卡原有的托管依赖 **1.2.1** 约束;更换版 编译成功证明 API 和生成代码兼容,不证明接线、PSRAM 配置、触摸复位时序或实机运行正确。 官方原理图链接与 AMOLED 迁移核对内容见[板卡说明](BOARDS_ZH.md)。 -实机运行和完整 Brookesia 应用需要分别验证。 +实机运行和应用层集成需要分别验证。 主要资料:[IDF v5.5.5](https://github.com/espressif/esp-idf/releases/tag/v5.5.5)、 [IDF v6.1](https://github.com/espressif/esp-idf/releases/tag/v6.1)、 diff --git a/docs/INTEGRATIONS.md b/docs/INTEGRATIONS.md new file mode 100644 index 0000000..4480a5b --- /dev/null +++ b/docs/INTEGRATIONS.md @@ -0,0 +1,125 @@ +# AMOLED brightness and optional integrations + +[简体中文](INTEGRATIONS_ZH.md) · [Home](../README.md) · [Board layout](BOARDS.md) + +## Brightness without Brookesia + +The public `waveshare_amoled_set_brightness(io, percent)` helper is available in +`include/waveshare_amoled.h`. It sends the original QSPI brightness command for +the supported CO5300/SH8601 panels without a Brookesia dependency. After board +initialization, an ordinary application can use the selected display's IO handle: + +```c +#include "esp_board_manager.h" +#include "dev_display_lcd.h" +#include "waveshare_amoled.h" + +// After esp_board_manager_init() succeeds for a supported AMOLED board: +dev_display_lcd_handles_t *display = NULL; +ESP_ERROR_CHECK(esp_board_manager_get_device_handle("display_lcd", (void **)&display)); +ESP_ERROR_CHECK(waveshare_amoled_set_brightness(display->io_handle, 75)); +``` + +The function clamps percentages above 100 and returns the LCD IO error on failure. +It has no cached state; the optional framework adapter below retains the original +cached getter, mutex, and interface lifecycle. RGB LCD boards do not use this +QSPI AMOLED command. + +## Brookesia AMOLED brightness + +`integrations/brookesia_hal_custom/` provides one shared adapter for the 1.75C, +1.8 V1, and 2.16 AMOLED profiles. It replaces their three identical brightness +implementations. Board discovery and hardware initialization use `boards/` and +do not select this component. Applications opt in when they need Brookesia HAL +brightness control. + +The shared adapter preserves: + +- Device name `CustomDisplay`, interface implementation `CustomDisplay:Backlight`, + and display group `display_lcd`. +- `set_brightness()` and `get_brightness()`, clamping to 0–100 percent and converting + to the panel's 0–255 brightness command (`0x51` over QSPI) through the public helper. +- The mutex, unchanged-command suppression, error propagation, and initialization + behavior. The plugin starts at 0 percent; the application then chooses brightness. + `get_brightness()` returns the last successfully set value, not a hardware readback. +- The original unsupported result for separate light on/off methods. + +The ordinary panel setup retains its existing initial-brightness command. The +plugin is a framework interface adapter, not a replacement panel or PMU driver. + +## Explicit application setup + +Use **ESP-IDF 6.1** for the optional adapter. Brookesia HAL interface **0.8.2** +and its lib_utils **0.8.2** dependency are tested. Upstream lib_utils 0.8 requires +IDF **6.0 through 6.2**; it cannot resolve on IDF 5.5. This upstream framework +requirement does not apply to the ordinary board pack, which continues to build +on IDF 5.5.5 and 6.1. See the +[upstream dependency contract](https://github.com/espressif/esp-brookesia/blob/6a087b6d76e989802b72fdb835928b273af76af8/utils/brookesia_lib_utils/idf_component.yml). + +For the local clone layout in the [quick start](../README.md#quick-start), add +this dependency to the application's `main/idf_component.yml`: + +```yaml +dependencies: + brookesia_hal_custom: + override_path: ../components/waveshare_boards/integrations/brookesia_hal_custom +``` + +Merge it with existing dependencies. Resolve dependencies, select the matching +AMOLED board, and build the application. Do not add this adapter dependency to +`board_devices.yaml`. Explicit component selection registers the plugin under +its original name; applications use their normal HAL interface lookup. + +The adapter directly uses `brookesia_hal_interface` and Board Manager. It no +longer includes the full `brookesia_hal_adaptor` solely for the `display_lcd` +group constant. This keeps the standalone plugin independent of the adaptor's +Board Manager version constraint. + +A complete Brookesia application still needs its own dependency review: +[HAL adaptor 0.8.4](https://github.com/espressif/esp-brookesia/blob/6a087b6d76e989802b72fdb835928b273af76af8/hal/brookesia_hal_adaptor/idf_component.yml) +requires Board Manager `0.5.*` when display is enabled, while this board pack +requires `>=0.7.2`. That upstream constraint is not changed here. Passing the +standalone interface-adapter test does not claim that an unmodified full +Brookesia application resolves with this pack. + +## Preserved application profiles + +The original Brookesia application defaults are retained separately: + +```text +integrations/brookesia_hal_custom/profiles/ + esp32_s3_touch_amoled_1_75c/sdkconfig.defaults + esp32_s3_touch_amoled_1_8/sdkconfig.defaults + esp32_s3_touch_amoled_2_16/sdkconfig.defaults +``` + +They are opt-in reference configuration, not automatically appended board +settings. They enable application features and refer to `partitions_16m.csv`, +which the consuming application must provide. Choose the matching board profile +and review it against that application's Brookesia version and partition layout. +The ordinary hardware defaults remain beside each board. + +## Validation + +CI builds the plain board pack for all four boards on both IDF lines (eight +builds), then separately enables this adapter for the three AMOLED boards on +IDF 6.1 (three builds). This proves compilation and plugin linkage against the +HAL interfaces. Host tests cover the public command encoding, percentage scaling, +clamping, invalid handles, and IO-error propagation. CI also compiles the public +header with both IDF lines. It does not exercise physical brightness changes or a full +Brookesia application. + +To compile the adapter with the repository's test app in a fresh checkout: + +```bash +python ci/scripts/board_pack.py pin 0.7.2 +python ci/scripts/board_pack.py integration brookesia +idf.py -C ci/test_app bmgr -b esp32_s3_touch_amoled_1_8 +idf.py -C ci/test_app build +``` + +Use `integration none` for the ordinary test mode. Both commands only modify +the test application's manifest; do not commit generated test inputs. + +The implementation and profiles retain their upstream copyright and license +notices. See [source attribution](BOARDS.md#source-licenses). diff --git a/docs/INTEGRATIONS_ZH.md b/docs/INTEGRATIONS_ZH.md new file mode 100644 index 0000000..850f844 --- /dev/null +++ b/docs/INTEGRATIONS_ZH.md @@ -0,0 +1,108 @@ +# AMOLED 调光与可选集成 + +[English](INTEGRATIONS.md) · [首页](../README_ZH.md) · [板卡结构](BOARDS_ZH.md) + +## 不依赖 Brookesia 的调光 + +公共函数 `waveshare_amoled_set_brightness(io, percent)` 位于 +`include/waveshare_amoled.h`,不依赖 Brookesia,使用原有 QSPI 亮度命令控制所支持的 +CO5300 / SH8601 面板。普通应用初始化板卡后,可以使用显示设备的 IO 句柄调光: + +```c +#include "esp_board_manager.h" +#include "dev_display_lcd.h" +#include "waveshare_amoled.h" + +// 在受支持的 AMOLED 板卡上,esp_board_manager_init() 成功之后: +dev_display_lcd_handles_t *display = NULL; +ESP_ERROR_CHECK(esp_board_manager_get_device_handle("display_lcd", (void **)&display)); +ESP_ERROR_CHECK(waveshare_amoled_set_brightness(display->io_handle, 75)); +``` + +函数将超过 100 的百分比限制为 100,发送失败时返回 LCD IO 错误。 +它不缓存状态;下面的可选框架适配继续保留原有缓存读取、线程互斥与接口生命周期。 +RGB LCD 板卡不使用这条 QSPI AMOLED 命令。 + +## Brookesia AMOLED 调光 + +`integrations/brookesia_hal_custom/` 为 1.75C、1.8 V1 和 2.16 三个 AMOLED 型号 +提供一份共用适配,替代原来重复的三份亮度实现。板卡发现和硬件初始化使用 `boards/`, +不会自动选择该组件。需要 Brookesia HAL 调光接口的应用可以显式接入。 + +共用适配保留以下行为: + +- 设备名 `CustomDisplay`、接口实现名 `CustomDisplay:Backlight` 和显示分组 `display_lcd`。 +- `set_brightness()`、`get_brightness()`,百分比限制在 0–100,转换成面板的 + 0–255 亮度值,通过公共函数发送原有 QSPI `0x51` 命令。 +- 线程互斥、相同值不重复发送、错误返回与初始化行为。插件初始化亮度仍为 0%, + 后续由应用设置亮度。`get_brightness()` 返回最近成功设置的值,不是从硬件读回。 +- 独立灯光开关接口仍返回不支持,与原实现一致。 + +普通屏幕初始化保留原有的初始亮度命令。该插件负责框架接口适配,不替代面板或 PMU 驱动。 + +## 应用显式接入 + +可选适配使用 **ESP-IDF 6.1**。测试的 Brookesia HAL interface 和 lib_utils 均为 **0.8.2**。 +上游 lib_utils 0.8 要求 IDF **6.0 至 6.2**,无法在 IDF 5.5 下解析依赖。 +这一上游框架限制不影响普通板卡包,普通模式继续覆盖 IDF 5.5.5 和 6.1。 +依据见[上游依赖约定](https://github.com/espressif/esp-brookesia/blob/6a087b6d76e989802b72fdb835928b273af76af8/utils/brookesia_lib_utils/idf_component.yml)。 + +采用[快速开始](../README_ZH.md#quick-start)中的本地克隆结构时,在应用的 +`main/idf_component.yml` 中增加: + +```yaml +dependencies: + brookesia_hal_custom: + override_path: ../components/waveshare_boards/integrations/brookesia_hal_custom +``` + +与已有依赖合并,解析依赖后选择对应 AMOLED 板卡,再编译应用。 +不要把这条依赖加回 `board_devices.yaml`。显式选择组件后,插件以原有名称注册, +应用仍通过正常的 HAL 接口查询方式使用它。 + +适配组件直接依赖 `brookesia_hal_interface` 和 Board Manager,不再仅为引用 +`display_lcd` 分组常量而包含完整的 `brookesia_hal_adaptor`,因此独立插件不受 +adaptor 的 Board Manager 版本约束牵连。 + +完整 Brookesia 应用仍需单独核对依赖: +[HAL adaptor 0.8.4](https://github.com/espressif/esp-brookesia/blob/6a087b6d76e989802b72fdb835928b273af76af8/hal/brookesia_hal_adaptor/idf_component.yml) +启用显示时要求 Board Manager `0.5.*`,而本板卡包要求 `>=0.7.2`。 +本次没有修改该上游约束。独立接口适配编译通过,不代表未修改的完整 Brookesia 应用 +能与本组件包一起解析依赖。 + +## 保留的应用配置 + +原 Brookesia 应用默认配置按型号分别保留: + +```text +integrations/brookesia_hal_custom/profiles/ + esp32_s3_touch_amoled_1_75c/sdkconfig.defaults + esp32_s3_touch_amoled_1_8/sdkconfig.defaults + esp32_s3_touch_amoled_2_16/sdkconfig.defaults +``` + +这些是按需采用的参考配置,不会自动追加到板卡配置中。 +它们会启用应用功能,并引用由应用提供的 `partitions_16m.csv`。 +选择对应板卡配置后,需要结合应用的 Brookesia 版本与分区表核对。 +普通硬件默认配置仍保存在各板卡目录。 + +## 验证范围 + +CI 对四块板卡在两个 IDF 版本线上运行普通模式编译,共八项; +另外在 IDF 6.1 上为三个 AMOLED 型号启用独立适配,共三项。 +它验证 HAL 接口的编译与插件链接。主机测试覆盖公共函数的命令编码、百分比换算、 +范围限制、无效句柄和 IO 错误返回;CI 也会在两个 IDF 版本线上编译公共头文件。 +这些检查不替代实机调光或完整 Brookesia 应用测试。 + +在干净副本中,通过仓库测试应用编译该适配: + +```bash +python ci/scripts/board_pack.py pin 0.7.2 +python ci/scripts/board_pack.py integration brookesia +idf.py -C ci/test_app bmgr -b esp32_s3_touch_amoled_1_8 +idf.py -C ci/test_app build +``` + +普通测试模式使用 `integration none`。命令只修改测试应用的清单,生成的测试输入不应提交。 + +实现和配置保留原有版权及许可证声明,详见[来源说明](BOARDS_ZH.md#来源许可证)。 diff --git a/include/waveshare_amoled.h b/include/waveshare_amoled.h new file mode 100644 index 0000000..30c1542 --- /dev/null +++ b/include/waveshare_amoled.h @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * SPDX-License-Identifier: Apache-2.0 + * + * Extracted from the Waveshare AMOLED brightness adapter in ESP-Brookesia. + */ +#pragma once + +#include +#include "esp_err.h" +#include "esp_lcd_panel_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Set brightness on the supported CO5300/SH8601 QSPI AMOLED panels. + * + * The caller supplies the initialized display's panel IO handle. Values above + * 100 are clamped; zero turns brightness down to zero. This helper has no + * Brookesia dependency or cached state and returns the panel IO result. + */ +static inline esp_err_t waveshare_amoled_set_brightness(esp_lcd_panel_io_handle_t io, uint8_t percent) +{ + if (!io) { + return ESP_ERR_INVALID_ARG; + } + if (percent > 100) { + percent = 100; + } + const uint8_t level = (uint8_t)((255U * percent) / 100U); + const int command = (0x02U << 24) | (0x51U << 8); + return esp_lcd_panel_io_tx_param(io, command, &level, sizeof(level)); +} + +#ifdef __cplusplus +} +#endif diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/CHANGELOG.md b/integrations/brookesia_hal_custom/CHANGELOG.md similarity index 100% rename from boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/CHANGELOG.md rename to integrations/brookesia_hal_custom/CHANGELOG.md diff --git a/integrations/brookesia_hal_custom/CMakeLists.txt b/integrations/brookesia_hal_custom/CMakeLists.txt new file mode 100644 index 0000000..bceba5c --- /dev/null +++ b/integrations/brookesia_hal_custom/CMakeLists.txt @@ -0,0 +1,13 @@ +# This component is selected explicitly by the consuming application. +idf_component_register( + SRCS "src/display/device.cpp" "src/display/backlight_impl.cpp" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "src" + REQUIRES waveshare_boards +) + +target_compile_features(${COMPONENT_LIB} PUBLIC cxx_std_17) +target_compile_definitions(${COMPONENT_LIB} PRIVATE + BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL=custom_display_device_plugin_symbol +) +target_link_libraries(${COMPONENT_LIB} PRIVATE "-u custom_display_device_plugin_symbol") diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/Kconfig b/integrations/brookesia_hal_custom/Kconfig similarity index 100% rename from boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/Kconfig rename to integrations/brookesia_hal_custom/Kconfig diff --git a/integrations/brookesia_hal_custom/idf_component.yml b/integrations/brookesia_hal_custom/idf_component.yml new file mode 100644 index 0000000..94fa444 --- /dev/null +++ b/integrations/brookesia_hal_custom/idf_component.yml @@ -0,0 +1,13 @@ +version: "0.1.1" +description: Optional AMOLED brightness integration for Brookesia HAL interfaces +license: Apache-2.0 +dependencies: + # Brookesia 0.8 lib_utils requires ESP-IDF 6.0 through 6.2. + idf: ">=6.0,<=6.2" + # Keep the interface ABI aligned with the imported Brookesia source. + espressif/brookesia_hal_interface: + version: "0.8.*" + require: public + espressif/esp_board_manager: + version: ">=0.7.2" + require: public diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/include/brookesia/hal_custom.hpp b/integrations/brookesia_hal_custom/include/brookesia/hal_custom.hpp similarity index 100% rename from boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/include/brookesia/hal_custom.hpp rename to integrations/brookesia_hal_custom/include/brookesia/hal_custom.hpp diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp b/integrations/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp similarity index 93% rename from boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp rename to integrations/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp index b797277..17f4585 100644 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp +++ b/integrations/brookesia_hal_custom/include/brookesia/hal_custom/display/device.hpp @@ -6,7 +6,7 @@ /** * @file device.hpp - * @brief Singleton HAL device that aggregates codec-based audio playback and recording for board-managed audio hardware. + * @brief Singleton HAL device providing brightness control for board-managed AMOLED displays. */ #pragma once diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h b/integrations/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h similarity index 100% rename from boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h rename to integrations/brookesia_hal_custom/include/brookesia/hal_custom/macro_configs.h diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/sdkconfig.defaults b/integrations/brookesia_hal_custom/profiles/esp32_s3_touch_amoled_1_75c/sdkconfig.defaults similarity index 100% rename from boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/sdkconfig.defaults rename to integrations/brookesia_hal_custom/profiles/esp32_s3_touch_amoled_1_75c/sdkconfig.defaults diff --git a/boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/sdkconfig.defaults b/integrations/brookesia_hal_custom/profiles/esp32_s3_touch_amoled_1_8/sdkconfig.defaults similarity index 100% rename from boards/esp32_s3_touch_amoled_1_8/components/brookesia_hal_custom/sdkconfig.defaults rename to integrations/brookesia_hal_custom/profiles/esp32_s3_touch_amoled_1_8/sdkconfig.defaults diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/sdkconfig.defaults b/integrations/brookesia_hal_custom/profiles/esp32_s3_touch_amoled_2_16/sdkconfig.defaults similarity index 100% rename from boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/sdkconfig.defaults rename to integrations/brookesia_hal_custom/profiles/esp32_s3_touch_amoled_2_16/sdkconfig.defaults diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/backlight_impl.cpp b/integrations/brookesia_hal_custom/src/display/backlight_impl.cpp similarity index 88% rename from boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/backlight_impl.cpp rename to integrations/brookesia_hal_custom/src/display/backlight_impl.cpp index 5425e1a..a7e0c0d 100644 --- a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/display/backlight_impl.cpp +++ b/integrations/brookesia_hal_custom/src/display/backlight_impl.cpp @@ -12,10 +12,8 @@ #include "esp_lcd_panel_ops.h" #include "esp_board_device.h" #include "esp_board_manager_includes.h" +#include "waveshare_amoled.h" #include "backlight_impl.hpp" -#include "brookesia/hal_adaptor/display/device.hpp" - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) namespace esp_brookesia::hal { @@ -32,7 +30,7 @@ esp_lcd_panel_io_handle_t get_io_handle(void *handles) CustomDisplayBacklightImpl::CustomDisplayBacklightImpl() : display::BacklightIface(display::BacklightIface::Info{ - .group_id = DisplayDevice::LCD_GROUP_ID, + .group_id = ESP_BOARD_DEVICE_NAME_DISPLAY_LCD, }) { BROOKESIA_LOG_TRACE_GUARD_WITH_THIS(); @@ -99,12 +97,7 @@ bool CustomDisplayBacklightImpl::set_brightness_internal(uint8_t percent, bool f return true; } - uint8_t data[1] = {static_cast((255 * percent_clamped) / 100)}; - int lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; - auto ret = esp_lcd_panel_io_tx_param(get_io_handle(handles_), lcd_cmd, data, sizeof(data)); + auto ret = waveshare_amoled_set_brightness(get_io_handle(handles_), percent_clamped); BROOKESIA_CHECK_ESP_ERR_RETURN(ret, false, "Failed to transmit brightness command"); brightness_ = percent_clamped; diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/backlight_impl.hpp b/integrations/brookesia_hal_custom/src/display/backlight_impl.hpp similarity index 93% rename from boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/backlight_impl.hpp rename to integrations/brookesia_hal_custom/src/display/backlight_impl.hpp index 25e1f3d..ca0a64a 100644 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/backlight_impl.hpp +++ b/integrations/brookesia_hal_custom/src/display/backlight_impl.hpp @@ -13,7 +13,7 @@ namespace esp_brookesia::hal { /** - * @brief Board-backed backlight HAL interface (holds LEDC handle, not the device object). + * @brief Board-backed AMOLED brightness HAL interface using the display panel IO handle. */ class CustomDisplayBacklightImpl : public display::BacklightIface { public: diff --git a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/device.cpp b/integrations/brookesia_hal_custom/src/display/device.cpp similarity index 96% rename from boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/device.cpp rename to integrations/brookesia_hal_custom/src/display/device.cpp index 20061dd..5cceead 100644 --- a/boards/esp32_s3_touch_amoled_2_16/components/brookesia_hal_custom/src/display/device.cpp +++ b/integrations/brookesia_hal_custom/src/display/device.cpp @@ -9,7 +9,6 @@ #endif #include "private/utils.hpp" #include "brookesia/lib_utils/function_guard.hpp" -#include "brookesia/hal_adaptor.hpp" #include "brookesia/hal_custom/display/device.hpp" #include "display/backlight_impl.hpp" @@ -89,11 +88,9 @@ void CustomDisplayDevice::deinit_backlight() interfaces_.erase(DISPLAY_BACKLIGHT_IMPL_NAME); } -#if BROOKESIA_HAL_ADAPTOR_ENABLE_DISPLAY_DEVICE BROOKESIA_PLUGIN_REGISTER_SINGLETON_WITH_SYMBOL( Device, CustomDisplayDevice, CustomDisplayDevice::DEVICE_NAME, CustomDisplayDevice::get_instance(), BROOKESIA_HAL_CUSTOM_DISPLAY_DEVICE_PLUGIN_SYMBOL ); -#endif } // namespace esp_brookesia::hal diff --git a/boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/private/utils.hpp b/integrations/brookesia_hal_custom/src/private/utils.hpp similarity index 100% rename from boards/esp32_s3_touch_amoled_1_75c/components/brookesia_hal_custom/src/private/utils.hpp rename to integrations/brookesia_hal_custom/src/private/utils.hpp