Skip to content

Commit 2272489

Browse files
authored
Merge pull request #11748 from espressif/rmt_loop_count
feat(rmt): adds new function to send specific number of loops
2 parents 6dedab3 + ba60ffa commit 2272489

File tree

3 files changed

+76
-14
lines changed

3 files changed

+76
-14
lines changed

cores/esp32/esp32-hal-rmt.c

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ bool rmtDeinit(int pin) {
285285
return false;
286286
}
287287

288-
static bool _rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, bool blocking, bool loop, uint32_t timeout_ms) {
288+
static bool _rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, bool blocking, uint32_t loop, uint32_t timeout_ms) {
289289
rmt_bus_handle_t bus = _rmtGetBus(pin, __FUNCTION__);
290290
if (bus == NULL) {
291291
return false;
@@ -303,11 +303,21 @@ static bool _rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, bool bl
303303
}
304304
}
305305

306+
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
306307
log_v("GPIO: %d - Request: %d RMT Symbols - %s - Timeout: %d", pin, num_rmt_symbols, blocking ? "Blocking" : "Non-Blocking", timeout_ms);
307-
log_v(
308-
"GPIO: %d - Currently in Loop Mode: [%s] | Asked to Loop: %s, LoopCancel: %s", pin, bus->rmt_ch_is_looping ? "YES" : "NO", loop ? "YES" : "NO",
309-
loopCancel ? "YES" : "NO"
310-
);
308+
// loop parameter semantics:
309+
// loop == 0: no looping (single transmission)
310+
// loop == 1: infinite looping
311+
// loop > 1: transmit the data 'loop' times
312+
{
313+
char buf[17]; // placeholder for up to maximum uint32_t value (4294967295) = 10 digits + " times" (6 chars) + null terminator (17 bytes)
314+
snprintf(buf, sizeof(buf), "%lu times", loop);
315+
log_v(
316+
"GPIO: %d - Currently in Loop Mode: [%s] | Loop Request: [%s], LoopCancel: [%s]", pin, bus->rmt_ch_is_looping ? "YES" : "NO",
317+
loop == 0 ? "NO" : (loop == 1 ? "FOREVER" : buf), loopCancel ? "YES" : "NO"
318+
);
319+
}
320+
#endif
311321

312322
if ((xEventGroupGetBits(bus->rmt_events) & RMT_FLAG_TX_DONE) == 0) {
313323
log_v("GPIO %d - RMT Write still pending to be completed.", pin);
@@ -336,8 +346,8 @@ static bool _rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, bool bl
336346
bus->rmt_ch_is_looping = false;
337347
} else { // new writing | looping request
338348
// looping | Writing over a previous looping state is valid
339-
if (loop) {
340-
transmit_cfg.loop_count = -1; // enable infinite loop mode
349+
if (loop > 0) {
350+
transmit_cfg.loop_count = (loop == 1) ? -1 : loop;
341351
// keeps RMT_FLAG_TX_DONE set - it never changes
342352
} else {
343353
// looping mode never sets this flag (IDF 5.1) in the callback
@@ -348,8 +358,10 @@ static bool _rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, bool bl
348358
retCode = false;
349359
log_w("GPIO %d - RMT Transmission failed.", pin);
350360
} else { // transmit OK
351-
if (loop) {
352-
bus->rmt_ch_is_looping = true; // for ever... until a channel canceling or new writing
361+
if (loop > 0) {
362+
// rmt_ch_is_looping is used as a flag to indicate that RMT is in looping execution in order to
363+
// be canceled whenever a new _rmtWrite() is executed while it is looping
364+
bus->rmt_ch_is_looping = true;
353365
} else {
354366
if (blocking) {
355367
// wait for transmission confirmation | timeout
@@ -402,15 +414,36 @@ static bool _rmtRead(int pin, rmt_data_t *data, size_t *num_rmt_symbols, bool wa
402414
}
403415

404416
bool rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t timeout_ms) {
405-
return _rmtWrite(pin, data, num_rmt_symbols, true /*blocks*/, false /*looping*/, timeout_ms);
417+
return _rmtWrite(pin, data, num_rmt_symbols, true /*blocks*/, 0 /*looping*/, timeout_ms);
406418
}
407419

408420
bool rmtWriteAsync(int pin, rmt_data_t *data, size_t num_rmt_symbols) {
409-
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, false /*looping*/, 0 /*N/A*/);
421+
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, 0 /*looping*/, 0 /*N/A*/);
410422
}
411423

412424
bool rmtWriteLooping(int pin, rmt_data_t *data, size_t num_rmt_symbols) {
413-
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, true /*looping*/, 0 /*N/A*/);
425+
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, 1 /*looping*/, 0 /*N/A*/);
426+
}
427+
428+
// Same as rmtWriteLooping(...) but it transmits the data a fixed number of times ("loop_count").
429+
// loop_count == 0 is invalid (no transmission); loop_count == 1 transmits once (no looping); loop_count > 1 transmits the data repeatedly (looping).
430+
bool rmtWriteRepeated(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t loop_count) {
431+
if (loop_count == 0) {
432+
log_e("RMT TX GPIO %d : Invalid loop_count (%u). Must be at least 1.", pin, loop_count);
433+
return false;
434+
}
435+
if (loop_count == 1) {
436+
// send the RMT symbols once using non-blocking write (single non-looping transmission)
437+
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, 0 /*looping*/, 0 /*N/A*/);
438+
} else {
439+
// write the RMT symbols for loop_count times
440+
#if SOC_RMT_SUPPORT_TX_LOOP_COUNT
441+
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, loop_count /*looping*/, 0 /*N/A*/);
442+
#else
443+
log_e("RMT TX GPIO %d : Loop Count is not supported. Writing failed.", pin);
444+
return false;
445+
#endif
446+
}
414447
}
415448

