Skip to content

Commit 4397831

Browse files
committed
Fixes per code review + support for rx callback mode
1 parent 826ef0e commit 4397831

File tree

3 files changed

+209
-88
lines changed

3 files changed

+209
-88
lines changed

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

+150-61
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ struct rmt_obj_s
7272
uint32_t* remaining_ptr;
7373
intr_mode_t intr_mode;
7474
transaction_state_t tx_state;
75+
rmt_rx_data_cb_t cb;
76+
bool data_alloc;
7577
};
7678

7779
/**
@@ -82,14 +84,14 @@ static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
8284
};
8385

8486
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
85-
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
86-
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
87-
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
88-
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
89-
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
90-
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
91-
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
92-
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive},
87+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive, NULL, false},
88+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive, NULL, false},
89+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive, NULL, false},
90+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive, NULL, false},
91+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive, NULL, false},
92+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive, NULL, false},
93+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive, NULL, false},
94+
{ false, NULL, 0, 0, 0, 0, 0, NULL, e_no_intr, e_inactive, NULL, false},
9395
};
9496

9597
/**
@@ -106,16 +108,16 @@ static xSemaphoreHandle g_rmt_block_lock = NULL;
106108
*/
107109
static void _initPin(int pin, int channel, bool tx_not_rx);
108110

109-
static bool _rmtSendOnce(rmt_obj_t* rmt, uint32_t* data, size_t size);
111+
static bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size);
110112

111113
static void IRAM_ATTR _rmt_isr(void* arg);
112114

113-
bool _rmtSendOnce(rmt_obj_t* rmt, uint32_t* data, size_t size);
114-
115115
static rmt_obj_t* _rmtAllocate(int pin, int from, int size);
116116

117117
static void _initPin(int pin, int channel, bool tx_not_rx);
118118

119+
static int IRAM_ATTR _rmt_get_mem_len(uint8_t channel);
120+
119121

