Reading nanosecond timing on GPIO (Neopixel)
Posted: Mon Oct 07, 2019 4:40 pm
Hi Everyone,
I am attempting a project that I have seen mentioned, but not found any definitive answers for. I am trying to read incoming signaling from a Neopixel controller (WS2812). The signaling is fairly straight forward, but also very fast. The pin is set high for about 300ns for a 0 bit and 600ns for a 1 bit, followed by 500-1000ns low before the next bit. The termination of a frame (24 bits times the number of targeted pixels) is signaled by the pin staying low for >= 6000ns.
My intention is to read this signal and modify some color values, then output to my LEDs. The output is not an issue using the RMT device, and I am not concerned about a bit of delay reading and translating the data. I have tried two methods to read the input signal, with issues each way:
Using RMT input with 7 channels worth of memory assigned I run into running out of buffer. The "lowest" polling rate I can really do to interpret the incoming signal is 100ns (clock divider of 8) and I believe this is just too much data before it hits an idle signal. Is there any way to start reading/clearing the hardware buffer before it hits idle state? I have been able to decode some of the incoming 24bit values into correct colors, but the output seems to be missing quite a bit (assumed to be due to the buffer filling)
Other method is a high priority task pinned to an otherwise unused core adding ccount to a queue when a change is detected on the pin and using that to calculate timing in another task in the other core. There is certainly some expected discrepancy in measured clock counts with this method, but my results seem to be fluctuating wildly with even minor code changes. At best I have been able to see mostly clean data values for the timing,but there are still quite a few nonsensical values mixed in that would throw off attempts to decode properly.
Has anyone figured out a method to reliably read very fast signals like this one? Any ideas?
I could post some code, but given how many variations I have built and not had work I am not sure it would be overly helpful...
Thanks!
I am attempting a project that I have seen mentioned, but not found any definitive answers for. I am trying to read incoming signaling from a Neopixel controller (WS2812). The signaling is fairly straight forward, but also very fast. The pin is set high for about 300ns for a 0 bit and 600ns for a 1 bit, followed by 500-1000ns low before the next bit. The termination of a frame (24 bits times the number of targeted pixels) is signaled by the pin staying low for >= 6000ns.
My intention is to read this signal and modify some color values, then output to my LEDs. The output is not an issue using the RMT device, and I am not concerned about a bit of delay reading and translating the data. I have tried two methods to read the input signal, with issues each way:
Using RMT input with 7 channels worth of memory assigned I run into running out of buffer. The "lowest" polling rate I can really do to interpret the incoming signal is 100ns (clock divider of 8) and I believe this is just too much data before it hits an idle signal. Is there any way to start reading/clearing the hardware buffer before it hits idle state? I have been able to decode some of the incoming 24bit values into correct colors, but the output seems to be missing quite a bit (assumed to be due to the buffer filling)
Other method is a high priority task pinned to an otherwise unused core adding ccount to a queue when a change is detected on the pin and using that to calculate timing in another task in the other core. There is certainly some expected discrepancy in measured clock counts with this method, but my results seem to be fluctuating wildly with even minor code changes. At best I have been able to see mostly clean data values for the timing,but there are still quite a few nonsensical values mixed in that would throw off attempts to decode properly.
Has anyone figured out a method to reliably read very fast signals like this one? Any ideas?
I could post some code, but given how many variations I have built and not had work I am not sure it would be overly helpful...
Thanks!