Well, here's the results of my research ...
I am just generating a test signal using Timer 1, and plugging D9 into D2 for testing how quickly we can see the transition.
First, using external interrupts. That is the slowest because of the way the ISR gets called (the overhead):
void gotData ()
{
PORTB = _BV (5); // toggle pin 13
PORTB = 0;
}
void setup ()
{
pinMode (9, OUTPUT);
pinMode (13, OUTPUT);
// set up Timer 1
TCCR1A = _BV (COM1A0); // toggle OC1A on Compare Match
TCCR1B = _BV(WGM12) | _BV(CS10) | _BV (CS12); // CTC, scale to clock / 1024
OCR1A = 4999; // compare A register value (5000 * clock speed / 1024)
attachInterrupt (0, gotData, RISING);
}
void loop ()
{
}
3.6875 uS before we do something useful.
Next, polling:
void setup ()
{
pinMode (9, OUTPUT);
pinMode (13, OUTPUT);
// set up Timer 1
TCCR1A = _BV (COM1A0); // toggle OC1A on Compare Match
TCCR1B = _BV(WGM12) | _BV(CS10) | _BV (CS12); // CTC, scale to clock / 1024
OCR1A = 4999; // compare A register value (5000 * clock speed / 1024)
}
void loop ()
{
while (PIND & _BV (2)); //make sure 1802 signal is low
while (true)
{
while ((PIND & _BV (2)) == 0); //wait for it to come high
PORTB = _BV (5); // toggle pin 13
PORTB = 0;
return;
}
}
That took 0.4375 uS.
Now, using a pin change interrupt:
ISR (PCINT2_vect)
{
PORTB = _BV (5); // toggle pin 13
PORTB = 0;
}
void setup ()
{
pinMode (9, OUTPUT);
pinMode (13, OUTPUT);
// set up Timer 1
TCCR1A = _BV (COM1A0); // toggle OC1A on Compare Match
TCCR1B = _BV(WGM12) | _BV(CS10) | _BV (CS12); // CTC, scale to clock / 1024
OCR1A = 4999; // compare A register value (5000 * clock speed / 1024)
// pin change interrupt
PCMSK2 = _BV (PCINT18); // only want pin 2
PCIFR = _BV (PCIF2); // clear any outstanding interrupts
PCICR |= _BV (PCIE2); // enable pin change interrupts for PCINT23..16
}
void loop ()
{
}
Reasonably fast: 1.375 uS. Less overhead before we hit the ISR.
Of course with the polling you can turn interrupts off so you don't get the jitter from Timer 0 interrupt being called. But you lose track of the elapsed time. The other methods require interrupts to be enabled, naturally. With a large gap between incoming bytes you could conceivably use Timer 1 as a timer with a suitable prescaler, as long as you catch any overflow before it wraps around.