## How many cycles takes Timer2 OVF ISR overhead?

13 posts / 0 new
Author
Message

Hello all,

I am sure this Q. has already been answered but so far I could not find the answer.

How many cycles does it take to handle Timer2 interrupt in C/Arduino? Or, maybe better, where could I see the intermediate ASM code generated by GCC when compiling the C sketch?

The point is I have 16-MHz Arduino with AVR 328 (and alternatively a similar one with LGT8F328P). I want to implement a sine wave generator controlled by morse encoder and want to implement gaussian error function in the beginning and end of the tone. Timer2 frequency would be roughly 32 KHz (approx. 31.25 usec until the next interrupt).

Since there is some shifting involved (24-bit shift, 8x8 multiplication into 16-bit variable, and 8-bit shift), I am afraid I could exceed the number of cycles available in those 31 microseconds.

Is there some analysis already written? (I am quite sure it is but search engine probably does not want to show me :-) ).

Thank you,

Jindra

-- bev

OK4RM wrote:
a sine wave generator

Why it should be a sine wave generator, for playing morse? Nobody does like to listen morse on perfect sine, it is not natural.

It's something like 20 cycles but it jitters as it depends on the interrupted opcode and how long it takes to complete. For DDS Google "avr jesper DDS"

Thank you! This is what I needed.

BTW, is there any rule of thumb for how many cycles takes 32-bit addition, 8x8 => 16 bit multiplication etc? I would guess 32-bit add could be approximately 4 cycles, would multiplication be something like 40-50 cycles? Plus I am not sure about bit shift by multiples of 8. I would assume the compiler would do that by reading high byte. But I cannot find a confirmation :)

73! Jindra

-- bev

Hi, Clawson,

I looked at the dds generator. It is a slightly different approach. Since I need frequencies only up to 800 Hz, I decided to use PWM output with a 32 KHz clock (Timer2: 16 MHz / 510).  This will save a number of components (especially, for this purpose the R-2R network is a kind of waste of material).

My point is that a plain sine wave generator works well. However, when keyed (hard on-off switch of the sine wave pattern) it creates quite strong, audible clicks. This would be unpleasant for keying slow morse (up to 10-12 wpm) but for normal training, 24 wpm and faster, it is intolerable. Therefore I want to implement a few simple operations at the beginning and the end of the tone, ie. multiplication by looked-up 8-bit value of gaussian error function (implemented as 8x8 bit multiplication and 8-bit shift right). That will require a few cycles more, I just want to make sure I will not exceed the available time of approximately 30 us. In fact, the keyer does nothing most of the time - it is just waiting in the loop and once a time it checks input from paddles, and may also read rotary encoder or serial input. Even if there are just 10-15 usec left for regular program in each tick, it is just fine.

Thank you,

Jindra

-- bev

Sounds like a great project.

If it turns out you need more processing power, then have a look at an Xmega32E5.

It runs, in spec, at 32 MHz, much faster than the 16 or 20 MHz than most of the AVRs run at.

Additionally, it has an internal DAC, which can further simplify such projects.

I'm not familiar with the click problem.

Is that from an old school approach of gating a sine wave signal, and hence having a variable voltage discontinuity in the signal with every on and off of the keying?

If so, perhaps you should give a software DDS approach a try.

One of the many nice features of a SW DDS is that it has phase continuity.

In this case you can always start the sine wave at a zero crossing point in the cycle.

With a little care, you can always end on one, also.

JC

Edit: Typos

