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(); +}