@@ -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
8486static 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 */
107109static 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
111113static void IRAM_ATTR _rmt_isr (void * arg );
112114
113- bool _rmtSendOnce (rmt_obj_t * rmt , uint32_t * data , size_t size );
114-
115115static rmt_obj_t * _rmtAllocate (int pin , int from , int size );
116116
117117static 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+
143163bool 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