Page 1 of 1

How can I dynamically modify the duration0 parameter of this structure 'bytes_encoder_config' after calling rmt_new_byte

Posted: Tue Dec 12, 2023 1:04 am
by chenkejin
In the following code,
In the following code, how do I dynamically modify the duration0 parameter already configured in the object nec_encoder->bytes_encoder of the rmt_encoder_handle_t structure?

Code: Select all

[Codebox=c file=Untitled.c]
typedef struct
{
    rmt_encoder_t base;           // the base "class", declares the standard encoder interface
    rmt_encoder_t *bytes_encoder; // use the bytes_encoder to encode the address and command data
    int state;
} rmt_ir_nec_encoder_t;

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)
{
    rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base);
    rmt_encode_state_t session_state = RMT_ENCODING_RESET;
    rmt_encode_state_t state = RMT_ENCODING_RESET;
    size_t encoded_symbols = 0;
    ir_nec_scan_code_t *scan_code = (ir_nec_scan_code_t *)primary_data;
    uint32_t flag[6] = {0x80000001, 0x80000001, 0x80000001, 0x80000001, 0x80000001, 0x80000001};

    rmt_encoder_handle_t bytes_encoder = nec_encoder->bytes_encoder;
[color=#FF0040]//?????
   //How can I dynamically modify the duration0 parameter of this structure 'bytes_encoder_config' after calling rmt_new_bytes_encoder.
   //?????[/color]
    switch (nec_encoder->state)
    {
    case 0:
        encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &flag[0], sizeof(uint32_t), &session_state);
        if (session_state & RMT_ENCODING_COMPLETE)
        {
            nec_encoder->state = 1; // we can only switch to next state when current encoder finished
        }
        if (session_state & RMT_ENCODING_MEM_FULL)
        {
            state |= RMT_ENCODING_MEM_FULL;
            goto out; // yield if there's no free space to put other encoding artifacts
        }
        // fall-through
    case 1:
        encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &flag[1], sizeof(uint32_t), &session_state);
        if (session_state & RMT_ENCODING_COMPLETE)
        {
            nec_encoder->state = 2; // we can only switch to next state when current encoder finished
        }
        if (session_state & RMT_ENCODING_MEM_FULL)
        {
            state |= RMT_ENCODING_MEM_FULL;
            goto out; // yield if there's no free space to put other encoding artifacts
        }
        // fall-through
    case 2:
        encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &flag[2], sizeof(uint32_t), &session_state);
        if (session_state & RMT_ENCODING_COMPLETE)
        {
            nec_encoder->state = 3; // we can only switch to next state when current encoder finished
        }
        if (session_state & RMT_ENCODING_MEM_FULL)
        {
            state |= RMT_ENCODING_MEM_FULL;
            goto out; // yield if there's no free space to put other encoding artifacts
        }
        // fall-through
    case 3:
        encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &flag[3], sizeof(uint32_t), &session_state);
        if (session_state & RMT_ENCODING_COMPLETE)
        {
            nec_encoder->state = 4; // we can only switch to next state when current encoder finished
        }
        if (session_state & RMT_ENCODING_MEM_FULL)
        {
            state |= RMT_ENCODING_MEM_FULL;
            goto out; // yield if there's no free space to put other encoding artifacts
        }
        // fall-through
    case 4:
        encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &flag[4], sizeof(uint32_t), &session_state);
        if (session_state & RMT_ENCODING_COMPLETE)
        {
            nec_encoder->state = 5; // we can only switch to next state when current encoder finished
        }
        if (session_state & RMT_ENCODING_MEM_FULL)
        {
            state |= RMT_ENCODING_MEM_FULL;
            goto out; // yield if there's no free space to put other encoding artifacts
        }
        // fall through
    case 5:
        encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, &flag[5], sizeof(uint32_t), &session_state);
        if (session_state & RMT_ENCODING_COMPLETE)
        {
            nec_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session
            state |= RMT_ENCODING_COMPLETE;
        }
        if (session_state & RMT_ENCODING_MEM_FULL)
        {
            state |= RMT_ENCODING_MEM_FULL;
            goto out; // yield if there's no free space to put other encoding artifacts
        }
        // fall through
    default:
        break;
    }
