Timer programming

What you did with the 32 was set and reset 4 bytes.

32 = 1 << 5.

So his code is setting / clearing a particular pin, and is identical to your code.

But how does this relate to a DAC???

For debugging purposes. He is trying to try to the code so it flips a pin - to be observed by a scope that signals that the timing portion of the code is working. He can then add the DAC portion of the code.

A fairly common way to build up and debug one's code.

dhenry:
For debugging purposes. He is trying to try to the code so it flips a pin - to be observed by a scope that signals that the timing portion of the code is working. He can then add the DAC portion of the code.

A fairly common way to build up and debug one's code.

So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?
And, most importantly, if the timing part underestimates the load that driving the DAC will have on the program, then all this is useless. First, test the DAC, see how fast can the Arduino drive it without timings and then worry about triggering the times at a rate the arduino can handle. Since no PWM is really needed, go for the simplest timing arrangement, with an overflow or with an Clear to count and overflow to better adjust the desired frequency.

So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?

Not really sure about the "interrupts keeping the processor busy all the time" part. Interrupts are useful precisely because they do not keep the processor busy - they interrupt the processor only when certain conditions are met.

And, most importantly, if the timing part underestimates the load that driving the DAC will have on the program, ...

I do not know how the DAC part is to be implemented. The DAC could be really fast - a parallel DAC for example, or it could be preloaded by the main loop and strobed / activated by the isr. It could be implemented without causing excessive delays in the isr, rendering your question moot.

First, test the DAC, ...

Different ways of skinning the cat. Without knowing all the details, it is impossible to assert if one approach is better than another.

dhenry:

So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?

Not really sure about the "interrupts keeping the processor busy all the time" part. Interrupts are useful precisely because they do not keep the processor busy - they interrupt the processor only when certain conditions are met.

Interrupts can keep the processor busy. If they fire too frequently and/or take too long, the CPU will have only little time to execute loop() code.

I'm really grateful to everybody for all the comments and the debate, meanwhile, unfortunately, the point of my question is fading away. My trouble is "why this code doesn't works?" I know you could write the code in a different way but this should works and generate a pulse on pin 13 at a frequency of 62.5KHz (16MHz clock/256 - and it do it exactly) but with a variable pulse width related to the value OCR2B-OCR2A, while the output pulse is about 1.8uS wide for any value of OCR2B and OCR2A I've tested.
I can't understand why . I'm going to put the same code on Arduino board using GNU Ccompiler, AVRstudio and ISP to check if I've the same problem. I'll keep you updated.

You lost me here:

n=0;

...

void loop() 
{
  while (n==0) {}
  n=0; 
}

This might help:

Thanks Nick your link is useful for timers programming even if this is not my problem at the moment.
As I say in previous post I've tested the code compiled with WInAVR and put on the same Arduino Uno with ISP .
This is the adapted code

unsigned int n;
char m;

void setup() 
{
  DDRB=255;  
  PORTB&=~32;
  m=1;
  cli();  
  TCCR1B= 0x00;
  TCCR0B= 0x00; //stop    
  TCCR2B= 0x00;
  
  TCNT0= 0x00;  
  
  OCR2A= 20;	  //  
  OCR2B= 40;
    
  TCCR2A= 0x00;
  
  n=0;

  TIMSK0= 0;	
  TIMSK1= 0;
  TIMSK2= 6;    // timer2 output compare A & B match enabled
  TCCR2B= 1;    // start timer2 - prescaler=1 - 16 MHz clock 
  
  EIMSK=0;

  sei();
}


ISR(TIMER2_COMPA_vect)
{
    PORTB|=32;   
}

ISR(TIMER2_COMPB_vect)
{
    PORTB&=~32;     
}

void main() 
{
  setup();
  while (n==0) {}
  n=0; 
}

In this case it works fine and if( OCR2A-OCR2B) > 30 we obtain a pulse width equal to ((OCR2A-OCR2B) * 62.5nS) as it should happens in previous case. The limit of 30 for OCR2A-OCR2B is probably due to the time for ISR call, the storing and retrieving of registers, ect.
What I would like to know is how Arduino waste all that time and, if is possible, where can I find the assembly code of my C source compiled in Arduino environment ? What Arduino is doing in "loop() "?

Glad it helped.

My advice is: don't use ISRs if you want accurate timer output. Use the timer hardware.

How to view assembly

Duane B

rcarduino.blogspot.com

The limit of 30 for OCR2A-OCR2B is probably due to the time for ISR call, the storing and retrieving of registers, ect.

Yes, it is due to interrupt latency: when the 1st interrupt is being serviced (the context saving takes around 20 ticks), global interrupt is disabled. But if the 2nd interrupt arrives before the exeution of the 1st isr is finished, it is not serviced until the 1st interrupt is finished and global interrupt is re-enabled.

gcc-avr, the compiler behind the arduino ide, is actually quite good. You may speed up using more optimization (-O3 for example), or naked isr (no automatic context saving).

Using isr allows you to get very accurate timing. You just need to know its limitations.

I played with it a little in gcc-avr. With naked isr, the lowest I can get between the two isrs is about 10 ticks -> <1us @ 16MIPS.

The risk with naked isrs is that you have to look at the generated assembly and perform context save (push/pop) yourself.

I repeat that to get jitter-free timer output you have to use the hardware timer output. Not an ISR.

to get jitter-free timer output

There is no jitter-free output of any kind. Phase noise is a fact of life in oscillators. They all exhibit certain degrees of jitter.

The more important question is: can your application live with such imperfection? or can you design around it? or can you compromise? A jittery but otherwise accurate oscillator for example is far better than a jitter-free but inaccurate oscillator for a clock.

to use the hardware timer output is surely a good idea by many point of view, unfortunately in my case, as I wrote in my post, I have to update a DAC and this require in sequence to put two bytes on a buffer, to set a write bit and to set a load bit, impossible to do with just a timer output and easy to do with ISR. If you have MIPS enough.
Next time I'll define the subject of my post "DAC update" in place of "timer programming".
Thanks to all of you and expecially to dhenry for all the tests and naked isr.

DuaneB:
How to view assembly

RCArduino: How To View Arduino and Arduino Due Assembly

Duane B

rcarduino.blogspot.com

Thanks, really useful link!

alebit:
... hardware timer output is surely a good idea ...[but] I have to update a DAC ...

I've gotten good results getting an audio-frequency signal from a DAC using a hardware timer. Most DAC's have a "load" input, often called "LDAC," usually active low, that transfers data from internal holding registers to the DAC output register, so that multiple DACs can be loaded in sequence, and update their outputs simultaneously. The hardware timer fires the LDAC pulse; the next data sample is loaded into the DAC by an ISR, or in the main program.

The timer is set up like this:

  • Waveform Generation Mode = Fast PWM
  • Compare Output Mode A = Normal, OCXA disconnected
  • Compare Output Mode B = OCXB set on match/clear at BOTTOM, or opposite, depending on the requirements of the DAC
  • Clock Select and OCRXA as required to generate the required DAC update frequency
  • OCRXB to provide a pulse of appropriate length to the DAC
  • Interrupt on OCRXB compare match enabled; other interrupts disabled

OCXB is connected to LDAC. The first sample is loaded to the DAC's internal registers in setup(), then the timer is started. ISR(TIMERX_COMPB_vect) loads the next sample into the DAC's internal registers, bumps the pointer, and exits. When the timer rolls over, the output goes low, and the data is loaded into the DAC's output registers, without any action from the program. If the timing isn't too fast, the ISR could instead signal the main program, and let the main handle the I/O.

For something like frequency synthesis, where timing accuracy matters, this method is superior to updating the DAC output from inside an ISR. There's no problem with interrupt latency, and no chance that the timer will fire late because some other interrupt was being serviced at the time. It may not be theoretically "jitter-free," but its jitter is so much reduced that, from a practical standpoint, you could call it "jitter-free."

Thats interesting, i have been using ISRs to generate DDS Audio and hadnt even considered the impact of the other ISRs on the sound quality, anyway its nice to know that there is a neat solution in your suggestion.

Thanks

Duane B

rcarduino.blogspot.com

tmd3:
...
For something like frequency synthesis, where timing accuracy matters, this method is superior to updating the DAC output from inside an ISR. There's no problem with interrupt latency, and no chance that the timer will fire late because some other interrupt was being serviced at the time. ..."

Thanks, very nice idea!