416449
bool rmtTransmitCompleted(int pin) {

cores/esp32/esp32-hal-rmt.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ bool rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t timeou
124124
bool rmtWriteAsync(int pin, rmt_data_t *data, size_t num_rmt_symbols);
125125

126126
/**
127-
Writing data up to the reserved memsize, looping continuously
127+
Writing data up to the reserved memsize, looping continuously (rmtWriteLooping()) or fixed
128+
number of <loop_count> times (rmtWriteRepeated())
129+
128130
<rmt_symbol> is a 32 bits structure as defined by rmt_data_t type.
129131
It is possible to use the macro RMT_SYMBOLS_OF(data), if data is an array of rmt_data_t
130132
@@ -133,9 +135,11 @@ bool rmtWriteAsync(int pin, rmt_data_t *data, size_t num_rmt_symbols);
133135
Non-Blocking mode - returns right after execution
134136
Returns <true> on execution success, <false> otherwise
135137
136-
<bool rmtTransmitCompleted(int pin)> will return always <true> while it is looping.
138+
<bool rmtTransmitCompleted(int pin)> will return always <true> while it is looping mode.
139+
looping mode is active for rmtWriteLooping() and for rmtWriteRepeated() when loop_count > 1.
137140
*/
138141
bool rmtWriteLooping(int pin, rmt_data_t *data, size_t num_rmt_symbols);
142+
bool rmtWriteRepeated(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t loop_count);
139143

140144
/**
141145
Checks if transmission is completed and the rmtChannel ready for transmitting new data.

libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,30 @@ void RMT_Loop_Write_Blink() {
276276
delay(2000);
277277
}
278278

279+
void RMT_Repeated_Write_Blink() {
280+
Serial.println("Using RMT Writing repeated N times to blink an LED.");
281+
Serial.println("Blinking at 1s on + 1s off :: 2 blinks");
282+
// repeating blink_1s_rmt_data (1s on + 1s off) 2 times for 2 blinks
283+
if (!rmtWriteRepeated(BLINK_GPIO, blink_1s_rmt_data, RMT_SYMBOLS_OF(blink_1s_rmt_data), 2)) {
284+
Serial.println("===> rmtWrite Blink 1s Error!");
285+
}
286+
delay(4000 + 1000); // it should blink 2 times and stop automatically
287+
Serial.println("Blinking at 500ms on + 500ms off :: 4 blinks");
288+
// repeating blink_500ms_rmt_data (500ms on + 500ms off) 4 times for 4 blinks
289+
if (!rmtWriteRepeated(BLINK_GPIO, blink_500ms_rmt_data, RMT_SYMBOLS_OF(blink_500ms_rmt_data), 4)) {
290+
Serial.println("===> rmtWrite Blink 0.5s Error!");
291+
}
292+
delay(4000 + 1000); // it should blink 4 times and stop automatically
293+
Serial.println("Blinking at 250ms on + 250ms off :: 8 blinks");
294+
// repeating blink_250ms_rmt_data (250ms on + 250ms off) 8 times for 8 blinks
295+
if (!rmtWriteRepeated(BLINK_GPIO, blink_250ms_rmt_data, RMT_SYMBOLS_OF(blink_250ms_rmt_data), 8)) {
296+
Serial.println("===> rmtWrite Blink 0.25s Error!");
297+
}
298+
delay(4000 + 1000); // it should blink 8 times and stop automatically
299+
Serial.println("Blinking is OFF for 2 seconds");
300+
delay(2000);
301+
}
302+
279303
void RMT_Single_Write_Blocking_Blink() {
280304
Serial.println("Using RMT Writing and its Completion to blink an LED.");
281305
Serial.println("Blinking at 1s on + 1s off :: 2 blinks");
@@ -356,6 +380,7 @@ void setup() {
356380
void loop() {
357381
RMT_Write_Aync_Non_Blocking_Blink();
358382
RMT_Loop_Write_Blink();
383+
RMT_Repeated_Write_Blink();
359384
RMT_Single_Write_Blocking_Blink();
360385
Serial.println("\nStarting OVER...\n");
361386
}

0 commit comments

Comments
 (0)