which I think is the same as 0xffffffff in HEX
That is the value of REPEAT_CODE. When a button is held, you get the REPEAT_CODE value from your decoder object (myDecoder.value).
The use of IRLibRecvLoop.h means you are blocking on getResults(), which only returns (always returns true) when an ir code is seen (or at least one bit is seen, which then eventually activates a timeout). So is easy enough to deal with your desired code and the REPEAT_CODE, but there is no ir code seen when a button is released so you would be waiting in a loop ( getResults() ) waiting for an ir code that will not be seen so cannot turn off the led when a button is released.
You could add an additional timeout to the getResults function-
https://github.com/cyborg5/IRLib2/blob/master/IRLib2/IRLibRecvLoop.cppinsert after line 27-
if( oldState == HIGH && recvGlobal.recvLength == 0 && ((micros() - startTime) > 300000ul) ){
return false;
}
which would then have getResults() return false for an inactivity timeout (300ms in this case). You can then turn off the led when no activity is seen.
void loop(){
if( myReceiver.getResults() ){
uint32_t ircode = myDecoder.value;
if( ircode == 0x2ED1C03F ) digitalWrite( greenLED, HIGH ); //valid ir code, turn on led
else if( ircode != REPEAT_CODE ) digitalWrite( greenLED, LOW ); //some other ir code (and not a repeat), turn off led
//if REPEAT_CODE, do nothing (led is still on, or off)
myReceiver.enableIRIn(); //rearm
}
else digitalWrite( greenLED, LOW ); //inactivity timeout, so turn off led
}
Using a timeout in getResults() now allows being a little 'late' to the next call and may miss the initial bit transition, so will also depend on how much other code executes between calls and how much tolerance is given for the ir sync timing. If you end up missing codes because of this scheme, then you should just use the interrupt version (or maybe use that anyway).