Using IR Remote library while bit banging

I'm working on a light installation that I would like to control with my IRremote.

To control the light string (Triklits) I use a modified DMXcode from the examples on the playground Arduino Playground - Examples

As IRlibrary I use shirriff Arduino Infrared Library (GitHub - Arduino-IRremote/Arduino-IRremote: Infrared remote library for Arduino: send and receive infrared signals with multiple protocols). This one works with interrupts, I've read that this is every 50microseconds.

Or course controlling the strings and receiving remote data works perfectly in seperate sketches. However the remote doesn't work when I add it to the sketch. I think because when sending the light string data interrupts are disabled (cli() and sei().

I tried to enable receiving IR using attachInterrupt (I use pin 2 (interrupt 0) for the IRreceiver). However the IRreceiving code stays running, so this didn't solve it either. I tried to disable the timer in the library again by adding (TIMER_DISABLE_INTR; to the IRrecv::resume() function). But than I didn't receive any data.

I tried different IRremote libraries and solutions, but none of them seem to work fine so I prefer to use the shirriff ir remote library.

Is it possible what I want? Or is it smarter to use two Arduinos one for receiving the IR and one for controlling the lights.
Any idea's on what I can modify?

I doesn't matter if the lights don't update when receiving IR.

Code IRremote

#include <IRremote.h>

int RECV_PIN = 2;
IRrecv irRecveiver(RECV_PIN);
decode_results results;

void setup()
{ Serial.begin(57600);
  irRecveiver.enableIRIn(); // Start the receiver
}

void loop() {
       
if (irRecveiver.decode(&results)) 
{  decodeReceivedIR(&results);
    irRecveiver.resume(); 
}

Code Triklits

int pin = 5;  
int port_to_output[] = {
   NOT_A_PORT,
   NOT_A_PORT,
   _SFR_IO_ADDR(PORTB),
   _SFR_IO_ADDR(PORTC),
   _SFR_IO_ADDR(PORTD)
   };

#define ARRAYLENGTH 24*3
int intensity_Array[ARRAYLENGTH];
int arraylength=ARRAYLENGTH;

byte ledNum; 
byte redVal; 
byte grnVal; 
byte bluVal;  

int arrayStartPos;

// ----------------------------------------------------------

void setup() 
{ pinMode(5, OUTPUT);
  digitalWrite(13, HIGH);  
  Serial.begin(57600); 
}

void loop()
{ 
    for(int i=0;i<(23*3);i=i+3)
    { 
      redVal = 0;
      grnVal = 10;
      bluVal = 128;
      
      if(i==(22*3)) redVal = 128;
      
      arrayStartPos = ledNum*3;
    
      intensity_Array[i]   = redVal;
      intensity_Array[i+1] = grnVal;
      intensity_Array[i+2] = bluVal;
    }
  
  
    cli();    
    sendFrame(); 
    sei();
}

void sendFrame()
{ int portNumber = port_to_output[digitalPinToPort(pin)];
  int pinMask = digitalPinToBitMask(pin);
  
  byte header = B0100; // reversed by loop to B0010
  byte mask; 
  
  // header 0010 --------------------------------  
    
  for (int count = 0; count < 4; count++) 
  { if (header & 0x01) _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;
    else               _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask; // 0
    header>>=1; 
    delayMicroseconds(22);
    asm("nop\n nop\n nop\n nop\n");    
  }   
  
  // RGB data 24 * 32 bits-----------------------
    
  for(int i=0;i<24;i++)
  { int count=i*3;  
    int r_Byte=intensity_Array[count]; //;intensity_Array[count*3];
    int g_Byte=intensity_Array[count+1];//intensity_Array[count];//=intensity_Array[(count*3)+1];
    int b_Byte=intensity_Array[count+2];//=intensity_Array[(count*3)+2];   
  
    // send interlaced RGB data for 1 light
    for (mask = 0x01; mask>0; mask <<= 1)
    { if (r_Byte & mask)  _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;  // 1
      else                _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask; // 0
    
      delayMicroseconds(22);
      asm("nop\n nop\n nop\n nop\n");
    
      if (g_Byte & mask) _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;  // 1
      else               _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask; // 0
    
      delayMicroseconds(22);
      asm("nop\n nop\n nop\n nop\n");
        
      if (b_Byte & mask) _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;   // 1
      else               _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask;  // 0 
       
      delayMicroseconds(22);
      asm("nop\n nop\n nop\n nop\n");
   
      if (b_Byte & mask) _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask; // 0
      else               _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;  // 1 // p is opposite of b   
    
      delayMicroseconds(22);
      asm("nop\n nop\n nop\n nop\n");
    
      //delayMicroseconds(16); // shorter because calculation at start.. it works...
    }    
  }
  
  // send trailer bit 0
  _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask; 
  delayMicroseconds(17);
}

It seems like it should work, although, you might be right that 2 Arduinos are the way to go. You could buy a standalone Atmega328 just for the IR sensor instead of using a whole Arduino. Jameco has a great tutorial on setting one up if you are interested http://www.jameco.com/Jameco/workshop/JamecoBuilds/arduinocircuit.html .

Perhaps instead of turning off interrupts and using delay() and nops for timing you could use a timer interrupt to send the bits at the right time.

Ok, but that seems pretty advanced. I was already glad that I could modify that DMX code. I'm not really into all the assembly stuff.

Do I only have to replace these delay and asm parts? Any hints or resources on how I could do that?

delayMicroseconds(22);
asm("nop\n nop\n nop\n nop\n");

I've solved it till now with an extra Arduino (I had one lying around, so that was easier than the "breadboard" circuit) for the IR remote.

However running everything from one Arduino would be better of course.