mirror of
https://github.com/ALLFATHER-BV/wadamesh.git
synced 2026-11-07 14:17:18 +00:00
The speed rules behind touchPrefsGetGpsBaud / touchPrefsSetGpsBaudFound move into src/helpers/esp32/GpsBaudPrefs.h (same results, same single write per change), so the test runs the real rules. test/test_gps_baud_probe.cpp compiles the real WadaNmeaLocationProvider.h over a fake UART whose receiver talks NMEA at one speed and reads as noise at every other, with a fake NVS that counts writes. T-Deck default 38400 with a 9600 receiver: found on the first probe step, stored once as the found speed (never as the user's choice), no reopen or write over two more minutes or a GPS saver rest; the next start opens at 9600 and writes nothing. M9 default 115200 with a 38400 receiver: 9600, 19200, 38400. A picked speed is never probed past and nothing is stored; a swapped receiver rewrites the found speed once; no receiver or an unlisted speed never stores anything; a stop mid-probe still finds the speed; the CAP_GPS_BAUD_AUTO path stores to the setting instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
203 lines
8.0 KiB
C++
203 lines
8.0 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
//
|
|
// Host test for GPS Auto speed (32533c45, CAP_GPS_BAUD_FIND on the T-Deck and the M9):
|
|
// the real src/helpers/WadaNmeaLocationProvider.h, with its UART probe, against a
|
|
// simulated receiver that talks NMEA at one speed (noise at every other speed), and
|
|
// the real speed rules of touchPrefsGetGpsBaud / touchPrefsSetGpsBaudFound
|
|
// (src/helpers/esp32/GpsBaudPrefs.h) over a fake NVS that counts writes.
|
|
//
|
|
// c++ -std=c++17 -Wall -Wextra -DESP32 -I src -I test/gps_probe_fakes test/test_gps_baud_probe.cpp \
|
|
// -o /tmp/test_gps_baud_probe && /tmp/test_gps_baud_probe
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
|
|
#include "helpers/WadaNmeaLocationProvider.h"
|
|
#include "helpers/esp32/GpsBaudPrefs.h"
|
|
|
|
uint32_t g_test_ms = 0;
|
|
|
|
// ---- the prefs the provider calls, over a fake NVS (TouchPrefsStore.cpp's wrappers) ----
|
|
static struct {
|
|
uint32_t chosen = 0; // s_cfg.gps_baud (settings blob)
|
|
bool have_found = false; // isKey("gps_bd_fd")
|
|
uint32_t found = 0;
|
|
int found_writes = 0; // prefsPutUInt("gps_bd_fd")
|
|
int chosen_writes = 0; // touchPrefsSetGpsBaud (cfgFlush)
|
|
} nvs;
|
|
|
|
uint32_t touchPrefsGetGpsBaud(uint32_t fallback) {
|
|
if (nvs.chosen != 0) return nvs.chosen;
|
|
return GpsBaudPrefs::effective(0, nvs.have_found ? nvs.found : 0, fallback);
|
|
}
|
|
bool touchPrefsGpsBaudChosen() { return nvs.chosen != 0; }
|
|
void touchPrefsSetGpsBaudFound(uint32_t baud) {
|
|
if (!GpsBaudPrefs::sane(baud)) return;
|
|
if (!GpsBaudPrefs::foundNeedsWrite(baud, nvs.have_found, nvs.have_found ? nvs.found : 0)) return;
|
|
nvs.have_found = true; nvs.found = baud; ++nvs.found_writes;
|
|
}
|
|
bool touchPrefsSetGpsBaud(uint32_t baud) { nvs.chosen = baud; ++nvs.chosen_writes; return true; }
|
|
|
|
static void resetNvs() { nvs = {}; nvs.chosen = 0; }
|
|
|
|
// A boot: the core opens Serial1 at touchPrefsGetGpsBaud(GPS_BAUD_RATE) (initBasicGPS),
|
|
// then the provider begins. The receiver keeps talking at `true_baud`.
|
|
struct Board {
|
|
HardwareSerial uart;
|
|
mesh::RTCClock clock;
|
|
WadaNmeaLocationProvider* gps = nullptr;
|
|
uint32_t default_baud;
|
|
Board(uint32_t true_baud, uint32_t def, bool keep_choice = true) : default_baud(def) {
|
|
uart.true_baud = true_baud;
|
|
uart.begin(touchPrefsGetGpsBaud(def));
|
|
gps = new WadaNmeaLocationProvider(uart, &clock, -1, -1, 18, 17, def, keep_choice);
|
|
gps->begin();
|
|
}
|
|
~Board() { delete gps; }
|
|
// Run the loop task for `ms`, a pass every 10 ms. Returns when the UART has carried
|
|
// a valid sentence at the receiver's speed and stayed there, or at the end.
|
|
void run(uint32_t ms) {
|
|
const uint32_t end = g_test_ms + ms;
|
|
while ((int32_t)(g_test_ms - end) < 0) { gps->loop(); g_test_ms += 10; }
|
|
}
|
|
};
|
|
|
|
int main() {
|
|
g_test_ms = 100000;
|
|
|
|
// ---- T-Deck (default 38400), a 9600 receiver, nothing picked or found ----
|
|
{
|
|
resetNvs();
|
|
Board b(9600, 38400);
|
|
assert(b.uart.baud == 38400); // the first start opens at the default
|
|
b.run(60000);
|
|
assert(b.uart.baud == 9600); // the probe found it...
|
|
assert(b.uart.begun_at.size() == 2 && b.uart.begun_at[1] == 9600); // ...on the first try after 38400
|
|
assert(nvs.have_found && nvs.found == 9600 && nvs.found_writes == 1); // stored once
|
|
assert(nvs.chosen == 0 && nvs.chosen_writes == 0); // never as the user's choice
|
|
const int begins = b.uart.begins;
|
|
b.run(120000); // two more minutes of valid NMEA
|
|
assert(b.uart.begins == begins && nvs.found_writes == 1); // locked: no reopen, no write
|
|
// the GPS saver rests it and wakes it: still no write, no probing
|
|
b.gps->stop(); b.run(5000); b.gps->begin(); b.run(30000);
|
|
assert(b.uart.baud == 9600 && nvs.found_writes == 1);
|
|
assert(b.uart.begins == begins);
|
|
}
|
|
// ---- the next start opens at the found 9600 and locks at once, writing nothing ----
|
|
{
|
|
Board b(9600, 38400);
|
|
assert(b.uart.baud == 9600);
|
|
b.run(60000);
|
|
assert(b.uart.begins == 1 && nvs.found_writes == 1);
|
|
}
|
|
|
|
// ---- a 38400 receiver, M9-style default 115200: found, stored once ----
|
|
{
|
|
resetNvs();
|
|
Board b(38400, 115200);
|
|
b.run(90000);
|
|
assert(b.uart.baud == 38400);
|
|
assert(nvs.found == 38400 && nvs.found_writes == 1);
|
|
// probe order after the default: 9600, 19200, 38400, at 9 s then every 5 s
|
|
assert(b.uart.begun_at.size() == 4);
|
|
assert(b.uart.begun_at[1] == 9600 && b.uart.begun_at[2] == 19200 && b.uart.begun_at[3] == 38400);
|
|
}
|
|
|
|
// ---- a 38400 receiver on the T-Deck default 38400: locks, nothing stored ----
|
|
{
|
|
resetNvs();
|
|
Board b(38400, 38400);
|
|
b.run(60000);
|
|
assert(b.uart.begins == 1 && b.uart.baud == 38400);
|
|
assert(nvs.found_writes == 0 && !nvs.have_found);
|
|
}
|
|
|
|
// ---- a picked speed is used as it is: no probing, nothing stored ----
|
|
{
|
|
resetNvs();
|
|
nvs.chosen = 115200; // the user picked 115200; the receiver talks 9600
|
|
Board b(9600, 38400);
|
|
assert(b.uart.baud == 115200);
|
|
b.run(120000);
|
|
assert(b.uart.begins == 1 && b.uart.baud == 115200);
|
|
assert(nvs.found_writes == 0 && nvs.chosen == 115200 && nvs.chosen_writes == 0);
|
|
}
|
|
// ---- ...and a found speed from before does not override the pick ----
|
|
{
|
|
resetNvs();
|
|
nvs.have_found = true; nvs.found = 9600; nvs.chosen = 57600;
|
|
Board b(9600, 38400);
|
|
assert(b.uart.baud == 57600);
|
|
b.run(60000);
|
|
assert(b.uart.begins == 1 && nvs.found == 9600 && nvs.found_writes == 0);
|
|
}
|
|
|
|
// ---- a swapped receiver: found 9600 stored, the new one talks 38400 ----
|
|
{
|
|
resetNvs();
|
|
nvs.have_found = true; nvs.found = 9600;
|
|
Board b(38400, 38400);
|
|
assert(b.uart.baud == 9600); // opens at the old found speed
|
|
b.run(60000);
|
|
assert(b.uart.baud == 38400 && nvs.found == 38400 && nvs.found_writes == 1);
|
|
}
|
|
|
|
// ---- no receiver at all: the probe keeps cycling, never stores anything ----
|
|
{
|
|
resetNvs();
|
|
Board b(0, 38400);
|
|
b.run(10 * 60000);
|
|
assert(nvs.found_writes == 0 && !nvs.have_found);
|
|
assert(b.uart.begins > 50); // every 5 s after the first 9 s
|
|
for (uint32_t s : b.uart.begun_at)
|
|
assert(s == 9600 || s == 19200 || s == 38400 || s == 57600 || s == 115200);
|
|
}
|
|
|
|
// ---- the GPS saver stops it mid-probe (receiver still silent), then it talks ----
|
|
// begin() takes the stored speed as the UART's without reopening it, so the probe
|
|
// skips that speed on its first pass; it must still find it on the next one.
|
|
{
|
|
resetNvs();
|
|
Board b(0, 38400); // asleep: nothing on the line
|
|
b.run(30000); // the probe has moved the UART off 38400
|
|
assert(b.uart.baud != 38400);
|
|
b.gps->stop(); b.run(2000);
|
|
b.uart.true_baud = 38400; // awake, talking at the default
|
|
b.gps->begin();
|
|
b.run(120000);
|
|
assert(b.uart.baud == 38400);
|
|
assert(nvs.found_writes == 0); // the default needs no stored speed
|
|
}
|
|
|
|
// ---- noise only (a receiver at a speed not in the list): nothing locks on noise ----
|
|
{
|
|
resetNvs();
|
|
Board b(4800, 38400);
|
|
b.run(10 * 60000);
|
|
assert(nvs.found_writes == 0);
|
|
}
|
|
|
|
// ---- CAP_GPS_BAUD_AUTO boards (keep_choice false): the found speed becomes the setting ----
|
|
{
|
|
resetNvs();
|
|
Board b(9600, 38400, false);
|
|
b.run(60000);
|
|
assert(b.uart.baud == 9600 && nvs.chosen == 9600 && nvs.chosen_writes == 1);
|
|
assert(nvs.found_writes == 0);
|
|
}
|
|
|
|
// ---- the rules themselves ----
|
|
assert(GpsBaudPrefs::effective(0, 0, 38400) == 38400);
|
|
assert(GpsBaudPrefs::effective(0, 9600, 38400) == 9600);
|
|
assert(GpsBaudPrefs::effective(0, 1234, 38400) == 38400); // insane found: ignored
|
|
assert(GpsBaudPrefs::effective(0, 0xFFFFFFFFu, 38400) == 38400);
|
|
assert(GpsBaudPrefs::effective(115200, 9600, 38400) == 115200); // a choice wins
|
|
assert(GpsBaudPrefs::foundNeedsWrite(9600, false, 0));
|
|
assert(!GpsBaudPrefs::foundNeedsWrite(9600, true, 9600));
|
|
assert(GpsBaudPrefs::foundNeedsWrite(38400, true, 9600));
|
|
assert(!GpsBaudPrefs::foundNeedsWrite(0, false, 0));
|
|
assert(!GpsBaudPrefs::foundNeedsWrite(1000000, false, 0));
|
|
|
|
printf("test_gps_baud_probe: ok\n");
|
|
return 0;
|
|
}
|