diff --git a/cores/esp32/esp32-hal-rmt.c b/cores/esp32/esp32-hal-rmt.c index 7bca1a1b529..6d8a6c7dfae 100644 --- a/cores/esp32/esp32-hal-rmt.c +++ b/cores/esp32/esp32-hal-rmt.c @@ -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; @@ -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); @@ -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 @@ -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 @@ -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) { diff --git a/cores/esp32/esp32-hal-rmt.h b/cores/esp32/esp32-hal-rmt.h index c15eadfbcd1..2698f9dd898 100644 --- a/cores/esp32/esp32-hal-rmt.h +++ b/cores/esp32/esp32-hal-rmt.h @@ -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 times (rmtWriteRepeated()) + 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 @@ -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 on execution success, otherwise - will return always while it is looping. + will return always 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. diff --git a/libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino b/libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino index 1cdd2224ea5..df906588479 100644 --- a/libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino +++ b/libraries/ESP32/examples/RMT/RMT_LED_Blink/RMT_LED_Blink.ino @@ -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"); @@ -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"); }