out:
    *ret_state = state;
    return encoded_symbols;
}

static esp_err_t rmt_del_ir_nec_encoder(rmt_encoder_t *encoder)
{
    rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base);
    rmt_del_encoder(nec_encoder->bytes_encoder);
    free(nec_encoder);
    return ESP_OK;
}

static esp_err_t rmt_ir_nec_encoder_reset(rmt_encoder_t *encoder)
{
    rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base);
    rmt_encoder_reset(nec_encoder->bytes_encoder);
    nec_encoder->state = RMT_ENCODING_RESET;
    return ESP_OK;
}

esp_err_t rmt_new_ir_nec_encoder(const ir_nec_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
{
    esp_err_t ret = ESP_OK;
    rmt_ir_nec_encoder_t *nec_encoder = NULL;
    ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
    nec_encoder = calloc(1, sizeof(rmt_ir_nec_encoder_t));
    ESP_GOTO_ON_FALSE(nec_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for ir nec encoder");

    nec_encoder->base.encode = rmt_encode_ir_nec;
    nec_encoder->base.del = rmt_del_ir_nec_encoder;
    nec_encoder->base.reset = rmt_ir_nec_encoder_reset;

    rmt_bytes_encoder_config_t bytes_encoder_config = {
        .bit0 = {
            .level0 = 0,
            .duration0 = config->speed * config->resolution / 1000000, // 
            .level1 = 0,
            .duration1 = config->speed * config->resolution / 1000000, // 
        },
        .bit1 = {
            .level0 = 1,
            .duration0 = config->speed * config->resolution / 1000000, // 
            .level1 = 1,
            .duration1 = config->speed * config->resolution / 1000000, // 
        },
        .flags.msb_first = 0, // 
    };
    rmt_new_bytes_encoder(&bytes_encoder_config, &nec_encoder->bytes_encoder);
    *ret_encoder = &nec_encoder->base;
    return ESP_OK;
err:
    if (nec_encoder)
    {
        if (nec_encoder->bytes_encoder)
        {
            rmt_del_encoder(nec_encoder->bytes_encoder);
        }
        free(nec_encoder);
    }
    return ret;
}
[/Codebox]

I tried to make a call to rmt_new_bytes_encoder in the rmt_encode_ir_nec function to achieve the effect I need. But there is a call to heap_caps_calloc in the rmt_new_bytes_encoder function, does this have a performance impact?

Code: Select all

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)
{
    rmt_ir_nec_encoder_t *nec_encoder = __containerof(encoder, rmt_ir_nec_encoder_t, base);
    rmt_encode_state_t session_state = RMT_ENCODING_RESET;
    rmt_encode_state_t state = RMT_ENCODING_RESET;
    size_t encoded_symbols = 0;
    ir_nec_scan_code_t *scan_code = (ir_nec_scan_code_t *)primary_data;
    uint32_t flag[6] = {0x80000001, 0x80000001, 0x80000001, 0x80000001, 0x80000001, 0x80000001};

    rmt_encoder_handle_t bytes_encoder ;
    rmt_bytes_encoder_config_t bytes_encoder_config = {
        .bit0 = {
            .level0 = 0,
            .duration0 = scan_code.command* scan_code.resolution / 1000000, // T0H=560us
            .level1 = 0,
            .duration1 = scan_code.command* scan_code.resolution/ 1000000, // T0L=560us
        },
        .bit1 = {
            .level0 = 1,
            .duration0 = scan_code.command* scan_code.resolution / 1000000, // T1H=560us
            .level1 = 1,
            .duration1 = scan_code.command* scan_code.resolution / 1000000, // T1L=1690us
        },
        .flags.msb_first = 0, // 从低bit位开始产生波形
    };
    rmt_new_bytes_encoder(&bytes_encoder_config, &bytes_encoder);

    switch (nec_encoder->state)
    {
    case 0:
       //..........
    }
out:
    *ret_state = state;
    return encoded_symbols;
}