120122
/**
121123
* Public method definitions
@@ -140,6 +142,24 @@ bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t
140142

141143
}
142144

145+
bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level)
146+
{
147+
if (!rmt || filter_level > 0xFF) {
148+
return false;
149+
}
150+
size_t channel = rmt->channel;
151+
152+
RMT_MUTEX_LOCK(channel);
153+
154+
RMT.conf_ch[channel].conf1.rx_filter_thres = filter_level;
155+
RMT.conf_ch[channel].conf1.rx_filter_en = filter_en;
156+
157+
RMT_MUTEX_UNLOCK(channel);
158+
159+
return true;
160+
161+
}
162+
143163
bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value)
144164
{
145165
if (!rmt || value > 0xFFFF) {
@@ -186,7 +206,7 @@ bool rmtDeinit(rmt_obj_t *rmt)
186206
return true;
187207
}
188208

189-
bool rmtSend(rmt_obj_t* rmt, uint32_t* data, size_t size)
209+
bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
190210
{
191211
if (!rmt) {
192212
return false;
@@ -205,7 +225,7 @@ bool rmtSend(rmt_obj_t* rmt, uint32_t* data, size_t size)
205225
}
206226

207227
rmt->remaining_to_send = size - MAX_DATA_PER_ITTERATION;
208-
rmt->remaining_ptr = data + MAX_DATA_PER_ITTERATION;
228+
rmt->remaining_ptr = ((uint32_t*)data) + MAX_DATA_PER_ITTERATION;
209229
rmt->intr_mode = e_tx_intr | e_txthr_intr;
210230
rmt->tx_state = e_set_conti | e_first_half;
211231

@@ -242,7 +262,7 @@ bool rmtSend(rmt_obj_t* rmt, uint32_t* data, size_t size)
242262
}
243263

244264

245-
bool rmtGetData(rmt_obj_t* rmt, uint32_t* data, size_t size)
265+
bool rmtReadData(rmt_obj_t* rmt, uint32_t* data, size_t size)
246266
{
247267
if (!rmt) {
248268
return false;
@@ -295,7 +315,41 @@ bool rmtReceiveCompleted(rmt_obj_t* rmt)
295315
}
296316
}
297317

298-
bool rmtReceive(rmt_obj_t* rmt, uint32_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout)
318+
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb)
319+
{
320+
if (!rmt && !cb) {
321+
return false;
322+
}
323+
int channel = rmt->channel;
324+
325+
RMT_MUTEX_LOCK(channel);
326+
rmt->intr_mode = e_rx_intr;
327+
rmt->tx_state = e_first_half;
328+
rmt->cb = cb;
329+
// allocate internally two buffers which would alternate
330+
if (!rmt->data_alloc) {
331+
rmt->remaining_ptr = (uint32_t*)malloc(2*MAX_DATA_PER_CHANNEL*(rmt->buffers)*sizeof(uint32_t));
332+
rmt->remaining_to_send = MAX_DATA_PER_CHANNEL*rmt->buffers;
333+
rmt->data_alloc = true;
334+
}
335+
336+
RMT.conf_ch[channel].conf1.mem_owner = 1;
337+
338+
RMT.int_clr.val = _INT_RX_END(channel);
339+
RMT.int_clr.val = _INT_ERROR(channel);
340+
341+
RMT.int_ena.val |= _INT_RX_END(channel);
342+
RMT.int_ena.val |= _INT_ERROR(channel);
343+
344+
RMT.conf_ch[channel].conf1.mem_wr_rst = 1;
345+
346+
RMT.conf_ch[channel].conf1.rx_en = 1;
347+
RMT_MUTEX_UNLOCK(channel);
348+
349+
return true;
350+
}
351+
352+
bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout)
299353
{
300354
if (!rmt) {
301355
return false;
@@ -312,7 +366,7 @@ bool rmtReceive(rmt_obj_t* rmt, uint32_t* data, size_t size, void* eventFlag, bo
312366
}
313367

314368
if (data && size>0) {
315-
rmt->remaining_ptr = data;
369+
rmt->remaining_ptr = (uint32_t*)data;
316370
rmt->remaining_to_send = size;
317371
}
318372

@@ -321,8 +375,8 @@ bool rmtReceive(rmt_obj_t* rmt, uint32_t* data, size_t size, void* eventFlag, bo
321375

322376
RMT.conf_ch[channel].conf1.mem_owner = 1;
323377

324-
RMT.int_clr.val |= _INT_RX_END(channel);
325-
RMT.int_clr.val |= _INT_ERROR(channel);
378+
RMT.int_clr.val = _INT_RX_END(channel);
379+
RMT.int_clr.val = _INT_ERROR(channel);
326380

327381
RMT.int_ena.val |= _INT_RX_END(channel);
328382
RMT.int_ena.val |= _INT_ERROR(channel);
@@ -439,7 +493,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
439493
RMT.conf_ch[channel].conf0.carrier_out_lv = 0;
440494
RMT.conf_ch[channel].conf0.mem_pd = 0;
441495

442-
RMT.conf_ch[channel].conf0.idle_thres = 0x8000;
496+
RMT.conf_ch[channel].conf0.idle_thres = 0x80;
443497
RMT.conf_ch[channel].conf1.rx_en = 0;
444498
RMT.conf_ch[channel].conf1.tx_conti_mode = 0;
445499
RMT.conf_ch[channel].conf1.ref_cnt_rst = 0;
@@ -448,6 +502,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
448502
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
449503
RMT.conf_ch[channel].conf1.idle_out_en = 1; // enable idle
450504
RMT.conf_ch[channel].conf1.ref_always_on = 0; // base clock
505+
RMT.apb_conf.fifo_mask = 1;
451506

452507
if (tx_not_rx) {
453508
// RMT.conf_ch[channel].conf1.rx_en = 0;
@@ -471,7 +526,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
471526
/**
472527
* Private methods definitions
473528
*/
474-
bool _rmtSendOnce(rmt_obj_t* rmt, uint32_t* data, size_t size)
529+
bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size)
475530
{
476531
if (!rmt) {
477532
return false;
@@ -482,7 +537,7 @@ bool _rmtSendOnce(rmt_obj_t* rmt, uint32_t* data, size_t size)
482537
size_t i;
483538
volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val);
484539
for (i = 0; i < size; i++) {
485-
*rmt_mem_ptr++ = data[i];
540+
*rmt_mem_ptr++ = data[i].val;
486541
}
487542
// tx end mark
488543
RMTMEM.chan[channel].data32[size].val = 0;
@@ -534,42 +589,66 @@ static void IRAM_ATTR _rmt_isr(void* arg)
534589

535590
int intr_val = RMT.int_st.val;
536591
size_t ch;
537-
for (ch=0; ch<MAX_CHANNELS; ch++) {
592+
for (ch = 0; ch < MAX_CHANNELS; ch++) {
538593

539-
if (intr_val&_INT_RX_END(ch)) {
594+
if (intr_val & _INT_RX_END(ch)) {
540595
// clear the flag
541-
RMT.int_clr.val |= _INT_RX_END(ch);
542-
//
543-
if ((g_rmt_objects[ch].intr_mode)&e_rx_intr) {
596+
RMT.int_clr.val = _INT_RX_END(ch); // TODO: replace clear interrupts
597+
RMT.int_ena.val &= ~_INT_RX_END(ch);
544598

599+
if ((g_rmt_objects[ch].intr_mode)&e_rx_intr) {
545600
if (g_rmt_objects[ch].events) {
546601
xEventGroupSetBits(g_rmt_objects[ch].events, RMT_FLAG_RX_DONE);
547602
}
548603
if (g_rmt_objects[ch].remaining_ptr && g_rmt_objects[ch].remaining_to_send > 0) {
549604
size_t i;
605+
uint32_t * data = g_rmt_objects[ch].remaining_ptr;
606+
if (g_rmt_objects[ch].cb) {
607+
if (g_rmt_objects[ch].tx_state&e_first_half) {
608+
g_rmt_objects[ch].tx_state &= ~e_first_half;
609+
} else {
610+
g_rmt_objects[ch].tx_state |= e_first_half;
611+
data += MAX_DATA_PER_CHANNEL*(g_rmt_objects[ch].buffers);
612+
}
613+
}
550614
for (i = 0; i < g_rmt_objects[ch].remaining_to_send; i++ ) {
551-
*(g_rmt_objects[ch].remaining_ptr)++ = RMTMEM.chan[ch].data32[i].val;
615+
*data++ = RMTMEM.chan[ch].data32[i].val;
616+
}
617+
// configured callback
618+
if (g_rmt_objects[ch].cb) {
619+
// actually received data ptr
620+
uint32_t * data = g_rmt_objects[ch].remaining_ptr;
621+
(g_rmt_objects[ch].cb)(data, _rmt_get_mem_len(ch));
622+
623+
// restart the reception
624+
RMT.conf_ch[ch].conf1.mem_owner = 1;
625+
RMT.conf_ch[ch].conf1.mem_wr_rst = 1;
626+
RMT.conf_ch[ch].conf1.rx_en = 1;
627+
RMT.int_ena.val |= _INT_RX_END(ch);
628+
} else {
629+
// if not callback provide, expect only one Rx
630+
g_rmt_objects[ch].intr_mode &= ~e_rx_intr;
552631
}
553632
}
554-
g_rmt_objects[ch].intr_mode &= ~e_rx_intr;
555-
556633
} else {
557634
// Report error and disable Rx interrupt
558-
ets_printf("Unexpected Rx interrupt!\n");
635+
log_e("Unexpected Rx interrupt!\n"); // TODO: eplace messages with log_X
559636
RMT.int_ena.val &= ~_INT_RX_END(ch);
560637
}
638+
639+
561640
}
562641

563642
if (intr_val&_INT_ERROR(ch)) {
643+
digitalWrite(2, 1);
564644
// clear the flag
565-
RMT.int_clr.val |= _INT_ERROR(ch);
645+
RMT.int_clr.val = _INT_ERROR(ch);
566646
RMT.int_ena.val &= ~_INT_ERROR(ch);
567647
// report error
568-
ets_printf("RMT Error %d!\n", ch);
648+
log_e("RMT Error %d!\n", ch);
569649
if (g_rmt_objects[ch].events) {
570650
xEventGroupSetBits(g_rmt_objects[ch].events, RMT_FLAG_ERROR);
571651
}
572-
573652
// reset memory
574653
RMT.conf_ch[ch].conf1.mem_rd_rst = 1;
575654
RMT.conf_ch[ch].conf1.mem_rd_rst = 0;
@@ -579,17 +658,29 @@ static void IRAM_ATTR _rmt_isr(void* arg)
579658

580659
if (intr_val&_INT_TX_END(ch)) {
581660

582-
RMT.int_clr.val |= _INT_TX_END(ch);
661+
RMT.int_clr.val = _INT_TX_END(ch);
583662

584663
if (g_rmt_objects[ch].tx_state&e_last_data) {
585664
g_rmt_objects[ch].tx_state = e_end_trans;
586-
ets_printf("Tx_End marked !\n");
587665
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
588-
666+
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
667+
int i;
668+
if (g_rmt_objects[ch].tx_state&e_first_half) {
669+
for (i = 0; i < half_tx_nr; i++) {
670+
RMTMEM.chan[ch].data32[i].val = 0x000F000F;
671+
}
672+
RMTMEM.chan[ch].data32[i].val = 0;
673+
g_rmt_objects[ch].tx_state &= ~e_first_half;
674+
} else {
675+
for (i = 0; i < half_tx_nr; i++) {
676+
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F;
677+
}
678+
RMTMEM.chan[ch].data32[i].val = 0;
679+
g_rmt_objects[ch].tx_state |= e_first_half;
680+
}
589681

590682
} else if (g_rmt_objects[ch].tx_state&e_end_trans) {
591-
ets_printf("Tx completed !\n");
592-
// disable interrupts and clear states
683+
RMT.conf_ch[ch].conf1.tx_conti_mode = 0;
593684
RMT.int_ena.val &= ~_INT_TX_END(ch);
594685
RMT.int_ena.val &= ~_INT_THR_EVNT(ch);
595686
g_rmt_objects[ch].intr_mode = e_no_intr;
@@ -599,7 +690,7 @@ static void IRAM_ATTR _rmt_isr(void* arg)
599690

600691
if (intr_val&_INT_THR_EVNT(ch)) {
601692
// clear the flag
602-
RMT.int_clr.val |= _INT_THR_EVNT(ch);
693+
RMT.int_clr.val | _INT_THR_EVNT(ch);
603694

604695
// initial setup of continuous mode
605696
if (g_rmt_objects[ch].tx_state&e_set_conti) {
@@ -635,9 +726,9 @@ static void IRAM_ATTR _rmt_isr(void* arg)
635726
g_rmt_objects[ch].remaining_ptr += half_tx_nr;
636727
} else {
637728
// less remaining data than buffer size -> fill in with fake (inactive) pulses
638-
// ets_printf("last chunk...");
729+
ets_printf("last chunk...");
639730
if (g_rmt_objects[ch].tx_state&e_first_half) {
640-
// ets_printf("first\n");
731+
ets_printf("first\n");
641732
RMTMEM.chan[ch].data32[0].val = data[0] - 1;
642733
for (i = 1; i < half_tx_nr; i++) {
643734
if (i < remaining_size) {
@@ -648,7 +739,7 @@ static void IRAM_ATTR _rmt_isr(void* arg)
648739
}
649740
g_rmt_objects[ch].tx_state &= ~e_first_half;
650741
} else {
651-
// ets_printf("second\n");
742+
ets_printf("second\n");
652743
for (i = 0; i < half_tx_nr; i++) {
653744
if (i < remaining_size) {
654745
RMTMEM.chan[ch].data32[half_tx_nr+i].val = data[i];
@@ -666,27 +757,9 @@ static void IRAM_ATTR _rmt_isr(void* arg)
666757
// no data left, just copy the fake (inactive) pulses
667758
if ( (!(g_rmt_objects[ch].tx_state&e_last_data)) &&
668759
(!(g_rmt_objects[ch].tx_state&e_end_trans)) ) {
669-
// ets_printf("tail (empty)");
670-
int half_tx_nr = MAX_DATA_PER_ITTERATION/2;
671-
int i;
672-
if (g_rmt_objects[ch].tx_state&e_first_half) {
673-
// ets_printf("...first\n");
674-
for (i = 0; i < half_tx_nr; i++) {
675-
RMTMEM.chan[ch].data32[i].val = 0x000F000F;
676-
}
677-
RMTMEM.chan[ch].data32[i].val = 0;
678-
g_rmt_objects[ch].tx_state &= ~e_first_half;
679-
} else {
680-
// ets_printf("...second\n");
681-
for (i = 0; i < half_tx_nr; i++) {
682-
RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F;
683-
}
684-
RMTMEM.chan[ch].data32[i].val = 0;
685-
g_rmt_objects[ch].tx_state |= e_first_half;
686-
}
687760
g_rmt_objects[ch].tx_state |= e_last_data;
688761
} else {
689-
// ets_printf("do_nothing\n");
762+
// ...do_nothing
690763
}
691764
}
692765
}
@@ -695,4 +768,20 @@ static void IRAM_ATTR _rmt_isr(void* arg)
695768
digitalWrite(2, 0);
696769
}
697770

771+
static int IRAM_ATTR _rmt_get_mem_len(uint8_t channel)
772+
{
773+
int block_num = RMT.conf_ch[channel].conf0.mem_size;
774+
int item_block_len = block_num * 64;
775+
volatile rmt_item32_t* data = RMTMEM.chan[channel].data32;
776+
int idx;
777+
for(idx = 0; idx < item_block_len; idx++) {
778+
if(data[idx].duration0 == 0) {
779+
return idx;
780+
} else if(data[idx].duration1 == 0) {
781+
return idx + 1;
782+
}
783+
}
784+
return idx;
785+
}
786+
698787
#endif /* MAIN_ESP32_HAL_RMT_H_ */

0 commit comments

Comments
 (0)