Page 1 of 1

how to sovle RMT encoding memory full

Posted: Sun Jul 09, 2023 3:16 am
by lazy_pika
I am new to RMT and want to transmit 100 symbols by RMT tx.
But I encountered a problem where I wanted to send 100 symbols. During the encoding phase, there was an error with insufficient encoding memory.
I used global variable to record the results(encoded symbols) of each step of encoding. Here is my code of encoding, based on esp-idf example:
  1. static size_t rmt_encode_ir_nec(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
  2. {
  3.     rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base);
  4.     rmt_encode_state_t session_state = 0;
  5.     rmt_encode_state_t state = 0;
  6.     size_t encoded_symbols = 0;
  7.     ir_nec_transmit_command_code_t *ir_nec_transmit_command_code = (ir_nec_transmit_command_code_t *)primary_data;
  8.     rmt_encoder_handle_t copy_encoder = nec_encoder->copy_encoder;
  9.     rmt_encoder_handle_t bytes_encoder = nec_encoder->bytes_encoder;
  10.     switch (nec_encoder->state) {
  11.     case 0: // send leading code
  12.         encoded_symbols += copy_encoder->encode(copy_encoder, channel, &nec_encoder->nec_leading_symbol,
  13.                                                 sizeof(rmt_symbol_word_t), &session_state);
  14.         g_encoded_symbols_after_leading_code = encoded_symbols;
  15.         if (session_state & RMT_ENCODING_COMPLETE) {
  16.             nec_encoder->state = 1; // we can only switch to next state when current encoder finished
  17.         }
  18.         if (session_state & RMT_ENCODING_MEM_FULL) {
  19.             state |= RMT_ENCODING_MEM_FULL;
  20.             goto out; // yield if there's no free space to put other encoding artifacts
  21.         }
  22.     // fall-through
  23.     case 1: // send command 1
  24.         encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &ir_nec_transmit_command_code->command1,
  25.                                                  sizeof(uint16_t), &session_state);
  26.  
  27.         g_encoded_symbols_after_command1 = encoded_symbols;
  28.         if (session_state & RMT_ENCODING_COMPLETE) {
  29.             nec_encoder->state = 2; // we can only switch to next state when current encoder finished
  30.         }
  31.         if (session_state & RMT_ENCODING_MEM_FULL) {
  32.             state |= RMT_ENCODING_MEM_FULL;
  33.             goto out; // yield if there's no free space to put other encoding artifacts
  34.         }
  35.     // fall-through
  36.     case 2: // send command 2
  37.         encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &ir_nec_transmit_command_code->command2,
  38.                                                  sizeof(uint16_t), &session_state);
  39.         g_encoded_symbols_after_command2 = encoded_symbols;                                          
  40.         if (session_state & RMT_ENCODING_COMPLETE) {
  41.             nec_encoder->state = 3; // we can only switch to next state when current encoder finished
  42.         }
  43.         if (session_state & RMT_ENCODING_MEM_FULL) {
  44.             state |= RMT_ENCODING_MEM_FULL;
  45.             goto out; // yield if there's no free space to put other encoding artifacts
  46.         }
  47.     // fall-through
  48.     case 3: // send command 3
  49.         encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &ir_nec_transmit_command_code->command3,
  50.                                                  sizeof(uint16_t), &session_state);
  51.  
  52.         g_encoded_symbols_after_command3 = encoded_symbols;                                        
  53.         if (session_state & RMT_ENCODING_COMPLETE) {
  54.             nec_encoder->state = 4; // we can only switch to next state when current encoder finished
  55.         }
  56.         if (session_state & RMT_ENCODING_MEM_FULL) {
  57.             state |= RMT_ENCODING_MEM_FULL;
  58.             goto out; // yield if there's no free space to put other encoding artifacts
  59.         }
  60.     // fall-through
  61.     case 4: // send middle code 1
  62.         encoded_symbols += copy_encoder->encode(copy_encoder, channel, &nec_encoder->nec_middle_symbol[0],
  63.                                                 sizeof(rmt_symbol_word_t), &session_state);
  64.         g_encoded_symbols_after_middle_code1 = encoded_symbols;
  65.         if (session_state & RMT_ENCODING_COMPLETE) {
  66.             nec_encoder->state = 5; // we can only switch to next state when current encoder finished
  67.         }
  68.         if (session_state & RMT_ENCODING_MEM_FULL) {
  69.             state |= RMT_ENCODING_MEM_FULL;
  70.             goto out; // yield if there's no free space to put other encoding artifacts
  71.         }
  72.     // fall-through
  73.     case 5: // send middle code 2
  74.         encoded_symbols += copy_encoder->encode(copy_encoder, channel, &nec_encoder->nec_middle_symbol[1],
  75.                                                 sizeof(rmt_symbol_word_t), &session_state);
  76.         g_encoded_symbols_after_middle_code2 = encoded_symbols;
  77.         if (session_state & RMT_ENCODING_COMPLETE) {
  78.             nec_encoder->state = 6; // we can only switch to next state when current encoder finished
  79.         }
  80.         if (session_state & RMT_ENCODING_MEM_FULL) {
  81.             state |= RMT_ENCODING_MEM_FULL;
  82.             goto out; // yield if there's no free space to put other encoding artifacts
  83.         }
  84.     // fall-through
  85.     case 6: // send command 4
  86.         encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &ir_nec_transmit_command_code->command4,
  87.                                                  sizeof(uint16_t), &session_state);
  88.         g_encoded_symbols_after_command4 = encoded_symbols;  
  89.         if (session_state & RMT_ENCODING_COMPLETE) {
  90.             nec_encoder->state = 7; // we can only switch to next state when current encoder finished
  91.         }
  92.         if (session_state & RMT_ENCODING_MEM_FULL) {
  93.             state |= RMT_ENCODING_MEM_FULL;
  94.             goto out; // yield if there's no free space to put other encoding artifacts
  95.         }
  96.     // fall-through
  97.     case 7: // send command 5
  98.         encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &ir_nec_transmit_command_code->command5,
  99.                                                  sizeof(uint16_t), &session_state);
  100.         g_encoded_symbols_after_command5 = encoded_symbols;  
  101.         if (session_state & RMT_ENCODING_COMPLETE) {
  102.             nec_encoder->state = 8; // we can only switch to next state when current encoder finished
  103.         }
  104.         if (session_state & RMT_ENCODING_MEM_FULL) {
  105.             state |= RMT_ENCODING_MEM_FULL;
  106.             goto out; // yield if there's no free space to put other encoding artifacts
  107.         }
  108.     // fall-through
  109.     case 8: // send command 6
  110.         encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &ir_nec_transmit_command_code->command6,
  111.                                                  sizeof(uint16_t), &session_state);
  112.         g_encoded_symbols_after_command6 = encoded_symbols;  
  113.         if (session_state & RMT_ENCODING_COMPLETE) {
  114.             nec_encoder->state = 9; // we can only switch to next state when current encoder finished
  115.         }
  116.         if (session_state & RMT_ENCODING_MEM_FULL) {
  117.             state |= RMT_ENCODING_MEM_FULL;
  118.             g_mem_full_flag = 1;
  119.             goto out; // yield if there's no free space to put other encoding artifacts
  120.         }
  121.     // fall-through
  122.     case 9: // send ending code
  123.         encoded_symbols += copy_encoder->encode(copy_encoder, channel, &nec_encoder->nec_ending_symbol,
  124.                                                 sizeof(rmt_symbol_word_t), &session_state);
  125.         g_encoded_symbols_after_end_code = encoded_symbols;
  126.         if (session_state & RMT_ENCODING_COMPLETE) {
  127.             nec_encoder->state = 0; // back to the initial encoding session
  128.             state |= RMT_ENCODING_COMPLETE;
  129.         }
  130.         if (session_state & RMT_ENCODING_MEM_FULL) {
  131.             state |= RMT_ENCODING_MEM_FULL;
  132.             goto out; // yield if there's no free space to put other encoding artifacts
  133.         }
  134.     }
  135. out:
  136.     *ret_state = state;
  137.     g_encoded_symbols = encoded_symbols;
  138.     return encoded_symbols;
  139. }
