mirror of
https://github.com/esphome/esphome.git
synced 2024-11-30 10:44:13 +01:00
Add packet mode and rx duration
This commit is contained in:
parent
ff6dd6ea9e
commit
55c14e0d48
3 changed files with 380 additions and 42 deletions
|
@ -1,23 +1,34 @@
|
|||
from esphome import pins
|
||||
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_FREQUENCY, CONF_ID
|
||||
from esphome.core import TimePeriod
|
||||
|
||||
CODEOWNERS = ["@swoboda1337"]
|
||||
DEPENDENCIES = ["spi"]
|
||||
|
||||
CONF_PA_POWER = "pa_power"
|
||||
CONF_PA_PIN = "pa_pin"
|
||||
CONF_DIO0_PIN = "dio0_pin"
|
||||
CONF_DIO2_PIN = "dio2_pin"
|
||||
CONF_NSS_PIN = "nss_pin"
|
||||
CONF_RST_PIN = "rst_pin"
|
||||
CONF_MODULATION = "modulation"
|
||||
CONF_SHAPING = "shaping"
|
||||
CONF_RX_FLOOR = "rx_floor"
|
||||
CONF_RX_START = "rx_start"
|
||||
CONF_RX_BANDWIDTH = "rx_bandwidth"
|
||||
CONF_RX_DURATION = "rx_duration"
|
||||
CONF_BITRATE = "bitrate"
|
||||
CONF_PAYLOAD_LENGTH = "payload_length"
|
||||
CONF_PREAMBLE_SIZE = "preamble_size"
|
||||
CONF_PREAMBLE_POLARITY = "preamble_polarity"
|
||||
CONF_PREAMBLE_ERRORS = "preamble_errors"
|
||||
CONF_SYNC_VALUE = "sync_value"
|
||||
CONF_FSK_FDEV = "fsk_fdev"
|
||||
CONF_FSK_RAMP = "fsk_ramp"
|
||||
CONF_FSK_SHAPING = "fsk_shaping"
|
||||
CONF_ON_PACKET = "on_packet"
|
||||
|
||||
sx127x_ns = cg.esphome_ns.namespace("sx127x")
|
||||
SX127x = sx127x_ns.class_("SX127x", cg.Component, spi.SPIDevice)
|
||||
|
@ -32,10 +43,12 @@ PA_PIN = {
|
|||
}
|
||||
|
||||
SHAPING = {
|
||||
"BT_0_3": SX127xPaRamp.SHAPING_BT_0_3,
|
||||
"BT_0_5": SX127xPaRamp.SHAPING_BT_0_5,
|
||||
"BT_1_0": SX127xPaRamp.SHAPING_BT_1_0,
|
||||
"NONE": SX127xPaRamp.SHAPING_NONE,
|
||||
"CUTOFF_BR_X_2": SX127xPaRamp.CUTOFF_BR_X_2,
|
||||
"CUTOFF_BR_X_1": SX127xPaRamp.CUTOFF_BR_X_1,
|
||||
"GAUSSIAN_BT_0_3": SX127xPaRamp.GAUSSIAN_BT_0_3,
|
||||
"GAUSSIAN_BT_0_5": SX127xPaRamp.GAUSSIAN_BT_0_5,
|
||||
"GAUSSIAN_BT_1_0": SX127xPaRamp.GAUSSIAN_BT_1_0,
|
||||
"NO_SHAPING": SX127xPaRamp.NO_SHAPING,
|
||||
}
|
||||
|
||||
RAMP = {
|
||||
|
@ -89,18 +102,33 @@ RX_BW = {
|
|||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(SX127x),
|
||||
cv.Optional(CONF_DIO0_PIN): pins.internal_gpio_input_pin_schema,
|
||||
cv.Optional(CONF_DIO2_PIN): pins.internal_gpio_input_pin_schema,
|
||||
cv.Required(CONF_RST_PIN): pins.internal_gpio_output_pin_schema,
|
||||
cv.Required(CONF_NSS_PIN): pins.internal_gpio_output_pin_schema,
|
||||
cv.Required(CONF_FREQUENCY): cv.int_range(min=137000000, max=1020000000),
|
||||
cv.Required(CONF_MODULATION): cv.enum(MOD),
|
||||
cv.Optional(CONF_SHAPING, default="NO_SHAPING"): cv.enum(SHAPING),
|
||||
cv.Optional(CONF_BITRATE, default=0): cv.int_range(min=0, max=300000),
|
||||
cv.Optional(CONF_FSK_FDEV, default=5000): cv.int_range(min=0, max=100000),
|
||||
cv.Optional(CONF_FSK_RAMP, default="40us"): cv.enum(RAMP),
|
||||
cv.Optional(CONF_FSK_SHAPING, default="NONE"): cv.enum(SHAPING),
|
||||
cv.Optional(CONF_SYNC_VALUE, default=[]): cv.ensure_list(cv.hex_uint8_t),
|
||||
cv.Optional(CONF_PAYLOAD_LENGTH, default=0): cv.int_range(min=0, max=64),
|
||||
cv.Optional(CONF_PREAMBLE_SIZE, default=0): cv.int_range(min=0, max=7),
|
||||
cv.Optional(CONF_PREAMBLE_POLARITY, default=0xAA): cv.All(
|
||||
cv.hex_int, cv.one_of(0xAA, 0x55)
|
||||
),
|
||||
cv.Optional(CONF_PREAMBLE_ERRORS, default=0): cv.int_range(min=0, max=31),
|
||||
cv.Optional(CONF_RX_FLOOR, default=-94): cv.float_range(min=-128, max=-1),
|
||||
cv.Optional(CONF_RX_START, default=True): cv.boolean,
|
||||
cv.Optional(CONF_RX_BANDWIDTH, default="50_0kHz"): cv.enum(RX_BW),
|
||||
cv.Optional(CONF_RX_DURATION, default="0ms"): cv.All(
|
||||
cv.positive_time_period_microseconds,
|
||||
cv.Range(max=TimePeriod(microseconds=1000000000)),
|
||||
),
|
||||
cv.Optional(CONF_PA_PIN, default="BOOST"): cv.enum(PA_PIN),
|
||||
cv.Optional(CONF_PA_POWER, default=17): cv.int_range(min=0, max=17),
|
||||
cv.Optional(CONF_ON_PACKET): automation.validate_automation(single=True),
|
||||
}
|
||||
).extend(spi.spi_device_schema(False, 8e6, "mode0"))
|
||||
|
||||
|
@ -109,17 +137,36 @@ 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")],
|
||||
config[CONF_ON_PACKET],
|
||||
)
|
||||
if CONF_DIO0_PIN in config:
|
||||
dio0_pin = await cg.gpio_pin_expression(config[CONF_DIO0_PIN])
|
||||
cg.add(var.set_dio0_pin(dio0_pin))
|
||||
if CONF_DIO2_PIN in config:
|
||||
dio2_pin = await cg.gpio_pin_expression(config[CONF_DIO2_PIN])
|
||||
cg.add(var.set_dio2_pin(dio2_pin))
|
||||
rst_pin = await cg.gpio_pin_expression(config[CONF_RST_PIN])
|
||||
cg.add(var.set_rst_pin(rst_pin))
|
||||
nss_pin = await cg.gpio_pin_expression(config[CONF_NSS_PIN])
|
||||
cg.add(var.set_nss_pin(nss_pin))
|
||||
cg.add(var.set_frequency(config[CONF_FREQUENCY]))
|
||||
cg.add(var.set_modulation(config[CONF_MODULATION]))
|
||||
cg.add(var.set_shaping(config[CONF_SHAPING]))
|
||||
cg.add(var.set_bitrate(config[CONF_BITRATE]))
|
||||
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_polarity(config[CONF_PREAMBLE_POLARITY]))
|
||||
cg.add(var.set_preamble_errors(config[CONF_PREAMBLE_ERRORS]))
|
||||
cg.add(var.set_sync_value(config[CONF_SYNC_VALUE]))
|
||||
cg.add(var.set_rx_floor(config[CONF_RX_FLOOR]))
|
||||
cg.add(var.set_rx_start(config[CONF_RX_START]))
|
||||
cg.add(var.set_rx_bandwidth(config[CONF_RX_BANDWIDTH]))
|
||||
cg.add(var.set_rx_duration(config[CONF_RX_DURATION]))
|
||||
cg.add(var.set_pa_pin(config[CONF_PA_PIN]))
|
||||
cg.add(var.set_pa_power(config[CONF_PA_POWER]))
|
||||
cg.add(var.set_fsk_fdev(config[CONF_FSK_FDEV]))
|
||||
cg.add(var.set_fsk_ramp(config[CONF_FSK_RAMP]))
|
||||
cg.add(var.set_fsk_shaping(config[CONF_FSK_SHAPING]))
|
||||
|
|
|
@ -7,7 +7,15 @@ namespace sx127x {
|
|||
|
||||
static const char *const TAG = "sx127x";
|
||||
|
||||
uint8_t SX127x::read_register_(uint8_t reg) { return this->single_transfer_((uint8_t) reg & 0x7f, 0x00); }
|
||||
void IRAM_ATTR HOT SX127xStore::gpio_intr(SX127xStore *arg) {
|
||||
if (arg->dio2_toggle) {
|
||||
arg->dio2_pin.pin_mode(gpio::FLAG_INPUT);
|
||||
}
|
||||
arg->dio0_micros = micros();
|
||||
arg->dio0_irq = true;
|
||||
}
|
||||
|
||||
uint8_t SX127x::read_register_(uint8_t reg) { return this->single_transfer_((uint8_t) reg & 0x7F, 0x00); }
|
||||
|
||||
void SX127x::write_register_(uint8_t reg, uint8_t value) { this->single_transfer_((uint8_t) reg | 0x80, value); }
|
||||
|
||||
|
@ -22,6 +30,28 @@ uint8_t SX127x::single_transfer_(uint8_t reg, uint8_t value) {
|
|||
return response;
|
||||
}
|
||||
|
||||
void SX127x::read_fifo_(std::vector<uint8_t> &packet) {
|
||||
this->delegate_->begin_transaction();
|
||||
this->nss_pin_->digital_write(false);
|
||||
this->delegate_->transfer(REG_FIFO & 0x7F);
|
||||
for (uint32_t i = 0; i < this->payload_length_; i++) {
|
||||
packet.push_back(this->delegate_->transfer(0x00));
|
||||
}
|
||||
this->nss_pin_->digital_write(true);
|
||||
this->delegate_->end_transaction();
|
||||
}
|
||||
|
||||
void SX127x::write_fifo_(const std::vector<uint8_t> &packet) {
|
||||
this->delegate_->begin_transaction();
|
||||
this->nss_pin_->digital_write(false);
|
||||
this->delegate_->transfer(REG_FIFO | 0x80);
|
||||
for (uint32_t i = 0; i < this->payload_length_; i++) {
|
||||
this->delegate_->transfer(packet[i]);
|
||||
}
|
||||
this->nss_pin_->digital_write(true);
|
||||
this->delegate_->end_transaction();
|
||||
}
|
||||
|
||||
void SX127x::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up SX127x...");
|
||||
|
||||
|
@ -32,6 +62,20 @@ void SX127x::setup() {
|
|||
// setup reset
|
||||
this->rst_pin_->setup();
|
||||
|
||||
// setup dio0
|
||||
if (this->dio0_pin_) {
|
||||
this->dio0_pin_->setup();
|
||||
this->dio0_pin_->attach_interrupt(SX127xStore::gpio_intr, &this->store_, gpio::INTERRUPT_RISING_EDGE);
|
||||
}
|
||||
|
||||
// setup dio2
|
||||
if (this->dio2_pin_) {
|
||||
this->dio2_pin_->setup();
|
||||
this->dio2_pin_->pin_mode(gpio::FLAG_OPEN_DRAIN);
|
||||
this->store_.dio2_pin = this->dio2_pin_->to_isr();
|
||||
this->store_.dio2_toggle = true;
|
||||
}
|
||||
|
||||
// start spi
|
||||
this->spi_setup();
|
||||
|
||||
|
@ -40,6 +84,8 @@ void SX127x::setup() {
|
|||
}
|
||||
|
||||
void SX127x::configure() {
|
||||
uint8_t bit_sync = BIT_SYNC_OFF;
|
||||
|
||||
// toggle chip reset
|
||||
this->rst_pin_->digital_write(false);
|
||||
delay(1);
|
||||
|
@ -53,7 +99,7 @@ void SX127x::configure() {
|
|||
}
|
||||
|
||||
// set modulation and make sure transceiver is in sleep mode
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_LF_ON | MODE_SLEEP);
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_SLEEP);
|
||||
delay(1);
|
||||
|
||||
// set freq
|
||||
|
@ -70,6 +116,47 @@ void SX127x::configure() {
|
|||
// set the channel bw
|
||||
this->write_register_(REG_RX_BW, this->rx_bandwidth_);
|
||||
|
||||
// set bitrate
|
||||
if (this->bitrate_ > 0) {
|
||||
uint64_t bitrate = (32000000u + this->bitrate_ / 2) / this->bitrate_;
|
||||
this->write_register_(REG_BITRATE_MSB, (uint8_t) ((bitrate >> 8) & 0xFF));
|
||||
this->write_register_(REG_BITRATE_LSB, (uint8_t) ((bitrate >> 0) & 0xFF));
|
||||
bit_sync = BIT_SYNC_ON;
|
||||
}
|
||||
|
||||
// configure dio mapping
|
||||
if (this->payload_length_ > 0) {
|
||||
this->write_register_(REG_DIO_MAPPING1, DIO0_MAPPING_00);
|
||||
} else if (this->rx_duration_ > 0) {
|
||||
this->write_register_(REG_DIO_MAPPING1, DIO0_MAPPING_01);
|
||||
} else {
|
||||
this->write_register_(REG_DIO_MAPPING1, DIO0_MAPPING_11);
|
||||
}
|
||||
if (this->preamble_size_ > 0) {
|
||||
this->write_register_(REG_DIO_MAPPING2, MAP_PREAMBLE_INT);
|
||||
} else {
|
||||
this->write_register_(REG_DIO_MAPPING2, MAP_RSSI_INT);
|
||||
}
|
||||
|
||||
// configure rx and afc
|
||||
uint8_t trigger = (this->preamble_size_ > 0) ? TRIGGER_PREAMBLE : TRIGGER_RSSI;
|
||||
this->write_register_(REG_AFC_FEI, AFC_AUTO_CLEAR_ON);
|
||||
if (this->modulation_ == MOD_FSK) {
|
||||
this->rx_config_ = AFC_AUTO_ON | AGC_AUTO_ON | trigger;
|
||||
} else {
|
||||
this->rx_config_ = AGC_AUTO_ON | trigger;
|
||||
}
|
||||
this->write_register_(REG_RX_CONFIG, this->rx_config_);
|
||||
|
||||
// configure packet mode
|
||||
this->write_register_(REG_PACKET_CONFIG_1, 0x00);
|
||||
if (this->payload_length_ > 0) {
|
||||
this->write_register_(REG_PACKET_CONFIG_2, PACKET_MODE);
|
||||
} else {
|
||||
this->write_register_(REG_PACKET_CONFIG_2, CONTINUOUS_MODE);
|
||||
}
|
||||
this->write_register_(REG_PAYLOAD_LENGTH, this->payload_length_);
|
||||
|
||||
// config pa
|
||||
if (this->pa_pin_ == PA_PIN_BOOST) {
|
||||
this->pa_power_ = std::max(this->pa_power_, (uint32_t) 2);
|
||||
|
@ -79,23 +166,42 @@ void SX127x::configure() {
|
|||
this->pa_power_ = std::min(this->pa_power_, (uint32_t) 14);
|
||||
this->write_register_(REG_PA_CONFIG, (this->pa_power_ - 0) | this->pa_pin_ | PA_MAX_POWER);
|
||||
}
|
||||
if (this->modulation_ == MOD_FSK) {
|
||||
this->write_register_(REG_PA_RAMP, this->fsk_ramp_ | this->fsk_shaping_);
|
||||
this->write_register_(REG_PA_RAMP, this->shaping_ | this->fsk_ramp_);
|
||||
this->write_register_(REG_FIFO_THRESH, TX_START_FIFO_EMPTY);
|
||||
|
||||
// config bit synchronizer
|
||||
if (this->sync_value_.size() > 0) {
|
||||
uint8_t polarity = (this->preamble_polarity_ == 0xAA) ? PREAMBLE_AA : PREAMBLE_55;
|
||||
uint8_t size = this->sync_value_.size() - 1;
|
||||
this->write_register_(REG_SYNC_CONFIG, SYNC_ON | polarity | size);
|
||||
for (uint32_t i = 0; i < this->sync_value_.size(); i++) {
|
||||
this->write_register_(REG_SYNC_VALUE1 + i, this->sync_value_[i]);
|
||||
}
|
||||
} else {
|
||||
this->write_register_(REG_PA_RAMP, this->fsk_ramp_);
|
||||
this->write_register_(REG_SYNC_CONFIG, SYNC_OFF);
|
||||
}
|
||||
|
||||
// disable packet mode
|
||||
this->write_register_(REG_PACKET_CONFIG_1, 0x00);
|
||||
this->write_register_(REG_PACKET_CONFIG_2, 0x00);
|
||||
// config preamble detector
|
||||
if (this->preamble_size_ > 0 && this->preamble_size_ < 4) {
|
||||
uint8_t size = (this->preamble_size_ - 1) << PREAMBLE_BYTES_SHIFT;
|
||||
uint8_t errors = this->preamble_errors_;
|
||||
this->write_register_(REG_PREAMBLE_DETECT, PREAMBLE_DETECTOR_ON | size | errors);
|
||||
} else {
|
||||
this->write_register_(REG_PREAMBLE_DETECT, PREAMBLE_DETECTOR_OFF);
|
||||
}
|
||||
this->write_register_(REG_PREAMBLE_MSB, 0);
|
||||
this->write_register_(REG_PREAMBLE_LSB, this->preamble_size_);
|
||||
|
||||
// disable bit synchronizer, disable sync generation and setup threshold
|
||||
this->write_register_(REG_SYNC_CONFIG, 0x00);
|
||||
this->write_register_(REG_OOK_PEAK, OOK_THRESH_STEP_0_5 | OOK_THRESH_PEAK);
|
||||
// config sync generation and setup ook threshold
|
||||
this->write_register_(REG_OOK_PEAK, bit_sync | OOK_THRESH_STEP_0_5 | OOK_THRESH_PEAK);
|
||||
this->write_register_(REG_OOK_AVG, OOK_THRESH_DEC_1_8);
|
||||
|
||||
// set ook floor
|
||||
// set rx floor
|
||||
this->write_register_(REG_OOK_FIX, 256 + int(this->rx_floor_ * 2.0));
|
||||
this->write_register_(REG_RSSI_THRESH, std::abs(int(this->rx_floor_ * 2.0)));
|
||||
|
||||
// clear irq flag
|
||||
this->store_.dio0_irq = false;
|
||||
|
||||
// enable standby mode
|
||||
this->set_mode_standby();
|
||||
|
@ -108,18 +214,68 @@ void SX127x::configure() {
|
|||
}
|
||||
}
|
||||
|
||||
void SX127x::set_mode_standby() { this->write_register_(REG_OP_MODE, this->modulation_ | MODE_LF_ON | MODE_STDBY); }
|
||||
void SX127x::transmit_packet(const std::vector<uint8_t> &packet) {
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_STDBY);
|
||||
delay(1);
|
||||
this->write_fifo_(packet);
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_TX_FS);
|
||||
delay(1);
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_TX);
|
||||
while (!this->store_.dio0_irq)
|
||||
;
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_STDBY);
|
||||
delay(1);
|
||||
if (this->rx_start_) {
|
||||
this->set_mode_rx();
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void SX127x::loop() {
|
||||
if (this->store_.dio0_irq) {
|
||||
if (this->payload_length_ > 0) {
|
||||
// read packet, reset the receiver and call the trigger
|
||||
std::vector<uint8_t> packet;
|
||||
this->read_fifo_(packet);
|
||||
this->store_.dio0_irq = false;
|
||||
this->write_register_(REG_RX_CONFIG, RESTART_PLL_LOCK | this->rx_config_);
|
||||
this->packet_trigger_->trigger(packet);
|
||||
} else {
|
||||
// wait until rx duration expires then reset rx and change dio2 mode to avoid overloading
|
||||
// remote receiver with too much noise
|
||||
if ((micros() - this->store_.dio0_micros) >= this->rx_duration_) {
|
||||
if (this->dio2_pin_) {
|
||||
this->dio2_pin_->pin_mode(gpio::FLAG_OPEN_DRAIN);
|
||||
}
|
||||
this->store_.dio0_irq = false;
|
||||
this->write_register_(REG_RX_CONFIG, RESTART_PLL_LOCK | this->rx_config_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SX127x::set_mode_standby() { this->write_register_(REG_OP_MODE, this->modulation_ | MODE_STDBY); }
|
||||
|
||||
void SX127x::set_mode_rx() {
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_LF_ON | MODE_RX_FS);
|
||||
if (this->dio2_pin_) {
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_STDBY);
|
||||
delay(1);
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_LF_ON | MODE_RX);
|
||||
this->dio2_pin_->pin_mode(this->modulation_ == MOD_OOK ? gpio::FLAG_INPUT : gpio::FLAG_OPEN_DRAIN);
|
||||
}
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_RX_FS);
|
||||
delay(1);
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_RX);
|
||||
}
|
||||
|
||||
void SX127x::set_mode_tx() {
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_LF_ON | MODE_TX_FS);
|
||||
if (this->dio2_pin_) {
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_STDBY);
|
||||
delay(1);
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_LF_ON | MODE_TX);
|
||||
this->dio2_pin_->pin_mode(gpio::FLAG_OUTPUT);
|
||||
}
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_TX_FS);
|
||||
delay(1);
|
||||
this->write_register_(REG_OP_MODE, this->modulation_ | MODE_TX);
|
||||
}
|
||||
|
||||
void SX127x::dump_config() {
|
||||
|
@ -130,24 +286,33 @@ void SX127x::dump_config() {
|
|||
ESP_LOGCONFIG(TAG, "SX127x:");
|
||||
LOG_PIN(" NSS Pin: ", this->nss_pin_);
|
||||
LOG_PIN(" RST Pin: ", this->rst_pin_);
|
||||
ESP_LOGCONFIG(TAG, " PA Pin: %s", this->pa_pin_ == PA_PIN_BOOST ? "BOOST" : "RFO");
|
||||
ESP_LOGCONFIG(TAG, " PA Power: %" PRIu32 " dBm", this->pa_power_);
|
||||
LOG_PIN(" DIO0 Pin: ", this->dio0_pin_);
|
||||
LOG_PIN(" DIO2 Pin: ", this->dio2_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Frequency: %f MHz", (float) this->frequency_ / 1000000);
|
||||
ESP_LOGCONFIG(TAG, " Modulation: %s", this->modulation_ == MOD_FSK ? "FSK" : "OOK");
|
||||
ESP_LOGCONFIG(TAG, " Bitrate: %" PRIu32 "b/s", this->bitrate_);
|
||||
ESP_LOGCONFIG(TAG, " Rx Duration: %" PRIu32 " us", this->rx_duration_);
|
||||
ESP_LOGCONFIG(TAG, " Rx Bandwidth: %.1f kHz", (float) rx_bw / 1000);
|
||||
ESP_LOGCONFIG(TAG, " Rx Start: %s", this->rx_start_ ? "true" : "false");
|
||||
ESP_LOGCONFIG(TAG, " Rx Floor: %.1f dBm", this->rx_floor_);
|
||||
ESP_LOGCONFIG(TAG, " Payload Length: %" PRIu32, this->payload_length_);
|
||||
ESP_LOGCONFIG(TAG, " Preamble Polarity: 0x%X", this->preamble_polarity_);
|
||||
ESP_LOGCONFIG(TAG, " Preamble Size: %" PRIu8, this->preamble_size_);
|
||||
ESP_LOGCONFIG(TAG, " Preamble Errors: %" PRIu8, this->preamble_errors_);
|
||||
if (this->sync_value_.size() > 0) {
|
||||
ESP_LOGCONFIG(TAG, " Sync Value: 0x%s", format_hex(this->sync_value_).c_str());
|
||||
}
|
||||
if (this->modulation_ == MOD_FSK) {
|
||||
static const char *SHAPING_LUT[4] = {"NO_SHAPING", "GAUSSIAN_BT_1_0", "GAUSSIAN_BT_0_5", "GAUSSIAN_BT_0_3"};
|
||||
ESP_LOGCONFIG(TAG, " Shaping: %s", SHAPING_LUT[this->shaping_ >> 5]);
|
||||
} else {
|
||||
static const char *SHAPING_LUT[4] = {"NO_SHAPING", "CUTOFF_BR_X_1", "CUTOFF_BR_X_2", "ERROR"};
|
||||
ESP_LOGCONFIG(TAG, " Shaping: %s", SHAPING_LUT[this->shaping_ >> 5]);
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " PA Pin: %s", this->pa_pin_ == PA_PIN_BOOST ? "BOOST" : "RFO");
|
||||
ESP_LOGCONFIG(TAG, " PA Power: %" PRIu32 " dBm", this->pa_power_);
|
||||
ESP_LOGCONFIG(TAG, " FSK Fdev: %" PRIu32 " Hz", this->fsk_fdev_);
|
||||
ESP_LOGCONFIG(TAG, " FSK Ramp: %" PRIu16 " us", RAMP_LUT[this->fsk_ramp_]);
|
||||
if (this->fsk_shaping_ == SHAPING_BT_1_0) {
|
||||
ESP_LOGCONFIG(TAG, " FSK Shaping: BT_1_0");
|
||||
} else if (this->fsk_shaping_ == SHAPING_BT_0_5) {
|
||||
ESP_LOGCONFIG(TAG, " FSK Shaping: BT_0_5");
|
||||
} else if (this->fsk_shaping_ == SHAPING_BT_0_3) {
|
||||
ESP_LOGCONFIG(TAG, " FSK Shaping: BT_0_3");
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, " FSK Shaping: NONE");
|
||||
}
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Configuring SX127x failed");
|
||||
}
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/components/spi/spi.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <vector>
|
||||
|
||||
namespace esphome {
|
||||
namespace sx127x {
|
||||
|
||||
enum SX127xReg : uint8_t {
|
||||
REG_FIFO = 0x00,
|
||||
REG_OP_MODE = 0x01,
|
||||
REG_BITRATE_MSB = 0x02,
|
||||
REG_BITRATE_LSB = 0x03,
|
||||
REG_FDEV_MSB = 0x04,
|
||||
REG_FDEV_LSB = 0x05,
|
||||
REG_FRF_MSB = 0x06,
|
||||
|
@ -14,16 +22,64 @@ enum SX127xReg : uint8_t {
|
|||
REG_FRF_LSB = 0x08,
|
||||
REG_PA_CONFIG = 0x09,
|
||||
REG_PA_RAMP = 0x0A,
|
||||
REG_RX_CONFIG = 0x0D,
|
||||
REG_RSSI_THRESH = 0x10,
|
||||
REG_RX_BW = 0x12,
|
||||
REG_OOK_PEAK = 0x14,
|
||||
REG_OOK_FIX = 0x15,
|
||||
REG_OOK_AVG = 0x16,
|
||||
REG_AFC_FEI = 0x1A,
|
||||
REG_PREAMBLE_DETECT = 0x1F,
|
||||
REG_PREAMBLE_MSB = 0x25,
|
||||
REG_PREAMBLE_LSB = 0x26,
|
||||
REG_SYNC_CONFIG = 0x27,
|
||||
REG_SYNC_VALUE1 = 0x28,
|
||||
REG_SYNC_VALUE2 = 0x29,
|
||||
REG_SYNC_VALUE3 = 0x2A,
|
||||
REG_SYNC_VALUE4 = 0x2B,
|
||||
REG_SYNC_VALUE5 = 0x2C,
|
||||
REG_SYNC_VALUE6 = 0x2D,
|
||||
REG_SYNC_VALUE7 = 0x2E,
|
||||
REG_SYNC_VALUE8 = 0x2F,
|
||||
REG_PACKET_CONFIG_1 = 0x30,
|
||||
REG_PACKET_CONFIG_2 = 0x31,
|
||||
REG_PAYLOAD_LENGTH = 0x32,
|
||||
REG_FIFO_THRESH = 0x35,
|
||||
REG_DIO_MAPPING1 = 0x40,
|
||||
REG_DIO_MAPPING2 = 0x41,
|
||||
REG_VERSION = 0x42
|
||||
};
|
||||
|
||||
enum SX127xRxConfig : uint8_t {
|
||||
RESTART_NO_LOCK = 0x40,
|
||||
RESTART_PLL_LOCK = 0x20,
|
||||
AFC_AUTO_ON = 0x10,
|
||||
AGC_AUTO_ON = 0x08,
|
||||
TRIGGER_NONE = 0x00,
|
||||
TRIGGER_RSSI = 0x01,
|
||||
TRIGGER_PREAMBLE = 0x06,
|
||||
TRIGGER_ALL = 0x07,
|
||||
};
|
||||
|
||||
enum SX127xFifoThresh : uint8_t {
|
||||
TX_START_FIFO_EMPTY = 0x80,
|
||||
TX_START_FIFO_LEVEL = 0x00,
|
||||
};
|
||||
|
||||
enum SX127xAfcFei : uint8_t {
|
||||
AFC_AUTO_CLEAR_ON = 0x01,
|
||||
};
|
||||
|
||||
enum SX127xSyncConfig : uint8_t {
|
||||
AUTO_RESTART_OFF = 0x00,
|
||||
AUTO_RESTART_NO_LOCK = 0x80,
|
||||
AUTO_RESTART_PLL_LOCK = 0x40,
|
||||
PREAMBLE_AA = 0x00,
|
||||
PREAMBLE_55 = 0x20,
|
||||
SYNC_OFF = 0x00,
|
||||
SYNC_ON = 0x10,
|
||||
};
|
||||
|
||||
enum SX127xOpMode : uint8_t {
|
||||
MOD_FSK = 0x00,
|
||||
MOD_OOK = 0x20,
|
||||
|
@ -36,6 +92,35 @@ enum SX127xOpMode : uint8_t {
|
|||
MODE_SLEEP = 0x00
|
||||
};
|
||||
|
||||
enum SX127xDioMapping1 : uint8_t {
|
||||
DIO0_MAPPING_00 = 0x00,
|
||||
DIO0_MAPPING_01 = 0x40,
|
||||
DIO0_MAPPING_10 = 0x80,
|
||||
DIO0_MAPPING_11 = 0xC0,
|
||||
DIO1_MAPPING_00 = 0x00,
|
||||
DIO1_MAPPING_01 = 0x10,
|
||||
DIO1_MAPPING_10 = 0x20,
|
||||
DIO1_MAPPING_11 = 0x30,
|
||||
DIO2_MAPPING_00 = 0x00,
|
||||
DIO2_MAPPING_01 = 0x04,
|
||||
DIO2_MAPPING_10 = 0x08,
|
||||
DIO2_MAPPING_11 = 0x0C,
|
||||
};
|
||||
|
||||
enum SX127xPreambleDetect : uint8_t {
|
||||
PREAMBLE_DETECTOR_ON = 0x80,
|
||||
PREAMBLE_DETECTOR_OFF = 0x00,
|
||||
PREAMBLE_BYTES_1 = 0x00,
|
||||
PREAMBLE_BYTES_2 = 0x20,
|
||||
PREAMBLE_BYTES_3 = 0x40,
|
||||
PREAMBLE_BYTES_SHIFT = 0x05,
|
||||
};
|
||||
|
||||
enum SX127xDioMapping2 : uint8_t {
|
||||
MAP_PREAMBLE_INT = 0x01,
|
||||
MAP_RSSI_INT = 0x00,
|
||||
};
|
||||
|
||||
enum SX127xOokPeak : uint8_t {
|
||||
BIT_SYNC_ON = 0x20,
|
||||
BIT_SYNC_OFF = 0x00,
|
||||
|
@ -63,6 +148,11 @@ enum SX127xOokAvg : uint8_t {
|
|||
OOK_THRESH_DEC_1 = 0x00
|
||||
};
|
||||
|
||||
enum SX127xPacketConfig2 : uint8_t {
|
||||
CONTINUOUS_MODE = 0x00,
|
||||
PACKET_MODE = 0x40,
|
||||
};
|
||||
|
||||
enum SX127xRxBw : uint8_t {
|
||||
RX_BW_2_6 = 0x17,
|
||||
RX_BW_3_1 = 0x0F,
|
||||
|
@ -88,10 +178,12 @@ enum SX127xRxBw : uint8_t {
|
|||
};
|
||||
|
||||
enum SX127xPaRamp : uint8_t {
|
||||
SHAPING_BT_0_3 = 0x60,
|
||||
SHAPING_BT_0_5 = 0x40,
|
||||
SHAPING_BT_1_0 = 0x20,
|
||||
SHAPING_NONE = 0x00,
|
||||
CUTOFF_BR_X_2 = 0x40,
|
||||
CUTOFF_BR_X_1 = 0x20,
|
||||
GAUSSIAN_BT_0_3 = 0x60,
|
||||
GAUSSIAN_BT_0_5 = 0x40,
|
||||
GAUSSIAN_BT_1_0 = 0x20,
|
||||
NO_SHAPING = 0x00,
|
||||
PA_RAMP_10 = 0x0F,
|
||||
PA_RAMP_12 = 0x0E,
|
||||
PA_RAMP_15 = 0x0D,
|
||||
|
@ -110,6 +202,14 @@ enum SX127xPaRamp : uint8_t {
|
|||
PA_RAMP_3400 = 0x00
|
||||
};
|
||||
|
||||
struct SX127xStore {
|
||||
static void gpio_intr(SX127xStore *arg);
|
||||
volatile uint32_t dio0_micros{0};
|
||||
volatile bool dio0_irq{false};
|
||||
volatile bool dio2_toggle{false};
|
||||
ISRInternalGPIOPin dio2_pin;
|
||||
};
|
||||
|
||||
enum SX127xPaConfig : uint8_t { PA_PIN_RFO = 0x00, PA_PIN_BOOST = 0x80, PA_MAX_POWER = 0x70 };
|
||||
|
||||
class SX127x : public Component,
|
||||
|
@ -118,38 +218,64 @@ class SX127x : public Component,
|
|||
public:
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
void set_dio0_pin(InternalGPIOPin *dio0_pin) { this->dio0_pin_ = dio0_pin; }
|
||||
void set_dio2_pin(InternalGPIOPin *dio2_pin) { this->dio2_pin_ = dio2_pin; }
|
||||
void set_rst_pin(InternalGPIOPin *rst_pin) { this->rst_pin_ = rst_pin; }
|
||||
void set_nss_pin(InternalGPIOPin *nss_pin) { this->nss_pin_ = nss_pin; }
|
||||
void set_frequency(uint32_t frequency) { this->frequency_ = frequency; }
|
||||
void set_bitrate(uint32_t bitrate) { this->bitrate_ = bitrate; }
|
||||
void set_modulation(SX127xOpMode modulation) { this->modulation_ = modulation; }
|
||||
void set_fsk_shaping(SX127xPaRamp shaping) { this->fsk_shaping_ = shaping; }
|
||||
void set_shaping(SX127xPaRamp shaping) { this->shaping_ = shaping; }
|
||||
void set_fsk_ramp(SX127xPaRamp ramp) { this->fsk_ramp_ = ramp; }
|
||||
void set_fsk_fdev(uint32_t fdev) { this->fsk_fdev_ = fdev; }
|
||||
void set_rx_start(bool start) { this->rx_start_ = start; }
|
||||
void set_rx_floor(float floor) { this->rx_floor_ = floor; }
|
||||
void set_rx_bandwidth(SX127xRxBw bandwidth) { this->rx_bandwidth_ = bandwidth; }
|
||||
void set_rx_duration(uint32_t duration) { this->rx_duration_ = duration; }
|
||||
void set_pa_pin(SX127xPaConfig pin) { this->pa_pin_ = pin; }
|
||||
void set_pa_power(uint32_t power) { this->pa_power_ = power; }
|
||||
void set_sync_value(const std::vector<uint8_t> &sync_value) { this->sync_value_ = sync_value; }
|
||||
void set_payload_length(uint8_t payload_length) { this->payload_length_ = payload_length; }
|
||||
void set_preamble_polarity(uint8_t preamble_polarity) { this->preamble_polarity_ = preamble_polarity; }
|
||||
void set_preamble_size(uint8_t preamble_size) { this->preamble_size_ = preamble_size; }
|
||||
void set_preamble_errors(uint8_t preamble_errors) { this->preamble_errors_ = preamble_errors; }
|
||||
void set_mode_standby();
|
||||
void set_mode_tx();
|
||||
void set_mode_rx();
|
||||
void configure();
|
||||
void transmit_packet(const std::vector<uint8_t> &packet);
|
||||
Trigger<std::vector<uint8_t>> *get_packet_trigger() const { return this->packet_trigger_; };
|
||||
|
||||
protected:
|
||||
void write_fifo_(const std::vector<uint8_t> &packet);
|
||||
void read_fifo_(std::vector<uint8_t> &packet);
|
||||
void write_register_(uint8_t reg, uint8_t value);
|
||||
uint8_t single_transfer_(uint8_t reg, uint8_t value);
|
||||
uint8_t read_register_(uint8_t reg);
|
||||
Trigger<std::vector<uint8_t>> *packet_trigger_{new Trigger<std::vector<uint8_t>>()};
|
||||
std::vector<uint8_t> sync_value_;
|
||||
InternalGPIOPin *dio0_pin_{nullptr};
|
||||
InternalGPIOPin *dio2_pin_{nullptr};
|
||||
InternalGPIOPin *rst_pin_{nullptr};
|
||||
InternalGPIOPin *nss_pin_{nullptr};
|
||||
SX127xStore store_;
|
||||
SX127xPaConfig pa_pin_;
|
||||
SX127xRxBw rx_bandwidth_;
|
||||
SX127xOpMode modulation_;
|
||||
SX127xPaRamp fsk_shaping_;
|
||||
SX127xPaRamp shaping_;
|
||||
SX127xPaRamp fsk_ramp_;
|
||||
uint32_t fsk_fdev_;
|
||||
uint32_t frequency_;
|
||||
uint32_t bitrate_;
|
||||
uint32_t rx_duration_;
|
||||
uint32_t pa_power_;
|
||||
uint32_t payload_length_;
|
||||
uint8_t preamble_polarity_;
|
||||
uint8_t preamble_size_;
|
||||
uint8_t preamble_errors_;
|
||||
uint8_t rx_config_;
|
||||
float rx_floor_;
|
||||
bool rx_start_;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue