tmmurcko:
the most number of interrupts you could handle is roughly 381,000 per second
OK - how come I can't get past the 80KHz frequency then?
You said:
digitalWrite isn't particularly fast, either. You can toggle pins faster than that, but why not let the timer do it for you?
How/what do you mean?
This is what digitalWrite does, with cycles counts at the end of each line in brackets:
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
180: 48 2f mov r20, r24 (1)
182: 50 e0 ldi r21, 0x00 ; 0 (1)
184: ca 01 movw r24, r20 (1)
186: 82 55 subi r24, 0x52 ; 82 (1)
188: 9f 4f sbci r25, 0xFF ; 255 (1)
18a: fc 01 movw r30, r24 (1)
18c: 24 91 lpm r18, Z+ (3)
uint8_t bit = digitalPinToBitMask(pin);
18e: ca 01 movw r24, r20 (1)
190: 86 56 subi r24, 0x66 ; 102 (1)
192: 9f 4f sbci r25, 0xFF ; 255 (1)
194: fc 01 movw r30, r24 (1)
196: 94 91 lpm r25, Z+ (3)
uint8_t port = digitalPinToPort(pin);
198: 4a 57 subi r20, 0x7A ; 122 (1)
19a: 5f 4f sbci r21, 0xFF ; 255 (1)
19c: fa 01 movw r30, r20 (1)
19e: 34 91 lpm r19, Z+ (3)
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
1a0: 33 23 and r19, r19 (1)
1a2: 09 f4 brne .+2 ; 0x1a6 <digitalWrite+0x26> (1/2)
1a4: 40 c0 rjmp .+128 ; 0x226 <digitalWrite+0xa6> (2)
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
1a6: 22 23 and r18, r18 (1)
1a8: 51 f1 breq .+84 ; 0x1fe <digitalWrite+0x7e> (1/2)
//
//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
//static inline void turnOffPWM(uint8_t timer)
static void turnOffPWM(uint8_t timer)
{
switch (timer)
1aa: 23 30 cpi r18, 0x03 ; 3 (1)
1ac: 71 f0 breq .+28 ; 0x1ca <digitalWrite+0x4a> (1/2)
1ae: 24 30 cpi r18, 0x04 ; 4 (1)
1b0: 28 f4 brcc .+10 ; 0x1bc <digitalWrite+0x3c> (1/2)
1b2: 21 30 cpi r18, 0x01 ; 1 (1)
1b4: a1 f0 breq .+40 ; 0x1de <digitalWrite+0x5e> (1/2)
1b6: 22 30 cpi r18, 0x02 ; 2 (1)
1b8: 11 f5 brne .+68 ; 0x1fe <digitalWrite+0x7e> (1/2)
1ba: 14 c0 rjmp .+40 ; 0x1e4 <digitalWrite+0x64> (2)
1bc: 26 30 cpi r18, 0x06 ; 6 (1)
1be: b1 f0 breq .+44 ; 0x1ec <digitalWrite+0x6c> (1/2)
1c0: 27 30 cpi r18, 0x07 ; 7 (1)
1c2: c1 f0 breq .+48 ; 0x1f4 <digitalWrite+0x74> (1/2)
1c4: 24 30 cpi r18, 0x04 ; 4 (1)
1c6: d9 f4 brne .+54 ; 0x1fe <digitalWrite+0x7e> (1/2)
1c8: 04 c0 rjmp .+8 ; 0x1d2 <digitalWrite+0x52> (2)
{
#if defined(TCCR1A) && defined(COM1A1)
case TIMER1A: cbi(TCCR1A, COM1A1); break;
1ca: 80 91 80 00 lds r24, 0x0080 (2)
1ce: 8f 77 andi r24, 0x7F ; 127 (1)
1d0: 03 c0 rjmp .+6 ; 0x1d8 <digitalWrite+0x58> (2)
#endif
#if defined(TCCR1A) && defined(COM1B1)
case TIMER1B: cbi(TCCR1A, COM1B1); break;
1d2: 80 91 80 00 lds r24, 0x0080 (2)
1d6: 8f 7d andi r24, 0xDF ; 223 (1)
1d8: 80 93 80 00 sts 0x0080, r24 (2)
1dc: 10 c0 rjmp .+32 ; 0x1fe <digitalWrite+0x7e> (2)
#if defined(TCCR2) && defined(COM21)
case TIMER2: cbi(TCCR2, COM21); break;
#endif
#if defined(TCCR0A) && defined(COM0A1)
case TIMER0A: cbi(TCCR0A, COM0A1); break;
1de: 84 b5 in r24, 0x24 ; 36 (1)
1e0: 8f 77 andi r24, 0x7F ; 127 (1)
1e2: 02 c0 rjmp .+4 ; 0x1e8 <digitalWrite+0x68> (2)
#endif
#if defined(TIMER0B) && defined(COM0B1)
case TIMER0B: cbi(TCCR0A, COM0B1); break;
1e4: 84 b5 in r24, 0x24 ; 36 (1)
1e6: 8f 7d andi r24, 0xDF ; 223 (1)
1e8: 84 bd out 0x24, r24 ; 36 (1)
1ea: 09 c0 rjmp .+18 ; 0x1fe <digitalWrite+0x7e> (2)
#endif
#if defined(TCCR2A) && defined(COM2A1)
case TIMER2A: cbi(TCCR2A, COM2A1); break;
1ec: 80 91 b0 00 lds r24, 0x00B0 (2)
1f0: 8f 77 andi r24, 0x7F ; 127 (1)
1f2: 03 c0 rjmp .+6 ; 0x1fa <digitalWrite+0x7a> (2)
#endif
#if defined(TCCR2A) && defined(COM2B1)
case TIMER2B: cbi(TCCR2A, COM2B1); break;
1f4: 80 91 b0 00 lds r24, 0x00B0 (2)
1f8: 8f 7d andi r24, 0xDF ; 223 (1)
1fa: 80 93 b0 00 sts 0x00B0, r24 (2)
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
1fe: e3 2f mov r30, r19 (1)
200: f0 e0 ldi r31, 0x00 ; 0 (1)
202: ee 0f add r30, r30 (1)
204: ff 1f adc r31, r31 (1)
206: ee 58 subi r30, 0x8E ; 142 (1)
208: ff 4f sbci r31, 0xFF ; 255 (1)
20a: a5 91 lpm r26, Z+ (3)
20c: b4 91 lpm r27, Z+ (3)
uint8_t oldSREG = SREG;
20e: 2f b7 in r18, 0x3f ; 63 (1)
cli();
210: f8 94 cli (1)
if (val == LOW) {
212: 66 23 and r22, r22 (1)
214: 21 f4 brne .+8 ; 0x21e <digitalWrite+0x9e> (1/2)
*out &= ~bit;
216: 8c 91 ld r24, X (2)
218: 90 95 com r25 (1)
21a: 89 23 and r24, r25 (1)
21c: 02 c0 rjmp .+4 ; 0x222 <digitalWrite+0xa2> (2)
} else {
*out |= bit;
21e: 8c 91 ld r24, X (2)
220: 89 2b or r24, r25 (1)
222: 8c 93 st X, r24 (2)
}
SREG = oldSREG;
224: 2f bf out 0x3f, r18 ; 63 (1)
226: 08 95 ret (4)
00000228 <digitalRead>:
}
Of course, all those lines won't be executed, but I think you'll agree that you will probably lose quite a few clock cycles while it does it.
And then there is the digitalRead you are doing.
This goes faster:
// timer compare interrupt service routine
ISR(TIMER1_COMPA_vect) {
PINB = bit (1);
}
That line toggles D9, believe it or not. 
But if you set the timer to do the toggling then you don't need an interrupt at all.