Skip to content

Commit 826ef0e

Browse files
committed
adding header sentinels, split interface to common and additional settings
1 parent f1c1dd6 commit 826ef0e

File tree

2 files changed

+158
-65
lines changed

2 files changed

+158
-65
lines changed

Diff for: cores/esp32/esp32-hal-rmt.c

+135-56
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#ifndef MAIN_ESP32_HAL_RMT_H_
2+
#define MAIN_ESP32_HAL_RMT_H_
3+
14
#include "freertos/FreeRTOS.h"
25
#include "freertos/event_groups.h"
36
#include "freertos/semphr.h"
@@ -13,7 +16,9 @@
1316
#include "soc/rmt_struct.h"
1417
#include "esp_intr_alloc.h"
1518

16-
19+
/**
20+
* Internal macros
21+
*/
1722
#define MAX_CHANNELS 8
1823
#define MAX_DATA_PER_CHANNEL 64
1924
#define MAX_DATA_PER_ITTERATION 40
@@ -37,6 +42,9 @@
3742
# define RMT_MUTEX_UNLOCK(channel) xSemaphoreGive(g_rmt_objlocks[channel])
3843
#endif /* CONFIG_DISABLE_HAL_LOCKS */
3944

45+
/**
46+
* Typedefs for internal stuctures, enums
47+
*/
4048
typedef enum {
4149
e_no_intr = 0,
4250
e_tx_intr = 1,
@@ -52,7 +60,6 @@ typedef enum {
5260
e_set_conti = 8,
5361
} transaction_state_t;
5462

55-
5663
struct rmt_obj_s
5764
{
5865
bool allocated;
@@ -67,6 +74,9 @@ struct rmt_obj_s
6774
transaction_state_t tx_state;
6875
};
6976

77+
/**
78+
* Internal variables for channel descriptors
79+
*/
7080
static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
7181
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
7282
};
@@ -82,20 +92,68 @@ static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
8292
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
8393
};
8494

95+
/**
96+
* Internal variables for driver data
97+
*/
8598
static intr_handle_t intr_handle;
8699

87100
static bool periph_enabled = false;
88101

89102
static xSemaphoreHandle g_rmt_block_lock = NULL;
90103

91-
104+
/**
105+
* Internal method (private) declarations
106+
*/
92107
static void _initPin(int pin, int channel, bool tx_not_rx);
93108

94109
static bool _rmtSendOnce(rmt_obj_t* rmt, uint32_t* data, size_t size);
95110

96-
97111
static void IRAM_ATTR _rmt_isr(void* arg);
98112

113+
bool _rmtSendOnce(rmt_obj_t* rmt, uint32_t* data, size_t size);
114+
115+
static rmt_obj_t* _rmtAllocate(int pin, int from, int size);
116+
117+
static void _initPin(int pin, int channel, bool tx_not_rx);
118+
119+
120+
/**
121+
* Public method definitions
122+
*/
123+
bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t low, uint32_t high)
124+
{
125+
if (!rmt || low > 0xFFFF || high > 0xFFFF) {
126+
return false;
127+
}
128+
size_t channel = rmt->channel;
129+
130+
RMT_MUTEX_LOCK(channel);
131+
132+
RMT.carrier_duty_ch[channel].low = low;
133+
RMT.carrier_duty_ch[channel].low = high;
134+
RMT.conf_ch[channel].conf0.carrier_en = carrier_en;
135+
RMT.conf_ch[channel].conf0.carrier_out_lv = carrier_level;
136+
137+
RMT_MUTEX_UNLOCK(channel);
138+
139+
return true;
140+
141+
}
142+
143+
bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value)
144+
{
145+
if (!rmt || value > 0xFFFF) {
146+
return false;
147+
}
148+
size_t channel = rmt->channel;
149+
150+
RMT_MUTEX_LOCK(channel);
151+
RMT.conf_ch[channel].conf0.idle_thres = value;
152+
RMT_MUTEX_UNLOCK(channel);
153+
154+
return true;
155+
}
156+
99157

100158
bool rmtDeinit(rmt_obj_t *rmt)
101159
{
@@ -128,7 +186,7 @@ bool rmtDeinit(rmt_obj_t *rmt)
128186
return true;
129187
}
130188

