4#include "TransceiverConfig.h"
5#include "pulse/RxDriver.h"
6#include "pulse/codecs/Codec.h"
7#include "pulse/codecs/ManchesterCodec.h"
8#include "pulse/tools/Logger.h"
9#include "pulse/tools/RingBuffer.h"
10#include "pulse/tools/Vector.h"
25 virtual void handleInterrupt() = 0;
28#if !defined(HAS_INTERRUPT_ARG)
38 for (
int i = 0;
i < 10;
i++) {
39 if (!_isrData[
i].active || _isrData[
i].pin == pin) {
40 _isrData[
i].instance = instance;
41 _isrData[
i].active =
true;
42 _isrData[
i].pin = pin;
50 static bool isAttached(
uint8_t pin) {
51 for (
int i = 0;
i < 10;
i++) {
52 if (_isrData[
i].active && _isrData[
i].pin == pin) {
59 static void detach(
uint8_t pin) {
60 for (
int i = 0;
i < 10;
i++) {
61 if (_isrData[
i].active && _isrData[
i].pin == pin) {
63 _isrData[
i].instance =
nullptr;
64 _isrData[
i].active =
false;
79 static InstanceData _isrData[10];
81 static void isr0() { dispatch(0); }
82 static void isr1() { dispatch(1); }
83 static void isr2() { dispatch(2); }
84 static void isr3() { dispatch(3); }
85 static void isr4() { dispatch(4); }
86 static void isr5() { dispatch(5); }
87 static void isr6() { dispatch(6); }
88 static void isr7() { dispatch(7); }
89 static void isr8() { dispatch(8); }
90 static void isr9() { dispatch(9); }
92 static void initISR() {
96 isr5, isr6, isr7, isr8, isr9};
97 for (
int i = 0;
i < 10; ++
i) {
98 _isrData[
i].instance =
nullptr;
100 _isrData[
i].pin = -1;
101 _isrData[
i].active =
false;
107 static void dispatch(
int index) {
109 _isrData[
index].instance->handleInterrupt();
173 ~RxDriverArduino() {
end(); }
177 _codec.setFrameSize(size);
179 _rxBuffer.resize(size * 2);
191 _bitPeriodUs = 1000000UL / _freqHz;
192 _minUs = _bitPeriodUs / 2;
193 _maxUs = _bitPeriodUs * 2;
195 "Bit frequency: %d Hz, Bit period: %d us, Timing window: [%d, %d] us",
196 _freqHz, _bitPeriodUs, _minUs, _maxUs);
198 if (_timeoutUs == 0) {
216#ifdef HAS_INTERRUPT_ARG
219 if (!ISRManager::attach(_pin,
this)) {
226 Logger::info(
"RX driver started on pin %d with codec %s with frame size %d",
227 _pin, _codec.
name(), _frameSize);
234 if (_rxBuffer.size() == 0) {
245 int result = _rxBuffer.available();
253#ifdef HAS_INTERRUPT_ARG
256 ISRManager::detach(_pin);
264 volatile bool _lastLevel;
267 uint16_t _frameSize = DEFAULT_FRAME_SIZE;
275 bool _useChecksum =
false;
277 volatile bool _is_active =
false;
278 volatile bool _is_open =
false;
280#ifdef HAS_INTERRUPT_ARG
286 void IRAM_ATTR handleInterrupt()
override {
287 bool newLevel = digitalRead(_pin);
288 uint32_t now = micros();
289 uint32_t duration = now - _lastEdge;
293 OutputEdge edge{_lastLevel, duration};
294 _edgeBuffer.write(edge);
295 _lastLevel = newLevel;
299 void processEdges() {
303 while (!_rxBuffer.isFull() && ok) {
305 ok = _edgeBuffer.read(edge);
307 uint8_t byte_data = 0;
308 if (ok && _codec.
decodeEdge(edge.pulseUs, edge.level, byte_data)) {
309 _rxBuffer.write(byte_data);
315 void checkTimeout() {
317 uint32_t now = micros();
318 uint32_t duration = now - _lastEdge;
319 uint8_t byte_data = 0;
324 bool has_data = _codec.
decodeEdge(_bitPeriodUs, _lastLevel, byte_data);
326 _rxBuffer.write(byte_data);
332 if (duration > _timeoutUs) {
341 _lastEdge = micros();
Abstract base class for IR protocol encoding and decoding.
virtual bool decodeEdge(uint32_t durationUs, bool level, uint8_t &result)
Edge-based decoding for protocol-agnostic RX drivers.
virtual bool begin(uint32_t bitFrequencyHz)
initialization method for codecs that require setup before use (e.g., loading PIO programs,...
virtual int getEndOfFrameDelayUs()=0
Provide the end of frame delay in microseconds for this protocol, used by RX driver to.
const char * name() const
Get the name of the codec type as a string (e.g., "PulseDistance", "Manchester").
virtual size_t getEdgeCount() const =0
Get the number of protocol symbols (bits, pulses, etc.) per encoded byte.
Manager for handling multiple ISR instances on platforms without attachInterruptArg.
static void debug(const char *format,...)
Log a debug message with formatting.
static void info(const char *format,...)
Log an informational message with formatting.
int readArray(T *dest, size_t len)
Read up to len elements into dest, returns number of elements read.
Interrupt-driven Arduino RX driver for pulse-based protocols.
void end()
Stop the receiver.
void setRxBufferSize(size_t size)
Set the size of the internal RX buffer.
bool begin(uint32_t bitFrequencyHz=DEFAULT_BIT_FREQ_HZ) override
Start the receiver.
int available() override
Get the number of bytes available in the internal buffer.
size_t readBytes(uint8_t *buffer, size_t length) override
RxDriverArduino(Codec &codec, uint8_t pin, uint32_t freqHz=DEFAULT_BIT_FREQ_HZ, bool useChecksum=false, uint32_t timeoutUs=0)
void setFrameSize(uint16_t size) override
Set the expected frame size for dynamic data reception.
Interrupt-capable IR RX driver interface for platforms without attachInterruptArg.
Abstract base class for IR receivers.
Small, header-only vector replacement for non-STL environments.
void resize(size_t n)
Resize vector to n elements.