Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3078091
feat(rmt): adds new function to send specific number of loops
SuGlider Aug 20, 2025
ddf778a
feat(rmt): adds new function to send specific number of loops
SuGlider Aug 20, 2025
a9fe74d
fix(rmt): bad code formatting
SuGlider Aug 20, 2025
5413697
fix(rmt): bad code formatting
SuGlider Aug 20, 2025
7a5df40
Merge branch 'master' into rmt_loop_count
SuGlider Sep 4, 2025
0f61b4f
Merge branch 'master' into rmt_loop_count
SuGlider Sep 5, 2025
f5d0513
feat(rmt): check the loop count parameter
SuGlider Sep 5, 2025
e9aa349
feat(rmt): improve commentaries
SuGlider Sep 5, 2025
3641446
feat(rmt): improve commentaries
SuGlider Sep 5, 2025
6c8007f
feat(rmt): Refine loop handling in RMT transmission
SuGlider Sep 5, 2025
8346673
fix(rmt): bad spelling in commentary
SuGlider Sep 5, 2025
182eef8
feat(rmt): improve code clarity
SuGlider Sep 5, 2025
7d8bf25
feat(rmt): single logv line for all looping cases
SuGlider Sep 5, 2025
00989d4
feat(rmt): rmtWriteLoopingCount improvement
SuGlider Sep 5, 2025
3bb70e7
feat(rmt): improve verbose logging code
SuGlider Sep 5, 2025
f2218ba
fix(rmt): code identation
SuGlider Sep 5, 2025
55b8244
fix(rmt): bad copy & paste of function signature
SuGlider Sep 5, 2025
fdd3ac4
feat(rmt): code improvement and clarity
SuGlider Sep 5, 2025
198a49c
feat(rmt): improved commentaries and code clarity
SuGlider Sep 5, 2025
a198804
rmt(fix): improve code reliability
SuGlider Sep 5, 2025
8883c30
feat(rmt): improved code readness
SuGlider Sep 5, 2025
c9c00f8
fix(rmt): typo in commentary
SuGlider Sep 5, 2025
d4b31b2
fix(rmt): increase buffer size for loop count loop log msg
SuGlider Sep 5, 2025
c5993be
fix(rmt): typo in commentary
SuGlider Sep 5, 2025
a92d64f
fix(rmt): typo in commentary
SuGlider Sep 5, 2025
9915feb
fix(rmt): buffer size for log message
SuGlider Sep 5, 2025
eedf368
rmt(fix): improve code readness
SuGlider Sep 5, 2025
a4f3e63
feat(rmt): guarding SOC_RMT_SUPPORT_TX_LOOP_COUNT
SuGlider Sep 6, 2025
c3b1919
feat(rmt): adds new function to the example
SuGlider Sep 6, 2025
b9a054f
fix(rmt): remove repeated function name in log msg
SuGlider Sep 6, 2025
5ab1ee5
fix(rmt): remove repeated function name in log msg
SuGlider Sep 6, 2025
0682d37
fix(rmt): fixes the example to wait for rmt TX
SuGlider Sep 6, 2025
7da1885
fix(rmt): fixes bad code formating
SuGlider Sep 6, 2025
85113f9
fix(rmt): fixes bad code formating
SuGlider Sep 6, 2025
d6d715a
fix(rmt): fixes bad code formating
SuGlider Sep 6, 2025
8775dd1
fix(rmt): fixes bad code formating
SuGlider Sep 6, 2025
4d836d0
fix(rmt): commentary complement
SuGlider Sep 6, 2025
7fffb38
fix(rmt): adds missing return value
SuGlider Sep 6, 2025
d1434bd
feat(rmt): improve commentaries
SuGlider Sep 6, 2025
29a1edc
Merge branch 'master' into rmt_loop_count
SuGlider Sep 10, 2025
87cce35
ci(pre-commit): Apply automatic fixes
pre-commit-ci-lite[bot] Sep 10, 2025
ba60ffa
fix(rmt): typo in commentary
SuGlider Sep 10, 2025
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
57 changes: 45 additions & 12 deletions cores/esp32/esp32-hal-rmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ bool rmtDeinit(int pin) {
return false;
}

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

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

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

bool rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t timeout_ms) {
return _rmtWrite(pin, data, num_rmt_symbols, true /*blocks*/, false /*looping*/, timeout_ms);
return _rmtWrite(pin, data, num_rmt_symbols, true /*blocks*/, 0 /*looping*/, timeout_ms);
}

bool rmtWriteAsync(int pin, rmt_data_t *data, size_t num_rmt_symbols) {
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, false /*looping*/, 0 /*N/A*/);
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, 0 /*looping*/, 0 /*N/A*/);
}

bool rmtWriteLooping(int pin, rmt_data_t *data, size_t num_rmt_symbols) {
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, true /*looping*/, 0 /*N/A*/);
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, 1 /*looping*/, 0 /*N/A*/);
}

