1111#include " adapter_gpio_v2.hpp"
1212#if defined(M5_UNIT_UNIFIED_USING_RMT_V2)
1313
14+ #include < freertos/ringbuf.h>
1415#include < esp_private/esp_clk.h>
1516#include < soc/soc_caps.h> // SOC_RMT_MEM_WORDS_PER_CHANNEL
1617
@@ -162,6 +163,9 @@ class GPIOImplV2 : public AdapterGPIO::GPIOImpl {
162163 rmt_disable (_rx_handle);
163164 rmt_del_channel (_rx_handle);
164165 }
166+ if (_ring_buf) {
167+ vRingbufferDelete (_ring_buf);
168+ }
165169 if (_rx_buf) {
166170 heap_caps_free (_rx_buf);
167171 }
@@ -194,8 +198,8 @@ class GPIOImplV2 : public AdapterGPIO::GPIOImpl {
194198
195199 uint16_t _rx_buf_len{};
196200
197- volatile uint16_t _receive_len{};
198201 uint8_t *_rx_buf{};
202+ RingbufHandle_t _ring_buf{};
199203
200204 callback_struct_t _callback_data{};
201205 SemaphoreHandle_t _sem{};
@@ -238,11 +242,16 @@ bool GPIOImplV2::begin(const gpio::adapter_config_t &cfg)
238242 }
239243
240244 _rx_buf = (uint8_t *)heap_caps_malloc (cfg.rx .ring_buffer_size , MALLOC_CAP_DMA | MALLOC_CAP_32BIT );
241-
242245 if (!_rx_buf) {
243246 M5_LIB_LOGE (" Failed to allocate memory %u" , cfg.rx .ring_buffer_size );
244247 return false ;
245248 }
249+
250+ _ring_buf = xRingbufferCreate (cfg.rx .ring_buffer_size , RINGBUF_TYPE_NOSPLIT );
251+ if (!_ring_buf) {
252+ M5_LIB_LOGE (" Failed to create ringbuffer" );
253+ return false ;
254+ }
246255 _rx_buf_len = cfg.rx .ring_buffer_size ;
247256
248257 _rx_config = to_rmt_rx_config (cfg, esp_clk_apb_freq ());
@@ -331,32 +340,28 @@ m5::hal::error::error_t GPIOImplV2::writeWithTransaction(const uint8_t *data, co
331340
332341m5::hal::error::error_t GPIOImplV2::readWithTransaction (uint8_t *data, const size_t len)
333342{
334- if (!_rx_handle) {
335- M5_LIB_LOGE (" Invalid handle" );
343+ if (!_rx_handle || !_ring_buf) {
336344 return m5::hal::error::error_t ::UNKNOWN_ERROR ;
337345 }
338346 if (!data || len < 4 ) {
339347 M5_LIB_LOGE (" Invalid arguments %p,%zu" , data, len);
340348 return m5::hal::error::error_t ::INVALID_ARGUMENT ;
341349 }
342350
343- if (_rx_buf && _rx_buf_len) {
344- xSemaphoreTake (_sem, portMAX_DELAY);
345- // Top of 2 bytes is receive length
346- uint16_t rlen = _receive_len;
347- if (rlen > len - 2 ) {
348- rlen = len - 2 ;
349- }
350- memcpy (data, &rlen, sizeof (rlen));
351-
352- memcpy (data + 2 , _rx_buf, rlen);
353- xSemaphoreGive (_sem);
351+ size_t max_len = len - 2 ; // Top of 2 bytes is receive length
352+ size_t rx_size{};
353+ auto *items = static_cast <uint8_t *>(xRingbufferReceive (_ring_buf, &rx_size, pdMS_TO_TICKS (50 )));
354354
355- // dump_symbols((rmt_symbol_word_t *)(data + 2), rlen / sizeof(rmt_symbol_word_t));
356-
357- return rlen ? m5::hal::error::error_t ::OK : m5::hal::error::error_t ::UNKNOWN_ERROR ;
355+ memcpy (data, " \0\0 " , 2 );
356+ if (items && rx_size) {
357+ uint16_t rlen = (rx_size > max_len) ? static_cast <uint16_t >(max_len) : static_cast <uint16_t >(rx_size);
358+ memcpy (data, &rlen, sizeof (rlen));
359+ memcpy (data + 2 , items, rlen);
358360 }
359- return m5::hal::error::error_t ::UNKNOWN_ERROR ;
361+ if (items) {
362+ vRingbufferReturnItem (_ring_buf, items);
363+ }
364+ return rx_size ? m5::hal::error::error_t ::OK : m5::hal::error::error_t ::TIMEOUT_ERROR ;
360365}
361366
362367void GPIOImplV2::receive_loop_task (void *)
@@ -373,8 +378,13 @@ void GPIOImplV2::receive_loop(const uint16_t received_len)
373378{
374379 xSemaphoreTake (_sem, portMAX_DELAY);
375380
376- _receive_len = received_len;
377- auto err = rmt_receive (_rx_handle, _rx_buf, _rx_buf_len, &_receive_config);
381+ // Push received data to ringbuffer before restarting rmt_receive
382+ if (_ring_buf && received_len > 0 ) {
383+ if (xRingbufferSend (_ring_buf, _rx_buf, received_len, 0 ) != pdTRUE) {
384+ M5_LIB_LOGW (" Ringbuffer full, dropped %u bytes" , received_len);
385+ }
386+ }
387+ auto err = rmt_receive (_rx_handle, _rx_buf, _rx_buf_len, &_receive_config);
378388
379389 xSemaphoreGive (_sem);
380390
0 commit comments