DUE clear interrupt flags

Hi,
how to clear interrupt flags on DUE?
I've tried a couple of things, but nothing seems to work. I get some random interrupts when starting the program...as probably all of us when using digitalPinToInterrupt :slight_smile:
I've tried:

noInterrupts();
interrupts();

And
EIFR = (1 << INTF0);
Or maybe I can somehow have a workaround?
My project, a "phone" is working like that:

  1. User picks up the receiver - hookOffState = 1;
  2. Intro.wav is playing telling user to choose between 4 languages.
  3. User picks a language and dials a number.
    IF user puts a receiver back and picks it up again - the interrupts when choosing a language seise to work...weird.

The code:

#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Keypad.h>

const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;

int code1 = 12345;  //The code I used, you can change it
int code2 = 45678;  //The code I used, you can change it
int code3 = 78900;  //The code I used, you can change it

int tot, i1, i2, i3, i4, i5;
char c1, c2, c3, c4;

char hexaKeys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte hookPinA = 23;  // your interrupt pin
byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

char keypresses[5];
char language;
char key;

volatile uint8_t interruptState = 0;
volatile byte hookOffState = 0;
int keyCounter = 0;

void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);
  SD.begin(10);
  analogWriteResolution(12);

  for ( int i = 0; i < ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
  for ( int i = 0; i < COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

  for ( int i = 0; i < ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW);
  pinMode(hookPinA, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
  //   noInterrupts();
  //  interrupts();
}


int state = 0;
const int STATE_OFF = 0;
const int STATE_IDLE = 1;
const int STATE_LISTEN_KEY = 2;
const int STATE_PLAYER = 3;

bool isLanguageKey(char customKey) {
  return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
}

void loop() {
  switch (state) {
    case STATE_OFF:
      //listen for a telephone receiver to be removed
      if (hookOffState == 1) {
        attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);
        interruptState = 0;
        state = STATE_IDLE;
      }
      break;
    case STATE_IDLE:
      //listen for a language key. Cannot dial a number before
      if (interruptState == 1) {
        isKeyPressed(); //get the key input
        buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
      }
      else if (hookOffState == 0) {
        detachInterrupt(digitalPinToInterrupt(pin_column[3]));
        state = STATE_OFF;
      }
      else {
        playSound("intro.wav");
      }
      break;
    case STATE_LISTEN_KEY:
      //listen for any key
      if (isKeyPressed()) {
        Serial.println(key);
        interruptState = 0;
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
        }
        else  {
          buttonBeep();
          keypresses[keyCounter] = key;
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
      else if (hookOffState == 0) {
        state = STATE_OFF;
      }
      break;
    case STATE_PLAYER:
      //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      interruptState = 0;
      state = STATE_LISTEN_KEY;
      break;
    default:
      break;
  }
}

void hookOffToggle() {     //detect a telephone receiver to be removed
  hookOffState = digitalRead(hookPinA);
}

void interruptToggle() {
  interruptState = 1;
}

bool isKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY;
}

bool langKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY && isLanguageKey(key);
}

void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
  keyCounter = 0;
  if (key == 'A') {
    Serial.println("   LT    ");
  }
  if (key == 'B') {
    Serial.println("   EN    ");
  }
  if (key == 'C') {
    Serial.println("   LV    ");
  }
  if (key == 'D') {
    Serial.println("   RU    ");
  }
  language = key;
}


void buttonBeep() {
  for (int j = 0; j < 200; j++) {
    for (int i = 0; i < 200; i++)
      analogWrite(DAC0, i);
    for (int i = 200; i >= 0; i--)
      analogWrite(DAC0, i);
  }
}

void backgroundHumm() {
  for (int j = 0; j < 256; j++) {
    for (int i = 0; i < 256; i++)
      analogWrite(DAC0, j);
    for (int j = 256; j >= 0; j--) {
      for (int i = 256; i >= 0; i--)
        analogWrite(DAC0, j);
    }
  }
}

void calculateAndPlay() {
  //if we have 4+1 numbers - proceed
  //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
  i1 = (keypresses[0] - 48) * 10000;
  i2 = (keypresses[1] - 48) * 1000;
  i3 = (keypresses[2] - 48) * 100;
  i4 = (keypresses[3] - 48) * 10;
  i5 = (keypresses[4] - 48) * 1;

  tot = i1 + i2 + i3 + i4 + i5;
  if (language == 'A') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLT.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLT.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLT.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLT.wav");
    }
  }
  if (language == 'B') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiEN.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisEN.wav");
    }
    else if (tot == code3)
    {
      playSound("draugEN.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasEN.wav");
    }
  }
  if (language == 'C') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLV.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLV.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLV.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLV.wav");
    }
  }
  if (language == 'D') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiRU.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisRU.wav");
    }
    else if (tot == code3)
    {
      playSound("draugRU.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasRU.wav");
    }
  }
}

