diff --git a/CMakeLists.txt b/CMakeLists.txt index fd08e56e359e567de9880b2f34f3493ed2d14e29..1cb8b7df5a53d3ae8288e4c4c926e2d89e134a19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,22 +280,19 @@ sbs_target(test-fsm stm32f429zi_stm32f4discovery) add_executable(test-sx1278fsk-bidir src/tests/radio/sx1278/fsk/test-sx1278-bidir.cpp) sbs_target(test-sx1278fsk-bidir stm32f429zi_skyward_groundstation_v2) -add_executable(test-sx1278fsk-tx src/tests/radio/sx1278/fsk/test-sx1278-bench-serial.cpp) +add_executable(test-sx1278fsk-tx src/tests/radio/sx1278/test-sx1278-bench-serial.cpp) target_compile_definitions(test-sx1278fsk-tx PRIVATE DISABLE_RX) sbs_target(test-sx1278fsk-tx stm32f429zi_skyward_groundstation_v2) -add_executable(test-sx1278fsk-rx src/tests/radio/sx1278/fsk/test-sx1278-bench-serial.cpp) +add_executable(test-sx1278fsk-rx src/tests/radio/sx1278/test-sx1278-bench-serial.cpp) target_compile_definitions(test-sx1278fsk-rx PRIVATE DISABLE_TX) sbs_target(test-sx1278fsk-rx stm32f429zi_skyward_groundstation_v2) -add_executable(test-sx1278fsk-gui src/tests/radio/sx1278/fsk/test-sx1278-bench-gui.cpp) -sbs_target(test-sx1278fsk-gui stm32f429zi_skyward_groundstation_v2) - -add_executable(test-sx1278fsk-gui-rx src/tests/radio/sx1278/fsk/test-sx1278-bench-gui.cpp) +add_executable(test-sx1278fsk-gui-rx src/tests/radio/sx1278/test-sx1278-bench-gui.cpp) target_compile_definitions(test-sx1278fsk-gui-rx PRIVATE DISABLE_TX) sbs_target(test-sx1278fsk-gui-rx stm32f429zi_skyward_groundstation_v2) -add_executable(test-sx1278fsk-gui-tx src/tests/radio/sx1278/fsk/test-sx1278-bench-gui.cpp) +add_executable(test-sx1278fsk-gui-tx src/tests/radio/sx1278/test-sx1278-bench-gui.cpp) target_compile_definitions(test-sx1278fsk-gui-tx PRIVATE DISABLE_RX) sbs_target(test-sx1278fsk-gui-tx stm32f429zi_skyward_groundstation_v2) @@ -311,14 +308,30 @@ sbs_target(test-sx1278lora-bidir stm32f429zi_skyward_groundstation_v2) add_executable(test-sx1278lora-mavlink src/tests/radio/sx1278/lora/test-sx1278-mavlink.cpp) sbs_target(test-sx1278lora-mavlink stm32f429zi_skyward_groundstation_v2) -add_executable(test-sx1278lora-rx src/tests/radio/sx1278/lora/test-sx1278-simple.cpp) -target_compile_definitions(test-sx1278lora-rx PRIVATE ENABLE_RX) -sbs_target(test-sx1278lora-rx stm32f429zi_skyward_groundstation_v2) +add_executable(test-sx1278lora-simple-rx src/tests/radio/sx1278/lora/test-sx1278-simple.cpp) +target_compile_definitions(test-sx1278lora-simple-rx PRIVATE ENABLE_RX) +sbs_target(test-sx1278lora-simple-rx stm32f429zi_skyward_groundstation_v2) -add_executable(test-sx1278lora-tx src/tests/radio/sx1278/lora/test-sx1278-simple.cpp) -target_compile_definitions(test-sx1278lora-tx PRIVATE ENABLE_TX) +add_executable(test-sx1278lora-simple-tx src/tests/radio/sx1278/lora/test-sx1278-simple.cpp) +target_compile_definitions(test-sx1278lora-simple-tx PRIVATE ENABLE_TX) +sbs_target(test-sx1278lora-simple-tx stm32f429zi_skyward_groundstation_v2) + +add_executable(test-sx1278lora-tx src/tests/radio/sx1278/test-sx1278-bench-serial.cpp) +target_compile_definitions(test-sx1278lora-tx PRIVATE DISABLE_RX SX1278_IS_LORA) sbs_target(test-sx1278lora-tx stm32f429zi_skyward_groundstation_v2) +add_executable(test-sx1278lora-rx src/tests/radio/sx1278/test-sx1278-bench-serial.cpp) +target_compile_definitions(test-sx1278lora-rx PRIVATE DISABLE_TX SX1278_IS_LORA) +sbs_target(test-sx1278lora-rx stm32f429zi_skyward_groundstation_v2) + +add_executable(test-sx1278lora-gui-rx src/tests/radio/sx1278/test-sx1278-bench-gui.cpp) +target_compile_definitions(test-sx1278lora-gui-rx PRIVATE DISABLE_TX SX1278_IS_LORA) +sbs_target(test-sx1278lora-gui-rx stm32f429zi_skyward_groundstation_v2) + +add_executable(test-sx1278lora-gui-tx src/tests/radio/sx1278/test-sx1278-bench-gui.cpp) +target_compile_definitions(test-sx1278lora-gui-tx PRIVATE DISABLE_RX SX1278_IS_LORA) +sbs_target(test-sx1278lora-gui-tx stm32f429zi_skyward_groundstation_v2) + #-----------------------------------------------------------------------------# # Tests - Sensors # #-----------------------------------------------------------------------------# diff --git a/src/entrypoints/sx1278-serial.cpp b/src/entrypoints/sx1278-serial.cpp index 39be5c51fd0e5e691bba7e48a6f36e63943cac9d..fdd565e83e0ddf5ead9adddf02fa118d90c7671c 100644 --- a/src/entrypoints/sx1278-serial.cpp +++ b/src/entrypoints/sx1278-serial.cpp @@ -159,14 +159,6 @@ int main() { initBoard(); - // Generic SPI configuration - SPIBusConfig spi_config; - spi_config.clockDivider = SPI::ClockDivider::DIV_64; - spi_config.mode = SPI::Mode::MODE_0; - spi_config.bitOrder = SPI::Order::MSB_FIRST; - spi_config.byteOrder = SPI::Order::MSB_FIRST; - spi_config.writeBit = SPI::WriteBit::INVERTED; - SPIBus bus(SX1278_SPI); GpioPin cs = cs::getPin(); diff --git a/src/shared/radio/SX1278/SX1278Common.h b/src/shared/radio/SX1278/SX1278Common.h index 6dd68834f5ed960c5e64d002c6f7bea9787091dc..605c97c34c9511884a8877c5487352067547b33e 100644 --- a/src/shared/radio/SX1278/SX1278Common.h +++ b/src/shared/radio/SX1278/SX1278Common.h @@ -27,6 +27,7 @@ #include <radio/Transceiver.h> #include <memory> +#include <cmath> #include "SX1278Defs.h" @@ -43,6 +44,22 @@ using DioMapping = RegDioMapping::Mapping; */ class ISX1278 : public Transceiver { +public: + /** + * @brief Get the RSSI in dBm, during last packet receive. + */ + virtual float getLastRxRssi() = 0; + + /** + * @brief Get the frequency error index in Hz, during last packet receive (NaN if not available). + */ + virtual float getLastRxFei() { return std::nanf(""); } + + /** + * @brief Get the signal to noise ratio, during last packet receive (NaN if not available). + */ + virtual float getLastRxSnr() { return std::nanf(""); } + protected: /* * Stuff used internally by SX1278Common diff --git a/src/shared/radio/SX1278/SX1278Fsk.h b/src/shared/radio/SX1278/SX1278Fsk.h index be110c8c55f9767e059639f2dd0cadb023cf3817..153fe72b71c445767cc288612b7d25461f6e1c9a 100644 --- a/src/shared/radio/SX1278/SX1278Fsk.h +++ b/src/shared/radio/SX1278/SX1278Fsk.h @@ -184,12 +184,12 @@ public: /** * @brief Get the RSSI in dBm, during last packet receive. */ - float getLastRxRssi(); + float getLastRxRssi() override; /** * @brief Get the frequency error index in Hz, during last packet receive. */ - float getLastRxFei(); + float getLastRxFei() override; private: void rateLimitTx(); diff --git a/src/shared/radio/SX1278/SX1278Lora.h b/src/shared/radio/SX1278/SX1278Lora.h index 94159b59089e15daf3e874e4644aad4f7c9a1f8c..e7e04b7a8cb0d44ddd6b749968323fd1dfbccdcb 100644 --- a/src/shared/radio/SX1278/SX1278Lora.h +++ b/src/shared/radio/SX1278/SX1278Lora.h @@ -180,12 +180,12 @@ public: /** * @brief Get the RSSI in dBm, during last packet receive. */ - float getLastRxRssi(); + float getLastRxRssi() override; /** * @brief Get the RSSI in dBm, during last packet receive. */ - float getLastRxSnr(); + float getLastRxSnr() override; private: void readFifo(uint8_t addr, uint8_t *dst, uint8_t size); diff --git a/src/tests/radio/sx1278/fsk/test-sx1278-bench-gui.cpp b/src/tests/radio/sx1278/fsk/test-sx1278-bench-gui.cpp deleted file mode 100644 index a4b85cc607f1b6a25cfa0af0bf9396004c8ad963..0000000000000000000000000000000000000000 --- a/src/tests/radio/sx1278/fsk/test-sx1278-bench-gui.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* Copyright (c) 2022 Skyward Experimental Rocketry - * Author: Davide Mor - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <drivers/interrupt/external_interrupts.h> -#include <radio/SX1278/SX1278Frontends.h> -#include <radio/SX1278/SX1278Fsk.h> - -#include <thread> - -#include "common.h" -#include "gui/GUI.h" - -// Include body of the test -#include "test-sx1278-bench.cpp" - -using namespace Boardcore; -using namespace miosix; -using namespace mxgui; - -#if defined _BOARD_STM32F429ZI_SKYWARD_GS_V2 -#include "interfaces-impl/hwmapping.h" - -using cs = peripherals::ra01::pc13::cs; -using dio0 = peripherals::ra01::pc13::dio0; -using dio1 = peripherals::ra01::pc13::dio1; -using dio3 = peripherals::ra01::pc13::dio3; - -using sck = interfaces::spi4::sck; -using miso = interfaces::spi4::miso; -using mosi = interfaces::spi4::mosi; - -#define SX1278_SPI SPI4 - -#define SX1278_IRQ_DIO0 EXTI6_IRQHandlerImpl -#define SX1278_IRQ_DIO1 EXTI2_IRQHandlerImpl -#define SX1278_IRQ_DIO3 EXTI11_IRQHandlerImpl - -#else -#error "Target not supported" -#endif - -void __attribute__((used)) SX1278_IRQ_DIO0() -{ - if (sx1278) - sx1278->handleDioIRQ(); -} - -void __attribute__((used)) SX1278_IRQ_DIO1() -{ - if (sx1278) - sx1278->handleDioIRQ(); -} - -void __attribute__((used)) SX1278_IRQ_DIO3() -{ - if (sx1278) - sx1278->handleDioIRQ(); -} - -void initBoard() -{ - GpioPin dio0_pin = dio0::getPin(); - GpioPin dio1_pin = dio1::getPin(); - GpioPin dio3_pin = dio3::getPin(); - - enableExternalInterrupt(dio0_pin.getPort(), dio0_pin.getNumber(), - InterruptTrigger::RISING_EDGE); - enableExternalInterrupt(dio1_pin.getPort(), dio1_pin.getNumber(), - InterruptTrigger::RISING_EDGE); - enableExternalInterrupt(dio3_pin.getPort(), dio3_pin.getNumber(), - InterruptTrigger::RISING_EDGE); -} - -GUI *gui = nullptr; - -void initGUI() -{ - // TODO: This should be in bsp - using GpioUserBtn = Gpio<GPIOA_BASE, 0>; - GpioUserBtn::mode(Mode::INPUT_PULL_DOWN); - - gui = new GUI(); - - ButtonHandler::getInstance().registerButtonCallback( - GpioUserBtn::getPin(), - [](auto event) { gui->screen_manager.onButtonEvent(event); }); -} - -int main() -{ - initBoard(); - initGUI(); - - SX1278Fsk::Config config = { - .freq_rf = 422075000, - .freq_dev = 25000, - .bitrate = 19200, - .rx_bw = SX1278Fsk::Config::RxBw::HZ_83300, - .afc_bw = SX1278Fsk::Config::RxBw::HZ_125000, - .ocp = 120, - .power = 17, - .shaping = SX1278Fsk::Config::Shaping::GAUSSIAN_BT_1_0, - .dc_free = SX1278Fsk::Config::DcFree::WHITENING}; - SX1278Fsk::Error err; - - SPIBus bus(SX1278_SPI); - GpioPin cs = cs::getPin(); - - std::unique_ptr<SX1278::ISX1278Frontend> frontend(new RA01Frontend()); - - sx1278 = - new SX1278Fsk(bus, cs, SPI::ClockDivider::DIV_64, std::move(frontend)); - - printf("\n[sx1278] Configuring sx1278...\n"); - if ((err = sx1278->init(config)) != SX1278Fsk::Error::NONE) - { - gui->stats_screen.updateError(err); - printf("[sx1278] sx1278->init error: %s\n", stringFromErr(err)); - - while (1) - Thread::wait(); - } - - printConfig(config); - gui->stats_screen.updateReady(); - - // Initialize backgrounds threads - spawnThreads(); - - while (1) - { - StatsScreen::Data data = { - stats.txBitrate(), stats.rxBitrate(), stats.corrupted_count, - stats.sent_count, stats.recv_count, 0.0f /* TODO: Packet loss */, - stats.rssi}; - - gui->stats_screen.updateStats(data); - Thread::sleep(100); - } -} diff --git a/src/tests/radio/sx1278/fsk/test-sx1278-bench-serial.cpp b/src/tests/radio/sx1278/fsk/test-sx1278-bench-serial.cpp deleted file mode 100644 index 6bbfaa3c3eec55c245eddacfe2a31e5266f06c2d..0000000000000000000000000000000000000000 --- a/src/tests/radio/sx1278/fsk/test-sx1278-bench-serial.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (c) 2021 Skyward Experimental Rocketry - * Author: Davide Mor - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <drivers/interrupt/external_interrupts.h> -#include <radio/SX1278/SX1278Frontends.h> -#include <radio/SX1278/SX1278Fsk.h> - -#include <thread> - -#include "common.h" - -// Include body of the test -#include "test-sx1278-bench.cpp" - -using namespace Boardcore; -using namespace miosix; - -#if defined _BOARD_STM32F429ZI_SKYWARD_GS_V2 -#include "interfaces-impl/hwmapping.h" - -using cs = peripherals::ra01::pc13::cs; -using dio0 = peripherals::ra01::pc13::dio0; -using dio1 = peripherals::ra01::pc13::dio1; -using dio3 = peripherals::ra01::pc13::dio3; - -using sck = interfaces::spi4::sck; -using miso = interfaces::spi4::miso; -using mosi = interfaces::spi4::mosi; - -#define SX1278_SPI SPI4 - -#define SX1278_IRQ_DIO0 EXTI6_IRQHandlerImpl -#define SX1278_IRQ_DIO1 EXTI2_IRQHandlerImpl -#define SX1278_IRQ_DIO3 EXTI11_IRQHandlerImpl - -#else -#error "Target not supported" -#endif - -void __attribute__((used)) SX1278_IRQ_DIO0() -{ - if (sx1278) - sx1278->handleDioIRQ(); -} - -void __attribute__((used)) SX1278_IRQ_DIO1() -{ - if (sx1278) - sx1278->handleDioIRQ(); -} - -void __attribute__((used)) SX1278_IRQ_DIO3() -{ - if (sx1278) - sx1278->handleDioIRQ(); -} - -void initBoard() -{ - GpioPin dio0_pin = dio0::getPin(); - GpioPin dio1_pin = dio1::getPin(); - GpioPin dio3_pin = dio3::getPin(); - - enableExternalInterrupt(dio0_pin.getPort(), dio0_pin.getNumber(), - InterruptTrigger::RISING_EDGE); - enableExternalInterrupt(dio1_pin.getPort(), dio1_pin.getNumber(), - InterruptTrigger::RISING_EDGE); - enableExternalInterrupt(dio3_pin.getPort(), dio3_pin.getNumber(), - InterruptTrigger::RISING_EDGE); -} - -int main() -{ - initBoard(); - - SX1278Fsk::Config config = { - .freq_rf = 422075000, - .freq_dev = 25000, - .bitrate = 19200, - .rx_bw = SX1278Fsk::Config::RxBw::HZ_83300, - .afc_bw = SX1278Fsk::Config::RxBw::HZ_125000, - .ocp = 120, - .power = 17, - .shaping = SX1278Fsk::Config::Shaping::GAUSSIAN_BT_1_0, - .dc_free = SX1278Fsk::Config::DcFree::WHITENING}; - SX1278Fsk::Error err; - - SPIBus bus(SX1278_SPI); - GpioPin cs = cs::getPin(); - - std::unique_ptr<SX1278::ISX1278Frontend> frontend(new RA01Frontend()); - - sx1278 = - new SX1278Fsk(bus, cs, SPI::ClockDivider::DIV_64, std::move(frontend)); - - printf("\n[sx1278] Configuring sx1278...\n"); - if ((err = sx1278->init(config)) != SX1278Fsk::Error::NONE) - { - printf("[sx1278] sx1278->init error: %s\n", stringFromErr(err)); - return -1; - } - - printConfig(config); - printf("\n[sx1278] Initialization complete!\n"); - - // Initialize backgrounds threads - spawnThreads(); - - while (1) - { - printf( - "\n[sx1278] Stats:\n" - "Tx bitrate: %.2f kb/s\n" - "Packet sent: %d\n" - "Rx bitrate: %.2f kb/s\n" - "Packet received: %d\n" - "Corrupted packets: %d\n" - "Packet loss: %.2f %%\n" - "RSSI: %.2f dBm\n" - "FEI: %.2f dBm\n", - static_cast<float>(stats.txBitrate()) / 1000.0f, stats.sent_count, - static_cast<float>(stats.rxBitrate()) / 1000.0f, stats.recv_count, - stats.corrupted_count, 0.0f /* TODO: Packet loss */, stats.rssi, - stats.fei); - - miosix::Thread::sleep(2000); - } - - return 0; -} diff --git a/src/tests/radio/sx1278/fsk/gui/GUI.h b/src/tests/radio/sx1278/gui/GUI.h similarity index 84% rename from src/tests/radio/sx1278/fsk/gui/GUI.h rename to src/tests/radio/sx1278/gui/GUI.h index bd4544a4e595f265e2553cfe75127064f51416d2..d42aa0125b80a9b25da95fbcc428a2be535dc6a1 100644 --- a/src/tests/radio/sx1278/fsk/gui/GUI.h +++ b/src/tests/radio/sx1278/gui/GUI.h @@ -49,8 +49,9 @@ public: int corrupted_count; int sent_count; int recv_count; - float packet_loss; float rssi; + float fei; + float snr; }; StatsScreen() @@ -72,16 +73,19 @@ public: rx_data.setCell(&lbl_rx_bitrate, 0, 0); rx_data.setCell(&lbl_recv_count, 1, 0); rx_data.setCell(&lbl_corrupted_count, 2, 0); - rx_data.setCell(&lbl_packet_loss, 3, 0); rx_data.setCell(&rx_bitrate, 0, 1); rx_data.setCell(&recv_count, 1, 1); rx_data.setCell(&corrupted_count, 2, 1); - rx_data.setCell(&packet_loss, 3, 1); lbl_misc_data.setTextColor(mxgui::blue); misc_data.setCell(&lbl_rssi, 0, 0); + misc_data.setCell(&lbl_fei, 1, 0); + misc_data.setCell(&lbl_snr, 2, 0); + misc_data.setCell(&rssi, 0, 1); + misc_data.setCell(&fei, 1, 1); + misc_data.setCell(&snr, 2, 1); root.addView(&status, 0.1); root.addView(&lbl_tx_data, 0.1); @@ -92,24 +96,6 @@ public: root.addView(&misc_data, 0.2); } - void updateError(Boardcore::SX1278Fsk::Error value) - { - switch (value) - { - case Boardcore::SX1278Fsk::Error::BAD_VALUE: - status.setBackgroundColor(mxgui::red); - status.setText("BAD VALUE"); - break; - case Boardcore::SX1278Fsk::Error::BAD_VERSION: - status.setBackgroundColor(mxgui::red); - status.setText("BAD VERSION"); - break; - - default: - break; - } - } - void updateReady() { status.setBackgroundColor(mxgui::green); @@ -124,18 +110,18 @@ public: rx_bitrate.setText(format_link_speed(stats.rx_bitrate)); recv_count.setText(fmt::format("{}", stats.recv_count)); corrupted_count.setText(fmt::format("{}", stats.corrupted_count)); - packet_loss.setText( - fmt::format("{:.2f} %", stats.packet_loss * 100.0f)); rssi.setText(fmt::format("{} dBm", stats.rssi)); + fei.setText(fmt::format("{} Hz", stats.fei)); + snr.setText(fmt::format("{}", stats.snr)); } Boardcore::VerticalLayout root{10}; Boardcore::TextView status{"LOADING"}; Boardcore::GridLayout tx_data{2, 2}; - Boardcore::GridLayout rx_data{4, 2}; - Boardcore::GridLayout misc_data{1, 2}; + Boardcore::GridLayout rx_data{3, 2}; + Boardcore::GridLayout misc_data{3, 2}; Boardcore::TextView lbl_tx_data{"Tx data"}; Boardcore::TextView lbl_rx_data{"Rx data"}; @@ -146,16 +132,18 @@ public: Boardcore::TextView lbl_rx_bitrate{"Rx bitrate:"}; Boardcore::TextView lbl_recv_count{"Packets received:"}; Boardcore::TextView lbl_corrupted_count{"Corrupted packets:"}; - Boardcore::TextView lbl_packet_loss{"Packet loss:"}; Boardcore::TextView lbl_rssi{"RSSI:"}; + Boardcore::TextView lbl_fei{"FEI:"}; + Boardcore::TextView lbl_snr{"SNR:"}; Boardcore::TextView tx_bitrate{"0.00 b/s"}; Boardcore::TextView rx_bitrate{"0.00 b/s"}; Boardcore::TextView corrupted_count{"0"}; Boardcore::TextView recv_count{"0"}; Boardcore::TextView sent_count{"0"}; - Boardcore::TextView packet_loss{"0 %"}; Boardcore::TextView rssi{"0 dBm"}; + Boardcore::TextView fei{"0 Hz"}; + Boardcore::TextView snr{"0"}; }; class GUI diff --git a/src/tests/radio/sx1278/sx1278-init.h b/src/tests/radio/sx1278/sx1278-init.h new file mode 100644 index 0000000000000000000000000000000000000000..0cdcfd2e6e75e255352220b32e5562611fe0f707 --- /dev/null +++ b/src/tests/radio/sx1278/sx1278-init.h @@ -0,0 +1,177 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Davide Mor + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <drivers/interrupt/external_interrupts.h> + +// SX1278 includes +#include <radio/SX1278/SX1278Frontends.h> +#include <radio/SX1278/SX1278Fsk.h> +#include <radio/SX1278/SX1278Lora.h> + +// Uncomment the following line to enable Lora mode +// Or use SBS to define it for you +// #define SX1278_IS_LORA + +#if defined _BOARD_STM32F429ZI_SKYWARD_GS_V2 +#include "interfaces-impl/hwmapping.h" + +// Uncomment the following line to enable Ebyte module +// #define SX1278_IS_EBYTE + +using cs = miosix::peripherals::ra01::pc13::cs; +using dio0 = miosix::peripherals::ra01::pc13::dio0; +using dio1 = miosix::peripherals::ra01::pc13::dio1; +using dio3 = miosix::peripherals::ra01::pc13::dio3; + +using sck = miosix::interfaces::spi4::sck; +using miso = miosix::interfaces::spi4::miso; +using mosi = miosix::interfaces::spi4::mosi; + +#ifdef SX1278_IS_EBYTE +using txen = miosix::Gpio<GPIOE_BASE, 4>; +using rxen = miosix::Gpio<GPIOD_BASE, 4>; +#endif + +#define SX1278_SPI SPI4 + +#define SX1278_IRQ_DIO0 EXTI6_IRQHandlerImpl +#define SX1278_IRQ_DIO1 EXTI2_IRQHandlerImpl +#define SX1278_IRQ_DIO3 EXTI11_IRQHandlerImpl + +#else +#error "Target not supported" +#endif + +#ifdef SX1278_IS_LORA +static constexpr size_t SX1278_MTU = Boardcore::SX1278Lora::MTU; +Boardcore::SX1278Lora *sx1278 = nullptr; +#else +static constexpr size_t SX1278_MTU = Boardcore::SX1278Fsk::MTU; +Boardcore::SX1278Fsk *sx1278 = nullptr; +#endif + +#ifdef SX1278_IRQ_DIO0 +void __attribute__((used)) SX1278_IRQ_DIO0() +{ + if (sx1278) + sx1278->handleDioIRQ(); +} +#endif + +#ifdef SX1278_IRQ_DIO1 +void __attribute__((used)) SX1278_IRQ_DIO1() +{ + if (sx1278) + sx1278->handleDioIRQ(); +} +#endif + +#ifdef SX1278_IRQ_DIO3 +void __attribute__((used)) SX1278_IRQ_DIO3() +{ + if (sx1278) + sx1278->handleDioIRQ(); +} +#endif + +void initBoard() +{ +#ifdef SX1278_IS_EBYTE + rxen::mode(miosix::Mode::OUTPUT); + txen::mode(miosix::Mode::OUTPUT); + rxen::low(); + txen::low(); +#endif + +#ifdef SX1278_IRQ_DIO0 + miosix::GpioPin dio0_pin = dio0::getPin(); + enableExternalInterrupt(dio0_pin.getPort(), dio0_pin.getNumber(), + InterruptTrigger::RISING_EDGE); +#endif + +#ifdef SX1278_IRQ_DIO1 + miosix::GpioPin dio1_pin = dio1::getPin(); + enableExternalInterrupt(dio1_pin.getPort(), dio1_pin.getNumber(), + InterruptTrigger::RISING_EDGE); +#endif + +#ifdef SX1278_IRQ_DIO3 + miosix::GpioPin dio3_pin = dio3::getPin(); + enableExternalInterrupt(dio3_pin.getPort(), dio3_pin.getNumber(), + InterruptTrigger::RISING_EDGE); +#endif +} + +bool initRadio() +{ + // Initialize frontend (if any) +#ifdef IS_EBYTE + std::unique_ptr<Boardcore::SX1278::ISX1278Frontend> frontend( + new Boardcore::EbyteFrontend(txen::getPin(), rxen::getPin())); +#else + std::unique_ptr<Boardcore::SX1278::ISX1278Frontend> frontend( + new Boardcore::RA01Frontend()); +#endif + + Boardcore::SPIBus bus(SX1278_SPI); + miosix::GpioPin cs = cs::getPin(); + + // Initialize actual radio driver +#ifdef SX1278_IS_LORA + // Run default configuration + Boardcore::SX1278Lora::Config config; + Boardcore::SX1278Lora::Error err; + + sx1278 = new Boardcore::SX1278Lora( + bus, cs, Boardcore::SPI::ClockDivider::DIV_64, std::move(frontend)); + + printf("\n[sx1278] Configuring sx1278 lora...\n"); + if ((err = sx1278->init(config)) != Boardcore::SX1278Lora::Error::NONE) + { + printf("[sx1278] sx1278->init error\n"); + return false; + } + + printf("\n[sx1278] Initialization complete!\n"); +#else + // Run default configuration + Boardcore::SX1278Fsk::Config config; + Boardcore::SX1278Fsk::Error err; + + sx1278 = new Boardcore::SX1278Fsk( + bus, cs, Boardcore::SPI::ClockDivider::DIV_64, std::move(frontend)); + + printf("\n[sx1278] Configuring sx1278 fsk...\n"); + if ((err = sx1278->init(config)) != Boardcore::SX1278Fsk::Error::NONE) + { + // FIXME: Why does clang-format put this line up here? + printf("[sx1278] sx1278->init error\n"); + return false; + } + + printf("\n[sx1278] Initialization complete!\n"); +#endif + + return true; +} \ No newline at end of file diff --git a/src/tests/radio/sx1278/test-sx1278-bench-gui.cpp b/src/tests/radio/sx1278/test-sx1278-bench-gui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0182e06f2ae8d6c91d35194d1a272b84b724b2f5 --- /dev/null +++ b/src/tests/radio/sx1278/test-sx1278-bench-gui.cpp @@ -0,0 +1,71 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Author: Davide Mor + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "gui/GUI.h" + +// Include body of the test +#include "test-sx1278-bench.cpp" + +using namespace mxgui; + +GUI *gui = nullptr; + +void initGUI() +{ + // TODO: This should be in bsp + using GpioUserBtn = Gpio<GPIOA_BASE, 0>; + GpioUserBtn::mode(Mode::INPUT_PULL_DOWN); + + gui = new GUI(); + + ButtonHandler::getInstance().registerButtonCallback( + GpioUserBtn::getPin(), + [](auto event) { gui->screen_manager.onButtonEvent(event); }); +} + +int main() +{ + initBoard(); + initGUI(); + if (!initRadio()) + { + while (1) + ; + } + + // Set display to ready + gui->stats_screen.updateReady(); + + // Initialize backgrounds threads + spawnThreads(); + + while (1) + { + StatsScreen::Data data = { + stats.txBitrate(), stats.rxBitrate(), stats.corrupted_count, + stats.sent_count, stats.recv_count, stats.rssi, + stats.fei, stats.snr}; + + gui->stats_screen.updateStats(data); + Thread::sleep(100); + } +} diff --git a/src/tests/radio/sx1278/test-sx1278-bench-serial.cpp b/src/tests/radio/sx1278/test-sx1278-bench-serial.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4cc2db9645decea157f8cd85e6eb40ae6db9b58 --- /dev/null +++ b/src/tests/radio/sx1278/test-sx1278-bench-serial.cpp @@ -0,0 +1,57 @@ +/* Copyright (c) 2021 Skyward Experimental Rocketry + * Author: Davide Mor + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Include the body of the test +#include "test-sx1278-bench.cpp" + +int main() +{ + initBoard(); + if(!initRadio()) { + while(1); + } + + // Initialize backgrounds threads + spawnThreads(); + + while (1) + { + printf( + "\n[sx1278] Stats:\n" + "Tx bitrate: %.2f kb/s\n" + "Packet sent: %d\n" + "Rx bitrate: %.2f kb/s\n" + "Packet received: %d\n" + "Corrupted packets: %d\n" + "RSSI: %.2f dBm\n" + "FEI: %.2f Hz\n" + "SNR: %.2f\n", + static_cast<float>(stats.txBitrate()) / 1000.0f, stats.sent_count, + static_cast<float>(stats.rxBitrate()) / 1000.0f, stats.recv_count, + stats.corrupted_count, stats.rssi, + stats.fei, stats.snr); + + miosix::Thread::sleep(2000); + } + + return 0; +} diff --git a/src/tests/radio/sx1278/fsk/test-sx1278-bench.cpp b/src/tests/radio/sx1278/test-sx1278-bench.cpp similarity index 97% rename from src/tests/radio/sx1278/fsk/test-sx1278-bench.cpp rename to src/tests/radio/sx1278/test-sx1278-bench.cpp index 66e153a862d7c9c74f44fdd0ab51767c6795ff46..ca8a8454ed1bda520671872953aaedf1c26adee9 100644 --- a/src/tests/radio/sx1278/fsk/test-sx1278-bench.cpp +++ b/src/tests/radio/sx1278/test-sx1278-bench.cpp @@ -20,9 +20,10 @@ * THE SOFTWARE. */ +#include "sx1278-init.h" + #include <drivers/timer/TimestampTimer.h> #include <miosix.h> -#include <radio/SX1278/SX1278Fsk.h> #include <utils/MovingAverage.h> #include <thread> @@ -30,8 +31,6 @@ using namespace Boardcore; using namespace miosix; -SX1278Fsk *sx1278 = nullptr; - // Simple xorshift RNG uint32_t xorshift32() { @@ -86,6 +85,7 @@ struct LinkStats float rssi = 0.0f; float fei = 0.0f; + float snr = 0.0f; uint64_t txBitrate() { @@ -120,6 +120,7 @@ void recvLoop() stats.rssi = sx1278->getLastRxRssi(); stats.fei = sx1278->getLastRxFei(); + stats.snr = sx1278->getLastRxSnr(); } else {