mirror of
https://github.com/Genaker/LoraSA.git
synced 2026-07-03 00:11:01 +02:00
Factor out detection + display loop
Refactor code that does not depend on y. Essentially, the following logic: Recall that some loops are folds, some are maps. Maps look at only elements with one index. The important property of maps is that map(f . g) = map(f) . map(g) - parts of the loop body can be split into separate loops. Another property of maps is that if map(f) does not depend on the output of map(g), then map(f) . map(g) = map(g) . map(f) - the loops can be reordered.
This commit is contained in:
+63
-4
@@ -6,17 +6,17 @@
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
|
||||
float Scan::getRSSI() { return 0.1; }
|
||||
|
||||
uint16_t Scan::rssiMethod(uint16_t *result)
|
||||
uint16_t Scan::rssiMethod(size_t samples, uint16_t *result, size_t res_size)
|
||||
{
|
||||
float scale((float)res_size / (HI_RSSI_THRESHOLD - LO_RSSI_THRESHOLD + 0.1));
|
||||
|
||||
memset(result, 0, res_size * sizeof(uint16_t));
|
||||
int result_index = 0;
|
||||
|
||||
//
|
||||
uint16_t max_signal = 65535;
|
||||
// N of samples
|
||||
for (int r = 0; r < SAMPLES_RSSI; r++)
|
||||
for (int r = 0; r < samples; r++)
|
||||
{
|
||||
float rssi = getRSSI();
|
||||
if (rssi < -65535)
|
||||
@@ -66,4 +66,63 @@ uint16_t Scan::rssiMethod(uint16_t *result)
|
||||
return max_signal;
|
||||
}
|
||||
|
||||
size_t Scan::detect(uint16_t *result, bool *filtered_result, size_t result_size,
|
||||
int samples)
|
||||
{
|
||||
size_t max_rssi_x = 999;
|
||||
|
||||
for (int y = 0; y < result_size; y++)
|
||||
{
|
||||
|
||||
LOG("%i:%i,", y, result[y]);
|
||||
#if !defined(FILTER_SPECTRUM_RESULTS) || FILTER_SPECTRUM_RESULTS == false
|
||||
if (result[y] && result[y] != 0)
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
filtered_result[y] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if samples low ~1 filter removes all values
|
||||
#if FILTER_SPECTRUM_RESULTS
|
||||
|
||||
filtered_result[y] = 0;
|
||||
// Filter Elements without neighbors
|
||||
// if RSSI method actual value is -xxx dB
|
||||
if (result[y] > 0 && samples > 1)
|
||||
{
|
||||
// do not process 'first' and 'last' row to avoid out of index
|
||||
// access.
|
||||
if ((y > 0) && (y < (result_size - 2)))
|
||||
{
|
||||
if (((result[y + 1] != 0) && (result[y + 2] != 0)) ||
|
||||
(result[y - 1] != 0))
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
// Fill empty pixel
|
||||
result[y + 1] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("Filtered::%i,", y);
|
||||
}
|
||||
}
|
||||
} // not filtering if samples == 1 because it will be filtered
|
||||
else if (result[y] > 0 && samples == 1)
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
}
|
||||
#endif
|
||||
if (filtered_result[y] && max_rssi_x > y)
|
||||
{
|
||||
max_rssi_x = y;
|
||||
}
|
||||
}
|
||||
|
||||
return max_rssi_x;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+13
-9
@@ -30,17 +30,21 @@ constexpr float LO_RSSI_THRESHOLD = HI_RSSI_THRESHOLD - 66;
|
||||
|
||||
struct Scan
|
||||
{
|
||||
Scan(int sz)
|
||||
: res_size(sz), scale((float)sz / (HI_RSSI_THRESHOLD - LO_RSSI_THRESHOLD + 0.1))
|
||||
{
|
||||
}
|
||||
virtual float getRSSI() = 0;
|
||||
|
||||
virtual float getRSSI();
|
||||
// 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(uint16_t *result);
|
||||
|
||||
int res_size;
|
||||
float scale;
|
||||
// detect method analyses result, and produces filtered_result, marking
|
||||
// those values that represent a detection event.
|
||||
// It returns index that represents strongest signal at which a detection event
|
||||
// occurred.
|
||||
static size_t detect(uint16_t *result, bool *filtered_result, size_t result_size,
|
||||
int samples);
|
||||
};
|
||||
|
||||
// Remove reading without neighbors
|
||||
#define FILTER_SPECTRUM_RESULTS true
|
||||
|
||||
#endif
|
||||
|
||||
+52
-96
@@ -144,8 +144,6 @@ bool ANIMATED_RELOAD = false;
|
||||
#define UP_FILTER 5
|
||||
// Trim low signals - nose level
|
||||
#define START_LOW 6
|
||||
// Remove reading without neighbors
|
||||
#define FILTER_SPECTRUM_RESULTS true
|
||||
#define FILTER_SAMPLES_MIN
|
||||
constexpr bool DRAW_DETECTION_TICKS = true;
|
||||
int16_t max_x_rssi[STEPS] = {999};
|
||||
@@ -888,9 +886,7 @@ void loop(void)
|
||||
float step = (range * ((float)x / (STEPS * SCAN_RBW_FACTOR)));
|
||||
|
||||
freq = fr_begin + step;
|
||||
#ifdef PRINT_DEBUG
|
||||
Serial.println("setFrequency:" + String(freq));
|
||||
#endif
|
||||
LOG("setFrequency:%f\n", freq);
|
||||
|
||||
#ifdef USING_SX1280PA
|
||||
state = radio.setFrequency(freq); // 1280 doesn't have calibration
|
||||
@@ -911,9 +907,7 @@ void loop(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef PRINT_DEBUG
|
||||
Serial.printf("Step:%d Freq: %f\n", x, freq);
|
||||
#endif
|
||||
LOG("Step:%d Freq: %f\n", x, freq);
|
||||
// SpectralScan Method
|
||||
#ifdef METHOD_SPECTRAL
|
||||
{
|
||||
@@ -971,59 +965,21 @@ void loop(void)
|
||||
display.setColor(WHITE);
|
||||
}
|
||||
#endif
|
||||
detected = false;
|
||||
detected_y[display_x] = false;
|
||||
max_rssi_x = 999;
|
||||
size_t detected_at = r.detect(
|
||||
result, filtered_result, RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE, samples);
|
||||
|
||||
for (y = 0; y < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE; y++)
|
||||
if (max_rssi_x > detected_at)
|
||||
{
|
||||
// MAx bin Value not RSSI
|
||||
max_rssi_x = detected_at;
|
||||
}
|
||||
|
||||
#ifdef PRINT_DEBUG
|
||||
Serial.print(String(y) + ":");
|
||||
Serial.print(String(result[y]) + ",");
|
||||
#endif
|
||||
#if !defined(FILTER_SPECTRUM_RESULTS) || FILTER_SPECTRUM_RESULTS == false
|
||||
if (result[y] && result[y] != 0)
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
filtered_result[y] = 0;
|
||||
}
|
||||
#endif
|
||||
detected = detected_at < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE;
|
||||
detected_y[display_x] = false;
|
||||
|
||||
// if samples low ~1 filter removes all values
|
||||
#if FILTER_SPECTRUM_RESULTS
|
||||
|
||||
filtered_result[y] = 0;
|
||||
// Filter Elements without neighbors
|
||||
// if RSSI method actual value is -xxx dB
|
||||
if (result[y] > 0 && samples > 1)
|
||||
{
|
||||
// do not process 'first' and 'last' row to avoid out of index
|
||||
// access.
|
||||
if ((y > 0) && (y < (RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE - 2)))
|
||||
{
|
||||
if (((result[y + 1] != 0) && (result[y + 2] != 0)) ||
|
||||
(result[y - 1] != 0))
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
// Fill empty pixel
|
||||
result[y + 1] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PRINT_DEBUG
|
||||
Serial.print("Filtered:" + String(x) + ":" + String(y) + ",");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // not filtering if samples == 1 because it will be filtered
|
||||
else if (result[y] > 0 && samples == 1)
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
}
|
||||
for (int y = 0; y < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE; y++)
|
||||
{
|
||||
// calculating max window x RSSI after filters
|
||||
x_window = (int)(display_x / WINDOW_SIZE);
|
||||
int abs_result = abs(result[y]);
|
||||
@@ -1031,16 +987,15 @@ void loop(void)
|
||||
max_x_window[x_window] > abs_result)
|
||||
{
|
||||
max_x_window[x_window] = abs_result;
|
||||
#ifdef PRINT_DEBUG
|
||||
Serial.println("MAX x window: " + String(x_window) + " " +
|
||||
String(abs_result));
|
||||
#endif
|
||||
LOG("MAX x window: %i %i\n", x_window, abs_result);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (detected_at <= drone_detection_level)
|
||||
{
|
||||
// check if we should alarm about a drone presence
|
||||
if ((filtered_result[y] == 1) // we have some data and
|
||||
&& (y <= drone_detection_level) &&
|
||||
detected_y[display_x] == false) // detection threshold match
|
||||
if (detected_y[display_x] == false) // detection threshold match
|
||||
{
|
||||
// Set LED to ON (filtered in UI component)
|
||||
UI_setLedFlag(true);
|
||||
@@ -1084,8 +1039,7 @@ void loop(void)
|
||||
}
|
||||
}
|
||||
#if (WATERFALL_ENABLED == true)
|
||||
if ((filtered_result[y] == 1) && (y <= drone_detection_level) &&
|
||||
(single_page_scan) && (waterfall[display_x] != true) && new_pixel)
|
||||
if ((single_page_scan) && (waterfall[display_x] != true) && new_pixel)
|
||||
{
|
||||
// If drone not found set dark pixel on the waterfall
|
||||
// TODO: make something like scrolling up if possible
|
||||
@@ -1095,44 +1049,46 @@ void loop(void)
|
||||
display.setColor(WHITE);
|
||||
}
|
||||
#endif
|
||||
// next 2 If's ... adds !!!! 10ms of runtime ......tfk ???
|
||||
}
|
||||
|
||||
#ifdef PRINT_DEBUG
|
||||
for (int y = 0; y < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE; y++)
|
||||
{
|
||||
if (filtered_result[y] == 1)
|
||||
{
|
||||
#ifdef PRINT_DEBUG
|
||||
Serial.print("Pixel:" + String(display_x) + "(" + String(x) + ")" +
|
||||
":" + String(y) + ",");
|
||||
#endif
|
||||
if (max_rssi_x > y)
|
||||
{
|
||||
// MAx bin Value not RSSI
|
||||
max_rssi_x = y;
|
||||
}
|
||||
// Set MAIN signal level pixel
|
||||
if (y < MAX_POWER_LEVELS - START_LOW)
|
||||
{
|
||||
display.setPixel(display_x, y + START_LOW);
|
||||
}
|
||||
if (!detected)
|
||||
{
|
||||
detected = true;
|
||||
}
|
||||
LOG("Pixel:%i(%i):%i,", display_x, x, y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Draw "Detection Level line" every 2 pixel
|
||||
// -------------------------------------------------------------
|
||||
if ((y == drone_detection_level) && (display_x % 2 == 0))
|
||||
for (int y = 0; y < min(RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE,
|
||||
MAX_POWER_LEVELS - START_LOW);
|
||||
y++)
|
||||
{
|
||||
if (filtered_result[y] == 1)
|
||||
{
|
||||
// Set MAIN signal level pixel
|
||||
display.setPixelColor(display_x, y + START_LOW, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Draw "Detection Level line" every 2 pixel
|
||||
// -------------------------------------------------------------
|
||||
if (display_x % 2 == 0)
|
||||
{
|
||||
if (filtered_result[drone_detection_level] == 1)
|
||||
{
|
||||
display.setColor(INVERSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
display.setColor(WHITE);
|
||||
if (filtered_result[y] == 1)
|
||||
{
|
||||
display.setColor(INVERSE);
|
||||
}
|
||||
display.setPixel(display_x, y + START_LOW);
|
||||
// display.setPixel(display_x, y + START_LOW - 1); // 2 px wide
|
||||
|
||||
display.setColor(WHITE);
|
||||
}
|
||||
display.setPixel(display_x, drone_detection_level + START_LOW);
|
||||
// display.setPixel(display_x, y + START_LOW - 1); // 2 px wide
|
||||
|
||||
display.setColor(WHITE);
|
||||
}
|
||||
|
||||
#ifdef JOYSTICK_ENABLED
|
||||
|
||||
@@ -66,4 +66,63 @@ uint16_t Scan::rssiMethod(size_t samples, uint16_t *result, size_t res_size)
|
||||
return max_signal;
|
||||
}
|
||||
|
||||
size_t Scan::detect(uint16_t *result, bool *filtered_result, size_t result_size,
|
||||
int samples)
|
||||
{
|
||||
size_t max_rssi_x = 999;
|
||||
|
||||
for (int y = 0; y < result_size; y++)
|
||||
{
|
||||
|
||||
LOG("%i:%i,", y, result[y]);
|
||||
#if !defined(FILTER_SPECTRUM_RESULTS) || FILTER_SPECTRUM_RESULTS == false
|
||||
if (result[y] && result[y] != 0)
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
filtered_result[y] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// if samples low ~1 filter removes all values
|
||||
#if FILTER_SPECTRUM_RESULTS
|
||||
|
||||
filtered_result[y] = 0;
|
||||
// Filter Elements without neighbors
|
||||
// if RSSI method actual value is -xxx dB
|
||||
if (result[y] > 0 && samples > 1)
|
||||
{
|
||||
// do not process 'first' and 'last' row to avoid out of index
|
||||
// access.
|
||||
if ((y > 0) && (y < (result_size - 2)))
|
||||
{
|
||||
if (((result[y + 1] != 0) && (result[y + 2] != 0)) ||
|
||||
(result[y - 1] != 0))
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
// Fill empty pixel
|
||||
result[y + 1] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG("Filtered::%i,", y);
|
||||
}
|
||||
}
|
||||
} // not filtering if samples == 1 because it will be filtered
|
||||
else if (result[y] > 0 && samples == 1)
|
||||
{
|
||||
filtered_result[y] = 1;
|
||||
}
|
||||
#endif
|
||||
if (filtered_result[y] && max_rssi_x > y)
|
||||
{
|
||||
max_rssi_x = y;
|
||||
}
|
||||
}
|
||||
|
||||
return max_rssi_x;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,16 @@ struct Scan
|
||||
// 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);
|
||||
|
||||
// detect method analyses result, and produces filtered_result, marking
|
||||
// those values that represent a detection event.
|
||||
// It returns index that represents strongest signal at which a detection event
|
||||
// occurred.
|
||||
static size_t detect(uint16_t *result, bool *filtered_result, size_t result_size,
|
||||
int samples);
|
||||
};
|
||||
|
||||
// Remove reading without neighbors
|
||||
#define FILTER_SPECTRUM_RESULTS true
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user