mirror of
https://github.com/Genaker/LoraSA.git
synced 2026-07-05 09:22:05 +02:00
Add SCAN_RESULT binary reporting over LoRa
This commit is contained in:
@@ -10,6 +10,9 @@ Comms *HostComms;
|
||||
Comms *Comms0 = NULL;
|
||||
Comms *Comms1 = NULL;
|
||||
|
||||
RadioComms *RxComms = NULL;
|
||||
RadioComms *TxComms = NULL;
|
||||
|
||||
void _onReceiveUsb(size_t len)
|
||||
{
|
||||
if (HostComms == NULL)
|
||||
@@ -102,6 +105,16 @@ bool Comms::initComms(Config &c)
|
||||
Serial.println("Configured none - Initialized no communications on Serial1");
|
||||
}
|
||||
|
||||
if (c.rx_lora != NULL)
|
||||
{
|
||||
RxComms = new RadioComms("RxComms", radio, *c.rx_lora);
|
||||
}
|
||||
|
||||
if (c.tx_lora != NULL)
|
||||
{
|
||||
TxComms = new RadioComms("TxComms", radio, *c.tx_lora);
|
||||
}
|
||||
|
||||
if (!fine)
|
||||
{
|
||||
HostComms = new NoopComms();
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#define __COMMS_H
|
||||
|
||||
#include <HardwareSerial.h>
|
||||
#include <LoRaBoards.h>
|
||||
|
||||
#include <LiLyGo.h>
|
||||
#include <config.h>
|
||||
|
||||
#ifdef HELTEC
|
||||
@@ -109,4 +112,25 @@ extern Comms *Comms0;
|
||||
|
||||
extern Comms *Comms1;
|
||||
|
||||
struct RadioComms
|
||||
{
|
||||
String name;
|
||||
RADIO_TYPE &radio;
|
||||
LoRaConfig &loraCfg;
|
||||
|
||||
RadioComms(String name, RADIO_TYPE &radio, LoRaConfig &cfg)
|
||||
: name(name), radio(radio), loraCfg(cfg)
|
||||
{
|
||||
}
|
||||
|
||||
Message **received;
|
||||
|
||||
int16_t configureRadio();
|
||||
int16_t send(Message &);
|
||||
Message *receive(uint16_t timeout_ms);
|
||||
};
|
||||
|
||||
extern RadioComms *RxComms;
|
||||
extern RadioComms *TxComms;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
#include "comms.h"
|
||||
|
||||
int16_t RadioComms::configureRadio()
|
||||
{
|
||||
int16_t status =
|
||||
radio.begin(loraCfg.freq, loraCfg.bw, loraCfg.sf, loraCfg.cr, loraCfg.sync_word,
|
||||
loraCfg.tx_power, loraCfg.preamble_len);
|
||||
if (status != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
Serial.printf("could not configure Lora: %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!loraCfg.crc)
|
||||
{
|
||||
status = radio.setCRC(0);
|
||||
if (status != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
Serial.printf("could not configure CRC for Lora: %d\n", status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
size_t _write(uint8_t *m, size_t sz, size_t p, uint8_t v)
|
||||
{
|
||||
if (p >= sz)
|
||||
return sz;
|
||||
m[p] = v;
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
size_t _write(uint8_t *m, size_t sz, size_t p, uint8_t *v, size_t v_sz)
|
||||
{
|
||||
while (v_sz > 0)
|
||||
{
|
||||
p = _write(m, sz, p, *v);
|
||||
v++;
|
||||
v_sz--;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#define MAX_MSG 128
|
||||
#define RSSI_HI -80
|
||||
#define DETAIL_RSSIS 8
|
||||
#define RSSI_LO (RSSI_HI - 1 - DETAIL_RSSIS)
|
||||
int16_t RadioComms::send(Message &m)
|
||||
{
|
||||
if (m.type != SCAN_RESULT)
|
||||
{
|
||||
return RADIOLIB_ERR_INVALID_FUNCTION;
|
||||
}
|
||||
|
||||
uint8_t msg[MAX_MSG];
|
||||
size_t dump_sz = m.payload.dump.sz;
|
||||
size_t p = _write(msg, MAX_MSG, 0, (uint8_t)m.type);
|
||||
|
||||
// first cut: dump the RSSI as-is
|
||||
// optimize the message size later
|
||||
p = _write(msg, MAX_MSG, p, (uint8_t *)&m.payload.dump.freqs_khz[0], 4);
|
||||
p = _write(msg, MAX_MSG, p, (uint8_t *)&m.payload.dump.freqs_khz[dump_sz - 1], 4);
|
||||
p = _write(msg, MAX_MSG, p, (uint8_t *)&dump_sz, 2);
|
||||
|
||||
size_t rem = MAX_MSG - p;
|
||||
if (rem > dump_sz)
|
||||
rem = dump_sz;
|
||||
|
||||
uint8_t bits = 0;
|
||||
size_t pp = p;
|
||||
for (int i = 0; i < dump_sz; i++)
|
||||
{
|
||||
if (i * rem / dump_sz > p - pp)
|
||||
{
|
||||
p = _write(msg, MAX_MSG, p, bits);
|
||||
bits = 0;
|
||||
}
|
||||
int16_t v = m.payload.dump.rssis[i];
|
||||
if (v >= 0)
|
||||
{
|
||||
v = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
v += 255;
|
||||
if (v < 0)
|
||||
{
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bits = max(bits, (uint8_t)v);
|
||||
}
|
||||
|
||||
if (dump_sz > 0)
|
||||
{
|
||||
p = _write(msg, MAX_MSG, p, bits);
|
||||
}
|
||||
|
||||
return radio.transmit(msg, p);
|
||||
}
|
||||
|
||||
size_t _read(uint8_t *buf, size_t sz, size_t p, uint8_t *v, size_t len)
|
||||
{
|
||||
for (; p < sz && len > 0; v++, p++, len--)
|
||||
{
|
||||
*v = buf[p];
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
size_t _read(uint8_t *buf, size_t sz, size_t p, uint8_t *v)
|
||||
{
|
||||
return _read(buf, sz, p, v, 1);
|
||||
}
|
||||
|
||||
volatile bool _received = false;
|
||||
void _rcv() { _received = true; }
|
||||
|
||||
Message *RadioComms::receive(uint16_t timeout_ms)
|
||||
{
|
||||
uint8_t msg[MAX_MSG];
|
||||
|
||||
// because of this, receive is single-threaded, single-device
|
||||
_received = false;
|
||||
radio.setDio1Action(_rcv);
|
||||
uint32_t timeout_ticks = (uint32_t)timeout_ms * (1000000 / 15625);
|
||||
|
||||
int16_t status = radio.startReceive(timeout_ticks);
|
||||
if (status != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
radio.clearDio1Action();
|
||||
Serial.printf("Failed to start receive: %d\n", status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// wait on a semaphore
|
||||
while (!_received)
|
||||
{
|
||||
yield();
|
||||
}
|
||||
radio.clearDio1Action();
|
||||
|
||||
size_t len = radio.getPacketLength(true);
|
||||
uint8_t *packet = msg;
|
||||
|
||||
if (len > MAX_MSG)
|
||||
{
|
||||
packet = new uint8_t[len];
|
||||
}
|
||||
status = radio.readData(packet, len);
|
||||
|
||||
if (status == RADIOLIB_ERR_RX_TIMEOUT)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (status != RADIOLIB_ERR_NONE || len == 0)
|
||||
{
|
||||
if (packet != msg)
|
||||
delete[] packet;
|
||||
|
||||
Serial.printf("Failed to read data: E(%d), len == %d\n", status, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len > MAX_MSG)
|
||||
{
|
||||
Serial.printf("Packet is longer than expected: %d\n", len);
|
||||
}
|
||||
|
||||
size_t p;
|
||||
uint8_t b;
|
||||
p = _read(packet, len, 0, &b);
|
||||
|
||||
Message *message = NULL;
|
||||
if (b == SCAN_RESULT)
|
||||
{
|
||||
message = new Message();
|
||||
message->type = SCAN_RESULT;
|
||||
|
||||
uint32_t s, e;
|
||||
size_t dump_sz = 0;
|
||||
p = _read(packet, len, p, (uint8_t *)&s, 4);
|
||||
p = _read(packet, len, p, (uint8_t *)&e, 4);
|
||||
p = _read(packet, len, p, (uint8_t *)&dump_sz, 2);
|
||||
size_t rem = len - p;
|
||||
|
||||
message->payload.dump.sz = dump_sz;
|
||||
if (dump_sz > 0)
|
||||
{
|
||||
message->payload.dump.rssis = new int16_t[dump_sz];
|
||||
message->payload.dump.freqs_khz = new uint32_t[dump_sz];
|
||||
message->payload.dump.freqs_khz[0] = s;
|
||||
message->payload.dump.freqs_khz[dump_sz - 1] = e;
|
||||
|
||||
for (int i = 1; i < dump_sz - 1; i++)
|
||||
{
|
||||
uint32_t incr = (e - s) / (dump_sz - i);
|
||||
s += incr;
|
||||
message->payload.dump.freqs_khz[i] = s;
|
||||
}
|
||||
|
||||
for (int i = 0, k = 0; i < rem; i++)
|
||||
{
|
||||
int j = (i + 1) * dump_sz / rem;
|
||||
int16_t rssi = 0;
|
||||
p = _read(packet, len, p, (uint8_t *)&rssi);
|
||||
rssi -= 255;
|
||||
for (; k < j; k++)
|
||||
{
|
||||
message->payload.dump.rssis[k] = rssi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("Received message type %" PRIu8 ", length %d, but expecting %" PRIu8
|
||||
" - ignoring\n",
|
||||
b, len, (uint8_t)MessageType::SCAN_RESULT);
|
||||
}
|
||||
|
||||
if (packet != msg)
|
||||
{
|
||||
delete[] packet;
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
@@ -88,6 +88,18 @@ Config Config::init()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r.key.equalsIgnoreCase("rx_lora"))
|
||||
{
|
||||
c.rx_lora = configureLora(r.value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r.key.equalsIgnoreCase("tx_lora"))
|
||||
{
|
||||
c.tx_lora = configureLora(r.value);
|
||||
continue;
|
||||
}
|
||||
|
||||
Serial.printf("Unknown key '%s' will be ignored\n", r.key);
|
||||
}
|
||||
|
||||
@@ -143,9 +155,52 @@ bool Config::updateConfig(String key, String value)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.equalsIgnoreCase("rx_lora"))
|
||||
{
|
||||
rx_lora = configureLora(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.equalsIgnoreCase("tx_lora"))
|
||||
{
|
||||
tx_lora = configureLora(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.equalsIgnoreCase("is_host"))
|
||||
{
|
||||
String v = value;
|
||||
bool p = v.equalsIgnoreCase("true");
|
||||
if (!p && !v.equalsIgnoreCase("false"))
|
||||
{
|
||||
Serial.printf("Expected bool for '%s', found '%s' - ignoring\n", key.c_str(),
|
||||
value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
is_host = p;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String loraConfigToStr(LoRaConfig *cfg)
|
||||
{
|
||||
if (cfg == NULL)
|
||||
{
|
||||
return String("none");
|
||||
}
|
||||
|
||||
return String("freq:") + String(cfg->freq) + String(",bw:") + String(cfg->bw) +
|
||||
String(",sf:") + String(cfg->sf) + String(",cr:") + String(cfg->cr) +
|
||||
String(",tx_power:") + String(cfg->tx_power) + String(",preamble_len:") +
|
||||
String(cfg->preamble_len) + String(",sync_word:") +
|
||||
String(cfg->sync_word, 16) + String(",crc:") + String(cfg->crc ? "1" : "0") +
|
||||
String(",implicit_header:") + String(cfg->implicit_header);
|
||||
}
|
||||
|
||||
String detectionStrategyToStr(Config &c)
|
||||
{
|
||||
String res = c.detection_strategy;
|
||||
@@ -195,6 +250,31 @@ int findSepa(String s, String sepa, int begin, int &end)
|
||||
return i + sepa.length();
|
||||
}
|
||||
|
||||
uint64_t fromHex(String s)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
for (char c : s)
|
||||
{
|
||||
uint64_t v;
|
||||
if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
v = c - 'A' + 10;
|
||||
}
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
v = c - 'a' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = c - '0';
|
||||
}
|
||||
|
||||
r = (r << 4) + v;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
uint64_t toUint64(String s)
|
||||
{
|
||||
String v = s.substring(0, s.length() % 15);
|
||||
@@ -269,6 +349,94 @@ ScanRange parseScanRange(String &cfg, int &begin)
|
||||
return res;
|
||||
}
|
||||
|
||||
LoRaConfig *configureLora(String cfg)
|
||||
{
|
||||
if (cfg.equalsIgnoreCase("none"))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LoRaConfig *lora = new LoRaConfig();
|
||||
|
||||
int begin = 0;
|
||||
int end, i;
|
||||
|
||||
while ((i = findSepa(cfg, ",", begin, end)) >= 0)
|
||||
{
|
||||
String param = cfg.substring(begin, end);
|
||||
begin = i;
|
||||
int j = param.indexOf(":");
|
||||
if (j < 0)
|
||||
{
|
||||
Serial.printf("Expected ':' to be present in '%s' - ignoring config\n",
|
||||
param);
|
||||
continue;
|
||||
}
|
||||
|
||||
String k = param.substring(0, j);
|
||||
|
||||
if (k.equalsIgnoreCase("sync_word"))
|
||||
{
|
||||
lora->sync_word = (uint8_t)fromHex(param.substring(j + 1));
|
||||
continue;
|
||||
}
|
||||
|
||||
int v = param.substring(j + 1).toInt();
|
||||
|
||||
if (k.equalsIgnoreCase("freq"))
|
||||
{
|
||||
lora->freq = (uint16_t)v;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.equalsIgnoreCase("bw"))
|
||||
{
|
||||
lora->bw = (uint16_t)v;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.equalsIgnoreCase("sf"))
|
||||
{
|
||||
lora->sf = (uint8_t)v;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.equalsIgnoreCase("cr"))
|
||||
{
|
||||
lora->cr = (uint8_t)v;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.equalsIgnoreCase("tx_power"))
|
||||
{
|
||||
lora->tx_power = (uint8_t)v;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.equalsIgnoreCase("preamble_len"))
|
||||
{
|
||||
lora->preamble_len = (uint8_t)v;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.equalsIgnoreCase("crc"))
|
||||
{
|
||||
lora->crc = v != 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k.equalsIgnoreCase("implicit_header"))
|
||||
{
|
||||
lora->implicit_header = (uint8_t)v;
|
||||
continue;
|
||||
}
|
||||
|
||||
Serial.printf("Unknown key '%s' will be ignored\n", k);
|
||||
}
|
||||
|
||||
return lora;
|
||||
}
|
||||
|
||||
void Config::configureDetectionStrategy(String cfg)
|
||||
{
|
||||
if (scan_ranges_sz > 0)
|
||||
@@ -329,6 +497,10 @@ bool Config::write_config(const char *path)
|
||||
|
||||
f.println("detection_strategy = " + getConfig("detection_strategy"));
|
||||
|
||||
f.println("rx_lora = " + getConfig("rx_lora"));
|
||||
f.println("tx_lora = " + getConfig("tx_lora"));
|
||||
f.println("is_host = " + getConfig("is_host"));
|
||||
|
||||
f.close();
|
||||
return true;
|
||||
}
|
||||
@@ -365,6 +537,21 @@ String Config::getConfig(String key)
|
||||
return detectionStrategyToStr(*this);
|
||||
}
|
||||
|
||||
if (key.equalsIgnoreCase("rx_lora"))
|
||||
{
|
||||
return loraConfigToStr(rx_lora);
|
||||
}
|
||||
|
||||
if (key.equalsIgnoreCase("tx_lora"))
|
||||
{
|
||||
return loraConfigToStr(tx_lora);
|
||||
}
|
||||
|
||||
if (key.equalsIgnoreCase("is_host"))
|
||||
{
|
||||
return String(is_host ? "true" : "false");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
+25
-3
@@ -10,6 +10,21 @@ struct ScanRange
|
||||
uint64_t step_khz;
|
||||
};
|
||||
|
||||
struct LoRaConfig
|
||||
{
|
||||
uint16_t freq;
|
||||
uint16_t bw;
|
||||
uint8_t sf;
|
||||
uint8_t cr;
|
||||
uint8_t tx_power;
|
||||
uint16_t preamble_len;
|
||||
uint8_t sync_word;
|
||||
bool crc;
|
||||
uint8_t implicit_header;
|
||||
};
|
||||
|
||||
LoRaConfig *configureLora(String cfg);
|
||||
|
||||
#define CREATE_MISSING_CONFIG true
|
||||
struct Config
|
||||
{
|
||||
@@ -23,12 +38,19 @@ struct Config
|
||||
String listen_on_serial0;
|
||||
String listen_on_serial1;
|
||||
String listen_on_usb;
|
||||
LoRaConfig *rx_lora;
|
||||
LoRaConfig *tx_lora;
|
||||
|
||||
bool is_host;
|
||||
|
||||
Config()
|
||||
: create_missing_config(CREATE_MISSING_CONFIG), print_profile_time(false),
|
||||
detection_strategy("RSSI"), samples(0), scan_ranges_sz(0), scan_ranges(NULL),
|
||||
log_data_json_interval(1000), listen_on_serial0(String("none")),
|
||||
listen_on_serial1(String("readline")), listen_on_usb("readline") {};
|
||||
detection_strategy(String("RSSI")), samples(0), scan_ranges_sz(0),
|
||||
scan_ranges(NULL), log_data_json_interval(1000),
|
||||
listen_on_serial0(String("none")), listen_on_serial1(String("readline")),
|
||||
listen_on_usb(String("readline")), rx_lora(NULL), tx_lora(NULL),
|
||||
is_host(false) {};
|
||||
|
||||
bool write_config(const char *path);
|
||||
|
||||
static Config init();
|
||||
|
||||
+157
-56
@@ -86,6 +86,8 @@ long noDevicesMillis = 0, cycleCnt = 0;
|
||||
bool present = false;
|
||||
bool scanFinished = true;
|
||||
|
||||
bool radioIsScan = false;
|
||||
|
||||
// time to scan BT
|
||||
#define BT_SCAN_TIME 10
|
||||
|
||||
@@ -533,19 +535,71 @@ StackedChart stacked(display, 0, 0, 0, 0);
|
||||
|
||||
UptimeClock *uptime;
|
||||
|
||||
int16_t initForScan(float freq)
|
||||
{
|
||||
int16_t state;
|
||||
|
||||
#if defined(USING_SX1280PA)
|
||||
state = radio.beginGFSK(freq);
|
||||
#elif defined(USING_LR1121)
|
||||
state = radio.beginGFSK(freq, 4.8F, 5.0F, 156.2F, 10, 16U, 1.7F);
|
||||
#else
|
||||
state = radio.beginFSK(freq);
|
||||
#endif
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool setFrequency(float curr_freq)
|
||||
{
|
||||
r.current_frequency = curr_freq;
|
||||
LOG("setFrequency:%f\n", r.current_frequency);
|
||||
|
||||
int16_t state;
|
||||
#ifdef USING_SX1280PA
|
||||
int16_t state1 =
|
||||
radio.setFrequency(r.current_frequency); // 1280 doesn't have calibration
|
||||
|
||||
state = radio.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF);
|
||||
if (state != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
Serial.println("Error:startReceive:" + String(state));
|
||||
}
|
||||
|
||||
state = state1;
|
||||
#elif USING_SX1276
|
||||
state = radio.setFrequency(freq);
|
||||
#elif defined(USING_LR1121)
|
||||
state = radio.setFrequency(r.current_frequency,
|
||||
true); // true = no calibration need here
|
||||
#else
|
||||
state = radio.setFrequency(r.current_frequency,
|
||||
false); // false = calibration is needed here
|
||||
#endif
|
||||
if (state != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
display.drawString(0, 64 - 10,
|
||||
"E(" + String(state) +
|
||||
"):setFrequency:" + String(r.current_frequency));
|
||||
Serial.println("E(" + String(state) +
|
||||
"):setFrequency:" + String(r.current_frequency));
|
||||
display.display();
|
||||
delay(2);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void init_radio()
|
||||
{
|
||||
// initialize SX1262 FSK modem at the initial frequency
|
||||
both.println("Init radio");
|
||||
#if defined(USING_SX1280PA)
|
||||
state = radio.beginGFSK(CONF_FREQ_BEGIN);
|
||||
#elif defined(USING_LR1121)
|
||||
state = radio.beginGFSK(CONF_FREQ_BEGIN, 4.8F, 5.0F, 156.2F, 10, 16U, 1.7F);
|
||||
#else
|
||||
state = radio.beginFSK(CONF_FREQ_BEGIN);
|
||||
#endif
|
||||
state = initForScan(CONF_FREQ_BEGIN);
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE)
|
||||
{
|
||||
radioIsScan = true;
|
||||
Serial.println(F("success!"));
|
||||
}
|
||||
else
|
||||
@@ -591,25 +645,9 @@ void init_radio()
|
||||
}
|
||||
both.println("Starting scanning...");
|
||||
|
||||
// calibrate only once ,,, at startup
|
||||
// TODO: check documentation (9.2.1) if we must calibrate in certain ranges
|
||||
#ifdef USING_SX1280PA
|
||||
state = radio.setFrequency(CONF_FREQ_BEGIN);
|
||||
if (state != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
Serial.println("Error:setFrequency:" + String(state));
|
||||
}
|
||||
state = radio.startReceive();
|
||||
if (state != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
Serial.println("Error:startReceive:" + String(state));
|
||||
}
|
||||
#elif USING_SX1276
|
||||
// Sets carrier frequency. Allowed values range from 137.0 MHz to 1020.0 MHz.
|
||||
radio.setFrequency(CONF_FREQ_BEGIN);
|
||||
#else
|
||||
radio.setFrequency(CONF_FREQ_BEGIN, true);
|
||||
#endif
|
||||
// calibrate only once ,,, at startup
|
||||
// TODO: check documentation (9.2.1) if we must calibrate in certain ranges
|
||||
setFrequency(CONF_FREQ_BEGIN);
|
||||
|
||||
delay(50);
|
||||
}
|
||||
@@ -1453,6 +1491,12 @@ void checkComms()
|
||||
// MAX Frequency RSSI BIN value of the samples
|
||||
int max_rssi_x = 999;
|
||||
|
||||
void doScan();
|
||||
|
||||
void reportScan(RadioComms &c);
|
||||
|
||||
int16_t checkRadio(RadioComms &c);
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
r.led_flag = false;
|
||||
@@ -1462,6 +1506,38 @@ void loop(void)
|
||||
|
||||
checkComms();
|
||||
|
||||
if (config.is_host)
|
||||
{
|
||||
if (TxComms != NULL)
|
||||
{
|
||||
// NB: swapping the use of Tx and Rx comms, so a pair of modules
|
||||
// with identical rx/tx_lora config can talk
|
||||
int16_t status = checkRadio(*TxComms);
|
||||
if (status != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
Serial.printf("Error getting a message: %d\n", status);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
doScan();
|
||||
if (TxComms != NULL)
|
||||
reportScan(*TxComms);
|
||||
if (RxComms != NULL)
|
||||
checkRadio(*RxComms);
|
||||
}
|
||||
}
|
||||
|
||||
void doScan()
|
||||
{
|
||||
if (!radioIsScan)
|
||||
{
|
||||
radioIsScan = true;
|
||||
initForScan(CONF_FREQ_BEGIN);
|
||||
state = radio.startReceive(RADIOLIB_SX126X_RX_TIMEOUT_NONE);
|
||||
}
|
||||
|
||||
// reset scan time
|
||||
if (config.print_profile_time)
|
||||
{
|
||||
@@ -1562,36 +1638,7 @@ void loop(void)
|
||||
// x > STEPS on SCAN_RBW_FACTOR
|
||||
int display_x = x / SCAN_RBW_FACTOR;
|
||||
|
||||
r.current_frequency = (float)curr_freq / 1000.0;
|
||||
LOG("setFrequency:%f\n", r.current_frequency);
|
||||
|
||||
#ifdef USING_SX1280PA
|
||||
state =
|
||||
radio.setFrequency(r.current_frequency); // 1280 doesn't have calibration
|
||||
radio.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF);
|
||||
#elif USING_SX1276
|
||||
state = radio.setFrequency(freq);
|
||||
#elif defined(USING_LR1121)
|
||||
state = radio.setFrequency(r.current_frequency,
|
||||
true); // true = no calibration need here
|
||||
#else
|
||||
state = radio.setFrequency(r.current_frequency,
|
||||
false); // false = calibration is needed here
|
||||
#endif
|
||||
int radio_error_count = 0;
|
||||
if (state != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
display.drawString(0, 64 - 10,
|
||||
"E(" + String(state) +
|
||||
"):setFrequency:" + String(r.current_frequency));
|
||||
Serial.println("E(" + String(state) +
|
||||
"):setFrequency:" + String(r.current_frequency));
|
||||
display.display();
|
||||
delay(2);
|
||||
radio_error_count++;
|
||||
if (radio_error_count > 10)
|
||||
continue;
|
||||
}
|
||||
setFrequency(curr_freq / 1000.0);
|
||||
|
||||
LOG("Step:%d Freq: %f\n", x, r.current_frequency);
|
||||
// SpectralScan Method
|
||||
@@ -1914,3 +1961,57 @@ void loop(void)
|
||||
sideBarCol = SIDEBAR_START_COL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t checkRadio(RadioComms &comms)
|
||||
{
|
||||
radioIsScan = false;
|
||||
int16_t status = comms.configureRadio();
|
||||
if (status != RADIOLIB_ERR_NONE)
|
||||
return status;
|
||||
|
||||
Message *msg = comms.receive(
|
||||
config.is_host
|
||||
? 2000
|
||||
: 200); // 200ms should be enough to receive 500 bytes at SF 7 and BW 500
|
||||
if (msg == NULL)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (msg->type == SCAN_RESULT)
|
||||
{
|
||||
HostComms->send(*msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("Received a message of unsupported type: %d\n", msg->type);
|
||||
}
|
||||
|
||||
delete msg;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void reportScan(RadioComms &comms)
|
||||
{
|
||||
radioIsScan = false;
|
||||
int16_t status = comms.configureRadio();
|
||||
if (status != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
Serial.printf("Failed to configure Radio: %d\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
Message m;
|
||||
m.type = SCAN_RESULT;
|
||||
m.payload.dump = frequency_scan_result.dump;
|
||||
status = comms.send(m);
|
||||
|
||||
m.payload.dump.sz = 0; // dump is shared, so should not delete underlying arrays
|
||||
|
||||
if (status != RADIOLIB_ERR_NONE)
|
||||
{
|
||||
Serial.printf("Failed to send scan result: %d\n", status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user