// Playing assigned filename
void playSound(const char* cName) {
  File myFile = SD.open(cName);
  const int S = 1024; // Number of samples to read in block
  short buffer[S];
  // until the file is not finished
  Serial.println("playing ");
  Serial.println(cName);


  Audio.begin(44100, 200);
  delay(200);
  while (myFile.available()) {
    myFile.read(buffer, sizeof(buffer));
    // Prepare samples
    int volume = 512;
    //max volume 1024
    Audio.prepare(buffer, S, volume);
    Audio.write(buffer, S);
    if ( interruptState ) break;
    else if ( hookOffState == 0 ) break;
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

I have not used a Due in quite a few years, but the interrupt handling is quite a lot more complex than on an AVR. As with most ARM chips, there are many interrupt sources, and a quite complex multi-level prioritized interrupt scheme. Simply turning ALL interrupts off for any length of time is generally a really bad idea. The proper way to deal with it is with a dedicated function that disables all interrupts, reads and saves the status register, modify the copy to mask ONLY the specific interrupt you want to block, then update the status register, then re-enable interrupts. When you want to re-enable it, do the above in reverse. Doing all this in a way that CANNOT interfere with other active interrupts is tricky. I figured it out years ago, but can no longer find the function I wrote to do the actual work. It does have to be done in assembler to get it right, so the exact code is often dependant on the specific version of the chip in use.

Let me guess: the contact bounces? Using interrupts for buttons is calling for trouble.

Instead of noInterrupts() you can use detachInterrupt() for external interrupts.

Thanks! But how to disable those interrupts for the time being?
I've tried this:

void loop() {
  switch (state) {
    case STATE_OFF:
      //listen for a telephone receiver to be removed
      if (hookOffState == 1) {
        attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);
        interruptState = 0;
        state = STATE_IDLE;
      }
      break;
    case STATE_IDLE:
      //listen for a language key. Cannot dial a number before
      if (interruptState == 1) {
        isKeyPressed(); //get the key input
        buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
      }
      else if (hookOffState == 0) {
        detachInterrupt(digitalPinToInterrupt(pin_column[3]));
        state = STATE_OFF;
      }
      else {
        playSound("intro.wav");
      }
      break;
    case STATE_LISTEN_KEY:
      //listen for any key
      if (isKeyPressed()) {
        Serial.println(key);
        interruptState = 0;
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
        }
        else  {
          buttonBeep();
          keypresses[keyCounter] = key;
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
      else if (hookOffState == 0) {
        state = STATE_OFF;
      }
      break;
    case STATE_PLAYER:
      //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      interruptState = 0;
      state = STATE_LISTEN_KEY;
      break;
    default:
      break;
  }
}

Weirder part - the first time the interrupt in here works fine:

    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
               if (interruptState == 1) {
         isKeyPressed(); //get the key input
...

But after running a program again (putting receiver hook on/off) it deteriorates - I must press longer and more times to get the same result (interrupt playing intro.wav).

Your code suffers from bad indentation, too many unknown functions, and interrupts on presumably bouncing switches.

Yes, indentation is not the best :confused: edited.
But functions are all known (or arent' they?) - I've included the full sketch in OP.
How else would you interrupt a .wav file playing without attachInterrupt(digitalPinToInterrupt..?

In your playSound() function where you are reading the SD file and writing it out to Audio, you could be reading the buttons...

Thanks! It worked :slight_smile: Indeed having interrupts as buttons was not the best idea...

#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Keypad.h>

const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;

int code1 = 12345;  //The code I used, you can change it
int code2 = 45678;  //The code I used, you can change it
int code3 = 78900;  //The code I used, you can change it

int tot, i1, i2, i3, i4, i5;
char c1, c2, c3, c4;

char hexaKeys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte hookPinA = 23;  // your interrupt pin
byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

char keypresses[5];
char language;
char key;

volatile uint8_t interruptState = 0;
volatile byte hookOffState = 0;
int keyCounter = 0;

void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);
  SD.begin(10);
  analogWriteResolution(12);

  pinMode(hookPinA, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);

  //  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}


int state = 0;
const int STATE_OFF = 0;
const int STATE_IDLE = 1;
const int STATE_LISTEN_KEY = 2;
const int STATE_PLAYER = 3;

bool isLanguageKey(char customKey) {
  return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
}

void loop() {
  switch (state) {
    case STATE_OFF:
      //listen for a telephone receiver to be removed
      if (hookOffState == 1) {
        //        interruptState = 0;
        state = STATE_IDLE;
      }
      break;
    case STATE_IDLE:
      Serial.println("STATE_IDLE");
      //listen for a language key. Cannot dial a number before
      if (isLanguageKey(key)) {
        buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
      }
      else if (hookOffState == 0) {
        state = STATE_OFF;
      }
      else {
        playSound("intro.wav");
      }
      break;
    case STATE_LISTEN_KEY:
      Serial.println("STATE_LISTEN_KEY");
      //listen for any key
      if (isKeyPressed()) {
        Serial.println(key);
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
        }
        else  {
          buttonBeep();
          keypresses[keyCounter] = key;
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
      else if (hookOffState == 0) {
        state = STATE_OFF;
      }
      break;
    case STATE_PLAYER:
      Serial.println("STATE_PLAYER");
      //Play the audio and go back to state LISTEN or Language key is pressed -> going to listen key
      calculateAndPlay();
      keyCounter = 0;
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
          state = STATE_LISTEN_KEY;
        }
      else {
        state = STATE_LISTEN_KEY;
        Serial.println("calculateAndPlay END");
      }
      break;
    default:
      break;
  }
}

void hookOffToggle() {     //detect a telephone receiver to be removed
  hookOffState = digitalRead(hookPinA);
}

void interruptToggle() {
  interruptState = 1;
}

bool isKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY;
}

bool langKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY && isLanguageKey(key);
}

void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
  keyCounter = 0;
  if (key == 'A') {
    Serial.println("   LT    ");
  }
  if (key == 'B') {
    Serial.println("   EN    ");
  }
  if (key == 'C') {
    Serial.println("   LV    ");
  }
  if (key == 'D') {
    Serial.println("   RU    ");
  }
  language = key;
}


void buttonBeep() {
  for (int j = 0; j < 200; j++) {
    for (int i = 0; i < 200; i++)
      analogWrite(DAC0, i);
    for (int i = 200; i >= 0; i--)
      analogWrite(DAC0, i);
  }
}

void backgroundHumm() {
  for (int j = 0; j < 256; j++) {
    for (int i = 0; i < 256; i++)
      analogWrite(DAC0, j);
    for (int j = 256; j >= 0; j--) {
      for (int i = 256; i >= 0; i--)
        analogWrite(DAC0, j);
    }
  }
}

void calculateAndPlay() {
  //if we have 4+1 numbers - proceed
  //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
  i1 = (keypresses[0] - 48) * 10000;
  i2 = (keypresses[1] - 48) * 1000;
  i3 = (keypresses[2] - 48) * 100;
  i4 = (keypresses[3] - 48) * 10;
  i5 = (keypresses[4] - 48) * 1;

  tot = i1 + i2 + i3 + i4 + i5;
  if (language == 'A') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLT.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLT.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLT.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLT.wav");
    }
  }
  if (language == 'B') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiEN.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisEN.wav");
    }
    else if (tot == code3)
    {
      playSound("draugEN.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasEN.wav");
    }
  }
  if (language == 'C') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLV.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLV.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLV.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLV.wav");
    }
  }
  if (language == 'D') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiRU.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisRU.wav");
    }
    else if (tot == code3)
    {
      playSound("draugRU.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasRU.wav");
    }
  }
}

// Playing assigned filename
void playSound(const char* cName) {
  File myFile = SD.open(cName);
  const int S = 1024; // Number of samples to read in block
  short buffer[S];
  // until the file is not finished
  Serial.println("playing ");
  Serial.println(cName);


  Audio.begin(44100, 200);
  delay(200);
  while (myFile.available()) {
    myFile.read(buffer, sizeof(buffer));
    // Prepare samples
    int volume = 512;
    //max volume 1024
    Audio.prepare(buffer, S, volume);
    Audio.write(buffer, S);
    if (isKeyPressed()) {
      if (isLanguageKey(key)) {
        break;
      }
    }
    else if ( hookOffState == 0 ) {
      break;
    }
  }
  Audio.end();
  myFile.close();
  delay(50);
  //  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.