Is it possible to detach interrupt in the function called with interrupt.

Is it possible to detach interrupt in the function called with interrupt.
Will this code work on standalone atmega 382p chip
Example:

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
  detachInterrupt(digitalPinToInterrupt(interruptPin));
}

Yes, it would not be unusual.

However if you just want to halt that interrupt for a period of time and reinstate it later it would be sufficient to change the Interrupt Mask register. For example on an Uno this will disable INT0

EIMSK &= 0b00000010;

and you can enable it with

EIMSK |= 0b00000001;

It would be a good idea to clear the interrupt flag immediately before re-enabling an interrupt in case there was some old baggage that will immediately trigger the interrupt. Writing a 1 clears the flag

EIFR = 0b00000001;

...R

Robin2 thanks for your help, my plan was to detach interrupt after using it to wake up arduino from deep sleep and later attach interupt before putting arduino back to sleep (low power). While interrupt is detached i would use the same interrupt button for other functions.
Would using just attachInterrupt() and detachInterrupt() be good practice and should i clear interrupt flag while using this functions.

Nevermore555:
should i clear interrupt flag while using this functions.

Yes you should still clear the flag. That keeps it from just firing off right when you first attach it.

Nevermore555:
Would using just attachInterrupt() and detachInterrupt() be good practice and should i clear interrupt flag while using this functions.

You do need to use detach and attach if you want to associate the same interrupt pin with a different ISR.

@DeltaG has covered the flag question

...R

Nevermore555:
Will this code work on standalone atmega 382p chip

No. Not without declaring 'ledPin', interruptPin, and 'state'.

Nevermore555:
Robin2 thanks for your help, my plan was to detach interrupt after using it to wake up arduino from deep sleep and later attach interupt before putting arduino back to sleep (low power). While interrupt is detached i would use the same interrupt button for other functions.
Would using just attachInterrupt() and detachInterrupt() be good practice and should i clear interrupt flag while using this functions.

That sounds like you want the button to do different things based on the current state of the system. You should not detach and attach different functions. That operation is considered "expensive" on the Arduino. Just use one function and a global state variable so it knows what to do.

MorganS:
That sounds like you want the button to do different things based on the current state of the system. You should not detach and attach different functions.

  1. First sentence is true i would like to use same button for different functions, i am working on a clock so first time when button is pressed i want to use interrupt and wake up atmega chip, later i would use the same button for changing time BUT i do not want to use interrupt while atmega is awake so my plan was to detach interrupt when it wake up and before putting it back to sleep attach it again.
  2. About second sentence i would use always the same function when attaching interrupt, would this also be problematic?

Delta_G:
Yes you should still clear the flag. That keeps it from just firing off right when you first attach it.

So before i use detachInterrupt() i should always clear interrupt flag and i can do that with this line of code:

Robin2:
EIFR = 0b00000001;

Nevermore555:

  1. First sentence is true i would like to use same button for different functions, i am working on a clock so first time when button is
    So before i use detachInterrupt() i should always clear interrupt flag and i can do that with this line of code:

Not quite.

You should do it immediately before attachInterrupt()

  1. About second sentence i would use always the same function when attaching interrupt, would this also be problematic?

@MorganS was suggestion that you don't use detach and attach and instead leave the ISR attached all the time and have a variable that is changed elsewhere in the code and which is used by the ISR to determine what it does - something like

void myISR() {
   if (myValue == 'a') {
      // code for one action
   }
   else if (myValue == 'b') {
      // code for another action
   }
   else {
      // do nothing
   }
 }

This approach would have value if the interrupt needed to change its behaviour frequently and if the time taken for the combined detach and attach was a significant part of the iteration time.

...R

Robin2:
@MorganS was suggestion that you don't use detach and attach and instead leave the ISR attached all the time and have a variable that is changed elsewhere in the code and which is used by the ISR to determine what it does.

Thanks for fast reply, so in my case it would look like this:

