Skip to content

Conversation

Graimalkin
Copy link

@Graimalkin Graimalkin commented Jun 14, 2025

IRremoteESP8266 appears abandoned ( last updated July 2023 ).

It's based on Arduino-IRremote, which IS being maintained, and is not quite a drop in swap.

So, I swapped them. 😛

I did have to make a choice here to either re-order all of ir_codes.h or swap the byte order for results.decodedRawData so that it could mimic results.value. I went with swapping the byte order via esp8266Value(), because changing all of ir_codes.h sounds unpleasant to review, and like it's just asking for issues.

Also added in some debugging output for the serial monitor so it's easier to see what's going on.

License changes from GNU GPL -> MIT, so that seems fine here.

This is part of a bigger change that allows WLED to work with MagiQuest wands from Great Wolf Lodge. The wands aren't working with the old IRremoteESP8266 library, but they do with this one! I'm just breaking the changes up for ease of processing. (Graimalkin#2)

Testing:

Tested with an ESP32 dev board, TSOP4838 IR sensor, and generic LED light strip. Also grabbed one of the white 44 key IR remotes from Amazon -- https://www.amazon.com/dp/B0982BVCSD

Colors changed, brightness goes up and down, can swap to presets.

I'd recommend trying on a few more hardware stacks if you have it.

image

Summary by CodeRabbit

  • Refactor

    • Updated infrared remote control support to use a newer IR library, improving compatibility and reliability.
    • Enhanced debug output for IR remote decoding.
    • Maintained compatibility with previous IR code values.
  • Chores

    • Updated dependency for the IR remote library to a newer version from a different source.

Copy link
Contributor

coderabbitai bot commented Jun 14, 2025

Walkthrough

The changes update the infrared (IR) remote control functionality to use the newer Arduino-IRremote library (version 4.4.2) instead of IRremoteESP8266. The IR handling code is refactored to use the new IrReceiver API, with added debug output and compatibility helpers. Infrared-related header includes are removed from the main header file.

Changes

Files / Groups Change Summary
platformio.ini Switched IR remote library dependency from [email protected] to [email protected] via a GitHub URL.
wled00/ir.cpp Refactored to use IrReceiver API; removed IRrecv pointer; added decodeTypeToStr helper; reversed bits for select protocols; enhanced IR handling and debug output.
wled00/wled.h Removed conditional inclusion of IRremoteESP8266-related headers regardless of WLED_DISABLE_INFRARED flag.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0dce70 and 59f829b.

📒 Files selected for processing (2)
  • wled00/ir.cpp (2 hunks)
  • wled00/wled.h (0 hunks)
💤 Files with no reviewable changes (1)
  • wled00/wled.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • wled00/ir.cpp
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Graimalkin Graimalkin marked this pull request as ready for review June 15, 2025 00:31
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
wled00/ir.cpp (1)

712-723: Consider making the protocol type conversion more complete.

The decodeTypeToStr() function only handles a subset of protocols. Consider adding more protocol types or using a more generic approach.

You could enhance this function to handle all protocols supported by Arduino-IRremote:

 const char* decodeTypeToStr(uint8_t type) 
 {
   switch (type) {
     case LG :       return "LG";
     case NEC:       return "NEC";
     case SONY:      return "SONY";
     case SAMSUNG:   return "SAMSUNG";
     case MAGIQUEST: return "MAGIQUEST";
-    // Add other protocol cases as needed...
+    case RC5:       return "RC5";
+    case RC6:       return "RC6";
+    case PANASONIC: return "PANASONIC";
+    case JVC:       return "JVC";
+    case SHARP:     return "SHARP";
     default:        return "UNKNOWN";
   }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2d5c42 and 1430cb2.

📒 Files selected for processing (3)
  • platformio.ini (2 hunks)
  • wled00/ir.cpp (2 hunks)
  • wled00/wled.h (0 hunks)
💤 Files with no reviewable changes (1)
  • wled00/wled.h
🔇 Additional comments (7)
platformio.ini (1)

142-142:

✅ Verification successful

Verify the Arduino-IRremote library version for security and compatibility.

The migration from IRremoteESP8266 to Arduino-IRremote looks good. However, please verify that version 4.4.2 is still secure and compatible with your requirements.

Also applies to: 230-230


🌐 Web query:

What is the latest stable version of Arduino-IRremote library and are there any known security issues with version 4.4.2?

💡 Result:

The latest stable version of the Arduino-IRremote library is v4.4.2, released on May 10, 2025. (github.com)

As of now, there are no known security issues associated with version 4.4.2. The changelog for this release includes improvements such as support for SAMD51 timer3 when timer5 is unavailable, fixes for overflow handling, enhanced repeat detection for DistanceWidthProtocol, and optimizations like storing PulseDistanceWidthProtocolConstants in PROGMEM to save RAM. (github.com)

For more detailed information, you can refer to the official changelog. (github.com)

Citations:


Arduino-IRremote v4.4.2 confirmed as latest stable release with no known security issues.
No changes required for platformio.ini (lines 142 & 230).

wled00/ir.cpp (6)

4-4: LGTM!

The header inclusion is correct for the Arduino-IRremote library.


708-709: LGTM!

The deinitialization is properly simplified for the Arduino-IRremote library.


726-732: LGTM!

The reverse8() function correctly reverses the bit order using standard bit manipulation techniques.


735-746: Well-implemented compatibility layer.

The esp8266Value() function correctly maintains backward compatibility with existing IR codes by transforming the raw data format from Arduino-IRremote to match the old IRremoteESP8266 format. This is a clever solution to avoid modifying all entries in ir_codes.h.


752-771:

✅ Verification successful

Excellent adaptation to the new Arduino-IRremote API.

The migration properly uses the new IrReceiver singleton API and adds comprehensive debugging output. The use of esp8266Value() ensures backward compatibility with existing IR codes.


🏁 Script executed:

#!/bin/bash
# Description: Verify that serialCanTX is defined elsewhere in the codebase

# Search for serialCanTX definition
rg "serialCanTX" --type cpp --type h -B 2 -A 2

# Also check if it's a global variable or macro
ast-grep --pattern 'serialCanTX'

Length of output: 3430


LGTM: New IRremote API integrated correctly

I’ve confirmed that serialCanTX is declared as a global in wled00/wled.h and initialized in wled00/wled.cpp. The updated handleIR():

  • Uses IrReceiver.decode() and accesses IrReceiver.decodedIRData correctly
  • Provides detailed debug output with protocol, raw data, address, command, and bit count
  • Maintains backward compatibility via esp8266Value()
  • Calls IrReceiver.resume() after processing

No further changes needed—ready to merge.


701-704:

❓ Verification inconclusive

Verify the second parameter in IrReceiver.begin().

The migration to use the IrReceiver singleton looks correct. However, please confirm that the false parameter is intended (typically this disables LED feedback).


🏁 Script executed:

#!/bin/bash
# Description: Search for documentation or usage of IrReceiver.begin() to understand the second parameter

# Search for IrReceiver.begin usage patterns in the codebase
rg -A 3 "IrReceiver\.begin\(" 

# Look for any comments or documentation about the begin method
ast-grep --pattern 'IrReceiver.begin($_, $_)'

Length of output: 178


Confirm LED feedback parameter in IrReceiver.begin()

The migration to the IrReceiver singleton is correct. In wled00/ir.cpp around lines 701–704:

  • IrReceiver.begin(irPin, false);

The second argument (false) disables the onboard LED feedback. Please verify against the Arduino-IRremote library documentation that disabling LED feedback is intentional here.

*/

IRrecv* irrecv;
decode_results results;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove unused variable.

The global decode_results results variable appears to be unused after the migration to Arduino-IRremote, as the new library uses IrReceiver.decodedIRData instead.

-decode_results results;
 unsigned long irCheckedTime = 0;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
decode_results results;
unsigned long irCheckedTime = 0;
🤖 Prompt for AI Agents
In wled00/ir.cpp at line 11, remove the declaration of the unused global
variable `decode_results results` since the code now uses
`IrReceiver.decodedIRData` from the Arduino-IRremote library and no longer
requires this variable.

@blazoncek
Copy link
Collaborator

Thank you!
I hope this also reduces the final WLED binary size. Have you compared those?
If it increases it instead it will be a tough call.
Other than that one of the possible rewrites is to convert everything to JSON based decoding.

Copy link
Member

@netmindz netmindz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of small tweaks needed to the code.
I have not tested as I do not have any IR setups

wled00/ir.cpp Outdated
Comment on lines 759 to 767
Serial.printf_P(PSTR(" Protocol Received: %s\n"), decodeTypeToStr(results.protocol));
Serial.printf_P(PSTR(" Raw Data: %d\n"), results.decodedRawData);
Serial.printf_P(PSTR(" Address: 0x%X\n"), results.address);
Serial.printf_P(PSTR(" Command: 0x%lX\n"), (unsigned long)results.command);
Serial.printf_P(PSTR(" Num Bits: %d\n"), results.numberOfBits);
Serial.printf_P(PSTR(" Code: 0x%06lX\n"), (unsigned long)value);

Serial.println();
Serial.println(F("========================="));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the normal WLED debug logging rather than raw Serial.print*

Copy link
Collaborator

@blazoncek blazoncek Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is supposed to replace "IR recv" string printed out to serial with actual IR code received.
This may be needed to create custom JSON IR override. However there is no need for such detailed output as only IR code is needed.

There is one caveat we've learned on devices with CDC USB: if nobody is reading the output ESP may enter extensive waits when UART transmit buffer is full. So this piece of code may need a revision.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be slimmed down, it was in there to make it easy to debug what was going on with the IR input while testing hardware stacks.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the normal WLED debug logging rather than raw Serial.print*

@netmindz - You're looking for DEBUG_PRINTF_P(), correct?

I don't see anything in the contributing docs about logging syntax, so just went with what was already in place here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Graimalkin you made it debug-like output.
Stick with only IR code and Serial.print() is ok. For anything else DEBUG_PRINT...() is the way to go.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that will have been my bad guidance. I didn't realise we ever used raw Serial in AC, for MM we have USER_PRINT for non-debug messages

Copy link
Author

@Graimalkin Graimalkin Jun 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made changes to the logging here.

  • serial now only outputs Protocol received and value, and only if WLED_DEBUG isn't defined
  • if WLED_DEBUG is defined, the full IR results are returned to make it easier to debug what's going on here.

Let me know if you want this cleaned up more, but I think there's value in saving it for folks who want to debug remotes that don't do the reversing bit trick. ( Since results.value is a mix of Address / Command broken out of Raw Data ).

Debugging:
image

Non-Debug serial out:
image

@netmindz netmindz added the dependencies Pull requests that update a dependency file label Jun 15, 2025
@DedeHai
Copy link
Collaborator

DedeHai commented Jun 15, 2025

checked for code size: looks like it saves about 3k on a C3 build in current state.
I would request more testing. IR is a feature used in many setups.

@netmindz
Copy link
Member

While the library we were using had started life as being "based off" the library you are swapping to here, there is mention on GitHub about almost total rewrite for version 2.0

There is also the question about which remotes are supposed by which library. The change brings support for the remote you are trying to use if I'm understanding correctly, but which remotes might we loose support for by swapping?

@Graimalkin
Copy link
Author

While the library we were using had started life as being "based off" the library you are swapping to here, there is mention on GitHub about almost total rewrite for version 2.0

There is also the question about which remotes are supposed by which library. The change brings support for the remote you are trying to use if I'm understanding correctly, but which remotes might we loose support for by swapping?

So right now, platformio.ini is by default enabling these IR remote types:

  -D DECODE_HASH=true
  -D DECODE_NEC=true
  -D DECODE_SONY=true
  -D DECODE_SAMSUNG=true
  -D DECODE_LG=true

All of these are supported by the new Arduino-IRremote library.

Of these, it looks like in the IRremoteESP8266 (old) repo, NEC based remotes ( like my white 44 key one ), Sony, and Samsung have their results.value info come in in LSB (least significant bit) order but their address and command have been hit by reverseBits which does what it sounds like - reverses the bits. This puts these in MSB order. So when I reconstruct results.value from decodedRawData, it needs to be reversed if we want the values to match what is already in ir_codes.h.

Arduino-IRremote on converting from MSB first to LSB first -- https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes

I did make a change to the code to only convert those remotes that I found in IRremoteESP8266 that were being reversed ( and that arduino-IRremote mentioned needing it ). You can see those changes here before the debug logging changes:
b0dce70

Anyways, I went ahead and ordered a few more IR remotes that are supported per docs and mentioned in ir_codes.h. These should be here in a couple of weeks, so I'm going to mark this a DRAFT for now, and re-open when the remotes come in and I can test them out.

@Graimalkin Graimalkin marked this pull request as draft June 17, 2025 17:53
@blazoncek
Copy link
Collaborator

blazoncek commented Jun 17, 2025

Just so you are informed: Many users (including me) use various remotes using JSON IR remote option.
For example: I have an old Apple TV remote that I repurposed for WLED.

If the new library reverses bits all of these remotes will stop working until JSON files are updated (and accompanying JSON files in WLED-Docs) or this reversal is taken care of.

EDIT: I'm very fond of these.

@Graimalkin
Copy link
Author

Graimalkin commented Jun 17, 2025

Just so you are informed: Many users (including me) use various remotes using JSON IR remote option. For example: I have an old Apple TV remote that I repurposed for WLED.

If the new library reverses bits all of these remotes will stop working until JSON files are updated (and accompanying JSON files in WLED-Docs) or this reversal is taken care of.

EDIT: I'm very fond of these.

I believe the Apple TV remote is NEC based, so would need the reversebit to work. I think it'll work with these changes as is. If you get a chance, can you check it out?

Most NEC remotes should work as-is. There are some weird 16 bit address extended NEC remotes that might potentially see issues - but I'm not sure without testing with one.

That little remote you linked looks like another NEC remote. I grabbed these ones for testing with (In addition to the 44 key one I have):

https://www.aliexpress.us/item/2255800121523134.html?spm=a2g0o.order_list.order_list_main.10.63e318028Xdvoc&gatewayAdapt=glo2usa

image
image

@blazoncek
Copy link
Collaborator

If you get a chance, can you check it out?

It will be more than 2 weeks before I'm back home. Where all my equipment is.

@Graimalkin
Copy link
Author

If you get a chance, can you check it out?

It will be more than 2 weeks before I'm back home. Where all my equipment is.

It's all good. It's about 2 weeks until I get those remotes in also. 👍


#ifndef WLED_DEBUG
if (results.numberOfBits != 0 && serialCanTX) { // only print results if anything is received ( != 0 )
Serial.printf_P(PSTR(" Protocol Received: %s, Value: 0x%0lX\n"), decodeTypeToStr(results.protocol), (unsigned long)value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the encoding type is of any use to the average user and may add more questions than it answers as this is auto-detected and nothing that is selectable. Or what's the reasoning to add it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the encoding type for users to be able to do an easy sanity check that the IR signal they received is from the remote device they're using. If you're trying to add a Samsung remote, you'd expect to see SAMSUNG as the encoding device. Also, since platformio.ini only enables a very small set of brand remotes, for folks who are trying to add a LG based remote, they would get UNKNOWN with their code - which could prompt them to dig deeper into what's going on. Remote brands that aren't covered wouldn't be decoded properly and would most likely be treated as a HASH based decode.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to agree with @DedeHai . "Regular" user, who may be instructed to monitor serial port to see IR codes, doesn't need to know which brand his/her/its remote belongs to, he/she/it only needs to know IR code itself (to construct JSON file, for example).

However, if you insist on providing this information to the enduser, please move all of the strings into flash.

@Graimalkin
Copy link
Author

Graimalkin commented Jul 19, 2025

So I got my collection of remotes in, and I'm taking a look at this some more today.

I'm currently testing with:

  • white 24-key IR remote with R,G,B + 12 color-tones
  • blue 40-key IR remote with keys for 25%, 50%, 75% and 100%
  • white 44-key IR remote with up/down arrows for the colors R,G and B
  • black 6-key IR remote with CH up/down + Vol up/down

All of these are NEC based remotes, and they all seem to be working correctly. I can change colors, dim, turn off, and even repeat press for dimming up / down.

I also grabbed one of the TV remotes around here (Samsung) which according to platformio.ini is being decoded, to see if the codes stayed the same between MAIN / this branch. These remotes aren't in ir_codes.h, or supported in the drop down. BUT they should be getting decoded. They're going to use a variant of the NEC standard, so 🤷. Here's some testing from it:

Button                                 MAIN                               branch
power                                 0xE0E040BF                      0xE0E040BF
vol up                                0xE0E0E01F                      0xE0E0E01F
vol down                              0xE0E0D02F                      0xE0E0D02F
channel up                            0xE0E048B7                      0xE0E048B7
channel down                          0xE0E008F7                      0xE0E008F7
1                                     0xE0E020DF                      0xE0E020DF
2                                     0xE0E0A05F                      0xE0E0A05F
3                                     0xE0E0609F                      0xE0E0609F

That's about it for the remotes that I have available for testing with.

Let me know if there are next steps, or if I should just abort.

@Graimalkin Graimalkin marked this pull request as ready for review July 19, 2025 23:18
Copy link
Collaborator

@blazoncek blazoncek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I am very comfortable using IRremoteESP8266, I do not exclude switching to a library that is more robust, has smaller footprint and/or uses less resources.

When I looked at Arduino-IRremote I noticed this pragraph. If it is true, it might be a dealbreaker or may require additional safeguards implemented.

As for testing, unfortunately life took a turn and I do not have time to do any proper testing. Sorry. IMO it may be best to ask for help with testing on Discord or forum. @scottrbailey was involved with IR in the past so he hight be able to help.


#ifndef WLED_DEBUG
if (results.numberOfBits != 0 && serialCanTX) { // only print results if anything is received ( != 0 )
Serial.printf_P(PSTR(" Protocol Received: %s, Value: 0x%0lX\n"), decodeTypeToStr(results.protocol), (unsigned long)value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to agree with @DedeHai . "Regular" user, who may be instructed to monitor serial port to see IR codes, doesn't need to know which brand his/her/its remote belongs to, he/she/it only needs to know IR code itself (to construct JSON file, for example).

However, if you insist on providing this information to the enduser, please move all of the strings into flash.

@DedeHai
Copy link
Collaborator

DedeHai commented Jul 20, 2025

If you can, please test on all platforms, especially ESP8266, C3 and S2 as those have a single core.

@willmmiles
Copy link
Member

When I looked at Arduino-IRremote I noticed this pragraph. If it is true, it might be a dealbreaker or may require additional safeguards implemented.

TL;DR: WLED will be fine. That warning is intended for people trying to do IR and LEDs using bit-banging on slower hardware and 2017-era libraries.

--

So as it happens, I was looking through our current IR library earlier because I was curious as to whether or not it used the RMT hardware on ESP32. Sending and receiving IR data is what the RMT device was intended for, after all!

It turns out that no, IRremoteESP8266 is already just using a generic GPIO interrupt, and timestamping when the line changed state. Inefficient perhaps compared to using the dedicated hardware; but works well enough and isn't particularly platform specific. (This is good for me, in the context of replacing the RMT driver, as there's no way to share the RMT interrupt between two different drivers ... )

I just took a quick look through the Arduino-IRremote code, it seems like they've taken a different approach: essentially sampling the receiver with a 20kHz (!!) timer interrupt. This also works, but it'll be really wasteful of CPU - you pay the cost for all those interrupts even when the IR line is idle.

That said: I don't anticipate that it will cause any (new) issues with NeoPixelBus LED output. Any time we're using real hardware (I2S, RMT, UART, whatever) we're insulated from small CPU timing gaps; and even the bit-banging driver allows interrupts through after every pixel is written. (I should know; I PR'd that feature to NeoPixelBus myself to fix some glitching/crashes on an 8266 ;)

@DedeHai
Copy link
Collaborator

DedeHai commented Jul 20, 2025

not using hardware pin-interrupts is a very bad design...

@DedeHai
Copy link
Collaborator

DedeHai commented Jul 21, 2025

Ran a quick test, the polling eats up 10% of CPU time i.e. I see a 10-15% drop in FPS. Not acceptable.

@willmmiles
Copy link
Member

not using hardware pin-interrupts is a very bad design...

In fairness to the devs, (ab)using a timer is almost certainly the most portable solution. It's the equivalent of bit-banging -- highest CPU costs, most vulnerable to timing issues, but works absolutely everywhere with every protocol on any pin that can do GPIO.

Having spent time digging through FastLED and NeoPixelBus - both libraries that aim to reach for good performance everywhere, with a large number of custom drivers included - I can appreciate why a library maintainer (or team) might opt to say "no, we are not interested in being a library of optimized drivers for every chip ever -- we just do the one simple thing all the time; if you don't want that, go elsewhere".

Unfortunately, the long term impact of such a choice is that we, the developer community, never get to settle on the "one battle-tested library that everyone uses"; we end up with a panopoly of competing libraries, forcing people to choose between performance vs protocol support vs hardware support vs active maintenance vs ease-of-use .. sigh.

@DedeHai
Copy link
Collaborator

DedeHai commented Jul 21, 2025

That may have sounded wrong. Not questioning the devs of that library: if it's to be universal and for arduino purposes, using timer polling is the easiest option, no doubt. For our purposes however, it's a bad design so it can't be used.
The easy part is to read the signal, the hard part is to decode it and support all the formats. So if we get a library that just does the decoding, writing a function that reads pin interrupt timings should not be a huge effort.

@willmmiles
Copy link
Member

Ran a quick test, the polling eats up 10% of CPU time i.e. I see a 10-15% drop in FPS. Not acceptable.

Agreed - that's a significant regression; I don't want to merge that for all users. I would like to see some path forward for the ultimate goal here, though - my family has good memories of Great Wolf Lodge, we're hoping to visit sometime soon. ;)

As I see it, that leaves:

  • Someone forks IRremoteESP8266 and adds MagiQuest protocol support, at least until the devs there get back on their feet. (I see recent commits in the repo, but it's hard to know how active they'll be, if they'll move through the backlog). We're already keeping a stable of forked dependencies in the project; it's not the first time and won't be the last.
  • Split the IR support out to a "core usermod". (I'd like to do this anyways, if only to make it possible to exclude the IR library dependency entirely when it's not needed!) Then it's possible to have two (or more) different implementations using different backing libraries via each module's library.json. This allows easy build time selection. (Or potentially runtime selection, if someone includes both.)
  • Both of the above?
  • Any other ideas?

The easy part is to read the signal, the hard part is to decode it and support all the formats. So if we get a library that just does the decoding, writing a function that reads pin interrupt timings should not be a huge effort.

I did a quick search and I couldn't find one - basically every library that does decoding also includes one or more hardware drivers to read into their own idiosyncratic decoding format. (Also the hardware drivers are legitimately nontrivial -- you need precise enough timestamping, which isn't standard on most platforms, so it has to be set up by the driver.) IMO it's probably easier to port the decoding from one library to another than it is to replace the drivers for one of the existing libraries. YMMV, though.

https://github.com/IRMP-org/IRMP might be worth looking at; it supports both timer-based and pin-irq-based sampling. Although curiously the README consistently links over to IRremoteESP8266 (?!?).

@Graimalkin
Copy link
Author

Ok, going to go ahead and close this then as not a good change due to the CPU increase.

Thanks for all of the feedback folks!

@Graimalkin Graimalkin closed this Jul 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants