Change frame to have prefix showing origin. Tested and all units received from the other tree. I should have committed then, but forgot. Here, the blocking has been activated, but not tested.

This commit is contained in:
John Poole 2026-05-28 21:23:10 -07:00
commit 7f78dfb70e
3 changed files with 96 additions and 14 deletions

View file

@ -50,6 +50,8 @@ build_flags =
-D LORA_SYNC_WORD=0x12
-D LORA_TX_POWER_DBM=14
-D USTORE_MAX_VALUE_LEN=1200
-D SIM_PHY_ENVELOPE=1
-D SIM_PHY_BLOCK_BOB_CY=1
; Live announces are enough for this single-hop field exercise. Do not define
; RNS_PERSIST_PATHS here: the LittleFS-backed path_store compactor can leave an
; active segment FD open while unlinking /path_store_*.dat on ESP32.

View file

@ -17,6 +17,15 @@
#ifndef LORA_BUSY
#error "LORA_BUSY not defined"
#endif
#ifndef NODE_SLOT_INDEX
#define NODE_SLOT_INDEX 255
#endif
#ifndef SIM_PHY_ENVELOPE
#define SIM_PHY_ENVELOPE 0
#endif
#ifndef SIM_PHY_BLOCK_BOB_CY
#define SIM_PHY_BLOCK_BOB_CY 0
#endif
using namespace RNS;
@ -24,7 +33,7 @@ TBeamSupremeLoRaInterface::TBeamSupremeLoRaInterface(const char* name) : Interfa
_IN = true;
_OUT = true;
_bitrate = (double)LORA_SF * ((4.0 / LORA_CR) / (pow(2, LORA_SF) / LORA_BW_KHZ)) * 1000.0;
_HW_MTU = 508;
_HW_MTU = (uint16_t)(LORA_MAX_PAYLOAD * 2);
}
TBeamSupremeLoRaInterface::~TBeamSupremeLoRaInterface() {
@ -82,13 +91,23 @@ void TBeamSupremeLoRaInterface::loop() {
}
int len = _radio->getPacketLength();
uint8_t rx_buf[255];
uint8_t rx_buf[RADIO_MAX_PAYLOAD];
int state = _radio->readData(rx_buf, len);
if (state == RADIOLIB_ERR_NONE && len > 1) {
if (state == RADIOLIB_ERR_NONE) {
_last_rssi = _radio->getRSSI();
_last_snr = _radio->getSNR();
uint8_t physical_tx = 255;
if (!unpack_frame(rx_buf, len, physical_tx)) {
_radio->startReceive();
return;
}
if (len <= 1) {
_radio->startReceive();
return;
}
uint8_t header = rx_buf[0];
uint8_t seq = packet_sequence(header);
@ -118,19 +137,71 @@ void TBeamSupremeLoRaInterface::loop() {
_radio->startReceive();
}
int TBeamSupremeLoRaInterface::transmit_frame(uint8_t header, const uint8_t* payload, size_t payload_len) {
uint8_t tx_buf[RADIO_MAX_PAYLOAD];
#if SIM_PHY_ENVELOPE
tx_buf[0] = PHY_MAGIC_0;
tx_buf[1] = PHY_MAGIC_1;
tx_buf[2] = PHY_VERSION;
tx_buf[3] = (uint8_t)NODE_SLOT_INDEX;
tx_buf[PHY_ENVELOPE_LEN] = header;
memcpy(tx_buf + PHY_ENVELOPE_LEN + 1, payload, payload_len);
return _radio->transmit(tx_buf, PHY_ENVELOPE_LEN + 1 + payload_len);
#else
tx_buf[0] = header;
memcpy(tx_buf + 1, payload, payload_len);
return _radio->transmit(tx_buf, 1 + payload_len);
#endif
}
bool TBeamSupremeLoRaInterface::unpack_frame(uint8_t* frame, int& len, uint8_t& physical_tx) {
#if SIM_PHY_ENVELOPE
if (len < PHY_ENVELOPE_LEN + 1) {
DEBUGF("SIM PHY malformed: short frame len=%d", len);
return false;
}
if (frame[0] != PHY_MAGIC_0 || frame[1] != PHY_MAGIC_1 || frame[2] != PHY_VERSION) {
DEBUGF("SIM PHY malformed: bad envelope len=%d", len);
return false;
}
physical_tx = frame[3];
if (should_drop_physical_tx(physical_tx)) {
DEBUGF("SIM PHY DROP: rx=%u tx=%u len=%d",
(unsigned)NODE_SLOT_INDEX,
(unsigned)physical_tx,
len);
return false;
}
len -= PHY_ENVELOPE_LEN;
memmove(frame, frame + PHY_ENVELOPE_LEN, len);
return true;
#else
(void)frame;
physical_tx = 255;
return true;
#endif
}
bool TBeamSupremeLoRaInterface::should_drop_physical_tx(uint8_t physical_tx) {
#if SIM_PHY_BLOCK_BOB_CY
const uint8_t local = (uint8_t)NODE_SLOT_INDEX;
return (local == 1U && physical_tx == 2U) || (local == 2U && physical_tx == 1U);
#else
(void)physical_tx;
return false;
#endif
}
void TBeamSupremeLoRaInterface::send_outgoing(const Bytes& data) {
if (!_online || !_radio) {
return;
}
try {
uint8_t tx_buf[255];
uint8_t rand_nibble = (uint8_t)(Cryptography::randomnum(256)) & 0xF0;
if ((int)data.size() <= LORA_MAX_PAYLOAD) {
tx_buf[0] = rand_nibble;
memcpy(tx_buf + 1, data.data(), data.size());
int state = _radio->transmit(tx_buf, 1 + data.size());
int state = transmit_frame(rand_nibble, data.data(), data.size());
if (state != RADIOLIB_ERR_NONE) {
ERRORF("LoRa transmit failed, code %d", state);
}
@ -138,17 +209,13 @@ void TBeamSupremeLoRaInterface::send_outgoing(const Bytes& data) {
uint8_t seq = (_tx_seq_ctr++) & HEADER_SEQ_MASK;
uint8_t split_header = rand_nibble | HEADER_SPLIT | seq;
tx_buf[0] = split_header;
memcpy(tx_buf + 1, data.data(), LORA_MAX_PAYLOAD);
int state = _radio->transmit(tx_buf, 1 + LORA_MAX_PAYLOAD);
int state = transmit_frame(split_header, data.data(), LORA_MAX_PAYLOAD);
if (state != RADIOLIB_ERR_NONE) {
ERRORF("LoRa transmit part 1 failed, code %d", state);
}
size_t remainder = data.size() - LORA_MAX_PAYLOAD;
tx_buf[0] = split_header;
memcpy(tx_buf + 1, data.data() + LORA_MAX_PAYLOAD, remainder);
state = _radio->transmit(tx_buf, 1 + remainder);
state = transmit_frame(split_header, data.data() + LORA_MAX_PAYLOAD, remainder);
if (state != RADIOLIB_ERR_NONE) {
ERRORF("LoRa transmit part 2 failed, code %d", state);
}

View file

@ -22,11 +22,24 @@ public:
private:
void send_outgoing(const RNS::Bytes& data) override;
void on_incoming(const RNS::Bytes& data);
int transmit_frame(uint8_t header, const uint8_t* payload, size_t payload_len);
bool unpack_frame(uint8_t* frame, int& len, uint8_t& physical_tx);
static bool should_drop_physical_tx(uint8_t physical_tx);
static constexpr uint8_t HEADER_SPLIT = 0x08;
static constexpr uint8_t HEADER_SEQ_MASK = 0x07;
static constexpr uint8_t SEQ_UNSET = 0xFF;
static constexpr int LORA_MAX_PAYLOAD = 254;
static constexpr int RADIO_MAX_PAYLOAD = 255;
#if defined(SIM_PHY_ENVELOPE) && SIM_PHY_ENVELOPE
static constexpr uint8_t PHY_MAGIC_0 = 0xC2;
static constexpr uint8_t PHY_MAGIC_1 = 0x04;
static constexpr uint8_t PHY_VERSION = 0x01;
static constexpr int PHY_ENVELOPE_LEN = 4;
static constexpr int LORA_MAX_PAYLOAD = RADIO_MAX_PAYLOAD - PHY_ENVELOPE_LEN - 1;
#else
static constexpr int PHY_ENVELOPE_LEN = 0;
static constexpr int LORA_MAX_PAYLOAD = RADIO_MAX_PAYLOAD - 1;
#endif
static bool is_split_packet(uint8_t header) { return (header & HEADER_SPLIT) != 0; }
static uint8_t packet_sequence(uint8_t header) { return header & HEADER_SEQ_MASK; }