Skip to content

Commit

Permalink
Adds RMT End of Transmission Level API (#9238)
Browse files Browse the repository at this point in the history
* RMT (featt):  adds a new function to set EOT level after RMT writing

* RMT (feat): adds new feature to set the EOT level after writing RMT channel

* adds return value to rmtSetEOT()

* adds bool return to rmtSetEOT()

* adds return value to the rmtSetEOT() function

* FIX (rmt): fixes eot_level setting using flags in the TX structure

* RMT(feat): Create RMT_EndOfTransmissionState.ino example

* Update cores/esp32/esp32-hal-rmt.h

Co-authored-by: Jan Procházka <[email protected]>

* Update cores/esp32/esp32-hal-rmt.c

Co-authored-by: Jan Procházka <[email protected]>

* Update cores/esp32/esp32-hal-rmt.c

Co-authored-by: Jan Procházka <[email protected]>

---------

Co-authored-by: Jan Procházka <[email protected]>
  • Loading branch information
SuGlider and P-R-O-C-H-Y authored Feb 14, 2024
1 parent 90036a2 commit 7eb1ce8
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
21 changes: 20 additions & 1 deletion cores/esp32/esp32-hal-rmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct rmt_obj_s {
bool rmt_ch_is_looping; // Is this RMT TX Channel in LOOPING MODE?
size_t *num_symbols_read; // Pointer to the number of RMT symbol read by IDF RMT RX Done
uint32_t frequency_Hz; // RMT Frequency
uint8_t rmt_EOT_Level; // RMT End of Transmission Level - default is LOW

#if !CONFIG_DISABLE_HAL_LOCKS
SemaphoreHandle_t g_rmt_objlocks; // Channel Semaphore Lock
Expand Down Expand Up @@ -185,6 +186,20 @@ static bool _rmtDetachBus(void *busptr)
Public method definitions
*/

bool rmtSetEOT(int pin, uint8_t EOT_Level)
{
rmt_bus_handle_t bus = _rmtGetBus(pin, __FUNCTION__);
if (bus == NULL) {
return false;
}
if (!_rmtCheckDirection(pin, RMT_TX_MODE, __FUNCTION__)) {
return false;
}

bus->rmt_EOT_Level = EOT_Level > 0 ? 1 : 0;
return true;
}

bool rmtSetCarrier(int pin, bool carrier_en, bool carrier_level, uint32_t frequency_Hz, float duty_percent)
{
rmt_bus_handle_t bus = _rmtGetBus(pin, __FUNCTION__);
Expand Down Expand Up @@ -316,6 +331,10 @@ static bool _rmtWrite(int pin, rmt_data_t* data, size_t num_rmt_symbols, bool bl
rmt_enable(bus->rmt_channel_h);
bus->rmt_ch_is_looping = false; // not looping anymore
}
// sets the End of Transmission level to HIGH if the user has requested so
if (bus->rmt_EOT_Level) {
transmit_cfg.flags.eot_level = 1; // EOT is HIGH
}
if (loopCancel) {
// just resets and releases the channel, maybe, already done above, then exits
bus->rmt_ch_is_looping = false;
Expand Down Expand Up @@ -487,7 +506,7 @@ bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t mem_
// store the RMT Freq to check Filter and Idle valid values in the RMT API
bus->frequency_Hz = frequency_Hz;
// pulses with width smaller than min_ns will be ignored (as a glitch)
bus->signal_range_min_ns = 0; // disabled
//bus->signal_range_min_ns = 0; // disabled --> not necessary CALLOC set all to ZERO.
// RMT stops reading if the input stays idle for longer than max_ns
bus->signal_range_max_ns = (1000000000 / frequency_Hz) * RMT_LL_MAX_IDLE_VALUE; // maximum possible
// creates the event group to control read_done and write_done
Expand Down
14 changes: 14 additions & 0 deletions cores/esp32/esp32-hal-rmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ typedef union {
*/
bool rmtInit(int pin, rmt_ch_dir_t channel_direction, rmt_reserve_memsize_t memsize, uint32_t frequency_Hz);

/**
Sets the End of Transmission level to be set for the <pin> when the RMT transmission ends.
This function affects how rmtWrite(), rmtWriteAsync() or rmtWriteLooping() will set the pin after writing the data.
The default EOT level is LOW, in case this function isn't used before RMT Writing.
This level can be set for each RMT pin and can be changed between writings to the same pin.
<EOT_Level> shall be Zero (LOW) or non-zero (HIGH) value.
It only affects the transmission process, therefore, it doesn't affect any IDLE LEVEL before starting the RMT transmission.
The pre-transmission idle level can be set manually calling, for instance, digitalWrite(pin, Level).
Returns <true> when EOT has been correctly set for <pin>, <false> otherwise.
*/
bool rmtSetEOT(int pin, uint8_t EOT_Level);

/**
Sending data in Blocking Mode.
<rmt_symbol> is a 32 bits structure as defined by rmt_data_t type.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#define BLINK_GPIO 2
#define EOT_INITIAL_STATE_TIME_MS 1000

// BLINK_GPIO shall start at RMT_EOT (HIGH or LOW) as initial state for EOT_INITIAL_STATE_TIME_MS,
// BLINK: 1 second ON, 1 second OFF and then return/stay to RMT_EOT level at the end.
#define RMT_EOT HIGH

// RMT is at 400KHz with a 2.5us tick
// This RMT data sends a 0.5Hz pulse with 1s High and 1s Low signal
rmt_data_t blink_1s_rmt_data[] = {
// 400,000 x 2.5us = 1 second ON
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
{25000, 1, 25000, 1,},
// 400,000 x 2.5us = 1 second OFF
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
{25000, 0, 25000, 0,},
// Looping mode needs a Zero ending data to mark the EOF
{0, 0, 0, 0}
};

void setup() {
Serial.begin(115200);
Serial.println("Starting Blink testing...");
Serial.flush();

// 1 RMT Block has 64 RMT_SYMBOLS (ESP32|ESP32S2) or 48 RMT_SYMBOLS (ESP32C3|ESP32S3)
if (!rmtInit(BLINK_GPIO, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, 400000)) { //2.5us tick
Serial.println("===> rmtInit Error!");
}

// sets the End of Transmission Level to HIGH, after writing to the pin. DEFAULT is LOW.
rmtSetEOT(BLINK_GPIO, RMT_EOT);
// set initial RMT state by writing a single RMT data
rmt_data_t initStateSetup_rmt_data[] = { {1, RMT_EOT, 0, 0} };
rmtWrite(BLINK_GPIO, initStateSetup_rmt_data, RMT_SYMBOLS_OF(initStateSetup_rmt_data), RMT_WAIT_FOR_EVER);
Serial.printf("\nLED GPIO%d start in the inital level %s\n", BLINK_GPIO, RMT_EOT == LOW ? "LOW" : "HIGH");
delay(EOT_INITIAL_STATE_TIME_MS); // set initial state of the LED is set by RMT_EOT.

// Send the data and wait until it is done - set EOT level to HIGH
Serial.printf("\nLED GPIO%d Blinks 1 second HIGH - 1 second LOW.\n", BLINK_GPIO);
if (!rmtWrite(BLINK_GPIO, blink_1s_rmt_data, RMT_SYMBOLS_OF(blink_1s_rmt_data) - 2, RMT_WAIT_FOR_EVER)) {
Serial.println("===> rmtWrite Blink 1s Error!");
}
Serial.printf("\nLED GPIO%d goes to the EOT level %s\n", BLINK_GPIO, RMT_EOT == LOW ? "LOW" : "HIGH");
}

void loop(){}

1 comment on commit 7eb1ce8

@sheenymoneem
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much. It is truly a wonderful work

Please sign in to comment.