fastest timer interrupt

hi everyone
I'm trying to understand the use of internal timers interrupt.
If I made the math correctly, the fastest overflow interrupt that we can get by the 8 bit timers is every 0,0625 us
to get this value, we need to use no prescaler and to load the closest possible value inside the timer counter (since it's 8 bit, we load in it 255) so that it can count only 1 time and then overflow. But does that gives 0,0625us or twice that time?

To count to one you load 0 because the timer is zero-relative.

However interrupts cannot be processed that fast.

I think the fastest you can get a timer to output stuff is by using the hardware toggle, eg. this sketch:

const byte CLOCKOUT = 9;

void setup ()
  {
  pinMode (CLOCKOUT, OUTPUT);
  // set up Timer 1
  TCCR1A = _BV (COM1A0);  // toggle OC1A on Compare Match
  TCCR1B = _BV(WGM12) | _BV(CS10);   // CTC, no prescaling
  OCR1A =  0;       // output every cycle
 }  // end of setup

void loop () {}

However that generates a frequency of 8 MHz as it does a toggle every 62.5 nS, as this screenshot shows:

thank you,
why it can't be processed that fast? maybe because the service routine would take too much to be completed related to every interrupt?
so what could be the fastest count that I can get from the internal timer interrupt (without CTC mode) ?

Interrupts take time. See this:

Scroll down to "How long does it take to execute an ISR?".

The minimum to enter and leave an ISR would be around 2.625 uS, and that is without actually doing anything useful.

What are you really trying to do here? What is the requirements to get fast counts?

thanks again, I didn't considered that on my counts..
I'm just experimenting trying to make the highest frequency I can get (square wave, 50% duty cycle) on a pin without using PWM..
of course inside the ISR I will need some assembly code to save time

Assembly code is unlikely to save you time, the compiler knows how to generate it.

Why are you setting up an ISR to generate a 50% PWM cycle, when the timer is designed to do exactly that? Whatever you do is going to be slower than the code I showed above. Plus there will be jitter.

I will setup the timer and not using the PWM because I'd like to output more than 1 PWM at the same time but at different frequencies.

about saving time, I've read somewhere that using DigitalWrite would take about 50 clock cycles, while directly writing inside the pin register would take 2 cycles.

You should actually read Nick's page...

The interrupt itself takes 4 clock cycles. Dispatch takes another 3, and return from interrupt takes 4. At least one instruction occurs between each interrupt. So that means that you could possibly have an interrupt occur every 12 clock cycles, if it did nothing at all.

I think you could write a very minimalist "naked" ISR in assembly using only IO instructions (sbi, cbi) that avoiding the usual context saving (because it doesn't change anything), and managed to toggle a port pin. But it wouldn't be able to access the timer registers,
or do any math, so...

I'd like to output more than 1 PWM at the same time but at different frequencies.

The minimal code wouldn't be anywhere CLOSE to doing that; if all it does is toggle a pin, it hasn't done anything more than the timer hardware could have done all by itself. The AVR does have three separate timers, so it could generate 3 separate PWM frequencies (or output toggle frequencies.) But to generate multiple frequencies from one timer, you'd have to do some additional math in the ISR, which means saving a bunch of context.

I've read somewhere that using DigitalWrite would take about 50 clock cycles, while directly writing inside the pin register would take 2 cycles.

Yes. And that has nothing to do with interrupt timing. You could go from about 40 cycles for the standard gcc ISR overhead, to about 12 cycles for the absolute minimum that doesn't do anything...

no, maybe I didn't explained very well because of my bad english, but I don't want to use assembly to save ISR access-exit time..I just meant that using assembly I could gain some time for the toggle operation..of course the time required for the ISR is fixed.
and of course the ISR can't be too minimal for what I need to do, since I have to keep some counters for each frequency I need to output.

Dimitree:
I will setup the timer and not using the PWM because I'd like to output more than 1 PWM at the same time but at different frequencies.

How many? As Westfw said, you can use the hardware timers to output 3 different frequencies right now. On a Mega you have more timers again.

In any case, using one timer and an ISR to output 3 separate frequencies is going to be fraught with peril because of all the calculations you will have to do: is it time to toggle pin 1, 2, 3 etc?

What is this project anyway? Are you making a function generator which outputs multiple frequencies at once?


I just meant that using assembly I could gain some time for the toggle operation.

You don't need to use assembly for that.

Example code:

void loop ()
  {
  PIND |= 1 << 4;  
  }  // end of loop

That is actually the fastest way you can toggle a pin, BTW. Writing to the PIN register toggles it. Now check the generated code:

000000be <loop>:
  be:	4c 9a       	sbi	0x09, 4	; 9
  c0:	08 95       	ret

A single "set bit" instruction. Even if you wrote in assembler you would choose that. So forget about using assembly to save time. You won't.

thanks again,
I made another mistake, I intended to say that I'd use to directly address the pin/register instead of using the digitalWrite, and I messed up that with Assembly, that is a different thing indeed.

No I'm not making a function generator actually I'm just trying to learn basic digital sound generation techniques

This might help -

Duane B

rcarduino.blogspot.com

thank you, that looks great.
it's a bit OT, but, looking at your project..you connect the output jack almost directly to the digital pins, in this way the output swings between 0V and 5V.
my question is, those levels are standard in the audio world? if not, what's the standard?
I ask this because I'd like to connect arduino to my usb souncard to test those things I'm learning.

btw, am I wrong or I can't set the precise frequency I need using the 3 timers with PWM modes?
I can only get those frequencies obtained by:

16 MHz / 64 / (OCR2A+1) = frequency
if I use 64 as prescaler value..and since I can use 256 values for OCR2A, I'm "limited" to 256 * 5 (possible prescaler values) possible frequencie values..am I right or I'm missing something? (I'm talking about the 8 bit timers of course, not considering the 16 bit one)

Yes, fundamentally. An 8-bit timer by definition is only going to give you 256 possible frequencies, and by choosing different prescalers those frequencies cover different ranges (there would be some overlap).

For example, a prescaler of 1, and counting to 8, would give the same results of a prescaler of 8, and counting to 1.

For a wider range of frequencies, use Timer 1 (the 16 bit timer). For more of them, use a Mega 2560 board.

I see..
so for now I will try to get a better accurance using timer overflow interrupt (of course doing some math based on the access-exit timer of ISR and every operation I will do there), If I can't get better accurance I will move to Mega2560

I dont really agree about the 256 frequencies.

The midi note range has only 128 tones which cover most of what a human can hear, so unless your making music for bats and dolphins forget about the timers and mega's and just get a good grasp of DDS on your UNO. Once you have this figured you might want to go directly to an Arduino Due, but whatever you do DDS is the foundation you need for sound and is easily learnt on the UNO.

Duane B

I've been studying the Fast Pwm mode on the 3 timers on those days (using OCRxA as TOP and so varying the frequency).
please correct me if I'm wrong, but seems like I can only use even values for OCRxA if I want a 50% duty cycle,
since to get 50% duty cycle it should result OCRxB+1 / OCRxA+1 = 0,5.
is this correct?

Yes, well odd really if you allow for them being zero-relative. But certainly, every second one.

eg. OCRA = 3 (counts to 4) then OCRB = 1 (counts to 2) gives you a 50% duty cycle.

If you just want a 50% cycle you could use CTC and toggle the output pin.

If you just want a 50% cycle you could use CTC and toggle the output pin.

Indeed, what I read on the AVR datasheet says (at the end of Fast PWM mode section) that I can achieve a 50% duty cycle waveform in fast PWM mode by setting OC2x to toggle on each compare match, by setting COM2x1:0 = 1.
I did that but I couldn't get anything from the output (OCR2B output).
Also, I don't understand if the prescaler is used in this mode too (if yes, I guess the calculation for the frequency is the same).