Open higaski opened 10 months ago
@higaski Thanks for your interest in the RMT.
The delay you see between RMT transmission is introduced by the software. When the previous transmission finished, we will call a callback function, then retrieve a new transmission from an internal queue, and afterward, set up the necessary registers according to the transmission description (In the function rmt_tx_do_transaction
). All of them cost time and can introduce delay.
BTW, a loop transmission is controlled by the hardware, so it's 100% consecutive.
I need to send different packets. How can I work around this issue? Is this really a hardware limitation? Could the driver potentially load RMT symbols from the next element in queue before the current transmission is done?
Can RMT trigger a timer or something so that I can calculate how far I'm off?
/edit https://github.com/espressif/esp-idf/issues/9991 seems kinda related
I'm afraid it's not easy to support the pre-load feature because the encoder is not working in a one-shot way. The encoder keeps generating new symbols and writes to the FIFO memory when the transmitter is working on the old symbols. Also we support different types of transmission (infinite loop, finite loop, no loop), they need different register configurations. So if we do a "pre-set", it will affect the current transmission.
I need to send different packets. How can I work around this issue?
Maybe you can make a customized encoder, and in the state machine, you can prepare any kinds of packets you link..
Can RMT trigger a timer or something so that I can calculate how far I'm off?
Do you mean the Event Task Matrix feature ? No, RMT doesn't have that hardware support yet.
I need to send different packets. How can I work around this issue?
Maybe you can make a customized encoder, and in the state machine, you can prepare any kinds of packets you link..
You mean like combining data into a single never ending transmission? If I do that I can no longer tell when one packet ends and the next one starts... Timing between them is crucial to me as well.
/edit I already have a custom "regular" encoder. I only use the bytes encoder for a convenience example so that you don't have to pile through 500 lines of shit C code. :D
Continous running transmission works in the 4.x IDE. We have a product that uses a continious transmission which consists of a fixed preamble and the changing paylaod. The payload is updated with rmt_fill_tx_items(channel, data, dataLen, preambleOffset)
while the preamble is running. Of course I want to be able to update my project to the 5.x IDE eventually. Please make that possible.
Regards, Harald.
REF to source: https://github.com/DCC-EX/CommandStation-EX/blob/master/DCCRMT.cpp
@habazut I see your request, we didn't expect the user will still want to update the FIFO memory dynamically in the loop mode. In the current design, we only preload the FIFO memory by the encoder for once, and the normal "one-round trans done" interrupt is disabled, because we don't want that event to happen too frequently in the loop mode if there's no data needs updated. We may reconsider this use case...
Is there a risk that while the RMT is transmitting the "IDLE" symbols, you're filling "data" to the same FIFO region?
So, what's the recommended approach now? Besides that drawback I pointed out in my original post I quite like the current encoder-based driver API. I thought about creating a workaround for my issue by introducing a special "very last symbol in a transmission" state which accommodates for the delay. So basically the last pulse would be shorter...
Of course this is rather ugly since that delay is, and correct me if I'm wrong, depended on
So one would have to adjust that last symbol depending on the current CPU frequency, compiler optimizations and maybe even compiler versions....?
/edit
I've just tried adjusting the mem_block_symbols
size from min (48) to max (384) and to my surprise this doesn't effect the delay at all. So apparently copying of a queued transmission does not take up any processor time, it's really just the peripheral setup?
With the 4.x IDE I can get continous transmission of abcdef
like this
abcdefabcdefabcdefabcdef....
My protocol does not like pauses between f
and a
or stretched symbols.
With the 4.x IDE I can get either an end interrupt after f
(happens during a
)
or I can with rmt_set_tx_thr_intr_en(... 3 ...)
get an interrupt during d
.
Or I can have both.
With the interrupt code during a
I can replace symbols def
to something else. Replacement is faster than one symbol time.
With the interrupt code duriung d
I can replace symbols abc
to something else.
How should I do this with the new IDE? Apparently the hardware can do it as the 4.x IDE can make the hardware do it that way. I don't want to fiddle with the RMT registers myself, that's what the HAL is for I suppose.
Regards, Harald.
I agree, this is a necessary feature. Relying on workarounds by tinkering with the transmission end is not very satisfying... specially not if the hardware would potentially be able to handle such cases itself.
Looking at the HW reference manuals of the ESP32 and the ESP32-S3 I want to use these two interrupts:
• RMT_CHn_TX_THR_EVENT_INT: Triggered when the amount of data the transmitter has sent matches the
value of RMT_CHn_TX_LIM_REG.
• RMT_CHn_TX_END_INT: Triggered when the transmitter has finished transmitting the signal.
Whis is explained in the manual:
...When an RMT_CHn_TX_THR_EVENT_INT interrupt is
detected by software, the already used RAM region can be updated by new pulse codes. In such way, the
transmitter can seamlessly send unlimited pulse codes...
Example code welcome. Reagards, Harald.
Answers checklist.
IDF version.
ESP-IDF v5.3-dev-1353-gb3f7e2c8a4
Espressif SoC revision.
ESP32-S3 (QFN56) (revision v0.1)
Operating System used.
Linux
How did you build your project?
Command line with idf.py
If you are using Windows, please specify command line type.
None
Development Kit.
ESP32-S3-DevKitC-1
Power Supply used.
USB
What is the expected behavior?
I've always been under the impression that the RMT peripheral should be able to do continuous transmissions when the transmission queue is specified to be greater 1. However this does not seem to be the case. The current driver does introduce a significant delay between two consecutive transmissions.
What is the actual behavior?
Take a look at the following scope image. It shows a simple bytes encoder transmitting a 1 bit as a 50us high/50 us low pulse. Inside a transmission frame those timings are kept perfect, but between two transmissions they are clearly not although the very first bit is a 1 again.
Steps to reproduce.
Here is a reproducible example of my issue. It uses GPIO11 to output a signal with RMT and GPIO10 to get some reference toggle between two transmissions. The whole example is also available here: https://github.com/higaski/esp32s3_rmt_bug
Debug Logs.
No response
More Information.
No response