Page 1 of 2

Could RMT split "rmt_symbols" by time, not by level change?

Posted: Sat May 03, 2025 4:58 pm
by imShara
I need to decode custom protocol in non-blocking mode. The data looks like this:

data.png
data.png (9.4 KiB) Viewed 247 times

With RMT I can receive symbols with level and duration.


Image

I can restore value by some calculations, but it will be better to get proper chunks directly from hardware like this:

Code: Select all

{1 high, 0 low}
{1 high, 0 low}
{1 high, 0 low}
{0 high, 1 low}
{1 high, 0 low}
{0 high, 1 low}
{0 high, 1 low}

I thought I could use signal_range_max_ns from rmt_receive_config_t, but no luck:

rmt_receive_config_t::signal_range_max_ns specifies the maximum valid pulse duration in either high or low logic levels. A pulse width that is bigger than this value is treated as Stop Signal, and the receiver generates receive-complete event immediately.

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Sun May 04, 2025 6:57 am
by imShara
I can restore value by some calculations

No, I cant, because If there will be multiple high level bits at the end of word, rmt won't calculate them because there is no falling edge after last bit... You can assume that there is high level bits if rmt symbols not enough. But it looks like a bad hack.

nofalling.png
nofalling.png (26.7 KiB) Viewed 242 times

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Mon May 05, 2025 2:14 am
by Sprite
You could; you can tell RMT to time out after not receiving a level change for x time. That would get you your final symbol. You could also go an entirely different way: for instance use the I2S input to grab an (unsynchronized) serial stream of bytes, then decode those in software. Also, if you actually get that clock signal as well, it looks like something the SPI peripheral should be able to receive.

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Tue May 06, 2025 5:13 am
by imShara
No, it's not an i2s, its just simple bit-banging protocol - it responds with a bit for every raising edge you transmit until word ends.

I solve it by counting low levels instead hi-levels and parse RMT output in that way:

Code: Select all

   // I set rx resolution to make rmt_symbols[i].duration = signal_level_duration * number_of_sent_bits by resolution_hz at rmt_rx_channel_config 
   // In my case I receive 1 bit per 2µs so resolution_hz is 500 000 Hz

    uint32_t pos = 24; // We receiving 24 bit word
    uint32_t result = 0b00000000111111111111111111111111; // Set all bits to 1
    
    // Loop over all symbols except last because it never reach low level, closed by timeout and has wrong durations
    for (size_t i = 0; i < symbol_num - 1; i++) {
    	// Shift insert position by whole symbol length
        pos -= rmt_symbols[i].duration0 + rmt_symbols[i].duration1;
        // Set number of bits equal to length of low level duration to zero at position
        result ^= ((1U << rmt_symbols[i].duration1) - 1) << pos;
    }

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Tue May 06, 2025 7:53 am
by MicroController
it responds with a bit for every raising edge you transmit until word ends.
So are you sending the clock signal? If so, using SPI would be the best choice.

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Tue May 06, 2025 1:05 pm
by imShara
o are you sending the clock signal?

Yes, I'm sending the clock signal. It's HX711 ADC (datasheet) ADC and I need to read different channels of couple ACDS in non blocking mode.

diagram.png
diagram.png (37.86 KiB) Viewed 211 times

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Thu May 08, 2025 9:33 am
by MicroController
I need to read [...] in non blocking mode.
Maybe you don't. At 5MHz clock frequency, transferring 27 bits takes ~5.4 micro-seconds, or ~1300 CPU cycles @ 240MHz. This may be less than the overhead incurred (context switching,...) for an asynchronous transfer.

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Fri May 09, 2025 10:00 am
by imShara
Thank you for answer. ~5.4 micro-seconds of blocked core - it's ideal value for single cell and high-end rates cpu/adc datarate possibilities, recommended speed from datasheet is 1µs for single bit - its reasonable to make system reliable.

But. I found that RMT totally unuseable in this case:

RMT impossible signal.png
RMT impossible signal.png (21.12 KiB) Viewed 178 times
We don't know how many LOW level bits were skipped at start and how many HI level bits will be in the end..

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Fri May 09, 2025 10:44 am
by MicroController
But. I found that RMT totally unuseable in this case:

RMT impossible signal.png

We don't know how many LOW level bits were skipped at start and how many HI level bits will be in the end..
It seems the RMT could still be used. The RMT should detect the 'asynchronous' falling edge of DOUT, then you send 25-27 clock pulses, then stop the RMT. You can calculate the bits 'backwards' in time, starting from the final falling edge of PD_SCK.
But using SPI is probably still easier.

Re: Could RMT split "rmt_symbols" by time, not by level change?

Posted: Fri May 09, 2025 1:23 pm
by imShara
Hmm.. I'm using interruption, but ok RMT could detect DOUT low as [HI=0 LO=0], but what should it gave? Time between DOUT turns low and SCK starts transmission is variable.

RMT impossible signal2.png
RMT impossible signal2.png (27.62 KiB) Viewed 165 times

Thre is only 2 SPI channels and 8 (could be 1TX 7RX) RMT
i2s can't be used too - it starts clocking before receive is strarted.