DocJC wrote:
With a little care, you can always end on one, also.
Exactly. To prevent "clicks" you just need to run the wave to its next "zero crossing" when the key is released (as it's only a fraction of one cycle and you are up in audio territory (like 440Hz or whatever) it should only be a matter of milliseconds to the next zero crossing in your wave output and the shaved ape listening to this thing will not realise the wave has run on for a few more sample points.

If we take your phase_accumulator code from https://www.avrfreaks.net/forum/can-8-bit-16-bit-24-bit-shift-c-be-replaced-directly-reading-high-byte then the use of 32-bit variables creates push & pop instructions galore. On AVR there' no way around this.

See here: https://godbolt.org/z/s9hqbxTWT

Hi, JC,

summary: it works like breeze, absolutely no timing problem. As a test sketch it plays QUICK BROWN FOX ... On the first run I was surprised by speed, far exceeding the programmed 22 WPM and high tone only to learn I forgot to set f_cpu parameter to 16 MHz, so PlatformIO build used 32 MHz as default. It seems 32 MHz is overkill for the purpose, the interrupt handler takes about 6 us during pause and up to ~11 us when it has to pick up sine values and multiply them by Gauss function (also from lookup table).

But it still audibly clicks. I did not have time yet to watch the output at oscilloscope. Hopefully it would reveal something useful.

As for the built-in DAC in LGT, I, too, noticed that possibility. The current script is universal - it should run equally well in both the AVR and LGT. I copied parts of code from some other AVR Arduino project, writing directly to control registers of ATMega, and it works in LGT, so it is universally compatible. I assume using DAC should generate less spurious RF radiation and provide cleaner signal, so later I will definitely try. The more so because I 'd have to change nothing in my program except the target control register(s) :)

Later today or during the weekend I will post it to github, hoping that someone would also find my bugs in applying the gauss function :) it is applied within like 14 or 15 ticks in the beginning and the end of the mark (tone), which should be about half millisecond. To me it seemed like long enough value, but the clicks don't approve that. During pause, there is constant output of 127, so kind of half-scale DC bias - could this be causing the clicks?

Jindra

DocJC wrote:

Sounds like a great project.

If it turns out you need more processing power, then have a look at an Xmega32E5.

It runs, in spec, at 32 MHz, much faster than the 16 or 20 MHz than most of the AVRs run at.

Additionally, it has an internal DAC, which can further simplify such projects.

I'm not familiar with the click problem.

Is that from an old school approach of gating a sine wave signal, and hence having a variable voltage discontinuity in the signal with every on and off of the keying?

If so, perhaps you should give a software DDS approach a try.

One of the many nice features of a SW DDS is that it has phase continuity.

In this case you can always start the sine wave at a zero crossing point in the cycle.

With a little care, you can always end on one, also.

JC

Edit: Typos

-- bev

Well, it IS a DDS in any case. The difference is that with a DDS + pin-wise DAC I'd have to use "many" pins and resistors ("many" is relative to only 1 pin of PWM output), while the same DDS approach used with PWM allows for a very simple circuit where you can plug in headphones without too much further signal conditioning or amplification (I use a two-stage RC lowpass to suppress PWM clock frequency and reduce output power to drive common, average headphones without hurting ears)

DocJC wrote:

...

If so, perhaps you should give a software DDS approach a try.

One of the many nice features of a SW DDS is that it has phase continuity.

...

JC

Edit: Typos

-- bev

OK4RM wrote:
22 WPM

Is it fixed value, can you have less, or more of it? There is my table, for your information:

; 2= Number of 2 ms elements per dot
; 3= Dot time in ms
; 4= One minute dot number: ndot=60000 ms/dottime
; 5= Speed in words per minute: wpm = ndot / 50
; 6= Associated tone frequency in Hz
;       1             2      3      4      5      6
;                            ms     ndot   wpm    Hz
.equ    zSpeedX     = 55   ; 110    545    11     128
.equ    zSpeedD     = 40   ; 80     750    15     256
.equ    zSpeedS     = 27   ; 54     1111   22     512
.equ    zSpeedM     = 20   ; 40     1500   30     1024
.equ    zSpeedF     = 17   ; 34     1765   35     2048

jqmosToneAndSpeed: ; 16, 8...  values of rQMOTone
.db 16,zSpeedX, 8,zSpeedD, 4,zSpeedS, 2,zSpeedM, 1,zSpeedF

Last Edited: Fri. Jun 24, 2022 - 11:23 AM

But it still audibly clicks.

Do you have other interrups running ?

If yes it will be hard to avoid some clicks.

One way could be to make a loop at the start of the interrupt that wait until the timer have a known value. (but the delay has to be the length of the longest time your interrupt can be hold back)