Просмотр исходного кода

rmt: support rmt user context in translator

Merges https://github.com/espressif/esp-idf/pull/6002
Nishanth Samala 5 лет назад
Родитель
Сommit
21bb6f2334
2 измененных файлов с 103 добавлено и 8 удалено
  1. 39 0
      components/driver/include/driver/rmt.h
  2. 64 8
      components/driver/rmt.c

+ 39 - 0
components/driver/include/driver/rmt.h

@@ -171,6 +171,22 @@ typedef struct {
 */
 */
 typedef void (*sample_to_rmt_t)(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num, size_t *translated_size, size_t *item_num);
 typedef void (*sample_to_rmt_t)(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num, size_t *translated_size, size_t *item_num);
 
 
+/**
+* @brief IDF 4.x Workaround callback function for sample_to_rmt_t that lets user pass in context for rmt_write_sample
+*
+* @param  src Pointer to the buffer storing the raw data that needs to be converted to rmt format.
+* @param[out] dest Pointer to the buffer storing the rmt format data.
+* @param  src_size The raw data size.
+* @param  wanted_num The number of rmt format data that wanted to get.
+* @param[out] translated_size The size of the raw data that has been converted to rmt format,
+*             it should return 0 if no data is converted in user callback.
+* @param[out] item_num The number of the rmt format data that actually converted to,
+*             it can be less than wanted_num if there is not enough raw data, but cannot exceed wanted_num.
+*             it should return 0 if no data was converted.
+* @param  context User context pointer
+*/
+typedef void (*sample_with_context_to_rmt_t)(const void *src, rmt_item32_t *dest, size_t src_size, size_t wanted_num, size_t *translated_size, size_t *item_num, void *context);
+
 /**
 /**
 * @brief Set RMT clock divider, channel clock is divided from source clock.
 * @brief Set RMT clock divider, channel clock is divided from source clock.
 *
 *
@@ -762,6 +778,29 @@ esp_err_t rmt_get_ringbuf_handle(rmt_channel_t channel, RingbufHandle_t *buf_han
 */
 */
 esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn);
 esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn);
 
 
