diff --git a/lib/config/config.h b/lib/config/config.h index a2d9003..859c428 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -17,7 +17,7 @@ struct Config bool print_profile_time; String detection_strategy; int samples; - int scan_ranges_sz; + size_t scan_ranges_sz; ScanRange *scan_ranges; int log_data_json_interval; String listen_on_serial0; diff --git a/lib/events/event_types.h b/lib/events/event_types.h new file mode 100644 index 0000000..725fdbc --- /dev/null +++ b/lib/events/event_types.h @@ -0,0 +1,13 @@ +#ifndef LORASA_EVENT_TYPES_H +#define LORASA_EVENT_TYPES_H + +struct Event; +enum EventType +{ + ALL_EVENTS = 0, // used only at registration time + DETECTED, + SCAN_TASK_COMPLETE, + _MAX_EVENT_TYPE = SCAN_TASK_COMPLETE // unused as event type +}; +struct Listener; +#endif diff --git a/lib/events/events.h b/lib/events/events.h index 329dea5..6f1dea0 100644 --- a/lib/events/events.h +++ b/lib/events/events.h @@ -1,17 +1,8 @@ #ifndef LORASA_EVENTS_H #define LORASA_EVENTS_H -struct Event; -enum EventType -{ - ALL_EVENTS = 0, // used only at registration time - DETECTED, - SCAN_TASK_COMPLETE, - _MAX_EVENT_TYPE = SCAN_TASK_COMPLETE // unused as event type -}; -struct Listener; - #include +#include #include struct Event diff --git a/lib/scan/scan.cpp b/lib/scan/scan.cpp index 89ff530..ea2f02d 100644 --- a/lib/scan/scan.cpp +++ b/lib/scan/scan.cpp @@ -4,9 +4,11 @@ #include "scan.h" #include #include +#include #include -uint16_t Scan::rssiMethod(size_t samples, uint16_t *result, size_t res_size) +uint16_t Scan::rssiMethod(float (*getRSSI)(void *), void *param, size_t samples, + uint16_t *result, size_t res_size) { float scale((float)res_size / (HI_RSSI_THRESHOLD - LO_RSSI_THRESHOLD + 0.1)); @@ -18,7 +20,7 @@ uint16_t Scan::rssiMethod(size_t samples, uint16_t *result, size_t res_size) // N of samples for (int r = 0; r < samples; r++) { - float rssi = getRSSI(); + float rssi = getRSSI(param); if (rssi < -65535) rssi = -65535; diff --git a/lib/scan/scan.h b/lib/scan/scan.h index c826609..6b8c28c 100644 --- a/lib/scan/scan.h +++ b/lib/scan/scan.h @@ -1,11 +1,11 @@ +#ifndef LORASA_SCAN_H +#define LORASA_SCAN_H + +#include #include -#include +#include #include -#ifndef LORASA_CORE_H - -#define LORASA_CORE_H - #ifdef PRINT_DEBUG #define LOG(args...) Serial.printf(args...) #define LOG_IF(cond, args...) \ @@ -34,6 +34,22 @@ constexpr float LO_RSSI_THRESHOLD = HI_RSSI_THRESHOLD - 66; #define SAMPLES_RSSI 20 #endif +struct ScanPage +{ + uint64_t start_mhz; + uint64_t end_mhz; + size_t page_sz; + ScanRange *scan_ranges; + + ~ScanPage() + { + if (page_sz > 0) + { + delete[] scan_ranges; + } + } +}; + struct Scan { uint64_t epoch; @@ -61,11 +77,10 @@ struct Scan }, comms_initialized(false) {}; - virtual float getRSSI() = 0; - // rssiMethod gets the data similar to the scan method, // but uses getRSSI directly. - uint16_t rssiMethod(size_t samples, uint16_t *result, size_t res_size); + uint16_t rssiMethod(float (*getRSSI)(void *), void *param, size_t samples, + uint16_t *result, size_t res_size); // detect method analyses result, and produces filtered_result, marking // those values that represent a detection event. diff --git a/src/main.cpp b/src/main.cpp index a1372c6..21dd5de 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -154,6 +154,10 @@ typedef enum // String SCAN_RANGES = String("850..890,920..950"); String SCAN_RANGES = ""; +size_t scan_pages_sz = 0; +ScanPage *scan_pages; +size_t scan_page = 0; + // MHZ per page // to put everything into one page set RANGE_PER_PAGE = FREQ_END - 800 uint64_t RANGE_PER_PAGE; // FREQ_END - CONF_FREQ_BEGIN @@ -211,8 +215,6 @@ bool detected_y[STEPS]; // 20 - ??? steps // Used as a Led Light and Buzzer/count trigger bool first_run, new_pixel, detected_x = false; -// drone detection flag -bool detected = false; uint64_t drone_detection_level = DEFAULT_DRONE_DETECTION_LEVEL; #define TRIGGER_LEVEL -80.0 uint64_t drone_detected_frequency_start = 0; @@ -241,9 +243,8 @@ HardwareSerial SerialPort(SERIAL_PORT); // #define WEB_SERVER true -uint64_t x, y, range_item, w = WATERFALL_START, i = 0; +uint64_t x, y, w = WATERFALL_START, i = 0; int osd_x = 1, osd_y = 2, col = 0, max_bin = 32; -uint64_t ranges_count = 0; int rssi = 0; int state = 0; @@ -482,13 +483,9 @@ void osdProcess() Config config; -struct RadioScan : Scan -{ - float getRSSI() override; -}; - -float RadioScan::getRSSI() +float getRSSI(void *param) { + Scan *r = (Scan *)param; #if defined(USING_SX1280PA) // radio.startReceive(); // get instantaneous RSSI value @@ -508,7 +505,7 @@ float RadioScan::getRSSI() #endif } -RadioScan r; +Scan r; #define WATERFALL_SENSITIVITY 0.05 DecoratedBarChart *bar; @@ -759,6 +756,81 @@ void logToSerialTask(void *parameter) void drone_sound_alarm(void *arg, Event &e); +void configurePages() +{ + if (scan_pages_sz > 0) + delete[] scan_pages; + + if (single_page_scan) + { + scan_pages_sz = 1; + ScanPage scan_page = { + start_mhz : CONF_FREQ_BEGIN, + end_mhz : CONF_FREQ_END, + page_sz : config.scan_ranges_sz + }; + if (scan_page.page_sz > 0) + { + scan_page.scan_ranges = new ScanRange[scan_page.page_sz]; + } + for (int i = 0; i < scan_page.page_sz; i++) + { + scan_page.scan_ranges[i] = config.scan_ranges[i]; + } + scan_pages = new ScanPage[1]{scan_page}; + scan_page.page_sz = + 0; // make sure it doesn't free up the Scanranges that were just constructed + } + else + { + scan_pages_sz = + (CONF_FREQ_END - CONF_FREQ_BEGIN + RANGE_PER_PAGE - 1) / RANGE_PER_PAGE; + scan_pages = new ScanPage[scan_pages_sz]; + for (int j = 0; j < scan_pages_sz; j++) + { + ScanPage scan_page = { + start_mhz : CONF_FREQ_BEGIN + j * RANGE_PER_PAGE, + end_mhz : CONF_FREQ_BEGIN + (j + 1) * RANGE_PER_PAGE, + page_sz : 0 + }; + for (int i = 0; i < config.scan_ranges_sz; i++) + { + if (config.scan_ranges[i].start_khz > scan_page.end_mhz * 1000 || + config.scan_ranges[i].end_khz < scan_page.start_mhz * 1000) + { + continue; + } + scan_page.page_sz++; + } + + if (scan_page.page_sz > 0) + { + scan_page.scan_ranges = new ScanRange[scan_page.page_sz]; + for (int i = 0, r = 0; i < config.scan_ranges_sz; i++) + { + if (config.scan_ranges[i].start_khz > scan_page.end_mhz * 1000 || + config.scan_ranges[i].end_khz < scan_page.start_mhz * 1000) + { + continue; + } + + scan_page.scan_ranges[r] = { + start_khz : max(config.scan_ranges[i].start_khz, + scan_page.start_mhz * 1000), + end_khz : + min(config.scan_ranges[i].end_khz, scan_page.end_mhz * 1000), + step_khz : config.scan_ranges[i].step_khz + }; + r++; + } + } + scan_pages[j] = scan_page; + scan_page.page_sz = + 0; // we copied over the values, make sure the array doesn't get freed + } + } +} + void configureDetection() { if (config.scan_ranges_sz == 0) @@ -793,6 +865,8 @@ void configureDetection() RANGE_PER_PAGE = CONF_FREQ_END - CONF_FREQ_BEGIN; // FREQ_END - CONF_FREQ_BEGIN RANGE = (int)(CONF_FREQ_END - CONF_FREQ_BEGIN); range = RANGE; + + configurePages(); } void readConfigFile() @@ -1038,6 +1112,8 @@ void setup(void) } } } + + configurePages(); display.clear(); Serial.println(); @@ -1348,7 +1424,6 @@ void loop(void) r.detection_count = 0; drone_detected_frequency_start = 0; - ranges_count = 0; checkComms(); @@ -1377,11 +1452,13 @@ void loop(void) r.fr_begin = CONF_FREQ_BEGIN; r.fr_end = r.fr_begin; - for (range_item = 0; range_item < config.scan_ranges_sz; range_item++) + for (scan_page = 0; scan_page < scan_pages_sz; scan_page++) { - r.fr_begin = config.scan_ranges[range_item].start_khz / 1000; - r.fr_end = config.scan_ranges[range_item].end_khz / 1000; + ScanPage &page = scan_pages[scan_page]; + r.fr_begin = page.start_mhz; + r.fr_end = page.end_mhz; range = r.fr_end - r.fr_begin; + median_frequency = (page.start_mhz + page.end_mhz) / 2; #ifdef DISABLED_CODE if (!ANIMATED_RELOAD || !single_page_scan) @@ -1402,17 +1479,37 @@ 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; x++) + for (int range = 0, step = 0; range < page.page_sz; range += (step == 0)) { - new_pixel = is_new_x_pixel(x); + // the logic is: + // 1. go through each scan_range in the order that they are declared + // in the page + // 2. start with scan_range.start and always end with scan_range.end + // if adding step lands us a little short of end, there will be + // extra iteration to scan actual end frequency + // 3. the next iteration after scanning end frequency will be next range + // 4. x is derived from the frequency we are going to scan with respect to + // the page size + ScanRange scan_range = page.scan_ranges[range]; + uint64_t curr_freq = scan_range.start_khz + scan_range.step_khz * step; + if (curr_freq > scan_range.end_khz) + curr_freq = scan_range.end_khz; + + // for now support legacy calculation of x that relies on SCAN_RBW_FACTOR + x = (curr_freq - page.start_mhz * 1000) * STEPS * SCAN_RBW_FACTOR / + ((page.end_mhz - page.start_mhz) * 1000); + + new_pixel = step == 0 || is_new_x_pixel(x); + if (curr_freq == scan_range.end_khz) + { + step = 0; // trigger switch to the next range on the next iteration + } + else + { + step++; + } + if (ANIMATED_RELOAD && SCAN_RBW_FACTOR == 1) { UI_drawCursor(x); @@ -1429,9 +1526,8 @@ 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 = (float)x * scan_range.step_khz / 1000.0; - r.current_frequency = r.fr_begin + step; + r.current_frequency = (float)curr_freq / 1000.0; LOG("setFrequency:%f\n", r.current_frequency); #ifdef USING_SX1280PA @@ -1494,7 +1590,16 @@ void loop(void) // Spectrum analyzer using getRSSI { LOG("METHOD RSSI"); - uint16_t max_rssi = r.rssiMethod(CONF_SAMPLES, result, + + float (*g)(void *); + samples = CONF_SAMPLES; + + if (config.detection_strategy.equalsIgnoreCase("RSSI")) + g = &getRSSI; + else + g = &getRSSI; + + uint16_t max_rssi = r.rssiMethod(g, &r, samples, result, RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE); if (max_x_rssi[display_x] > max_rssi) @@ -1532,10 +1637,8 @@ void loop(void) max_rssi_x = detected_at; } - detected = event.detected.detected; detected_y[display_x] = false; - float rr = event.detected.rssi; r.drone_detection_level = drone_detection_level; if (event.detected.trigger) diff --git a/src/ui.cpp b/src/ui.cpp index 77bdc58..4349d85 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -15,17 +15,14 @@ #define SCALE_TEXT_TOP (HEIGHT + X_AXIS_WEIGHT + MAJOR_TICK_LENGTH) // temporary dirty import ... to be solved durring upcoming refactoring -extern unsigned int RANGE_PER_PAGE; extern uint64_t CONF_FREQ_BEGIN; extern uint64_t CONF_FREQ_END; extern unsigned int median_frequency; extern unsigned int drone_detected_frequency_start; extern unsigned int drone_detected_frequency_end; -extern unsigned int ranges_count; -extern int SCAN_RANGES[]; -extern unsigned int ranges_count; -extern unsigned int iterations; -extern unsigned int range_item; +extern size_t scan_pages_sz; +extern ScanPage *scan_pages; +extern size_t scan_page; extern uint64_t loop_time; @@ -166,7 +163,7 @@ void StatusBar::draw() digitalWrite(LED, LOW); } - if (ranges_count == 0) + if (scan_pages_sz == 1) { #ifdef DEBUG display.setTextAlignment(TEXT_ALIGN_LEFT); @@ -179,18 +176,18 @@ void StatusBar::draw() display.setTextAlignment(TEXT_ALIGN_RIGHT); display.drawString(pos_x + width, text_y, String(CONF_FREQ_END)); } - else if (ranges_count > 0) + else if (scan_pages_sz > 1) { display.setTextAlignment(TEXT_ALIGN_LEFT); display.drawString(pos_x, text_y, - String(SCAN_RANGES[range_item] / 1000) + "-" + - String(SCAN_RANGES[range_item] % 1000)); - if (range_item + 1 < iterations) + String(scan_pages[scan_page].start_mhz) + "-" + + String(scan_pages[scan_page].end_mhz)); + if (scan_page + 1 < scan_pages_sz) { display.setTextAlignment(TEXT_ALIGN_RIGHT); display.drawString(pos_x + width, text_y, - String(SCAN_RANGES[range_item + 1] / 1000) + "-" + - String(SCAN_RANGES[range_item + 1] % 1000)); + String(scan_pages[scan_page + 1].start_mhz) + "-" + + String(scan_pages[scan_page + 1].end_mhz)); } } ui_initialized = true; diff --git a/test/test_rssi.cpp b/test/test_rssi.cpp index a38d166..737caea 100644 --- a/test/test_rssi.cpp +++ b/test/test_rssi.cpp @@ -7,21 +7,21 @@ struct TestScan : Scan { TestScan(float *ctx, int sz) : ctx(ctx), sz(sz), idx(0) {} - float getRSSI() override; - float *ctx; int sz; int idx; }; -float TestScan::getRSSI() +float getRSSI(void *param) { - if (idx >= sz) + TestScan *r = (TestScan *)param; + + if (r->idx >= r->sz) { return -1000000; } - return ctx[idx++]; + return r->ctx[r->idx++]; } constexpr int test_sz = 13; @@ -35,7 +35,7 @@ void test_rssi(void) TestScan t = TestScan(inputs, inputs_sz); - uint16_t r = t.rssiMethod(inputs_sz, samples, test_sz); + uint16_t r = t.rssiMethod(getRSSI, &t, inputs_sz, samples, test_sz); uint16_t expect[test_sz] = {20, 50, 55, 60, 0, 70, 75, 80, 0, 90, 0, 100, 110};