| 118 | } // namespace |
| 119 | |
| 120 | inline void autoResearchLowMemorySetup() { |
| 121 | fl::serial_begin(115200); |
| 122 | |
| 123 | // Arm the watchdog so a hung sketch unbricks itself on crash. |
| 124 | fl::Watchdog::instance().begin(3000); |
| 125 | |
| 126 | // Emit a literal-only warning so the autoresearch harness can verify |
| 127 | // the FL_WARN log pipeline reaches the host. |
| 128 | FL_WARN_LIT("FL_WARN: low-memory bring-up OK"); |
| 129 | |
| 130 | // The C++ inline-ODR rule guarantees a single shared instance across |
| 131 | // every translation unit that calls this inline function, which is |
| 132 | // exactly what we want (one Remote bound to the singleton Serial |
| 133 | // transport). The included-once-per-sketch model of `.ino` builds |
| 134 | // also reduces to a single TU in practice. |
| 135 | static fl::Remote remote( // okay static in header |
| 136 | fl::createSerialRequestSource(), |
| 137 | fl::createSerialResponseSink("REMOTE: ")); |
| 138 | g_low_memory_remote = &remote; |
| 139 | remote.bind("echo", [](int v) -> int { |
| 140 | FL_WARN_LIT("FL_WARN: echo invoked"); |
| 141 | return v; |
| 142 | }); |
| 143 | |
| 144 | #if defined(FL_IS_ARM_LPC) |
| 145 | // pinToggleRx (FastLED #3021 Phase 1) — bit-bang square wave on tx_pin |
| 146 | // and capture SCT edges on rx_pin. CSV stats out. |
| 147 | remote.bind("pinToggleRx", |
| 148 | [](int tx_pin, int rx_pin, int freq_hz, int duration_ms) -> fl::string { |
| 149 | if (tx_pin < 0 || rx_pin < 0 || freq_hz <= 0 || duration_ms <= 0) { |
| 150 | return fl::string("0,0,0,0,0,0,0"); |
| 151 | } |
| 152 | const fl::u32 expected_edges = |
| 153 | 2u * static_cast<fl::u32>(freq_hz) * |
| 154 | static_cast<fl::u32>(duration_ms) / 1000u; |
| 155 | fl::u32 cap = expected_edges + (expected_edges / 2u); |
| 156 | if (cap < 256u) cap = 256u; |
| 157 | if (cap > 2048u) cap = 2048u; |
| 158 | |
| 159 | auto rx = fl::LpcSctRxChannel::create(rx_pin); |
| 160 | if (!rx) return fl::string("0,0,0,0,0,0,0"); |
| 161 | |
| 162 | fl::RxConfig cfg; |
| 163 | cfg.buffer_size = cap; |
| 164 | cfg.start_low = true; |
| 165 | if (!rx->begin(cfg)) return fl::string("0,0,0,0,0,0,0"); |
| 166 | |
| 167 | pinMode(tx_pin, OUTPUT); |
| 168 | digitalWrite(tx_pin, LOW); |
| 169 | |
| 170 | const fl::u32 half_us = 500000u / static_cast<fl::u32>(freq_hz); |
| 171 | const fl::u32 cycles = static_cast<fl::u32>(freq_hz) * |
| 172 | static_cast<fl::u32>(duration_ms) / 1000u; |
| 173 | |
| 174 | for (fl::u32 i = 0; i < cycles; ++i) { |
| 175 | digitalWrite(tx_pin, HIGH); |
| 176 | delayMicroseconds(half_us); |
| 177 | rx->pollOnce(); |
nothing calls this directly
no test coverage detected