PPM Reading and Generating with Timer Interrupts

Hi all!

I am fairly new to timer interrupts, maybe someone can help me out! I am trying to program an Arduino that can read a PPM signal, process some stuff and generate a new PPM signal. Currently I am only working on the reading and generating.
I am using Timer1 in Mode 15 to create the PPM signal on the Arduino Pin10. The pulse length is set with OCR1B, and the time between to pulses is set with OCR1A on every Timer Overflow.
I want to read in a PPM signal with Arduino Pin 8 (the Input Capture Pin). With every rising edge the time of Timer1 is stored, which is used to calculate the time between two pulses. If the Timer overflows its Top value is added to the total to keep time.

That at least is the theory… in practice I sometimes get negativ values for the time between to pulses. I believe that happens because the ISR(TIMER1_OVF_vect){} is skipped. Is that correct and can you tell me if there is a workaround for that?

Here is my Code:

const int Num_Channels_Out = 8;
const int Num_Channels_In = 8;
unsigned long PPM_Out[Num_Channels_Out + 1]; 
long PPM_In[Num_Channels_In];
long PPM_In_Capture = 0;
int PPM_Out_Channel_Index = 0;
int PPM_In_Channel_Index = 0;

unsigned long PPM_Max = 32233; //Blanking = 65535, 100% = 32233, 50% = 24016, 0% = 15799 (using Trial and Error)
unsigned long PPM_Min = 15799;
unsigned long PPM_Center = (PPM_Min + PPM_Max) / 2;
unsigned long PPM_Blanking = 65535;

void setup() {
  //Pin Setup
  pinMode(8,INPUT);  // Ensure the Timer 1 Input Capture pin is configured for Input
  pinMode(10,OUTPUT); // Ensure the Timer 1 Channel B pin is configured for output
  //Timer Setup
  cli();         // Disable Interrupts
  //Timer1 Setup
  TCCR1A = 0;    // Reset TCCR1A Register
  TCCR1B = 0;    // Reset TCCR1B Register
  TCCR1C = 0;    // Reset TCCR1C Register
  TCNT1 = 0;    // Ensure the first slope is complete
  ICR1 = 0;
  OCR1B = 4799; // Compare Match -> On-Time aka. 0,3ms -> 4799
  OCR1A = 65535; //Top -> Pulse-Lenght, Set in Interrupt-Method, here set to Max > 4ms  
  TIMSK1 = (1 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (1 << TOIE1); // Using InputCaptureInterrupt to read PPM in on Pin D8, Using TimerOverflowInterrupt to set OCR1A
  TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (1 << WGM11) | (1 << WGM10); // Mode 15 -> Fast PWM, no Prescaling, OC1A disconnected, OC1B connected -> Pin D10
  TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10); // Start Timer1, Input Capture Edge Select set to Rising
  sei(); //Enable Interrupts

  //Setup of PPM Arrays
  PPM_Out[0] = PPM_Blanking;
  for(int i = 1; i <= Num_Channels_Out; i++){
    PPM_Out[i] = PPM_Center;
    }
  for(int i = 0; i < Num_Channels_In; i++){
    PPM_In[i] = 0;
    }

  Serial.begin(115200);
}

void loop() {
  
 for(int i = 0; i < Num_Channels_In - 1; i++){ //only here for debugging
    Serial.print(PPM_In[i]);
    Serial.print(" ");
    }
 Serial.println(PPM_In[Num_Channels_In - 1]);

}

ISR(TIMER1_CAPT_vect){
  PPM_In_Capture += TCNT1;
  if(PPM_In_Capture > 47999){ // equals 3ms -> Blanking, new Signal
     PPM_In_Channel_Index = 0; //go to first Channel
    }
  else if(PPM_In_Channel_Index < Num_Channels_In){ //normal Channel
    PPM_In[PPM_In_Channel_Index] = PPM_In_Capture;
    PPM_In_Channel_Index++; //go to next Channel
    }
  PPM_In_Capture = (long) -1 * TCNT1; //resets PPM_In_Capture, to capture new Channel 
}

ISR(TIMER1_OVF_vect){
  PPM_In_Capture += OCR1A; //adds last Pulse-Lenght to PPM_In to keep time, allthough Timer1 Overflows 
  OCR1A = PPM_Out[PPM_Out_Channel_Index]; //sets Pulse-Lenght for PPM_Out Pulse
  if(PPM_Out_Channel_Index < Num_Channels_Out){ //Setup for next PPM_Out Pulse
    PPM_Out_Channel_Index++;
    }
  else{
    PPM_Out_Channel_Index = 0;
    }
}

Thank you!

Nevermind!

I was adding the OCR1A of a wrong cycle, that is why i got wrong results. By shifting this back one interation, it works.