From 7b1e8599b9b719a300fe9b0e8583731139b163fb Mon Sep 17 00:00:00 2001 From: Sassa NF Date: Thu, 19 Sep 2024 19:51:43 +0100 Subject: [PATCH 1/3] Testable RSSI method --- platformio.ini | 3 ++ src/core.cpp | 57 ++++++++++++++++++++++++++++++ src/core.h | 45 ++++++++++++++++++++++++ src/main.cpp | 88 +++++++++++----------------------------------- test/test_rssi.cpp | 56 +++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+), 68 deletions(-) create mode 100644 src/core.cpp create mode 100644 src/core.h create mode 100644 test/test_rssi.cpp diff --git a/platformio.ini b/platformio.ini index 26992cb..e8fcfb9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -127,3 +127,6 @@ lib_deps = adafruit/Adafruit GFX Library@^1.11.10 ropg/Heltec_ESP32_LoRa_v3@^0.9.1 adafruit/Adafruit ST7735 and ST7789 Library@^1.10.4 + +[env:native] +platform = native diff --git a/src/core.cpp b/src/core.cpp new file mode 100644 index 0000000..a1c6330 --- /dev/null +++ b/src/core.cpp @@ -0,0 +1,57 @@ +#ifndef LORASA_CORE_CPP +#define LORASA_CORE_CPP + +#include "core.h" +#include +#include +#include + +float Scan::getRSSI() { return 0.1; } + +uint16_t Scan::rssiMethod(uint16_t *result) +{ + 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++) + { + float rssi = getRSSI(); + uint16_t abs_rssi = abs(rssi); + if (abs_rssi < max_signal) + { + max_signal = abs_rssi; + } + // ToDO: check if 4 is correct value for 33 power bins + // Now we have more space because we are ignoring low dB values + // we can / 3 default 4 + if (RSSI_OUTPUT_FORMULA == 1) + { + result_index = + /// still not clear formula but it works + uint8_t(abs(rssi) / 4); + } + else if (RSSI_OUTPUT_FORMULA == 2) + { + // I like this formula better + result_index = uint8_t(abs(rssi) / 2) - 22; + } + + if (result_index >= res_size) + { + // Maximum index possible + result_index = res_size - 1; + } + + LOG("RSSI: %f IDX: %d\n", rssi, result_index); + if (result[result_index] == 0 || result[result_index] > abs_rssi) + { + result[result_index] = abs_rssi; + } + } + + return max_signal; +} + +#endif diff --git a/src/core.h b/src/core.h new file mode 100644 index 0000000..bdcaa51 --- /dev/null +++ b/src/core.h @@ -0,0 +1,45 @@ +#include +#include + +#ifndef LORASA_CORE_H + +#define LORASA_CORE_H + +#ifdef PRINT_DEBUG +#define LOG(args...) Serial.printf(args...) +#define LOG_IF(cond, args...) \ + if (cond) \ + LOG(args...) +#elif !defined(LOG) +#define LOG(args...) +#define LOG_IF(cond, args...) +#endif + +// Output Pixel Formula +// 1 = rssi / 4, 2 = (rssi / 2) - 22 or 20 +constexpr int RSSI_OUTPUT_FORMULA = 2; + +// based on the formula for RSSI_OUTPUT_FORMULA == 2 +// -2 * (22 + RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE) < rssi =< -44 +// practice may require a better pair of thresholds +constexpr float HI_RSSI_THRESHOLD = -44.0; +constexpr float LO_RSSI_THRESHOLD = HI_RSSI_THRESHOLD - 66; + +// number of samples for RSSI method +#define SAMPLES_RSSI 12 // 21 // + +struct Scan +{ + Scan(int sz) + : res_size(sz) + { + } + + virtual float getRSSI(); + + uint16_t rssiMethod(uint16_t *result); + + int res_size; +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp index 36667a6..71320a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,6 +29,8 @@ // #define WIFI_SCANNING_ENABLED true // #define BT_SCANNING_ENABLED true +#include "core.h" + #ifndef LILYGO #include // This file contains a binary patch for the SX1262 @@ -160,10 +162,6 @@ typedef enum // #define METHOD_SPECTRAL // Spectral scan method #define METHOD_RSSI // Uncomment this and comment METHOD_SPECTRAL fot RSSI -// Output Pixel Formula -// 1 = rssi / 4, 2 = (rssi / 2) - 22 or 20 -constexpr int RSSI_OUTPUT_FORMULA = 2; - // Feature to scan diapasones. Other frequency settings will be ignored. // int SCAN_RANGES[] = {850890, 920950}; int SCAN_RANGES[] = {}; @@ -201,8 +199,6 @@ constexpr int WINDOW_SIZE = 15; // Number of samples for each frequency scan. Fewer samples = better temporal resolution. // if more than 100 it can freeze #define SAMPLES 35 //(scan time = 1294) -// number of samples for RSSI method -#define SAMPLES_RSSI 12 // 21 // #define RANGE (int)(FREQ_END - FREQ_BEGIN) @@ -220,7 +216,7 @@ uint64_t median_frequency = FREQ_BEGIN + FREQ_END - FREQ_BEGIN / 2; // #define DISABLE_PLOT_CHART false // unused // Array to store the scan results -int16_t result[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE]; +uint16_t result[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE]; bool filtered_result[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE]; @@ -763,9 +759,21 @@ void check_ranges() single_page_scan = false; } } + +struct RadioScan : Scan +{ + RadioScan() : Scan(RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE) {} + + float getRSSI() override; +}; + +float RadioScan::getRSSI() { return radio.getRSSI(false); } + // MAX Frequency RSSI BIN value of the samples int max_rssi_x = 999; +RadioScan r; + void loop(void) { UI_displayDecorate(0, 0, false); // some default values @@ -854,6 +862,7 @@ void loop(void) // horizontal (x axis) Frequency loop osd_x = 1, osd_y = 2, col = 0, max_bin = 0; + int radio_error_count = 0; // x loop for (x = 0; x < STEPS * SCAN_RBW_FACTOR; x++) { @@ -882,12 +891,7 @@ void loop(void) Serial.println("setFrequency:" + String(freq)); #endif -#ifdef LILYGO state = radio.setFrequency(freq, false); // false = no calibration need here -#else - state = radio.setFrequency(freq, false); // false = no calibration need here -#endif - int radio_error_count = 0; if (state != RADIOLIB_ERR_NONE) { display.drawString(0, 64 - 10, "E:setFrequency:" + String(freq)); @@ -933,63 +937,11 @@ void loop(void) #ifdef METHOD_RSSI // Spectrum analyzer using getRSSI { -#ifdef PRINT_DEBUG - Serial.println("METHOD RSSI"); -#endif - // memset - // memset(result, 0, RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE); - // Some issues with memset function - for (i = 0; i < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE; i++) + LOG("METHOD RSSI"); + uint16_t max_rssi = r.rssiMethod(result); + if (max_x_rssi[display_x] > max_rssi) { - result[i] = 0; - } - result_index = 0; - // N of samples - for (int r = 0; r < SAMPLES_RSSI; r++) - { - rssi = radio.getRSSI(false); - int abs_rssi = abs(rssi); - // ToDO: check if 4 is correct value for 33 power bins - // Now we have more space because we are ignoring low dB values - // we can / 3 default 4 - if (RSSI_OUTPUT_FORMULA == 1) - { - result_index = - /// still not clear formula but it works - uint8_t(abs_rssi / 4); - } - else if (RSSI_OUTPUT_FORMULA == 2) - { - // I like this formula better - result_index = uint8_t(abs_rssi / 2) - 22; - } - if (result_index >= RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE) - { - // Maximum index possible - result_index = RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE - 1; - } - -#ifdef PRINT_DEBUG - Serial.printf("RSSI: %d IDX: %d\n", rssi, result_index); -#endif - // avoid buffer overflow - if (result_index < RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE) - { - // Saving max ABS value of RSSI. dB is negative, so smaller - // absolute value represents stronger signal. - if (result[result_index] == 0 || result[result_index] > abs_rssi) - { - result[result_index] = abs_rssi; - } - if (max_x_rssi[display_x] > abs_rssi) - { - max_x_rssi[display_x] = abs_rssi; - } - } - else - { - Serial.print("Out-of-Range: result_index %d\n"); - } + max_x_rssi[display_x] = max_rssi; } } #endif // SCAN_METHOD == METHOD_RSSI diff --git a/test/test_rssi.cpp b/test/test_rssi.cpp new file mode 100644 index 0000000..fad8e22 --- /dev/null +++ b/test/test_rssi.cpp @@ -0,0 +1,56 @@ +#include +#define LOG(args...) printf(args) +#include "../src/core.cpp" +#include + +void setUp(void) {} + +void tearDown(void) {} + +struct TestScan : Scan +{ + TestScan(float *ctx, int sz) : Scan(sz), ctx(ctx), sz(sz), idx(0) {} + + float getRSSI() override; + + float *ctx; + int sz; + int idx; +}; + +float TestScan::getRSSI() +{ + if (idx >= sz) + { + return -1000000; + } + + return ctx[idx++]; +} + +constexpr int test_sz = 13; + +void test_rssi(void) +{ + uint16_t samples[test_sz]; + float inputs[] = {-40.0, -100.0, -200.0, -50.0, -400.0, -60.0, -20, + -75.5, -70, -80, -90, -55.9, -110}; + + TestScan t = TestScan(inputs, test_sz); + + uint16_t r = t.rssiMethod(samples); + + uint16_t expect[test_sz] = {20, 50, 55, 60, 0, 70, 75, 80, 0, 90, 0, 100, 200}; + + TEST_ASSERT_EQUAL_INT16(20, r); + TEST_ASSERT_EQUAL_INT16_ARRAY(expect, samples, test_sz); +} + +int main(int argc, char **argv) +{ + UNITY_BEGIN(); + + RUN_TEST(test_rssi); + + UNITY_END(); +} From dbbe3f4e3a02eca9a7b22b4a30b39a68e6a5ce82 Mon Sep 17 00:00:00 2001 From: Sassa NF Date: Thu, 19 Sep 2024 19:52:49 +0100 Subject: [PATCH 2/3] Tests pass --- src/core.cpp | 15 +++++++++++++-- src/core.h | 3 ++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index a1c6330..1eca711 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -18,6 +18,9 @@ uint16_t Scan::rssiMethod(uint16_t *result) for (int r = 0; r < SAMPLES_RSSI; r++) { float rssi = getRSSI(); + if (rssi < -65535) + rssi = -65535; + uint16_t abs_rssi = abs(rssi); if (abs_rssi < max_signal) { @@ -34,8 +37,16 @@ uint16_t Scan::rssiMethod(uint16_t *result) } else if (RSSI_OUTPUT_FORMULA == 2) { - // I like this formula better - result_index = uint8_t(abs(rssi) / 2) - 22; + if (rssi > HI_RSSI_THRESHOLD) + { + rssi = HI_RSSI_THRESHOLD; + } + else if (rssi < LO_RSSI_THRESHOLD) + { + rssi = LO_RSSI_THRESHOLD; + } + + result_index = uint8_t((HI_RSSI_THRESHOLD - rssi) * scale); } if (result_index >= res_size) diff --git a/src/core.h b/src/core.h index bdcaa51..36f449c 100644 --- a/src/core.h +++ b/src/core.h @@ -31,7 +31,7 @@ constexpr float LO_RSSI_THRESHOLD = HI_RSSI_THRESHOLD - 66; struct Scan { Scan(int sz) - : res_size(sz) + : res_size(sz), scale((float)sz / (HI_RSSI_THRESHOLD - LO_RSSI_THRESHOLD + 0.1)) { } @@ -40,6 +40,7 @@ struct Scan uint16_t rssiMethod(uint16_t *result); int res_size; + float scale; }; #endif From ea319a6cac8694ca3a2338970afc4e579cae77b9 Mon Sep 17 00:00:00 2001 From: Egor Shitikov Date: Thu, 19 Sep 2024 16:00:38 -0700 Subject: [PATCH 3/3] Refactor RSSI Scan --- include/DFRobot_OSD.h | 59 +++++++++++++++++++++++++++++ src/core.cpp => lib/scan/scan.cpp | 3 +- src/core.h => lib/scan/scan.h | 0 platformio.ini | 1 + src/main.cpp | 62 ++----------------------------- test/test_rssi.cpp | 2 +- 6 files changed, 66 insertions(+), 61 deletions(-) rename src/core.cpp => lib/scan/scan.cpp (98%) rename src/core.h => lib/scan/scan.h (100%) diff --git a/include/DFRobot_OSD.h b/include/DFRobot_OSD.h index d446a86..063753c 100644 --- a/include/DFRobot_OSD.h +++ b/include/DFRobot_OSD.h @@ -13,8 +13,67 @@ #ifndef _DFRobot_OSD_H_ #define _DFRobot_OSD_H_ +#define MAX_POWER_LEVELS 33 + #include +/*Define Custom characters Example*/ +static const int buf0[36] = {0x02, 0x80, 0x02, 0x40, 0x7F, 0xE0, 0x42, 0x00, + 0x42, 0x00, 0x7A, 0x40, 0x4A, 0x40, 0x4A, 0x80, + 0x49, 0x20, 0x5A, 0xA0, 0x44, 0x60, 0x88, 0x20}; + +static constexpr uint16_t levels[10] = { + 0x105, // 0 + 0x10E, // 1 + 0x10D, // 2 + 0x10C, // 3 + 0x10B, // 4 + 0x10A, // 5 + 0x109, // 6 + 0x108, // 7 + 0x107, // 8 + 0x106, // 9 +}; + +static constexpr uint16_t power_level[MAX_POWER_LEVELS + 1] = { + 0x10E, // 0 + 0x10E, // 1 + 0x10D, // 2 + 0x10C, // 3 + 0x10B, // 4 + 0x10A, // 5 + 0x109, // 6 + 0x108, // 7 + 0x107, // 8 + 0x106, // 9 not using 106 to accent rise + // new line + 0x10E, // 10 + 0x10D, // 11 + 0x10C, // 12 + 0x10B, // 13 + 0x10A, // 14 + 0x109, // 15 + 0x108, // 16 + 0x107, // 17 + 0x106, // 18 not using 106 + // new line + 0x10E, // 19 + 0x10D, // 20 + 0x10C, // 21 + 0x10B, // 22 + 0x10A, // 23 + 0x109, // 24 + 0x108, // 25 + 0x107, // 26 + 0x106, // 27 + 0x105, // 28 --- + 0x105, // 29 + 0x105, // 30 + 0x105, // 31 + 0x105, // 32 + 0x105 // 33 +}; + // #define ENABLE_DBG //!< Open this macro and you can see the details of the program #ifdef ENABLE_DBG #define DBG(...) \ diff --git a/src/core.cpp b/lib/scan/scan.cpp similarity index 98% rename from src/core.cpp rename to lib/scan/scan.cpp index 1eca711..bf8b416 100644 --- a/src/core.cpp +++ b/lib/scan/scan.cpp @@ -1,7 +1,7 @@ #ifndef LORASA_CORE_CPP #define LORASA_CORE_CPP -#include "core.h" +#include "scan.h" #include #include #include @@ -13,6 +13,7 @@ uint16_t Scan::rssiMethod(uint16_t *result) 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++) diff --git a/src/core.h b/lib/scan/scan.h similarity index 100% rename from src/core.h rename to lib/scan/scan.h diff --git a/platformio.ini b/platformio.ini index e8fcfb9..7145e78 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,6 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] +default_envs = heltec_wifi_lora_32_V3 ; for env:vision-master-e190 ; src_dir = tft_src ; for env:vision-master-e290 diff --git a/src/main.cpp b/src/main.cpp index 71320a5..b6953bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,11 +25,12 @@ #include -// #define OSD_ENABLED true +#define OSD_ENABLED true // #define WIFI_SCANNING_ENABLED true // #define BT_SCANNING_ENABLED true -#include "core.h" +// RSSI Scan Logic +#include #ifndef LILYGO #include @@ -64,58 +65,6 @@ uint64_t bt_start = 0; #include "DFRobot_OSD.h" #define OSD_SIDE_BAR true -static constexpr uint16_t levels[10] = { - 0x105, // 0 - 0x10E, // 1 - 0x10D, // 2 - 0x10C, // 3 - 0x10B, // 4 - 0x10A, // 5 - 0x109, // 6 - 0x108, // 7 - 0x107, // 8 - 0x106, // 9 -}; - -static constexpr uint16_t power_level[MAX_POWER_LEVELS + 1] = { - 0x10E, // 0 - 0x10E, // 1 - 0x10D, // 2 - 0x10C, // 3 - 0x10B, // 4 - 0x10A, // 5 - 0x109, // 6 - 0x108, // 7 - 0x107, // 8 - 0x106, // 9 not using 106 to accent rise - // new line - 0x10E, // 10 - 0x10D, // 11 - 0x10C, // 12 - 0x10B, // 13 - 0x10A, // 14 - 0x109, // 15 - 0x108, // 16 - 0x107, // 17 - 0x106, // 18 not using 106 - // new line - 0x10E, // 19 - 0x10D, // 20 - 0x10C, // 21 - 0x10B, // 22 - 0x10A, // 23 - 0x109, // 24 - 0x108, // 25 - 0x107, // 26 - 0x106, // 27 - 0x105, // 28 --- - 0x105, // 29 - 0x105, // 30 - 0x105, // 31 - 0x105, // 32 - 0x105 // 33 -}; - // SPI pins #define OSD_CS 47 #define OSD_MISO 33 @@ -140,11 +89,6 @@ int global_counter = 0; DFRobot_OSD osd(OSD_CS); #endif -/*Define Custom characters Example*/ -static const int buf0[36] = {0x02, 0x80, 0x02, 0x40, 0x7F, 0xE0, 0x42, 0x00, - 0x42, 0x00, 0x7A, 0x40, 0x4A, 0x40, 0x4A, 0x80, - 0x49, 0x20, 0x5A, 0xA0, 0x44, 0x60, 0x88, 0x20}; - #include "global_config.h" #include "ui.h" diff --git a/test/test_rssi.cpp b/test/test_rssi.cpp index fad8e22..9c4b023 100644 --- a/test/test_rssi.cpp +++ b/test/test_rssi.cpp @@ -1,6 +1,6 @@ #include #define LOG(args...) printf(args) -#include "../src/core.cpp" +#include #include void setUp(void) {}