+/**
+* @brief Workaround for IDF 4.x
+*        TODO: Add context to sample_to_rmt_t callback signature and allow user to pass in context
+*              on rmt_translator_init
+*
+* @param channel RMT channel .
+* @param fn Point to the data conversion function.
+*
+* @return
+*     - ESP_FAIL Init fail.
+*     - ESP_OK Init success.
+*/
+esp_err_t rmt_translator_init_with_context(rmt_channel_t channel, sample_with_context_to_rmt_t fn, void* context);
+
+/**
+* @brief Sets the user context for the translator
+*        Requires rmt_translator_init_with_context to init the translator first
+* @return
+*     - ESP_FAIL Set context fail
+*     - ESP_OK Set context success
+*/
+esp_err_t rmt_set_translator_context(rmt_channel_t channel, void* context);
+
 /**
 /**
 * @brief Translate uint8_t type of data into rmt format and send it out.
 * @brief Translate uint8_t type of data into rmt format and send it out.
 *        Requires rmt_translator_init to init the translator first.
 *        Requires rmt_translator_init to init the translator first.

+ 64 - 8
components/driver/rmt.c

@@ -99,6 +99,8 @@ typedef struct {
     int rx_item_start_idx;
     int rx_item_start_idx;
 #endif
 #endif
     sample_to_rmt_t sample_to_rmt;
     sample_to_rmt_t sample_to_rmt;
+    sample_with_context_to_rmt_t sample_with_context_to_rmt;
+    void* tx_context;
     size_t sample_size_remain;
     size_t sample_size_remain;
     const uint8_t *sample_cur;
     const uint8_t *sample_cur;
 } rmt_obj_t;
 } rmt_obj_t;
@@ -783,12 +785,21 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg)
             if (p_rmt->translator) {
             if (p_rmt->translator) {
                 if (p_rmt->sample_size_remain > 0) {
                 if (p_rmt->sample_size_remain > 0) {
                     size_t translated_size = 0;
                     size_t translated_size = 0;
-                    p_rmt->sample_to_rmt((void *)p_rmt->sample_cur,
-                                         p_rmt->tx_buf,
-                                         p_rmt->sample_size_remain,
-                                         p_rmt->tx_sub_len,
-                                         &translated_size,
-                                         &p_rmt->tx_len_rem);
+                    if (p_rmt->sample_with_context_to_rmt == NULL)
+                        p_rmt->sample_to_rmt((void *)p_rmt->sample_cur,
+                                            p_rmt->tx_buf,
+                                            p_rmt->sample_size_remain,
+                                            p_rmt->tx_sub_len,
+                                            &translated_size,
+                                            &p_rmt->tx_len_rem);
+                    else
+                        p_rmt->sample_with_context_to_rmt((void *)p_rmt->sample_cur,
+                                            p_rmt->tx_buf,
+                                            p_rmt->sample_size_remain,
+                                            p_rmt->tx_sub_len,
+                                            &translated_size,
+                                            &p_rmt->tx_len_rem,
+                                            p_rmt->tx_context);
                     p_rmt->sample_size_remain -= translated_size;
                     p_rmt->sample_size_remain -= translated_size;
                     p_rmt->sample_cur += translated_size;
                     p_rmt->sample_cur += translated_size;
                     p_rmt->tx_data = p_rmt->tx_buf;
                     p_rmt->tx_data = p_rmt->tx_buf;
@@ -1216,17 +1227,59 @@ esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn)
         }
         }
     }
     }
     p_rmt_obj[channel]->sample_to_rmt = fn;
     p_rmt_obj[channel]->sample_to_rmt = fn;
+    p_rmt_obj[channel]->sample_with_context_to_rmt = NULL;
+    p_rmt_obj[channel]->tx_context = NULL;
     p_rmt_obj[channel]->sample_size_remain = 0;
     p_rmt_obj[channel]->sample_size_remain = 0;
     p_rmt_obj[channel]->sample_cur = NULL;
     p_rmt_obj[channel]->sample_cur = NULL;
     ESP_LOGD(RMT_TAG, "RMT translator init done");
     ESP_LOGD(RMT_TAG, "RMT translator init done");
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
+esp_err_t rmt_translator_init_with_context(rmt_channel_t channel, sample_with_context_to_rmt_t fn, void* context)
+{
+    RMT_CHECK(fn != NULL, RMT_TRANSLATOR_NULL_STR, ESP_ERR_INVALID_ARG);
+    RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
+    RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL);
+    const uint32_t block_size = rmt_ll_get_mem_blocks(p_rmt_obj[channel]->hal.regs, channel) *
+                                RMT_MEM_ITEM_NUM * sizeof(rmt_item32_t);
+    if (p_rmt_obj[channel]->tx_buf == NULL) {
+#if !CONFIG_SPIRAM_USE_MALLOC
+        p_rmt_obj[channel]->tx_buf = (rmt_item32_t *)malloc(block_size);
+#else
+        if (p_rmt_obj[channel]->intr_alloc_flags & ESP_INTR_FLAG_IRAM) {
+            p_rmt_obj[channel]->tx_buf = (rmt_item32_t *)malloc(block_size);
+        } else {
+            p_rmt_obj[channel]->tx_buf = (rmt_item32_t *)heap_caps_calloc(1, block_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+        }
+#endif
+        if (p_rmt_obj[channel]->tx_buf == NULL) {
+            ESP_LOGE(RMT_TAG, "RMT translator buffer create fail");
+            return ESP_FAIL;
+        }
+    }
+    p_rmt_obj[channel]->sample_to_rmt = NULL;
+    p_rmt_obj[channel]->sample_with_context_to_rmt = fn;
+    p_rmt_obj[channel]->tx_context = context;
+    p_rmt_obj[channel]->sample_size_remain = 0;
+    p_rmt_obj[channel]->sample_cur = NULL;
+    ESP_LOGD(RMT_TAG, "RMT translator init done");
+    return ESP_OK;
+}
+
+esp_err_t rmt_set_translator_context(rmt_channel_t channel, void* context)
+{
+    RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
+    RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL);
+
+    p_rmt_obj[channel]->tx_context = context;
+    return ESP_OK;
+}
+
 esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src_size, bool wait_tx_done)
 esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src_size, bool wait_tx_done)
 {
 {
     RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
     RMT_CHECK(RMT_IS_TX_CHANNEL(channel), RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
     RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL);
     RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL);
-    RMT_CHECK(p_rmt_obj[channel]->sample_to_rmt != NULL, RMT_TRANSLATOR_UNINIT_STR, ESP_FAIL);
+    RMT_CHECK(p_rmt_obj[channel]->sample_to_rmt != NULL || p_rmt_obj[channel]->sample_with_context_to_rmt != NULL, RMT_TRANSLATOR_UNINIT_STR, ESP_FAIL);
 #if CONFIG_SPIRAM_USE_MALLOC
 #if CONFIG_SPIRAM_USE_MALLOC
     if (p_rmt_obj[channel]->intr_alloc_flags & ESP_INTR_FLAG_IRAM) {
     if (p_rmt_obj[channel]->intr_alloc_flags & ESP_INTR_FLAG_IRAM) {
         if (!esp_ptr_internal(src)) {
         if (!esp_ptr_internal(src)) {
@@ -1241,7 +1294,10 @@ esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src
     const uint32_t item_block_len = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
     const uint32_t item_block_len = rmt_ll_tx_get_mem_blocks(rmt_contex.hal.regs, channel) * RMT_MEM_ITEM_NUM;
     const uint32_t item_sub_len = item_block_len / 2;
     const uint32_t item_sub_len = item_block_len / 2;
     xSemaphoreTake(p_rmt->tx_sem, portMAX_DELAY);
     xSemaphoreTake(p_rmt->tx_sem, portMAX_DELAY);
-    p_rmt->sample_to_rmt((void *)src, p_rmt->tx_buf, src_size, item_block_len, &translated_size, &item_num);
+    if (p_rmt->sample_with_context_to_rmt == NULL)
+        p_rmt->sample_to_rmt((void *)src, p_rmt->tx_buf, src_size, item_block_len, &translated_size, &item_num);
+    else
+        p_rmt->sample_with_context_to_rmt((void*)src, p_rmt->tx_buf, src_size, item_block_len, &translated_size, &item_num, p_rmt->tx_context);
     p_rmt->sample_size_remain = src_size - translated_size;
     p_rmt->sample_size_remain = src_size - translated_size;
     p_rmt->sample_cur = src + translated_size;
     p_rmt->sample_cur = src + translated_size;
     rmt_fill_memory(channel, p_rmt->tx_buf, item_num, 0);
     rmt_fill_memory(channel, p_rmt->tx_buf, item_num, 0);