void myISR() {
   if (mode == 'sleeping') {
      mode = 'awake';
   }
   //else if mode == 'awake' do nothing
 }

But what is bugging me about this is that every time i would push that button while in 'awake' mode i would always trigger interrupt and myISR() function but if that is more optimized than detaching and attaching IRS i am happy, or maybe it will not trigger interrupt and myISR() since i would not reset the interrupt flag until moment before putting it back to sleep?

void myISR() {
   if (mode == 'sleeping') {
      mode = 'awake';
   }
   //else if mode == 'awake' do nothing
 }

Single quotes denote a single char
What type of variable is mode ?

UKHeliBob:
Single quotes denote a single char
What type of variable is mode ?

You are right it is a mistake, i edited Robin2s code just to make the point and ignored single quotes. In my original sketch i use integer for mode variable (0 for sleep, 1 for awake), but in this context i don't think that is relevant i am more interested in functionality behind interrupts and how they work.

OK i think that this might be the best solution so for example code like this:

#include <LowPower.h>

int8_t mode = 0;

void setup(){
  attachInterrupt(digitalPinToInterrupt(2), turnOn, FALLING); // attach interrupt
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //zzzz
}

void turnOn(){
  if(mode == 0){
    mode = 1;
    detachInterrupt(digitalPinToInterrupt(2)); // disable interrupt
  }
}

void loop(){
  if(mode == 1){
    //do stuff
    // if aweken for more than some time change mode to 2
  } else if(mode == 2){
    EIFR = 0b00000001; // clear the flag
    attachInterrupt(digitalPinToInterrupt(2), turnOn, FALLING); // attach interrupt
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //zzzz
  }
}

Would do the same thing like this code here:

#include <LowPower.h>

int8_t mode = 0;

void setup(){
  attachInterrupt(digitalPinToInterrupt(2), turnOn, FALLING); // attach interrupt
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //zzzz
}

void turnOn(){
  if(mode == 0){
    mode = 1;
    EIMSK &= 0b00000010; // disable interrupt
  }
}

void loop(){
  if(mode == 1){
    //do stuff
    // if aweken for more than some time change mode to 2
  } else if(mode == 2){
    EIFR = 0b00000001; // clear the flag
    EIMSK |= 0b00000001; // enable interrupt
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //zzzz
  }
}

But this last one is more optimized and faster, what do you guys think?

I'm late to this discussion, but would like to vote for detaching the interrupt in the ISR, and clearing the interrupt flag immediately thereafter - while still in the ISR. A push button can bounce a good bit, and you could have the flag set again immediately as you leave the ISR unless you clear it after you detach the interrupt. Then you don't have to clear the flag again when you attach the interrupt while in active mode, but you do need to be sure the button is not being pressed when you are trying to go to sleep.

I just finished a Nano remote control with a numeric keypad, and it uses pin change interrupts on the column pins to wake up the processor out of deep sleep, but then those pins function normally when decoding the keypress in awake mode. I actually left the interrupt enabled, but used the pin mask register to enable and disable any firing or flag setting on those pins. I think I did it that way to make sure I didn't interfere with the keypad library in case it was using pin change interrupts on other pins. So the overall PCI for the port is enabled in Setup and left that way, but the mask bits are fiddled with in the Loop. Anyway, the ISR just looks like this:

ISR (PCINT2_vect) {                 // pin change interrupt service routine
  PCMSK2 = PCMSK2 & (~PCImask);     // clear mask bits = disable further interrupts
  PCIFR = PCIFR | PCIenable;        // clear any pending interrupt flag bits
}

This works quite well. Even though the button is still being held down, and possibly bouncing, during the ISR, if you disable the interrupt, then clear the flag, there can be no interrupts after that until you enable the interrupt again.

Nevermore555:
So before i use detachInterrupt() i should always clear interrupt flag and i can do that with this line of code:

No, clear it just before you attach the interrupt.