Skip to content

espressif: pulseio.PulseIn - Use dma only when necessary #10499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions ports/espressif/common-hal/pulseio/PulseIn.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,20 @@ static bool _done_callback(rmt_channel_handle_t rx_chan,

void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu_pin_obj_t *pin,
uint16_t maxlen, bool idle_state) {

// Only use dma when necessary, since dma-rmt might not be available.
// If dma is necessary but not available, this will raise an error below.
bool use_dma = maxlen > 128;

self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t));
if (self->buffer == NULL) {
m_malloc_fail(maxlen * sizeof(uint16_t));
}
// We add one to the maxlen version to ensure that two symbols at lease are
// captured because we may skip the first portion of a symbol.
self->raw_symbols_size = MIN(64, maxlen / 2 + 1) * sizeof(rmt_symbol_word_t);
self->raw_symbols = (rmt_symbol_word_t *)m_malloc_without_collect(self->raw_symbols_size);
self->raw_symbols_size = (maxlen / 2 + 1) * sizeof(rmt_symbol_word_t);
// RMT DMA mode cannot access PSRAM -> ensure raw_symbols is in internal ram
self->raw_symbols = (rmt_symbol_word_t *)port_malloc(self->raw_symbols_size, use_dma);
if (self->raw_symbols == NULL) {
m_free(self->buffer);
m_malloc_fail(self->raw_symbols_size);
Expand Down Expand Up @@ -109,17 +115,31 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu
.clk_src = RMT_CLK_SRC_DEFAULT,
// 2 us resolution so we can capture 65ms pulses. The RMT period is only 15 bits.
.resolution_hz = 1000000 / 2,
.mem_block_symbols = SOC_RMT_MEM_WORDS_PER_CHANNEL,
.mem_block_symbols = use_dma ? self->raw_symbols_size : SOC_RMT_MEM_WORDS_PER_CHANNEL,
.flags.with_dma = use_dma
};
// If we fail here, the buffers allocated above will be garbage collected.
CHECK_ESP_RESULT(rmt_new_rx_channel(&config, &self->channel));
// If we fail here, the self->buffer will be garbage collected.
esp_err_t result = rmt_new_rx_channel(&config, &self->channel);
if (result != ESP_OK) {
port_free(self->raw_symbols);
if (result == ESP_ERR_NOT_SUPPORTED || result == ESP_ERR_NOT_FOUND) {
// DMA not available, cannot record long pulse sequences.
mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_maxlen);
} else {
raise_esp_error(result);
}
}

rmt_rx_event_callbacks_t rx_callback = {
.on_recv_done = _done_callback
};
rmt_rx_register_event_callbacks(self->channel, &rx_callback, self);
rmt_enable(self->channel);
rmt_receive(self->channel, self->raw_symbols, self->raw_symbols_size, &rx_config);
result = rmt_receive(self->channel, self->raw_symbols, self->raw_symbols_size, &rx_config);
if (result != ESP_OK) {
port_free(self->raw_symbols);
raise_esp_error(result);
}
}

bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t *self) {
Expand Down
4 changes: 4 additions & 0 deletions shared-bindings/pulseio/PulseIn.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
//| :param bool idle_state: Idle state of the pin. At start and after `resume`
//| the first recorded pulse will the opposite state from idle.
//|
//| **Limitations**: The `maxlen` parameter is limited depending on the specific board.
//| On most ESP32 variants the limit is 128. On ESP32-S3 and ESP32-P4 the first `PulseIn` instance
//| can use `maxlen` up to available RAM; all subsequent instances are limited to 128.
//|
//| Read a short series of pulses::
//|
//| import pulseio
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy