3#include <driver/rmt_rx.h>
4#include <driver/rmt_tx.h>
5#include <freertos/FreeRTOS.h>
6#include <freertos/queue.h>
7#include <freertos/task.h>
13#include "pulse/Vector.h"
14#include "pulse/Logger.h"
15#include "pulse/RxDriver.h"
16#include "pulse/TxDriver.h"
17#include "pulse/Codec.h"
18#include "pulse/RingBuffer.h"
58 void setFrameSize(
uint8_t size)
override { _frameSize = size; }
67 bool begin()
override {
71 manchesterBits.
reserve(_codec.getBitCount());
73 uint8_t dma = (_frameSize > 64) ? 1 : 0;
74 rmt_rx_channel_config_t rx_config = {.gpio_num = (gpio_num_t)_rxPin,
75 .clk_src = RMT_CLK_SRC_DEFAULT,
76 .resolution_hz = 1000000,
77 .mem_block_symbols = 64,
84 rmt_channel_handle_t rx_channel =
nullptr;
85 esp_err_t rmt_result = rmt_new_rx_channel(&rx_config, &rx_channel);
86 if (rmt_result != ESP_OK || rx_channel ==
nullptr) {
87 Logger::error(
"RMT RX channel initialization failed: %d", rmt_result);
90 _rxChannel = rx_channel;
93 int count = _rxBufferSize / _frameSize;
94 if (_rxBufferSize % _frameSize != 0) count++;
97 _frameQueue = xQueueCreate(count, _frameSize);
98 if (_frameQueue ==
nullptr) {
102 rxOverflow.resize(_rxBufferSize);
106 BaseType_t taskResult = xTaskCreatePinnedToCore(
rxTask,
"rmt_rx", 4096,
107 this, 1, &_taskHandle, 1);
108 if (taskResult != pdPASS || _taskHandle ==
nullptr) {
122 _taskHandle =
nullptr;
126 _rxChannel =
nullptr;
133 while (
length > 0 && rxOverflow.available() > 0) {
134 int b = rxOverflow.
read();
142 while (
length > 0 && _frameQueue &&
151 if (
toCopy < _frameSize) {
160 if (!_frameQueue)
return 0;
165 size_t _rxBufferSize = 256;
167 uint16_t _frameSize = DEFAULT_FRAME_SIZE;
171 volatile bool _stopTask =
false;
173 bool _inFrame =
false;
178 bool _useChecksum =
false;
198 while (!
self->_stopTask) {
217 bool level =
isOne ? 1 : 0;
222 if (
self->_useChecksum) {
226 for (
size_t j = 0;
j <
frameLen - 1; ++
j) sum += data[
j];
242 if (
self->_codec.decodeEdge(0, 0, 0, 0, data,
self->_frameSize,
frameLen)) {
243 if (
self->_useChecksum) {
246 for (
size_t j = 0;
j <
frameLen - 1; ++
j) sum += data[
j];
static void error(const char *format,...)
Log an error message with formatting.
Manchester encoding/decoding utility class for IR communication.
bool begin(uint32_t bitFrequencyHz) override
initialization method for codecs that require setup before use (e.g., loading PIO programs,...
bool read(T &out)
Read and remove the next element. Returns true if successful.
High-performance ESP32 IR RX driver using the RMT peripheral and Manchester decoding.
RxDriverESP32(ManchesterCodec &codec, uint8_t pin, uint32_t freqHz=DEFAULT_BIT_FREQ_HZ, bool useChecksum=false, uint32_t timeoutUs=5000)
void end() override
Stop 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
static void rxTask(void *arg)
FreeRTOS task for receiving and decoding IR frames using ESP32 RMT.
void setRxBufferSize(size_t size) override
Set the size of the internal RX buffer.
Abstract base class for IR receivers.
Small, header-only vector replacement for non-STL environments.
void reserve(size_t cap)
Reserve space for at least cap elements.
T * data()
Pointer to underlying data.
size_t size() const
Number of elements in vector.