diff --git a/.github/workflows/run-unit-tests.yml b/.github/workflows/run-unit-tests.yml index 2a23a20a08..9768b290b5 100644 --- a/.github/workflows/run-unit-tests.yml +++ b/.github/workflows/run-unit-tests.yml @@ -20,7 +20,7 @@ jobs: uses: ./.github/actions/setup-build-environment - name: Run Unit Tests - run: pio test -e native -e native_kiss_modem -e native_core -e native_ofast -e native_chat -e native_identity_store -e native_node_prefs -e native_radio_wrappers -e native_server -e native_sensor -e native_repeater -e native_repeater_full -e native_region -e native_radio_chips -e native_variant_target -e native_variant_target_override -e native_companion -vv + run: pio test -e native -e native_kiss_modem -e native_core -e native_ofast -e native_chat -e native_identity_store -e native_node_prefs -e native_radio_wrappers -e native_server -e native_sensor -e native_repeater -e native_repeater_full -e native_region -e native_radio_chips -e native_variant_target -e native_variant_target_override -e native_companion -e native_esp32_rtc_backup -vv - name: Upload Test Results # Upload test results even if the test step failed. diff --git a/docs/refactoring/0011-variant-target.md b/docs/refactoring/0011-variant-target.md index b163c54096..94fd7d3406 100644 --- a/docs/refactoring/0011-variant-target.md +++ b/docs/refactoring/0011-variant-target.md @@ -3,7 +3,9 @@ Status: cut A (one shared `radio_new_identity()`) and cut B (one shared FEM RX gain handler) implemented, each its own pull request, B stacked on A. Cut C (one default `radio_init()` for 31 nRF52 variants) implemented, its own pull request, on top of -A and B. Cuts D and E are planned and need their own review before code. Behaviour change: none. +A and B. Cut D (the radio, wrapper and RTC globals) is implemented as two pull requests, +D1 (31 nRF52 variants) and D2 (22 ESP32 variants) on top of it, see "Cut D". Cut E is +planned. Behaviour change: none. ## Context @@ -87,7 +89,7 @@ weak" below). | A | one `radio_new_identity()` for all RadioLib variants | 87 `target.cpp`, 1 new source, 1 header | implemented, see "Cut A" | | B | one class for the FEM gain handlers of HeltecV4, HeltecV4R8, T096, HeltecTrackerV2 | 4 board classes, 1 new helper | implemented, see "Cut B" | | C | a shared default `radio_init()` for the bodies that need no new description (28 + 3 of 89, all nRF52) | 31 `target.cpp`, 1 source, 1 header | implemented, see "Cut C" | -| D | the radio, wrapper and RTC globals from the board's build flags | about 87 `target.cpp` | planned (description: build flags, decided) | +| D | the radio, wrapper and RTC globals from the board description (D1: 31 nRF52, D2: 22 ESP32 variants) | 53 `target.cpp` and `target.h`, 1 source | D1 and D2 implemented, see "Cut D" | | E | sensors, display and button from the board description | the rest | planned | Cut B in more detail: the four bodies are the same once the class name is replaced, @@ -1033,6 +1035,599 @@ definition. If a reviewer wants a board run, the check on any of the 31: flash t repeater firmware, see it boot past `radio_init()` (no `Radio init failed`), and `get radio` answers with the stored settings. +## Cut D: the radio, wrapper and RTC globals from the board description + +The design below was written and committed before any code of this cut. + +### Inventory of the globals + +Measured on `e0d05fde` (`integration`, cuts A to C, 9b and 10c merged) with +`tools/refactoring/variant_target_globals.py` (in this cut). For every +`target.cpp` it takes the "radio block": the declarations of the SPI object, +`radio`, `radio_driver`, `fallback_clock` and `rtc_clock` and the preprocessor +lines around them, compares the blocks normalized and groups them, with the +environments and platforms of each group from `pio project config`. 89 +`target.cpp`, 606 firmware environments build one of them. + +| variants | envs | block (normalized, `PINS` = `P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY`) | platform | +|---:|---:|---|---| +| 30 | 185 | `radio(new Module(PINS, SPI))`, Volatile fallback, AutoDiscover | nRF52 | +| 20 | 175 | `#if P_LORA_SCLK`: `static SPIClass spi;` and `Module(PINS, spi)`, else `Module(PINS)`; ESP32 fallback, AutoDiscover | ESP32 | +| 8 | 61 | as the 20, without the `#if` (`P_LORA_SCLK` is defined in all their environments) | ESP32 | +| 4 | 34 | as the 20, with `spi(FSPI)` | ESP32 | +| 4 | 20 | `Module(PINS, SPI)`, `VolatileRTCClock rtc_clock` without fallback (LR11x0, LR2021) | nRF52 | +| 3 | 23 | `#if P_LORA_SCLK`: `Module(PINS, SPI)`, else `Module(PINS)`; Volatile fallback | nRF52 | +| 3 | 20 | as the 20, with the SX1276 pins `P_LORA_DIO_0, ..., P_LORA_DIO_1` | ESP32 | +| 3 | 20 | `Module(PINS, SPI1)`, Volatile fallback | RP2040 | +| 4 | 16 | `STM32WLx_Module`, RF switch tables in between, `VolatileRTCClock rtc_clock` | STM32 | +| 2 | 5 | `ESP32RTCClock rtc_clock` only (ESP-NOW, no LoRa radio) | ESP32 | +| 8 | 47 | one each: `spi(HSPI)`, `spi(0)`, SX1276 pins without `#if`, `Module(PINS)` on ESP32 with `P_LORA_SCLK` (`heltec_ct62`), `Module(PINS, SPI)` on ESP32 (`thinknode_m9`), `Module(PINS)` on RP2040, and two nRF52 blocks with sensors or a display declared in between (`mesh_pocket`, `muziworks_r1_neo`) | mixed | + +So the block is not one text but a few rules, and almost all of it follows from +macros the variants already have: + +- **Pins**: SX1276 (`USE_SX1276`, defined by `CustomSX1276Wrapper.h`) takes + `P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1` after `P_LORA_NSS`, every other chip + `P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY`. +- **Fallback clock**: `ESP32RTCClock` on ESP32, `VolatileRTCClock` elsewhere, and + `AutoDiscoverRTCClock rtc_clock(fallback_clock)` on top. +- **SPI**: nRF52 passes `SPI`; ESP32 has its own `static SPIClass spi` exactly when + `P_LORA_SCLK` is defined and passes nothing otherwise. The three nRF52 blocks with + `#if P_LORA_SCLK` are the `SPI` rule: `P_LORA_SCLK` is defined in all 23 of their + environments (20 by build flag, `heltec_t1` in its `variant.h`). +- **Not derivable**: the SPI host of the ESP32 bus (`FSPI` in 4, `0` in + `lilygo_tlora_c6`; `HSPI` in `lilygo_teth_elite` is the `SPIClass` default). + +"`Module(PINS)`" and "`Module(PINS, SPI)`" are not the same thing, even where +RadioLib's default bus is `SPI`: the first makes RadioLib call `SPI.begin()` itself +(`ArduinoHal()` sets `initInterface`), the second leaves it to the caller +(`ArduinoHal(spi, settings)`). The rules keep exactly the constructor each variant +calls. + +### Which variants can take their globals from shared code + +A variant can drop its block only if nothing else in its `target.cpp` names +`radio`, `spi` or `fallback_clock`, since those then live in another translation +unit (the script checks this, after removing a `radio_init()` body that a shared +default can take over): + +- **31 nRF52 variants, 195 environments**: exactly the 31 of cut C, whose + `radio_init()` is already the shared one. Their blocks are the "30" and "3" + groups above minus `muzi_base`, `thinknode_m3`, `thinknode_m4` (own + `radio_init()`), plus `muziworks_r1_neo`. +- **22 ESP32 variants, 195 environments**: the 18 and 5 `radio_init()` groups that + cut C left for this cut, minus `lilygo_teth_elite` (its `target.cpp` has four + more functions on `radio`). Their two `radio_init()` bodies are one function: + the 5 call `std_init(&spi)` without the `#if`, and `P_LORA_SCLK` is defined in + all their environments, so with the `#if` they take the same branch. +- **34 stay as they are**: their own code names the globals (LR11x0 and STM32WL + setup, RP2040 on `SPI1`, the ESP32 bodies with `spi.begin()`, `pinMode()` or + extra calls, `mesh_pocket` and the nRF52 LR variants, `heltec_ct62`, + `thinknode_m9`). Sharing their globals would mean adding `extern` declarations + of `radio` to their `target.cpp`, which is not "deletions only"; that is left to + a later cut, or to a board that is touched anyway. + +### Why the globals cannot be weak + +Cuts A and C shared functions with weak definitions, so a variant that keeps its +own still links. Objects with a constructor cannot be shared that way. A weak +object is still constructed by the initializer of its translation unit, and that +initializer writes to the symbol the linker resolved, which is the variant's +object. Measured: a host program with a weak `Obj radio_driver(1)` in one file and +a strong `Obj radio_driver(2)` in another runs the constructor twice, at the same +address (`Obj ctor #1 (1) at 0x100db000c`, `Obj ctor #2 (2) at 0x100db000c`). With +`arm-none-eabi-g++` the weak file's initializer is guarded only by a guard variable +of its own (`_ZGV12radio_driver`), which the strong file never sets, so the same +happens on the firmware toolchain. For `radio` that would mean a second +`new Module`, for `spi` a second mutex, in every variant that keeps its block. + +So the variant has to say that it takes the shared globals. That is the one new +description macro every variant of this cut gets. + +### What changes + +- `RADIOLIB_TARGET_GLOBALS` (new), defined in the variant's `target.h`: the + variant takes `radio`, `radio_driver`, `fallback_clock`, `rtc_clock` and, on + ESP32 with `P_LORA_SCLK`, `spi` from `RadioLibTarget.cpp`. In `target.h` because + both translation units read it (the variant's and the shared one). +- `P_LORA_SPI_HOST` (new, optional): the host of the ESP32 radio's own SPI bus, + for the 5 variants that do not use the `SPIClass` default. +- `RadioLibTarget.cpp` defines, under `WRAPPER_CLASS` and `RADIOLIB_TARGET_GLOBALS`, + in the order the variants have them: + ```cpp + #if defined(ESP32) && defined(P_LORA_SCLK) + static SPIClass spi; // or spi(P_LORA_SPI_HOST) + RADIO_CLASS radio = new Module(PINS, spi); + #elif defined(NRF52_PLATFORM) + RADIO_CLASS radio = new Module(PINS, SPI); + #else + RADIO_CLASS radio = new Module(PINS); + #endif + WRAPPER_CLASS radio_driver(radio, board); + FALLBACK_CLOCK fallback_clock; // ESP32RTCClock or VolatileRTCClock + AutoDiscoverRTCClock rtc_clock(fallback_clock); + ``` + `radio` and `spi` keep internal linkage (`static`), as `spi` had: no new name + becomes visible to the rest of the firmware. `fallback_clock` keeps the external + linkage it has today, because `UnitC6LBoard.cpp` and `XiaoC6Board.cpp` define one + of their own and are not touched (they have no `target.h` with the macro). +- For ESP32, a weak default `radio_init()` next to cut C's, under `ESP32` and + `RADIOLIB_TARGET_GLOBALS`: `fallback_clock.begin(); rtc_clock.begin(Wire);` then + `std_init(&spi)` with `P_LORA_SCLK`, else `std_init()`. It uses the shared `radio` + directly, no accessor. +- In each variant: `target.cpp` loses its block (and on ESP32 its `radio_init()`), + deletions only; `target.h` gains the macro line (and `P_LORA_SPI_HOST` where + needed), additions only. + +Initialization order: the five objects are now constructed by the shared file's +initializer instead of the variant's, so their order relative to the variant's +other globals (`board`, `sensors`, `display`, `user_btn`) is the link order instead +of the source order. Among the five the order stays the same. None of the +constructors involved reads another global: `RadioLibWrapper` and +`AutoDiscoverRTCClock` store references, `new Module` allocates, `SPIClass` +allocates a mutex, `VolatileRTCClock` reads `millis()`, which is 0 before the +scheduler starts on nRF52 (`tick2ms(xTaskGetTickCount())`), and the variant's +objects that use the globals take their address (`MicroNMEALocationProvider(Serial1, +&rtc_clock)`). What can change is the order of heap allocations at start-up, so +heap addresses, not anything a user, an app or the mesh sees. The pull requests +show this by reading the constructors of every global the 53 `target.cpp` keep, +and by comparing images (see "Verification plan"). + +The constructors of the moved globals, read in the sources the builds use +(RadioLib at `6d893483`, the libraries PlatformIO installed for the environments; +arduino-esp32 3.20017 for ESP32, 3.1.3 and 3.3.9 for the C6 builds): none of them +reads another global object. They store their arguments, allocate, or read a clock. + +| global | constructor chain | what it does | source | +|---|---|---|---| +| `radio` (`new Module(...)`, 4 pins) | `Module(cs, irq, rst, gpio)` | stores the pins, `new ArduinoHal()`, which stores the address of RadioLib's default bus (`spi(&RADIOLIB_DEFAULT_SPI)`) and constants | RadioLib `src/Module.cpp:10`, `src/hal/Arduino/ArduinoHal.cpp:5`, `src/Hal.cpp:5` | +| `radio` (`new Module(..., SPI)` or `spi`) | `Module(cs, irq, rst, gpio, SPIClass&, SPISettings)` | stores the pins, `new ArduinoHal(spi, settings)`, which stores the bus's address and the settings | `src/Module.cpp:14`, `src/hal/Arduino/ArduinoHal.cpp:7` | +| `radio` (SX1262, SX1268) | `CustomSX126x(Module*)`, `SX1262`/`SX1268(Module*)`, `SX126x(Module*)`, `PhysicalLayer()` | sets members (chip type, step size, `mod`) | `src/helpers/radiolib/CustomSX126x.h:16`, RadioLib `src/modules/SX126x/SX1262.cpp:44`, `SX1268.cpp:44`, `SX126x.cpp:6`, `src/protocols/PhysicalLayer/PhysicalLayer.cpp:5` | +| `radio` (SX1276) | `CustomSX1276(Module*)`, `SX1276`, `SX1278`, `SX127x(Module*)`, `PhysicalLayer()` | sets members | `src/helpers/radiolib/CustomSX1276.h:13`, RadioLib `src/modules/SX127x/SX1276.cpp:4`, `SX1278.cpp:5`, `SX127x.cpp:5` | +| `radio_driver` | `CustomSX1262Wrapper`, `CustomSX1268Wrapper`, `CustomSX1276Wrapper(radio, board)`, `RadioLibWrapper(PhysicalLayer&, MainBoard&)` | stores the addresses of `radio` and `board`, zeroes counters | `src/helpers/radiolib/CustomSX1262Wrapper.h:13`, `CustomSX1268Wrapper.h:13`, `CustomSX1276Wrapper.h:12`, `RadioLibWrappers.h:34` | +| `fallback_clock` (nRF52) | `VolatileRTCClock()` | sets a fixed base time and reads `millis()`, which is `tick2ms(xTaskGetTickCount())` and 0 before the scheduler starts, in either order | `src/helpers/ArduinoHelpers.h:11`, Adafruit nRF52 core `cores/nRF5/delay.c:28` | +| `fallback_clock` (ESP32) | `ESP32RTCClock()` | nothing | `src/helpers/ESP32Board.h:210` | +| `rtc_clock` | `AutoDiscoverRTCClock(RTCClock&)` | stores the address of `fallback_clock` | `src/helpers/AutoDiscoverRTCClock.h:12` | +| `spi` (ESP32) | `SPIClass(uint8_t spi_bus)` | sets members, creates its parameter mutex (`xSemaphoreCreateMutex()`), which allocates | arduino-esp32 `libraries/SPI/src/SPI.cpp:34` (3.20017), `:38` (3.1.3, 3.3.9) | + +What the order can change is therefore the order of the heap allocations +(`new Module`, `new ArduinoHal`, the mutex) relative to the variant's other +globals, so heap addresses. The builds bound the image differences to that: see +"D1: builds" and "D2: builds" (`nm` and `objdump`, `SOURCE_DATE_EPOCH` fixed, same +worktree). + +### Two pull requests + +- **D1, nRF52**: the globals of the 31 variants of cut C. No new `radio_init()` + (cut C's stays as it is), no `P_LORA_SPI_HOST`. 31 `target.cpp` (deletions), 31 + `target.h` (one line each), the shared file. +- **D2, ESP32**: the globals and the weak `radio_init()` of the 22 variants, + `P_LORA_SPI_HOST` for 5 of them. Stacked on D1. Globals and `radio_init()` go + together because the body names `spi`, which must be in the same translation + unit. + +Each is one concern per platform, with one platform's toolchain and boards to +verify, and each is about the size of cut C. + +### Alternatives considered + +- **Weak globals, like cuts A and C.** Rejected: constructed twice where a variant + keeps its own (measured above). +- **A header the variant includes in place of its block** + (`#include ` in `target.cpp`). Keeps + the translation unit and the initialization order, so the variant's object would + stay the same. Rejected: the shared `radio_init()` of D2 lives in another + translation unit and needs `spi`, which would stay file local in the variant, + and `RadioLibTarget.cpp` cannot see whether a variant included the header, so a + macro in `target.h` would be needed anyway. Two lines per variant instead of one, + and the block is still written out in every variant's source. +- **Give `radio` external linkage and declare it in a shared header**, so that the + 34 variants with own code could take the shared globals as well. Rejected: it + makes `radio` part of the interface every role sees, which cut A deliberately + avoided, and it adds lines to 34 `target.cpp`. +- **Opt-in by build flag in `platformio.ini` instead of `target.h`.** Not chosen: + equally one line, but a variant's environments are spread over several sections + in some `platformio.ini`, and `target.h` is the one file per variant both + translation units read. +- **A constexpr struct per board, or a generator** (options 2 and 3). Rejected by + the decision above. + +### Verification plan + +- Host tests in `native_variant_target`: a first commit pins the variants' block + and ESP32 body (copied verbatim into a test variant) with recording stand-ins: + which `Module` constructor was called with which pins and which bus, that + `radio_driver` wraps `radio` and `board`, that `rtc_clock` falls back to + `fallback_clock`, and for ESP32 the order clock, RTC, `std_init(&spi)` or + `std_init()`. The code commit runs the same cases against the shared definitions, + in a native environment per rule (nRF52; ESP32 with and without `P_LORA_SCLK`, + with `P_LORA_SPI_HOST`; SX1276 pins). Mutation tests on the shared code (wrong + pin order, wrong bus, `SPI` passed where nothing was, wrong clock class, ESP32 + default not weak, guard without the opt-in). +- Builds from the start commit and from the code commit, in the same worktree: one + environment per edited variant, the controls of each platform (variants that + keep their block, with and without own `radio_init()`), the series' matrix of 18, + the two C6 variants without `target.cpp`. Flash and RAM per environment, `nm` for + the symbols that moved (`radio`, `spi` now local symbols of `RadioLibTarget.cpp`, + `radio_init()` weak), and an image comparison of a sample built with + `SOURCE_DATE_EPOCH` set (RadioLib writes `__DATE__`/`__TIME__` into the image + otherwise), to show that what differs is the initializer and the placement. +- All 17 host test environments green on both commits. +- Hardware only with a board from `kb device claim`, otherwise recorded as without + board. + +### Upstream collisions + +Checked on 21.10.2026 against meshcore-dev/MeshCore: the file lists of all 499 +open pull requests (100 files each by GraphQL, the 4 with more through the REST +file list), and for every pull request that touches one of the 53 `target.cpp` or +`target.h`, the changed lines of its diff matched against the block and +`radio_init()`. + +- **#1962** (nRF52 time across warm resets, updated 2026-10-12) changes + `VolatileRTCClock fallback_clock;` to `NRF52RTCClock` in 19 of the 31 D1 files. + D1 deletes that line there, so whichever lands second has to follow: after D1, + #1962 changes one line of the shared code (the nRF52 fallback class) instead of + 19 files, and the 12 variants it did not touch get the same clock unless the + shared rule keeps them apart (which would then be a new description macro, + decided in #1962's rebase, not here). +- **#3213** (ESP32-C3 SPI host, updated 2026-08-14) changes `static SPIClass spi;` + to `spi(FSPI)` in `tenstar_c3`. After D2 that is `P_LORA_SPI_HOST=FSPI` in its + `target.h`. +- **#3638** (dual radio profiles, updated 2026-10-20) constructs `heltec_v4`'s + radio with its own HAL. After D2, `heltec_v4` would have to go back to its own + block (drop the macro), which still links. +- **#2682** lists `thinknode_m8` and `wio-tracker-l1-1w` with the whole block as + added lines; for cuts B and C its head was identical to `upstream/dev` in both + files (a merge, not a change). Not checked again for this cut. +- Every other open pull request on these files changes other lines (GPS, sensors, + display; #1799, #1913, #1924, #1937, #1972, #2058, #2185, #2679, #2794, #2837, + #2882, #2927, #3051, #3141, #3222, #3289, #3307, #3331, #3346, #3374, #3527, + #3613, #3651). Those that change `target.cpp` lines next to the block conflict by + context at most; those on `target.h` add lines elsewhere in the file. +- New board pull requests carry their own block and keep linking: the shared + globals exist only where a `target.h` asks for them. + +### D1: host tests + +`native_variant_target_globals` (new) builds `RadioLibTarget.cpp` against the +target.h of an nRF52 variant (`test/mocks/radiolib_variant_globals`) with the real +`AutoDiscoverRTCClock` (its out-of-line members, which need the RTC chip libraries, +stood in by the test) and a `Module` stand-in that keeps its pins and tells its two +constructors apart. The variant stand-ins move into +`test/mocks/radiolib_variant/variant_stubs.h`. + +The first commit (`6510e4da`) has the block of the 31 variants twice, copied +verbatim: once at file scope, where a variant's `target.cpp` has it, and once in a +namespace as the reference. Six cases run on both: + +- the radio is built from a `Module`, +- with `P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY` in that order, +- with `SPI` passed (the constructor that leaves starting the bus to `std_init()`), +- `radio_driver` wraps the board, +- `rtc_clock` reads and sets the time through `fallback_clock`, +- `rtc_clock.tick()` advances `fallback_clock` by `millis()`, which is what + `VolatileRTCClock` does. + +and one more: cut C's shared `radio_init()` starts the RTC, then the radio that +`radio_driver` wraps, on `SPI`, once. + +The code commit deletes the file-scope block from the test, as from the variants, +and defines the macro in the stand-in `target.h`; the cases are unchanged and now +run against the shared globals. All 18 host environments pass on both commits: 629 +test cases each (616 on `e0d05fde`). + +Mutations of the shared globals, each of which must fail: + +| mutation | result | +|---|---| +| M1: `P_LORA_BUSY` and `P_LORA_DIO_1` swapped | 1 test fails | +| M2: no `SPI` argument (RadioLib starts the bus) | 1 test fails | +| M3: `rtc_clock` falls back to another clock | 2 tests fail | +| M4: defined without the opt-in | `native_variant_target` does not compile (pins and `board` undeclared, `rtc_clock` redefined) | +| M5: opt-in misspelt | `native_variant_target_globals` does not link (globals undefined) | +| M6: `radio_driver` built on another board | 1 test fails | + +### D1: what the code commit changes + +`a8dc76a6`: the globals in `RadioLibTarget.cpp` (with an `#error` for a platform +or chip whose description is not written yet), and in `variants/`: 31 `target.cpp`, +deletions only (215 lines, the block with the blank line after it, and the +`#if defined(P_LORA_SCLK)` around the radio in `heltec_t096`, `heltec_t1` and +`heltec_t114`); 31 `target.h`, one line each, additions only. No file uses CRLF. +`tools/refactoring/variant_target_globals.py` afterwards lists no nRF52 radio block +that could still be shared. + +### D1: builds + +The 53 environments of cut C were built from `6510e4da` (the test commit, firmware +sources as on `e0d05fde`) and from the code commit `a8dc76a6`, both in the same +worktree, with `SOURCE_DATE_EPOCH=1760000000` so that `__DATE__` and `__TIME__` are +the same on both sides. + +- 52 build on both. `ThinkNode_M8_repeater` fails on both, as since cut A. +- **Every environment outside the 31 variants has the same image.** The nRF52, + RP2040 and STM32 controls (`Mesh_pocket_repeater`, `muzi_base_uno_repeater`, + `MeshTracker_X1_repeater`, `t1000e_repeater`, `PicoW_repeater`, + `waveshare_rp2040_lora_repeater_bridge_rs232`, the two `wio-e5-mini`) are byte + for byte identical. The 8 ESP32 ones (the five `Heltec_v3`, `RAK_3112`, the two + C6) differ only in the 65 bytes of the image that hash the ELF file + (`esp_app_desc_t.app_elf_sha256` and the checksum and SHA-256 appended to the + image), which change with any byte of the ELF, debug information included + (`RadioLibTarget.cpp` has new lines); checked by comparing the images byte by byte + outside those fields. +- In the 36 environments of the 31 variants, RAM changes by -8 to +8 bytes and + flash grows by 4 to 84 bytes. Measured with `nm` (all 36, symbols compared as + name, size and binding): + - `radio` becomes a local symbol (`b` instead of `B`), same size; + `radio_driver`, `fallback_clock` and `rtc_clock` keep name, size and binding. + - The variant's static initializer (`_GLOBAL__sub_I_board`; in `xiao_nrf52`, + whose first global is the display, `_GLOBAL__sub_I_display`) loses 0xb8 to + 0xe4 bytes and `RadioLibTarget.cpp` gets one of 0xd8 or 0xdc bytes + (`_GLOBAL__sub_I_radio_driver`): the construction moved, as designed. + - `MicroNMEALocationProvider::loop()` (30 environments, an inline function + compiled in `target.cpp`), and `NanoG2UltraSensorManager::loop()`, + `ThinkNodeM1SensorManager::loop()` and `SolarSensorManager::loop()` (one each) + grow by 28 bytes: the compiler now devirtualizes the call to the clock's + `setCurrentTime()` speculatively, it compares the function pointer with + `VolatileRTCClock::setCurrentTime` and runs that function inlined, otherwise + makes the indirect call as before (`objdump`: the address of + `VolatileRTCClock::setCurrentTime` is in the functions' literal pool after the + change, not before). Same function called with the same arguments either way. + - No other symbol changes. The RAM differences of 8 bytes are alignment: every + data and bss symbol keeps its size, `radio` now sits in another object file's + `.bss`. +- No hardware evidence (without board), for the reasons given in cut C; the pool + boards of these variants are kept for other purposes. A board run would check + that the radio starts (`Radio init failed` absent) and `get radio` answers. + +
+All 53 environments + +| Environment | Flash before | Flash after | Flash delta | RAM before | RAM after | RAM delta | image | +|---|---:|---:|---:|---:|---:|---:|---| +| `GAT562_30S_Mesh_Kit_repeater` | 411,568 | 411,604 | +36 | 35,932 | 35,932 | +0 | differs (hex) | +| `GAT562_Mesh_EVB_Pro_repeater` | 365,764 | 365,816 | +52 | 35,124 | 35,124 | +0 | differs (hex) | +| `GAT562_Mesh_Tracker_Pro_repeater` | 381,276 | 381,328 | +52 | 35,492 | 35,492 | +0 | differs (hex) | +| `GAT562_Mesh_Watch13_companion_radio_ble` | 400,552 | 400,572 | +20 | 147,888 | 147,888 | +0 | differs (hex) | +| `Heltec_mesh_solar_repeater` | 365,600 | 365,668 | +68 | 34,284 | 34,292 | +8 | differs (hex) | +| `Heltec_t096_repeater` | 414,464 | 414,532 | +68 | 35,564 | 35,572 | +8 | differs (hex) | +| `Heltec_t114_without_display_repeater` | 366,260 | 366,312 | +52 | 35,140 | 35,140 | +0 | differs (hex) | +| `Heltec_t1_repeater` | 413,508 | 413,560 | +52 | 35,204 | 35,204 | +0 | differs (hex) | +| `Heltec_tower_v2_repeater` | 309,528 | 309,596 | +68 | 33,292 | 33,292 | +0 | differs (hex) | +| `Heltec_v3_companion_radio_ble` | 1,671,657 | 1,671,657 | +0 | 194,844 | 194,844 | +0 | differs (bin) | +| `Heltec_v3_companion_radio_wifi` | 1,107,825 | 1,107,825 | +0 | 172,384 | 172,384 | +0 | differs (bin) | +| `Heltec_v3_repeater` | 1,175,025 | 1,175,025 | +0 | 62,512 | 62,512 | +0 | differs (bin) | +| `Heltec_v3_room_server` | 1,170,173 | 1,170,173 | +0 | 66,200 | 66,200 | +0 | differs (bin) | +| `Heltec_v3_sensor` | 1,181,561 | 1,181,561 | +0 | 60,600 | 60,600 | +0 | differs (bin) | +| `KeepteenLT1_repeater` | 322,028 | 322,096 | +68 | 33,436 | 33,436 | +0 | differs (hex) | +| `LilyGo_T-Echo-Lite_repeater` | 335,772 | 335,792 | +20 | 37,716 | 37,716 | +0 | differs (hex) | +| `LilyGo_T-Echo_Card_repeater` | 322,368 | 322,404 | +36 | 34,004 | 34,012 | +8 | differs (hex) | +| `LilyGo_T-Echo_repeater` | 350,096 | 350,100 | +4 | 38,484 | 38,492 | +8 | differs (hex) | +| `LilyGo_T_Impulse_Plus_repeater` | 366,508 | 366,560 | +52 | 35,236 | 35,236 | +0 | differs (hex) | +| `M5Stack_Unit_C6L_repeater` | 552,821 | 552,821 | +0 | 29,752 | 29,752 | +0 | differs (bin) | +| `MeshTracker_X1_repeater` | 301,152 | 301,152 | +0 | 32,956 | 32,956 | +0 | identical | +| `Mesh_pocket_repeater` | 326,840 | 326,840 | +0 | 36,820 | 36,820 | +0 | identical | +| `Meshtiny_companion_radio_usb` | 331,112 | 331,132 | +20 | 141,364 | 141,372 | +8 | differs (hex) | +| `Nano_G2_Ultra_repeater` | 319,500 | 319,568 | +68 | 33,332 | 33,332 | +0 | differs (hex) | +| `PicoW_repeater` | 492,668 | 492,668 | +0 | 85,368 | 85,368 | +0 | identical | +| `ProMicro_companion_radio_usb` | 359,796 | 359,816 | +20 | 99,468 | 99,468 | +0 | differs (hex) | +| `ProMicro_repeater` | 346,240 | 346,276 | +36 | 33,892 | 33,900 | +8 | differs (hex) | +| `ProMicro_room_server` | 339,288 | 339,340 | +52 | 37,588 | 37,596 | +8 | differs (hex) | +| `ProMicro_sensor` | 342,956 | 343,008 | +52 | 31,988 | 31,996 | +8 | differs (hex) | +| `R1Neo_repeater` | 368,916 | 368,984 | +68 | 34,892 | 34,892 | +0 | differs (hex) | +| `RAK_3112_repeater_bridge_espnow` | 1,176,333 | 1,176,333 | +0 | 64,072 | 64,072 | +0 | differs (bin) | +| `RAK_3401_repeater` | 411,040 | 411,092 | +52 | 35,636 | 35,636 | +0 | differs (hex) | +| `RAK_4631_companion_radio_ble` | 465,172 | 465,224 | +52 | 149,768 | 149,768 | +0 | differs (hex) | +| `RAK_4631_repeater` | 441,784 | 441,820 | +36 | 37,240 | 37,240 | +0 | differs (hex) | +| `RAK_4631_room_server` | 435,096 | 435,116 | +20 | 40,928 | 40,928 | +0 | differs (hex) | +| `RAK_4631_sensor` | 438,776 | 438,812 | +36 | 35,328 | 35,328 | +0 | differs (hex) | +| `RAK_WisMesh_Tag_repeater` | 369,076 | 369,128 | +52 | 34,916 | 34,908 | -8 | differs (hex) | +| `SenseCap_Solar_repeater` | 366,108 | 366,160 | +52 | 34,876 | 34,876 | +0 | differs (hex) | +| `ThinkNode_M1_repeater` | 306,180 | 306,264 | +84 | 32,980 | 32,972 | -8 | differs (hex) | +| `ThinkNode_M6_repeater` | 366,212 | 366,280 | +68 | 34,932 | 34,932 | +0 | differs (hex) | +| `ThinkNode_M8_repeater` | FAIL | FAIL | | FAIL | FAIL | | | +| `WioTrackerL1-1W_repeater` | 378,716 | 378,768 | +52 | 35,436 | 35,436 | +0 | differs (hex) | +| `WioTrackerL1_repeater` | 377,724 | 377,760 | +36 | 35,428 | 35,428 | +0 | differs (hex) | +| `Xiao_C6_repeater_` | 542,479 | 542,479 | +0 | 29,856 | 29,856 | +0 | differs (bin) | +| `Xiao_nrf52_repeater` | 361,800 | 361,836 | +36 | 34,596 | 34,604 | +8 | differs (hex) | +| `ikoka_handheld_nrf_e22_30dbm_repeater` | 358,296 | 358,316 | +20 | 34,468 | 34,476 | +8 | differs (hex) | +| `ikoka_nano_nrf_22dbm_repeater` | 361,176 | 361,212 | +36 | 34,556 | 34,564 | +8 | differs (hex) | +| `ikoka_stick_nrf_22dbm_repeater` | 373,768 | 373,804 | +36 | 34,708 | 34,716 | +8 | differs (hex) | +| `muzi_base_uno_repeater` | 301,236 | 301,236 | +0 | 32,932 | 32,932 | +0 | identical | +| `t1000e_repeater` | 294,712 | 294,712 | +0 | 32,876 | 32,876 | +0 | identical | +| `waveshare_rp2040_lora_repeater_bridge_rs232` | 241,080 | 241,080 | +0 | 26,704 | 26,704 | +0 | identical | +| `wio-e5-mini_repeater` | 204,136 | 204,136 | +0 | 17,172 | 17,172 | +0 | identical | +| `wio-e5-mini_sensor` | 203,664 | 203,664 | +0 | 15,276 | 15,276 | +0 | identical | + +
+ +### D2: host tests + +`native_variant_target_esp32` and three siblings (new) build `RadioLibTarget.cpp` +against the target.h of an ESP32 variant (`test/mocks/radiolib_variant_esp32`, +with a stand-in `helpers/ESP32Board.h` whose `ESP32RTCClock` records `begin()`), +one environment per board description that occurs among the 22: SX1262 on an own +bus on the default host; the same without `P_LORA_SCLK`; SX1276; own bus on +`P_LORA_SPI_HOST=FSPI`. The SPI stand-in gets bus numbers, the radio stand-in tells +"the module's own bus" apart from `SPI`. + +The first commit (`02978dd3`) has, per environment, the variants' block and +`radio_init()` verbatim at file scope (heltec_v3 and the others with the plain +block, heltec_v2 for the SX1276, heltec_e213 for the own host) and once more in a +namespace as reference; where `P_LORA_SCLK` is set also the blocks written without +the `#if` (lilygo_t3s3, meshadventurer, the nibble boards, lilygo_tlora_v2_1), +the bus of lilygo_tlora_c6 (`spi(0)`) and the `radio_init()` body without the +`#if`. Seven cases run on each: + +- the radio is built from a `Module`, with the pins in the chip's order + (SX1276: `P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1`), +- on an own bus that is not `SPI`, on the variant's host or the default one, or + with no bus where `P_LORA_SCLK` is not set, +- `radio_driver` wraps the board, `rtc_clock` falls back to `fallback_clock`, +- `radio_init()` starts the fallback clock, then the RTC on `Wire`, then the radio + once on its own bus (or with none), and passes `false` through. + +The code commit deletes the file-scope block and `radio_init()` from the test and +defines the macro in the stand-in `target.h`; the cases are unchanged. +`test_variant_target_esp32_override` (new, in the first ESP32 environment) defines +its own `radio_init()` with the shared globals and checks it wins. All 22 host +environments pass: 706 test cases on the test commit, 707 on the code commit (the +override case). + +Mutations of the shared code, each of which must fail: + +| mutation | result | +|---|---| +| M1: SX1276 pins in SX126x order | 1 test fails | +| M2: `P_LORA_SPI_HOST` ignored | 1 test fails | +| M3: own bus created but not passed to the `Module` | 6 tests fail | +| M4: RTC started before the fallback clock | 4 tests fail | +| M5: fallback clock not started | 8 tests fail | +| M6: `std_init()` without the bus where there is one | 3 tests fail | +| M7: `std_init()` result dropped | 3 tests fail | +| M8: `radio_init()` not weak | the override suite does not link (`duplicate symbol 'radio_init()'`) | +| M9: `rtc_clock` falls back to another clock | 4 tests fail | +| M10: `SPI` passed where `P_LORA_SCLK` is not set | 1 test fails | + +### D2: what the code commit changes + +`67619b76`: `RadioLibTarget.cpp` describes the globals for ESP32 too (pins by chip, +own `SPIClass` with `P_LORA_SCLK`, on `P_LORA_SPI_HOST` if set, `ESP32RTCClock` +from `helpers/ESP32Board.h`) and gets the weak `radio_init()` for ESP32 with an +SX1262, SX1268 or SX1276; the D1 `#error` for SX1276 goes, since the pin order is +now described. In `variants/`: 22 `target.cpp`, deletions only (455 lines: block, +`radio_init()`, blank lines); 22 `target.h` with the opt-in line and 5 of them with +`#define P_LORA_SPI_HOST FSPI` (`heltec_e213`, `heltec_e290`, `heltec_rc32`, +`heltec_t190`) or `0` (`lilygo_tlora_c6`), additions only. `nibble_screen_connect` +uses CRLF, kept. + +`ESP32Board.h` defines `static RTC_NOINIT_ATTR uint32_t _rtc_backup_time` and +`_rtc_backup_magic` in the header, used by the inline members of `ESP32RTCClock`, +so every translation unit that uses those members gets its own copy. Moving +`fallback_clock` and its `begin()` to `RadioLibTarget.cpp` must not leave two +copies, or one that `begin()` reads and `setCurrentTime()` writes another. Checked +with `objdump -t` in all 29 edited environments: exactly one copy of each before and +after, before in `target.cpp`, after in `RadioLibTarget.cpp`, at the same address +in `.rtc_noinit` (so a time saved by the old image is read by the new one). + +Initialization order, as designed: in the 53 `target.cpp` of D1 and D2, the only +remaining globals that name a moved object are the 35 GPS providers +(`MicroNMEALocationProvider(Serial1, &rtc_clock, ...)`), which store the pointer; +the moved constructors store references (`board`, `fallback_clock`) and do not read +any other global. + +### D2: builds + +50 environments, built from `02978dd3` (the test commit, firmware sources as on +D1's code commit) and from `67619b76`, in the same worktree, with +`SOURCE_DATE_EPOCH=1760000000`: one per edited variant (22, a repeater each), the +SX1268 builds of `generic-e22` and `meshadventurer`, the other roles of +`heltec_v3` and `RAK_3112`, ESP32 variants that keep their block (`heltec_ct62`, +`thinknode_m9`, `station_g2`, `lilygo_teth_elite`, `xiao_c3`, `thinknode_m7`, +`lilygo_tbeam_supreme_SX1262`), the two C6, and the nRF52, RP2040 and STM32 +environments of the series' matrix. + +- All 50 build on both commits. +- **Every environment outside the 22 variants has the same image**: nRF52, RP2040 + and STM32 byte for byte, ESP32 and C6 outside the 65 bytes that hash the ELF (as + for D1). +- In the 29 environments of the 22 variants, flash changes by -100 to +76 bytes + (21 smaller, 3 equal, 5 larger), RAM by -16 to +8. +- To tell what in those images differs, 9 of the environments (SX1262, SX1276, + own host, C3 and C6 on RISC-V) were built a second time from `02978dd3` in + another worktree; those images equal the first build's outside the ELF hash, and + their object files were compared with the code commit's, as disassembly with + relocations and without comments: **in all 9, only `RadioLibTarget.cpp.o` and the + variant's `target.cpp.o` differ**; the other 249 to 291 object files are the same. + So any other difference in the images comes from linking. +- `nm` on all 29 (symbols as name, size and binding): `radio` becomes local, + `radio_init()` becomes weak (`W`) and comes from `RadioLibTarget.cpp`, the + construction moves from the variant's initializer to `_GLOBAL__sub_I_radio_driver`, + and the destructor registration with it (`_GLOBAL__sub_D_radio_driver`; + `SPIClass` has a destructor; in 27 of the 29, not in the C3 and C6 builds). + Besides those, up to 8 functions per environment change size; for each, the link + map says which object file its code comes from: + - from an unchanged object file (`Dispatcher.cpp`, `Mesh.cpp`, `Packet.cpp`, + `main.cpp`'s `loop()`, `AutoDiscoverRTCClock.cpp`, `ESP32Board.cpp`, + `SSD1306Display.cpp`, `RadioLibWrappers.cpp`, even the prebuilt `libesp_wifi.a`): + the code is the same before linking, the size changes with the linker's + relaxation on Xtensa and RISC-V, which picks shorter or longer instruction + forms depending on the final addresses (2 or 4 bytes on RISC-V); + - inline functions whose kept copy moved from `target.cpp.o` to + `RadioLibTarget.cpp.o` with the construction of the radio and the wrapper + (`sx126xResetAGC()`, `CustomSX126x::isReceiving()`, `CustomSX1276::std_init()`, + `ESP32RTCClock::begin()`, `CustomSX1262Wrapper::doResetAGC()` and + `isReceivingPacket()`), and `MicroNMEALocationProvider::waitFor()` and + `formatAge()`, which stay in the changed `target.cpp.o`: compared function by + function in the object files, the same instructions with the same relocation + targets; the differences are Xtensa's narrow and wide encodings of the same + instruction (`mov.n a11, a3` for `or a11, a3, a3`), alignment fill, and + offsets; + - `radio_init()` itself: the shared one equals each variant's in all 9, apart + from the relocation to `radio`, which is now a local symbol (on the C3 also the + numbering of its float constants, whose contents are the same). +- No hardware evidence (without board). A board run would check the same as for + D1, plus on an ESP32 that the time survives a reset (the RTC backup above). + +
+All 50 environments + +| Environment | Flash before | Flash after | Flash delta | RAM before | RAM after | RAM delta | image | +|---|---:|---:|---:|---:|---:|---:|---| +| `Generic_E22_sx1262_repeater` | 1,143,573 | 1,143,573 | +0 | 60,620 | 60,620 | +0 | differs (bin) | +| `Heltec_E213_repeater` | 1,162,233 | 1,162,241 | +8 | 71,932 | 71,940 | +8 | differs (bin) | +| `Heltec_E290_repeater` | 1,160,185 | 1,160,261 | +76 | 72,116 | 72,124 | +8 | differs (bin) | +| `heltec_rc32_without_display_repeater` | 1,162,169 | 1,162,121 | -48 | 62,176 | 62,176 | +0 | differs (bin) | +| `Heltec_T190_repeater_` | 1,139,397 | 1,139,373 | -24 | 71,872 | 71,872 | +0 | differs (bin) | +| `Heltec_Wireless_Tracker_repeater` | 1,157,621 | 1,157,521 | -100 | 61,088 | 61,088 | +0 | differs (bin) | +| `heltec_tracker_v2_repeater` | 1,226,257 | 1,226,209 | -48 | 74,344 | 74,352 | +8 | differs (bin) | +| `Heltec_v2_repeater` | 1,151,913 | 1,151,901 | -12 | 60,604 | 60,604 | +0 | differs (bin) | +| `Heltec_v3_repeater` | 1,175,025 | 1,174,961 | -64 | 62,512 | 62,512 | +0 | differs (bin) | +| `heltec_v4_repeater` | 1,173,137 | 1,173,089 | -48 | 62,476 | 62,484 | +8 | differs (bin) | +| `heltec_v4_r8_repeater` | 1,176,629 | 1,176,589 | -40 | 62,400 | 62,400 | +0 | differs (bin) | +| `Heltec_Wireless_Paper_repeater` | 1,121,873 | 1,121,873 | +0 | 60,376 | 60,376 | +0 | differs (bin) | +| `LilyGo_T3S3_sx1262_repeater` | 1,108,533 | 1,108,537 | +4 | 60,500 | 60,500 | +0 | differs (bin) | +| `Tbeam_SX1262_repeater` | 1,205,213 | 1,205,157 | -56 | 61,212 | 61,212 | +0 | differs (bin) | +| `Tbeam_SX1276_repeater` | 1,201,181 | 1,201,113 | -68 | 61,092 | 61,092 | +0 | differs (bin) | +| `LilyGo_Tlora_C6_repeater_` | 542,447 | 542,449 | +2 | 29,856 | 29,856 | +0 | differs (bin) | +| `LilyGo_TLora_V2_1_1_6_repeater` | 1,663,989 | 1,663,977 | -12 | 62,472 | 62,472 | +0 | differs (bin) | +| `Meshadventurer_sx1262_repeater` | 1,162,097 | 1,162,029 | -68 | 61,084 | 61,084 | +0 | differs (bin) | +| `nibble_screen_connect_repeater_` | 1,103,205 | 1,103,209 | +4 | 60,216 | 60,216 | +0 | differs (bin) | +| `nibble_zero_connect_repeater_` | 1,103,309 | 1,103,301 | -8 | 60,216 | 60,216 | +0 | differs (bin) | +| `RAK_3112_repeater` | 1,165,829 | 1,165,765 | -64 | 62,416 | 62,424 | +8 | differs (bin) | +| `Tenstar_C3_sx1262_repeater` | 1,152,392 | 1,152,378 | -14 | 53,812 | 53,796 | -16 | differs (bin) | +| `Heltec_ct62_repeater` | 1,151,874 | 1,151,874 | +0 | 53,772 | 53,772 | +0 | differs (bin) | +| `ThinkNode_M9_repeater_` | 1,182,977 | 1,182,977 | +0 | 62,144 | 62,144 | +0 | differs (bin) | +| `Station_G2_repeater` | 1,207,885 | 1,207,885 | +0 | 74,712 | 74,712 | +0 | differs (bin) | +| `LilyGo_TETH_Elite_sx1262_repeater` | 1,076,289 | 1,076,289 | +0 | 59,408 | 59,408 | +0 | differs (bin) | +| `Xiao_C3_repeater` | 1,158,046 | 1,158,046 | +0 | 54,076 | 54,076 | +0 | differs (bin) | +| `ThinkNode_M7_repeater` | 1,089,241 | 1,089,241 | +0 | 59,688 | 59,688 | +0 | differs (bin) | +| `T_Beam_S3_Supreme_SX1262_repeater` | 1,155,517 | 1,155,517 | +0 | 61,072 | 61,072 | +0 | differs (bin) | +| `RAK_4631_repeater` | 441,820 | 441,820 | +0 | 37,240 | 37,240 | +0 | identical | +| `ProMicro_repeater` | 346,276 | 346,276 | +0 | 33,900 | 33,900 | +0 | identical | +| `Heltec_v3_room_server` | 1,170,173 | 1,170,101 | -72 | 66,200 | 66,200 | +0 | differs (bin) | +| `Heltec_v3_companion_radio_ble` | 1,671,657 | 1,671,593 | -64 | 194,844 | 194,844 | +0 | differs (bin) | +| `Heltec_v3_companion_radio_wifi` | 1,107,825 | 1,107,797 | -28 | 172,384 | 172,384 | +0 | differs (bin) | +| `Heltec_v3_sensor` | 1,181,561 | 1,181,489 | -72 | 60,600 | 60,600 | +0 | differs (bin) | +| `RAK_4631_room_server` | 435,116 | 435,116 | +0 | 40,928 | 40,928 | +0 | identical | +| `RAK_4631_companion_radio_ble` | 465,224 | 465,224 | +0 | 149,768 | 149,768 | +0 | identical | +| `RAK_4631_sensor` | 438,812 | 438,812 | +0 | 35,328 | 35,328 | +0 | identical | +| `PicoW_repeater` | 492,668 | 492,668 | +0 | 85,368 | 85,368 | +0 | identical | +| `wio-e5-mini_repeater` | 204,136 | 204,136 | +0 | 17,172 | 17,172 | +0 | identical | +| `wio-e5-mini_sensor` | 203,664 | 203,664 | +0 | 15,276 | 15,276 | +0 | identical | +| `RAK_3112_repeater_bridge_espnow` | 1,176,333 | 1,176,269 | -64 | 64,072 | 64,072 | +0 | differs (bin) | +| `waveshare_rp2040_lora_repeater_bridge_rs232` | 241,080 | 241,080 | +0 | 26,704 | 26,704 | +0 | identical | +| `ProMicro_room_server` | 339,340 | 339,340 | +0 | 37,596 | 37,596 | +0 | identical | +| `ProMicro_companion_radio_usb` | 359,816 | 359,816 | +0 | 99,468 | 99,468 | +0 | identical | +| `ProMicro_sensor` | 343,008 | 343,008 | +0 | 31,996 | 31,996 | +0 | identical | +| `Xiao_C6_repeater_` | 542,479 | 542,479 | +0 | 29,856 | 29,856 | +0 | differs (bin) | +| `M5Stack_Unit_C6L_repeater` | 552,821 | 552,821 | +0 | 29,752 | 29,752 | +0 | differs (bin) | +| `Generic_E22_sx1268_repeater` | 1,143,361 | 1,143,361 | +0 | 60,620 | 60,620 | +0 | differs (bin) | +| `Meshadventurer_sx1268_repeater` | 1,161,869 | 1,161,797 | -72 | 61,084 | 61,084 | +0 | differs (bin) | + +
+ ## Upstream Searched meshcore-dev/MeshCore on 20.10.2026: text queries over all pull requests diff --git a/docs/refactoring/0012-esp32-rtc-backup.md b/docs/refactoring/0012-esp32-rtc-backup.md new file mode 100644 index 0000000000..686ab57e38 --- /dev/null +++ b/docs/refactoring/0012-esp32-rtc-backup.md @@ -0,0 +1,269 @@ +# 0012: One RTC backup for ESP32RTCClock + +Status: implemented. Stacked on cut D2 of step 11 +([0011](0011-variant-target.md), section "D2: what the code commit changes"), where +the trap was found. It fixes a definition, not a behaviour: every ESP32 image keeps +its one copy of the backup at the address it had, except two that never restore it +(below). + +## Context + +`ESP32RTCClock` (`src/helpers/ESP32Board.h`) keeps the time across a reset that +loses the system time: `setCurrentTime()` and `tick()` write it to +`_rtc_backup_time` and `_rtc_backup_magic` in RTC memory (`RTC_NOINIT_ATTR`, the +section `.rtc_noinit`, which a reset does not clear), and `begin()` restores it when +the magic matches. + +The header defined both as `static`: + +```cpp +static RTC_NOINIT_ATTR uint32_t _rtc_backup_time; +static RTC_NOINIT_ATTR uint32_t _rtc_backup_magic; +``` + +`static` at namespace scope gives every translation unit that includes the header +its own pair. The members that use them are inline, so each unit that calls them +compiles a copy of `begin()`, `setCurrentTime()` and `tick()` against its own pair. +That is a violation of the one definition rule (an inline function that names an +object with internal linkage, defined in several units), and what an image does with +it depends on the compiler and the linker: + +- A call the compiler inlines reads and writes the pair of the unit it is in. +- A call that is not inlined goes to the one out of line copy the linker keeps of + each inline member, which uses the pair of whichever unit that copy came from. + +Today it does no harm because exactly one unit per image uses the members: the +variant's `target.cpp` before cut D, `src/helpers/radiolib/RadioLibTarget.cpp` after +it for the 22 variants of D2, `XiaoC6Board.cpp` and `UnitC6LBoard.cpp` for the two +C6 board files. The day a second unit calls one of them (a variant that starts the +clock in its board file and sets it in `target.cpp`, a helper that saves the time +before a deep sleep), `begin()` can read a pair that `setCurrentTime()` never wrote, +and the time no longer survives a reset, with no error and no warning. + +## What changes + +- `ESP32Board.h` declares the two variables `extern`, with a comment why. +- `ESP32Board.cpp` defines them once, with `RTC_NOINIT_ATTR`, inside its existing + `#ifdef ESP_PLATFORM`. + +Names, types and the section stay the same, so code that uses the variables keeps +compiling. With one definition the linker enforces the rest: a second definition +does not link (`multiple definition`), a missing one does not either (`undefined +reference`). + +## Alternatives + +- **Define them in a file of their own** (`src/helpers/ESP32RTCBackup.cpp`). Built + first and measured: the ESP32 images are the same as with `ESP32Board.cpp`, but + the new object file, empty on every other platform, is one more input to every + link, and on RP2040 that alone reorders the linker's long branch veneers + (`PicoW_repeater`: 157 bytes differ; built without the file, the image equals the + start commit's byte for byte). `ESP32Board.cpp` is compiled for every platform + already, so the other platforms' images stay byte for byte the same. +- **`inline` variables** (C++17, `inline RTC_NOINIT_ATTR uint32_t ...` in the + header). Not built. Rejected: the definition would still be in every unit that + uses it, with the linker choosing one, and `RTC_NOINIT_ATTR` gives each unit its + own section name (`.rtc_noinit.<__COUNTER__>`); which copy lands where is the kind + of link question this change removes. +- **Move the backup into `ESP32RTCClock`** as static members. Rejected for this + step: it renames the variables for anyone who uses them, and it still needs one + out of line definition, so it would be this change plus a rename. + +## The address in `.rtc_noinit` + +A time saved by the old image is read by the new one only if both variables keep +their address. The address follows from the link: `.rtc_noinit` collects +`*(.rtc_noinit .rtc_noinit.*)` in input order, without `KEEP`. Before, every unit +that included the header carried the pair's sections (the link maps list them for +`main.cpp.o`, `MyMesh.cpp.o`, `UITask.cpp.o` and others), and `--gc-sections` dropped +all but those of the one unit that uses the members; after, they come from +`ESP32Board.cpp.o`. ESP-IDF's own variables there (`s_rtc_last_ticks`, +`s_esp_rtc_time_us`) come from archives linked after the project's objects. Within +the object, the order of the two is the compiler's. + +Measured with `objdump -t` on every ESP32 image of the matrix below: + +- In 55 of the 57 ESP32 images, before and after: exactly one `_rtc_backup_time` and + one `_rtc_backup_magic`, at the same addresses (for example `0x50000000`/`0x50000004` on the + S3, `0x50000200`/`0x50000204` on the ESP32, `0x50000018`/`0x5000001c` on the C3, + `0x50000048`/`0x5000004c` on the C6), and every other symbol in `.rtc_noinit` at + the same address too. The order of the two is not the same in every image (time + first in `LilyGo_TLora_V2_1_1_6` and the three C3 builds, magic first elsewhere), + and each image keeps its own. +- In `ThinkNode_M7_repeater` and `ThinkNode_M9_repeater_`, the address of + `_rtc_backup_time` changes, from `0x50000000` to `0x50000004`, and + `_rtc_backup_magic` appears at `0x50000000`. These two variants never call + `fallback_clock.begin()` (`variants/thinknode_m7/target.cpp`, + `variants/thinknode_m9/target.cpp`), so the image never reads the backup: with a + `static` pair, the compiler saw `_rtc_backup_magic` written and never read in the + unit and dropped it with its stores (disassembly: before, `setCurrentTime()` + stores the time only; after, it stores both). Nothing is restored on these two + boards before or after, so the moved address loses nothing. The ESP-IDF variables + after them keep their addresses (`s_rtc_last_ticks` at `0x50000008`, + `s_esp_rtc_time_us` at `0x50000010`), since the 4 bytes of the magic fill what was + alignment padding. + +## Verification + +### Tests first + +`test/test_esp32_rtc_backup` (`pio test -e native_esp32_rtc_backup`, added to the +unit test workflow): the real `ESP32Board.h` and `ESP32Board.cpp` on the host, +against stand ins for the ESP-IDF headers they include (`test/mocks/esp32_idf/`: +`esp_reset_reason()` returns what a test sets, `settimeofday()` records instead of +setting the host's clock, `RTC_NOINIT_ATTR` is empty) and for the variant's +`target.h`. The members are called from two translation units, the test and +`other_unit.cpp`, in both directions: a time set in one is restored by `begin()` in +the other, also when `tick()` saved it, and the backup the test reads directly is +the one the members wrote. Further tests pin `begin()`: no backup or a wrong magic +seeds `RTC_TIME_MIN`, a time before `RTC_TIME_MIN` is not restored, a wake from deep +sleep keeps the system time. + +On the start commit (`12e37302`, the tests with the firmware sources of +`a0511463`) 5 of the 9 tests fail: the test's unit sees its own zero pair. The 4 +cross unit tests that call members in both units pass there, because at `-O0` +nothing is inlined and the host linker kept the out of line members of +`other_unit.cpp`, so all calls agreed on that unit's pair (as the 5 failures, +all reading the test unit's pair, show): the hazard depends on +inlining, which is why the tests also read the pair directly. On the code commit +(`836678d2`) all 9 pass. + +`e6072261` adds the suite to `test_ignore` of the `native` environment, which would +otherwise pick it up without the stand ins; it changes no firmware source. +`24e3ead4` includes `` in the stand ins: on macOS `` declares +`time()`, with glibc it does not, and the unit test workflow on Linux failed to +compile the suite without it. It changes no firmware source either. + +### Host suites + +All 23 native environments: 716 tests pass (707 on the head of D2 plus the 9 new). + +### Mutation tests + +| mutation | result | +|---|---| +| M1: the start commit's `ESP32Board.h` and `ESP32Board.cpp` (`static` in the header) | 5 tests fail | +| M2: `setCurrentTime()` does not write the magic | 3 tests fail | +| M3: `begin()` ignores the magic | 1 test fails | +| M4: `begin()` restores after a wake from deep sleep | 1 test fails | +| M5: `tick()` saves nothing | 2 tests fail | +| M6: `begin()` without the lower bound `RTC_TIME_MIN` | 1 test fails | +| M7: `begin()` accepts a time equal to `RTC_TIME_MIN` | all pass: equivalent, restoring `RTC_TIME_MIN` and seeding it set the same time | +| M8: `_rtc_backup_magic` not defined | does not link (`Undefined symbols ... _rtc_backup_magic`) | + +### Build matrix + +64 environments, built from `12e37302` and `836678d2` in the same worktree with +`SOURCE_DATE_EPOCH=1760000000`: one per ESP32 variant folder (44; all 44 use +`ESP32RTCClock`), every role of `heltec_v3` (repeater, both bridges, room server, +terminal chat, companion USB, BLE and WiFi, sensor, KISS modem), the SX1268 builds +of `generic-e22` and `meshadventurer`, `RAK_3112_repeater_bridge_espnow`, more C6 +builds (`Xiao_C6_companion_radio_ble_`, `Meshimi_repeater_`, +`M5Stack_Unit_C6L_companion_radio_ble`), and nRF52, RP2040 and STM32 controls +(`RAK_4631_repeater`, `RAK_4631_companion_radio_ble`, `ProMicro_repeater`, +`PicoW_repeater`, `wio-e5-mini_repeater`). + +- 62 build on both commits. `Generic_ESPNOW_terminal_chat` and + `SenseCapIndicator-ESPNow_comp_radio_usb` fail on both, with the same error + (`'P_LORA_DIO_1' was not declared in this scope` in `ESP32Board.h`, a board + without LoRa); not touched here. +- **nRF52, RP2040 and STM32: the same image, byte for byte** (5 of 5). +- **ESP32, C3 and C6: flash and RAM unchanged** in 55 of 57; `ThinkNode_M7` +28 and + `ThinkNode_M9` +24 bytes of flash (the magic stores the compiler now keeps), RAM + unchanged. +- The ESP32, S3 and C6 images (52) differ only in the 64 or 65 bytes that hash the ELF + (at `0xb0` and at the end of the image), so their contents are the same. The three + C3 builds (`Heltec_ct62`, `Tenstar_C3_sx1262`, `Xiao_C3`) differ in 16 or 17 more bytes, + all in `ESP32RTCClock::tick()`: same length, same instructions apart from how the + address of `_rtc_backup_time` is formed (before `lui a5,0x50000; add a5,a5,24; + lw a3,0(a5)`, after `lui a4,0x50000; lw a3,24(a4)`, because a global symbol's + offset can be folded into the load), and the registers that follow from it. +- `.rtc_noinit`: as in the section above. +- The two C6 board files (`variants/xiao_c6/XiaoC6Board.cpp`, + `variants/m5stack_unit_c6l/UnitC6LBoard.cpp`) are the one unit that uses the + members in their images, as `target.cpp` is elsewhere; their five builds above + have one copy at `0x50000048`/`0x5000004c` before and after. They need no change. + +No hardware evidence (without board). A board run would set the time on an ESP32 +with the old image, flash the new one, and read the time after the reset that +follows the flash: the same, not `RTC_TIME_MIN`. + +## Follow-up outside this step + +`ThinkNode_M7` and `ThinkNode_M9` never call `fallback_clock.begin()`, so on these +two boards the time is not restored after a reset, even without the trap above. +Whether that is meant +(both have an RTC chip that `AutoDiscoverRTCClock` may find) is a question for the +boards' maintainers, not a refactoring. + +
+All 64 environments + +| Environment | Flash before | Flash after | Flash delta | RAM before | RAM after | RAM delta | image | backup before | backup after | +|---|---:|---:|---:|---:|---:|---:|---|---|---| +| `Ebyte_EoRa-S3_Repeater` | 1,108,433 | 1,108,433 | +0 | 60,500 | 60,500 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Generic_E22_sx1262_repeater` | 1,143,573 | 1,143,573 | +0 | 60,620 | 60,620 | +0 | differs (65 bytes) | time @ 0x50000204, magic @ 0x50000200 | magic @ 0x50000200, time @ 0x50000204 | +| `Generic_ESPNOW_terminal_chat` | | | | | | | does not build on either commit | | | +| `Heltec_ct62_repeater` | 1,151,874 | 1,151,874 | +0 | 53,772 | 53,772 | +0 | differs (81 bytes) | time @ 0x50000018, magic @ 0x5000001c | magic @ 0x5000001c, time @ 0x50000018 | +| `Heltec_E213_repeater` | 1,162,241 | 1,162,241 | +0 | 71,940 | 71,940 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_E290_repeater` | 1,160,261 | 1,160,261 | +0 | 72,124 | 72,124 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `heltec_rc32_without_display_repeater` | 1,162,121 | 1,162,121 | +0 | 62,176 | 62,176 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_T190_repeater_` | 1,139,373 | 1,139,373 | +0 | 71,872 | 71,872 | +0 | differs (64 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_Wireless_Tracker_repeater` | 1,157,521 | 1,157,521 | +0 | 61,088 | 61,088 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `heltec_tracker_v2_repeater` | 1,226,209 | 1,226,209 | +0 | 74,352 | 74,352 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v2_repeater` | 1,151,901 | 1,151,901 | +0 | 60,604 | 60,604 | +0 | differs (65 bytes) | time @ 0x50000204, magic @ 0x50000200 | magic @ 0x50000200, time @ 0x50000204 | +| `Heltec_v3_repeater` | 1,174,961 | 1,174,961 | +0 | 62,512 | 62,512 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `heltec_v4_repeater` | 1,173,089 | 1,173,089 | +0 | 62,484 | 62,484 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `heltec_v4_r8_repeater` | 1,176,589 | 1,176,589 | +0 | 62,400 | 62,400 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_Wireless_Paper_repeater` | 1,121,873 | 1,121,873 | +0 | 60,376 | 60,376 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `LilyGo_T3S3_sx1262_repeater` | 1,108,537 | 1,108,537 | +0 | 60,500 | 60,500 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `LilyGo_T3S3_sx1276_repeater` | 1,105,521 | 1,105,521 | +0 | 60,484 | 60,484 | +0 | differs (64 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `LilyGo_TBeam_1W_repeater` | 1,154,973 | 1,154,973 | +0 | 72,752 | 72,752 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Tbeam_SX1262_repeater` | 1,205,157 | 1,205,157 | +0 | 61,212 | 61,212 | +0 | differs (64 bytes) | time @ 0x50000204, magic @ 0x50000200 | magic @ 0x50000200, time @ 0x50000204 | +| `Tbeam_SX1276_repeater` | 1,201,113 | 1,201,113 | +0 | 61,092 | 61,092 | +0 | differs (65 bytes) | time @ 0x50000204, magic @ 0x50000200 | magic @ 0x50000200, time @ 0x50000204 | +| `T_Beam_S3_Supreme_SX1262_repeater` | 1,155,517 | 1,155,517 | +0 | 61,072 | 61,072 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `LilyGo_TDeck_repeater` | 1,144,713 | 1,144,713 | +0 | 61,424 | 61,424 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `LilyGo_TETH_Elite_sx1262_repeater` | 1,076,289 | 1,076,289 | +0 | 59,408 | 59,408 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `LilyGo_Tlora_C6_repeater_` | 542,449 | 542,449 | +0 | 29,856 | 29,856 | +0 | differs (64 bytes) | time @ 0x5000004c, magic @ 0x50000048 | magic @ 0x50000048, time @ 0x5000004c | +| `LilyGo_TLora_V2_1_1_6_repeater` | 1,663,977 | 1,663,977 | +0 | 62,472 | 62,472 | +0 | differs (65 bytes) | time @ 0x50000200, magic @ 0x50000204 | magic @ 0x50000204, time @ 0x50000200 | +| `M5Stack_Unit_C6L_repeater` | 552,821 | 552,821 | +0 | 29,752 | 29,752 | +0 | differs (65 bytes) | time @ 0x5000004c, magic @ 0x50000048 | magic @ 0x50000048, time @ 0x5000004c | +| `Meshadventurer_sx1262_repeater` | 1,162,029 | 1,162,029 | +0 | 61,084 | 61,084 | +0 | differs (65 bytes) | time @ 0x50000204, magic @ 0x50000200 | magic @ 0x50000200, time @ 0x50000204 | +| `meshnology_w12_repeater` | 1,183,449 | 1,183,449 | +0 | 62,800 | 62,800 | +0 | differs (64 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `nibble_screen_connect_repeater_` | 1,103,209 | 1,103,209 | +0 | 60,216 | 60,216 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `nibble_zero_connect_repeater_` | 1,103,301 | 1,103,301 | +0 | 60,216 | 60,216 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `RAK_3112_repeater` | 1,165,765 | 1,165,765 | +0 | 62,424 | 62,424 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `SenseCapIndicator-ESPNow_comp_radio_usb` | | | | | | | does not build on either commit | | | +| `Station_G2_repeater` | 1,207,885 | 1,207,885 | +0 | 74,712 | 74,712 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Station_G3_ESP32_repeater` | 1,209,469 | 1,209,469 | +0 | 74,720 | 74,720 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Tenstar_C3_sx1262_repeater` | 1,152,378 | 1,152,378 | +0 | 53,796 | 53,796 | +0 | differs (82 bytes) | time @ 0x50000018, magic @ 0x5000001c | magic @ 0x5000001c, time @ 0x50000018 | +| `ThinkNode_M2_Repeater` | 1,110,181 | 1,110,181 | +0 | 58,160 | 58,160 | +0 | differs (64 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `ThinkNode_M5_Repeater` | 1,127,465 | 1,127,465 | +0 | 63,648 | 63,648 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `ThinkNode_M7_repeater` | 1,089,241 | 1,089,269 | +28 | 59,688 | 59,688 | +0 | differs: length 1089664 -> 1089680 | time @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `ThinkNode_M9_repeater_` | 1,182,977 | 1,183,001 | +24 | 62,144 | 62,144 | +0 | differs: length 1183392 -> 1183424 | time @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Waveshare_S3_LR1121_repeater` | 1,084,869 | 1,084,869 | +0 | 59,868 | 59,868 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Xiao_C3_repeater` | 1,158,046 | 1,158,046 | +0 | 54,076 | 54,076 | +0 | differs (82 bytes) | time @ 0x50000018, magic @ 0x5000001c | magic @ 0x5000001c, time @ 0x50000018 | +| `Xiao_C6_repeater_` | 542,479 | 542,479 | +0 | 29,856 | 29,856 | +0 | differs (64 bytes) | time @ 0x5000004c, magic @ 0x50000048 | magic @ 0x50000048, time @ 0x5000004c | +| `Xiao_S3_repeater` | 1,137,605 | 1,137,605 | +0 | 61,680 | 61,680 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Xiao_S3_WIO_repeater` | 1,127,969 | 1,127,969 | +0 | 61,320 | 61,320 | +0 | differs (64 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_repeater_bridge_rs232` | 1,177,429 | 1,177,429 | +0 | 64,096 | 64,096 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_repeater_bridge_espnow` | 1,185,425 | 1,185,425 | +0 | 64,168 | 64,168 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_room_server` | 1,170,101 | 1,170,101 | +0 | 66,200 | 66,200 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_terminal_chat` | 602,317 | 602,317 | +0 | 95,868 | 95,868 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_companion_radio_usb` | 658,149 | 658,149 | +0 | 103,404 | 103,404 | +0 | differs (64 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_companion_radio_ble` | 1,671,593 | 1,671,593 | +0 | 194,844 | 194,844 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_companion_radio_wifi` | 1,107,797 | 1,107,797 | +0 | 172,384 | 172,384 | +0 | differs (64 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_sensor` | 1,181,489 | 1,181,489 | +0 | 60,600 | 60,600 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Heltec_v3_kiss_modem` | 581,185 | 581,185 | +0 | 24,580 | 24,580 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Generic_E22_sx1268_repeater` | 1,143,361 | 1,143,361 | +0 | 60,620 | 60,620 | +0 | differs (65 bytes) | time @ 0x50000204, magic @ 0x50000200 | magic @ 0x50000200, time @ 0x50000204 | +| `Meshadventurer_sx1268_repeater` | 1,161,797 | 1,161,797 | +0 | 61,084 | 61,084 | +0 | differs (64 bytes) | time @ 0x50000204, magic @ 0x50000200 | magic @ 0x50000200, time @ 0x50000204 | +| `RAK_3112_repeater_bridge_espnow` | 1,176,269 | 1,176,269 | +0 | 64,072 | 64,072 | +0 | differs (65 bytes) | time @ 0x50000004, magic @ 0x50000000 | magic @ 0x50000000, time @ 0x50000004 | +| `Xiao_C6_companion_radio_ble_` | 1,446,683 | 1,446,683 | +0 | 164,292 | 164,292 | +0 | differs (64 bytes) | time @ 0x5000004c, magic @ 0x50000048 | magic @ 0x50000048, time @ 0x5000004c | +| `RAK_4631_repeater` | 441,964 | 441,964 | +0 | 37,240 | 37,240 | +0 | same | none | none | +| `RAK_4631_companion_radio_ble` | 465,224 | 465,224 | +0 | 149,768 | 149,768 | +0 | same | none | none | +| `PicoW_repeater` | 492,668 | 492,668 | +0 | 85,368 | 85,368 | +0 | same | none | none | +| `wio-e5-mini_repeater` | 204,136 | 204,136 | +0 | 17,172 | 17,172 | +0 | same | none | none | +| `ProMicro_repeater` | 346,276 | 346,276 | +0 | 33,900 | 33,900 | +0 | same | none | none | +| `Meshimi_repeater_` | 542,535 | 542,535 | +0 | 29,856 | 29,856 | +0 | differs (64 bytes) | time @ 0x5000004c, magic @ 0x50000048 | magic @ 0x50000048, time @ 0x5000004c | +| `M5Stack_Unit_C6L_companion_radio_ble` | 1,454,227 | 1,454,227 | +0 | 164,180 | 164,180 | +0 | differs (65 bytes) | time @ 0x5000004c, magic @ 0x50000048 | magic @ 0x50000048, time @ 0x5000004c | + +
diff --git a/platformio.ini b/platformio.ini index 4bbc58bb5f..cd38837dcd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -182,7 +182,11 @@ test_ignore = test_region_map test_variant_target test_variant_target_override + test_variant_target_globals + test_variant_target_esp32 + test_variant_target_esp32_override test_companion_frames + test_esp32_rtc_backup build_src_filter = -<*> +<../src/Utils.cpp> @@ -521,6 +525,137 @@ build_src_filter = ${env:native_variant_target.build_src_filter} lib_deps = google/googletest @ 1.17.0 +[env:native_variant_target_globals] +; The radio, wrapper and RTC globals of a RadioLib variant (cut D of note 0011): +; the shared code against the target.h of a variant with the real +; AutoDiscoverRTCClock (test/mocks/radiolib_variant_globals, ahead of the other +; stand-ins). The pins and NRF52_PLATFORM are what an nRF52 variant's build +; flags and variant.h set; their values only have to differ from each other. +platform = native +test_framework = googletest +build_flags = -std=c++17 + -I test/mocks/radiolib_variant_globals + -I test/mocks/radiolib_variant + -I src + -I test/mocks + -D LORA_SF=8 + -D WRAPPER_CLASS=TestRadioWrapper + -D RADIO_CLASS=TestRadio + -D NRF52_PLATFORM + -D P_LORA_NSS=11 + -D P_LORA_DIO_1=12 + -D P_LORA_RESET=13 + -D P_LORA_BUSY=14 +test_build_src = yes +test_filter = test_variant_target_globals +build_src_filter = ${env:native_variant_target.build_src_filter} +lib_deps = + google/googletest @ 1.17.0 + +[env:native_variant_target_esp32] +; The radio globals and radio_init() of an ESP32 variant of cut D2 of note 0011, +; with an SX1262 on its own SPI bus (P_LORA_SCLK) on the default host, and a +; variant with its own radio_init() (test_variant_target_esp32_override); the +; three below are the other board descriptions that occur. ESP32 and the pins +; are what the variants' build flags set; the values only have to differ. +; ICACHE_RAM_ATTR is what the ESP32 core defines for RadioLibWrappers.cpp. +platform = native +test_framework = googletest +build_flags = -std=c++17 + -I test/mocks/radiolib_variant_esp32 + -I test/mocks/radiolib_variant + -I src + -I test/mocks + -D LORA_SF=8 + -D WRAPPER_CLASS=TestRadioWrapper + -D RADIO_CLASS=TestRadio + -D ESP32 + -D ICACHE_RAM_ATTR= + -D P_LORA_NSS=11 + -D P_LORA_DIO_1=12 + -D P_LORA_RESET=13 + -D P_LORA_BUSY=14 + -D P_LORA_DIO_0=15 + -D P_LORA_SCLK=16 +test_build_src = yes +test_filter = test_variant_target_esp32* +build_src_filter = ${env:native_variant_target.build_src_filter} +lib_deps = + google/googletest @ 1.17.0 + +[env:native_variant_target_esp32_no_sclk] +; The same without P_LORA_SCLK: no own bus, RadioLib starts the default one. +platform = native +test_framework = googletest +build_flags = -std=c++17 + -I test/mocks/radiolib_variant_esp32 + -I test/mocks/radiolib_variant + -I src + -I test/mocks + -D LORA_SF=8 + -D WRAPPER_CLASS=TestRadioWrapper + -D RADIO_CLASS=TestRadio + -D ESP32 + -D ICACHE_RAM_ATTR= + -D P_LORA_NSS=11 + -D P_LORA_DIO_1=12 + -D P_LORA_RESET=13 + -D P_LORA_BUSY=14 + -D P_LORA_DIO_0=15 +test_build_src = yes +test_filter = test_variant_target_esp32 +build_src_filter = ${env:native_variant_target.build_src_filter} +lib_deps = + google/googletest @ 1.17.0 + +[env:native_variant_target_esp32_sx1276] +; The same with an SX1276, whose Module takes DIO0 and DIO1 instead of DIO1 +; and BUSY (USE_SX1276 is what CustomSX1276Wrapper.h defines). +platform = native +test_framework = googletest +build_flags = ${env:native_variant_target_esp32.build_flags} + -D USE_SX1276 +test_build_src = yes +test_filter = test_variant_target_esp32 +build_src_filter = ${env:native_variant_target.build_src_filter} +lib_deps = + google/googletest @ 1.17.0 + +[env:native_esp32_rtc_backup] +; The RTC backup of ESP32RTCClock: the real src/helpers/ESP32Board.h and +; ESP32Board.cpp, which defines the backup, against stand-ins for the ESP-IDF +; headers and the variant's target.h, used from two translation units +; (test/test_esp32_rtc_backup/other_unit.cpp). The pins are what ESP32Board +; uses; their values are not. +platform = native +test_framework = googletest +build_flags = -std=c++17 + -I test/mocks/esp32_idf + -I src + -I test/mocks + -D ESP_PLATFORM + -D P_LORA_DIO_1=1 + -D P_LORA_NSS=2 +test_build_src = yes +test_filter = test_esp32_rtc_backup +build_src_filter = + -<*> + + +lib_deps = + google/googletest @ 1.17.0 + +[env:native_variant_target_esp32_spi_host] +; The same with the own bus on another host than the SPIClass default. +platform = native +test_framework = googletest +build_flags = ${env:native_variant_target_esp32.build_flags} + -D P_LORA_SPI_HOST=FSPI +test_build_src = yes +test_filter = test_variant_target_esp32 +build_src_filter = ${env:native_variant_target.build_src_filter} +lib_deps = + google/googletest @ 1.17.0 + [env:native_region] ; RegionMap on the host. It reads packets and keys and writes nothing but its own ; table, so it builds against the small stubs in test/test_region_map/stubs, which are diff --git a/src/helpers/ESP32Board.cpp b/src/helpers/ESP32Board.cpp index a55abb264e..d190fca190 100644 --- a/src/helpers/ESP32Board.cpp +++ b/src/helpers/ESP32Board.cpp @@ -3,6 +3,10 @@ #include "ESP32Board.h" #include +// The RTC backup of ESP32RTCClock, declared in ESP32Board.h. +RTC_NOINIT_ATTR uint32_t _rtc_backup_time; +RTC_NOINIT_ATTR uint32_t _rtc_backup_magic; + #if defined(ADMIN_PASSWORD) && !defined(DISABLE_WIFI_OTA) // Repeater or Room Server only #include #include diff --git a/src/helpers/ESP32Board.h b/src/helpers/ESP32Board.h index 3f95e6923f..cd274cd931 100644 --- a/src/helpers/ESP32Board.h +++ b/src/helpers/ESP32Board.h @@ -200,8 +200,11 @@ class ESP32Board : public mesh::MainBoard { } }; -static RTC_NOINIT_ATTR uint32_t _rtc_backup_time; -static RTC_NOINIT_ATTR uint32_t _rtc_backup_magic; +// The time ESP32RTCClock restores after a reset, in RTC memory that a reset does +// not clear. Defined once, in ESP32Board.cpp: the inline members below run in +// every translation unit that uses them and must all see the same backup. +extern uint32_t _rtc_backup_time; +extern uint32_t _rtc_backup_magic; #define RTC_BACKUP_MAGIC 0xAA55CC33 #define RTC_TIME_MIN 1772323200 // 1 Mar 2026 diff --git a/src/helpers/radiolib/RadioLibTarget.cpp b/src/helpers/radiolib/RadioLibTarget.cpp index a9259e2b18..7b4dc01ced 100644 --- a/src/helpers/radiolib/RadioLibTarget.cpp +++ b/src/helpers/radiolib/RadioLibTarget.cpp @@ -1,5 +1,5 @@ // The parts of a variant's target.cpp that every board with a RadioLib radio -// writes the same way, defined once here. They are weak: a variant (or a +// writes the same way, defined once here. The functions are weak: a variant (or a // downstream fork's variant) that still defines its own keeps compiling, and its // definition takes precedence. WRAPPER_CLASS is what tells a RadioLib variant // apart; the ESP-NOW variants have no LoRa radio and define their own. @@ -9,6 +9,81 @@ #include +// The radio, its wrapper and the RTC clock, for the variants whose target.h +// asks for them with RADIOLIB_TARGET_GLOBALS. Built from the board's +// description: the P_LORA_* pins, the chip, the platform, and on ESP32 +// P_LORA_SCLK (an own SPI bus) and P_LORA_SPI_HOST (its host, if not the +// SPIClass default). Not weak, unlike the functions below: a weak object is +// still constructed here, into the variant's object where the variant defines +// its own, so a variant that keeps its globals simply does not define the macro. +#ifdef RADIOLIB_TARGET_GLOBALS + +#if !defined(NRF52_PLATFORM) && !defined(ESP32) + #error "RADIOLIB_TARGET_GLOBALS: the radio globals are described for nRF52 and ESP32 only so far; define them in target.cpp" +#endif + +#include +#include +#if defined(ESP32) + #include +#else + #include +#endif + +// The pins in the order the chip's Module takes them. +#if defined(USE_SX1276) + #define RADIOLIB_TARGET_PINS P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1 +#else + #define RADIOLIB_TARGET_PINS P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY +#endif + +// On nRF52 the radio is on SPI, passed to RadioLib, so that std_init() and not +// RadioLib starts the bus. On ESP32 it has a bus of its own where the board +// names the SPI pins, and otherwise RadioLib starts its default bus itself. +#if defined(ESP32) + #if defined(P_LORA_SCLK) + #if defined(P_LORA_SPI_HOST) + static SPIClass spi(P_LORA_SPI_HOST); + #else + static SPIClass spi; + #endif + static RADIO_CLASS radio = new Module(RADIOLIB_TARGET_PINS, spi); + #else + static RADIO_CLASS radio = new Module(RADIOLIB_TARGET_PINS); + #endif +#else + static RADIO_CLASS radio = new Module(RADIOLIB_TARGET_PINS, SPI); +#endif + +WRAPPER_CLASS radio_driver(radio, board); + +#if defined(ESP32) + ESP32RTCClock fallback_clock; +#else + VolatileRTCClock fallback_clock; +#endif +AutoDiscoverRTCClock rtc_clock(fallback_clock); + +// The radio_init() of these variants on ESP32 with a chip that has std_init(): +// start the fallback clock and the RTC, then the radio on its bus. +#if defined(ESP32) && (defined(USE_SX1262) || defined(USE_SX1268) || defined(USE_SX1276)) + +#include + +__attribute__((weak)) bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); +#if defined(P_LORA_SCLK) + return radio.std_init(&spi); +#else + return radio.std_init(); +#endif +} + +#endif + +#endif + // A new random identity, from the noise of the radio radio_driver wraps (which // is the variant's global radio). Slow, so only for creating the node's identity. __attribute__((weak)) mesh::LocalIdentity radio_new_identity() { diff --git a/test/mocks/esp32_idf/Wire.h b/test/mocks/esp32_idf/Wire.h new file mode 100644 index 0000000000..7539b1c24b --- /dev/null +++ b/test/mocks/esp32_idf/Wire.h @@ -0,0 +1,10 @@ +#pragma once + +// Stand-in for the Arduino Wire library, as far as ESP32Board::begin() uses it. +class TwoWire { +public: + bool begin() { return true; } + bool begin(int sda, int scl) { return true; } +}; + +inline TwoWire Wire; diff --git a/test/mocks/esp32_idf/driver/rtc_io.h b/test/mocks/esp32_idf/driver/rtc_io.h new file mode 100644 index 0000000000..f39de99bb6 --- /dev/null +++ b/test/mocks/esp32_idf/driver/rtc_io.h @@ -0,0 +1,4 @@ +#pragma once + +// Stand-in for the ESP-IDF header of the same name, see esp32_idf_stubs.h. +#include "../esp32_idf_stubs.h" diff --git a/test/mocks/esp32_idf/esp32_idf_stubs.h b/test/mocks/esp32_idf/esp32_idf_stubs.h new file mode 100644 index 0000000000..1ad186cada --- /dev/null +++ b/test/mocks/esp32_idf/esp32_idf_stubs.h @@ -0,0 +1,72 @@ +#pragma once + +// Stand-in for the parts of the ESP32 Arduino core and ESP-IDF that +// src/helpers/ESP32Board.h and ESP32Board.cpp name, so both compile on the host. +// Only ESP32RTCClock is exercised: esp_reset_reason() returns what a test sets, +// and settimeofday() is redirected to a recorder, so a test sees which time +// begin() and setCurrentTime() set without touching the host's clock. The other +// declarations only have to compile. + +#include +#include +#include // time(), which the ESP32 core declares through Arduino.h + +// esp_attr.h: on the ESP32 a section in RTC memory that a reset does not clear; +// on the host ordinary (zero initialized) memory. +#define RTC_NOINIT_ATTR + +typedef enum { + ESP_RST_UNKNOWN, + ESP_RST_POWERON, + ESP_RST_EXT, + ESP_RST_SW, + ESP_RST_PANIC, + ESP_RST_INT_WDT, + ESP_RST_TASK_WDT, + ESP_RST_WDT, + ESP_RST_DEEPSLEEP, + ESP_RST_BROWNOUT, + ESP_RST_SDIO, +} esp_reset_reason_t; + +inline esp_reset_reason_t g_esp_reset_reason = ESP_RST_POWERON; +inline esp_reset_reason_t esp_reset_reason() { return g_esp_reset_reason; } +inline void esp_restart() { } + +// settimeofday() as ESP32RTCClock calls it: records the time instead of setting +// the host's clock. is included above, so the header's own include +// of it does not see the macro. +inline int g_settimeofday_calls = 0; +inline time_t g_settimeofday_sec = 0; +inline int esp32_test_settimeofday(const struct timeval* tv, const void*) { + g_settimeofday_calls++; + g_settimeofday_sec = tv->tv_sec; + return 0; +} +#define settimeofday esp32_test_settimeofday + +typedef int gpio_num_t; +enum { GPIO_INTR_POSEDGE = 1, GPIO_INTR_HIGH_LEVEL = 5 }; +#ifndef HIGH +#define HIGH 1 +#endif +inline int gpio_get_level(gpio_num_t) { return 0; } +inline void gpio_wakeup_enable(gpio_num_t, int) { } +inline void gpio_wakeup_disable(gpio_num_t) { } +inline void gpio_set_intr_type(gpio_num_t, int) { } +inline void esp_sleep_enable_timer_wakeup(uint64_t) { } +inline void esp_sleep_enable_gpio_wakeup() { } +inline void esp_light_sleep_start() { } +enum { ESP_SLEEP_WAKEUP_ALL = 0 }; +inline void esp_sleep_disable_wakeup_source(int) { } +inline void esp_deep_sleep_start() { } +inline void rtc_gpio_hold_en(gpio_num_t) { } +inline void gpio_hold_en(gpio_num_t) { } +inline void digitalWrite(int, int) { } + +typedef int portMUX_TYPE; +#define portMUX_INITIALIZER_UNLOCKED 0 +#define portENTER_CRITICAL(mux) ((void)(mux)) +#define portEXIT_CRITICAL(mux) ((void)(mux)) + +inline float temperatureRead() { return 0.0f; } diff --git a/test/mocks/esp32_idf/esp_system.h b/test/mocks/esp32_idf/esp_system.h new file mode 100644 index 0000000000..6d8152b3ff --- /dev/null +++ b/test/mocks/esp32_idf/esp_system.h @@ -0,0 +1,4 @@ +#pragma once + +// Stand-in for the ESP-IDF header of the same name, see esp32_idf_stubs.h. +#include "esp32_idf_stubs.h" diff --git a/test/mocks/esp32_idf/rom/rtc.h b/test/mocks/esp32_idf/rom/rtc.h new file mode 100644 index 0000000000..f39de99bb6 --- /dev/null +++ b/test/mocks/esp32_idf/rom/rtc.h @@ -0,0 +1,4 @@ +#pragma once + +// Stand-in for the ESP-IDF header of the same name, see esp32_idf_stubs.h. +#include "../esp32_idf_stubs.h" diff --git a/test/mocks/esp32_idf/soc/rtc.h b/test/mocks/esp32_idf/soc/rtc.h new file mode 100644 index 0000000000..f39de99bb6 --- /dev/null +++ b/test/mocks/esp32_idf/soc/rtc.h @@ -0,0 +1,4 @@ +#pragma once + +// Stand-in for the ESP-IDF header of the same name, see esp32_idf_stubs.h. +#include "../esp32_idf_stubs.h" diff --git a/test/mocks/esp32_idf/target.h b/test/mocks/esp32_idf/target.h new file mode 100644 index 0000000000..4f9808ea91 --- /dev/null +++ b/test/mocks/esp32_idf/target.h @@ -0,0 +1,19 @@ +#pragma once + +// Stand-in for a variant's target.h, as far as src/helpers/ESP32Board.cpp uses +// it: ESP32Board::enterDeepSleep() powers off the radio and stops the GPS. + +#include + +struct TestRadioDriver { + void powerOff() { } +}; +inline TestRadioDriver radio_driver; + +struct TestLocationProvider { + void stop() { } +}; +struct TestSensors { + TestLocationProvider* getLocationProvider() { return nullptr; } +}; +inline TestSensors sensors; diff --git a/test/mocks/radiolib_variant/SPI.h b/test/mocks/radiolib_variant/SPI.h index 6bfbe442e2..971d06aa14 100644 --- a/test/mocks/radiolib_variant/SPI.h +++ b/test/mocks/radiolib_variant/SPI.h @@ -1,7 +1,20 @@ #pragma once -// Stand-in for the Arduino SPI library: only the type and the global, so a test -// can see which bus the radio is started on. -class SPIClass { }; +#include + +// Stand-in for the Arduino SPI library: the type, the global and the bus +// numbers, so a test can see which bus the radio is started on and which host +// an ESP32 variant's own bus is on. FSPI and HSPI as on the ESP32-S3 and C3; +// the default host is HSPI, as in the ESP32 core. +#ifndef FSPI +#define FSPI 0 +#define HSPI 1 +#endif + +class SPIClass { +public: + uint8_t bus; + SPIClass(uint8_t spi_bus = HSPI) : bus(spi_bus) { } +}; inline SPIClass SPI; diff --git a/test/mocks/radiolib_variant/target.h b/test/mocks/radiolib_variant/target.h index 65dcede0fb..736ba0a3be 100644 --- a/test/mocks/radiolib_variant/target.h +++ b/test/mocks/radiolib_variant/target.h @@ -6,57 +6,7 @@ // As on a board, the environment sets WRAPPER_CLASS and the variant's target.cpp // (here: the test) defines the globals declared below. -#include -#include -#include - -#include -#include - -// What the stand-ins below were asked to do, in order, for the tests to compare. -inline std::vector target_calls; - -// Stand-in for a chip class with std_init() (CustomSX1262 and its siblings): -// records the call and the SPI bus it was given, and counts the calls per radio. -class TestRadio : public PhysicalLayer { -public: - bool std_init_result = true; - int std_init_calls = 0; - - bool std_init(SPIClass* spi = nullptr) { - target_calls.push_back(spi == &SPI ? "std_init(&SPI)" : spi ? "std_init(other SPI)" : "std_init()"); - std_init_calls++; - return std_init_result; - } -}; - -// Stand-in for AutoDiscoverRTCClock: records which bus it was started on. -class TestRTCClock { -public: - void begin(TwoWire& wire) { target_calls.push_back(&wire == &Wire ? "rtc_clock.begin(Wire)" : "rtc_clock.begin(other)"); } -}; - -// What CustomSX1262Wrapper.h defines, which every target.h of an SX1262 variant -// includes. -#ifndef USE_SX1262 -#define USE_SX1262 -#endif - -class TestRadioWrapper : public RadioLibWrapper { -public: - TestRadioWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } - void setParams(float, float, uint8_t, uint8_t) override { } - bool isReceivingPacket() override { return false; } - float getCurrentRSSI() override { return -100.0f; } -}; - -class TestBoard : public mesh::MainBoard { -public: - uint16_t getBattMilliVolts() override { return 4200; } - const char* getManufacturerName() const override { return "test"; } - void reboot() override { } - uint8_t getStartupReason() const override { return 0; } -}; +#include "variant_stubs.h" extern WRAPPER_CLASS radio_driver; extern TestRTCClock rtc_clock; diff --git a/test/mocks/radiolib_variant/target_calls.h b/test/mocks/radiolib_variant/target_calls.h new file mode 100644 index 0000000000..c7e98265ed --- /dev/null +++ b/test/mocks/radiolib_variant/target_calls.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include + +// What the variant stand-ins were asked to do, in order, for the tests to compare. +inline std::vector target_calls; diff --git a/test/mocks/radiolib_variant/variant_stubs.h b/test/mocks/radiolib_variant/variant_stubs.h new file mode 100644 index 0000000000..2f236b41c3 --- /dev/null +++ b/test/mocks/radiolib_variant/variant_stubs.h @@ -0,0 +1,84 @@ +#pragma once + +// The parts of the RadioLib variant stand-ins that do not depend on how the +// variant defines its globals: a recording radio, wrapper, board and RTC clock, +// and RadioLib's Module. Included by test/mocks/radiolib_variant/target.h (a +// variant that defines its globals in its target.cpp) and by +// test/mocks/radiolib_variant_globals/target.h (one that takes them from +// RadioLibTarget.cpp). + +#include +#include +#include + +#include +#include + +#include "target_calls.h" + +// Stand-in for RadioLib's Module, with its two Arduino constructors, which do +// different things: without an SPI bus RadioLib starts the default bus itself, +// with one it leaves that to the caller. `spi` tells them apart (null for the +// first), the pins are kept as given. +class Module { +public: + uint32_t cs, irq, rst, gpio; + SPIClass* spi; + + Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio = (uint32_t)-1) + : cs(cs), irq(irq), rst(rst), gpio(gpio), spi(nullptr) { } + Module(uint32_t cs, uint32_t irq, uint32_t rst, uint32_t gpio, SPIClass& spi) + : cs(cs), irq(irq), rst(rst), gpio(gpio), spi(&spi) { } +}; + +// Stand-in for a chip class with std_init() (CustomSX1262 and its siblings): +// records the call and the SPI bus it was given, and counts the calls per radio. +class TestRadio : public PhysicalLayer { +public: + Module* module = nullptr; // what the variant constructed it from, as `new Module(...)` + bool std_init_result = true; + int std_init_calls = 0; + + bool std_init(SPIClass* spi = nullptr) { + target_calls.push_back(spi == &SPI ? "std_init(&SPI)" + : spi && module && spi == module->spi ? "std_init(module bus)" + : spi ? "std_init(other SPI)" : "std_init()"); + std_init_calls++; + return std_init_result; + } + + TestRadio() = default; + TestRadio(Module* mod) : module(mod) { } +}; + +// Stand-in for AutoDiscoverRTCClock: records which bus it was started on. +class TestRTCClock { +public: + void begin(TwoWire& wire) { target_calls.push_back(&wire == &Wire ? "rtc_clock.begin(Wire)" : "rtc_clock.begin(other)"); } +}; + +// What CustomSX1262Wrapper.h defines, which every target.h of an SX1262 variant +// includes; an environment for an SX1276 variant sets USE_SX1276 instead. +#if !defined(USE_SX1262) && !defined(USE_SX1276) +#define USE_SX1262 +#endif + +class TestRadioWrapper : public RadioLibWrapper { +public: + TestRadioWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } + // What it was constructed with, for the tests (the real wrappers keep them + // protected as well). + PhysicalLayer* wrapped_radio() const { return _radio; } + mesh::MainBoard* wrapped_board() const { return _board; } + void setParams(float, float, uint8_t, uint8_t) override { } + bool isReceivingPacket() override { return false; } + float getCurrentRSSI() override { return -100.0f; } +}; + +class TestBoard : public mesh::MainBoard { +public: + uint16_t getBattMilliVolts() override { return 4200; } + const char* getManufacturerName() const override { return "test"; } + void reboot() override { } + uint8_t getStartupReason() const override { return 0; } +}; diff --git a/test/mocks/radiolib_variant_esp32/helpers/ESP32Board.h b/test/mocks/radiolib_variant_esp32/helpers/ESP32Board.h new file mode 100644 index 0000000000..56c38632ac --- /dev/null +++ b/test/mocks/radiolib_variant_esp32/helpers/ESP32Board.h @@ -0,0 +1,16 @@ +#pragma once + +// Stand-in for src/helpers/ESP32Board.h, which the ESP32 variants include +// through their board header: only ESP32RTCClock, recording begin(), since the +// real one sets the system time from the ESP32's RTC memory. + +#include +#include "../../radiolib_variant/target_calls.h" + +class ESP32RTCClock : public mesh::RTCClock { + uint32_t _time = 0; +public: + void begin() { target_calls.push_back("fallback_clock.begin()"); } + uint32_t getCurrentTime() override { return _time; } + void setCurrentTime(uint32_t time) override { _time = time; } +}; diff --git a/test/mocks/radiolib_variant_esp32/target.h b/test/mocks/radiolib_variant_esp32/target.h new file mode 100644 index 0000000000..8843938b19 --- /dev/null +++ b/test/mocks/radiolib_variant_esp32/target.h @@ -0,0 +1,20 @@ +#pragma once + +// Stand-in for the target.h of an ESP32 variant of cut D2 of note 0011, for the +// suite that pins its radio, wrapper and RTC globals and its radio_init(). The +// RTC clock is the real AutoDiscoverRTCClock (its out-of-line members are stood +// in by the test); helpers/ESP32Board.h, which the variants include through +// their board header, is a stand-in next to this file. The environment sets the pins, P_LORA_SCLK and ESP32, +// as the variants' build flags do. Listed ahead of test/mocks/radiolib_variant. + +#include +#include "../radiolib_variant/variant_stubs.h" +#include + +extern TestBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; + +bool radio_init(); +mesh::LocalIdentity radio_new_identity(); diff --git a/test/mocks/radiolib_variant_globals/target.h b/test/mocks/radiolib_variant_globals/target.h new file mode 100644 index 0000000000..c719c466fe --- /dev/null +++ b/test/mocks/radiolib_variant_globals/target.h @@ -0,0 +1,20 @@ +#pragma once + +// Stand-in for the target.h of an nRF52 variant of cut D of note 0011, for the +// suite that pins its radio, wrapper and RTC globals. As in the variants, the +// RTC clock is the real AutoDiscoverRTCClock (its out-of-line members are stood +// in by the test), and the environment sets the pins and the platform, as the +// variants' build flags and variant.h do. Listed ahead of +// test/mocks/radiolib_variant, whose target.h stands in for a variant whose +// RTC clock is a recording stand-in. + +#include "../radiolib_variant/variant_stubs.h" +#include + +extern TestBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; + +bool radio_init(); +mesh::LocalIdentity radio_new_identity(); diff --git a/test/test_esp32_rtc_backup/other_unit.cpp b/test/test_esp32_rtc_backup/other_unit.cpp new file mode 100644 index 0000000000..4d8c9d6a06 --- /dev/null +++ b/test/test_esp32_rtc_backup/other_unit.cpp @@ -0,0 +1,21 @@ +// A second translation unit that uses ESP32RTCClock, as a variant's target.cpp +// and src/helpers/radiolib/RadioLibTarget.cpp would if both did. The test in +// test_esp32_rtc_backup.cpp calls these and checks that begin(), setCurrentTime() +// and tick() see the same RTC backup whichever unit they run in. + +#include + +void other_unit_set_time(uint32_t time) { + ESP32RTCClock clock; + clock.setCurrentTime(time); +} + +void other_unit_tick() { + ESP32RTCClock clock; + clock.tick(); +} + +void other_unit_begin() { + ESP32RTCClock clock; + clock.begin(); +} diff --git a/test/test_esp32_rtc_backup/test_esp32_rtc_backup.cpp b/test/test_esp32_rtc_backup/test_esp32_rtc_backup.cpp new file mode 100644 index 0000000000..fd828bae5e --- /dev/null +++ b/test/test_esp32_rtc_backup/test_esp32_rtc_backup.cpp @@ -0,0 +1,119 @@ +// The RTC backup of ESP32RTCClock (src/helpers/ESP32Board.h): setCurrentTime() +// and tick() save the time in RTC memory that a reset does not clear, begin() +// restores it after a reset that lost the system time. The backup has to be one +// object for the whole image, so the tests write it in one translation unit +// (other_unit.cpp) and read it in another (this one), in both directions. + +#include +#include + +#include + +void other_unit_set_time(uint32_t time); +void other_unit_tick(); +void other_unit_begin(); + +namespace { + +const uint32_t SAVED_TIME = RTC_TIME_MIN + 123456; + +class Esp32RtcBackupTest : public ::testing::Test { +protected: + void SetUp() override { + // RTC_NOINIT memory holds anything after power-on; start without a backup. + _rtc_backup_time = 0; + _rtc_backup_magic = 0; + g_esp_reset_reason = ESP_RST_POWERON; + g_settimeofday_calls = 0; + g_settimeofday_sec = 0; + } + + // A reset that lost the system time, then begin() in this unit. + void resetAndBeginHere(esp_reset_reason_t reason = ESP_RST_SW) { + g_esp_reset_reason = reason; + g_settimeofday_calls = 0; + ESP32RTCClock clock; + clock.begin(); + } +}; + +TEST_F(Esp32RtcBackupTest, BeginRestoresTimeSetInAnotherUnit) { + other_unit_set_time(SAVED_TIME); + resetAndBeginHere(); + EXPECT_EQ(g_settimeofday_calls, 1); + EXPECT_EQ(g_settimeofday_sec, (time_t)SAVED_TIME); +} + +TEST_F(Esp32RtcBackupTest, BeginInAnotherUnitRestoresTimeSetHere) { + ESP32RTCClock clock; + clock.setCurrentTime(SAVED_TIME); + g_esp_reset_reason = ESP_RST_PANIC; + g_settimeofday_calls = 0; + other_unit_begin(); + EXPECT_EQ(g_settimeofday_calls, 1); + EXPECT_EQ(g_settimeofday_sec, (time_t)SAVED_TIME); +} + +TEST_F(Esp32RtcBackupTest, BeginRestoresTimeSavedByTickInAnotherUnit) { + // tick() saves the system time, here the host's, which is after RTC_TIME_MIN. + time_t before = time(NULL); + other_unit_tick(); + time_t after = time(NULL); + ASSERT_GT(before, (time_t)RTC_TIME_MIN); + resetAndBeginHere(ESP_RST_TASK_WDT); + EXPECT_EQ(g_settimeofday_calls, 1); + EXPECT_GE(g_settimeofday_sec, before); + EXPECT_LE(g_settimeofday_sec, after); +} + +TEST_F(Esp32RtcBackupTest, SetCurrentTimeSetsSystemTimeAndBackup) { + ESP32RTCClock clock; + clock.setCurrentTime(SAVED_TIME); + EXPECT_EQ(g_settimeofday_calls, 1); + EXPECT_EQ(g_settimeofday_sec, (time_t)SAVED_TIME); + EXPECT_EQ(_rtc_backup_time, SAVED_TIME); + EXPECT_EQ(_rtc_backup_magic, (uint32_t)RTC_BACKUP_MAGIC); +} + +TEST_F(Esp32RtcBackupTest, BeginWithoutBackupSeedsMinimumTime) { + resetAndBeginHere(ESP_RST_POWERON); + EXPECT_EQ(g_settimeofday_calls, 1); + EXPECT_EQ(g_settimeofday_sec, (time_t)RTC_TIME_MIN); +} + +TEST_F(Esp32RtcBackupTest, BeginIgnoresBackupWithoutMagic) { + _rtc_backup_time = SAVED_TIME; + _rtc_backup_magic = RTC_BACKUP_MAGIC ^ 1; + resetAndBeginHere(); + EXPECT_EQ(g_settimeofday_sec, (time_t)RTC_TIME_MIN); +} + +TEST_F(Esp32RtcBackupTest, BeginIgnoresBackupBeforeMinimumTime) { + _rtc_backup_time = RTC_TIME_MIN - 1; + _rtc_backup_magic = RTC_BACKUP_MAGIC; + resetAndBeginHere(); + EXPECT_EQ(g_settimeofday_sec, (time_t)RTC_TIME_MIN); +} + +TEST_F(Esp32RtcBackupTest, BeginAfterDeepSleepKeepsSystemTime) { + other_unit_set_time(SAVED_TIME); + resetAndBeginHere(ESP_RST_DEEPSLEEP); + EXPECT_EQ(g_settimeofday_calls, 0); +} + +TEST_F(Esp32RtcBackupTest, TickSavesSystemTimeOverOlderBackup) { + // setCurrentTime() saves any time; tick() saves the system time when it is + // after RTC_TIME_MIN and differs from the backup, as the host's clock does. + other_unit_set_time(RTC_TIME_MIN - 10); + EXPECT_EQ(_rtc_backup_time, (uint32_t)(RTC_TIME_MIN - 10)); + ESP32RTCClock clock; + clock.tick(); + EXPECT_GT(_rtc_backup_time, (uint32_t)RTC_TIME_MIN); +} + +} // namespace + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/test_variant_target_esp32/test_variant_target_esp32.cpp b/test/test_variant_target_esp32/test_variant_target_esp32.cpp new file mode 100644 index 0000000000..82e3b75729 --- /dev/null +++ b/test/test_variant_target_esp32/test_variant_target_esp32.cpp @@ -0,0 +1,211 @@ +#include + +#include + +#include +#include "target.h" + +// The radio, wrapper and RTC globals and radio_init() of the 22 ESP32 variants +// of cut D2, pinned on the host: which RadioLib Module constructor the radio is +// built with (pins, own SPI bus and its host, or none), what radio_driver +// wraps, which clock rtc_clock falls back to, and how radio_init() starts them. +// Built in four environments, one per board description that occurs (see +// platformio.ini); each compiles the variant blocks of its description, +// verbatim. See docs/refactoring/0011-variant-target.md, "Cut D". + +mesh::Identity::Identity() { memset(pub_key, 0, sizeof(pub_key)); } +mesh::LocalIdentity::LocalIdentity(mesh::RNG* rng) { rng->random(pub_key, SEED_SIZE); } +void AutoDiscoverRTCClock::begin(TwoWire& wire) { + target_calls.push_back(&wire == &Wire ? "rtc_clock.begin(Wire)" : "rtc_clock.begin(other)"); +} +uint32_t AutoDiscoverRTCClock::getCurrentTime() { return _fallback->getCurrentTime(); } +void AutoDiscoverRTCClock::setCurrentTime(uint32_t time) { _fallback->setCurrentTime(time); } + +TestBoard board; + +// No target.h declares the fallback clock; the test needs it to see where +// rtc_clock falls back to. +extern ESP32RTCClock fallback_clock; + +// The same block and body once more, as the reference the cases are checked +// against on every commit, whatever defines the globals above. +namespace copy { +#if defined(USE_SX1276) +#if defined(P_LORA_SCLK) + static SPIClass spi; + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); +#else + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1); +#endif +#elif defined(P_LORA_SPI_HOST) +#if defined(P_LORA_SCLK) + static SPIClass spi(FSPI); + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); +#else + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); +#endif +#else +#if defined(P_LORA_SCLK) + static SPIClass spi; + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); +#else + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); +#endif +#endif + +WRAPPER_CLASS radio_driver(radio, board); + +ESP32RTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + +#if defined(P_LORA_SCLK) + return radio.std_init(&spi); +#else + return radio.std_init(); +#endif +} +} // namespace copy + +// The blocks of the variants that have their own bus in every environment and +// so write it without the #if (lilygo_t3s3, meshadventurer and the two nibble +// boards; lilygo_tlora_v2_1 with the SX1276), the bus of lilygo_tlora_c6 (own +// host 0, the branch its #if takes), and the radio_init() body four of them +// write without the #if (lilygo_t3s3, lilygo_tbeam_SX1262 and the two nibble +// boards). Only where their description is this environment's. +#if defined(P_LORA_SCLK) +namespace unconditional { +#if defined(USE_SX1276) +static SPIClass spi; +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); +#elif defined(P_LORA_SPI_HOST) + static SPIClass spi(0); + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); +#else +static SPIClass spi; +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); +#endif + +WRAPPER_CLASS radio_driver(radio, board); + +ESP32RTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + return radio.std_init(&spi); +} +} // namespace unconditional +#endif + +namespace { + +struct Globals { + const char* name; + TestRadioWrapper* driver; + AutoDiscoverRTCClock* rtc; + ESP32RTCClock* fallback; + bool (*init)(); +}; + +std::string name_of(const ::testing::TestParamInfo& info) { return info.param.name; } + +class RadioGlobals : public ::testing::TestWithParam { +protected: + TestRadio* radio() { return static_cast(GetParam().driver->wrapped_radio()); } + void SetUp() override { + target_calls.clear(); + if (radio()) { + radio()->std_init_calls = 0; + radio()->std_init_result = true; + } + } +}; + +TEST_P(RadioGlobals, RadioIsBuiltFromAModule) { + ASSERT_NE(nullptr, radio()); + EXPECT_NE(nullptr, radio()->module); +} + +TEST_P(RadioGlobals, ModuleHasTheBoardPinsInTheChipsOrder) { + ASSERT_NE(nullptr, radio()->module); + EXPECT_EQ((uint32_t)P_LORA_NSS, radio()->module->cs); +#if defined(USE_SX1276) + EXPECT_EQ((uint32_t)P_LORA_DIO_0, radio()->module->irq); + EXPECT_EQ((uint32_t)P_LORA_RESET, radio()->module->rst); + EXPECT_EQ((uint32_t)P_LORA_DIO_1, radio()->module->gpio); +#else + EXPECT_EQ((uint32_t)P_LORA_DIO_1, radio()->module->irq); + EXPECT_EQ((uint32_t)P_LORA_RESET, radio()->module->rst); + EXPECT_EQ((uint32_t)P_LORA_BUSY, radio()->module->gpio); +#endif +} + +TEST_P(RadioGlobals, ModuleBus) { + ASSERT_NE(nullptr, radio()->module); +#if defined(P_LORA_SCLK) + // An own bus, passed to RadioLib, on the variant's host or the default one. + ASSERT_NE(nullptr, radio()->module->spi); + EXPECT_NE(&SPI, radio()->module->spi); +#if defined(P_LORA_SPI_HOST) + EXPECT_EQ(FSPI, radio()->module->spi->bus); +#else + EXPECT_EQ(HSPI, radio()->module->spi->bus); +#endif +#else + // No bus: RadioLib starts its default bus itself. + EXPECT_EQ(nullptr, radio()->module->spi); +#endif +} + +TEST_P(RadioGlobals, DriverWrapsTheBoard) { + EXPECT_EQ(&board, GetParam().driver->wrapped_board()); +} + +TEST_P(RadioGlobals, RtcClockFallsBackToTheFallbackClock) { + GetParam().fallback->setCurrentTime(1234567); + EXPECT_EQ(1234567u, GetParam().rtc->getCurrentTime()); + GetParam().rtc->setCurrentTime(7654321); + EXPECT_EQ(7654321u, GetParam().fallback->getCurrentTime()); +} + +TEST_P(RadioGlobals, InitStartsTheFallbackClockThenTheRtcThenTheRadio) { + EXPECT_TRUE(GetParam().init()); +#if defined(P_LORA_SCLK) + std::vector expected = {"fallback_clock.begin()", "rtc_clock.begin(Wire)", "std_init(module bus)"}; +#else + std::vector expected = {"fallback_clock.begin()", "rtc_clock.begin(Wire)", "std_init()"}; +#endif + EXPECT_EQ(expected, target_calls); + EXPECT_EQ(1, radio()->std_init_calls); +} + +TEST_P(RadioGlobals, InitReturnsFalseWhenTheRadioFails) { + radio()->std_init_result = false; + EXPECT_FALSE(GetParam().init()); + EXPECT_EQ(3u, target_calls.size()); +} + +INSTANTIATE_TEST_SUITE_P(Copy, RadioGlobals, + ::testing::Values(Globals{"Copy", ©::radio_driver, ©::rtc_clock, ©::fallback_clock, ©::radio_init}), name_of); + +#if defined(P_LORA_SCLK) +INSTANTIATE_TEST_SUITE_P(Unconditional, RadioGlobals, + ::testing::Values(Globals{"Unconditional", &unconditional::radio_driver, &unconditional::rtc_clock, + &unconditional::fallback_clock, &unconditional::radio_init}), name_of); +#endif + +// The globals and radio_init() the variant gets, whoever defines them. +INSTANTIATE_TEST_SUITE_P(Variant, RadioGlobals, + ::testing::Values(Globals{"Variant", &radio_driver, &rtc_clock, &fallback_clock, &radio_init}), name_of); + +} // namespace + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/test_variant_target_esp32_override/test_variant_target_esp32_override.cpp b/test/test_variant_target_esp32_override/test_variant_target_esp32_override.cpp new file mode 100644 index 0000000000..646dec2aed --- /dev/null +++ b/test/test_variant_target_esp32_override/test_variant_target_esp32_override.cpp @@ -0,0 +1,41 @@ +#include + +#include + +#include +#include "target.h" + +// An ESP32 variant that takes its globals from RadioLibTarget.cpp but keeps its +// own radio_init(), as a downstream fork's variant may. Its definition must take +// precedence over the shared default, which is built into this binary as well; +// if the default were not weak, this suite would not link. + +mesh::Identity::Identity() { memset(pub_key, 0, sizeof(pub_key)); } +mesh::LocalIdentity::LocalIdentity(mesh::RNG* rng) { rng->random(pub_key, SEED_SIZE); } +void AutoDiscoverRTCClock::begin(TwoWire&) { target_calls.push_back("rtc_clock.begin(Wire)"); } +uint32_t AutoDiscoverRTCClock::getCurrentTime() { return _fallback->getCurrentTime(); } +void AutoDiscoverRTCClock::setCurrentTime(uint32_t time) { _fallback->setCurrentTime(time); } + +TestBoard board; + +bool radio_init() { + target_calls.push_back("variant radio_init()"); + return false; +} + +namespace { + +TEST(VariantTargetEsp32Override, VariantRadioInitTakesPrecedence) { + target_calls.clear(); + EXPECT_FALSE(radio_init()); + std::vector expected = {"variant radio_init()"}; + EXPECT_EQ(expected, target_calls); + EXPECT_EQ(0, static_cast(radio_driver.wrapped_radio())->std_init_calls); +} + +} // namespace + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/test_variant_target_globals/test_variant_target_globals.cpp b/test/test_variant_target_globals/test_variant_target_globals.cpp new file mode 100644 index 0000000000..2aecd2beff --- /dev/null +++ b/test/test_variant_target_globals/test_variant_target_globals.cpp @@ -0,0 +1,123 @@ +#include + +#include + +#include +#include +#include "target.h" + +// The radio, wrapper and RTC globals of a variant's target.cpp, pinned on the +// host: which RadioLib Module constructor the radio is built with (pins and SPI +// bus), what radio_driver wraps, and which clock rtc_clock falls back to. See +// docs/refactoring/0011-variant-target.md, "Cut D". + +// Stand-ins for src/Identity.cpp (Ed25519) and for the out-of-line members of +// AutoDiscoverRTCClock (the RTC chip libraries). The real getCurrentTime() and +// setCurrentTime() use the fallback clock when no RTC chip answered, which is +// the case these tests look at; begin() is recorded as the variant stand-in's +// RTC clock does. +mesh::Identity::Identity() { memset(pub_key, 0, sizeof(pub_key)); } +mesh::LocalIdentity::LocalIdentity(mesh::RNG* rng) { rng->random(pub_key, SEED_SIZE); } +void AutoDiscoverRTCClock::begin(TwoWire& wire) { + target_calls.push_back(&wire == &Wire ? "rtc_clock.begin(Wire)" : "rtc_clock.begin(other)"); +} +uint32_t AutoDiscoverRTCClock::getCurrentTime() { return _fallback->getCurrentTime(); } +void AutoDiscoverRTCClock::setCurrentTime(uint32_t time) { _fallback->setCurrentTime(time); } + +TestBoard board; + +// No target.h declares the fallback clock; the test needs it to see where +// rtc_clock falls back to. +extern VolatileRTCClock fallback_clock; + +// The same block once more, as the reference the cases are checked against on +// every commit, whatever defines the globals above. +namespace copy { +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); + +WRAPPER_CLASS radio_driver(radio, board); + +VolatileRTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); +} // namespace copy + +namespace { + +struct Globals { + const char* name; + TestRadioWrapper* driver; + AutoDiscoverRTCClock* rtc; + VolatileRTCClock* fallback; +}; + +std::string name_of(const ::testing::TestParamInfo& info) { return info.param.name; } + +class RadioGlobals : public ::testing::TestWithParam { +protected: + TestRadio* radio() { return static_cast(GetParam().driver->wrapped_radio()); } +}; + +TEST_P(RadioGlobals, RadioIsBuiltFromAModule) { + ASSERT_NE(nullptr, radio()); + EXPECT_NE(nullptr, radio()->module); +} + +TEST_P(RadioGlobals, ModuleHasTheBoardPinsInSx126xOrder) { + ASSERT_NE(nullptr, radio()->module); + EXPECT_EQ((uint32_t)P_LORA_NSS, radio()->module->cs); + EXPECT_EQ((uint32_t)P_LORA_DIO_1, radio()->module->irq); + EXPECT_EQ((uint32_t)P_LORA_RESET, radio()->module->rst); + EXPECT_EQ((uint32_t)P_LORA_BUSY, radio()->module->gpio); +} + +TEST_P(RadioGlobals, ModuleIsOnTheDefaultSpiBusPassedExplicitly) { + // Passed, not left to RadioLib: with the bus as argument RadioLib does not + // start it itself, std_init() does. + ASSERT_NE(nullptr, radio()->module); + EXPECT_EQ(&SPI, radio()->module->spi); +} + +TEST_P(RadioGlobals, DriverWrapsTheBoard) { + EXPECT_EQ(&board, GetParam().driver->wrapped_board()); +} + +TEST_P(RadioGlobals, RtcClockFallsBackToTheFallbackClock) { + GetParam().fallback->setCurrentTime(1234567); + EXPECT_EQ(1234567u, GetParam().rtc->getCurrentTime()); + GetParam().rtc->setCurrentTime(7654321); + EXPECT_EQ(7654321u, GetParam().fallback->getCurrentTime()); +} + +TEST_P(RadioGlobals, FallbackClockCountsMillisWhenTheRtcClockTicks) { + // What VolatileRTCClock does, and AutoDiscoverRTCClock::tick() forwards to it. + GetParam().fallback->setCurrentTime(1000); + g_mock_millis += 4000; + GetParam().rtc->tick(); + EXPECT_EQ(1004u, GetParam().fallback->getCurrentTime()); +} + +INSTANTIATE_TEST_SUITE_P(Copy, RadioGlobals, + ::testing::Values(Globals{"Copy", ©::radio_driver, ©::rtc_clock, ©::fallback_clock}), name_of); + +// The globals the variant gets, whoever defines them. +INSTANTIATE_TEST_SUITE_P(Variant, RadioGlobals, + ::testing::Values(Globals{"Variant", &radio_driver, &rtc_clock, &fallback_clock}), name_of); + +TEST(RadioGlobalsBoot, RadioInitStartsTheRtcThenTheWrappedRadioOnSpi) { + // Cut C's shared radio_init() on these globals: the boot path of the 31. + target_calls.clear(); + TestRadio* r = static_cast(radio_driver.wrapped_radio()); + r->std_init_calls = 0; + r->std_init_result = true; + EXPECT_TRUE(radio_init()); + std::vector expected = {"rtc_clock.begin(Wire)", "std_init(&SPI)"}; + EXPECT_EQ(expected, target_calls); + EXPECT_EQ(1, r->std_init_calls); +} + +} // namespace + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/refactoring/variant_target_globals.py b/tools/refactoring/variant_target_globals.py new file mode 100644 index 0000000000..ca70492a7e --- /dev/null +++ b/tools/refactoring/variant_target_globals.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 +"""Inventory of the radio, wrapper and RTC globals in the variants' target.cpp. + +Used for cut D of step 11 of the refactoring series +(docs/refactoring/0011-variant-target.md). Python 3 standard library plus the +`pio` command; run from the repository root: + + python3 tools/refactoring/variant_target_globals.py [--detail] + +For every variants/*/target.cpp it extracts the "radio block": the declarations +of the SPI object, `radio`, `radio_driver`, `fallback_clock` and `rtc_clock`, +together with the preprocessor lines around them, from the first of those lines +to the last. Blocks are compared normalized (comments and white space removed) +and grouped. For each group it reports the variants, their firmware environments +(an environment belongs to a variant when its build_src_filter names +variants/), the platforms and whether the block is contiguous (nothing but +those declarations and preprocessor lines between the first and the last). +It then does the same for the bodies of radio_init(), and lists for every +variant which of `radio`, `spi` and `fallback_clock` its target.cpp still names +once the radio block and a radio_init() body that a shared default can take over +are gone (the variants that name none can take their globals from shared code). +""" + +import collections +import glob +import json +import re +import subprocess +import sys + +DECL = re.compile( + r"^\s*(?:static\s+)?(?:" + r"SPIClass\s+\w+|" + r"RADIO_CLASS\s+radio\b|" + r"WRAPPER_CLASS\s+radio_driver\b|" + r"\w*RTCClock\s+fallback_clock\b|" + r"\w*RTCClock\s+rtc_clock\b)" +) +PREPROC = re.compile(r"^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b") + + +def strip_comments(text): + text = re.sub(r"/\*.*?\*/", "", text, flags=re.S) + return re.sub(r"//[^\n]*", "", text) + + +def norm(line): + return re.sub(r"\s+", " ", line).strip() + + +def radio_block(src): + """(block lines, contiguous, depth problem) of the radio declarations.""" + lines = [norm(l) for l in strip_comments(src).splitlines()] + lines = [l for l in lines if l] + idx = [i for i, l in enumerate(lines) if DECL.match(l)] + if not idx: + return [], True, [] + first, last = idx[0], idx[-1] + # widen to the enclosing preprocessor lines that open/close inside the block + depth, lo = 0, first + for i in range(first, last + 1): + m = PREPROC.match(lines[i]) + if m and m.group(1) in ("if", "ifdef", "ifndef"): + depth += 1 + elif m and m.group(1) == "endif": + depth -= 1 + hi = last + while depth > 0 and hi + 1 < len(lines): + hi += 1 + m = PREPROC.match(lines[hi]) + if m and m.group(1) in ("if", "ifdef", "ifndef"): + depth += 1 + elif m and m.group(1) == "endif": + depth -= 1 + while depth < 0 and lo > 0: + lo -= 1 + m = PREPROC.match(lines[lo]) + if m and m.group(1) in ("if", "ifdef", "ifndef"): + depth += 1 + elif m and m.group(1) == "endif": + depth -= 1 + block = lines[lo:hi + 1] + foreign = [l for l in block if not DECL.match(l) and not PREPROC.match(l)] + # preprocessor context the first declaration sits in (unclosed #if before it) + ctx = [] + for l in lines[:lo]: + m = PREPROC.match(l) + if m and m.group(1) in ("if", "ifdef", "ifndef"): + ctx.append(l) + elif m and m.group(1) == "endif" and ctx: + ctx.pop() + return block, not foreign, ctx + + +def function_body(src, name): + src = strip_comments(src) + m = re.search(r"^[^\n;]*\b" + re.escape(name) + r"\s*\(\s*\)\s*\{", src, re.M) + if m is None: + return None + depth, i = 1, m.end() + while depth: + depth += (src[i] == "{") - (src[i] == "}") + i += 1 + return norm(src[m.end():i - 1]) + + +# radio_init() bodies a shared default can take over: none (cut C's nRF52 +# default), or the two ESP32 bodies that differ only where P_LORA_SCLK is +# undefined, which their variants' blocks never are. +SHAREABLE_INIT = { + None, + "fallback_clock.begin(); rtc_clock.begin(Wire); #if defined(P_LORA_SCLK) " + "return radio.std_init(&spi); #else return radio.std_init(); #endif", + "fallback_clock.begin(); rtc_clock.begin(Wire); return radio.std_init(&spi);", +} + + +def remaining_refs(src, init_body): + """Names of the radio block target.cpp still uses outside the block.""" + src = strip_comments(src) + rest = "\n".join(l for l in src.splitlines() if not DECL.match(norm(l))) + if init_body in SHAREABLE_INIT: + m = re.search(r"bool\s+radio_init\s*\(\s*\)\s*\{", rest) + if m: + depth, i = 1, m.end() + while depth: + depth += (rest[i] == "{") - (rest[i] == "}") + i += 1 + rest = rest[:m.start()] + rest[i:] + return sorted(set(re.findall(r"\b(radio|spi|fallback_clock)\b", rest))) + + +def environments(): + out = subprocess.run(["pio", "project", "config", "--json-output"], + capture_output=True, text=True, check=True).stdout + envs = {} + for section, items in json.loads(out): + if not section.startswith("env:"): + continue + kv = dict(items) + flags = " ".join(kv.get("build_flags", [])) + envs[section[4:]] = { + "src": " ".join(kv.get("build_src_filter", [])), + "platform": kv.get("platform", ""), + "flags": flags, + } + return envs + + +def platform_name(p): + if "espressif32" in p: + return "ESP32" + if "nordicnrf52" in p: + return "nRF52" + if "raspberrypi" in p: + return "RP2040" + if "ststm32" in p: + return "STM32" + return p or "native" + + +def flag(flags, name): + m = re.search(r"-D\s*" + name + r"(?:=(\S+))?", flags) + return None if m is None else (m.group(1) or "1") + + +def main(): + detail = "--detail" in sys.argv + envs = environments() + variants = sorted(p.split("/")[1] for p in glob.glob("variants/*/target.cpp")) + info = {} + for v in variants: + src = open(f"variants/{v}/target.cpp", encoding="utf-8", errors="replace").read() + block, contiguous, ctx = radio_block(src) + mine = {e: d for e, d in envs.items() + if re.search(r"variants/" + re.escape(v) + r"(?:>|/)", d["src"])} + info[v] = { + "block": block, "contiguous": contiguous, "ctx": ctx, + "envs": mine, + "platforms": sorted({platform_name(d["platform"]) for d in mine.values()}), + "sclk": sorted({flag(d["flags"], "P_LORA_SCLK") is not None for d in mine.values()}), + "wrapper": sorted({flag(d["flags"], "WRAPPER_CLASS") or "-" for d in mine.values()}), + "radio_init": function_body(src, "radio_init"), + } + info[v]["refs"] = remaining_refs(src, info[v]["radio_init"]) + + print(f"target.cpp: {len(variants)}, firmware environments: " + f"{sum(len(i['envs']) for i in info.values())} of {len(envs)}") + print() + print("== radio blocks (normalized) ==") + groups = collections.defaultdict(list) + for v, i in info.items(): + groups[tuple(i["block"])].append(v) + for block, vs in sorted(groups.items(), key=lambda kv: -len(kv[1])): + nenv = sum(len(info[v]["envs"]) for v in vs) + plats = sorted({p for v in vs for p in info[v]["platforms"]}) + cont = sum(info[v]["contiguous"] for v in vs) + ctx = sorted({" / ".join(info[v]["ctx"]) for v in vs if info[v]["ctx"]}) + sclk = sorted({str(s) for v in vs for s in info[v]["sclk"]}) + print(f"-- {len(vs)} variants, {nenv} envs, {','.join(plats)}, contiguous {cont}/{len(vs)}," + f" P_LORA_SCLK in envs: {'/'.join(sclk)}" + (f", inside: {ctx}" if ctx else "")) + for l in block: + print(f" {l}") + print(f" variants: {', '.join(vs)}") + print() + print("== radio_init() bodies (normalized), by platform ==") + rg = collections.defaultdict(list) + for v, i in info.items(): + if i["radio_init"] is not None: + rg[(",".join(i["platforms"]), i["radio_init"])].append(v) + for (plat, body), vs in sorted(rg.items(), key=lambda kv: (kv[0][0], -len(kv[1]))): + nenv = sum(len(info[v]["envs"]) for v in vs) + print(f"-- {plat}: {len(vs)} variants, {nenv} envs") + print(f" {body}") + print(f" variants: {', '.join(vs)}") + without = [v for v, i in info.items() if i["radio_init"] is None] + print(f"-- without own radio_init() (cut C default or none): {len(without)}") + print() + print("== variants whose target.cpp names no radio global once block and shareable radio_init() are gone ==") + cand = collections.defaultdict(list) + for v, i in info.items(): + if not i["refs"] and i["block"] and "radio_driver" in " ".join(i["block"]): + cand[(",".join(i["platforms"]), i["radio_init"] is None)].append(v) + for (plat, default), vs in sorted(cand.items()): + nenv = sum(len(info[v]["envs"]) for v in vs) + how = "radio_init() already shared" if default else "own radio_init() shareable" + print(f"-- {plat}, {how}: {len(vs)} variants, {nenv} envs") + print(f" {', '.join(vs)}") + rest = [f"{v} ({'/'.join(i['refs'])})" for v, i in info.items() if i["refs"]] + print(f"-- still naming them: {len(rest)}: {', '.join(rest)}") + if detail: + print() + for v, i in info.items(): + print(v, i["platforms"], len(i["envs"]), "sclk", i["sclk"], i["wrapper"]) + + +if __name__ == "__main__": + main() diff --git a/variants/gat562_30s_mesh_kit/target.cpp b/variants/gat562_30s_mesh_kit/target.cpp index 11ee09f07a..c635aad532 100644 --- a/variants/gat562_30s_mesh_kit/target.cpp +++ b/variants/gat562_30s_mesh_kit/target.cpp @@ -18,13 +18,6 @@ GAT56230SMeshKitBoard board; #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/gat562_30s_mesh_kit/target.h b/variants/gat562_30s_mesh_kit/target.h index d526a5d037..eef1b5b1e5 100644 --- a/variants/gat562_30s_mesh_kit/target.h +++ b/variants/gat562_30s_mesh_kit/target.h @@ -19,6 +19,7 @@ #endif extern GAT56230SMeshKitBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/gat562_mesh_evb_pro/target.cpp b/variants/gat562_mesh_evb_pro/target.cpp index d1b021c8cf..b198c5e294 100644 --- a/variants/gat562_mesh_evb_pro/target.cpp +++ b/variants/gat562_mesh_evb_pro/target.cpp @@ -17,13 +17,6 @@ GAT562EVBProBoard board; #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/gat562_mesh_evb_pro/target.h b/variants/gat562_mesh_evb_pro/target.h index 9111704fca..d01a95ef84 100644 --- a/variants/gat562_mesh_evb_pro/target.h +++ b/variants/gat562_mesh_evb_pro/target.h @@ -18,6 +18,7 @@ #endif extern GAT562EVBProBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/gat562_mesh_tracker_pro/target.cpp b/variants/gat562_mesh_tracker_pro/target.cpp index ad85c842f2..57f7fef3e2 100644 --- a/variants/gat562_mesh_tracker_pro/target.cpp +++ b/variants/gat562_mesh_tracker_pro/target.cpp @@ -18,13 +18,6 @@ GAT562MeshTrackerProBoard board; #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/gat562_mesh_tracker_pro/target.h b/variants/gat562_mesh_tracker_pro/target.h index 0d3b7d76ea..6627d11052 100644 --- a/variants/gat562_mesh_tracker_pro/target.h +++ b/variants/gat562_mesh_tracker_pro/target.h @@ -19,6 +19,7 @@ #endif extern GAT562MeshTrackerProBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/gat562_mesh_watch13/target.cpp b/variants/gat562_mesh_watch13/target.cpp index dddd24485a..b996b02101 100644 --- a/variants/gat562_mesh_watch13/target.cpp +++ b/variants/gat562_mesh_watch13/target.cpp @@ -15,11 +15,5 @@ GAT56MeshWatch13Board board; #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); EnvironmentSensorManager sensors; diff --git a/variants/gat562_mesh_watch13/target.h b/variants/gat562_mesh_watch13/target.h index 9ed5cda717..1932114be6 100644 --- a/variants/gat562_mesh_watch13/target.h +++ b/variants/gat562_mesh_watch13/target.h @@ -20,6 +20,7 @@ #endif extern GAT56MeshWatch13Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/generic-e22/target.cpp b/variants/generic-e22/target.cpp index 0e7e69d0a3..d76285b224 100644 --- a/variants/generic-e22/target.cpp +++ b/variants/generic-e22/target.cpp @@ -3,26 +3,4 @@ ESP32Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); SensorManager sensors; - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - - #if defined(P_LORA_SCLK) - return radio.std_init(&spi); - #else - return radio.std_init(); - #endif -} diff --git a/variants/generic-e22/target.h b/variants/generic-e22/target.h index 16612f67b6..a8c7749428 100644 --- a/variants/generic-e22/target.h +++ b/variants/generic-e22/target.h @@ -10,6 +10,7 @@ #include extern ESP32Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/heltec_e213/target.cpp b/variants/heltec_e213/target.cpp index 12e22b30a8..a836c1f5c6 100644 --- a/variants/heltec_e213/target.cpp +++ b/variants/heltec_e213/target.cpp @@ -3,32 +3,9 @@ HeltecE213Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi(FSPI); - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display(&board.periph_power); MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_e213/target.h b/variants/heltec_e213/target.h index 6f2c291bb8..26fc647e0a 100644 --- a/variants/heltec_e213/target.h +++ b/variants/heltec_e213/target.h @@ -13,6 +13,8 @@ #endif extern HeltecE213Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp +#define P_LORA_SPI_HOST FSPI // the radio's own SPI bus extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/heltec_e290/target.cpp b/variants/heltec_e290/target.cpp index bcfdbcdba2..8612d534df 100644 --- a/variants/heltec_e290/target.cpp +++ b/variants/heltec_e290/target.cpp @@ -3,32 +3,9 @@ HeltecE290Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi(FSPI); - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display(&board.periph_power); MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_e290/target.h b/variants/heltec_e290/target.h index d78521fcfb..26d807cdee 100644 --- a/variants/heltec_e290/target.h +++ b/variants/heltec_e290/target.h @@ -13,6 +13,8 @@ #endif extern HeltecE290Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp +#define P_LORA_SPI_HOST FSPI // the radio's own SPI bus extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/heltec_mesh_solar/target.cpp b/variants/heltec_mesh_solar/target.cpp index c89eea6b80..10110b0c17 100644 --- a/variants/heltec_mesh_solar/target.cpp +++ b/variants/heltec_mesh_solar/target.cpp @@ -6,12 +6,6 @@ MeshSolarBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); SolarSensorManager sensors = SolarSensorManager(nmea); SolarExternalWatchdog external_watchdog; diff --git a/variants/heltec_mesh_solar/target.h b/variants/heltec_mesh_solar/target.h index 8e13a9601c..48261a9eb0 100644 --- a/variants/heltec_mesh_solar/target.h +++ b/variants/heltec_mesh_solar/target.h @@ -41,6 +41,7 @@ class SolarExternalWatchdog : public ExternalWatchdogManager { }; extern MeshSolarBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SolarSensorManager sensors; diff --git a/variants/heltec_rc32/target.cpp b/variants/heltec_rc32/target.cpp index be6d73b87b..e47fb35e81 100644 --- a/variants/heltec_rc32/target.cpp +++ b/variants/heltec_rc32/target.cpp @@ -6,18 +6,6 @@ HeltecRC32Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi(FSPI); - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, PIN_GPS_RESET, PIN_GPS_EN); @@ -34,14 +22,3 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); RotaryInput& rotary_input = rotaryInputImpl; #endif #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_rc32/target.h b/variants/heltec_rc32/target.h index 04cb6d94a4..34d2c66f11 100644 --- a/variants/heltec_rc32/target.h +++ b/variants/heltec_rc32/target.h @@ -21,6 +21,8 @@ #endif extern HeltecRC32Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp +#define P_LORA_SPI_HOST FSPI // the radio's own SPI bus extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_t096/target.cpp b/variants/heltec_t096/target.cpp index 34452dfbf3..f84fd9efd9 100644 --- a/variants/heltec_t096/target.cpp +++ b/variants/heltec_t096/target.cpp @@ -9,17 +9,6 @@ T096Board board; -#if defined(P_LORA_SCLK) -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); -#else -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power); diff --git a/variants/heltec_t096/target.h b/variants/heltec_t096/target.h index 137d8db5ec..297db2ca15 100644 --- a/variants/heltec_t096/target.h +++ b/variants/heltec_t096/target.h @@ -17,6 +17,7 @@ #endif extern T096Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_t1/target.cpp b/variants/heltec_t1/target.cpp index cc372637d9..1c76573ee2 100644 --- a/variants/heltec_t1/target.cpp +++ b/variants/heltec_t1/target.cpp @@ -9,17 +9,6 @@ T1Board board; -#if defined(P_LORA_SCLK) -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); -#else -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/heltec_t1/target.h b/variants/heltec_t1/target.h index ffd9434fac..6868e9790a 100644 --- a/variants/heltec_t1/target.h +++ b/variants/heltec_t1/target.h @@ -17,6 +17,7 @@ #endif extern T1Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_t114/target.cpp b/variants/heltec_t114/target.cpp index 625812d2d5..ab5787fb22 100644 --- a/variants/heltec_t114/target.cpp +++ b/variants/heltec_t114/target.cpp @@ -9,17 +9,6 @@ T114Board board; -#if defined(P_LORA_SCLK) -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); -#else -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/heltec_t114/target.h b/variants/heltec_t114/target.h index 5aac84dbe2..8f9510a335 100644 --- a/variants/heltec_t114/target.h +++ b/variants/heltec_t114/target.h @@ -19,6 +19,7 @@ #endif extern T114Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_t190/target.cpp b/variants/heltec_t190/target.cpp index 3c32f047eb..7fcc8a8dd4 100644 --- a/variants/heltec_t190/target.cpp +++ b/variants/heltec_t190/target.cpp @@ -3,32 +3,9 @@ HeltecT190Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi(FSPI); - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_t190/target.h b/variants/heltec_t190/target.h index cde63220a8..597a6a91e9 100644 --- a/variants/heltec_t190/target.h +++ b/variants/heltec_t190/target.h @@ -13,6 +13,8 @@ #endif extern HeltecT190Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp +#define P_LORA_SPI_HOST FSPI // the radio's own SPI bus extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/heltec_tower_v2/target.cpp b/variants/heltec_tower_v2/target.cpp index 54c2621e80..647a774b0b 100644 --- a/variants/heltec_tower_v2/target.cpp +++ b/variants/heltec_tower_v2/target.cpp @@ -6,12 +6,6 @@ HeltecTowerV2Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); TowerV2ExternalWatchdog external_watchdog; diff --git a/variants/heltec_tower_v2/target.h b/variants/heltec_tower_v2/target.h index 0b9de40ca4..f61ab0d5c9 100644 --- a/variants/heltec_tower_v2/target.h +++ b/variants/heltec_tower_v2/target.h @@ -25,6 +25,7 @@ class TowerV2ExternalWatchdog : public ExternalWatchdogManager { }; extern HeltecTowerV2Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_tracker/target.cpp b/variants/heltec_tracker/target.cpp index 7d88a33210..2fbe32740b 100644 --- a/variants/heltec_tracker/target.cpp +++ b/variants/heltec_tracker/target.cpp @@ -6,17 +6,6 @@ HeltecV3Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); // GPS_EN (GPIO35) drives N-ch MOSFET → P-ch high-side switch; GPS_RESET (GPIO36) active LOW MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power); HWTSensorManager sensors = HWTSensorManager(nmea); @@ -26,18 +15,6 @@ HWTSensorManager sensors = HWTSensorManager(nmea); MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif - -} - void HWTSensorManager::start_gps() { if (!gps_active) { _location->begin(); // Claims periph_power via RefCountedDigitalPin diff --git a/variants/heltec_tracker/target.h b/variants/heltec_tracker/target.h index 2931eda816..16578dca7c 100644 --- a/variants/heltec_tracker/target.h +++ b/variants/heltec_tracker/target.h @@ -32,6 +32,7 @@ class HWTSensorManager : public SensorManager { }; extern HeltecV3Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern HWTSensorManager sensors; diff --git a/variants/heltec_tracker_v2/target.cpp b/variants/heltec_tracker_v2/target.cpp index 6d04291366..6498a1858b 100644 --- a/variants/heltec_tracker_v2/target.cpp +++ b/variants/heltec_tracker_v2/target.cpp @@ -3,18 +3,6 @@ HeltecTrackerV2Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power); @@ -27,14 +15,3 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); DISPLAY_CLASS display(&board.periph_power); // peripheral power pin is shared MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_tracker_v2/target.h b/variants/heltec_tracker_v2/target.h index 240d9d4c58..e37da63405 100644 --- a/variants/heltec_tracker_v2/target.h +++ b/variants/heltec_tracker_v2/target.h @@ -14,6 +14,7 @@ #endif extern HeltecTrackerV2Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_v2/target.cpp b/variants/heltec_v2/target.cpp index 5698f4095c..1a1de17d18 100644 --- a/variants/heltec_v2/target.cpp +++ b/variants/heltec_v2/target.cpp @@ -3,31 +3,9 @@ HeltecV2Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_v2/target.h b/variants/heltec_v2/target.h index cdffc18a17..0cf2235204 100644 --- a/variants/heltec_v2/target.h +++ b/variants/heltec_v2/target.h @@ -13,6 +13,7 @@ #endif extern HeltecV2Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/heltec_v3/target.cpp b/variants/heltec_v3/target.cpp index b467bd98c5..9c6f5b1f4e 100644 --- a/variants/heltec_v3/target.cpp +++ b/variants/heltec_v3/target.cpp @@ -3,18 +3,6 @@ HeltecV3Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); @@ -27,14 +15,3 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_v3/target.h b/variants/heltec_v3/target.h index 2944b38435..1743af20e0 100644 --- a/variants/heltec_v3/target.h +++ b/variants/heltec_v3/target.h @@ -14,6 +14,7 @@ #endif extern HeltecV3Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_v4/target.cpp b/variants/heltec_v4/target.cpp index 9f163e1a8d..a29bd70daa 100644 --- a/variants/heltec_v4/target.cpp +++ b/variants/heltec_v4/target.cpp @@ -3,18 +3,6 @@ HeltecV4Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); @@ -27,14 +15,3 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); DISPLAY_CLASS display(NULL); MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_v4/target.h b/variants/heltec_v4/target.h index 5d668186b2..dfc446de52 100644 --- a/variants/heltec_v4/target.h +++ b/variants/heltec_v4/target.h @@ -18,6 +18,7 @@ #endif extern HeltecV4Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_v4_r8/target.cpp b/variants/heltec_v4_r8/target.cpp index 2f5390c596..8d18c3ce05 100644 --- a/variants/heltec_v4_r8/target.cpp +++ b/variants/heltec_v4_r8/target.cpp @@ -3,18 +3,6 @@ HeltecV4R8Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power); @@ -27,14 +15,3 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); DISPLAY_CLASS display(&board.periph_power); MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_v4_r8/target.h b/variants/heltec_v4_r8/target.h index 2d1d7a5bb4..a83052f300 100644 --- a/variants/heltec_v4_r8/target.h +++ b/variants/heltec_v4_r8/target.h @@ -18,6 +18,7 @@ #endif extern HeltecV4R8Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/heltec_wireless_paper/target.cpp b/variants/heltec_wireless_paper/target.cpp index 91ee526f11..0373576cd6 100644 --- a/variants/heltec_wireless_paper/target.cpp +++ b/variants/heltec_wireless_paper/target.cpp @@ -3,31 +3,9 @@ HeltecWirelessPaperBoard board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/heltec_wireless_paper/target.h b/variants/heltec_wireless_paper/target.h index 7206678181..b6e77d2b91 100644 --- a/variants/heltec_wireless_paper/target.h +++ b/variants/heltec_wireless_paper/target.h @@ -19,6 +19,7 @@ class HeltecWirelessPaperBoard : public HeltecV3Board { #endif extern HeltecWirelessPaperBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/ikoka_handheld_nrf/target.cpp b/variants/ikoka_handheld_nrf/target.cpp index 6f658f8319..1de48ae35b 100644 --- a/variants/ikoka_handheld_nrf/target.cpp +++ b/variants/ikoka_handheld_nrf/target.cpp @@ -4,13 +4,6 @@ IkokaNrf52Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS diff --git a/variants/ikoka_handheld_nrf/target.h b/variants/ikoka_handheld_nrf/target.h index 18f7c9c5ee..f11dca027c 100644 --- a/variants/ikoka_handheld_nrf/target.h +++ b/variants/ikoka_handheld_nrf/target.h @@ -18,6 +18,7 @@ extern IkokaNrf52Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/ikoka_nano_nrf/target.cpp b/variants/ikoka_nano_nrf/target.cpp index 85177c24a0..cd329c78e1 100644 --- a/variants/ikoka_nano_nrf/target.cpp +++ b/variants/ikoka_nano_nrf/target.cpp @@ -9,10 +9,4 @@ IkokaNanoNRFBoard board; // MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); EnvironmentSensorManager sensors; diff --git a/variants/ikoka_nano_nrf/target.h b/variants/ikoka_nano_nrf/target.h index 30ee5cb69e..83b8d5e0d6 100644 --- a/variants/ikoka_nano_nrf/target.h +++ b/variants/ikoka_nano_nrf/target.h @@ -17,6 +17,7 @@ #endif extern IkokaNanoNRFBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/ikoka_stick_nrf/target.cpp b/variants/ikoka_stick_nrf/target.cpp index c48f677de6..5f4607a7fb 100644 --- a/variants/ikoka_stick_nrf/target.cpp +++ b/variants/ikoka_stick_nrf/target.cpp @@ -9,10 +9,4 @@ IkokaStickNRFBoard board; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); EnvironmentSensorManager sensors; diff --git a/variants/ikoka_stick_nrf/target.h b/variants/ikoka_stick_nrf/target.h index 46b05e8b2e..97f7984b20 100644 --- a/variants/ikoka_stick_nrf/target.h +++ b/variants/ikoka_stick_nrf/target.h @@ -17,6 +17,7 @@ #endif extern IkokaStickNRFBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/keepteen_lt1/target.cpp b/variants/keepteen_lt1/target.cpp index 396c2fa711..a6bf135bca 100644 --- a/variants/keepteen_lt1/target.cpp +++ b/variants/keepteen_lt1/target.cpp @@ -4,12 +4,6 @@ KeepteenLT1Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/keepteen_lt1/target.h b/variants/keepteen_lt1/target.h index 5b73bb6684..151cea2b2c 100644 --- a/variants/keepteen_lt1/target.h +++ b/variants/keepteen_lt1/target.h @@ -14,6 +14,7 @@ #include extern KeepteenLT1Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/lilygo_t3s3/target.cpp b/variants/lilygo_t3s3/target.cpp index 2679f6f914..6dcf5878d5 100644 --- a/variants/lilygo_t3s3/target.cpp +++ b/variants/lilygo_t3s3/target.cpp @@ -3,12 +3,6 @@ ESP32Board board; -static SPIClass spi; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); SensorManager sensors; #ifdef DISPLAY_CLASS @@ -19,10 +13,3 @@ SensorManager sensors; #ifndef LORA_CR #define LORA_CR 5 #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - - return radio.std_init(&spi); -} diff --git a/variants/lilygo_t3s3/target.h b/variants/lilygo_t3s3/target.h index 965cdd1a2e..490f4654f8 100644 --- a/variants/lilygo_t3s3/target.h +++ b/variants/lilygo_t3s3/target.h @@ -13,6 +13,7 @@ #endif extern ESP32Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/lilygo_t_impulse_plus/target.cpp b/variants/lilygo_t_impulse_plus/target.cpp index cb34ae6e83..0aa8b3b75d 100644 --- a/variants/lilygo_t_impulse_plus/target.cpp +++ b/variants/lilygo_t_impulse_plus/target.cpp @@ -5,13 +5,6 @@ TImpulsePlusBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/lilygo_t_impulse_plus/target.h b/variants/lilygo_t_impulse_plus/target.h index ff168fbedf..e52f12c91b 100644 --- a/variants/lilygo_t_impulse_plus/target.h +++ b/variants/lilygo_t_impulse_plus/target.h @@ -14,6 +14,7 @@ #endif extern TImpulsePlusBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/lilygo_tbeam_SX1262/target.cpp b/variants/lilygo_tbeam_SX1262/target.cpp index d5ea9ad1f8..25baf47ece 100644 --- a/variants/lilygo_tbeam_SX1262/target.cpp +++ b/variants/lilygo_tbeam_SX1262/target.cpp @@ -3,18 +3,6 @@ TBeamBoard board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); @@ -27,9 +15,3 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - return radio.std_init(&spi); -} diff --git a/variants/lilygo_tbeam_SX1262/target.h b/variants/lilygo_tbeam_SX1262/target.h index c532a73af9..2674694f31 100644 --- a/variants/lilygo_tbeam_SX1262/target.h +++ b/variants/lilygo_tbeam_SX1262/target.h @@ -13,6 +13,7 @@ #endif extern TBeamBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/lilygo_tbeam_SX1276/target.cpp b/variants/lilygo_tbeam_SX1276/target.cpp index 35b2c0af3f..feb4c5fdfb 100644 --- a/variants/lilygo_tbeam_SX1276/target.cpp +++ b/variants/lilygo_tbeam_SX1276/target.cpp @@ -3,18 +3,6 @@ LilygoTBeamSX1276Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); @@ -27,14 +15,3 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/lilygo_tbeam_SX1276/target.h b/variants/lilygo_tbeam_SX1276/target.h index 0d56f88f8b..3184c2b8e6 100644 --- a/variants/lilygo_tbeam_SX1276/target.h +++ b/variants/lilygo_tbeam_SX1276/target.h @@ -13,6 +13,7 @@ #endif extern LilygoTBeamSX1276Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/lilygo_techo/target.cpp b/variants/lilygo_techo/target.cpp index e3f797e5c9..e1451599af 100644 --- a/variants/lilygo_techo/target.cpp +++ b/variants/lilygo_techo/target.cpp @@ -5,13 +5,6 @@ TechoBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/lilygo_techo/target.h b/variants/lilygo_techo/target.h index 2b8a1783f0..1388853e1e 100644 --- a/variants/lilygo_techo/target.h +++ b/variants/lilygo_techo/target.h @@ -15,6 +15,7 @@ #endif extern TechoBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/lilygo_techo_card/target.cpp b/variants/lilygo_techo_card/target.cpp index 15059da30f..637157982f 100644 --- a/variants/lilygo_techo_card/target.cpp +++ b/variants/lilygo_techo_card/target.cpp @@ -5,13 +5,6 @@ TechoCardBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/lilygo_techo_card/target.h b/variants/lilygo_techo_card/target.h index f394f7dafb..8a210b0479 100644 --- a/variants/lilygo_techo_card/target.h +++ b/variants/lilygo_techo_card/target.h @@ -15,6 +15,7 @@ #endif extern TechoCardBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/lilygo_techo_lite/target.cpp b/variants/lilygo_techo_lite/target.cpp index 6bff6ad95d..4d49d478fb 100644 --- a/variants/lilygo_techo_lite/target.cpp +++ b/variants/lilygo_techo_lite/target.cpp @@ -5,13 +5,6 @@ TechoBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/lilygo_techo_lite/target.h b/variants/lilygo_techo_lite/target.h index 2b8a1783f0..1388853e1e 100644 --- a/variants/lilygo_techo_lite/target.h +++ b/variants/lilygo_techo_lite/target.h @@ -15,6 +15,7 @@ #endif extern TechoBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/lilygo_tlora_c6/target.cpp b/variants/lilygo_tlora_c6/target.cpp index 02dfcd52a3..d76285b224 100644 --- a/variants/lilygo_tlora_c6/target.cpp +++ b/variants/lilygo_tlora_c6/target.cpp @@ -3,26 +3,4 @@ ESP32Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi(0); - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); SensorManager sensors; - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/lilygo_tlora_c6/target.h b/variants/lilygo_tlora_c6/target.h index 81e99ee3ab..1af86e66ae 100644 --- a/variants/lilygo_tlora_c6/target.h +++ b/variants/lilygo_tlora_c6/target.h @@ -9,6 +9,8 @@ #include extern ESP32Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp +#define P_LORA_SPI_HOST 0 // the radio's own SPI bus extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/lilygo_tlora_v2_1/target.cpp b/variants/lilygo_tlora_v2_1/target.cpp index 00ae597b84..3f43f6e1a9 100644 --- a/variants/lilygo_tlora_v2_1/target.cpp +++ b/variants/lilygo_tlora_v2_1/target.cpp @@ -3,27 +3,9 @@ LilyGoTLoraBoard board; -static SPIClass spi; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/lilygo_tlora_v2_1/target.h b/variants/lilygo_tlora_v2_1/target.h index fa954b329b..75de03a5e3 100644 --- a/variants/lilygo_tlora_v2_1/target.h +++ b/variants/lilygo_tlora_v2_1/target.h @@ -13,6 +13,7 @@ #endif extern LilyGoTLoraBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/meshadventurer/target.cpp b/variants/meshadventurer/target.cpp index 8241cac144..4a42b96590 100644 --- a/variants/meshadventurer/target.cpp +++ b/variants/meshadventurer/target.cpp @@ -6,12 +6,6 @@ MeshadventurerBoard board; -static SPIClass spi; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); MASensorManager sensors = MASensorManager(nmea); @@ -20,17 +14,6 @@ MASensorManager sensors = MASensorManager(nmea); MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} - void MASensorManager::start_gps() { if(!gps_active) { diff --git a/variants/meshadventurer/target.h b/variants/meshadventurer/target.h index 0749565d36..b051e1c80f 100644 --- a/variants/meshadventurer/target.h +++ b/variants/meshadventurer/target.h @@ -32,6 +32,7 @@ class MASensorManager : public SensorManager { }; extern MeshadventurerBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern MASensorManager sensors; diff --git a/variants/meshtiny/target.cpp b/variants/meshtiny/target.cpp index 179ed75d31..61726bf2ba 100644 --- a/variants/meshtiny/target.cpp +++ b/variants/meshtiny/target.cpp @@ -5,12 +5,6 @@ MeshtinyBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(); #ifdef DISPLAY_CLASS diff --git a/variants/meshtiny/target.h b/variants/meshtiny/target.h index 3987e18c29..3546d64521 100644 --- a/variants/meshtiny/target.h +++ b/variants/meshtiny/target.h @@ -14,6 +14,7 @@ #include extern MeshtinyBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/muziworks_r1_neo/target.cpp b/variants/muziworks_r1_neo/target.cpp index 401eab17b0..f9d82328ff 100644 --- a/variants/muziworks_r1_neo/target.cpp +++ b/variants/muziworks_r1_neo/target.cpp @@ -4,9 +4,6 @@ R1NeoBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); -WRAPPER_CLASS radio_driver(radio, board); - #ifdef DISPLAY_CLASS NullDisplayDriver display; #endif @@ -15,9 +12,6 @@ WRAPPER_CLASS radio_driver(radio, board); MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/muziworks_r1_neo/target.h b/variants/muziworks_r1_neo/target.h index 5bf3f26850..676a95ebda 100644 --- a/variants/muziworks_r1_neo/target.h +++ b/variants/muziworks_r1_neo/target.h @@ -9,6 +9,7 @@ #include extern R1NeoBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/nano_g2_ultra/target.cpp b/variants/nano_g2_ultra/target.cpp index 2e3c9c5622..c86ddc83dc 100644 --- a/variants/nano_g2_ultra/target.cpp +++ b/variants/nano_g2_ultra/target.cpp @@ -7,12 +7,6 @@ NanoG2Ultra board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); NanoG2UltraSensorManager sensors = NanoG2UltraSensorManager(nmea); diff --git a/variants/nano_g2_ultra/target.h b/variants/nano_g2_ultra/target.h index 5c6ebee11d..c34f9975df 100644 --- a/variants/nano_g2_ultra/target.h +++ b/variants/nano_g2_ultra/target.h @@ -33,6 +33,7 @@ class NanoG2UltraSensorManager : public SensorManager { }; extern NanoG2Ultra board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern NanoG2UltraSensorManager sensors; diff --git a/variants/nibble_screen_connect/target.cpp b/variants/nibble_screen_connect/target.cpp index 6609338e75..c46e511a83 100644 --- a/variants/nibble_screen_connect/target.cpp +++ b/variants/nibble_screen_connect/target.cpp @@ -3,12 +3,6 @@ ESP32Board board; -static SPIClass spi; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); SensorManager sensors; #ifdef DISPLAY_CLASS @@ -19,10 +13,3 @@ SensorManager sensors; #ifndef LORA_CR #define LORA_CR 5 #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - - return radio.std_init(&spi); -} diff --git a/variants/nibble_screen_connect/target.h b/variants/nibble_screen_connect/target.h index dcbcf8e1df..1b65464d20 100644 --- a/variants/nibble_screen_connect/target.h +++ b/variants/nibble_screen_connect/target.h @@ -13,6 +13,7 @@ #endif extern ESP32Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/nibble_zero_connect/target.cpp b/variants/nibble_zero_connect/target.cpp index 2679f6f914..6dcf5878d5 100644 --- a/variants/nibble_zero_connect/target.cpp +++ b/variants/nibble_zero_connect/target.cpp @@ -3,12 +3,6 @@ ESP32Board board; -static SPIClass spi; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); SensorManager sensors; #ifdef DISPLAY_CLASS @@ -19,10 +13,3 @@ SensorManager sensors; #ifndef LORA_CR #define LORA_CR 5 #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - - return radio.std_init(&spi); -} diff --git a/variants/nibble_zero_connect/target.h b/variants/nibble_zero_connect/target.h index 87c55f0f2e..24da363ec2 100644 --- a/variants/nibble_zero_connect/target.h +++ b/variants/nibble_zero_connect/target.h @@ -13,6 +13,7 @@ #endif extern ESP32Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/promicro/target.cpp b/variants/promicro/target.cpp index a476bf7e48..1a03e83824 100644 --- a/variants/promicro/target.cpp +++ b/variants/promicro/target.cpp @@ -4,12 +4,6 @@ PromicroBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/promicro/target.h b/variants/promicro/target.h index e577ab4e97..35f0bb6251 100644 --- a/variants/promicro/target.h +++ b/variants/promicro/target.h @@ -14,6 +14,7 @@ #include extern PromicroBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/rak3112/target.cpp b/variants/rak3112/target.cpp index 214426d474..42076afc8e 100644 --- a/variants/rak3112/target.cpp +++ b/variants/rak3112/target.cpp @@ -3,18 +3,6 @@ RAK3112Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); @@ -27,14 +15,3 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/rak3112/target.h b/variants/rak3112/target.h index f93cd53996..4388532e45 100644 --- a/variants/rak3112/target.h +++ b/variants/rak3112/target.h @@ -14,6 +14,7 @@ #endif extern RAK3112Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/rak3401/target.cpp b/variants/rak3401/target.cpp index a1a7358857..ff8af0a137 100644 --- a/variants/rak3401/target.cpp +++ b/variants/rak3401/target.cpp @@ -17,13 +17,6 @@ RAK3401Board board; #endif #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/rak3401/target.h b/variants/rak3401/target.h index 00653e90e5..758d6c7895 100644 --- a/variants/rak3401/target.h +++ b/variants/rak3401/target.h @@ -19,6 +19,7 @@ #endif extern RAK3401Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/rak4631/target.cpp b/variants/rak4631/target.cpp index b7691dd26c..ce7b9b2adf 100644 --- a/variants/rak4631/target.cpp +++ b/variants/rak4631/target.cpp @@ -17,13 +17,6 @@ RAK4631Board board; #endif #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/rak4631/target.h b/variants/rak4631/target.h index 1529f90424..d5599f7934 100644 --- a/variants/rak4631/target.h +++ b/variants/rak4631/target.h @@ -19,6 +19,7 @@ #endif extern RAK4631Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/rak_wismesh_tag/target.cpp b/variants/rak_wismesh_tag/target.cpp index 95f8961eb2..84475ef5e4 100644 --- a/variants/rak_wismesh_tag/target.cpp +++ b/variants/rak_wismesh_tag/target.cpp @@ -13,13 +13,6 @@ RAKWismeshTagBoard board; MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true); #endif -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #if ENV_INCLUDE_GPS #include MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); diff --git a/variants/rak_wismesh_tag/target.h b/variants/rak_wismesh_tag/target.h index fbe18d2d11..65b902e995 100644 --- a/variants/rak_wismesh_tag/target.h +++ b/variants/rak_wismesh_tag/target.h @@ -16,6 +16,7 @@ #endif extern RAKWismeshTagBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/sensecap_solar/target.cpp b/variants/sensecap_solar/target.cpp index 01574e9f79..0203af7982 100644 --- a/variants/sensecap_solar/target.cpp +++ b/variants/sensecap_solar/target.cpp @@ -6,12 +6,6 @@ #endif SenseCapSolarBoard board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/sensecap_solar/target.h b/variants/sensecap_solar/target.h index a1c01f1368..276aee702f 100644 --- a/variants/sensecap_solar/target.h +++ b/variants/sensecap_solar/target.h @@ -10,6 +10,7 @@ #include extern SenseCapSolarBoard board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/tenstar_c3/target.cpp b/variants/tenstar_c3/target.cpp index b800e2df6c..13400fecf7 100644 --- a/variants/tenstar_c3/target.cpp +++ b/variants/tenstar_c3/target.cpp @@ -3,26 +3,4 @@ XiaoC3Board board; -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); SensorManager sensors; - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} diff --git a/variants/tenstar_c3/target.h b/variants/tenstar_c3/target.h index 7839fa973a..1700fcaa92 100644 --- a/variants/tenstar_c3/target.h +++ b/variants/tenstar_c3/target.h @@ -10,6 +10,7 @@ #include extern XiaoC3Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern SensorManager sensors; diff --git a/variants/thinknode_m1/target.cpp b/variants/thinknode_m1/target.cpp index 3a0a7f04f9..f12cb32d34 100644 --- a/variants/thinknode_m1/target.cpp +++ b/variants/thinknode_m1/target.cpp @@ -6,12 +6,6 @@ ThinkNodeM1Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); ThinkNodeM1SensorManager sensors = ThinkNodeM1SensorManager(nmea); diff --git a/variants/thinknode_m1/target.h b/variants/thinknode_m1/target.h index ec1297beff..d41dbaaaaf 100644 --- a/variants/thinknode_m1/target.h +++ b/variants/thinknode_m1/target.h @@ -33,6 +33,7 @@ class ThinkNodeM1SensorManager : public SensorManager { }; extern ThinkNodeM1Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern ThinkNodeM1SensorManager sensors; diff --git a/variants/thinknode_m6/target.cpp b/variants/thinknode_m6/target.cpp index f8258af1d0..335896c384 100644 --- a/variants/thinknode_m6/target.cpp +++ b/variants/thinknode_m6/target.cpp @@ -5,12 +5,6 @@ ThinkNodeM6Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/thinknode_m6/target.h b/variants/thinknode_m6/target.h index 76188e584e..30150b0790 100644 --- a/variants/thinknode_m6/target.h +++ b/variants/thinknode_m6/target.h @@ -15,6 +15,7 @@ #endif extern ThinkNodeM6Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/thinknode_m8/target.cpp b/variants/thinknode_m8/target.cpp index 5bf588139a..6ef6e9d878 100644 --- a/variants/thinknode_m8/target.cpp +++ b/variants/thinknode_m8/target.cpp @@ -6,12 +6,6 @@ ThinkNodeM8Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/thinknode_m8/target.h b/variants/thinknode_m8/target.h index c3402a01a7..17d98cbfbc 100644 --- a/variants/thinknode_m8/target.h +++ b/variants/thinknode_m8/target.h @@ -16,6 +16,7 @@ #endif extern ThinkNodeM8Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/wio-tracker-l1-1w/target.cpp b/variants/wio-tracker-l1-1w/target.cpp index 1170282a50..c7100385d0 100644 --- a/variants/wio-tracker-l1-1w/target.cpp +++ b/variants/wio-tracker-l1-1w/target.cpp @@ -5,13 +5,6 @@ WioTrackerL1Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/wio-tracker-l1-1w/target.h b/variants/wio-tracker-l1-1w/target.h index 05bc7ff1ca..7d918811a2 100644 --- a/variants/wio-tracker-l1-1w/target.h +++ b/variants/wio-tracker-l1-1w/target.h @@ -19,6 +19,7 @@ #include extern WioTrackerL1Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/wio-tracker-l1/target.cpp b/variants/wio-tracker-l1/target.cpp index 1170282a50..c7100385d0 100644 --- a/variants/wio-tracker-l1/target.cpp +++ b/variants/wio-tracker-l1/target.cpp @@ -5,13 +5,6 @@ WioTrackerL1Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - #ifdef ENV_INCLUDE_GPS MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); diff --git a/variants/wio-tracker-l1/target.h b/variants/wio-tracker-l1/target.h index 05bc7ff1ca..7d918811a2 100644 --- a/variants/wio-tracker-l1/target.h +++ b/variants/wio-tracker-l1/target.h @@ -19,6 +19,7 @@ #include extern WioTrackerL1Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors; diff --git a/variants/xiao_nrf52/target.cpp b/variants/xiao_nrf52/target.cpp index ecdcbdb6e9..932095066e 100644 --- a/variants/xiao_nrf52/target.cpp +++ b/variants/xiao_nrf52/target.cpp @@ -9,11 +9,4 @@ XiaoNrf52Board board; -RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI); - -WRAPPER_CLASS radio_driver(radio, board); - -VolatileRTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); - EnvironmentSensorManager sensors; diff --git a/variants/xiao_nrf52/target.h b/variants/xiao_nrf52/target.h index 20093904aa..504b055ca8 100644 --- a/variants/xiao_nrf52/target.h +++ b/variants/xiao_nrf52/target.h @@ -17,6 +17,7 @@ #endif extern XiaoNrf52Board board; +#define RADIOLIB_TARGET_GLOBALS // radio, radio_driver and rtc_clock come from RadioLibTarget.cpp extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; extern EnvironmentSensorManager sensors;