mirror of
https://github.com/Genaker/LoraSA.git
synced 2026-05-02 19:42:59 +02:00
Factor out scan configuration
This commit is contained in:
@@ -124,6 +124,12 @@ Config Config::init()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r.key.equalsIgnoreCase("detection_strategy"))
|
||||
{
|
||||
c.configureDetectionStrategy(r.value);
|
||||
continue;
|
||||
}
|
||||
|
||||
Serial.printf("Unknown key '%s' will be ignored\n", r.key);
|
||||
}
|
||||
|
||||
@@ -131,6 +137,173 @@ Config Config::init()
|
||||
return c;
|
||||
}
|
||||
|
||||
String detectionStrategyToStr(Config &c)
|
||||
{
|
||||
String res = c.detection_strategy;
|
||||
if (c.scan_ranges_sz > 0)
|
||||
{
|
||||
res += ":";
|
||||
for (int i = 0; i < c.scan_ranges_sz; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
res += ",";
|
||||
}
|
||||
|
||||
res += String(c.scan_ranges[i].start_khz);
|
||||
int s = c.scan_ranges[i].end_khz - c.scan_ranges[i].start_khz;
|
||||
if (s > 0)
|
||||
{
|
||||
res += ".." + String(c.scan_ranges[i].end_khz);
|
||||
if (c.scan_ranges[i].step_khz < s)
|
||||
{
|
||||
res += ":" + String(c.scan_ranges[i].step_khz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// findSepa looks for a sepa in s from position begin, and does two things:
|
||||
// updates end with the index of the end of the string between begin and
|
||||
// separator or end of string, and returns index of the next search position
|
||||
// or -1 to stop the search.
|
||||
//
|
||||
// So you can do something like this:
|
||||
// for (int i = 0, j = 0, k = 0; (i = findSepa(s, sepa, j, k)) >= 0; j = i)
|
||||
// ...s.substring(j, k)
|
||||
int findSepa(String s, String sepa, int begin, int &end)
|
||||
{
|
||||
int i = s.indexOf(sepa, begin);
|
||||
if (i < 0)
|
||||
{
|
||||
end = s.length();
|
||||
return begin == end ? -1 : end;
|
||||
}
|
||||
|
||||
end = i;
|
||||
return i + sepa.length();
|
||||
}
|
||||
|
||||
uint64_t toUint64(String s)
|
||||
{
|
||||
String v = s.substring(0, s.length() % 15);
|
||||
s = s.substring(v.length());
|
||||
uint64_t r = v.toInt();
|
||||
|
||||
while (s.length() > 0)
|
||||
{
|
||||
r = r * ((uint64_t)1000000000000000ll) + s.substring(0, 15).toInt();
|
||||
s = s.substring(15);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
ScanRange parseScanRange(String &cfg, int &begin)
|
||||
{
|
||||
ScanRange res;
|
||||
int end;
|
||||
int i = findSepa(cfg, ",", begin, end);
|
||||
|
||||
String r = cfg.substring(begin, end);
|
||||
begin = i;
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
res.start_khz = -1;
|
||||
res.end_khz = -1;
|
||||
res.step_khz = -1;
|
||||
return res;
|
||||
}
|
||||
|
||||
i = r.indexOf("..");
|
||||
if (i < 0)
|
||||
{
|
||||
i = r.length();
|
||||
}
|
||||
|
||||
res.start_khz = toUint64(r.substring(0, i));
|
||||
if (i == r.length())
|
||||
{
|
||||
res.end_khz = res.start_khz;
|
||||
res.step_khz = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
r = r.substring(i + 2);
|
||||
i = r.indexOf("+");
|
||||
if (i < 0)
|
||||
{
|
||||
i = r.indexOf("/");
|
||||
if (i < 0)
|
||||
i = r.length();
|
||||
}
|
||||
|
||||
res.end_khz = toUint64(r.substring(0, i));
|
||||
if (i == r.length())
|
||||
{
|
||||
res.step_khz = res.end_khz - res.start_khz;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.step_khz = toUint64(r.substring(i + 1));
|
||||
if (r.charAt(i) == '/')
|
||||
{
|
||||
// then it is not a literal increment, it is the number of steps
|
||||
if (res.step_khz == 0)
|
||||
res.step_khz = 1;
|
||||
res.step_khz = round(((double)(res.end_khz - res.start_khz)) / res.step_khz);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Config::configureDetectionStrategy(String cfg)
|
||||
{
|
||||
if (scan_ranges_sz > 0)
|
||||
delete[] scan_ranges;
|
||||
scan_ranges = NULL;
|
||||
|
||||
String method = cfg;
|
||||
int i = cfg.indexOf(":");
|
||||
if (i >= 0)
|
||||
{
|
||||
method = cfg.substring(0, i);
|
||||
cfg = cfg.substring(i + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg = "";
|
||||
}
|
||||
|
||||
samples = 0;
|
||||
i = method.indexOf(",");
|
||||
if (i >= 0)
|
||||
{
|
||||
samples = method.substring(i + 1).toInt();
|
||||
method = method.substring(0, i);
|
||||
}
|
||||
detection_strategy = method;
|
||||
|
||||
scan_ranges_sz = 0;
|
||||
for (int i = 0, k = 0; (i = findSepa(cfg, ",", i, k)) >= 0; scan_ranges_sz++)
|
||||
;
|
||||
|
||||
if (scan_ranges_sz == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scan_ranges = new ScanRange[scan_ranges_sz];
|
||||
|
||||
for (int i = 0, j = 0; i < scan_ranges_sz; i++)
|
||||
{
|
||||
scan_ranges[i] = parseScanRange(cfg, j);
|
||||
}
|
||||
}
|
||||
|
||||
bool Config::write_config(const char *path)
|
||||
{
|
||||
File f = SD.open(path, FILE_WRITE, /*create = */ true);
|
||||
@@ -145,6 +318,8 @@ bool Config::write_config(const char *path)
|
||||
f.println("listen_on_serial1 = " + listen_on_serial1);
|
||||
f.println("listen_on_usb = " + listen_on_usb);
|
||||
|
||||
f.println("detection_strategy = " + detectionStrategyToStr(*this));
|
||||
|
||||
f.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,22 @@
|
||||
|
||||
#include <SD.h>
|
||||
|
||||
struct ScanRange
|
||||
{
|
||||
uint64_t start_khz;
|
||||
uint64_t end_khz;
|
||||
uint64_t step_khz;
|
||||
};
|
||||
|
||||
#define CREATE_MISSING_CONFIG true
|
||||
struct Config
|
||||
{
|
||||
bool create_missing_config;
|
||||
bool print_profile_time;
|
||||
String detection_strategy;
|
||||
int samples;
|
||||
int scan_ranges_sz;
|
||||
ScanRange *scan_ranges;
|
||||
int log_data_json_interval;
|
||||
String listen_on_serial0;
|
||||
String listen_on_serial1;
|
||||
@@ -15,11 +26,14 @@ struct Config
|
||||
|
||||
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") {};
|
||||
bool write_config(const char *path);
|
||||
|
||||
static Config init();
|
||||
|
||||
void configureDetectionStrategy(String cfg);
|
||||
};
|
||||
|
||||
struct ParseResult
|
||||
|
||||
153
src/main.cpp
153
src/main.cpp
@@ -151,8 +151,8 @@ typedef enum
|
||||
// constexpr int RSSI_OUTPUT_FORMULA = 2;
|
||||
|
||||
// Feature to scan diapasones. Other frequency settings will be ignored.
|
||||
// int SCAN_RANGES[] = {850890, 920950};
|
||||
int SCAN_RANGES[] = {};
|
||||
// String SCAN_RANGES = String("850..890,920..950");
|
||||
String SCAN_RANGES = "";
|
||||
|
||||
// MHZ per page
|
||||
// to put everything into one page set RANGE_PER_PAGE = FREQ_END - 800
|
||||
@@ -759,6 +759,42 @@ void logToSerialTask(void *parameter)
|
||||
|
||||
void drone_sound_alarm(void *arg, Event &e);
|
||||
|
||||
void configureDetection()
|
||||
{
|
||||
if (config.scan_ranges_sz == 0)
|
||||
{
|
||||
config.scan_ranges_sz = 1;
|
||||
config.scan_ranges = new ScanRange[1];
|
||||
config.scan_ranges[0].start_khz = FREQ_BEGIN * 1000;
|
||||
config.scan_ranges[0].end_khz = FREQ_END * 1000;
|
||||
config.scan_ranges[0].step_khz =
|
||||
(float)(FREQ_END - FREQ_BEGIN) * 1000 / (STEPS * SCAN_RBW_FACTOR);
|
||||
}
|
||||
|
||||
if (config.samples <= 0)
|
||||
{
|
||||
config.samples = SAMPLES_RSSI;
|
||||
}
|
||||
|
||||
CONF_SAMPLES = config.samples;
|
||||
|
||||
CONF_FREQ_BEGIN = config.scan_ranges[0].start_khz / 1000;
|
||||
CONF_FREQ_END = config.scan_ranges[0].end_khz / 1000;
|
||||
for (int i = 0; i < config.scan_ranges_sz; i++)
|
||||
{
|
||||
CONF_FREQ_BEGIN = min(CONF_FREQ_BEGIN, config.scan_ranges[i].start_khz / 1000);
|
||||
CONF_FREQ_END = max(CONF_FREQ_END, config.scan_ranges[i].end_khz / 1000);
|
||||
}
|
||||
|
||||
median_frequency = (CONF_FREQ_BEGIN + CONF_FREQ_END) / 2;
|
||||
|
||||
samples = CONF_SAMPLES;
|
||||
|
||||
RANGE_PER_PAGE = CONF_FREQ_END - CONF_FREQ_BEGIN; // FREQ_END - CONF_FREQ_BEGIN
|
||||
RANGE = (int)(CONF_FREQ_END - CONF_FREQ_BEGIN);
|
||||
range = RANGE;
|
||||
}
|
||||
|
||||
void readConfigFile()
|
||||
{
|
||||
// writeFile(LittleFS, "/text.txt", "{WIFI:{name:\"sdfsdf\",
|
||||
@@ -784,27 +820,22 @@ void readConfigFile()
|
||||
smpls = readParameterFromParameterFile("samples");
|
||||
Serial.println("SAMPLES: " + smpls);
|
||||
|
||||
CONF_SAMPLES = (smpls == "") ? samples : atoi(smpls.c_str());
|
||||
samples = CONF_SAMPLES;
|
||||
CONF_FREQ_BEGIN = (fstart == "") ? FREQ_BEGIN : atoi(fstart.c_str());
|
||||
CONF_FREQ_END = (fend == "") ? FREQ_END : atoi(fend.c_str());
|
||||
String detection = String("RSSI");
|
||||
if (smpls.length() > 0)
|
||||
detection += "," + smpls;
|
||||
if (fstart.length() == 0)
|
||||
fstart = String(FREQ_BEGIN * 1000);
|
||||
if (fend.length() == 0)
|
||||
fend = String(FREQ_END * 1000);
|
||||
|
||||
detection += ":" + fstart + ".." + fend + "/" + String(STEPS * SCAN_RBW_FACTOR);
|
||||
|
||||
config.configureDetectionStrategy(detection);
|
||||
configureDetection();
|
||||
|
||||
both.println("C FREQ BEGIN:" + String(CONF_FREQ_BEGIN));
|
||||
both.println("C FREQ END:" + String(CONF_FREQ_END));
|
||||
both.println("C SAMPLES:" + String(CONF_SAMPLES));
|
||||
|
||||
RANGE_PER_PAGE = CONF_FREQ_END - CONF_FREQ_BEGIN; // FREQ_END - CONF_FREQ_BEGIN
|
||||
|
||||
RANGE = (int)(CONF_FREQ_END - CONF_FREQ_BEGIN);
|
||||
|
||||
SINGLE_STEP = (float)(RANGE / (STEPS * SCAN_RBW_FACTOR));
|
||||
|
||||
range = (int)(CONF_FREQ_END - CONF_FREQ_BEGIN);
|
||||
|
||||
iterations = RANGE / RANGE_PER_PAGE;
|
||||
|
||||
// uint64_t range_frequency = FREQ_END - CONF_FREQ_BEGIN;
|
||||
median_frequency = (CONF_FREQ_BEGIN + CONF_FREQ_END) / 2;
|
||||
}
|
||||
|
||||
void setup(void)
|
||||
@@ -918,24 +949,19 @@ void setup(void)
|
||||
initLittleFS();
|
||||
|
||||
readConfigFile();
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef WEB_SERVER
|
||||
CONF_SAMPLES = samples;
|
||||
CONF_FREQ_BEGIN = FREQ_BEGIN;
|
||||
CONF_FREQ_END = FREQ_END;
|
||||
if (config.scan_ranges_sz == 0 && SCAN_RANGES.length() > 0)
|
||||
{
|
||||
config.configureDetectionStrategy(config.detection_strategy + ":" + SCAN_RANGES);
|
||||
}
|
||||
|
||||
configureDetection();
|
||||
|
||||
both.println("FREQ BEGIN:" + String(CONF_FREQ_BEGIN));
|
||||
both.println("FREQ END:" + String(CONF_FREQ_END));
|
||||
both.println("SAMPLES:" + String(CONF_SAMPLES));
|
||||
|
||||
RANGE_PER_PAGE = CONF_FREQ_END - CONF_FREQ_BEGIN; // FREQ_END - CONF_FREQ_BEGIN
|
||||
RANGE = (int)(CONF_FREQ_END - CONF_FREQ_BEGIN);
|
||||
SINGLE_STEP = (float)(RANGE / (STEPS * SCAN_RBW_FACTOR));
|
||||
range = (int)(CONF_FREQ_END - CONF_FREQ_BEGIN);
|
||||
iterations = RANGE / RANGE_PER_PAGE;
|
||||
median_frequency = (CONF_FREQ_BEGIN + CONF_FREQ_END) / 2;
|
||||
#endif
|
||||
init_radio();
|
||||
|
||||
@@ -1249,29 +1275,6 @@ bool is_new_x_pixel(int x)
|
||||
return false;
|
||||
}
|
||||
|
||||
void check_ranges()
|
||||
{
|
||||
if (RANGE_PER_PAGE == range)
|
||||
{
|
||||
single_page_scan = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
single_page_scan = false;
|
||||
}
|
||||
|
||||
for (int range : SCAN_RANGES)
|
||||
{
|
||||
ranges_count++;
|
||||
}
|
||||
|
||||
if (ranges_count > 0)
|
||||
{
|
||||
iterations = ranges_count;
|
||||
single_page_scan = false;
|
||||
}
|
||||
}
|
||||
|
||||
void checkComms()
|
||||
{
|
||||
while (HostComms->available() > 0)
|
||||
@@ -1374,35 +1377,11 @@ void loop(void)
|
||||
r.fr_begin = CONF_FREQ_BEGIN;
|
||||
r.fr_end = r.fr_begin;
|
||||
|
||||
// 50 is a single-screen range
|
||||
// TODO: Make 50 a variable with the option to show the full range
|
||||
iterations = range / RANGE_PER_PAGE;
|
||||
|
||||
#if 0 // disabled code
|
||||
if (range % RANGE_PER_PAGE != 0)
|
||||
for (range_item = 0; range_item < config.scan_ranges_sz; range_item++)
|
||||
{
|
||||
// add more scan
|
||||
//++;
|
||||
}
|
||||
#endif
|
||||
|
||||
check_ranges();
|
||||
|
||||
// Iterating by small ranges by 50 Mhz each pixel is 0.4 Mhz
|
||||
for (range_item = 0; range_item < iterations; range_item++)
|
||||
{
|
||||
range = RANGE_PER_PAGE;
|
||||
if (ranges_count == 0)
|
||||
{
|
||||
r.fr_begin = (range_item == 0) ? r.fr_begin : r.fr_begin + range;
|
||||
r.fr_end = r.fr_begin + RANGE_PER_PAGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.fr_begin = SCAN_RANGES[range_item] / 1000;
|
||||
r.fr_end = SCAN_RANGES[range_item] % 1000;
|
||||
range = r.fr_end - r.fr_begin;
|
||||
}
|
||||
r.fr_begin = config.scan_ranges[range_item].start_khz / 1000;
|
||||
r.fr_end = config.scan_ranges[range_item].end_khz / 1000;
|
||||
range = r.fr_end - r.fr_begin;
|
||||
|
||||
#ifdef DISABLED_CODE
|
||||
if (!ANIMATED_RELOAD || !single_page_scan)
|
||||
@@ -1422,8 +1401,16 @@ void loop(void)
|
||||
|
||||
// horizontal (x axis) Frequency loop
|
||||
osd_x = 1, osd_y = 2, col = 0, max_bin = 0;
|
||||
|
||||
ScanRange scan_range = config.scan_ranges[range_item];
|
||||
int steps = 1;
|
||||
if (scan_range.step_khz > 0)
|
||||
steps = 1 + (scan_range.end_khz - scan_range.start_khz) / scan_range.step_khz;
|
||||
if (steps == 0)
|
||||
steps = 1;
|
||||
|
||||
// x loop
|
||||
for (x = 0; x < STEPS * SCAN_RBW_FACTOR; x++)
|
||||
for (x = 0; x < steps; x++)
|
||||
{
|
||||
new_pixel = is_new_x_pixel(x);
|
||||
if (ANIMATED_RELOAD && SCAN_RBW_FACTOR == 1)
|
||||
@@ -1442,7 +1429,7 @@ void loop(void)
|
||||
// Because of the SCAN_RBW_FACTOR x is not a display coordinate anymore
|
||||
// x > STEPS on SCAN_RBW_FACTOR
|
||||
int display_x = x / SCAN_RBW_FACTOR;
|
||||
float step = (range * ((float)x / (STEPS * SCAN_RBW_FACTOR)));
|
||||
float step = (float)x * scan_range.step_khz / 1000.0;
|
||||
|
||||
r.current_frequency = r.fr_begin + step;
|
||||
LOG("setFrequency:%f\n", r.current_frequency);
|
||||
|
||||
Reference in New Issue
Block a user