From 1963734e483018029c3da3229bb662777de1d67e Mon Sep 17 00:00:00 2001 From: Sassa NF Date: Sun, 26 Jan 2025 11:50:29 +0000 Subject: [PATCH] Initial support for additional Radio Module SX1262 --- lib/comms/bus.cpp | 4 +- lib/comms/comms.cpp | 2 +- lib/comms/comms.h | 1 + lib/config/config.cpp | 120 ++++++++++++++++++++++++++++++---- lib/config/config.h | 57 +++++++++++++++- lib/events/events.h | 1 + lib/loraboards/LoRaBoards.cpp | 6 +- lib/radio/SX1262.cpp | 49 ++++++++++++++ lib/radio/radio.h | 29 ++++++++ src/main.cpp | 50 ++++++++++++++ 10 files changed, 298 insertions(+), 21 deletions(-) create mode 100644 lib/radio/SX1262.cpp create mode 100644 lib/radio/radio.h diff --git a/lib/comms/bus.cpp b/lib/comms/bus.cpp index d9af703..520aa58 100644 --- a/lib/comms/bus.cpp +++ b/lib/comms/bus.cpp @@ -35,8 +35,8 @@ bool initSPIs(Config &config) // if all the pins are -1, then will use the default for SPI bus_num hspi.begin(config.spi1.clk, config.spi1.miso, config.spi1.mosi); - Serial.printf("Initialized SPI%d: SC:%d MISO:%d MOSI:%d clock:%d\n", - (int)config.spi1.bus_num, (int)config.spi1.clk, + Serial.printf("Initialized SPI%d @ %x: SC:%d MISO:%d MOSI:%d clock:%d\n", + (int)config.spi1.bus_num, (void *)&hspi, (int)config.spi1.clk, (int)config.spi1.miso, (int)config.spi1.mosi, (int)config.spi1.clock_freq); } diff --git a/lib/comms/comms.cpp b/lib/comms/comms.cpp index 0814047..c0215d0 100644 --- a/lib/comms/comms.cpp +++ b/lib/comms/comms.cpp @@ -418,7 +418,7 @@ String _scan_result_str(ScanTaskResult &r) for (int i = 0; i < r.sz; i++) { p += (i == 0 ? "(" : ", (") + String(r.freqs_khz[i]) + ", " + String(r.rssis[i]) + - ")"; + (r.rssis2 ? ", " + String(r.rssis2[i]) : "") + ")"; } return p + " ]\n"; diff --git a/lib/comms/comms.h b/lib/comms/comms.h index b8d2905..57fb90b 100644 --- a/lib/comms/comms.h +++ b/lib/comms/comms.h @@ -51,6 +51,7 @@ struct ScanTaskResult size_t sz; uint32_t *freqs_khz; int16_t *rssis; + int16_t *rssis2; int16_t prssi; }; diff --git a/lib/config/config.cpp b/lib/config/config.cpp index faadd48..3f3d8d9 100644 --- a/lib/config/config.cpp +++ b/lib/config/config.cpp @@ -88,18 +88,6 @@ Config Config::init() continue; } - if (r.key.equalsIgnoreCase("rx_lora")) - { - c.rx_lora = configureLora(r.value); - continue; - } - - if (r.key.equalsIgnoreCase("tx_lora")) - { - c.tx_lora = configureLora(r.value); - continue; - } - Serial.printf("Unknown key '%s' will be ignored\n", r.key); } @@ -194,6 +182,12 @@ bool Config::updateConfig(String key, String value) return true; } + if (key.equalsIgnoreCase("radio2")) + { + radio2 = RadioModuleSPIConfig::configure(value); + return true; + } + UPDATE_BOOL(is_host, key, value); UPDATE_BOOL(lora_enabled, key, value); @@ -523,6 +517,102 @@ void Config::configureDetectionStrategy(String cfg) } } +RadioModuleSPIConfig RadioModuleSPIConfig::configure(String cfg) +{ + RadioModuleSPIConfig c; + + c.bus_num = 1; + c.cs = RADIO_MODULE_CS_PIN; + c.rst = RADIO_MODULE_RST_PIN; + c.dio1 = RADIO_MODULE_DIO1_PIN; + c.busy = RADIO_MODULE_BUSY_PIN; + + c.clock_freq = RADIO_MODULE_CLOCK_FREQ; + c.msb_first = RADIO_MODULE_MSB_FIRST; + c.spi_mode = RADIO_MODULE_SPI_MODE; + + int begin = 0; + int end, i; + + while ((i = findSepa(cfg, ",", begin, end)) >= 0) + { + String param = cfg.substring(begin, end); + begin = i; + int j = param.indexOf(":"); + if (j < 0) + { + c.module = param; + c.enabled = !param.equalsIgnoreCase("none"); + continue; + } + + String k = param.substring(0, j); + param = param.substring(j + 1); + + k.toLowerCase(); + if (k.equals("bus")) + { + c.bus_num = param.toInt(); + continue; + } + + if (k.equals("rst")) + { + c.rst = param.toInt(); + continue; + } + + if (k.equals("dio1")) + { + c.dio1 = param.toInt(); + continue; + } + + if (k.equals("busy")) + { + c.busy = param.toInt(); + continue; + } + + if (k.equals("freq")) + { + c.clock_freq = param.toInt(); + continue; + } + + if (k.equals("msb")) + { + c.msb_first = !!param.toInt(); + continue; + } + + if (k.equals("spi_mode")) + { + c.spi_mode = param.toInt(); + continue; + } + + c.module = k; + c.cs = param.toInt(); + c.enabled = true; + } + + return c; +} + +String RadioModuleSPIConfig::toStr() +{ + if (!enabled) + { + return "none"; + } + + return module + ":" + String(cs) + ",bus:" + String(bus_num) + ",rst:" + String(rst) + + ",dio1:" + String(dio1) + ",busy:" + String(busy) + + ",freq:" + String(clock_freq) + ",msb:" + String(msb_first ? 1 : 0) + + ",spi_mode:" + String(spi_mode); +} + bool Config::write_config(const char *path) { File f = SD.open(path, FILE_WRITE, /*create = */ true); @@ -549,6 +639,7 @@ bool Config::write_config(const char *path) f.println("uart1 = " + getConfig("uart1")); f.println("spi1 = " + getConfig("spi1")); f.println("wire1 = " + getConfig("wire1")); + f.println("radio2 = " + getConfig("radio2")); f.close(); return true; @@ -621,6 +712,11 @@ String Config::getConfig(String key) return wire1.toStr(); } + if (key.equalsIgnoreCase("radio2")) + { + return radio2.toStr(); + } + return ""; } diff --git a/lib/config/config.h b/lib/config/config.h index 7ef380e..4be175c 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -96,6 +96,52 @@ struct BusConfig String toStr(); }; +#ifndef RADIO_MODULE_CS_PIN +#define RADIO_MODULE_CS_PIN 38 +#endif + +#ifndef RADIO_MODULE_DIO1_PIN +#define RADIO_MODULE_DIO1_PIN 40 +#endif + +#ifndef RADIO_MODULE_RST_PIN +#define RADIO_MODULE_RST_PIN 41 +#endif + +#ifndef RADIO_MODULE_BUSY_PIN +#define RADIO_MODULE_BUSY_PIN 39 +#endif + +#ifndef RADIO_MODULE_CLOCK_FREQ +#define RADIO_MODULE_CLOCK_FREQ 16000000 +#endif + +#ifndef RADIO_MODULE_MSB_FIRST +#define RADIO_MODULE_MSB_FIRST 1 +#endif + +#ifndef RADIO_MODULE_SPI_MODE +#define RADIO_MODULE_SPI_MODE 0 +#endif + +struct RadioModuleSPIConfig +{ + bool enabled; + String module; + int8_t bus_num; + int8_t cs; + int8_t rst; + int8_t dio1; + int8_t busy; + + uint32_t clock_freq; + bool msb_first; + int8_t spi_mode; + + static RadioModuleSPIConfig configure(String cfg); + String toStr(); +}; + #ifndef FREQ_RX #define FREQ_RX 866 #endif @@ -136,13 +182,17 @@ struct BusConfig #endif #ifndef DEFAULT_SPI1 -#define DEFAULT_SPI1 "none" +#define DEFAULT_SPI1 "s1:16000000,clk:42,mosi:46,miso:45" #endif #ifndef DEFAULT_WIRE1 #define DEFAULT_WIRE1 "none" #endif +#ifndef DEFAULT_RADIO2 +#define DEFAULT_RADIO2 "none" +#endif + #define CREATE_MISSING_CONFIG true struct Config { @@ -163,6 +213,7 @@ struct Config BusConfig uart1; BusConfig spi1; BusConfig wire1; + RadioModuleSPIConfig radio2; bool is_host; bool lora_enabled; @@ -177,8 +228,8 @@ struct Config uart0(BusConfig::configure(DEFAULT_UART0)), uart1(BusConfig::configure(DEFAULT_UART1)), spi1(BusConfig::configure(DEFAULT_SPI1)), - wire1(BusConfig::configure(DEFAULT_WIRE1)), - lora_enabled(DEFAULT_LORA_ENABLED) {}; + wire1(BusConfig::configure(DEFAULT_WIRE1)), lora_enabled(DEFAULT_LORA_ENABLED), + radio2(RadioModuleSPIConfig::configure(DEFAULT_RADIO2)) {}; bool write_config(const char *path); diff --git a/lib/events/events.h b/lib/events/events.h index 6f1dea0..b1b249b 100644 --- a/lib/events/events.h +++ b/lib/events/events.h @@ -18,6 +18,7 @@ struct Event struct { float rssi; + float rssi2; float freq; bool trigger; bool detected; diff --git a/lib/loraboards/LoRaBoards.cpp b/lib/loraboards/LoRaBoards.cpp index 9af8543..61e515b 100644 --- a/lib/loraboards/LoRaBoards.cpp +++ b/lib/loraboards/LoRaBoards.cpp @@ -533,7 +533,7 @@ bool beginDisplay() Wire.beginTransmission(DISPLAY_ADDR); if (Wire.endTransmission() == 0) { - Serial.printf("Find Display model at 0x%X address\n", DISPLAY_ADDR); + Serial.printf("Found Display model at 0x%X address\n", DISPLAY_ADDR); u8g2 = new DISPLAY_MODEL(U8G2_R0, U8X8_PIN_NONE); u8g2->begin(); u8g2->clearBuffer(); @@ -569,6 +569,7 @@ bool beginSDCard() else { Serial.println("Warning: Failed to init Sd Card"); + SDCardSPI.end(); } #endif return false; @@ -792,10 +793,9 @@ void setupBoards(bool disable_u8g2) bool sdReady; #ifndef DISABLE_SDCARD - for (int i = 0; i < 5 && !(sdReady = beginSDCard()); i++) + if (!(sdReady = beginSDCard())) { Serial.println("SD card failed or not found"); - delay(1000); } #endif diff --git a/lib/radio/SX1262.cpp b/lib/radio/SX1262.cpp new file mode 100644 index 0000000..fe2237b --- /dev/null +++ b/lib/radio/SX1262.cpp @@ -0,0 +1,49 @@ +#include "radio.h" +#include +#include + +SX1262Module::SX1262Module(RadioModuleSPIConfig radio2) : RadioModule() +{ + _radio = new SX1262(new Module( + radio2.cs, radio2.dio1, radio2.rst, radio2.busy, radio2.bus_num == 1 ? hspi : SPI, + SPISettings(radio2.clock_freq, radio2.msb_first ? MSBFIRST : LSBFIRST, + radio2.spi_mode))); + Serial.printf("Initialized Radio2: %s\n", radio2.toStr().c_str()); +} + +int16_t SX1262Module::beginScan(float init_freq, float bw, uint8_t shaping) +{ + int16_t status = _radio->beginFSK(init_freq); + if (status != RADIOLIB_ERR_NONE) + { + Serial.printf("Radio2: Failed beginFSK: %d\n", status); + return status; + } + + status = _radio->startReceive(RADIOLIB_SX126X_RX_TIMEOUT_NONE); + + if (status != RADIOLIB_ERR_NONE) + { + Serial.printf("Radio2: Failed startReceive: %d\n", status); + return status; + } + + status = setFrequency(init_freq); + if (status != RADIOLIB_ERR_NONE) + { + Serial.printf("Radio2: Failed setFrequency: %d\n", status); + return status; + } + + return status; +} + +int16_t SX1262Module::setFrequency(float freq) +{ + return _radio->setFrequency(freq, + true); // false = calibration is needed here +} + +int16_t SX1262Module::setRxBandwidth(float bw) { return _radio->setRxBandwidth(bw); } + +float SX1262Module::getRSSI() { return _radio->getRSSI(false); } diff --git a/lib/radio/radio.h b/lib/radio/radio.h new file mode 100644 index 0000000..81c14a1 --- /dev/null +++ b/lib/radio/radio.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +struct RadioModule +{ + RadioModule() {}; + + virtual int16_t beginScan(float init_freq, float bw, uint8_t shaping) = 0; + virtual int16_t setFrequency(float freq) = 0; + virtual int16_t setRxBandwidth(float bw) = 0; + virtual float getRSSI() = 0; +}; + +#ifdef USING_SX1262 +struct SX1262Module : RadioModule +{ + SX1262 *_radio; + + SX1262Module(RadioModuleSPIConfig cfg); + + int16_t beginScan(float init_freq, float bw, uint8_t shaping) override; + int16_t setFrequency(float freq) override; + int16_t setRxBandwidth(float bw) override; + + float getRSSI() override; +}; +#endif diff --git a/src/main.cpp b/src/main.cpp index 54597ba..9079f65 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -141,10 +141,13 @@ void sendBTData(float heading, float rssi) #include #include +#include DroneHeading droneHeading; Compass *compass = NULL; +RadioModule *radio2; + #define BT_SCAN_DELAY 60 * 1 * 1000 #define WF_SCAN_DELAY 60 * 2 * 1000 long noDevicesMillis = 0, cycleCnt = 0; @@ -942,6 +945,25 @@ void init_radio() setFrequency(CONF_FREQ_BEGIN); delay(100); + + if (config.radio2.enabled && config.radio2.module.equalsIgnoreCase("SX1262")) + { + radio2 = new SX1262Module(config.radio2); + state = radio2->beginScan(CONF_FREQ_BEGIN, BANDWIDTH, RADIOLIB_SHAPING_NONE); + if (state == RADIOLIB_ERR_NONE) + { + both.println("Initialized additional module OK"); + radio2->setRxBandwidth(BANDWIDTH); + } + else + { + Serial.printf("Error initializing additional module: %d\n", state); + if (state == RADIOLIB_ERR_CHIP_NOT_FOUND) + { + Serial.println("Radio2: CHIP NOT FOUND"); + } + } + } } struct frequency_scan_result @@ -973,12 +995,19 @@ void eventListenerForReport(void *arg, Event &e) frequency_scan_result.readings_sz = frequency_scan_result.dump.sz + 1; uint32_t *f = new uint32_t[frequency_scan_result.readings_sz]; int16_t *r = new int16_t[frequency_scan_result.readings_sz]; + int16_t *r2 = radio2 ? new int16_t[frequency_scan_result.readings_sz] : NULL; if (old_sz > 0) { memcpy(f, frequency_scan_result.dump.freqs_khz, old_sz * sizeof(uint32_t)); memcpy(r, frequency_scan_result.dump.rssis, old_sz * sizeof(int16_t)); + if (radio2) + { + memcpy(r2, frequency_scan_result.dump.rssis2, + old_sz * sizeof(int16_t)); + delete[] frequency_scan_result.dump.rssis2; + } delete[] frequency_scan_result.dump.freqs_khz; delete[] frequency_scan_result.dump.rssis; @@ -986,12 +1015,16 @@ void eventListenerForReport(void *arg, Event &e) frequency_scan_result.dump.freqs_khz = f; frequency_scan_result.dump.rssis = r; + frequency_scan_result.dump.rssis2 = r2; } frequency_scan_result.dump.freqs_khz[frequency_scan_result.dump.sz] = e.detected.freq * 1000; // convert to kHz frequency_scan_result.dump.rssis[frequency_scan_result.dump.sz] = max(e.detected.rssi, -999.0f); + if (radio2) + frequency_scan_result.dump.rssis2[frequency_scan_result.dump.sz] = + max(e.detected.rssi2, -999.0f); frequency_scan_result.dump.sz++; if (e.epoch != frequency_scan_result.last_epoch || @@ -2705,6 +2738,14 @@ void doScan() int display_x = x / SCAN_RBW_FACTOR; freqX[(int)r.current_frequency] = display_x; setFrequency(curr_freq / 1000.0); + if (radio2 != NULL) + { + state = radio2->setFrequency(curr_freq / 1000.0); + if (state != RADIOLIB_ERR_NONE) + { + Serial.printf("Radio2: Failed to set freq: %d\n", state); + } + } LOG("Step:%d Freq: %f\n", x, r.current_frequency); // SpectralScan Method @@ -2736,6 +2777,8 @@ void doScan() #endif #ifdef METHOD_RSSI // Spectrum analyzer using getRSSI + float rssi2 = -999; + { LOG("METHOD RSSI"); @@ -2755,6 +2798,7 @@ void doScan() else g = &getRSSI; uint16_t max_rssi = 120; + // Scan if not in the ignore list if (ignoredFreq.find((int)r.current_frequency) == ignoredFreq.end()) { @@ -2766,6 +2810,11 @@ void doScan() { xRSSI[display_x] = (int)max_rssi; } + + for (int i = 0; radio2 != NULL && i < samples; i++) + { + rssi2 = max(rssi2, radio2->getRSSI()); + } } else { @@ -2801,6 +2850,7 @@ void doScan() Event event = r.detect(result, filtered_result, RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE, samples); event.time_ms = millis(); + event.detected.rssi2 = rssi2; size_t detected_at = event.detected.detected_at; if (max_rssi_x > detected_at)