mirror of
https://github.com/esphome/esphome.git
synced 2025-06-15 23:06:58 +02:00
Merge becf44ef59456d59d2275ad10c102024d0b6586c into 07cf6e723bdd93a738bfc033ad9a932c1bf74b09
This commit is contained in:
commit
23070dffb8
@ -436,6 +436,7 @@ esphome/components/sun/* @OttoWinter
|
||||
esphome/components/sun_gtil2/* @Mat931
|
||||
esphome/components/switch/* @esphome/core
|
||||
esphome/components/switch/binary_sensor/* @ssieb
|
||||
esphome/components/sx126x/* @swoboda1337
|
||||
esphome/components/syslog/* @clydebarrow
|
||||
esphome/components/t6615/* @tylermenezes
|
||||
esphome/components/tc74/* @sethgirvan
|
||||
|
323
esphome/components/sx126x/__init__.py
Normal file
323
esphome/components/sx126x/__init__.py
Normal file
@ -0,0 +1,323 @@
|
||||
from esphome import automation, pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import spi
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_BUSY_PIN, CONF_DATA, CONF_FREQUENCY, CONF_ID
|
||||
from esphome.core import TimePeriod
|
||||
|
||||
MULTI_CONF = True
|
||||
CODEOWNERS = ["@swoboda1337"]
|
||||
DEPENDENCIES = ["spi"]
|
||||
|
||||
CONF_SX126X_ID = "sx126x_id"
|
||||
|
||||
CONF_BANDWIDTH = "bandwidth"
|
||||
CONF_BITRATE = "bitrate"
|
||||
CONF_CODING_RATE = "coding_rate"
|
||||
CONF_CRC_ENABLE = "crc_enable"
|
||||
CONF_DEVIATION = "deviation"
|
||||
CONF_DIO1_PIN = "dio1_pin"
|
||||
CONF_HW_VERSION = "hw_version"
|
||||
CONF_MODULATION = "modulation"
|
||||
CONF_ON_PACKET = "on_packet"
|
||||
CONF_PA_POWER = "pa_power"
|
||||
CONF_PA_RAMP = "pa_ramp"
|
||||
CONF_PAYLOAD_LENGTH = "payload_length"
|
||||
CONF_PREAMBLE_DETECT = "preamble_detect"
|
||||
CONF_PREAMBLE_SIZE = "preamble_size"
|
||||
CONF_RST_PIN = "rst_pin"
|
||||
CONF_RX_START = "rx_start"
|
||||
CONF_RF_SWITCH = "rf_switch"
|
||||
CONF_SHAPING = "shaping"
|
||||
CONF_SPREADING_FACTOR = "spreading_factor"
|
||||
CONF_SYNC_VALUE = "sync_value"
|
||||
CONF_TCXO_VOLTAGE = "tcxo_voltage"
|
||||
CONF_TCXO_DELAY = "tcxo_delay"
|
||||
|
||||
sx126x_ns = cg.esphome_ns.namespace("sx126x")
|
||||
SX126x = sx126x_ns.class_("SX126x", cg.Component, spi.SPIDevice)
|
||||
SX126xListener = sx126x_ns.class_("SX126xListener")
|
||||
SX126xBw = sx126x_ns.enum("SX126xBw")
|
||||
SX126xPacketType = sx126x_ns.enum("SX126xPacketType")
|
||||
SX126xTcxoCtrl = sx126x_ns.enum("SX126xTcxoCtrl")
|
||||
SX126xRampTime = sx126x_ns.enum("SX126xRampTime")
|
||||
SX126xPulseShape = sx126x_ns.enum("SX126xPulseShape")
|
||||
SX126xLoraCr = sx126x_ns.enum("SX126xLoraCr")
|
||||
|
||||
BW = {
|
||||
"4_8kHz": SX126xBw.SX126X_BW_4800,
|
||||
"5_8kHz": SX126xBw.SX126X_BW_5800,
|
||||
"7_3kHz": SX126xBw.SX126X_BW_7300,
|
||||
"9_7kHz": SX126xBw.SX126X_BW_9700,
|
||||
"11_7kHz": SX126xBw.SX126X_BW_11700,
|
||||
"14_6kHz": SX126xBw.SX126X_BW_14600,
|
||||
"19_5kHz": SX126xBw.SX126X_BW_19500,
|
||||
"23_4kHz": SX126xBw.SX126X_BW_23400,
|
||||
"29_3kHz": SX126xBw.SX126X_BW_29300,
|
||||
"39_0kHz": SX126xBw.SX126X_BW_39000,
|
||||
"46_9kHz": SX126xBw.SX126X_BW_46900,
|
||||
"58_6kHz": SX126xBw.SX126X_BW_58600,
|
||||
"78_2kHz": SX126xBw.SX126X_BW_78200,
|
||||
"93_8kHz": SX126xBw.SX126X_BW_93800,
|
||||
"117_3kHz": SX126xBw.SX126X_BW_117300,
|
||||
"156_2kHz": SX126xBw.SX126X_BW_156200,
|
||||
"187_2kHz": SX126xBw.SX126X_BW_187200,
|
||||
"234_3kHz": SX126xBw.SX126X_BW_234300,
|
||||
"312_0kHz": SX126xBw.SX126X_BW_312000,
|
||||
"373_6kHz": SX126xBw.SX126X_BW_373600,
|
||||
"467_0kHz": SX126xBw.SX126X_BW_467000,
|
||||
"7_8kHz": SX126xBw.SX126X_BW_7810,
|
||||
"10_4kHz": SX126xBw.SX126X_BW_10420,
|
||||
"15_6kHz": SX126xBw.SX126X_BW_15630,
|
||||
"20_8kHz": SX126xBw.SX126X_BW_20830,
|
||||
"31_3kHz": SX126xBw.SX126X_BW_31250,
|
||||
"41_7kHz": SX126xBw.SX126X_BW_41670,
|
||||
"62_5kHz": SX126xBw.SX126X_BW_62500,
|
||||
"125_0kHz": SX126xBw.SX126X_BW_125000,
|
||||
"250_0kHz": SX126xBw.SX126X_BW_250000,
|
||||
"500_0kHz": SX126xBw.SX126X_BW_500000,
|
||||
}
|
||||
|
||||
CODING_RATE = {
|
||||
"CR_4_5": SX126xLoraCr.LORA_CR_4_5,
|
||||
"CR_4_6": SX126xLoraCr.LORA_CR_4_6,
|
||||
"CR_4_7": SX126xLoraCr.LORA_CR_4_7,
|
||||
"CR_4_8": SX126xLoraCr.LORA_CR_4_8,
|
||||
}
|
||||
|
||||
MOD = {
|
||||
"LORA": SX126xPacketType.PACKET_TYPE_LORA,
|
||||
"FSK": SX126xPacketType.PACKET_TYPE_GFSK,
|
||||
}
|
||||
|
||||
TCXO_VOLTAGE = {
|
||||
"1_6V": SX126xTcxoCtrl.TCXO_CTRL_1_6V,
|
||||
"1_7V": SX126xTcxoCtrl.TCXO_CTRL_1_7V,
|
||||
"1_8V": SX126xTcxoCtrl.TCXO_CTRL_1_8V,
|
||||
"2_2V": SX126xTcxoCtrl.TCXO_CTRL_2_2V,
|
||||
"2_4V": SX126xTcxoCtrl.TCXO_CTRL_2_4V,
|
||||
"2_7V": SX126xTcxoCtrl.TCXO_CTRL_2_7V,
|
||||
"3_0V": SX126xTcxoCtrl.TCXO_CTRL_3_0V,
|
||||
"3_3V": SX126xTcxoCtrl.TCXO_CTRL_3_3V,
|
||||
"NONE": SX126xTcxoCtrl.TCXO_CTRL_NONE,
|
||||
}
|
||||
|
||||
RAMP = {
|
||||
"10us": SX126xRampTime.PA_RAMP_10,
|
||||
"20us": SX126xRampTime.PA_RAMP_20,
|
||||
"40us": SX126xRampTime.PA_RAMP_40,
|
||||
"80us": SX126xRampTime.PA_RAMP_80,
|
||||
"200us": SX126xRampTime.PA_RAMP_200,
|
||||
"800us": SX126xRampTime.PA_RAMP_800,
|
||||
"1700us": SX126xRampTime.PA_RAMP_1700,
|
||||
"3400us": SX126xRampTime.PA_RAMP_3400,
|
||||
}
|
||||
|
||||
SHAPING = {
|
||||
"GAUSSIAN_BT_0_3": SX126xPulseShape.GAUSSIAN_BT_0_3,
|
||||
"GAUSSIAN_BT_0_5": SX126xPulseShape.GAUSSIAN_BT_0_5,
|
||||
"GAUSSIAN_BT_0_7": SX126xPulseShape.GAUSSIAN_BT_0_7,
|
||||
"GAUSSIAN_BT_1_0": SX126xPulseShape.GAUSSIAN_BT_1_0,
|
||||
"NONE": SX126xPulseShape.NO_FILTER,
|
||||
}
|
||||
|
||||
RunImageCalAction = sx126x_ns.class_(
|
||||
"RunImageCalAction", automation.Action, cg.Parented.template(SX126x)
|
||||
)
|
||||
SendPacketAction = sx126x_ns.class_(
|
||||
"SendPacketAction", automation.Action, cg.Parented.template(SX126x)
|
||||
)
|
||||
SetModeTxAction = sx126x_ns.class_(
|
||||
"SetModeTxAction", automation.Action, cg.Parented.template(SX126x)
|
||||
)
|
||||
SetModeRxAction = sx126x_ns.class_(
|
||||
"SetModeRxAction", automation.Action, cg.Parented.template(SX126x)
|
||||
)
|
||||
SetModeSleepAction = sx126x_ns.class_(
|
||||
"SetModeSleepAction", automation.Action, cg.Parented.template(SX126x)
|
||||
)
|
||||
SetModeStandbyAction = sx126x_ns.class_(
|
||||
"SetModeStandbyAction", automation.Action, cg.Parented.template(SX126x)
|
||||
)
|
||||
|
||||
|
||||
def validate_raw_data(value):
|
||||
if isinstance(value, str):
|
||||
return value.encode("utf-8")
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
if isinstance(value, list):
|
||||
return cv.Schema([cv.hex_uint8_t])(value)
|
||||
raise cv.Invalid(
|
||||
"data must either be a string wrapped in quotes or a list of bytes"
|
||||
)
|
||||
|
||||
|
||||
def validate_config(config):
|
||||
lora_bws = [
|
||||
"7_8kHz",
|
||||
"10_4kHz",
|
||||
"15_6kHz",
|
||||
"20_8kHz",
|
||||
"31_3kHz",
|
||||
"41_7kHz",
|
||||
"62_5kHz",
|
||||
"125_0kHz",
|
||||
"250_0kHz",
|
||||
"500_0kHz",
|
||||
]
|
||||
if config[CONF_MODULATION] == "LORA":
|
||||
if config[CONF_BANDWIDTH] not in lora_bws:
|
||||
raise cv.Invalid(
|
||||
f"Bandwidth {config[CONF_BANDWIDTH]} is not available with LORA"
|
||||
)
|
||||
if config[CONF_PREAMBLE_SIZE] > 0 and config[CONF_PREAMBLE_SIZE] < 6:
|
||||
raise cv.Invalid("Minimum preamble size is 6 with LORA")
|
||||
if config[CONF_SPREADING_FACTOR] == 6 and config[CONF_PAYLOAD_LENGTH] == 0:
|
||||
raise cv.Invalid("Payload length must be set when spreading factor is 6")
|
||||
else:
|
||||
if config[CONF_BANDWIDTH] in lora_bws:
|
||||
raise cv.Invalid(
|
||||
f"Bandwidth {config[CONF_BANDWIDTH]} is not available with FSK"
|
||||
)
|
||||
if config[CONF_PREAMBLE_DETECT] > len(config[CONF_SYNC_VALUE]):
|
||||
raise cv.Invalid("Preamble detection length must be <= sync value length")
|
||||
return config
|
||||
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(SX126x),
|
||||
cv.Optional(CONF_BANDWIDTH, default="125_0kHz"): cv.enum(BW),
|
||||
cv.Optional(CONF_BITRATE, default=4800): cv.int_range(min=600, max=300000),
|
||||
cv.Required(CONF_BUSY_PIN): pins.internal_gpio_input_pin_schema,
|
||||
cv.Optional(CONF_CODING_RATE, default="CR_4_5"): cv.enum(CODING_RATE),
|
||||
cv.Optional(CONF_CRC_ENABLE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_DEVIATION, default=5000): cv.int_range(min=0, max=100000),
|
||||
cv.Required(CONF_DIO1_PIN): pins.internal_gpio_input_pin_schema,
|
||||
cv.Required(CONF_FREQUENCY): cv.int_range(min=137000000, max=1020000000),
|
||||
cv.Required(CONF_HW_VERSION): cv.one_of(
|
||||
"sx1261", "sx1262", "sx1268", "llcc68", lower=True
|
||||
),
|
||||
cv.Required(CONF_MODULATION): cv.enum(MOD),
|
||||
cv.Optional(CONF_ON_PACKET): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_PA_POWER, default=17): cv.int_range(min=-3, max=22),
|
||||
cv.Optional(CONF_PA_RAMP, default="40us"): cv.enum(RAMP),
|
||||
cv.Optional(CONF_PAYLOAD_LENGTH, default=0): cv.int_range(min=0, max=256),
|
||||
cv.Optional(CONF_PREAMBLE_DETECT, default=2): cv.int_range(min=0, max=4),
|
||||
cv.Required(CONF_PREAMBLE_SIZE): cv.int_range(min=1, max=65535),
|
||||
cv.Required(CONF_RST_PIN): pins.internal_gpio_output_pin_schema,
|
||||
cv.Optional(CONF_RX_START, default=True): cv.boolean,
|
||||
cv.Required(CONF_RF_SWITCH): cv.boolean,
|
||||
cv.Optional(CONF_SHAPING, default="NONE"): cv.enum(SHAPING),
|
||||
cv.Optional(CONF_SPREADING_FACTOR, default=7): cv.int_range(min=6, max=12),
|
||||
cv.Optional(CONF_SYNC_VALUE, default=[]): cv.ensure_list(cv.hex_uint8_t),
|
||||
cv.Optional(CONF_TCXO_VOLTAGE, default="NONE"): cv.enum(TCXO_VOLTAGE),
|
||||
cv.Optional(CONF_TCXO_DELAY, default="5ms"): cv.All(
|
||||
cv.positive_time_period_microseconds,
|
||||
cv.Range(max=TimePeriod(microseconds=262144000)),
|
||||
),
|
||||
},
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(spi.spi_device_schema(True, 8e6, "mode0"))
|
||||
.add_extra(validate_config)
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await spi.register_spi_device(var, config)
|
||||
if CONF_ON_PACKET in config:
|
||||
await automation.build_automation(
|
||||
var.get_packet_trigger(),
|
||||
[
|
||||
(cg.std_vector.template(cg.uint8), "x"),
|
||||
(cg.float_, "rssi"),
|
||||
(cg.float_, "snr"),
|
||||
],
|
||||
config[CONF_ON_PACKET],
|
||||
)
|
||||
if CONF_DIO1_PIN in config:
|
||||
dio1_pin = await cg.gpio_pin_expression(config[CONF_DIO1_PIN])
|
||||
cg.add(var.set_dio1_pin(dio1_pin))
|
||||
rst_pin = await cg.gpio_pin_expression(config[CONF_RST_PIN])
|
||||
cg.add(var.set_rst_pin(rst_pin))
|
||||
busy_pin = await cg.gpio_pin_expression(config[CONF_BUSY_PIN])
|
||||
cg.add(var.set_busy_pin(busy_pin))
|
||||
cg.add(var.set_bandwidth(config[CONF_BANDWIDTH]))
|
||||
cg.add(var.set_frequency(config[CONF_FREQUENCY]))
|
||||
cg.add(var.set_hw_version(config[CONF_HW_VERSION]))
|
||||
cg.add(var.set_deviation(config[CONF_DEVIATION]))
|
||||
cg.add(var.set_modulation(config[CONF_MODULATION]))
|
||||
cg.add(var.set_pa_ramp(config[CONF_PA_RAMP]))
|
||||
cg.add(var.set_pa_power(config[CONF_PA_POWER]))
|
||||
cg.add(var.set_shaping(config[CONF_SHAPING]))
|
||||
cg.add(var.set_bitrate(config[CONF_BITRATE]))
|
||||
cg.add(var.set_crc_enable(config[CONF_CRC_ENABLE]))
|
||||
cg.add(var.set_payload_length(config[CONF_PAYLOAD_LENGTH]))
|
||||
cg.add(var.set_preamble_size(config[CONF_PREAMBLE_SIZE]))
|
||||
cg.add(var.set_preamble_detect(config[CONF_PREAMBLE_DETECT]))
|
||||
cg.add(var.set_coding_rate(config[CONF_CODING_RATE]))
|
||||
cg.add(var.set_spreading_factor(config[CONF_SPREADING_FACTOR]))
|
||||
cg.add(var.set_sync_value(config[CONF_SYNC_VALUE]))
|
||||
cg.add(var.set_rx_start(config[CONF_RX_START]))
|
||||
cg.add(var.set_rf_switch(config[CONF_RF_SWITCH]))
|
||||
cg.add(var.set_tcxo_voltage(config[CONF_TCXO_VOLTAGE]))
|
||||
cg.add(var.set_tcxo_delay(config[CONF_TCXO_DELAY]))
|
||||
|
||||
|
||||
NO_ARGS_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(SX126x),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"sx126x.run_image_cal", RunImageCalAction, NO_ARGS_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"sx126x.set_mode_tx", SetModeTxAction, NO_ARGS_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"sx126x.set_mode_rx", SetModeRxAction, NO_ARGS_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"sx126x.set_mode_sleep", SetModeSleepAction, NO_ARGS_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"sx126x.set_mode_standby", SetModeStandbyAction, NO_ARGS_ACTION_SCHEMA
|
||||
)
|
||||
async def no_args_action_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
SEND_PACKET_ACTION_SCHEMA = cv.maybe_simple_value(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(SX126x),
|
||||
cv.Required(CONF_DATA): cv.templatable(validate_raw_data),
|
||||
},
|
||||
key=CONF_DATA,
|
||||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"sx126x.send_packet", SendPacketAction, SEND_PACKET_ACTION_SCHEMA
|
||||
)
|
||||
async def send_packet_action_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
data = config[CONF_DATA]
|
||||
if isinstance(data, bytes):
|
||||
data = list(data)
|
||||
if cg.is_template(data):
|
||||
templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8))
|
||||
cg.add(var.set_data_template(templ))
|
||||
else:
|
||||
cg.add(var.set_data_static(data))
|
||||
return var
|
62
esphome/components/sx126x/automation.h
Normal file
62
esphome/components/sx126x/automation.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/sx126x/sx126x.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sx126x {
|
||||
|
||||
template<typename... Ts> class RunImageCalAction : public Action<Ts...>, public Parented<SX126x> {
|
||||
public:
|
||||
void play(Ts... x) override { this->parent_->run_image_cal(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class SendPacketAction : public Action<Ts...>, public Parented<SX126x> {
|
||||
public:
|
||||
void set_data_template(std::function<std::vector<uint8_t>(Ts...)> func) {
|
||||
this->data_func_ = func;
|
||||
this->static_ = false;
|
||||
}
|
||||
|
||||
void set_data_static(const std::vector<uint8_t> &data) {
|
||||
this->data_static_ = data;
|
||||
this->static_ = true;
|
||||
}
|
||||
|
||||
void play(Ts... x) override {
|
||||
if (this->static_) {
|
||||
this->parent_->transmit_packet(this->data_static_);
|
||||
} else {
|
||||
this->parent_->transmit_packet(this->data_func_(x...));
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool static_{false};
|
||||
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
||||
std::vector<uint8_t> data_static_{};
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetModeTxAction : public Action<Ts...>, public Parented<SX126x> {
|
||||
public:
|
||||
void play(Ts... x) override { this->parent_->set_mode_tx(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetModeRxAction : public Action<Ts...>, public Parented<SX126x> {
|
||||
public:
|
||||
void play(Ts... x) override { this->parent_->set_mode_rx(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetModeSleepAction : public Action<Ts...>, public Parented<SX126x> {
|
||||
public:
|
||||
void play(Ts... x) override { this->parent_->set_mode_sleep(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetModeStandbyAction : public Action<Ts...>, public Parented<SX126x> {
|
||||
public:
|
||||
void play(Ts... x) override { this->parent_->set_mode_standby(STDBY_XOSC); }
|
||||
};
|
||||
|
||||
} // namespace sx126x
|
||||
} // namespace esphome
|
26
esphome/components/sx126x/packet_transport/__init__.py
Normal file
26
esphome/components/sx126x/packet_transport/__init__.py
Normal file
@ -0,0 +1,26 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.packet_transport import (
|
||||
PacketTransport,
|
||||
new_packet_transport,
|
||||
transport_schema,
|
||||
)
|
||||
import esphome.config_validation as cv
|
||||
from esphome.cpp_types import PollingComponent
|
||||
|
||||
from .. import CONF_SX126X_ID, SX126x, SX126xListener, sx126x_ns
|
||||
|
||||
SX126xTransport = sx126x_ns.class_(
|
||||
"SX126xTransport", PacketTransport, PollingComponent, SX126xListener
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = transport_schema(SX126xTransport).extend(
|
||||
{
|
||||
cv.GenerateID(CONF_SX126X_ID): cv.use_id(SX126x),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var, _ = await new_packet_transport(config)
|
||||
sx126x = await cg.get_variable(config[CONF_SX126X_ID])
|
||||
cg.add(var.set_parent(sx126x))
|
@ -0,0 +1,26 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "sx126x_transport.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sx126x {
|
||||
|
||||
static const char *const TAG = "sx126x_transport";
|
||||
|
||||
void SX126xTransport::setup() {
|
||||
PacketTransport::setup();
|
||||
this->parent_->register_listener(this);
|
||||
}
|
||||
|
||||
void SX126xTransport::update() {
|
||||
PacketTransport::update();
|
||||
this->updated_ = true;
|
||||
this->resend_data_ = true;
|
||||
}
|
||||
|
||||
void SX126xTransport::send_packet(const std::vector<uint8_t> &buf) const { this->parent_->transmit_packet(buf); }
|
||||
|
||||
void SX126xTransport::on_packet(const std::vector<uint8_t> &packet, float rssi, float snr) { this->process_(packet); }
|
||||
|
||||
} // namespace sx126x
|
||||
} // namespace esphome
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sx126x/sx126x.h"
|
||||
#include "esphome/components/packet_transport/packet_transport.h"
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace sx126x {
|
||||
|
||||
class SX126xTransport : public packet_transport::PacketTransport, public Parented<SX126x>, public SX126xListener {
|
||||
public:
|
||||
void setup() override;
|
||||
void update() override;
|
||||
void on_packet(const std::vector<uint8_t> &packet, float rssi, float snr) override;
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
|
||||
protected:
|
||||
void send_packet(const std::vector<uint8_t> &buf) const override;
|
||||
bool should_send() override { return true; }
|
||||
size_t get_max_packet_size() override { return this->parent_->get_max_packet_size(); }
|
||||
};
|
||||
|
||||
} // namespace sx126x
|
||||
} // namespace esphome
|
504
esphome/components/sx126x/sx126x.cpp
Normal file
504
esphome/components/sx126x/sx126x.cpp
Normal file
@ -0,0 +1,504 @@
|
||||
#include "sx126x.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sx126x {
|
||||
|
||||
static const char *const TAG = "sx126x";
|
||||
static const uint16_t RAMP[8] = {10, 20, 40, 80, 200, 800, 1700, 3400};
|
||||
static const uint32_t BW_HZ[31] = {4800, 5800, 7300, 9700, 11700, 14600, 19500, 23400, 29300, 39000, 46900,
|
||||
58600, 78200, 93800, 117300, 156200, 187200, 234300, 312000, 373600, 467000, 7810,
|
||||
10420, 15630, 20830, 31250, 41670, 62500, 125000, 250000, 500000};
|
||||
static const uint8_t BW_LORA[10] = {LORA_BW_7810, LORA_BW_10420, LORA_BW_15630, LORA_BW_20830, LORA_BW_31250,
|
||||
LORA_BW_41670, LORA_BW_62500, LORA_BW_125000, LORA_BW_250000, LORA_BW_500000};
|
||||
static const uint8_t BW_FSK[21] = {
|
||||
FSK_BW_4800, FSK_BW_5800, FSK_BW_7300, FSK_BW_9700, FSK_BW_11700, FSK_BW_14600, FSK_BW_19500,
|
||||
FSK_BW_23400, FSK_BW_29300, FSK_BW_39000, FSK_BW_46900, FSK_BW_58600, FSK_BW_78200, FSK_BW_93800,
|
||||
FSK_BW_117300, FSK_BW_156200, FSK_BW_187200, FSK_BW_234300, FSK_BW_312000, FSK_BW_373600, FSK_BW_467000};
|
||||
|
||||
uint8_t SX126x::wakeup_() {
|
||||
this->wait_busy_();
|
||||
this->enable();
|
||||
this->transfer_byte(RADIO_GET_STATUS);
|
||||
uint8_t status = this->transfer_byte(0x00);
|
||||
this->disable();
|
||||
this->wait_busy_();
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t SX126x::read_fifo_(uint8_t offset, std::vector<uint8_t> &packet) {
|
||||
this->wait_busy_();
|
||||
this->enable();
|
||||
this->transfer_byte(RADIO_READ_BUFFER);
|
||||
this->transfer_byte(offset);
|
||||
uint8_t status = this->transfer_byte(0x00);
|
||||
for (uint8_t &byte : packet) {
|
||||
byte = this->transfer_byte(0x00);
|
||||
}
|
||||
this->disable();
|
||||
this->wait_busy_();
|
||||
return status;
|
||||
}
|
||||
|
||||
void SX126x::write_fifo_(uint8_t offset, const std::vector<uint8_t> &packet) {
|
||||
this->wait_busy_();
|
||||
this->enable();
|
||||
this->transfer_byte(RADIO_WRITE_BUFFER);
|
||||
this->transfer_byte(offset);
|
||||
for (const uint8_t &byte : packet) {
|
||||
this->transfer_byte(byte);
|
||||
}
|
||||
this->disable();
|
||||
this->wait_busy_();
|
||||
}
|
||||
|
||||
uint8_t SX126x::read_opcode_(uint8_t opcode, uint8_t *data, uint8_t size) {
|
||||
this->wait_busy_();
|
||||
this->enable();
|
||||
this->transfer_byte(opcode);
|
||||
uint8_t status = this->transfer_byte(0x00);
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
data[i] = this->transfer_byte(0x00);
|
||||
}
|
||||
this->disable();
|
||||
this->wait_busy_();
|
||||
return status;
|
||||
}
|
||||
|
||||
void SX126x::write_opcode_(uint8_t opcode, uint8_t *data, uint8_t size) {
|
||||
this->wait_busy_();
|
||||
this->enable();
|
||||
this->transfer_byte(opcode);
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
this->transfer_byte(data[i]);
|
||||
}
|
||||
this->disable();
|
||||
this->wait_busy_();
|
||||
}
|
||||
|
||||
void SX126x::read_register_(uint16_t reg, uint8_t *data, uint8_t size) {
|
||||
this->wait_busy_();
|
||||
this->enable();
|
||||
this->write_byte(RADIO_READ_REGISTER);
|
||||
this->write_byte((reg >> 8) & 0xFF);
|
||||
this->write_byte((reg >> 0) & 0xFF);
|
||||
this->write_byte(0x00);
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
data[i] = this->transfer_byte(0x00);
|
||||
}
|
||||
this->disable();
|
||||
this->wait_busy_();
|
||||
}
|
||||
|
||||
void SX126x::write_register_(uint16_t reg, uint8_t *data, uint8_t size) {
|
||||
this->wait_busy_();
|
||||
this->enable();
|
||||
this->write_byte(RADIO_WRITE_REGISTER);
|
||||
this->write_byte((reg >> 8) & 0xFF);
|
||||
this->write_byte((reg >> 0) & 0xFF);
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
this->transfer_byte(data[i]);
|
||||
}
|
||||
this->disable();
|
||||
this->wait_busy_();
|
||||
}
|
||||
|
||||
void SX126x::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
|
||||
// setup pins
|
||||
this->busy_pin_->setup();
|
||||
this->rst_pin_->setup();
|
||||
this->dio1_pin_->setup();
|
||||
|
||||
// start spi
|
||||
this->spi_setup();
|
||||
|
||||
// configure rf
|
||||
this->configure();
|
||||
}
|
||||
|
||||
void SX126x::configure() {
|
||||
uint8_t buf[8];
|
||||
|
||||
// toggle chip reset
|
||||
this->rst_pin_->digital_write(true);
|
||||
delayMicroseconds(5000);
|
||||
this->rst_pin_->digital_write(false);
|
||||
delayMicroseconds(2000);
|
||||
this->rst_pin_->digital_write(true);
|
||||
delayMicroseconds(5000);
|
||||
|
||||
// wakeup
|
||||
this->wakeup_();
|
||||
|
||||
// config tcxo
|
||||
if (this->tcxo_voltage_ != TCXO_CTRL_NONE) {
|
||||
uint32_t delay = this->tcxo_delay_ >> 6;
|
||||
buf[0] = this->tcxo_voltage_;
|
||||
buf[1] = (delay >> 16) & 0xFF;
|
||||
buf[2] = (delay >> 8) & 0xFF;
|
||||
buf[3] = (delay >> 0) & 0xFF;
|
||||
this->write_opcode_(RADIO_SET_TCXOMODE, buf, 4);
|
||||
buf[0] = 0x7F;
|
||||
this->write_opcode_(RADIO_CALIBRATE, buf, 1);
|
||||
}
|
||||
|
||||
// clear errors
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x00;
|
||||
this->write_opcode_(RADIO_CLR_ERROR, buf, 2);
|
||||
|
||||
// rf switch
|
||||
if (this->rf_switch_) {
|
||||
buf[0] = 0x01;
|
||||
this->write_opcode_(RADIO_SET_RFSWITCHMODE, buf, 1);
|
||||
}
|
||||
|
||||
// check silicon version to make sure hw is ok
|
||||
this->read_register_(REG_VERSION_STRING, (uint8_t *) this->version_, 16);
|
||||
if (strncmp(this->version_, "SX126", 5) != 0 && strncmp(this->version_, "LLCC68", 6) != 0) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup packet type
|
||||
buf[0] = this->modulation_;
|
||||
this->write_opcode_(RADIO_SET_PACKETTYPE, buf, 1);
|
||||
|
||||
// calibrate image
|
||||
this->run_image_cal();
|
||||
|
||||
// set frequency
|
||||
uint64_t freq = ((uint64_t) this->frequency_ << 25) / XTAL_FREQ;
|
||||
buf[0] = (uint8_t) ((freq >> 24) & 0xFF);
|
||||
buf[1] = (uint8_t) ((freq >> 16) & 0xFF);
|
||||
buf[2] = (uint8_t) ((freq >> 8) & 0xFF);
|
||||
buf[3] = (uint8_t) (freq & 0xFF);
|
||||
this->write_opcode_(RADIO_SET_RFFREQUENCY, buf, 4);
|
||||
|
||||
// configure pa
|
||||
int8_t pa_power = this->pa_power_;
|
||||
if (this->hw_version_ == "sx1261") {
|
||||
if (pa_power == 15) {
|
||||
uint8_t cfg[4] = {0x06, 0x00, 0x01, 0x01};
|
||||
this->write_opcode_(RADIO_SET_PACONFIG, cfg, 4);
|
||||
} else {
|
||||
uint8_t cfg[4] = {0x04, 0x00, 0x01, 0x01};
|
||||
this->write_opcode_(RADIO_SET_PACONFIG, cfg, 4);
|
||||
}
|
||||
pa_power = std::max(pa_power, (int8_t) -3);
|
||||
pa_power = std::min(pa_power, (int8_t) 14);
|
||||
buf[0] = 0x18; // max 80 mA
|
||||
this->write_register_(REG_OCP, buf, 1);
|
||||
} else {
|
||||
uint8_t cfg[4] = {0x04, 0x07, 0x00, 0x01};
|
||||
this->write_opcode_(RADIO_SET_PACONFIG, cfg, 4);
|
||||
pa_power = std::max(pa_power, (int8_t) -3);
|
||||
pa_power = std::min(pa_power, (int8_t) 22);
|
||||
buf[0] = 0x38; // max 140 mA
|
||||
this->write_register_(REG_OCP, buf, 1);
|
||||
}
|
||||
buf[0] = pa_power;
|
||||
buf[1] = this->pa_ramp_;
|
||||
this->write_opcode_(RADIO_SET_TXPARAMS, buf, 2);
|
||||
|
||||
// configure modem
|
||||
if (this->modulation_ == PACKET_TYPE_LORA) {
|
||||
// set modulation params
|
||||
float duration = 1000.0f * std::pow(2, this->spreading_factor_) / BW_HZ[this->bandwidth_];
|
||||
buf[0] = this->spreading_factor_;
|
||||
buf[1] = BW_LORA[this->bandwidth_ - SX126X_BW_7810];
|
||||
buf[2] = this->coding_rate_;
|
||||
buf[3] = (duration > 16.38f) ? 0x01 : 0x00;
|
||||
this->write_opcode_(RADIO_SET_MODULATIONPARAMS, buf, 4);
|
||||
|
||||
// set packet params and sync word
|
||||
this->set_packet_params_(this->payload_length_);
|
||||
if (this->sync_value_.size() == 2) {
|
||||
for (uint32_t i = 0; i < this->sync_value_.size(); i++) {
|
||||
uint8_t data = this->sync_value_[i];
|
||||
this->write_register_(REG_LORA_SYNCWORD + i, &data, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// set modulation params
|
||||
uint32_t bitrate = ((uint64_t) XTAL_FREQ * 32) / this->bitrate_;
|
||||
uint32_t fdev = ((uint64_t) this->deviation_ << 25) / XTAL_FREQ;
|
||||
buf[0] = (bitrate >> 16) & 0xFF;
|
||||
buf[1] = (bitrate >> 8) & 0xFF;
|
||||
buf[2] = (bitrate >> 0) & 0xFF;
|
||||
buf[3] = this->shaping_;
|
||||
buf[4] = BW_FSK[this->bandwidth_ - SX126X_BW_4800];
|
||||
buf[5] = (fdev >> 16) & 0xFF;
|
||||
buf[6] = (fdev >> 8) & 0xFF;
|
||||
buf[7] = (fdev >> 0) & 0xFF;
|
||||
this->write_opcode_(RADIO_SET_MODULATIONPARAMS, buf, 8);
|
||||
|
||||
// set packet params and sync word
|
||||
this->set_packet_params_(this->payload_length_);
|
||||
if (!this->sync_value_.empty()) {
|
||||
for (uint32_t i = 0; i < this->sync_value_.size(); i++) {
|
||||
uint8_t data = this->sync_value_[i];
|
||||
this->write_register_(REG_GFSK_SYNCWORD + i, &data, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// switch to rx or sleep
|
||||
if (this->rx_start_) {
|
||||
this->set_mode_rx();
|
||||
} else {
|
||||
this->set_mode_sleep();
|
||||
}
|
||||
}
|
||||
|
||||
size_t SX126x::get_max_packet_size() {
|
||||
if (this->payload_length_ > 0) {
|
||||
return this->payload_length_;
|
||||
}
|
||||
return 256;
|
||||
}
|
||||
|
||||
void SX126x::set_packet_params_(uint8_t payload_length) {
|
||||
uint8_t buf[9];
|
||||
if (this->modulation_ == PACKET_TYPE_LORA) {
|
||||
buf[0] = (this->preamble_size_ >> 8) & 0xFF;
|
||||
buf[1] = (this->preamble_size_ >> 0) & 0xFF;
|
||||
buf[2] = (this->payload_length_ > 0) ? 0x01 : 0x00;
|
||||
buf[3] = payload_length;
|
||||
buf[4] = (this->crc_enable_) ? 0x01 : 0x00;
|
||||
buf[5] = 0x00;
|
||||
this->write_opcode_(RADIO_SET_PACKETPARAMS, buf, 6);
|
||||
} else {
|
||||
uint16_t preamble_size = this->preamble_size_ * 8;
|
||||
buf[0] = (preamble_size >> 8) & 0xFF;
|
||||
buf[1] = (preamble_size >> 0) & 0xFF;
|
||||
buf[2] = (this->preamble_detect_ > 0) ? ((this->preamble_detect_ - 1) | 0x04) : 0x00;
|
||||
buf[3] = this->sync_value_.size() * 8;
|
||||
buf[4] = 0x00;
|
||||
buf[5] = 0x00;
|
||||
buf[6] = payload_length;
|
||||
buf[7] = this->crc_enable_ ? 0x06 : 0x01;
|
||||
buf[8] = 0x00;
|
||||
this->write_opcode_(RADIO_SET_PACKETPARAMS, buf, 9);
|
||||
}
|
||||
}
|
||||
|
||||
void SX126x::transmit_packet(const std::vector<uint8_t> &packet) {
|
||||
if (this->payload_length_ > 0 && this->payload_length_ != packet.size()) {
|
||||
ESP_LOGE(TAG, "Packet size does not match config");
|
||||
return;
|
||||
}
|
||||
if (packet.empty() || packet.size() > this->get_max_packet_size()) {
|
||||
ESP_LOGE(TAG, "Packet size out of range");
|
||||
return;
|
||||
}
|
||||
this->set_mode_standby(STDBY_XOSC);
|
||||
if (this->payload_length_ == 0) {
|
||||
this->set_packet_params_(packet.size());
|
||||
}
|
||||
this->write_fifo_(0x00, packet);
|
||||
this->set_mode_tx();
|
||||
uint32_t start = millis();
|
||||
while (!this->dio1_pin_->digital_read()) {
|
||||
if (millis() - start > 4000) {
|
||||
ESP_LOGE(TAG, "Transmit packet failure");
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint8_t buf[2];
|
||||
buf[0] = 0xFF;
|
||||
buf[1] = 0xFF;
|
||||
this->write_opcode_(RADIO_CLR_IRQSTATUS, buf, 2);
|
||||
if (this->rx_start_) {
|
||||
this->set_mode_rx();
|
||||
} else {
|
||||
this->set_mode_sleep();
|
||||
}
|
||||
}
|
||||
|
||||
void SX126x::call_listeners_(const std::vector<uint8_t> &packet, float rssi, float snr) {
|
||||
for (auto &listener : this->listeners_) {
|
||||
listener->on_packet(packet, rssi, snr);
|
||||
}
|
||||
this->packet_trigger_->trigger(packet, rssi, snr);
|
||||
}
|
||||
|
||||
void SX126x::loop() {
|
||||
if (this->dio1_pin_->digital_read()) {
|
||||
uint16_t status;
|
||||
uint8_t buf[3];
|
||||
uint8_t rssi;
|
||||
int8_t snr;
|
||||
this->read_opcode_(RADIO_GET_IRQSTATUS, buf, 2);
|
||||
this->write_opcode_(RADIO_CLR_IRQSTATUS, buf, 2);
|
||||
status = (buf[0] << 8) | buf[1];
|
||||
if ((status & IRQ_RX_DONE) == IRQ_RX_DONE) {
|
||||
if ((status & IRQ_CRC_ERROR) != IRQ_CRC_ERROR) {
|
||||
this->read_opcode_(RADIO_GET_PACKETSTATUS, buf, 3);
|
||||
if (this->modulation_ == PACKET_TYPE_LORA) {
|
||||
rssi = buf[0];
|
||||
snr = buf[1];
|
||||
} else {
|
||||
rssi = buf[2];
|
||||
snr = 0;
|
||||
}
|
||||
this->read_opcode_(RADIO_GET_RXBUFFERSTATUS, buf, 2);
|
||||
std::vector<uint8_t> packet(buf[0]);
|
||||
this->read_fifo_(buf[1], packet);
|
||||
this->call_listeners_(packet, (float) rssi / -2.0f, (float) snr / 4.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SX126x::run_image_cal() {
|
||||
uint8_t buf[2] = {0, 0};
|
||||
if (this->frequency_ > 900000000) {
|
||||
buf[0] = 0xE1;
|
||||
buf[1] = 0xE9;
|
||||
} else if (this->frequency_ > 850000000) {
|
||||
buf[0] = 0xD7;
|
||||
buf[1] = 0xD8;
|
||||
} else if (this->frequency_ > 770000000) {
|
||||
buf[0] = 0xC1;
|
||||
buf[1] = 0xC5;
|
||||
} else if (this->frequency_ > 460000000) {
|
||||
buf[0] = 0x75;
|
||||
buf[1] = 0x81;
|
||||
} else if (this->frequency_ > 425000000) {
|
||||
buf[0] = 0x6B;
|
||||
buf[1] = 0x6F;
|
||||
}
|
||||
if (buf[0] > 0 && buf[1] > 0) {
|
||||
this->write_opcode_(RADIO_CALIBRATEIMAGE, buf, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void SX126x::set_mode_rx() {
|
||||
uint8_t buf[8];
|
||||
|
||||
// configure irq params
|
||||
uint16_t irq = IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT | IRQ_CRC_ERROR;
|
||||
buf[0] = (irq >> 8) & 0xFF;
|
||||
buf[1] = (irq >> 0) & 0xFF;
|
||||
buf[2] = (irq >> 8) & 0xFF;
|
||||
buf[3] = (irq >> 0) & 0xFF;
|
||||
buf[4] = (IRQ_RADIO_NONE >> 8) & 0xFF;
|
||||
buf[5] = (IRQ_RADIO_NONE >> 0) & 0xFF;
|
||||
buf[6] = (IRQ_RADIO_NONE >> 8) & 0xFF;
|
||||
buf[7] = (IRQ_RADIO_NONE >> 0) & 0xFF;
|
||||
this->write_opcode_(RADIO_SET_DIOIRQPARAMS, buf, 8);
|
||||
|
||||
// set timeout to 0
|
||||
buf[0] = 0x00;
|
||||
this->write_opcode_(RADIO_SET_LORASYMBTIMEOUT, buf, 1);
|
||||
|
||||
// switch to continuous mode rx
|
||||
buf[0] = 0xFF;
|
||||
buf[1] = 0xFF;
|
||||
buf[2] = 0xFF;
|
||||
this->write_opcode_(RADIO_SET_RX, buf, 3);
|
||||
}
|
||||
|
||||
void SX126x::set_mode_tx() {
|
||||
uint8_t buf[8];
|
||||
|
||||
// configure irq params
|
||||
uint16_t irq = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;
|
||||
buf[0] = (irq >> 8) & 0xFF;
|
||||
buf[1] = (irq >> 0) & 0xFF;
|
||||
buf[2] = (irq >> 8) & 0xFF;
|
||||
buf[3] = (irq >> 0) & 0xFF;
|
||||
buf[4] = (IRQ_RADIO_NONE >> 8) & 0xFF;
|
||||
buf[5] = (IRQ_RADIO_NONE >> 0) & 0xFF;
|
||||
buf[6] = (IRQ_RADIO_NONE >> 8) & 0xFF;
|
||||
buf[7] = (IRQ_RADIO_NONE >> 0) & 0xFF;
|
||||
this->write_opcode_(RADIO_SET_DIOIRQPARAMS, buf, 8);
|
||||
|
||||
// switch to single mode tx
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0x00;
|
||||
this->write_opcode_(RADIO_SET_TX, buf, 3);
|
||||
}
|
||||
|
||||
void SX126x::set_mode_sleep() {
|
||||
uint8_t buf[1];
|
||||
buf[0] = 0x05;
|
||||
this->write_opcode_(RADIO_SET_SLEEP, buf, 1);
|
||||
}
|
||||
|
||||
void SX126x::set_mode_standby(SX126xStandbyMode mode) {
|
||||
uint8_t buf[1];
|
||||
buf[0] = mode;
|
||||
this->write_opcode_(RADIO_SET_STANDBY, buf, 1);
|
||||
}
|
||||
|
||||
void SX126x::wait_busy_() {
|
||||
uint32_t start = millis();
|
||||
while (this->busy_pin_->digital_read()) {
|
||||
if (millis() - start > 1000) {
|
||||
ESP_LOGE(TAG, "Wait busy timout");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SX126x::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "SX126x:");
|
||||
ESP_LOGCONFIG(TAG, " HW Version: %15s", this->version_);
|
||||
LOG_PIN(" CS Pin: ", this->cs_);
|
||||
LOG_PIN(" BUSY Pin: ", this->busy_pin_);
|
||||
LOG_PIN(" RST Pin: ", this->rst_pin_);
|
||||
LOG_PIN(" DIO1 Pin: ", this->dio1_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Frequency: %" PRIu32 " Hz", this->frequency_);
|
||||
ESP_LOGCONFIG(TAG, " Bandwidth: %" PRIu32 " Hz", BW_HZ[this->bandwidth_]);
|
||||
ESP_LOGCONFIG(TAG, " PA Power: %" PRId8 " dBm", this->pa_power_);
|
||||
ESP_LOGCONFIG(TAG, " PA Ramp: %" PRIu16 " us", RAMP[this->pa_ramp_]);
|
||||
if (this->modulation_ == PACKET_TYPE_GFSK) {
|
||||
ESP_LOGCONFIG(TAG, " Modulation: %s", "FSK");
|
||||
ESP_LOGCONFIG(TAG, " Deviation: %" PRIu32 " Hz", this->deviation_);
|
||||
if (this->shaping_ == GAUSSIAN_BT_0_3) {
|
||||
ESP_LOGCONFIG(TAG, " Shaping: GAUSSIAN_BT_0_3");
|
||||
} else if (this->shaping_ == GAUSSIAN_BT_0_5) {
|
||||
ESP_LOGCONFIG(TAG, " Shaping: GAUSSIAN_BT_0_5");
|
||||
} else if (this->shaping_ == GAUSSIAN_BT_0_7) {
|
||||
ESP_LOGCONFIG(TAG, " Shaping: GAUSSIAN_BT_0_7");
|
||||
} else if (this->shaping_ == GAUSSIAN_BT_1_0) {
|
||||
ESP_LOGCONFIG(TAG, " Shaping: GAUSSIAN_BT_1_0");
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, " Shaping: NONE");
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Preamble Size: %" PRIu16, this->preamble_size_);
|
||||
ESP_LOGCONFIG(TAG, " Preamble Detect: %" PRIu16, this->preamble_detect_);
|
||||
ESP_LOGCONFIG(TAG, " Bitrate: %" PRIu32 "b/s", this->bitrate_);
|
||||
} else if (this->modulation_ == PACKET_TYPE_LORA) {
|
||||
ESP_LOGCONFIG(TAG, " Modulation: %s", "LORA");
|
||||
ESP_LOGCONFIG(TAG, " Spreading Factor: %" PRIu8, this->spreading_factor_);
|
||||
if (this->coding_rate_ == LORA_CR_4_5) {
|
||||
ESP_LOGCONFIG(TAG, " Coding Rate: 4/5");
|
||||
} else if (this->coding_rate_ == LORA_CR_4_6) {
|
||||
ESP_LOGCONFIG(TAG, " Coding Rate: 4/6");
|
||||
} else if (this->coding_rate_ == LORA_CR_4_7) {
|
||||
ESP_LOGCONFIG(TAG, " Coding Rate: 4/7");
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, " Coding Rate: 4/8");
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Preamble Size: %" PRIu16, this->preamble_size_);
|
||||
}
|
||||
if (!this->sync_value_.empty()) {
|
||||
ESP_LOGCONFIG(TAG, " Sync Value: 0x%s", format_hex(this->sync_value_).c_str());
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Payload Length: %" PRIu32, this->payload_length_);
|
||||
ESP_LOGCONFIG(TAG, " CRC Enable: %s", TRUEFALSE(this->crc_enable_));
|
||||
ESP_LOGCONFIG(TAG, " Rx Start: %s", TRUEFALSE(this->rx_start_));
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Configuring SX126x failed");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sx126x
|
||||
} // namespace esphome
|
138
esphome/components/sx126x/sx126x.h
Normal file
138
esphome/components/sx126x/sx126x.h
Normal file
@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/spi/spi.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "sx126x_reg.h"
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace sx126x {
|
||||
|
||||
enum SX126xBw : uint8_t {
|
||||
// FSK
|
||||
SX126X_BW_4800,
|
||||
SX126X_BW_5800,
|
||||
SX126X_BW_7300,
|
||||
SX126X_BW_9700,
|
||||
SX126X_BW_11700,
|
||||
SX126X_BW_14600,
|
||||
SX126X_BW_19500,
|
||||
SX126X_BW_23400,
|
||||
SX126X_BW_29300,
|
||||
SX126X_BW_39000,
|
||||
SX126X_BW_46900,
|
||||
SX126X_BW_58600,
|
||||
SX126X_BW_78200,
|
||||
SX126X_BW_93800,
|
||||
SX126X_BW_117300,
|
||||
SX126X_BW_156200,
|
||||
SX126X_BW_187200,
|
||||
SX126X_BW_234300,
|
||||
SX126X_BW_312000,
|
||||
SX126X_BW_373600,
|
||||
SX126X_BW_467000,
|
||||
// LORA
|
||||
SX126X_BW_7810,
|
||||
SX126X_BW_10420,
|
||||
SX126X_BW_15630,
|
||||
SX126X_BW_20830,
|
||||
SX126X_BW_31250,
|
||||
SX126X_BW_41670,
|
||||
SX126X_BW_62500,
|
||||
SX126X_BW_125000,
|
||||
SX126X_BW_250000,
|
||||
SX126X_BW_500000,
|
||||
};
|
||||
|
||||
class SX126xListener {
|
||||
public:
|
||||
virtual void on_packet(const std::vector<uint8_t> &packet, float rssi, float snr);
|
||||
};
|
||||
|
||||
class SX126x : public Component,
|
||||
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
|
||||
spi::DATA_RATE_8MHZ> {
|
||||
public:
|
||||
size_t get_max_packet_size();
|
||||
float get_setup_priority() const override { return setup_priority::PROCESSOR; }
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
void set_bandwidth(SX126xBw bandwidth) { this->bandwidth_ = bandwidth; }
|
||||
void set_bitrate(uint32_t bitrate) { this->bitrate_ = bitrate; }
|
||||
void set_busy_pin(InternalGPIOPin *busy_pin) { this->busy_pin_ = busy_pin; }
|
||||
void set_coding_rate(uint8_t coding_rate) { this->coding_rate_ = coding_rate; }
|
||||
void set_crc_enable(bool crc_enable) { this->crc_enable_ = crc_enable; }
|
||||
void set_deviation(uint32_t deviation) { this->deviation_ = deviation; }
|
||||
void set_dio1_pin(InternalGPIOPin *dio1_pin) { this->dio1_pin_ = dio1_pin; }
|
||||
void set_frequency(uint32_t frequency) { this->frequency_ = frequency; }
|
||||
void set_hw_version(const std::string &hw_version) { this->hw_version_ = hw_version; }
|
||||
void set_mode_rx();
|
||||
void set_mode_tx();
|
||||
void set_mode_standby(SX126xStandbyMode mode);
|
||||
void set_mode_sleep();
|
||||
void set_modulation(uint8_t modulation) { this->modulation_ = modulation; }
|
||||
void set_pa_power(int8_t power) { this->pa_power_ = power; }
|
||||
void set_pa_ramp(uint8_t ramp) { this->pa_ramp_ = ramp; }
|
||||
void set_payload_length(uint8_t payload_length) { this->payload_length_ = payload_length; }
|
||||
void set_preamble_detect(uint16_t preamble_detect) { this->preamble_detect_ = preamble_detect; }
|
||||
void set_preamble_size(uint16_t preamble_size) { this->preamble_size_ = preamble_size; }
|
||||
void set_rst_pin(InternalGPIOPin *rst_pin) { this->rst_pin_ = rst_pin; }
|
||||
void set_rx_start(bool rx_start) { this->rx_start_ = rx_start; }
|
||||
void set_rf_switch(bool rf_switch) { this->rf_switch_ = rf_switch; }
|
||||
void set_shaping(uint8_t shaping) { this->shaping_ = shaping; }
|
||||
void set_spreading_factor(uint8_t spreading_factor) { this->spreading_factor_ = spreading_factor; }
|
||||
void set_sync_value(const std::vector<uint8_t> &sync_value) { this->sync_value_ = sync_value; }
|
||||
void set_tcxo_voltage(uint8_t tcxo_voltage) { this->tcxo_voltage_ = tcxo_voltage; }
|
||||
void set_tcxo_delay(uint32_t tcxo_delay) { this->tcxo_delay_ = tcxo_delay; }
|
||||
void run_image_cal();
|
||||
void configure();
|
||||
void transmit_packet(const std::vector<uint8_t> &packet);
|
||||
void register_listener(SX126xListener *listener) { this->listeners_.push_back(listener); }
|
||||
Trigger<std::vector<uint8_t>, float, float> *get_packet_trigger() const { return this->packet_trigger_; };
|
||||
|
||||
protected:
|
||||
void configure_fsk_ook_();
|
||||
void configure_lora_();
|
||||
void set_packet_params_(uint8_t payload_length);
|
||||
uint8_t read_fifo_(uint8_t offset, std::vector<uint8_t> &packet);
|
||||
void write_fifo_(uint8_t offset, const std::vector<uint8_t> &packet);
|
||||
void write_opcode_(uint8_t opcode, uint8_t *data, uint8_t size);
|
||||
uint8_t read_opcode_(uint8_t opcode, uint8_t *data, uint8_t size);
|
||||
void write_register_(uint16_t reg, uint8_t *data, uint8_t size);
|
||||
void read_register_(uint16_t reg, uint8_t *data, uint8_t size);
|
||||
void call_listeners_(const std::vector<uint8_t> &packet, float rssi, float snr);
|
||||
void wait_busy_();
|
||||
uint8_t wakeup_();
|
||||
Trigger<std::vector<uint8_t>, float, float> *packet_trigger_{new Trigger<std::vector<uint8_t>, float, float>()};
|
||||
std::vector<SX126xListener *> listeners_;
|
||||
std::vector<uint8_t> sync_value_;
|
||||
InternalGPIOPin *busy_pin_{nullptr};
|
||||
InternalGPIOPin *dio1_pin_{nullptr};
|
||||
InternalGPIOPin *rst_pin_{nullptr};
|
||||
std::string hw_version_;
|
||||
SX126xBw bandwidth_;
|
||||
char version_[16];
|
||||
uint32_t bitrate_;
|
||||
uint32_t deviation_;
|
||||
uint32_t frequency_;
|
||||
uint32_t payload_length_;
|
||||
uint32_t tcxo_delay_;
|
||||
uint16_t preamble_detect_;
|
||||
uint16_t preamble_size_;
|
||||
uint8_t tcxo_voltage_;
|
||||
uint8_t coding_rate_;
|
||||
uint8_t modulation_;
|
||||
uint8_t pa_ramp_;
|
||||
uint8_t shaping_;
|
||||
uint8_t spreading_factor_;
|
||||
int8_t pa_power_;
|
||||
bool crc_enable_;
|
||||
bool rx_start_;
|
||||
bool rf_switch_;
|
||||
};
|
||||
|
||||
} // namespace sx126x
|
||||
} // namespace esphome
|
163
esphome/components/sx126x/sx126x_reg.h
Normal file
163
esphome/components/sx126x/sx126x_reg.h
Normal file
@ -0,0 +1,163 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/hal.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sx126x {
|
||||
|
||||
static const uint32_t XTAL_FREQ = 32000000;
|
||||
|
||||
enum SX126xOpCode : uint8_t {
|
||||
RADIO_GET_STATUS = 0xC0,
|
||||
RADIO_WRITE_REGISTER = 0x0D,
|
||||
RADIO_READ_REGISTER = 0x1D,
|
||||
RADIO_WRITE_BUFFER = 0x0E,
|
||||
RADIO_READ_BUFFER = 0x1E,
|
||||
RADIO_SET_SLEEP = 0x84,
|
||||
RADIO_SET_STANDBY = 0x80,
|
||||
RADIO_SET_FS = 0xC1,
|
||||
RADIO_SET_TX = 0x83,
|
||||
RADIO_SET_RX = 0x82,
|
||||
RADIO_SET_RXDUTYCYCLE = 0x94,
|
||||
RADIO_SET_CAD = 0xC5,
|
||||
RADIO_SET_TXCONTINUOUSWAVE = 0xD1,
|
||||
RADIO_SET_TXCONTINUOUSPREAMBLE = 0xD2,
|
||||
RADIO_SET_PACKETTYPE = 0x8A,
|
||||
RADIO_GET_PACKETTYPE = 0x11,
|
||||
RADIO_SET_RFFREQUENCY = 0x86,
|
||||
RADIO_SET_TXPARAMS = 0x8E,
|
||||
RADIO_SET_PACONFIG = 0x95,
|
||||
RADIO_SET_CADPARAMS = 0x88,
|
||||
RADIO_SET_BUFFERBASEADDRESS = 0x8F,
|
||||
RADIO_SET_MODULATIONPARAMS = 0x8B,
|
||||
RADIO_SET_PACKETPARAMS = 0x8C,
|
||||
RADIO_GET_RXBUFFERSTATUS = 0x13,
|
||||
RADIO_GET_PACKETSTATUS = 0x14,
|
||||
RADIO_GET_RSSIINST = 0x15,
|
||||
RADIO_GET_STATS = 0x10,
|
||||
RADIO_RESET_STATS = 0x00,
|
||||
RADIO_SET_DIOIRQPARAMS = 0x08,
|
||||
RADIO_GET_IRQSTATUS = 0x12,
|
||||
RADIO_CLR_IRQSTATUS = 0x02,
|
||||
RADIO_CALIBRATE = 0x89,
|
||||
RADIO_CALIBRATEIMAGE = 0x98,
|
||||
RADIO_SET_REGULATORMODE = 0x96,
|
||||
RADIO_GET_ERROR = 0x17,
|
||||
RADIO_CLR_ERROR = 0x07,
|
||||
RADIO_SET_TCXOMODE = 0x97,
|
||||
RADIO_SET_TXFALLBACKMODE = 0x93,
|
||||
RADIO_SET_RFSWITCHMODE = 0x9D,
|
||||
RADIO_SET_STOPRXTIMERONPREAMBLE = 0x9F,
|
||||
RADIO_SET_LORASYMBTIMEOUT = 0xA0,
|
||||
};
|
||||
|
||||
enum SX126xRegister : uint16_t {
|
||||
REG_VERSION_STRING = 0x0320,
|
||||
REG_GFSK_SYNCWORD = 0x06C0,
|
||||
REG_LORA_SYNCWORD = 0x0740,
|
||||
REG_OCP = 0x08E7,
|
||||
};
|
||||
|
||||
enum SX126xStandbyMode : uint8_t {
|
||||
STDBY_RC = 0x00,
|
||||
STDBY_XOSC = 0x01,
|
||||
};
|
||||
|
||||
enum SX126xPacketType : uint8_t {
|
||||
PACKET_TYPE_GFSK = 0x00,
|
||||
PACKET_TYPE_LORA = 0x01,
|
||||
PACKET_TYPE_LRHSS = 0x03,
|
||||
};
|
||||
|
||||
enum SX126xFskBw : uint8_t {
|
||||
FSK_BW_4800 = 0x1F,
|
||||
FSK_BW_5800 = 0x17,
|
||||
FSK_BW_7300 = 0x0F,
|
||||
FSK_BW_9700 = 0x1E,
|
||||
FSK_BW_11700 = 0x16,
|
||||
FSK_BW_14600 = 0x0E,
|
||||
FSK_BW_19500 = 0x1D,
|
||||
FSK_BW_23400 = 0x15,
|
||||
FSK_BW_29300 = 0x0D,
|
||||
FSK_BW_39000 = 0x1C,
|
||||
FSK_BW_46900 = 0x14,
|
||||
FSK_BW_58600 = 0x0C,
|
||||
FSK_BW_78200 = 0x1B,
|
||||
FSK_BW_93800 = 0x13,
|
||||
FSK_BW_117300 = 0x0B,
|
||||
FSK_BW_156200 = 0x1A,
|
||||
FSK_BW_187200 = 0x12,
|
||||
FSK_BW_234300 = 0x0A,
|
||||
FSK_BW_312000 = 0x19,
|
||||
FSK_BW_373600 = 0x11,
|
||||
FSK_BW_467000 = 0x09,
|
||||
};
|
||||
|
||||
enum SX126xLoraBw : uint8_t {
|
||||
LORA_BW_7810 = 0x00,
|
||||
LORA_BW_10420 = 0x08,
|
||||
LORA_BW_15630 = 0x01,
|
||||
LORA_BW_20830 = 0x09,
|
||||
LORA_BW_31250 = 0x02,
|
||||
LORA_BW_41670 = 0x0A,
|
||||
LORA_BW_62500 = 0x03,
|
||||
LORA_BW_125000 = 0x04,
|
||||
LORA_BW_250000 = 0x05,
|
||||
LORA_BW_500000 = 0x06,
|
||||
};
|
||||
|
||||
enum SX126xLoraCr : uint8_t {
|
||||
LORA_CR_4_5 = 0x01,
|
||||
LORA_CR_4_6 = 0x02,
|
||||
LORA_CR_4_7 = 0x03,
|
||||
LORA_CR_4_8 = 0x04,
|
||||
};
|
||||
|
||||
enum SX126xIrqMasks : uint16_t {
|
||||
IRQ_RADIO_NONE = 0x0000,
|
||||
IRQ_TX_DONE = 0x0001,
|
||||
IRQ_RX_DONE = 0x0002,
|
||||
IRQ_PREAMBLE_DETECTED = 0x0004,
|
||||
IRQ_SYNCWORD_VALID = 0x0008,
|
||||
IRQ_HEADER_VALID = 0x0010,
|
||||
IRQ_HEADER_ERROR = 0x0020,
|
||||
IRQ_CRC_ERROR = 0x0040,
|
||||
IRQ_CAD_DONE = 0x0080,
|
||||
IRQ_CAD_ACTIVITY_DETECTED = 0x0100,
|
||||
IRQ_RX_TX_TIMEOUT = 0x0200,
|
||||
IRQ_RADIO_ALL = 0xFFFF,
|
||||
};
|
||||
|
||||
enum SX126xTcxoCtrl : uint8_t {
|
||||
TCXO_CTRL_1_6V = 0x00,
|
||||
TCXO_CTRL_1_7V = 0x01,
|
||||
TCXO_CTRL_1_8V = 0x02,
|
||||
TCXO_CTRL_2_2V = 0x03,
|
||||
TCXO_CTRL_2_4V = 0x04,
|
||||
TCXO_CTRL_2_7V = 0x05,
|
||||
TCXO_CTRL_3_0V = 0x06,
|
||||
TCXO_CTRL_3_3V = 0x07,
|
||||
TCXO_CTRL_NONE = 0xFF,
|
||||
};
|
||||
|
||||
enum SX126xPulseShape : uint8_t {
|
||||
NO_FILTER = 0x00,
|
||||
GAUSSIAN_BT_0_3 = 0x08,
|
||||
GAUSSIAN_BT_0_5 = 0x09,
|
||||
GAUSSIAN_BT_0_7 = 0x0A,
|
||||
GAUSSIAN_BT_1_0 = 0x0B,
|
||||
};
|
||||
|
||||
enum SX126xRampTime : uint8_t {
|
||||
PA_RAMP_10 = 0x00,
|
||||
PA_RAMP_20 = 0x01,
|
||||
PA_RAMP_40 = 0x02,
|
||||
PA_RAMP_80 = 0x03,
|
||||
PA_RAMP_200 = 0x04,
|
||||
PA_RAMP_800 = 0x05,
|
||||
PA_RAMP_1700 = 0x06,
|
||||
PA_RAMP_3400 = 0x07,
|
||||
};
|
||||
|
||||
} // namespace sx126x
|
||||
} // namespace esphome
|
40
tests/components/sx126x/common.yaml
Normal file
40
tests/components/sx126x/common.yaml
Normal file
@ -0,0 +1,40 @@
|
||||
spi:
|
||||
clk_pin: ${clk_pin}
|
||||
mosi_pin: ${mosi_pin}
|
||||
miso_pin: ${miso_pin}
|
||||
|
||||
sx126x:
|
||||
dio1_pin: ${dio1_pin}
|
||||
cs_pin: ${cs_pin}
|
||||
busy_pin: ${busy_pin}
|
||||
rst_pin: ${rst_pin}
|
||||
pa_power: 3
|
||||
bandwidth: 125_0kHz
|
||||
crc_enable: true
|
||||
frequency: 433920000
|
||||
modulation: LORA
|
||||
rx_start: true
|
||||
hw_version: sx1262
|
||||
rf_switch: true
|
||||
sync_value: [0x14, 0x24]
|
||||
preamble_size: 8
|
||||
spreading_factor: 7
|
||||
coding_rate: CR_4_6
|
||||
tcxo_voltage: 1_8V
|
||||
tcxo_delay: 5ms
|
||||
on_packet:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("lambda", "packet %.2f %.2f %s", rssi, snr, format_hex(x).c_str());
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: "SX126x Button"
|
||||
on_press:
|
||||
then:
|
||||
- sx126x.set_mode_standby
|
||||
- sx126x.run_image_cal
|
||||
- sx126x.set_mode_sleep
|
||||
- sx126x.set_mode_rx
|
||||
- sx126x.send_packet:
|
||||
data: [0xC5, 0x51, 0x78, 0x82, 0xB7, 0xF9, 0x9C, 0x5C]
|
10
tests/components/sx126x/test.esp32-ard.yaml
Normal file
10
tests/components/sx126x/test.esp32-ard.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
substitutions:
|
||||
clk_pin: GPIO5
|
||||
mosi_pin: GPIO27
|
||||
miso_pin: GPIO19
|
||||
cs_pin: GPIO18
|
||||
rst_pin: GPIO23
|
||||
busy_pin: GPIO25
|
||||
dio1_pin: GPIO26
|
||||
|
||||
<<: !include common.yaml
|
10
tests/components/sx126x/test.esp32-c3-ard.yaml
Normal file
10
tests/components/sx126x/test.esp32-c3-ard.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
substitutions:
|
||||
clk_pin: GPIO5
|
||||
mosi_pin: GPIO18
|
||||
miso_pin: GPIO19
|
||||
cs_pin: GPIO1
|
||||
rst_pin: GPIO2
|
||||
busy_pin: GPIO4
|
||||
dio1_pin: GPIO3
|
||||
|
||||
<<: !include common.yaml
|
10
tests/components/sx126x/test.esp32-c3-idf.yaml
Normal file
10
tests/components/sx126x/test.esp32-c3-idf.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
substitutions:
|
||||
clk_pin: GPIO5
|
||||
mosi_pin: GPIO18
|
||||
miso_pin: GPIO19
|
||||
cs_pin: GPIO1
|
||||
rst_pin: GPIO2
|
||||
busy_pin: GPIO4
|
||||
dio1_pin: GPIO3
|
||||
|
||||
<<: !include common.yaml
|
10
tests/components/sx126x/test.esp32-idf.yaml
Normal file
10
tests/components/sx126x/test.esp32-idf.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
substitutions:
|
||||
clk_pin: GPIO5
|
||||
mosi_pin: GPIO27
|
||||
miso_pin: GPIO19
|
||||
cs_pin: GPIO18
|
||||
rst_pin: GPIO23
|
||||
busy_pin: GPIO25
|
||||
dio1_pin: GPIO26
|
||||
|
||||
<<: !include common.yaml
|
10
tests/components/sx126x/test.esp8266-ard.yaml
Normal file
10
tests/components/sx126x/test.esp8266-ard.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
substitutions:
|
||||
clk_pin: GPIO5
|
||||
mosi_pin: GPIO13
|
||||
miso_pin: GPIO12
|
||||
cs_pin: GPIO1
|
||||
rst_pin: GPIO2
|
||||
busy_pin: GPIO4
|
||||
dio1_pin: GPIO3
|
||||
|
||||
<<: !include common.yaml
|
10
tests/components/sx126x/test.rp2040-ard.yaml
Normal file
10
tests/components/sx126x/test.rp2040-ard.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
substitutions:
|
||||
clk_pin: GPIO2
|
||||
mosi_pin: GPIO3
|
||||
miso_pin: GPIO4
|
||||
cs_pin: GPIO5
|
||||
rst_pin: GPIO6
|
||||
busy_pin: GPIO8
|
||||
dio1_pin: GPIO7
|
||||
|
||||
<<: !include common.yaml
|
Loading…
x
Reference in New Issue
Block a user