Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions boards/meshnology_w12.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_16MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "opi",
"hwids": [["0x303A", "0x0002"], ["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "meshnology_w12"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "heltec_wifi_lora_32 v5 (16 MB FLASH, 8 MB PSRAM)",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},
"url": "https://heltec.org/",
"vendor": "heltec"
}
6 changes: 6 additions & 0 deletions examples/simple_repeater/MyMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,12 @@ bool MyMesh::setRxBoostedGain(bool enable) {
return radio_driver.setRxBoostedGainMode(enable);
}

#if defined(USE_LR2021)
bool MyMesh::configSideDetectors(const uint8_t sideDetSFs[], uint8_t num, float bw) {
return radio_driver.configSideDetectors(sideDetSFs, num, bw);
}
#endif

void MyMesh::formatNeighborsReply(char *reply) {
char *dp = reply;

Expand Down
4 changes: 4 additions & 0 deletions examples/simple_repeater/MyMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,8 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {

bool setRxBoostedGain(bool enable) override;

#if defined(USE_LR2021)
virtual bool configSideDetectors(const uint8_t sideDetSFs[], uint8_t num, float bw) override;
#endif

};
30 changes: 30 additions & 0 deletions src/helpers/CommonCLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,28 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
_prefs->adc_multiplier = 0.0f;
strcpy(reply, "Error: unsupported");
};
#if defined(USE_LR2021)
} else if (memcmp(config, "extra.sf ", 9) == 0) {
strcpy(tmp, &config[9]);
const char *parts[4];
uint8_t sideDetSFs[4];
int num = mesh::Utils::parseTextParts(tmp, parts, 4);
if (num > 3) {
sprintf(reply, "Invalid extra SF config");
} else {
for (int i = 0; i < num; i++) {
sideDetSFs[i] = atoi(parts[i]);
}
sideDetSFs[num] = 0;
if (_callbacks->configSideDetectors(sideDetSFs, num, _prefs->bw)) {
for (int i = 0; i <= num; i++) _prefs->extra_sf[i] = sideDetSFs[i];
savePrefs();
sprintf(reply, "OK - extra SFs set");
} else {
sprintf(reply, "Invalid extra SF config");
}
}
#endif
} else {
strcpy(reply, "unknown config: ");
StrHelper::strncpy(&reply[16], config, 160-17);
Expand Down Expand Up @@ -922,6 +944,14 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
#else
strcpy(reply, "ERROR: Power management not supported");
#endif
} else if (memcmp(config, "extra.sf", 8) == 0) {
char* tmp = reply;
for (int i = 0; i < 3 && _prefs->extra_sf[i] != 0; i++) {
tmp += sprintf(tmp, "%s%d", (i == 0) ? "" : ",", _prefs->extra_sf[i]);
}
if (tmp == reply) {
sprintf(reply, "No extra SF configured");
}
} else {
sprintf(reply, "??: %s", config);
}
Expand Down
7 changes: 7 additions & 0 deletions src/helpers/CommonCLI.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class NodePrefs : public ConfigSerializer {
uint8_t path_hash_mode = 0; // which path mode to use when sending
uint8_t loop_detect = 0;
uint8_t cad_enabled = 0; // hardware Channel Activity Detection before TX (boolean)
uint8_t extra_sf[4];

private:
class RadioPrefs : public ConfigSerializer {
Expand Down Expand Up @@ -238,6 +239,12 @@ class CommonCLICallbacks {
virtual bool setRxBoostedGain(bool enable) {
return false; // CommonCLI reports unsupported if not overridden by wrapper
};

#if defined(USE_LR2021)
virtual bool configSideDetectors(const uint8_t sideDetSFs[], uint8_t num, float bw) {
return false; // Override in wrapper
}
#endif
};

class CommonCLI {
Expand Down
76 changes: 76 additions & 0 deletions src/helpers/radiolib/CustomLR2021.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#pragma once

#include <RadioLib.h>
#include "MeshCore.h"

class CustomLR2021 : public LR2021 {
bool _rx_boosted = false;

public:
CustomLR2021(Module *mod) : LR2021(mod) { irqDioNum = LR2021_IRQ_DIO; }

bool std_init(SPIClass* spi = NULL)
{

#ifdef LR2021_TCXO_VOLTAGE
float tcxo = LR2021_TCXO_VOLTAGE;
#else
float tcxo = 1.6f;
#endif

#ifdef LORA_CR
uint8_t cr = LORA_CR;
#else
uint8_t cr = 5;
#endif

#if defined(P_LORA_SCLK)
#ifdef NRF52_PLATFORM
if (spi) { spi->setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI); spi->begin(); }
#elif defined(RP2040_PLATFORM)
if (spi) {
spi->setMISO(P_LORA_MISO);
//spi->setCS(P_LORA_NSS); // Setting CS results in freeze
spi->setSCK(P_LORA_SCLK);
spi->setMOSI(P_LORA_MOSI);
spi->begin();
}
#else
if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
#endif
#endif
int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_LR2021_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
// if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f
if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) {
tcxo = 0.0f;
status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_LR2021_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
}
if (status != RADIOLIB_ERR_NONE) {
Serial.print("ERROR: radio init failed: ");
Serial.println(status);
return false; // fail
}

setCRC(2);
explicitHeader();


#ifdef LR2021_RX_BOOSTED_GAIN
setRxBoostedGainMode(LR2021_RX_BOOSTED_GAIN);
#endif

return true; // success
}

float getFreqMHz() const { return freqMHz; }

bool getRxBoostedGainMode() const { return _rx_boosted; }

bool isReceiving() {
uint32_t irq = getIrqStatus();
bool detected = ((irq & RADIOLIB_LR2021_IRQ_SYNCWORD_VALID) || (irq & RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED));
return detected;
}

uint8_t getSpreadingFactor() const { return spreadingFactor; }
};
107 changes: 107 additions & 0 deletions src/helpers/radiolib/CustomLR2021Wrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#pragma once

#include "CustomLR2021.h"
#include "RadioLibWrappers.h"

#ifndef USE_LR2021
#define USE_LR2021
#endif

#ifndef LR2021_RX_BOOST_LEVEL
#define LR2021_RX_BOOST_LEVEL 7
#endif

class CustomLR2021Wrapper : public RadioLibWrapper {
public:
CustomLR2021Wrapper(CustomLR2021& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }

void setParams(float freq, float bw, uint8_t sf, uint8_t cr) override {
((CustomLR2021 *)_radio)->setFrequency(freq);
((CustomLR2021 *)_radio)->setSpreadingFactor(sf);
((CustomLR2021 *)_radio)->setBandwidth(bw);
((CustomLR2021 *)_radio)->setCodingRate(cr);
updatePreamble(sf);
applySideDetectorConfig();
}

bool configSideDetectors(const uint8_t* sideDetSFs, uint8_t num, float bw) override {
LR2021LoRaSideDetector_t tmp[3];
uint8_t sf = getSpreadingFactor();

if (sf >= 10 && num > 1) { return false; } // only 1 side detector allowed when primary SF >= 10
for (int i = 0; i < num; i++) {
if (sideDetSFs[i] > 12 || sideDetSFs[i] < 5) { return false; } // must be valid SF
if (sideDetSFs[i] <= sf) { return false; } // must be < primary SF
if (sideDetSFs[i] > sf + 4) { return false; } // span must not be > 4

tmp[i].sf = sideDetSFs[i];
float tSym = calcTsym(tmp[i].sf, bw);
if (tSym >= 16.0f) {
tmp[i].ldro = true;
} else {
tmp[i].ldro = false;
}
tmp[i].invertIQ = false;
tmp[i].syncWord = 0x12;
}
int16_t status = ((CustomLR2021 *)_radio)->setSideDetector(tmp, num);
RadioLibWrapper::idle(); // trigger startReceive()
MESH_DEBUG_PRINTLN("setSideDetector() returned %d", status);

if (status == RADIOLIB_ERR_NONE) {
for (int i = 0; i < num; i++) { _sideDet[i] = tmp[i]; }
_numSideDet = num;
} else {
return false;
}

return true;
}

int16_t applySideDetectorConfig() {
int16_t status = ((CustomLR2021 *)_radio)->setSideDetector(_sideDet, _numSideDet);
RadioLibWrapper::idle(); // trigger startReceive()
return status;
}

float calcTsym(uint8_t sf, float bw) {
float tSym = (float)(uint32_t(1) << sf) / (float)bw;
return tSym;
}

bool isReceivingPacket() override {
return ((CustomLR2021 *)_radio)->isReceiving();
}

float getCurrentRSSI() override {
float rssi = -110;
((CustomLR2021 *)_radio)->getRssiInst(&rssi);
return rssi;
}

void onSendFinished() override {
RadioLibWrapper::onSendFinished();
_radio->setPreambleLength(preambleLengthForSF(getSpreadingFactor())); // overcomes weird issues with small and big pkts
}

float getLastRSSI() const override { return ((CustomLR2021 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomLR2021 *)_radio)->getSNR(); }

uint8_t getSpreadingFactor() const override { return ((CustomLR2021 *)_radio)->getSpreadingFactor(); }

bool setRxBoostedGainMode(bool en) override {
((CustomLR2021 *)_radio)->standby(); // LR2021 must be in standby to accept setRxBoostedGainMode
int16_t status = ((CustomLR2021 *)_radio)->setRxBoostedGainMode(en ? LR2021_RX_BOOST_LEVEL: 0);
RadioLibWrapper::idle(); // trigger startReceive()
return status == RADIOLIB_ERR_NONE;
}

bool getRxBoostedGainMode() const override {
return ((CustomLR2021 *)_radio)->getRxBoostedGainMode();
}

protected:
LR2021LoRaSideDetector_t _sideDet[3];
size_t _numSideDet = 0;

};
7 changes: 7 additions & 0 deletions src/helpers/radiolib/RadioLibWrappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ void RadioLibWrapper::loop() {
}

void RadioLibWrapper::startRecv() {
#if defined(USE_LR2021)
_radio->standby(); // without this LR2021 can throw -706 when calling startReceive after hardware CAD when side detectors are enabled
#endif
int err = _radio->startReceive();
if (err == RADIOLIB_ERR_NONE) {
state = STATE_RX;
Expand Down Expand Up @@ -133,7 +136,11 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) {
n_recv++;
}
}
#if defined(USE_LR2021)
state = STATE_RX; // LR2021 stays in Rx after readData, calling startReceive while still in Rx throws -706 errors
#else
state = STATE_IDLE; // need another startReceive()
#endif
}

if (state != STATE_RX) {
Expand Down
2 changes: 2 additions & 0 deletions src/helpers/radiolib/RadioLibWrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class RadioLibWrapper : public mesh::Radio {

virtual bool setRxBoostedGainMode(bool) { return false; }
virtual bool getRxBoostedGainMode() const { return false; }

virtual bool configSideDetectors(const uint8_t sideDetSFs[], uint8_t num, float bw) { return false; }
};

/**
Expand Down
Loading
Loading