Skip to content

Commit 3ceb712

Browse files
committed
Allocate RMT buffer from heap, better RMT channel handling, allow freeing of RMT resources
1 parent c96772c commit 3ceb712

File tree

1 file changed

+61
-22
lines changed

1 file changed

+61
-22
lines changed

esp.c

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,33 +35,72 @@
3535
#ifdef HAS_ESP_IDF_5
3636

3737
void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) {
38-
rmt_data_t led_data[numBytes * 8];
39-
40-
if (!rmtInit(pin, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, 10000000)) {
41-
log_e("Failed to init RMT TX mode on pin %d", pin);
38+
// Note: Not thread-safe!!! Also because rmtPin is shared between
39+
// all instances, we will end up releasing/initializing the RMT
40+
// channels each time we invoke on different pins. This is probably
41+
// ok, just not efficient. led_data will be allocated with enough
42+
// space for the largest instance but data is not used between
43+
// calls so this should be fine.
44+
static rmt_data_t *led_data = NULL;
45+
static uint32_t led_data_size = 0;
46+
static int rmtPin = -1;
47+
48+
uint32_t requiredSize = numBytes * 8;
49+
if (requiredSize > led_data_size) {
50+
free(led_data);
51+
if (led_data = (rmt_data_t *)malloc(requiredSize * sizeof(rmt_data_t))) {
52+
led_data_size = requiredSize;
53+
} else {
54+
led_data_size = 0;
55+
}
56+
} else if (requiredSize == 0) {
57+
// To release RMT resources (RMT channels and led_data), call
58+
// .updateLength(0) to set number of pixels/bytes to zero,
59+
// then call .show() to invoke this code and free resources.
60+
free(led_data);
61+
led_data = NULL;
62+
if (rmtPin >= 0) {
63+
rmtDeinit(rmtPin);
64+
rmtPin = -1;
65+
}
66+
led_data_size = 0;
4267
return;
4368
}
4469

45-
int i=0;
46-
for (int b=0; b < numBytes; b++) {
47-
for (int bit=0; bit<8; bit++){
48-
if ( pixels[b] & (1<<(7-bit)) ) {
49-
led_data[i].level0 = 1;
50-
led_data[i].duration0 = 8;
51-
led_data[i].level1 = 0;
52-
led_data[i].duration1 = 4;
53-
} else {
54-
led_data[i].level0 = 1;
55-
led_data[i].duration0 = 4;
56-
led_data[i].level1 = 0;
57-
led_data[i].duration1 = 8;
70+
if (requiredSize <= led_data_size) {
71+
if (pin != rmtPin) {
72+
if (rmtPin >= 0) {
73+
rmtDeinit(rmtPin);
74+
rmtPin = -1;
5875
}
59-
i++;
76+
if (!rmtInit(pin, RMT_TX_MODE, RMT_MEM_NUM_BLOCKS_1, 10000000)) {
77+
log_e("Failed to init RMT TX mode on pin %d", pin);
78+
return;
79+
}
80+
rmtPin = pin;
6081
}
61-
}
6282

63-
//pinMode(pin, OUTPUT); // don't do this, will cause the rmt to disable!
64-
rmtWrite(pin, led_data, numBytes * 8, RMT_WAIT_FOR_EVER);
83+
int i=0;
84+
for (int b=0; b < numBytes; b++) {
85+
for (int bit=0; bit<8; bit++){
86+
if ( pixels[b] & (1<<(7-bit)) ) {
87+
led_data[i].level0 = 1;
88+
led_data[i].duration0 = 8;
89+
led_data[i].level1 = 0;
90+
led_data[i].duration1 = 4;
91+
} else {
92+
led_data[i].level0 = 1;
93+
led_data[i].duration0 = 4;
94+
led_data[i].level1 = 0;
95+
led_data[i].duration1 = 8;
96+
}
97+
i++;
98+
}
99+
}
100+
101+
//pinMode(pin, OUTPUT); // don't do this, will cause the rmt to disable!
102+
rmtWrite(pin, led_data, numBytes * 8, RMT_WAIT_FOR_EVER);
103+
}
65104
}
66105

67106

@@ -219,6 +258,6 @@ void espShow(uint8_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz)
219258
}
220259

221260
#endif // ifndef IDF5
222-
261+
223262

224263
#endif // ifdef(ESP32)

0 commit comments

Comments
 (0)