I'm working on trying to implement code that has been working on my Uno/Nano, onto an Arduino Mega. The code in question is Kelvin Nelson's "Read PWM, Decode RC Receiver Input, and Apply Fail-Safe" which can be found in detail here.
It seems the port registers are coded for the Nano and Uno, instead of using the hardware abstraction layer to ensure compatibility. I'm trying to figure out the best way to translate these to a mega board in a way that maintains the higher speed interrupt service.
I believe it is this section here that is causing the mismatch, but I would greatly appreciate any help.
// FUNCTION USED TO TURN ON THE INTERRUPTS ON THE RELEVANT PINS
// code from http://playground.arduino.cc/Main/PinChangeInterrupt
void pciSetup(byte pin){
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}
// FUNCTION USED TO FIND THE PIN POSITION ON EACH PORT REGISTER: helps the interrupt service routines, ISR, run faster
void pwmPIN_to_port(){
for (int i = 0; i < num_ch; i++){
// determine which port and therefore ISR (PCINT0_vect, PCINT1_vect or PCINT2_vect) each pwmPIN belongs to.
pwmPIN_port[i] = 1; // pin belongs to PCINT1_vect (PORT C)
if (pwmPIN[i] >= 0 && pwmPIN[i] <= 7) pwmPIN_port[i] = 2; // pin belongs to PCINT2_vect (PORT D)
else if (pwmPIN[i] >= 8 && pwmPIN[i] <= 13) pwmPIN_port[i] = 0; // pin belongs to PCINT0_vect (PORT B)
// covert the pin number (i.e. pin 11 or pin A0) to the pin position in the port register. There is most likely a better way of doing this using a macro...
// (Reading the pin state directly from the port registers speeds up the code in the ISR)
if(pwmPIN[i] == 0 || pwmPIN[i] == A0 || pwmPIN[i] == 8) pwmPIN_reg[i] = 0b00000001;
else if(pwmPIN[i] == 1 || pwmPIN[i] == A1 || pwmPIN[i] == 9) pwmPIN_reg[i] = 0b00000010;
else if(pwmPIN[i] == 2 || pwmPIN[i] == A2 || pwmPIN[i] == 10) pwmPIN_reg[i] = 0b00000100;
else if(pwmPIN[i] == 3 || pwmPIN[i] == A3 || pwmPIN[i] == 11) pwmPIN_reg[i] = 0b00001000;
else if(pwmPIN[i] == 4 || pwmPIN[i] == A4 || pwmPIN[i] == 12) pwmPIN_reg[i] = 0b00010000;
else if(pwmPIN[i] == 5 || pwmPIN[i] == A5 || pwmPIN[i] == 13) pwmPIN_reg[i] = 0b00100000;
else if(pwmPIN[i] == 6) pwmPIN_reg[i] = 0b01000000;
else if(pwmPIN[i] == 7) pwmPIN_reg[i] = 0b10000000;
}
}
// SETUP OF PIN CHANGE INTERRUPTS
void setup_pwmRead(){
for(int i = 0; i < num_ch; i++){ // run through each input pin
pciSetup(pwmPIN[i]); // enable pinchange interrupt for pin
}
pwmPIN_to_port(); // determines the port for each input pin
// pwmPIN_to_port() also coverts the pin number in pwmPIN[] (i.e. pin 11 or pin A0) to the pin position in the port register (i.e. 0b00000001) for use in the ISR.
if(RC_inputs == 0 || RC_inputs > num_ch) RC_inputs = num_ch; // define the number of pins connected to an RC receiver.
}
