mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-08-22 08:09:44 +00:00
Merge pull request #3115 from oltaco/meshnology_w12
Add support for Meshnology W12 and LR2021 Wrapper
This commit is contained in:
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
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 {
|
||||
@@ -238,6 +239,12 @@ public:
|
||||
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 {
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
|
||||
@@ -77,6 +77,8 @@ public:
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user