And now the FastLED3.1 branch allows for handling of interrupts on the due, teensy 3/3.1, and AVR. Now comes the great debugginging (IE. WTH is IRRemote doing that still doesn’t play nicely with us?)
I think with Neopixels going full blast we’ll service interrupts about 30,000/sec. That means the max “signal” received is 15,000Hz. Wonder what IR needs…
Yay! Thanks so much guys. You seriously rock.
So I may have bad news for @Andrew_Tuline and others waiting for IRRemote and ws2812s to play nicely with each other. It’s not going to happen yet.
The IRRemote library is designed around sampling the ir pin every 50 microseconds and counting the time spent high or low by counting “ticks” - however, because interrupts are blocked 30us at a time for writing ws2812 data the gap between two calls to the interrupt handler may be closer to 60-80us and the sampling timing counting would be off - the library is based on the assumption of a tick being 50us, and it is unclear how much room it has for slop.
One way around this would be re-working the ws2811 code so that it starts writing an led’s worth of data immediately after the IRRemote interrupt fires, and only write one pixel at a time, then wait until the next interrupt fires before writing the next pixel out. This would also significantly slow down led data writing, as pixels would now take 50us instead of 30us.
It is potentially a pretty significant juggling of code to pull this off though, and for anyone who wants to use IRRemote sooner rather than later my advice would be switch to lpd8806 or apa102. I’m not saying I wont ever tackle it, but I wouldn’t plan anything around it :). I have some thoughts on a simpler workaround, but it is very likely they would be arm only.
I really appreciate your efforts in this.
Hey- that library looks great, and I’m willing to bet a dollar that it works (or can be made to work) with FastLED 3.1, because it’s driven by a relatively small number of interrupts, instead of the constant fast-ticking interrupt of the (older) IRRemote library.
Dude. I just looked at it, and Hoodloaded2 is crazy awesome. Seriously. I need to seriously look into this thing.
No reason why it wouldn’t be - you’d need to define pin definitions in fastpin_avr.h - from a quick scan of the 16u2 datasheet it appears that the peripheral registers that FastLED uses are all the same.
On an UNO running WS2812B LED’s, with the latest FastLED 3.1 and IRLremote installed, I modified both the ReceiveBlocking and ReceiveInterrupt demos by adding a short FastLED routine. Both showed results (for protocol 3) when FastLED.show() was disabled , but didn’t display anything when it was enabled. I repeated this several times just to be sure.
In addition, I got past my 3.1 compile issues by deleting clockless_arm_sam_h and the pointer to it.
What 3.1 compile issues?
nevermind, found/fixed.
So, some other things with the IRLRemote library - which looks like it may be an improvement over the IRRemote library - however there still may be timing issues. Because AVR interrupts aren’t time stamped in any meaningful way, and because micros only has a 4µs resolution the perceived length of a signal can swing by as much as 34µs - while a single ‘tick’ for the panasonic remote is 26µs and for an NEC remote is 37µs - an entire _MARK_ONE or _MARK_ZERO could be missed.
So, again, it looks like if you want something that works with IR remotes (and don’t want to wait for me to have the time to put into trying to wedge the ws2812 code around working with IRRemote’s interrupts), either use dual controllers (one to capture IR and then use something like SPI or i2c that doesn’t need to track interrupts at microsecond level accuracy) or stop using NeoPixels and switch over to LPD8806 or APA102s (hell, even WS2801s would be better in this case).
I wonder if there’s an IR receiver / decoder / MCU with something like I2C output or similar – all in one prebuilt module. 
I hope I’m not bugging you guys. I do have a 2 Arduino version working as well as one with WS2801’s. Have also got APA102’s on order.
Switching from IR to RF: I recently used an “XD-YK04” to great success in conjunction with FastLED. It’s a four-button RF ‘key fob’ wireless remote with a matched signal decoder on board, $11 from Amazon, and available elsewhere (e.g. eBay, DX http://is.gd/sXWClj , etc.) for less.
http://amzn.com/B00NCL8P9W
The decoder board has one output for ‘signal received’ which can be tied to an interrupt, and four separate pins, each of which reads out as the state of one of the push buttons on the key fob remote (e.g., you can read ‘chords’ of buttons). Range out of the box sucks, but solder on a 17cm wire and it’s suddenly pretty good.
Going to port it to the Teensy 3.1 ?
Are the pulses as long as 560µs? That’ll be a bit better - my read on the code was that some of the pulses could be really short. Unfortunately - there’s a bigger problem with using IRLremote now - your interrupt handler takes a lot of cycles to run (nested function calls in interrupt handlers is bad) - and with the WS2812 it turns out you only have about 100 clock cycles (give or take a few) to do your work in with interrupts before I have to cancel writing out the current led frame.
AttachInterrupt - the interrupt handler for this is 80 clock cycles alone, not including the overhead for the dispatched function. If someone is using IR_ALL, IRLinterrupt is going to have another ~70 clock cycles (not including the time spent in the calls to micros or the three decode functions. You’re now out of cycles on the NeoPixels - haven’t even gotten down into the actual decode function yet.
Using IR_NEC, you still have the same overheads of AttachInterrupt but now IRLinterupt is still going to take ~60 cycles (not including the calls to micros) before it gets to calling decodeNec. Add to that the 80 clock cycles for AttachInterrupt, and it’s still unhappy.
With your Receive_PinChangeInterrupt_Basic version, your interrupt handler is still going to be ~75 clock cycles before it calls IRLinterrupt, which has the same timing issues as mentioned above.
(Note that we haven’t even gotten into decodeNec yet - and the budget for cycles in the interrupt gap is blown - decodeDec will add another 13-40ish, not including the time spent in either IRLdecode (at least another 34 clocks) or IREvent. ).
This is what I mean by nested function calls in interrupt handlers being bad. Yes, the templated code pulls a lot out, but the overhead for function calling is pretty heavy, and because there’s multiple layers of function calls being made all that overhead is multiplied. Plus, the interrupt handler has to be stupidly aggressive about push/pop’ing registers that might be used.
I can get the interrupt handler down to 93 clocks in the best case (which sadly, is when the timeout threshold hasn’t been met) and up to another 40-60 clock cycles given other conditions.
Some changes I’d suggest making. For one - it’s not enough to mark the function prototypes as inline, I would also add attribute((always_inline)) to them. Not only that, but you need to add inline attribute((always_inline)) to the function definitions as well. This allowed quite a bit of flattening of the call tree - now the only function calls that’re left being made during this whole thing is IREvent and micros.
Also - you have a bunch of 4 byte comparision operations happening in there (duration is 4 bytes, so all the comparisons with your 16 bit threshold/timeout values are going to be 4-8 cycles - you can halve those by getting duration into a 2 byte value as soon as possible).
Finally, the big thing killing this all around is the number of registers that’s used by the interrupt handler, even flattened - each register used is going to be 4 cycles of push/pop and right now gcc is insisting on using 18 registers. (19 if you include the saving/restoring of SREG that happens on the way into the function).
The call to micros is going to also be an expensive call, another ~30 clocks.
For cycle counting, a better way than using micros might be to use Timer1 (or, on 32u4 Timer3) with a clock divider of 64 - then you can read that value in 2 clock cycles (since it’ll be a 16 bit value), and the value in TCNT1H/TCNT1L*4 will be the number of microseconds (though divide your constant µs values by 4 to save the shifting). You can use the overflow bits to easily determine whether or not it’s been more than 200ms or some such. This would also have the side effect of changing your duration values to being 16-bit instead of 32-bit automatically, saving you the variety of cycles on the comparisons I mentioned above. With using higher clock dividers you might even be able to get away with using an 8-bit timer halving, again, the cost of your comparison operations.
Once you switch to using timer values (getting rid of the call to micros) and replace calling IREvent you may want to consider re-doing the inner bits of the IRLdecode function in asm, if only to tighten up the register usage a bit more. (in fact, your default IREvent function is a bit redundant - I would say just have IRLremote set global vlaues for IRLAddress/Command/Protocol as well as a flag indicating that a new command has been set - and ditch the call to IREvent entirely. Trusting people to write their own interrupt handlers opens up a world of pain if you have to care about timing 
Note - i’m not suggesting using timer1 interrupts - which is what IRRemote uses - just using timer1 to get timing values - also, when using ARM based devices running at 48-96Mhz (looking at you, due, and teensy) - you’ve got 4-6 times as many clock cycles to play with, but not only that, 32 bit operations that would be 4-8 clock cycles on avr are only one cycle on ARM making your clock cycles even more efficient for you.
Also, it would seem that telling me “Faster isn’t possible” is a great way to get a code audit 
“Whats happening if the IR remote “destroys” an LED update?”
I know that the decodeAll function is unlikely to be used in many places, it’s why I quickly switched to using IR_NEC as my example. However, it turns out that the structure/overhead of the top level IRLinterrupt function isn’t terribly different whether you’re calling decodeNec or decodeAll (because the bulk of the cost in the body of that function is the register saving/loading).
“For me ive got SPI leds anyways, i think this wont cause problems, does it?”
No - this is only an issue for WS2812 leds (and this is part of why my recommendation to folks who want to use IR remotes is to either go ARM or APA102/LPD8806). Basically, what would happen is that any led frame that was being written out when the IRLremote interrupts fire would be cut short. Depending on how frequently frames were being written and updated, it would cause the latter part of the set of leds to appear to freeze. (Note, I also still need to adjust, I think, the interrupt timing values to make sure that I minimize the chance of the interrupt messings with WS2812’s in a way that I don’t catch, which would cause random flashing - but I think to really test this i’m going to need to get an IR remote setup running here so I can do timing directly).
Some people would prefer not to have any glitching happen w/the leds just because they pressed a button on the remote.