131-
bool rmtSent(rmt_obj_t* rmt, uint32_t* data, size_t size)
189+
bool rmtSend(rmt_obj_t* rmt, uint32_t* data, size_t size)
132190
{
133191
if (!rmt) {
134192
return false;
@@ -184,7 +242,7 @@ bool rmtSent(rmt_obj_t* rmt, uint32_t* data, size_t size)
184242
}
185243

186244

187-
bool rmtWaitForData(rmt_obj_t* rmt, uint32_t* data, size_t size)
245+
bool rmtGetData(rmt_obj_t* rmt, uint32_t* data, size_t size)
188246
{
189247
if (!rmt) {
190248
return false;
@@ -195,12 +253,6 @@ bool rmtWaitForData(rmt_obj_t* rmt, uint32_t* data, size_t size)
195253
return false;
196254
}
197255

198-
// wait for the interrupt
199-
while (!(RMT.int_raw.val&_INT_RX_END(channel))) {}
200-
201-
// clear the interrupt
202-
RMT.int_clr.val |= _INT_RX_END(channel);
203-
204256
size_t i;
205257
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
206258
for (i=0; i<size; i++) {
@@ -210,28 +262,40 @@ bool rmtWaitForData(rmt_obj_t* rmt, uint32_t* data, size_t size)
210262
return true;
211263
}
212264

213-
bool rmtReceive(rmt_obj_t* rmt, size_t idle_thres)
265+
bool rmtBeginReceive(rmt_obj_t* rmt)
214266
{
215267
if (!rmt) {
216268
return false;
217269
}
218270
int channel = rmt->channel;
219271

220272
RMT.int_clr.val |= _INT_ERROR(channel);
221-
222273
RMT.int_ena.val |= _INT_ERROR(channel);
223274

224275
RMT.conf_ch[channel].conf1.mem_owner = 1;
225-
RMT.conf_ch[channel].conf0.idle_thres = idle_thres;
226-
227276
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
228-
229277
RMT.conf_ch[channel].conf1.rx_en = 1;
230278

231279
return true;
232280
}
233281

234-
bool rmtReceiveAsync(rmt_obj_t* rmt, size_t idle_thres, uint32_t* data, size_t size, void* eventFlag)
282+
bool rmtReceiveCompleted(rmt_obj_t* rmt)
283+
{
284+
if (!rmt) {
285+
return false;
286+
}
287+
int channel = rmt->channel;
288+
289+
if (RMT.int_raw.val&_INT_RX_END(channel)) {
290+
// RX end flag
291+
RMT.int_clr.val |= _INT_RX_END(channel);
292+
return true;
293+
} else {
294+
return false;
295+
}
296+
}
297+
298+
bool rmtReceive(rmt_obj_t* rmt, uint32_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout)
235299
{
236300
if (!rmt) {
237301
return false;
@@ -256,7 +320,6 @@ bool rmtReceiveAsync(rmt_obj_t* rmt, size_t idle_thres, uint32_t* data, size_t s
256320
rmt->intr_mode = e_rx_intr;
257321

258322
RMT.conf_ch[channel].conf1.mem_owner = 1;
259-
RMT.conf_ch[channel].conf0.idle_thres = idle_thres;
260323

261324
RMT.int_clr.val |= _INT_RX_END(channel);
262325
RMT.int_clr.val |= _INT_ERROR(channel);
@@ -269,49 +332,18 @@ bool rmtReceiveAsync(rmt_obj_t* rmt, size_t idle_thres, uint32_t* data, size_t s
269332
RMT.conf_ch[channel].conf1.rx_en = 1;
270333
RMT_MUTEX_UNLOCK(channel);
271334

272-
return true;
273-
}
274-
275-
276-
bool _rmtSendOnce(rmt_obj_t* rmt, uint32_t* data, size_t size)
277-
{
278-
if (!rmt) {
279-
return false;
280-
}
281-
int channel = rmt->channel;
282-
RMT.apb_conf.fifo_mask = 1;
283-
if (data && size>0) {
284-
size_t i;
285-
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
286-
for (i = 0; i < size; i++) {
287-
*rmt_mem_ptr++ = data[i];
335+
// wait for data if requested so
336+
if (waitForData && eventFlag) {
337+
uint32_t flags = xEventGroupWaitBits(eventFlag, RMT_FLAGS_ALL,
338+
pdTRUE /* clear on exit */, pdFALSE /* wait for all bits */, timeout);
339+
if (flags & RMT_FLAG_ERROR) {
340+
return false;
288341
}
289-
// tx end mark
290-
RMTMEM.chan[channel].data32[size].val = 0;
291342
}
292343

293-
RMT_MUTEX_LOCK(channel);
294-
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
295-
RMT.conf_ch[channel].conf1.tx_start = 1;
296-
RMT_MUTEX_UNLOCK(channel);
297-
298344
return true;
299345
}
300346

301-
static rmt_obj_t* _rmtAllocate(int pin, int from, int size)
302-
{
303-
size_t i;
304-
// setup how many buffers shall we use
305-
g_rmt_objects[from].buffers = size;
306-
307-
for (i=0; i<size; i++) {
308-
// mark the block of channels as used
309-
g_rmt_objects[i+from].allocated = true;
310-
}
311-
return &(g_rmt_objects[from]);
312-
}
313-
314-
315347
float rmtSetTick(rmt_obj_t* rmt, float tick)
316348
{
317349
if (!rmt) {
@@ -400,12 +432,14 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
400432
// Initialize the registers in default mode:
401433
// - no carrier, filter
402434
// - timebase tick of 1us
435+
// - idle threshold set to 0x8000 (max pulse width + 1)
403436
RMT.conf_ch[channel].conf0.div_cnt = 1;
404437
RMT.conf_ch[channel].conf0.mem_size = buffers;
405438
RMT.conf_ch[channel].conf0.carrier_en = 0;
406439
RMT.conf_ch[channel].conf0.carrier_out_lv = 0;
407440
RMT.conf_ch[channel].conf0.mem_pd = 0;
408441

442+
RMT.conf_ch[channel].conf0.idle_thres = 0x8000;
409443
RMT.conf_ch[channel].conf1.rx_en = 0;
410444
RMT.conf_ch[channel].conf1.tx_conti_mode = 0;
411445
RMT.conf_ch[channel].conf1.ref_cnt_rst = 0;
@@ -434,6 +468,49 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
434468
return rmt;
435469
}
436470

471+
/**
472+
* Private methods definitions
473+
*/
474+
bool _rmtSendOnce(rmt_obj_t* rmt, uint32_t* data, size_t size)
475+
{
476+
if (!rmt) {
477+
return false;
478+
}
479+
int channel = rmt->channel;
480+
RMT.apb_conf.fifo_mask = 1;
481+
if (data && size>0) {
482+
size_t i;
483+
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
484+
for (i = 0; i < size; i++) {
485+
*rmt_mem_ptr++ = data[i];
486+
}
487+
// tx end mark
488+
RMTMEM.chan[channel].data32[size].val = 0;
489+
}
490+
491+
RMT_MUTEX_LOCK(channel);
492+
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
493+
RMT.conf_ch[channel].conf1.tx_start = 1;
494+
RMT_MUTEX_UNLOCK(channel);
495+
496+
return true;
497+
}
498+
499+
500+
static rmt_obj_t* _rmtAllocate(int pin, int from, int size)
501+
{
502+
size_t i;
503+
// setup how many buffers shall we use
504+
g_rmt_objects[from].buffers = size;
505+
506+
for (i=0; i<size; i++) {
507+
// mark the block of channels as used
508+
g_rmt_objects[i+from].allocated = true;
509+
}
510+
return &(g_rmt_objects[from]);
511+
}
512+
513+
437514
static void _initPin(int pin, int channel, bool tx_not_rx)
438515
{
439516
if (!periph_enabled) {
@@ -617,3 +694,5 @@ static void IRAM_ATTR _rmt_isr(void* arg)
617694
digitalWrite(4, 0);
618695
digitalWrite(2, 0);
619696
}
697+
698+
#endif /* MAIN_ESP32_HAL_RMT_H_ */

Diff for: cores/esp32/esp32-hal-rmt.h

+23-9
Original file line numberDiff line numberDiff line change
@@ -43,31 +43,45 @@ float rmtSetTick(rmt_obj_t* rmt, float tick);
4343
bool rmtSend(rmt_obj_t* rmt, uint32_t* data, size_t size);
4444

4545
/**
46-
* Initiates simple data receive without interrupts
46+
* Initiates async receive, event flag indicates data received
4747
*
4848
*/
49-
bool rmtBeginReceive(rmt_obj_t* rmt, size_t idle_thres);
49+
bool rmtReceive(rmt_obj_t* rmt, uint32_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout);
50+
51+
52+
/* Additional interface */
5053

5154
/**
52-
* Wait method for synchronous receive
55+
* Start reception
5356
*
5457
*/
55-
bool rmtWaitForData(rmt_obj_t* rmt, uint32_t* data, size_t size);
58+
bool rmtBeginReceive(rmt_obj_t* rmt);
5659

5760
/**
58-
* Initiates async receive, event flag indicates data received
61+
* Checks if reception completes
5962
*
6063
*/
61-
bool rmtReceiveAsync(rmt_obj_t* rmt, size_t idle_thres, uint32_t* data, size_t size, void* event_flags);
64+
bool rmtReceiveCompleted(rmt_obj_t* rmt);
65+
66+
/**
67+
* Reads the data for particular channel
68+
*
69+
*/
70+
bool rmtGetData(rmt_obj_t* rmt, uint32_t* data, size_t size);
71+
72+
/**
73+
* Setting threshold for Rx completed
74+
*/
75+
bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value);
76+
77+
bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t low, uint32_t high);
6278

6379
// TODO:
64-
// * add timeout to waiForData
65-
// * try to eliminate idle_thres from the receiving functions
66-
// * carrier interface
6780
// * uninstall interrupt when all channels are deinit
6881
// * send only-conti mode with circular-buffer
6982
// * put sanity checks to some macro or inlines
7083
// * doxy comments
84+
// * error reporting
7185

7286
#ifdef __cplusplus
7387
}

0 commit comments

Comments
 (0)