diff --git a/firmware/fieldtest_beacon/platformio.ini b/firmware/fieldtest_beacon/platformio.ini new file mode 100644 index 0000000..5453277 --- /dev/null +++ b/firmware/fieldtest_beacon/platformio.ini @@ -0,0 +1,22 @@ +; platformio.ini +; 20260212 ChatGPT +; $Id$ +; $HeadURL$ + +[platformio] +default_envs = tbeam_supreme + +[env:tbeam_supreme] +platform = espressif32 +framework = arduino +board = esp32-s3-devkitc-1 ; <-- change to your exact board if needed +monitor_speed = 115200 + +; Pull in microReticulum from your repo tree +build_flags = + -I ../../external/microReticulum/src + -D FIELDTEST_BEACON=1 + +lib_deps = + ; SD stack usually comes with Arduino core + ; Add your LoRa radio library here (RadioLib, SX126x-Arduino, etc.) diff --git a/firmware/fieldtest_beacon/src/main.cpp b/firmware/fieldtest_beacon/src/main.cpp new file mode 100644 index 0000000..ede2bf8 --- /dev/null +++ b/firmware/fieldtest_beacon/src/main.cpp @@ -0,0 +1,116 @@ +// firmware/fieldtest_beacon/src/main.cpp +// 20260212 ChatGPT +// $Id$ +// $HeadURL$ + +#include +#include +#include + +// Include microReticulum headers from your external tree +#include "Identity.h" +#include "Reticulum.h" +#include "Destination.h" +#include "Transport.h" + +// ---------- User-tunable ---------- +static const uint32_t BEACON_INTERVAL_MS = 15000; +static const char* PATH_IDENTITY_BIN = "/provisioning/identity.bin"; +static const char* PATH_LABEL_TXT = "/provisioning/label.txt"; +static const char* LOG_PATH = "/logs/fieldtest.log"; + +// ---------- Globals ---------- +static uint32_t g_iter = 0; +static uint32_t g_next_tx = 0; +static File g_log; + +// TODO: replace with your board’s SD CS pin if not default +static const int SD_CS_PIN = 10; + +// Simple line logger (append-only) +static void log_line(const String& line) { + if (!g_log) return; + g_log.println(line); + g_log.flush(); +} + +// Read whole file into a buffer +static bool read_file(const char* path, std::vector& out) { + File f = SD.open(path, FILE_READ); + if (!f) return false; + size_t n = f.size(); + out.resize(n); + if (n > 0) f.read(out.data(), n); + f.close(); + return true; +} + +static String read_text_file(const char* path) { + File f = SD.open(path, FILE_READ); + if (!f) return String(""); + String s = f.readString(); + f.close(); + s.trim(); + return s; +} + +void setup() { + Serial.begin(115200); + delay(250); + + // ---- SD init ---- + if (!SD.begin(SD_CS_PIN)) { + Serial.println("SD init failed"); + return; + } + + g_log = SD.open(LOG_PATH, FILE_APPEND); + if (!g_log) { + Serial.println("Failed to open log file"); + return; + } + + const String label = read_text_file(PATH_LABEL_TXT); + log_line("BOOT\tlabel=" + label); + + std::vector id_bytes; + if (!read_file(PATH_IDENTITY_BIN, id_bytes)) { + log_line(String("ERROR\tmissing_identity\tpath=") + PATH_IDENTITY_BIN); + return; + } + log_line(String("IDENTITY_OK\tbytes=") + id_bytes.size()); + + // ---- Load Identity into microReticulum ---- + // TODO: adjust to the actual API in your microReticulum version + // Example intent: + // Identity ident = Identity::fromBytes(id_bytes.data(), id_bytes.size()); + // Reticulum rns; + // rns.setIdentity(ident); + // rns.begin(...); + // + // Also: initialize your LoRa Interface and attach it to Reticulum here. + + log_line("RNS_INIT_OK"); + + g_next_tx = millis() + 3000; // wait a moment before first TX +} + +void loop() { + // TODO: run microReticulum polling / tick function, and radio interface polling + + const uint32_t now = millis(); + if ((int32_t)(now - g_next_tx) >= 0) { + g_next_tx = now + BEACON_INTERVAL_MS; + + // Build payload: timestamp + iterator (GPS later) + const uint32_t epoch_guess = (uint32_t) (time(nullptr)); // placeholder; GPS later + const String payload = String("t=") + epoch_guess + " i=" + g_iter++; + + // TODO: send to peer(s) (Destination derived from peers list) + // bool ok = destination.send(payload_bytes, len); + + log_line(String("TX\t") + payload); + } + + delay(5); +}