rmt_encoder.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/cdefs.h>
  9. #include <sys/param.h>
  10. #include "sdkconfig.h"
  11. #if CONFIG_RMT_ENABLE_DEBUG_LOG
  12. // The local log level must be defined before including esp_log.h
  13. // Set the maximum log level for this source file
  14. #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
  15. #endif
  16. #include "esp_log.h"
  17. #include "esp_check.h"
  18. #include "driver/rmt_encoder.h"
  19. #include "rmt_private.h"
  20. #include "hal/hal_utils.h"
  21. static const char *TAG = "rmt";
  22. typedef struct rmt_bytes_encoder_t {
  23. rmt_encoder_t base; // encoder base class
  24. size_t last_bit_index; // index of the encoding bit position in the encoding byte
  25. size_t last_byte_index; // index of the encoding byte in the primary stream
  26. rmt_symbol_word_t bit0; // bit zero representing
  27. rmt_symbol_word_t bit1; // bit one representing
  28. struct {
  29. uint32_t msb_first: 1; // encode MSB firstly
  30. } flags;
  31. } rmt_bytes_encoder_t;
  32. typedef struct rmt_copy_encoder_t {
  33. rmt_encoder_t base; // encoder base class
  34. size_t last_symbol_index; // index of symbol position in the primary stream
  35. } rmt_copy_encoder_t;
  36. static esp_err_t rmt_bytes_encoder_reset(rmt_encoder_t *encoder)
  37. {
  38. rmt_bytes_encoder_t *bytes_encoder = __containerof(encoder, rmt_bytes_encoder_t, base);
  39. // reset index to zero
  40. bytes_encoder->last_bit_index = 0;
  41. bytes_encoder->last_byte_index = 0;
  42. return ESP_OK;
  43. }
  44. static size_t IRAM_ATTR rmt_encode_bytes(rmt_encoder_t *encoder, rmt_channel_handle_t channel,
  45. const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
  46. {
  47. rmt_bytes_encoder_t *bytes_encoder = __containerof(encoder, rmt_bytes_encoder_t, base);
  48. rmt_tx_channel_t *tx_chan = __containerof(channel, rmt_tx_channel_t, base);
  49. const uint8_t *nd = (const uint8_t *)primary_data;
  50. rmt_encode_state_t state = RMT_ENCODING_RESET;
  51. rmt_dma_descriptor_t *desc0 = NULL;
  52. rmt_dma_descriptor_t *desc1 = NULL;
  53. size_t byte_index = bytes_encoder->last_byte_index;
  54. size_t bit_index = bytes_encoder->last_bit_index;
  55. // how many symbols will be generated by the encoder
  56. size_t mem_want = (data_size - byte_index - 1) * 8 + (8 - bit_index);
  57. // how many symbols we can save for this round
  58. size_t mem_have = tx_chan->mem_end - tx_chan->mem_off;
  59. // where to put the encoded symbols? DMA buffer or RMT HW memory
  60. rmt_symbol_word_t *mem_to_nc = NULL;
  61. if (channel->dma_chan) {
  62. mem_to_nc = (rmt_symbol_word_t *)RMT_GET_NON_CACHE_ADDR(channel->dma_mem_base);
  63. } else {
  64. mem_to_nc = channel->hw_mem_base;
  65. }
  66. // how many symbols will be encoded in this round
  67. size_t encode_len = MIN(mem_want, mem_have);
  68. bool encoding_truncated = mem_have < mem_want;
  69. bool encoding_space_free = mem_have > mem_want;
  70. if (channel->dma_chan) {
  71. // mark the start descriptor
  72. if (tx_chan->mem_off < tx_chan->ping_pong_symbols) {
  73. desc0 = &tx_chan->dma_nodes_nc[0];
  74. } else {
  75. desc0 = &tx_chan->dma_nodes_nc[1];
  76. }
  77. }
  78. size_t len = encode_len;
  79. while (len > 0) {
  80. // start from last time truncated encoding
  81. uint8_t cur_byte = nd[byte_index];
  82. // bit-wise reverse
  83. if (bytes_encoder->flags.msb_first) {
  84. cur_byte = hal_utils_bitwise_reverse8(cur_byte);
  85. }
  86. while ((len > 0) && (bit_index < 8)) {
  87. if (cur_byte & (1 << bit_index)) {
  88. mem_to_nc[tx_chan->mem_off++] = bytes_encoder->bit1;
  89. } else {
  90. mem_to_nc[tx_chan->mem_off++] = bytes_encoder->bit0;
  91. }
  92. len--;
  93. bit_index++;
  94. }
  95. if (bit_index >= 8) {
  96. byte_index++;
  97. bit_index = 0;
  98. }
  99. }
  100. if (channel->dma_chan) {
  101. // mark the end descriptor
  102. if (tx_chan->mem_off < tx_chan->ping_pong_symbols) {
  103. desc1 = &tx_chan->dma_nodes_nc[0];
  104. } else {
  105. desc1 = &tx_chan->dma_nodes_nc[1];
  106. }
  107. // cross line, means desc0 has prepared with sufficient data buffer
  108. if (desc0 != desc1) {
  109. desc0->dw0.length = tx_chan->ping_pong_symbols * sizeof(rmt_symbol_word_t);
  110. desc0->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
  111. }
  112. }
  113. if (encoding_truncated) {
  114. // this encoding has not finished yet, save the truncated position
  115. bytes_encoder->last_bit_index = bit_index;
  116. bytes_encoder->last_byte_index = byte_index;
  117. } else {
  118. // reset internal index if encoding session has finished
  119. bytes_encoder->last_bit_index = 0;
  120. bytes_encoder->last_byte_index = 0;
  121. state |= RMT_ENCODING_COMPLETE;
  122. }
  123. if (!encoding_space_free) {
  124. // no more free memory, the caller should yield
  125. state |= RMT_ENCODING_MEM_FULL;
  126. }
  127. // reset offset pointer when exceeds maximum range
  128. if (tx_chan->mem_off >= tx_chan->ping_pong_symbols * 2) {
  129. if (channel->dma_chan) {
  130. desc1->dw0.length = tx_chan->ping_pong_symbols * sizeof(rmt_symbol_word_t);
  131. desc1->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
  132. }
  133. tx_chan->mem_off = 0;
  134. }
  135. *ret_state = state;
  136. return encode_len;
  137. }
  138. static esp_err_t rmt_copy_encoder_reset(rmt_encoder_t *encoder)
  139. {
  140. rmt_copy_encoder_t *copy_encoder = __containerof(encoder, rmt_copy_encoder_t, base);
  141. copy_encoder->last_symbol_index = 0;
  142. return ESP_OK;
  143. }
  144. static size_t IRAM_ATTR rmt_encode_copy(rmt_encoder_t *encoder, rmt_channel_handle_t channel,
  145. const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
  146. {
  147. rmt_copy_encoder_t *copy_encoder = __containerof(encoder, rmt_copy_encoder_t, base);
  148. rmt_tx_channel_t *tx_chan = __containerof(channel, rmt_tx_channel_t, base);
  149. rmt_symbol_word_t *symbols = (rmt_symbol_word_t *)primary_data;
  150. rmt_encode_state_t state = RMT_ENCODING_RESET;
  151. rmt_dma_descriptor_t *desc0 = NULL;
  152. rmt_dma_descriptor_t *desc1 = NULL;
  153. size_t symbol_index = copy_encoder->last_symbol_index;
  154. // how many symbols will be copied by the encoder
  155. size_t mem_want = (data_size / 4 - symbol_index);
  156. // how many symbols we can save for this round
  157. size_t mem_have = tx_chan->mem_end - tx_chan->mem_off;
  158. // where to put the encoded symbols? DMA buffer or RMT HW memory
  159. rmt_symbol_word_t *mem_to_nc = NULL;
  160. if (channel->dma_chan) {
  161. mem_to_nc = (rmt_symbol_word_t *)RMT_GET_NON_CACHE_ADDR(channel->dma_mem_base);
  162. } else {
  163. mem_to_nc = channel->hw_mem_base;
  164. }
  165. // how many symbols will be encoded in this round
  166. size_t encode_len = MIN(mem_want, mem_have);
  167. bool encoding_truncated = mem_have < mem_want;
  168. bool encoding_space_free = mem_have > mem_want;
  169. if (channel->dma_chan) {
  170. // mark the start descriptor
  171. if (tx_chan->mem_off < tx_chan->ping_pong_symbols) {
  172. desc0 = &tx_chan->dma_nodes_nc[0];
  173. } else {
  174. desc0 = &tx_chan->dma_nodes_nc[1];
  175. }
  176. }
  177. size_t len = encode_len;
  178. while (len > 0) {
  179. mem_to_nc[tx_chan->mem_off++] = symbols[symbol_index++];
  180. len--;
  181. }
  182. if (channel->dma_chan) {
  183. // mark the end descriptor
  184. if (tx_chan->mem_off < tx_chan->ping_pong_symbols) {
  185. desc1 = &tx_chan->dma_nodes_nc[0];
  186. } else {
  187. desc1 = &tx_chan->dma_nodes_nc[1];
  188. }
  189. // cross line, means desc0 has prepared with sufficient data buffer
  190. if (desc0 != desc1) {
  191. desc0->dw0.length = tx_chan->ping_pong_symbols * sizeof(rmt_symbol_word_t);
  192. desc0->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
  193. }
  194. }
  195. if (encoding_truncated) {
  196. // this encoding has not finished yet, save the truncated position
  197. copy_encoder->last_symbol_index = symbol_index;
  198. } else {
  199. // reset internal index if encoding session has finished
  200. copy_encoder->last_symbol_index = 0;
  201. state |= RMT_ENCODING_COMPLETE;
  202. }
  203. if (!encoding_space_free) {
  204. // no more free memory, the caller should yield
  205. state |= RMT_ENCODING_MEM_FULL;
  206. }
  207. // reset offset pointer when exceeds maximum range
  208. if (tx_chan->mem_off >= tx_chan->ping_pong_symbols * 2) {
  209. if (channel->dma_chan) {
  210. desc1->dw0.length = tx_chan->ping_pong_symbols * sizeof(rmt_symbol_word_t);
  211. desc1->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
  212. }
  213. tx_chan->mem_off = 0;
  214. }
  215. *ret_state = state;
  216. return encode_len;
  217. }
  218. static esp_err_t rmt_del_bytes_encoder(rmt_encoder_t *encoder)
  219. {
  220. rmt_bytes_encoder_t *bytes_encoder = __containerof(encoder, rmt_bytes_encoder_t, base);
  221. free(bytes_encoder);
  222. return ESP_OK;
  223. }
  224. static esp_err_t rmt_del_copy_encoder(rmt_encoder_t *encoder)
  225. {
  226. rmt_copy_encoder_t *copy_encoder = __containerof(encoder, rmt_copy_encoder_t, base);
  227. free(copy_encoder);
  228. return ESP_OK;
  229. }
  230. esp_err_t rmt_new_bytes_encoder(const rmt_bytes_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
  231. {
  232. esp_err_t ret = ESP_OK;
  233. ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
  234. rmt_bytes_encoder_t *encoder = heap_caps_calloc(1, sizeof(rmt_bytes_encoder_t), RMT_MEM_ALLOC_CAPS);
  235. ESP_GOTO_ON_FALSE(encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for bytes encoder");
  236. encoder->base.encode = rmt_encode_bytes;
  237. encoder->base.del = rmt_del_bytes_encoder;
  238. encoder->base.reset = rmt_bytes_encoder_reset;
  239. encoder->bit0 = config->bit0;
  240. encoder->bit1 = config->bit1;
  241. encoder->flags.msb_first = config->flags.msb_first;
  242. // return general encoder handle
  243. *ret_encoder = &encoder->base;
  244. ESP_LOGD(TAG, "new bytes encoder @%p", encoder);
  245. err:
  246. return ret;
  247. }
  248. esp_err_t rmt_new_copy_encoder(const rmt_copy_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
  249. {
  250. esp_err_t ret = ESP_OK;
  251. ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
  252. rmt_copy_encoder_t *encoder = heap_caps_calloc(1, sizeof(rmt_copy_encoder_t), RMT_MEM_ALLOC_CAPS);
  253. ESP_GOTO_ON_FALSE(encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for copy encoder");
  254. encoder->base.encode = rmt_encode_copy;
  255. encoder->base.del = rmt_del_copy_encoder;
  256. encoder->base.reset = rmt_copy_encoder_reset;
  257. // return general encoder handle
  258. *ret_encoder = &encoder->base;
  259. ESP_LOGD(TAG, "new copy encoder @%p", encoder);
  260. err:
  261. return ret;
  262. }
  263. esp_err_t rmt_del_encoder(rmt_encoder_handle_t encoder)
  264. {
  265. ESP_RETURN_ON_FALSE(encoder, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
  266. return encoder->del(encoder);
  267. }
  268. esp_err_t rmt_encoder_reset(rmt_encoder_handle_t encoder)
  269. {
  270. ESP_RETURN_ON_FALSE(encoder, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
  271. return encoder->reset(encoder);
  272. }