Pages: 1 [2]   Go Down
Author Topic: Clean way to turn interrupts on and off?  (Read 1589 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

analogRead() seems to be fast enough. ... But we're drifting off topic...

Well, not really, because timing seems to be important to you.

-My sample clock wants to be 125us which I think will be another timer interrupt (I'll write that part tomorrow).

A normal analogRead (save fidding with registers) will take 104 uS. So most of your 125 uS is gone in doing the analogRead alone. I'm drawing that to your attention in case you think it is instant, and that you have something like 110 uS over between reads.

One possible thing you could do which would remove the worry about interrupt latency, and also whether or not another interrupt was active, would be to use the external ADC trigger (page 252 and 266 of the datasheet). You could start the conversion highly reliably on a timer compare match event, and then just use an interrupt to gather the ADC results, when available. This also means you don't wait 104 uS doing nothing. Win win!
Logged

SF Bay Area (USA)
Online Online
Tesla Member
***
Karma: 106
Posts: 6381
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Avoiding other issues...

Quote
There must be a slick way to turn interrupts on and off individually with minimal avr register writes.
Why do you have this "minimal avr register writes" desire?  To turn off an INDIVIDUAL interrupt, you typically have to change a single bit setting in one register:
Code:
TIMSK1 &= ~(1<<OCIE1B);  // Turn off timer interrupt
  :
TIMSK1 |= (1<<OCIE1B); // Turn timer interrupt back on
Those should run about 3 Instructions each, and this isn't some multi-GHz chip where accessing an IO register might be unusually "expensive" because it stalls the pipeline and invalidates caches or something.  If you want control of the individual interrupts, I don't think that you can get any "slicker."  Now do you need to.
Note that you do NOT need to reinitialize the rest of the timer just to turn interrupts on and off, but that may mean that you will get an interrupt as soon as you re-enable it...

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

analogRead() seems to be fast enough. ... But we're drifting off topic...

Well, not really, because timing seems to be important to you.

-My sample clock wants to be 125us which I think will be another timer interrupt (I'll write that part tomorrow).

A normal analogRead (save fidding with registers) will take 104 uS. So most of your 125 uS is gone in doing the analogRead alone. I'm drawing that to your attention in case you think it is instant, and that you have something like 110 uS over between reads.

One possible thing you could do which would remove the worry about interrupt latency, and also whether or not another interrupt was active, would be to use the external ADC trigger (page 252 and 266 of the datasheet). You could start the conversion highly reliably on a timer compare match event, and then just use an interrupt to gather the ADC results, when available. This also means you don't wait 104 uS doing nothing. Win win!

Yeah, I was measuring ~120us max latency in the analogRead(), plus whatever to write an int to an array (I didn't measure that yet). This drove the 125us sample time goal. There's time between bursts to process the array of samples as little, and as much time as it takes to post process it after the scan.

--> I really  like the auto triggered ADC and will certainly do that. Very helpful, many thanks.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Avoiding other issues...

Quote
There must be a slick way to turn interrupts on and off individually with minimal avr register writes.
Why do you have this "minimal avr register writes" desire?  To turn off an INDIVIDUAL interrupt, you typically have to change a single bit setting in one register:
Code:
TIMSK1 &= ~(1<<OCIE1B);  // Turn off timer interrupt
  :
TIMSK1 |= (1<<OCIE1B); // Turn timer interrupt back on
Those should run about 3 Instructions each, and this isn't some multi-GHz chip where accessing an IO register might be unusually "expensive" because it stalls the pipeline and invalidates caches or something.  If you want control of the individual interrupts, I don't think that you can get any "slicker."  Now do you need to.
Note that you do NOT need to reinitialize the rest of the timer just to turn interrupts on and off, but that may mean that you will get an interrupt as soon as you re-enable it...



Yes, that's what I was after, thank you. By minimal register writes this is what I had in mind (I was hoping (assuming) that I wouldn't need to re-setup all the registers, or figure out what exactly detachInterrupts() does).  Cheers.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4036
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm just wondering if you'll be using millis() or micros() while interrupts are off?

There are fast read ADC chips you could add and 328P's have a fast read 8 bit ADC mode.
Most code runs at clock MIPs but I/O takes a bit longer.

I have timing code that does a digital read, counter increment, and counter timeout check all in just under 1 usec per while loop with zero interrupts since I'm using micros() for time as well. 

Change that to an analog read and I'm 105 usec per loop.

IIRC whole sections of the MCU shut down during ADC so as to not affect the conversion, or is that a non-default option?

You should be playing with sound chips at those speeds anyway. 8k samples per ain't much to those, even at higher resolution.
Logged

Examples can be found in your IDE.

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 53
Posts: 1802
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The sleep mode for ADC is non-default. I'm currently using the 8-bit mode at a 32x prescaler and it works well.
Logged


Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4036
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I never even tried 8-bit mode. How fast is it?
Logged

Examples can be found in your IDE.

Pages: 1 [2]   Go Up
Jump to: