6#if SKETCH_HAS_LOTS_OF_MEMORY
11#include "platforms/is_platform.h"
17#include "freertos/FreeRTOS.h"
18#include "freertos/task.h"
19#include "soc/io_mux_reg.h"
20#include "soc/gpio_periph.h"
21#include "soc/gpio_reg.h"
25constexpr fl::u32 kMaxStamps = 200;
26volatile fl::u32 g_stamps[kMaxStamps];
27volatile fl::u32 g_count = 0;
28volatile fl::u32 g_selftest_edges = 0;
29volatile fl::u32 g_probe_state = 0;
30volatile fl::u32 g_rmt_live[8] = {0};
37static inline fl::u32 probeCycles() {
38 return static_cast<fl::u32
>(esp_cpu_get_cycle_count());
41void ARDUINO_ISR_ATTR edgeIsr() {
42 const fl::u32 i = g_count;
45 const fl::u32 lvl_now =
static_cast<fl::u32
>(
digitalRead(g_pin));
46 g_stamps[i] = ((lvl_now ^ 1u) << 31) | (probeCycles() & 0x7FFFFFFFu);
56 if (g_pin >= 0 && !passive) {
57 detachInterrupt(digitalPinToInterrupt(g_pin));
65 attachInterrupt(digitalPinToInterrupt(pin), edgeIsr, CHANGE);
73 for (
int i = 0; i < 4; ++i) {
79 g_selftest_edges = g_count;
88 xTaskCreate([](
void *arg) {
89 const int pin =
static_cast<int>(
reinterpret_cast<intptr_t>(arg));
91 vTaskDelay(pdMS_TO_TICKS(150));
92 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[pin]);
98 volatile fl::u32 *in_reg;
101 in_reg =
reinterpret_cast<volatile fl::u32 *
>(GPIO_IN_REG);
104 mask = 1u << (pin - 32);
105 in_reg =
reinterpret_cast<volatile fl::u32 *
>(GPIO_IN1_REG);
107 mask = 1u << (pin & 31);
108 in_reg =
reinterpret_cast<volatile fl::u32 *
>(GPIO_IN_REG);
111 const fl::u32 idle = *in_reg & mask;
121 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[pin]);
122 const fl::u32 b0 = probeCycles();
123 const fl::u32 lvl0 = *in_reg & mask;
124 while (probeCycles() - b0 < burst_cycles) {
125 if ((*in_reg & mask) != lvl0) {
triggered =
true;
break; }
133#if defined(CONFIG_IDF_TARGET_ESP32C6)
136 g_rmt_live[0] = *
reinterpret_cast<volatile fl::u32 *
>(0x60006038);
137 g_rmt_live[1] = *
reinterpret_cast<volatile fl::u32 *
>(0x60006030);
138 g_rmt_live[2] = *
reinterpret_cast<volatile fl::u32 *
>(0x60006034);
139 g_rmt_live[3] = *
reinterpret_cast<volatile fl::u32 *
>(0x6000601C);
140 g_rmt_live[6] = *
reinterpret_cast<volatile fl::u32 *
>(0x60091000 + 0x154 + 71 * 4);
141 g_rmt_live[7] = *
reinterpret_cast<volatile fl::u32 *
>(0x60091000 + 0x154 + 72 * 4);
144 fl::u32 prev = *in_reg & mask;
145 fl::u32 last_edge = probeCycles();
146 const fl::u32 start = last_edge;
149 const fl::u32 now = probeCycles();
150 if (now - start > budget)
break;
151 const fl::u32
cur = *in_reg & mask;
153 if (idx < kMaxStamps) {
154 g_stamps[idx] = ((prev ? 1u : 0u) << 31) | (now & 0x7FFFFFFFu);
162#if defined(CONFIG_IDF_TARGET_ESP32C6)
165 g_rmt_live[4] = *
reinterpret_cast<volatile fl::u32 *
>(0x60006038);
166 g_rmt_live[5] = *
reinterpret_cast<volatile fl::u32 *
>(0x60006030);
170 vTaskDelete(
nullptr);
171 },
"edgeprobe_rearm", 3072,
reinterpret_cast<void *
>(
static_cast<intptr_t>(pin)), 20,
nullptr);
176 return const_cast<const fl::u32 *
>(g_stamps);
183const fl::u32 *
edgeProbeRmtLive() {
return const_cast<const fl::u32 *
>(g_rmt_live); }
186 return static_cast<fl::u32
>(getCpuFrequencyMhz());
200struct EdgeProbeNoopState {
const fl::u32 * edgeProbeStamps(fl::u32 &count)
Timestamp buffer: entry = (level_before_edge << 31) | cycle_count.
fl::u32 edgeProbeState()
Probe task progress: 0=not started 1=started 2=triggered 3=sampled.
const fl::u32 * edgeProbeRmtLive()
RMT registers snapshotted at trigger time (INT_RAW, CH2STATUS, CH3STATUS, CH2_RX_CONF1).
fl::u32 edgeProbeSelfTestEdges()
Edges recorded by the arm-time pull-toggle self-test.
void edgeProbeArmMode(int pin, bool passive)
Passive variant: no pinMode/attachInterrupt/pull toggles — only the triggered tight-loop sampler task...
fl::u32 edgeProbeCpuMhz()
CPU frequency in MHz for cycle→ns conversion.
void edgeProbeArm(int pin)
Arm the probe on a pin (re-arming resets the buffer).
static T & instance() FL_NO_EXCEPT
void pinMode(int pin, PinMode mode)
Set pin mode (input, output, pull-up, pull-down)
PinValue digitalRead(int pin)
Read digital value from pin.
void delayMicroseconds(u32 us)
Delay for a given number of microseconds.