#pragma once #include #include #include #include "Config.h" #include "Core.h" #if CONFIG_IDF_TARGET_ESP32S3 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) #define OPTICAL_USE_MCPWM_CAPTURE 1 #include #else #define OPTICAL_USE_MCPWM_CAPTURE 0 #endif class PulseReceiver { public: bool begin(); bool start(uint32_t expectedHz, float expectedDutyPct); void stop(); void resetStream(); size_t readPeriods(PulsePeriod *periods, size_t capacity, TickType_t waitTicks = 0); uint32_t takeDroppedItems(); uint32_t tickHz() const; uint32_t pulseTickHz() const { return tickHz(); } uint32_t plannedTickHz(uint32_t expectedHz, float expectedDutyPct) const; uint32_t plannedPulseTickHz(uint32_t expectedHz, float expectedDutyPct) const { return plannedTickHz(expectedHz, expectedDutyPct); } uint16_t receiveChunkSymbols() const { return 1; } bool highRateBackend() const { return OPTICAL_USE_MCPWM_CAPTURE; } private: struct Edge { uint32_t tick; uint8_t rising; }; struct TimedEdge { uint64_t tick; bool rising; }; bool consumeEdge(const Edge &edge, PulsePeriod &period); bool nextOrderedEdge(Edge &edge, TickType_t waitTicks); TimedEdge extendEdge(const Edge &edge); #if OPTICAL_USE_MCPWM_CAPTURE static bool IRAM_ATTR onCapture(mcpwm_cap_channel_handle_t, const mcpwm_capture_event_data_t *, void *); mcpwm_cap_timer_handle_t captureTimer_ = nullptr; mcpwm_cap_channel_handle_t risingChannel_ = nullptr; mcpwm_cap_channel_handle_t fallingChannel_ = nullptr; uint32_t captureResolutionHz_ = 0; #else static void IRAM_ATTR onGpio(void *ctx); uint32_t cpuTickHz_ = 0; #endif QueueHandle_t queue_ = nullptr; Edge reorderEdge_ = {}; bool haveReorderEdge_ = false; volatile uint32_t droppedItems_ = 0; volatile bool running_ = false; uint32_t expectedHz_ = 0; float expectedDutyPct_ = 50.0f; bool polarityKnown_ = false, activeStartRising_ = false; TimedEdge syncEdges_[3] = {}; uint8_t syncEdgeCount_ = 0; bool waitingForActiveEnd_ = true; uint64_t activeStart_ = 0, activeEnd_ = 0; bool haveRawTick_ = false; uint32_t lastRawTick_ = 0; uint64_t tickEpoch_ = 0; };