mirror of
https://github.com/esphome/esphome.git
synced 2025-08-03 08:57:47 +00:00
Merge branch 'integration' into memory_api
This commit is contained in:
commit
ff1239c2a4
@ -117,22 +117,9 @@ CONF_BLE_ID = "ble_id"
|
|||||||
CONF_IO_CAPABILITY = "io_capability"
|
CONF_IO_CAPABILITY = "io_capability"
|
||||||
CONF_ADVERTISING_CYCLE_TIME = "advertising_cycle_time"
|
CONF_ADVERTISING_CYCLE_TIME = "advertising_cycle_time"
|
||||||
CONF_DISABLE_BT_LOGS = "disable_bt_logs"
|
CONF_DISABLE_BT_LOGS = "disable_bt_logs"
|
||||||
CONF_PREFERRED_PHY = "preferred_phy"
|
|
||||||
|
|
||||||
NO_BLUETOOTH_VARIANTS = [const.VARIANT_ESP32S2]
|
NO_BLUETOOTH_VARIANTS = [const.VARIANT_ESP32S2]
|
||||||
|
|
||||||
# ESP32 variants that support BLE
|
|
||||||
BLE_VARIANTS = {
|
|
||||||
const.VARIANT_ESP32,
|
|
||||||
const.VARIANT_ESP32C3,
|
|
||||||
const.VARIANT_ESP32S3,
|
|
||||||
const.VARIANT_ESP32C6,
|
|
||||||
const.VARIANT_ESP32H2,
|
|
||||||
}
|
|
||||||
|
|
||||||
# ESP32 variants that support 2M PHY
|
|
||||||
BLE_2M_PHY_VARIANTS = BLE_VARIANTS - {const.VARIANT_ESP32}
|
|
||||||
|
|
||||||
esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble")
|
esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble")
|
||||||
ESP32BLE = esp32_ble_ns.class_("ESP32BLE", cg.Component)
|
ESP32BLE = esp32_ble_ns.class_("ESP32BLE", cg.Component)
|
||||||
|
|
||||||
@ -153,13 +140,6 @@ IO_CAPABILITY = {
|
|||||||
"display_yes_no": IoCapability.IO_CAP_IO,
|
"display_yes_no": IoCapability.IO_CAP_IO,
|
||||||
}
|
}
|
||||||
|
|
||||||
BLEPhy = esp32_ble_ns.enum("BLEPhy")
|
|
||||||
BLE_PHY_OPTIONS = {
|
|
||||||
"1m": BLEPhy.BLE_PHY_1M,
|
|
||||||
"2m": BLEPhy.BLE_PHY_2M,
|
|
||||||
"auto": BLEPhy.BLE_PHY_AUTO,
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_power_level_t = cg.global_ns.enum("esp_power_level_t")
|
esp_power_level_t = cg.global_ns.enum("esp_power_level_t")
|
||||||
|
|
||||||
TX_POWER_LEVELS = {
|
TX_POWER_LEVELS = {
|
||||||
@ -173,18 +153,6 @@ TX_POWER_LEVELS = {
|
|||||||
9: esp_power_level_t.ESP_PWR_LVL_P9,
|
9: esp_power_level_t.ESP_PWR_LVL_P9,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def validate_phy(value: str) -> str:
|
|
||||||
"""Validate PHY selection based on ESP32 variant."""
|
|
||||||
variant = get_esp32_variant()
|
|
||||||
if value == "2m" and variant not in BLE_2M_PHY_VARIANTS:
|
|
||||||
raise cv.Invalid(
|
|
||||||
f"2M PHY is not supported on {variant}. "
|
|
||||||
f"Only supported on: {', '.join(sorted(BLE_2M_PHY_VARIANTS))}"
|
|
||||||
)
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.Schema(
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(ESP32BLE),
|
cv.GenerateID(): cv.declare_id(ESP32BLE),
|
||||||
@ -199,10 +167,6 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
cv.SplitDefault(CONF_DISABLE_BT_LOGS, esp32_idf=True): cv.All(
|
cv.SplitDefault(CONF_DISABLE_BT_LOGS, esp32_idf=True): cv.All(
|
||||||
cv.only_with_esp_idf, cv.boolean
|
cv.only_with_esp_idf, cv.boolean
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_PREFERRED_PHY, default="1m"): cv.All(
|
|
||||||
cv.enum(BLE_PHY_OPTIONS, lower=True),
|
|
||||||
validate_phy,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
@ -273,7 +237,6 @@ async def to_code(config):
|
|||||||
cg.add(var.set_enable_on_boot(config[CONF_ENABLE_ON_BOOT]))
|
cg.add(var.set_enable_on_boot(config[CONF_ENABLE_ON_BOOT]))
|
||||||
cg.add(var.set_io_capability(config[CONF_IO_CAPABILITY]))
|
cg.add(var.set_io_capability(config[CONF_IO_CAPABILITY]))
|
||||||
cg.add(var.set_advertising_cycle_time(config[CONF_ADVERTISING_CYCLE_TIME]))
|
cg.add(var.set_advertising_cycle_time(config[CONF_ADVERTISING_CYCLE_TIME]))
|
||||||
cg.add(var.set_preferred_phy(config[CONF_PREFERRED_PHY]))
|
|
||||||
if (name := config.get(CONF_NAME)) is not None:
|
if (name := config.get(CONF_NAME)) is not None:
|
||||||
cg.add(var.set_name(name))
|
cg.add(var.set_name(name))
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
@ -23,35 +23,6 @@ namespace esphome::esp32_ble {
|
|||||||
|
|
||||||
static const char *const TAG = "esp32_ble";
|
static const char *const TAG = "esp32_ble";
|
||||||
|
|
||||||
static const char *phy_mode_to_string(BLEPhy phy) {
|
|
||||||
switch (phy) {
|
|
||||||
case BLE_PHY_1M:
|
|
||||||
return "1M";
|
|
||||||
case BLE_PHY_2M:
|
|
||||||
return "2M";
|
|
||||||
case BLE_PHY_AUTO:
|
|
||||||
return "AUTO";
|
|
||||||
default:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6) || \
|
|
||||||
defined(USE_ESP32_VARIANT_ESP32H2)
|
|
||||||
static uint8_t phy_mode_to_mask(BLEPhy phy) {
|
|
||||||
switch (phy) {
|
|
||||||
case BLE_PHY_1M:
|
|
||||||
return ESP_BLE_GAP_PHY_1M_PREF_MASK;
|
|
||||||
case BLE_PHY_2M:
|
|
||||||
return ESP_BLE_GAP_PHY_2M_PREF_MASK;
|
|
||||||
case BLE_PHY_AUTO:
|
|
||||||
return ESP_BLE_GAP_PHY_1M_PREF_MASK | ESP_BLE_GAP_PHY_2M_PREF_MASK;
|
|
||||||
default:
|
|
||||||
return ESP_BLE_GAP_PHY_1M_PREF_MASK; // Default to 1M
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ESP32BLE::setup() {
|
void ESP32BLE::setup() {
|
||||||
global_ble = this;
|
global_ble = this;
|
||||||
if (!ble_pre_setup_()) {
|
if (!ble_pre_setup_()) {
|
||||||
@ -237,23 +208,6 @@ bool ESP32BLE::ble_setup_() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure PHY settings
|
|
||||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6) || \
|
|
||||||
defined(USE_ESP32_VARIANT_ESP32H2)
|
|
||||||
// Only newer ESP32 variants support PHY configuration
|
|
||||||
if (this->preferred_phy_ != BLE_PHY_AUTO) {
|
|
||||||
uint8_t phy_mask = phy_mode_to_mask(this->preferred_phy_);
|
|
||||||
|
|
||||||
err = esp_ble_gap_set_preferred_default_phy(phy_mask, phy_mask);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGW(TAG, "esp_ble_gap_set_preferred_default_phy failed: %d", err);
|
|
||||||
// Not a fatal error, continue
|
|
||||||
} else {
|
|
||||||
ESP_LOGD(TAG, "Set preferred PHY to %s", phy_mode_to_string(this->preferred_phy_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// BLE takes some time to be fully set up, 200ms should be more than enough
|
// BLE takes some time to be fully set up, 200ms should be more than enough
|
||||||
delay(200); // NOLINT
|
delay(200); // NOLINT
|
||||||
|
|
||||||
@ -563,10 +517,8 @@ void ESP32BLE::dump_config() {
|
|||||||
ESP_LOGCONFIG(TAG,
|
ESP_LOGCONFIG(TAG,
|
||||||
"BLE:\n"
|
"BLE:\n"
|
||||||
" MAC address: %s\n"
|
" MAC address: %s\n"
|
||||||
" IO Capability: %s\n"
|
" IO Capability: %s",
|
||||||
" Preferred PHY: %s",
|
format_mac_address_pretty(mac_address).c_str(), io_capability_s);
|
||||||
format_mac_address_pretty(mac_address).c_str(), io_capability_s,
|
|
||||||
phy_mode_to_string(this->preferred_phy_));
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGCONFIG(TAG, "Bluetooth stack is not enabled");
|
ESP_LOGCONFIG(TAG, "Bluetooth stack is not enabled");
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,6 @@ enum IoCapability {
|
|||||||
IO_CAP_KBDISP = ESP_IO_CAP_KBDISP,
|
IO_CAP_KBDISP = ESP_IO_CAP_KBDISP,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BLEPhy : uint8_t {
|
|
||||||
BLE_PHY_1M = 0x01,
|
|
||||||
BLE_PHY_2M = 0x02,
|
|
||||||
BLE_PHY_AUTO = 0x03,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum BLEComponentState : uint8_t {
|
enum BLEComponentState : uint8_t {
|
||||||
/** Nothing has been initialized yet. */
|
/** Nothing has been initialized yet. */
|
||||||
BLE_COMPONENT_STATE_OFF = 0,
|
BLE_COMPONENT_STATE_OFF = 0,
|
||||||
@ -104,7 +98,6 @@ class BLEStatusEventHandler {
|
|||||||
class ESP32BLE : public Component {
|
class ESP32BLE : public Component {
|
||||||
public:
|
public:
|
||||||
void set_io_capability(IoCapability io_capability) { this->io_cap_ = (esp_ble_io_cap_t) io_capability; }
|
void set_io_capability(IoCapability io_capability) { this->io_cap_ = (esp_ble_io_cap_t) io_capability; }
|
||||||
void set_preferred_phy(BLEPhy phy) { this->preferred_phy_ = phy; }
|
|
||||||
|
|
||||||
void set_advertising_cycle_time(uint32_t advertising_cycle_time) {
|
void set_advertising_cycle_time(uint32_t advertising_cycle_time) {
|
||||||
this->advertising_cycle_time_ = advertising_cycle_time;
|
this->advertising_cycle_time_ = advertising_cycle_time;
|
||||||
@ -177,7 +170,6 @@ class ESP32BLE : public Component {
|
|||||||
// 1-byte aligned members (grouped together to minimize padding)
|
// 1-byte aligned members (grouped together to minimize padding)
|
||||||
BLEComponentState state_{BLE_COMPONENT_STATE_OFF}; // 1 byte (uint8_t enum)
|
BLEComponentState state_{BLE_COMPONENT_STATE_OFF}; // 1 byte (uint8_t enum)
|
||||||
bool enable_on_boot_{}; // 1 byte
|
bool enable_on_boot_{}; // 1 byte
|
||||||
BLEPhy preferred_phy_{BLE_PHY_1M}; // 1 byte (uint8_t enum)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
#include <esp_gap_ble_api.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_ble_client {
|
namespace esp32_ble_client {
|
||||||
|
|
||||||
@ -129,6 +131,25 @@ void BLEClientBase::connect() {
|
|||||||
ESP_LOGI(TAG, "[%d] [%s] 0x%02x Attempting BLE connection", this->connection_index_, this->address_str_.c_str(),
|
ESP_LOGI(TAG, "[%d] [%s] 0x%02x Attempting BLE connection", this->connection_index_, this->address_str_.c_str(),
|
||||||
this->remote_addr_type_);
|
this->remote_addr_type_);
|
||||||
this->paired_ = false;
|
this->paired_ = false;
|
||||||
|
|
||||||
|
// For connections without cache, set fast connection parameters before connecting
|
||||||
|
// This ensures service discovery completes within the 10-second timeout that
|
||||||
|
// some devices like HomeKit BLE sensors enforce
|
||||||
|
if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
|
||||||
|
auto ret = esp_ble_gap_set_prefer_conn_params(this->remote_bda_,
|
||||||
|
0x06, // min_int: 7.5ms
|
||||||
|
0x06, // max_int: 7.5ms
|
||||||
|
0, // latency: 0
|
||||||
|
1000); // timeout: 10s
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gap_set_prefer_conn_params failed: %d", this->connection_index_,
|
||||||
|
this->address_str_.c_str(), ret);
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "[%d] [%s] Set preferred connection params for fast discovery (no cache)", this->connection_index_,
|
||||||
|
this->address_str_.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto ret = esp_ble_gattc_open(this->gattc_if_, this->remote_bda_, this->remote_addr_type_, true);
|
auto ret = esp_ble_gattc_open(this->gattc_if_, this->remote_bda_, this->remote_addr_type_, true);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_open error, status=%d", this->connection_index_, this->address_str_.c_str(),
|
ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_open error, status=%d", this->connection_index_, this->address_str_.c_str(),
|
||||||
@ -278,12 +299,14 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
this->address_str_.c_str(), ret);
|
this->address_str_.c_str(), ret);
|
||||||
}
|
}
|
||||||
this->set_state(espbt::ClientState::CONNECTED);
|
this->set_state(espbt::ClientState::CONNECTED);
|
||||||
|
ESP_LOGI(TAG, "[%d] [%s] Connection open", this->connection_index_, this->address_str_.c_str());
|
||||||
if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
|
if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) {
|
||||||
ESP_LOGI(TAG, "[%d] [%s] Connected", this->connection_index_, this->address_str_.c_str());
|
ESP_LOGI(TAG, "[%d] [%s] Using cached services", this->connection_index_, this->address_str_.c_str());
|
||||||
// only set our state, subclients might have more stuff to do yet.
|
// only set our state, subclients might have more stuff to do yet.
|
||||||
this->state_ = espbt::ClientState::ESTABLISHED;
|
this->state_ = espbt::ClientState::ESTABLISHED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ESP_LOGD(TAG, "[%d] [%s] Searching for services", this->connection_index_, this->address_str_.c_str());
|
||||||
esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id, nullptr);
|
esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id, nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -296,8 +319,15 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
case ESP_GATTC_DISCONNECT_EVT: {
|
case ESP_GATTC_DISCONNECT_EVT: {
|
||||||
if (!this->check_addr(param->disconnect.remote_bda))
|
if (!this->check_addr(param->disconnect.remote_bda))
|
||||||
return false;
|
return false;
|
||||||
ESP_LOGD(TAG, "[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason %d", this->connection_index_,
|
// Check if we were disconnected while waiting for service discovery
|
||||||
this->address_str_.c_str(), param->disconnect.reason);
|
if (param->disconnect.reason == 0x13 && // 0x13 = ESP_GATT_CONN_TERMINATE_PEER
|
||||||
|
this->state_ == espbt::ClientState::CONNECTED) {
|
||||||
|
ESP_LOGW(TAG, "[%d] [%s] Disconnected by remote during service discovery", this->connection_index_,
|
||||||
|
this->address_str_.c_str());
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason 0x%02x", this->connection_index_,
|
||||||
|
this->address_str_.c_str(), param->disconnect.reason);
|
||||||
|
}
|
||||||
this->release_services();
|
this->release_services();
|
||||||
this->set_state(espbt::ClientState::IDLE);
|
this->set_state(espbt::ClientState::IDLE);
|
||||||
break;
|
break;
|
||||||
@ -353,7 +383,23 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
|||||||
ESP_LOGV(TAG, "[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->connection_index_,
|
ESP_LOGV(TAG, "[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->connection_index_,
|
||||||
this->address_str_.c_str(), svc->start_handle, svc->end_handle);
|
this->address_str_.c_str(), svc->start_handle, svc->end_handle);
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "[%d] [%s] Connected", this->connection_index_, this->address_str_.c_str());
|
ESP_LOGI(TAG, "[%d] [%s] Service discovery complete", this->connection_index_, this->address_str_.c_str());
|
||||||
|
|
||||||
|
// For non-cached connections, restore default connection parameters after service discovery
|
||||||
|
// Now that we've discovered all services, we can use more balanced parameters
|
||||||
|
// that save power and reduce interference
|
||||||
|
if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
|
||||||
|
esp_ble_conn_update_params_t conn_params = {0};
|
||||||
|
memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t));
|
||||||
|
conn_params.min_int = 0x0A; // 12.5ms - ESP-IDF default minimum (BTM_BLE_CONN_INT_MIN_DEF)
|
||||||
|
conn_params.max_int = 0x0C; // 15ms - ESP-IDF default maximum (BTM_BLE_CONN_INT_MAX_DEF)
|
||||||
|
conn_params.latency = 0;
|
||||||
|
conn_params.timeout = 600; // 6s - ESP-IDF default timeout (BTM_BLE_CONN_TIMEOUT_DEF)
|
||||||
|
ESP_LOGD(TAG, "[%d] [%s] Restoring default connection parameters after service discovery",
|
||||||
|
this->connection_index_, this->address_str_.c_str());
|
||||||
|
esp_ble_gap_update_conn_params(&conn_params);
|
||||||
|
}
|
||||||
|
|
||||||
this->state_ = espbt::ClientState::ESTABLISHED;
|
this->state_ = espbt::ClientState::ESTABLISHED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,8 @@ from esphome.final_validate import full_config
|
|||||||
|
|
||||||
from . import mipi_dsi_ns, models
|
from . import mipi_dsi_ns, models
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
# Currently only ESP32-P4 is supported, so esp_ldo and psram are required
|
||||||
|
DEPENDENCIES = ["esp32", "esp_ldo", "psram"]
|
||||||
DOMAIN = "mipi_dsi"
|
DOMAIN = "mipi_dsi"
|
||||||
|
|
||||||
LOGGER = logging.getLogger(DOMAIN)
|
LOGGER = logging.getLogger(DOMAIN)
|
||||||
|
@ -533,9 +533,17 @@ void WiFiComponent::check_scanning_finished() {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (a.get_matches() && b.get_matches()) {
|
if (a.get_matches() && b.get_matches()) {
|
||||||
// if both match, check priority
|
// For APs with the same SSID, always prefer stronger signal
|
||||||
|
// This helps with mesh networks and multiple APs
|
||||||
|
if (a.get_ssid() == b.get_ssid()) {
|
||||||
|
return a.get_rssi() > b.get_rssi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// For different SSIDs, check priority first
|
||||||
if (a.get_priority() != b.get_priority())
|
if (a.get_priority() != b.get_priority())
|
||||||
return a.get_priority() > b.get_priority();
|
return a.get_priority() > b.get_priority();
|
||||||
|
// If priorities are equal, prefer stronger signal
|
||||||
|
return a.get_rssi() > b.get_rssi();
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.get_rssi() > b.get_rssi();
|
return a.get_rssi() > b.get_rssi();
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
esp32_ble:
|
esp32_ble:
|
||||||
io_capability: keyboard_only
|
io_capability: keyboard_only
|
||||||
# Default configuration - should use 1m PHY
|
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
esp32_ble:
|
|
||||||
preferred_phy: 2m
|
|
@ -1,2 +0,0 @@
|
|||||||
esp32_ble:
|
|
||||||
preferred_phy: auto
|
|
@ -12,6 +12,8 @@ display:
|
|||||||
#- platform: mipi_dsi
|
#- platform: mipi_dsi
|
||||||
#id: backlight_id
|
#id: backlight_id
|
||||||
|
|
||||||
|
psram:
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
sda: GPIO7
|
sda: GPIO7
|
||||||
scl: GPIO8
|
scl: GPIO8
|
||||||
|
Loading…
x
Reference in New Issue
Block a user