And the result output:
g_encoded_symbols_after_leading_code = 1
g_encoded_symbols_after_command1 = 17
g_encoded_symbols_after_command2 = 33
g_encoded_symbols_after_command3 = 49
g_encoded_symbols_after_middle_code1 = 50
g_encoded_symbols_after_middle_code2 = 51
g_encoded_symbols_after_command4 = 67
g_encoded_symbols_after_command5 = 83
g_encoded_symbols_after_command6 = 96
g_encoded_symbols_after_end_code = 0
g_mem_full_flag = 1

It seems that memory was full in command6 encoding.
how can I encode 100 symbols completely?
Thank you in advance!

Re: how to sovle RMT encoding memory full

Posted: Sun Jul 09, 2023 10:33 am
by MicroController
there was an error with insufficient encoding memory.
That's not an error. RMT_ENCODING_MEM_FULL is a valid intermediate state during encoding a transmission. It is used to let the RMT driver know that it needs to call the encoder again because more symbols need to be encoded, in contrast to RMT_ENCODING_COMPLETE.
how can I encode 100 symbols completely?
The RMT driver will call the encoder again as needed, until it returns RMT_ENCODING_COMPLETE.

Re: how to sovle RMT encoding memory full

Posted: Sun Jul 09, 2023 11:07 am
by lazy_pika
thank you. So does it mean it transmitted the whole 100 symbols actually? I'd better to check it. ;)