diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index d57cff7a..1bc22d81 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -62,7 +62,7 @@ #include static ESP32Board board; #elif defined(RAK_4631) - #include + #include #include static RAK4631Board board; #else diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index e803a815..73d63a4e 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -19,7 +19,7 @@ /* ------------------------------ Config -------------------------------- */ -#define FIRMWARE_VER_TEXT "v2 (build: 2 Feb 2025)" +#define FIRMWARE_VER_TEXT "v3 (build: 2 Feb 2025)" #ifndef LORA_FREQ #define LORA_FREQ 915.0 @@ -65,7 +65,7 @@ #include static ESP32Board board; #elif defined(RAK_4631) - #include + #include #include static RAK4631Board board; #else @@ -126,6 +126,7 @@ struct NodePrefs { // persisted to file class MyMesh : public mesh::Mesh { RadioLibWrapper* my_radio; FILESYSTEM* _fs; + mesh::MainBoard* _board; NodePrefs _prefs; uint8_t reply_data[MAX_PACKET_PAYLOAD]; int num_clients; @@ -362,8 +363,8 @@ protected: } public: - MyMesh(RadioLibWrapper& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables) - : mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables) + MyMesh(mesh::MainBoard& board, RadioLibWrapper& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables) + : mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables), _board(&board) { my_radio = &radio; num_clients = 0; @@ -442,6 +443,12 @@ public: } else { strcpy(reply, "ERR: clock cannot go backwards"); } + } else if (memcmp(command, "start ota", 9) == 0) { + if (_board->startOTAUpdate()) { + strcpy(reply, "OK"); + } else { + strcpy(reply, "Error"); + } } else if (memcmp(command, "clock", 5) == 0) { uint32_t now = getRTCClock()->getCurrentTime(); DateTime dt = DateTime(now); @@ -494,7 +501,7 @@ public: } else if (memcmp(command, "ver", 3) == 0) { strcpy(reply, FIRMWARE_VER_TEXT); } else { - sprintf(reply, "Unknown: %s (commands: reboot, advert, clock, set, ver)", command); + sprintf(reply, "Unknown: %s (commands: reboot, advert, clock, set, ver, password, start ota)", command); } } }; @@ -516,7 +523,7 @@ ESP32RTCClock rtc_clock; VolatileRTCClock rtc_clock; #endif -MyMesh the_mesh(*new WRAPPER_CLASS(radio, board), *new ArduinoMillis(), fast_rng, rtc_clock, tables); +MyMesh the_mesh(board, *new WRAPPER_CLASS(radio, board), *new ArduinoMillis(), fast_rng, rtc_clock, tables); void halt() { while (1) ; diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 3d84796a..38dfbc36 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -74,7 +74,7 @@ #include static ESP32Board board; #elif defined(RAK_4631) - #include + #include #include static RAK4631Board board; #else diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index cdb8c6c5..41faa731 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -61,7 +61,7 @@ #include static ESP32Board board; #elif defined(RAK_4631) - #include + #include #include static RAK4631Board board; #else diff --git a/platformio.ini b/platformio.ini index 917f24ae..83f56fa5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -315,8 +315,10 @@ lib_deps = [rak4631] extends = nrf52840_base +platform = https://github.com/maxgerhardt/platform-nordicnrf52.git#rak board = wiscore_rak4631 board_check = true +build_src_filter = ${nrf52840_base.build_src_filter} + build_flags = ${nrf52840_base.build_flags} -D RAK_4631 -D RADIO_CLASS=CustomSX1262 diff --git a/src/MeshCore.h b/src/MeshCore.h index b340f5a8..6bb11989 100644 --- a/src/MeshCore.h +++ b/src/MeshCore.h @@ -41,6 +41,7 @@ public: virtual void onAfterTransmit() { } virtual void reboot() = 0; virtual uint8_t getStartupReason() const = 0; + virtual bool startOTAUpdate() { return false; } // not supported }; } \ No newline at end of file diff --git a/src/helpers/nrf52/RAK4631Board.cpp b/src/helpers/nrf52/RAK4631Board.cpp new file mode 100644 index 00000000..c5c93907 --- /dev/null +++ b/src/helpers/nrf52/RAK4631Board.cpp @@ -0,0 +1,63 @@ +#include +#include "RAK4631Board.h" + +#include +#include + +static BLEDfu bledfu; + +static void connect_callback(uint16_t conn_handle) +{ + (void)conn_handle; + MESH_DEBUG_PRINTLN("BLE client connected"); +} + +static void disconnect_callback(uint16_t conn_handle, uint8_t reason) +{ + (void)conn_handle; + (void)reason; + + MESH_DEBUG_PRINTLN("BLE client disconnected"); +} + +bool RAK4631Board::startOTAUpdate() { + // Config the peripheral connection with maximum bandwidth + // more SRAM required by SoftDevice + // Note: All config***() function must be called before begin() + Bluefruit.configPrphBandwidth(BANDWIDTH_MAX); + Bluefruit.configPrphConn(92, BLE_GAP_EVENT_LENGTH_MIN, 16, 16); + + Bluefruit.begin(1, 0); + // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4 + Bluefruit.setTxPower(4); + // Set the BLE device name + Bluefruit.setName("RAK4631_OTA"); + + Bluefruit.Periph.setConnectCallback(connect_callback); + Bluefruit.Periph.setDisconnectCallback(disconnect_callback); + + // To be consistent OTA DFU should be added first if it exists + bledfu.begin(); + + // Set up and start advertising + // Advertising packet + Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); + Bluefruit.Advertising.addTxPower(); + Bluefruit.Advertising.addName(); + + /* Start Advertising + - Enable auto advertising if disconnected + - Interval: fast mode = 20 ms, slow mode = 152.5 ms + - Timeout for fast mode is 30 seconds + - Start(timeout) with timeout = 0 will advertise forever (until connected) + + For recommended advertising interval + https://developer.apple.com/library/content/qa/qa1931/_index.html + */ + Bluefruit.Advertising.restartOnDisconnect(true); + Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms + Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode + Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds + + return true; +} diff --git a/src/helpers/RAK4631Board.h b/src/helpers/nrf52/RAK4631Board.h similarity index 97% rename from src/helpers/RAK4631Board.h rename to src/helpers/nrf52/RAK4631Board.h index 5894f586..53849f61 100644 --- a/src/helpers/RAK4631Board.h +++ b/src/helpers/nrf52/RAK4631Board.h @@ -3,8 +3,6 @@ #include #include -#if defined(NRF52_PLATFORM) - // LoRa radio module pins for RAK4631 #define P_LORA_DIO_1 47 #define P_LORA_NSS 42 @@ -61,6 +59,6 @@ public: void reboot() override { NVIC_SystemReset(); } -}; -#endif + bool startOTAUpdate() override; +};