RMT callback delay
Posted: Wed Mar 06, 2024 5:23 pm
Hi,
for my project I need to set 4 gpio outputs based on signal in form of very short pulses (tens of ns) and speed is crucial. I think RMT is great for reading the pulses, however, the callback seems to have a high latency. The code below is simplified ir_nec_transceiver example. So far it only toggles the output pin 32 when pulses are received. It takes roughly 7 us from receiving the last pulse to modifying the output. Is there any way to reduce the delay?
for my project I need to set 4 gpio outputs based on signal in form of very short pulses (tens of ns) and speed is crucial. I think RMT is great for reading the pulses, however, the callback seems to have a high latency. The code below is simplified ir_nec_transceiver example. So far it only toggles the output pin 32 when pulses are received. It takes roughly 7 us from receiving the last pulse to modifying the output. Is there any way to reduce the delay?
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "freertos/queue.h"
- #include "esp_log.h"
- #include "driver/rmt_rx.h"
- #include "soc/soc.h"
- #include "soc/gpio_reg.h"
- #define OUTPUT_PINS_START 32
- #define OUTPUT_PINS 1111 << (OUTPUT_PINS_START-32)
- #define RMT_RESOLUTION_HZ 80000000
- #define RMT_RX_GPIO_NUM 19
- #define RMT_MIN_DURATION 25
- #define RMT_MAX_DURATION 400
- #define RMT_BUFFER_SIZE 64
- static const char *TAG = "mux";
- uint32_t output_value = 0;
- rmt_channel_handle_t rx_channel = NULL;
- rmt_receive_config_t receive_config = {
- .signal_range_min_ns = RMT_MIN_DURATION, // A pulse whose width is smaller than this threshold will be treated as glitch and ignored
- .signal_range_max_ns = RMT_MAX_DURATION, //RMT will stop receiving if one symbol level has kept more than
- };
- // save the received RMT symbols
- rmt_symbol_word_t raw_symbols[RMT_BUFFER_SIZE];
- rmt_rx_done_event_data_t rx_data;
- static bool example_rmt_rx_done_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *user_data)
- {
- output_value++;
- output_value &= OUTPUT_PINS;
- REG_WRITE(GPIO_OUT1_REG, output_value);
- ESP_ERROR_CHECK(rmt_receive(rx_channel, raw_symbols, sizeof(raw_symbols), &receive_config));
- return false;
- }
- void app_main(void)
- {
- ESP_LOGI(TAG, "create output channels");
- REG_WRITE(GPIO_ENABLE1_W1TS_REG, OUTPUT_PINS);
- ESP_LOGI(TAG, "create RMT RX channel");
- rmt_rx_channel_config_t rx_channel_cfg = {
- .clk_src = RMT_CLK_SRC_DEFAULT,
- .resolution_hz = RMT_RESOLUTION_HZ,
- .mem_block_symbols = RMT_BUFFER_SIZE,
- .gpio_num = RMT_RX_GPIO_NUM,
- };
- ESP_ERROR_CHECK(rmt_new_rx_channel(&rx_channel_cfg, &rx_channel));
- ESP_LOGI(TAG, "register RX done callback");
- QueueHandle_t receive_queue = xQueueCreate(1, sizeof(rmt_rx_done_event_data_t));
- assert(receive_queue);
- rmt_rx_event_callbacks_t cbs = {
- .on_recv_done = example_rmt_rx_done_callback,
- };
- ESP_ERROR_CHECK(rmt_rx_register_event_callbacks(rx_channel, &cbs, receive_queue));
- ESP_LOGI(TAG, "enable RMT RX channel");
- ESP_ERROR_CHECK(rmt_enable(rx_channel));
- // ready to receive
- ESP_ERROR_CHECK(rmt_receive(rx_channel, raw_symbols, sizeof(raw_symbols), &receive_config));
- }