sebmillet / RF433any

GNU Lesser General Public License v3.0
41 stars 4 forks source link

buffer management for ARM mcus won't work #14

Open danyhm opened 1 year ago

danyhm commented 1 year ago

Hello again,

I've been studying your algorithm for interrupt management for quite some time now. I noticed you implemented a small buffer so you could achieve rcswitch compatibility. however, the following snippet won't work on ARM MCUs like arduino DUO because the interrupt handler is quite different in ARM. In AVR the following code supposedly reenables the same interrupt to happen again while you're inside the ISR (nested interrupt) so you won't miss a level change while inside the ISR.

sei();

            Receiver *ptr_rec = RF_manager::get_head();
            while (ptr_rec) {

#ifdef DEBUG_AUTOMAT
                dbgf("\nptr_rec = %lu", (unsigned long)ptr_rec);
#endif

                ptr_rec->process_signal(compact_signal_duration, signal_val);
                ptr_rec = ptr_rec->get_next();
            }

cli();

This method works only in AVR. For ARM the NVIC doesn't support this functionality. any idea how to add support for ARM?

danyhm commented 1 year ago

I'm still reviewing this method. One thought that comes to mind is how effective this method is in not missing signal changes. because if the execution speed of the ISR is lower than the speed of signal change, eventually the buffer will be overrun. it's like a race to fill and read the buffer. if the filling happens more often than reading, the buffer will eventually overrun. it's still surprising that you could reach RCSwitch compatibility using this method.

sebmillet commented 11 months ago

Hello

thanks for your interest with this lib!

Actually I implemented the small buffer, because what matters is the overall timing of a bit. That is, sometimes the timing "short" is VERY short (too short for my ISR) but the total "short then long" (or long then short) is big enough that in practice, there is no buffer overrun because the "long" timing will leave enough time to the library (enough time to consume the buffer.)

But indeed, if the timing of a whole bit is too short, there'll be a buffer overrun.

This question was a key one when developing the lib: I didn't want to SAVE the timings and ANALYZE it later, as do some libraries (and as does RCSwitch). This way of doing requires a lot of memory, and I wanted something compatible with Arduino Uno / Nano, that come with 2 KB of memory. Also the schema "saving timings and analyze it later" is not easy in regards to detecting coding start - RF433any has no expectation for the initial "sync start" sequence, and tries to decode continually.

Note that NOT saving timing is also at the core of rf433recv library, again, I don't like the idea of save-then-analyze-only-when-saving-is-over. But that's a matter of taste...

Regards

danyhm commented 11 months ago

Thanks for the explanation. however, the sei and cli lines don't work in ARM like stm32. because interrupt nesting of the same priority is not supported. actually, once inside an interrupt, the CPU won't interrupt the same ISR until the last one is finished.

sebmillet commented 11 months ago

So that means, providing a version of RF433any without the small buffer would help? It'd prevent it from decoding certain too short timings but at least, would work for the rest? Reg.

danyhm commented 11 months ago

actually, i was hoping for a better algorithm so it works cross MCUs. In the mean time just commenting out the cli and sei would make it work on ARM.

Actually I implemented the small buffer, because what matters is the overall timing of a bit. That is, sometimes the timing "short" is VERY short (too short for my ISR) but the total "short then long" (or long then short) is big enough that in practice, there is no buffer overrun because the "long" timing will leave enough time to the library (enough time to consume the buffer.)

one thing that comes to my mind for this problem is that if we detect that an upcoming signal is very short then just store the current signal in the buffer, then wait for an upcoming long signal, and then process the buffer. I don't know if it can be done in practice.