Three real regressions from the 2026-07-19 upstream merge, all invisible to the two prescribed smoke builds: - heltec_tracker_v2/HeltecTrackerV2Board.cpp: the FEM trio (setLoRaFemLnaEnabled/canControlLoRaFemLna/isLoRaFemLnaEnabled) was duplicated verbatim by auto-merge, and upstream's new powerOff() (35f654ce) used P_LORA_PA_POWER unguarded — a macro defined only for the tracker_v2 envs, while heltec_tracker_v1_1 compiles the same board file. Guarded it the same way LoRaFEMControl.cpp already guards that macro. - SimpleMeshTables.h: the tracker variants pull in TFT_eSPI, whose TFT_eSPI_ESP32_S3.h defines FS_NO_GLOBALS. That suppresses FS.h's own 'using fs::File', so File never reached global scope and every TU routed through it failed with "'File' has not been declared" — here and at simple_repeater/MyMesh.h:158. Restore the using when FS_NO_GLOBALS is set. Explicit fs::File is not an option: File is also the global type on the nRF52/RP2040 paths, which have no fs namespace. - ST7735Display.cpp: upstream's HSPI fix (d30d8ed7) guarded on HELTEC_LORA_V3 || HELTEC_TRACKER_V2. heltec_tracker_v1_1 matches neither and fell through to &SPI1, which is not instantiated on ESP32. Added it to the guard. Also parks LilyGo_TLora_V2_1_1_6_{repeater,room_server}_observer_mqtt with a trailing underscore (the nibble_screen_connect convention fromb8f1fad6), which also excludes them from the workflows' enumeration regex. That board does NOT fit and never did: 2,069,397 / 1,966,080 = 105.3% on flex, with no webconfig and no upstream merge. It has been failing on production all along — the release ships 30 envs, not 32 — hidden because build.sh does not propagate pio's exit code. Dropping webconfig would recover ~46 KB of a ~101 KB deficit, so that is not a fix. Rationale and options in .scratch/tlora-v2-oversize.md.
87 lines
2.4 KiB
C++
87 lines
2.4 KiB
C++
#pragma once
|
|
|
|
#include <Mesh.h>
|
|
|
|
#ifdef ESP32
|
|
#include <FS.h>
|
|
// TFT_eSPI (pulled in by the tracker variants' display driver) defines
|
|
// FS_NO_GLOBALS, which suppresses FS.h's own `using fs::File`. Without this,
|
|
// File never reaches global scope and every TU that reaches FS.h through
|
|
// TFT_eSPI first fails with "'File' has not been declared" — here and in
|
|
// simple_repeater/MyMesh.h. Restore exactly what FS.h would have done.
|
|
// Cannot use fs::File explicitly instead: File is also the global type on the
|
|
// nRF52/RP2040 paths, which have no fs namespace.
|
|
#if defined(FS_NO_GLOBALS)
|
|
using fs::File;
|
|
#endif
|
|
#endif
|
|
|
|
#define MAX_PACKET_HASHES (128+32)
|
|
|
|
class SimpleMeshTables : public mesh::MeshTables {
|
|
uint8_t _hashes[MAX_PACKET_HASHES*MAX_HASH_SIZE];
|
|
int _next_idx;
|
|
uint32_t _direct_dups, _flood_dups;
|
|
|
|
public:
|
|
SimpleMeshTables() {
|
|
memset(_hashes, 0, sizeof(_hashes));
|
|
_next_idx = 0;
|
|
_direct_dups = _flood_dups = 0;
|
|
}
|
|
|
|
#ifdef ESP32
|
|
void restoreFrom(File f) {
|
|
f.read(_hashes, sizeof(_hashes));
|
|
f.read((uint8_t *) &_next_idx, sizeof(_next_idx));
|
|
}
|
|
void saveTo(File f) {
|
|
f.write(_hashes, sizeof(_hashes));
|
|
f.write((const uint8_t *) &_next_idx, sizeof(_next_idx));
|
|
}
|
|
#endif
|
|
|
|
bool wasSeen(const mesh::Packet* packet) override {
|
|
uint8_t hash[MAX_HASH_SIZE];
|
|
packet->calculatePacketHash(hash);
|
|
|
|
const uint8_t* sp = _hashes;
|
|
for (int i = 0; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
|
|
if (memcmp(hash, sp, MAX_HASH_SIZE) == 0) {
|
|
if (packet->isRouteDirect()) {
|
|
_direct_dups++;
|
|
} else {
|
|
_flood_dups++;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void markSeen(const mesh::Packet* packet) override {
|
|
uint8_t hash[MAX_HASH_SIZE];
|
|
packet->calculatePacketHash(hash);
|
|
memcpy(&_hashes[_next_idx * MAX_HASH_SIZE], hash, MAX_HASH_SIZE);
|
|
_next_idx = (_next_idx + 1) % MAX_PACKET_HASHES;
|
|
}
|
|
|
|
void clear(const mesh::Packet* packet) override {
|
|
uint8_t hash[MAX_HASH_SIZE];
|
|
packet->calculatePacketHash(hash);
|
|
|
|
uint8_t* sp = _hashes;
|
|
for (int i = 0; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
|
|
if (memcmp(hash, sp, MAX_HASH_SIZE) == 0) {
|
|
memset(sp, 0, MAX_HASH_SIZE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t getNumDirectDups() const { return _direct_dups; }
|
|
uint32_t getNumFloodDups() const { return _flood_dups; }
|
|
|
|
void resetStats() { _direct_dups = _flood_dups = 0; }
|
|
};
|