// Same as rmtWriteLooping(...) but it transmits the data a fixed number of times ("loop_count").
// loop_count == 0 is invalid (no transmission); loop_count == 1 transmits once (no looping); loop_count > 1 transmits the data repeatedly (looping).
bool rmtWriteRepeated(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t loop_count) {
if (loop_count == 0) {
log_e("RMT TX GPIO %d : Invalid loop_count (%u). Must be at least 1.", pin, loop_count);
return false;
}
if (loop_count == 1) {
// send the RMT symbols once using non-blocking write (single non-looping transmission)
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, 0 /*looping*/, 0 /*N/A*/);
} else {
// write the RMT symbols for loop_count times
#if SOC_RMT_SUPPORT_TX_LOOP_COUNT
return _rmtWrite(pin, data, num_rmt_symbols, false /*blocks*/, loop_count /*looping*/, 0 /*N/A*/);
#else
log_e("RMT TX GPIO %d : Loop Count is not supported. Writing failed.", pin);
return false;
#endif
}
}

bool rmtTransmitCompleted(int pin) {
Expand Down
8 changes: 6 additions & 2 deletions cores/esp32/esp32-hal-rmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ bool rmtWrite(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t timeou
bool rmtWriteAsync(int pin, rmt_data_t *data, size_t num_rmt_symbols);

/**
Writing data up to the reserved memsize, looping continuously
Writing data up to the reserved memsize, looping continuously (rmtWriteLooping()) or fixed
number of <loop_count> times (rmtWriteRepeated())

<rmt_symbol> is a 32 bits structure as defined by rmt_data_t type.
It is possible to use the macro RMT_SYMBOLS_OF(data), if data is an array of rmt_data_t

Expand All @@ -133,9 +135,11 @@ bool rmtWriteAsync(int pin, rmt_data_t *data, size_t num_rmt_symbols);
Non-Blocking mode - returns right after execution
Returns <true> on execution success, <false> otherwise

<bool rmtTransmitCompleted(int pin)> will return always <true> while it is looping.
<bool rmtTransmitCompleted(int pin)> will return always <true> while it is looping mode.
looping mode is active for rmtWriteLooping() and for rmtWriteRepeated() when loop_count > 1.
*/
bool rmtWriteLooping(int pin, rmt_data_t *data, size_t num_rmt_symbols);
bool rmtWriteRepeated(int pin, rmt_data_t *data, size_t num_rmt_symbols, uint32_t loop_count);

/**
Checks if transmission is completed and the rmtChannel ready for transmitting new data.
Expand Down
25 changes: 25 additions & 0 deletions libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,30 @@ void RMT_Loop_Write_Blink() {
delay(2000);
}

void RMT_Repeated_Write_Blink() {
Serial.println("Using RMT Writing repeated N times to blink an LED.");
Serial.println("Blinking at 1s on + 1s off :: 2 blinks");
// repeating blink_1s_rmt_data (1s on + 1s off) 2 times for 2 blinks
if (!rmtWriteRepeated(BLINK_GPIO, blink_1s_rmt_data, RMT_SYMBOLS_OF(blink_1s_rmt_data), 2)) {
Serial.println("===> rmtWrite Blink 1s Error!");
}
delay(4000 + 1000); // it should blink 2 times and stop automatically
Serial.println("Blinking at 500ms on + 500ms off :: 4 blinks");
// repeating blink_500ms_rmt_data (500ms on + 500ms off) 4 times for 4 blinks
if (!rmtWriteRepeated(BLINK_GPIO, blink_500ms_rmt_data, RMT_SYMBOLS_OF(blink_500ms_rmt_data), 4)) {
Serial.println("===> rmtWrite Blink 0.5s Error!");
}
delay(4000 + 1000); // it should blink 4 times and stop automatically
Serial.println("Blinking at 250ms on + 250ms off :: 8 blinks");
// repeating blink_250ms_rmt_data (250ms on + 250ms off) 8 times for 8 blinks
if (!rmtWriteRepeated(BLINK_GPIO, blink_250ms_rmt_data, RMT_SYMBOLS_OF(blink_250ms_rmt_data), 8)) {
Serial.println("===> rmtWrite Blink 0.25s Error!");
}
delay(4000 + 1000); // it should blink 8 times and stop automatically
Serial.println("Blinking is OFF for 2 seconds");
delay(2000);
}

void RMT_Single_Write_Blocking_Blink() {
Serial.println("Using RMT Writing and its Completion to blink an LED.");
Serial.println("Blinking at 1s on + 1s off :: 2 blinks");
Expand Down Expand Up @@ -356,6 +380,7 @@ void setup() {
void loop() {
RMT_Write_Aync_Non_Blocking_Blink();
RMT_Loop_Write_Blink();
RMT_Repeated_Write_Blink();
RMT_Single_Write_Blocking_Blink();
Serial.println("\nStarting OVER...\n");
}
Loading