DUE playing sound and receiving input at the same time?

Hi!
I have this "phone" project. When picking the phone I would like to play some instructions on how to select the language, etc. But I cannot find a way to make it work.
This is my sketch:


int previousMillis = 0; //set first old time to 0
int currentMillis = 0; //define currentMillis
long interval = 5000;

int currentLCDMillis = 0;



#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Key.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 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

int keyCounter = 0;

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

char keypresses[5];

char language;
char key;

int goIntoKeys = 0;

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

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


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

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

void loop() {
  switch (state) {
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
    //kalba();
      if (langKeyPressed ()) {
                buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
        }
      else {
        playSound("intro.wav");
        //play instruction how to select a language until language is selected
      }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      if (isKeyPressed()) {
                   buttonBeep();
        if (isLanguageKey(key)) {
          processLanguage();
        }
        else {
          keypresses[keyCounter] = key;
          keyDial();
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
      break;
    case STATE_PLAYER:
        //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      state = STATE_LISTEN_KEY;
      break;
    default:
      break;
  }
}

void kalba() {
  Serial.println("Kalba? Language? Valoda? Yazik?");
}

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
  //goIntoKeys = 1;
  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 keyDial() {    // LCD displays the number dialed in 3 slots.
  keypresses[keyCounter] = 0x00;//null-byte
  keypresses[keyCounter] = key;

  if (key != NO_KEY)   {
    Serial.println(keypresses[keyCounter]);
  }
}

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 alertBeep(){
      for (int j = 0; j < 100; j++) {
        for (int i = 0; i < 100; i++)
          //analogWrite(DAC0, i);
            Serial.print(i);
             Serial.println(", ");
             Serial.print(j);
            delay(50);
      }  
}

void backgroundHumm() {
          analogWrite(DAC0, 128);
 }
 
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");
    }
  }
  //    else if (tot == code1 || tot == code2 || tot == code3){
  //        coinsValue = 0;
  //  }
}

// 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);
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

So everything works, but DUE is not receiving any input unless intro.wav has finished playing.
Maybe there is a way to play+receive input at the same time? Cheers.

EDIT. Entire sketch is here. Wav file name corrected.
EDIT 2. It works - full sketch below in the last comment.

The problem is in the code you did not post.

Did you mean "intro.wav" as I don't see instructions.wav?
As @jremington points out, post your entire sketch.

IF playSound() does start playing a .wav file and return before it is finished, you still do not want the STATE_IDLE state to start playing it every time through loop(). It would constantly be starting to play... You either need a new state or a flag to indicate you have/or need to play the intro.wav file. Or, if you want to play it in a loop, you need to at least wait until it is finished before starting it again.

Yes, you are probably right - problems are always where we least expect.
Posting full sketch in the first post.

But as I understand I only start playing the infro.wav when it finished.
Anyway - the intro must be playing all the time, until a language is selected.

The Due can be made to multitask. If the intro must be playing all the time and the program must check for a language being selected then it might be in the OP's interest in doing one of the multi-tasking schemes such as using millis() to do multiple things at the same time or, a state machine or loading up the uMT library.

Heck, I'll post a uMT app running on a Due. Just a minute.

OK, I'm back with the multitasking code for a Due using uMT:





#include <uMT.h>
#include <Wire.h>
#include "TFMini.h"
#include <Servo.h>
#include <SimpleDHT.h>


//*************************************************
// scl pin 5, sda pin 4, vcc 3.3
// temperature, pressure, altitude, sealevelpressure
#define BMP085_ADDRESS 0x77  // I2C address of BMP085
#define BMP_Interval 65503
const unsigned char OSS = 0;  // Oversampling Setting
// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
// b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5;
//*********************************************
const String sSeperator = " ";
//*********************************************
Servo ServoLIDAR;
#define ServoLIDARPosit 1450
#define  byteServo_LIDAR_Pin 11
String sA = "";
//*********************************************
//X Axis servo
Servo X_Axis;
#define byteXaxisServoPin 9
#define iX_Posit90 1538 //using writeMicroseconds
int iX_HowMuch = iX_Posit90;
//Y Axis servo
Servo Y_Axis;
#define byteYaxisServoPin 10
#define iY_Posit90 1492 //using writeMicroseconds
int iY_HowMuch = iY_Posit90;
//*************************************************
TFMini tfmini;
// unsigned long lPreviousLIDAR_SequenceMillis = 0;
#define lLIDAR_SequenceInterval 50 // milliseconds
// 25mS is 40Hz
// 33mS ~30Hz
// 50mS 20Hz
// bool bBlankLIDAR = false;
//*************************************************
//
#define byteUnoDataReady 22
//*************************************************
// unsigned long lCurrentMillis = 0;
//*************************************************
//microwave motion detector= iMW
#define MWM_PINin 34
#define MWM_PINout 36
//*************************************************
// #define lLEDRateInterval 125 //milliseconds,  second
// unsigned long lPreviousLED_BlinkMillis = 0;
// bool bLedOnOff = false;
//*************************************************
String sMessageToSend;
String sPi;
//*************************************************
//*************************************************
// bool bRcveDone = false;
//*************************************************
// for DHT11,
//      VCC: 5V or 3V
//      GND: GND
//      DATA: 2
#define pinDHT11 2
SimpleDHT11 dht11(pinDHT11);
#define iDHT_Interval 60503
//*************************************************
#define iDoVolts_Interval 45007
//*************************************************
#define MINservo 1000
#define MAXservo 2000
#define SerialBaudRate 9600
#define Serial2BaudRate 115200
#define StringBufferSize 50
//*************************************************
// bool bTask2Started = false;
//*************************************************
#define EVENT_A  0x0001
TaskId_t iEvtID_A;
//
#define EVENT_B  0x0002
TaskId_t iEvtID_B;
//
#define EVENT_C  0x0003
TaskId_t iEvtID_C;
//
#define EVENT_D  0x0004
TaskId_t iEvtID_D;
//
#define EVENT_E  0x0005
TaskId_t iEvtID_E;
//
#define EVENT_F  0x0006
TaskId_t iEvtID_F;
//*************************************************
#define  SEM_ID_01   1   // Semaphore id
#define  SEM_ID_02   2   // Semaphore id
#define  SEM_ID_03   3   // Semaphore id
#define  SEM_ID_04   4   // Semaphore id
// #define TIMEOUT_A
//*************************************************
Stream* stream2Ptr;
//*************************************************


void setup()
{

  pinMode(40, OUTPUT);
  digitalWrite( 40, LOW );
  ////
  pinMode(byteUnoDataReady, OUTPUT);//setup interrupt pin as output
  digitalWrite(byteUnoDataReady, LOW);//set state initial
  ////
  Serial1.begin(TFMINI_BAUDRATE);
  // Initialize the TFMini LIDAR
  tfmini.begin(&Serial1);
  // Initialize single measurement mode with external trigger
  tfmini.setSingleScanMode();
  ////
  Serial2.begin( Serial2BaudRate );
  stream2Ptr = &Serial2;
  ////
  pinMode(MWM_PINin, INPUT);
  pinMode(MWM_PINout, OUTPUT);
  ////
  pinMode(LED_BUILTIN, OUTPUT);//blink LED at pin 13
  ////
  analogReadResolution( 12 );
  ////
  ServoLIDAR.attach( byteServo_LIDAR_Pin, MINservo, MAXservo );  // attaches the servo pin to the servo object
  ServoLIDAR.writeMicroseconds(ServoLIDARPosit);//sets initial posit
  ////
  X_Axis.attach( byteXaxisServoPin, MINservo, MAXservo );
  X_Axis.writeMicroseconds( iX_Posit90 );
  ////
  Y_Axis.attach( byteYaxisServoPin, MINservo, MAXservo );
  Y_Axis.writeMicroseconds( iY_Posit90 );
  ////
  Serial.begin(SerialBaudRate);
  ////
  // allocate a buffer in memory for these strings
  sMessageToSend.reserve( StringBufferSize );
  sPi.reserve( StringBufferSize );
  ////
  Wire.begin();
  bmp085Calibration();
  ////
  ADC->ADC_MR |= 0x80;  //set free running mode on ADC
  REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000; // adc start up value
  // ADC->ADC_CHER = 0x80; //enable ADC on pin A0
  ////
  Kernel.Kn_Start();

} // setup()



void loop()
{
  // if ( !bTask2Started )
  // {
  Errno_t error;

  TaskId_t fC_P;
  // fCheck_Pressure
  error = Kernel.Tk_CreateTask(fCheck_Pressure, fC_P);
  if ( error != E_SUCCESS )
  {
    fKernalError( "fCheck_Pressure", error );
  }
  ////
  // bTask2Started = !bTask2Started;
  ////
  Kernel.Tk_StartTask(fC_P);
  // fCheck_TH
  TaskId_t fC_TH;
  error = Kernel.Tk_CreateTask(fCheck_TH, fC_TH);
  if ( error != E_SUCCESS )
  {
    fKernalError( "fCheck_TH", error );
  }
  Kernel.Tk_StartTask( fC_TH ) ;
  // fCheckInputVoltage
  TaskId_t fDoVolts;
  error = Kernel.Tk_CreateTask( fCheckInputVoltage, fDoVolts );
  if ( error != E_SUCCESS )
  {
    fKernalError( "fCheckInputVoltage", error );
  }
  Kernel.Tk_StartTask( fDoVolts ) ;
  //  fDoLIDAR
  TaskId_t fLIDAR;
  error = Kernel.Tk_CreateTask( fDoLIDAR, fLIDAR );
  if ( error != E_SUCCESS )
  {
    fKernalError( "fDoLIDAR", error );
  }
  Kernel.Tk_StartTask( fLIDAR ) ;
  //    //
  //    ////////////////////////////
  //    ////////////////////////////
  //    ////////////////////////////
  // fReadSerial
  error = Kernel.Tk_CreateTask( fReadSerial, iEvtID_A );
  Kernel.Tk_StartTask( iEvtID_A );
  // fDO_bRcveDone
  error = Kernel.Tk_CreateTask( fDO_bRcveDone, iEvtID_B );
  Kernel.Tk_StartTask( iEvtID_B );
  // fTweakServoX
  error = Kernel.Tk_CreateTask( fTweakServoX, iEvtID_C );
  Kernel.Tk_StartTask( iEvtID_C );
  // fTweakServoY
  error = Kernel.Tk_CreateTask( fTweakServoY, iEvtID_D );
  Kernel.Tk_StartTask( iEvtID_D );
  // fLIDAR_ServoAspectChange
  error = Kernel.Tk_CreateTask( fLIDAR_ServoAspectChange, iEvtID_E );
  Kernel.Sm_Release( SEM_ID_02 ); // release a single SEMAPHORE token
  Kernel.Sm_Release( SEM_ID_03 );
  Kernel.Tk_StartTask( iEvtID_E );
  // fSendOut_SEMAPHORE
  error = Kernel.Tk_CreateTask( fSendOut_SEMAPHORE, iEvtID_F );
  Kernel.Sm_Release( SEM_ID_01 ); // release a single SEMAPHORE token
  Kernel.Tk_StartTask( iEvtID_F );
  ////////////////////////////////////////
  ////////////////////////////////////////
  ////////////////////////////////////////
  // }
  for ( ;; )
  {
    if ( stream2Ptr->available() >= 1 )
    // if (Serial2.available() >= 1)
    {
      Kernel.Ev_Send(iEvtID_A, EVENT_A);
      Kernel.Sm_Claim(SEM_ID_04, uMT_WAIT); // stop and wait for serial to be received and release of SEMAPHORE token
    }  //  serial available
    Kernel.Tk_Yield();
  }
} // loop
//******************************************
//******************************************
//******************************************
//
void fKernalError(String sTask, unsigned error)
{
  Serial.print( " Tk_CreateTask(): " + sTask + " Failure! - returned " );
  Serial.println( error );
  Serial.flush();
  Kernel.isr_Kn_FatalError();
} // void fKernalError()
//******************************************
//   digitalWriteDirect / digitalReadDirect
//******************************************
// example: digitalWriteDirect(13, HIGH)
inline void digitalWriteDirect(int pin, boolean val)
{
  if (val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}
// example: digitalReadDirect(12)
inline int digitalReadDirect(int pin)
{
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}
//******************************************
//
//******************************************
//
//******************************************
//******************************************
///
//******************************************
void fDoLIDAR()
{
  //
  long iLIDAR_Distance = 0;
  long iLIDAR_Strength = 0;
  String sMsgToSend;
  String s_cm = "cm ";
  sMsgToSend.reserve( 16 );
  while (1)
  {
    Kernel.Tm_WakeupAfter( lLIDAR_SequenceInterval );   // Wake up after ... milliseconds
    Kernel.Sm_Claim(SEM_ID_02, uMT_WAIT); // // stop lidar servo
    Kernel.Sm_Claim(SEM_ID_03, uMT_WAIT); // stop x y servo
    //    if ( !bBlankLIDAR )
    //    {
    if ( digitalReadDirect( MWM_PINin ) )
      // if ( digitalRead( MWM_PINin ) == 1 )
    {
      digitalWriteDirect( MWM_PINout, HIGH );
      tfmini.externalTrigger();
      iLIDAR_Distance = tfmini.getDistance();
      iLIDAR_Strength = tfmini.getRecentSignalStrength();
      if (iLIDAR_Distance < 600)
      {
        // Serial.println( "TF Mini distance " + String(iLIDAR_Distance) + s_cm + " strength " + String(iLIDAR_Strength ) );
        // Serial.flush();
        sMsgToSend.concat( s_cm + String(iLIDAR_Distance) + " " + String(iLIDAR_Strength ) );
        Kernel.Sm_Claim(SEM_ID_01, uMT_WAIT); // // claim a single SEMAPHORE token
        sMessageToSend = sMsgToSend;
        Kernel.Ev_Send(iEvtID_F, EVENT_F);  // trigger fSendOut_SEMAPHORE + consume a single SEMAPHORE token
        sMsgToSend = "";
      }
    }
    else
    {
      digitalWriteDirect( MWM_PINout, LOW );
    }
    Kernel.Sm_Release( SEM_ID_02 ); // release a single SEMAPHORE token
    Kernel.Sm_Release( SEM_ID_03 );
  }
}
//******************************************
//      bmp085 functions
//******************************************
// Calculate pressure given up
// calibration values must be known
// b5 is also required so bmp085GetTemperature(...) must be called first.
// Value returned will be pressure in units of Pa.
long bmp085GetPressure(unsigned long up)
{
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;

  b6 = b5 - 4000;
  // Calculate B3
  x1 = (b2 * (b6 * b6) >> 12) >> 11;
  x2 = (ac2 * b6) >> 11;
  x3 = x1 + x2;
  b3 = (((((long)ac1) * 4 + x3) << OSS) + 2) >> 2;

  // Calculate B4
  x1 = (ac3 * b6) >> 13;
  x2 = (b1 * ((b6 * b6) >> 12)) >> 16;
  x3 = ((x1 + x2) + 2) >> 2;
  b4 = (ac4 * (unsigned long)(x3 + 32768)) >> 15;

  b7 = ((unsigned long)(up - b3) * (50000 >> OSS));
  if (b7 < 0x80000000)
    p = (b7 << 1) / b4;
  else
    p = (b7 / b4) << 1;

  x1 = (p >> 8) * (p >> 8);
  x1 = (x1 * 3038) >> 16;
  x2 = (-7357 * p) >> 16;
  p += (x1 + x2 + 3791) >> 4;

  return p;
}
// Calculate temperature given ut.
// Value returned will be in units of 0.1 deg C
short bmp085GetTemperature(unsigned int ut)
{
  long x1, x2;

  x1 = (((long)ut - (long)ac6) * (long)ac5) >> 15;
  x2 = ((long)mc << 11) / (x1 + md);
  b5 = x1 + x2;

  return ((b5 + 8) >> 4);
}
// Read the uncompensated pressure value
unsigned long bmp085ReadUP()
{
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;

  // Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ oversampling setting
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x4 + (OSS << 6));
  Wire.endTransmission();

  // Wait for conversion, delay time dependent on OSS
  // delay(2 + (3 << OSS));
  Kernel.Tm_WakeupAfter( 2 + (3 << OSS) );
  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF6);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 3);

  // Wait for data to become available
  while (Wire.available() < 3)
    ;
  msb = Wire.read();
  lsb = Wire.read();
  xlsb = Wire.read();
  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8 - OSS);

  return up;
}
// Read the uncompensated temperature value
unsigned int bmp085ReadUT()
{
  unsigned int ut;
  // Write 0x2E into Register 0xF4
  // This requests a temperature reading
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();
  // Wait at least 4.5ms
  Kernel.Tm_WakeupAfter( 5 );
  // delay(5);
  // Read two bytes from registers 0xF6 and 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}
// Stores all of the bmp085's calibration values into global variables
// Calibration values are required to calculate temp and pressure
// This function should be called at the beginning of the program
void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}
// Read 2 bytes from the BMP085
// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
  unsigned char msb, lsb;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 2);
  while (Wire.available() < 2);
  msb = Wire.read();
  lsb = Wire.read();

  return (int) msb << 8 | lsb;
}
// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
  unsigned char data;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 1);
  while (!Wire.available())
    ;

  return Wire.read();
}
void fCheck_Pressure()
{
  Errno_t error;
  // TimerId_t TmId;
  String sMsgToSend;
  sMsgToSend.reserve( StringBufferSize );
  short bmp_temperature;
  long bmp_pressure;
  // float bmp_altitude;
  //Serial.println( "do fCheck_Pressure" );
  //Serial.flush();
  while (1)
  {
    error = Kernel.Tm_WakeupAfter( BMP_Interval );   // Wake up after ... seconds
    if (error != E_SUCCESS)
    {
      Serial.print(F(" WakeupAfter(): Tm_WakeupAfter() Failure! - returned "));
      Serial.print((unsigned)error);
      Serial.flush();
      break;
    }
    if ( digitalReadDirect( MWM_PINin ) == 0 )
    {
      sMsgToSend = "Pa ";
      // Serial.println( "do fCheck_Pressure3" );
      // Serial.flush();
      bmp_temperature = bmp085GetTemperature(bmp085ReadUT());
      bmp_pressure = bmp085GetPressure(bmp085ReadUP());
      // sMsgToSend.concat( String(bmp_temperature) + sSeperator );
      sMsgToSend.concat( String(bmp_pressure) + sSeperator );
      // sMsgToSend.concat( String(bmp_altitude) + sSeperator );
      // Serial.println( sMsgToSend );
      // Serial.flush();
      Kernel.Sm_Claim(SEM_ID_01, uMT_WAIT); // // claim a single SEMAPHORE token
      sMessageToSend = sMsgToSend;
      Kernel.Ev_Send(iEvtID_F, EVENT_F);  // trigger fSendOut_SEMAPHORE + consume a single SEMAPHORE token
      sMsgToSend = "";
    }
  }
  //  // bTask2Started = false;
}
//******************************************
void fCheck_TH()
{
  // TimerId_t TmId1;
  String sMsgToSend;
  byte temperature = 0;
  byte humidity = 0;
  String sTH = "TH ";
  sMsgToSend.reserve( 16 );
  while (1)
  {
    Kernel.Tm_WakeupAfter( iDHT_Interval );   // Wake up after ... seconds
    if ( digitalReadDirect( MWM_PINin ) == 0 )
    {
      dht11.read(&temperature, &humidity, NULL);
      sMsgToSend = sTH;
      sMsgToSend.concat( String(temperature) + sSeperator + String(humidity) );
      // Serial.println( sMsgToSend );
      // Serial.flush();
      Kernel.Sm_Claim(SEM_ID_01, uMT_WAIT); // // claim a single SEMAPHORE token
      sMessageToSend = sMsgToSend;
      Kernel.Ev_Send(iEvtID_F, EVENT_F);  // trigger fSendOut_SEMAPHORE + consume a single SEMAPHORE token
      sMsgToSend = "";
    }
  } // while (1)
}
//******************************************
//
//******************************************
void fDO_bRcveDone()
{
  String sAspectCng = "AspectCng";
  String s_gX = "gX";
  String s_gY = "gY";
  Event_t  eventoutB;
  while (1)
  {
    Kernel.Ev_Receive(EVENT_B, uMT_ANY, &eventoutB);
    digitalWriteDirect( 40, HIGH );
    sPi.replace( "/", " " );
    // sPi.trim();
    // Serial.println(sPi + " bRcveDone" );
    // Serial.flush();
    ////
    if (sPi.substring(0, 9) == sAspectCng)
    {
      // Serial.println(sPi + " rcvd" );
      sA = sPi.substring(9);
      Kernel.Ev_Send(iEvtID_E, EVENT_E);
      // Serial.println("AspectString " + sA );
      // Serial.flush();
    }
    ////
    // Serial.println( sPi.substring(0, 2) );
    if ( sPi.substring(0, 2) == s_gX )
    {
      // Serial.println(sPi);
      // Serial.flush();
      // stop lidar if lidar has token do not wait for freed token skip torque attempt
      if ( Kernel.Sm_Claim(SEM_ID_03, uMT_NOWAIT) != E_WOULD_BLOCK )
      {
        iX_HowMuch = sPi.substring(3).toInt();
        Kernel.Ev_Send(iEvtID_C, EVENT_C);
      }
    }
    ////
    if ( sPi.substring(0, 2) == s_gY )
    {
      // Serial.println(sPi);
      // Serial.flush();
      if ( Kernel.Sm_Claim(SEM_ID_03, uMT_NOWAIT) != E_WOULD_BLOCK )
      {
        iY_HowMuch = sPi.substring(3).toInt();
        Kernel.Ev_Send(iEvtID_D, EVENT_D);
      }
    }
    sPi = "";
    digitalWriteDirect( 40, LOW );
  }
}
//******************************************
//
//******************************************
void fReadSerial()
{
  //
  Event_t  eventoutA;
  char OneChar;
  while (1)
  {
    // Event_t  eventoutA;
    Kernel.Ev_Receive(EVENT_A, uMT_ANY, &eventoutA);
    ////
    while ( stream2Ptr->available() )
    {
      OneChar = stream2Ptr->read();
      if ( (OneChar != '\n') )
      {
        //Serial.println(sPi);
        sPi.concat( OneChar );
        // Serial.println(sPi + " char" );
        // Serial.flush();
        digitalWrite( 40, LOW );
      } // if ( (OneChar != '\n') )
      else
      {
        Kernel.Ev_Send(iEvtID_B, EVENT_B);  // trigger fDO_bRcveDone
        // bRcveDone = true;
        // Serial.println( "bRcveDone set true" );
        Serial.flush();
        break;
      } // if ( (chrOne != '\n') ) else
    } // while ( Serial2.available() )
    Kernel.Sm_Release( SEM_ID_04); // release serial avaible trigger in loop
  } //  while (1)
}
//******************************************
//
/*
  1000 u sec to 2000 u sec limit = 90 degrees of travel +/-45 deg
  1K = 45 to 2K = 135

*/
//******************************************
void fTweakServoX()
{
  Event_t  eventoutC;
  while (1)
  {
    Kernel.Ev_Receive(EVENT_C, uMT_ANY, &eventoutC);
    X_Axis.writeMicroseconds( iX_HowMuch );
    Kernel.Sm_Release( SEM_ID_03 );
  }
}
void fTweakServoY()
{
  Event_t  eventoutD;
  while (1)
  {
    Kernel.Ev_Receive(EVENT_D, uMT_ANY, &eventoutD);
    // Serial.println( "iY_HowMuch = " + String(iY_HowMuch) );
    Y_Axis.writeMicroseconds( iY_HowMuch );
    Kernel.Sm_Release( SEM_ID_03 );
  }
}
//******************************************
//  send data to RPi
//******************************************
void fSendOut_SEMAPHORE()
{
  Event_t  eventoutF;
  while (1)
  {
    Kernel.Ev_Receive(EVENT_F, uMT_ANY, &eventoutF);
    // Serial.println("fSendOut_SEMAPHORE 0 " + sMessageToSend );
    // Serial1.flush();
    if ( sMessageToSend.length() >= 2 )
    {
      // Serial.println("fSendOut_SEMAPHORE 1 " + sMessageToSend );
      // Serial.flush();
      stream2Ptr->println( sMessageToSend );
      digitalWrite(byteUnoDataReady, HIGH);//TRIGGER RPi3 to read data
      // delay( .05 );
      Kernel.Tm_WakeupAfter( 50 );
      // Serial.println( sMessageToSend.length() );
      // Serial.println("fSendOut_SEMAPHORE " + sMessageToSend );
      // Serial.flush();
      digitalWrite(byteUnoDataReady, LOW);//reset
      sMessageToSend = "";
      Kernel.Sm_Release( SEM_ID_01 ); // release a single SEMAPHORE token
    }
  }
}
//****************************************************
//
//****************************************************
void fLIDAR_ServoAspectChange()
{

  char fltBuff[32];
  String sAspectComplete = "AspectComplete";
  Event_t  eventoutE;
  String sMsgToSend;
  sMsgToSend.reserve( 16 );
  //
  while (1)
  {
    Kernel.Ev_Receive(EVENT_E, uMT_ANY, &eventoutE);
    Kernel.Sm_Claim(SEM_ID_02, uMT_WAIT); // // claim a single SEMAPHORE token.
    if ( sA.length() < 8 )
    {
      // bBlankLIDAR = true;
      sA.toCharArray(fltBuff, sizeof(fltBuff));
      float fltAspect = atof(fltBuff);
      //
      if (fltAspect > 900.00f)
      {
        // Serial.println("AspectString " + String(sA));
        // Serial.flush();
        ServoLIDAR.writeMicroseconds(fltAspect);
      }
      //delay(20);
      // Serial.println( "AspectComplete " + sA );
      // Serial.flush();
    }
    else
    {
      Serial.println("AspectString reject " + String(sA));
    }
    // Serial.println( "fLIDAR_ServoAspectChange " + sMessageToSend );
    // Serial.flush();
    Kernel.Sm_Release( SEM_ID_02 ); // release a single SEMAPHORE token
    Kernel.Sm_Claim(SEM_ID_01, uMT_WAIT); // // claim a single SEMAPHORE token
    sMsgToSend = sAspectComplete;
    sMessageToSend = sMsgToSend;
    Kernel.Ev_Send(iEvtID_F, EVENT_F);  // trigger fSendOut_SEMAPHORE + consume a single SEMAPHORE token
    // bBlankLIDAR = false;
    //
  }
}
//******************************************
//
//******************************************
void fCheckInputVoltage()
{
  String sMsgToSend;
  String s_Volts = "VOLT ";
  sMsgToSend.reserve( 16 );
  while (1)
  {
    Kernel.Tm_WakeupAfter( iDoVolts_Interval );   // Wake up after ... seconds
    // Serial.println( "dovolt awake1" );
    // Serial.flush();
    if ( digitalReadDirect( MWM_PINin ) == 0 )
    {
      sMsgToSend = s_Volts;
      sMsgToSend.concat(String(analogRead(A0)));
      // Serial.println( "fCheckInputVoltage" + sMsgToSend );
      // Serial.flush();
      Kernel.Sm_Claim(SEM_ID_01, uMT_WAIT); // // claim a single SEMAPHORE token
      sMessageToSend = sMsgToSend;
      Kernel.Ev_Send(iEvtID_F, EVENT_F);  // trigger fSendOut_SEMAPHORE + consume a single SEMAPHORE token
      sMsgToSend = "";
      // Kernel.Sm_Release(SEM_ID_02);
    }
  }
}
//******************************************
//
//*************************************************

uMT is a great introduction into using an RTOS.

Thanks. I am trying to understand uMT, not that easy it seems :confused:
What do you think about this way:

Not sure if this could be applied to my project thought.

Doing several things at the same time could work well for your project. In your case, I'd consider using an interrupt detect a button press whiles the loop() plays the intro tune.

I'm not breaking up the code will work in this case since you are opening a file on the SD, reading it and sending it out. I am not familiar with the Due, but I would be worried about how much time you really have between writes until it is noticable.

OK. I've found many topics about interrupt pins that let exit the loop/state. Not many with the actual solutions though.
So far I have managed to come with this. Sadly, the program instantly gets interrupted and switches the state.


int previousMillis = 0; //set first old time to 0
int currentMillis = 0; //define currentMillis
long interval = 5000;

int currentLCDMillis = 0;



#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Key.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 interruptPin = 0;  // 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

int keyCounter = 0;

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

char keypresses[5];

char language;
char key;

int goIntoKeys = 0;
bool interruptState = 0;

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

  pinMode(pin_rows[ROW_NUM], INPUT_PULLUP);
  pinMode(pin_column[COLUMN_NUM], INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pin_rows[ROW_NUM]), interruptToggle, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pin_column[COLUMN_NUM]), interruptToggle, CHANGE);


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


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

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

void loop() {
  switch (state) {
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
    //kalba();
               if (interruptState == 0) {
              playSound("intro.wav");
               }
            else {
                buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
        }
//      if (langKeyPressed ()) {
//                buttonBeep();
//        processLanguage();
//        state = STATE_LISTEN_KEY;
//        }
//      else {
//        //play instruction how to select a language until language is selected
//      }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      if (isKeyPressed()) {
                   buttonBeep();
        if (isLanguageKey(key)) {
          processLanguage();
        }
        else {
          keypresses[keyCounter] = key;
          keyDial();
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
      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 interruptToggle() {
  interruptState = 1;
}

void kalba() {
  Serial.println("Kalba? Language? Valoda? Yazik?");
}

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
  //goIntoKeys = 1;
  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 keyDial() {    // LCD displays the number dialed in 3 slots.
  keypresses[keyCounter] = 0x00;//null-byte
  keypresses[keyCounter] = key;

  if (key != NO_KEY)   {
    Serial.println(keypresses[keyCounter]);
  }
}

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 alertBeep(){
      for (int j = 0; j < 100; j++) {
        for (int i = 0; i < 100; i++)
          //analogWrite(DAC0, i);
            Serial.print(i);
             Serial.println(", ");
             Serial.print(j);
            delay(50);
      }  
}

void backgroundHumm() {
          analogWrite(DAC0, 128);
 }
 
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");
    }
  }
  //    else if (tot == code1 || tot == code2 || tot == code3){
  //        coinsValue = 0;
  //  }
}

// 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);
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1

}

This does not cause you problems with the DUE pin 0 being RX0?

This does not make sense. pin_rows[ROW_NUM] and pin_column[COLUMN_NUM] are both an access outside your array

No, it was only for testing - I am not even using it.

@blh64 - I see. But how can I access an array from attachInterrupt? Is it even possible?

This is what I've found on other topics similar to mine. So I guess it's wrong:

void setup () {
attachInterrupt(digitalPinToInterrupt(sensorValues[0], retreat, FALLING);
}

attachInterrupt() takes a single pin, not an entire array. You can certainly use any one of the pins in the array, such as attachInterrupt(digitalPinToInterrupt(pin_rows[0]), interruptToggle, CHANGE); but ROW_NUM is 4 and there is no pin_rows[4], just 0...3

You can use a for loop to go through an array of pins attaching the pins as the loop progresses.

What does that mean?

Move the ISR before setup()

Here the OP wants to toggle the ISR with every state change. So when the ISR goes High, the ISR is triggered and when the ISR goes low the ISR is triggered which produces a 'true' for every state change of the ISR. Is that what the OP wants? Remember OP your complaint is:

Thanks a lot! Changed CHANGE to RISING. It seems that interrupt the intro.wav kinda works. But with a delay of ~5+ sec. Not good enough. I wonder what can cause that.
EDIT: It does the same as the sketch before - waits when .wav is finished and then goes to the next state. Probably my spaghetti code somewhere...


int previousMillis = 0; //set first old time to 0
int currentMillis = 0; //define currentMillis
long interval = 5000;

int currentLCDMillis = 0;



#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Key.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 interruptPin = 0;  // 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

int keyCounter = 0;

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

char keypresses[5];

char language;
char key;

int goIntoKeys = 0;
bool interruptState = 0;

void interruptToggle() {
  interruptState = 1;
}

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

  pinMode(pin_rows[ROW_NUM], INPUT_PULLUP);
  pinMode(pin_column[COLUMN_NUM], INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pin_rows[0]), interruptToggle, RISING);
  attachInterrupt(digitalPinToInterrupt(pin_rows[1]), interruptToggle, RISING);
  attachInterrupt(digitalPinToInterrupt(pin_rows[2]), interruptToggle, RISING);
  attachInterrupt(digitalPinToInterrupt(pin_rows[3]), interruptToggle, RISING);
  attachInterrupt(digitalPinToInterrupt(pin_column[0]), interruptToggle, RISING);
  attachInterrupt(digitalPinToInterrupt(pin_column[1]), interruptToggle, RISING);
  attachInterrupt(digitalPinToInterrupt(pin_column[2]), interruptToggle, RISING);
  attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, RISING);


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


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

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

void loop() {
  switch (state) {
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
    //kalba();
               if (interruptState == 0) {
              playSound("intro.wav");
               }
            else {
                buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
        }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      if (isKeyPressed()) {
                   buttonBeep();
        if (isLanguageKey(key)) {
          processLanguage();
        }
        else {
          keypresses[keyCounter] = key;
          keyDial();
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
      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 kalba() {
  Serial.println("Kalba? Language? Valoda? Yazik?");
}

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
  //goIntoKeys = 1;
  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 keyDial() {    // LCD displays the number dialed in 3 slots.
  keypresses[keyCounter] = 0x00;//null-byte
  keypresses[keyCounter] = key;

  if (key != NO_KEY)   {
    Serial.println(keypresses[keyCounter]);
  }
}

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 alertBeep(){
      for (int j = 0; j < 100; j++) {
        for (int i = 0; i < 100; i++)
          //analogWrite(DAC0, i);
            Serial.print(i);
             Serial.println(", ");
             Serial.print(j);
            delay(50);
      }  
}

void backgroundHumm() {
          analogWrite(DAC0, 128);
 }
 
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);
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1

}

If you are going to initialize the serial port might as well use it. You can use serial prints to get to the area of the delay like:

The serial prints should happen rather quickly. By using them you can find the spot of the 5 second delay and then go from there.

So it does not really have 5sec delay - it just waits for .wav to finish (volume was too low and I thought it does work :confused: )
I think I misuse interrupt somehow. It just seems too simple that this if-else control would work.

 if (interruptState == 0) {
              playSound("intro.wav");
               }
            else {
                buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
        }

[/quote]

One might consider changing the interruptState variable back to 1? after the interrupt has been processed.

And you might want to use a bool over an int for interruptState.

Hmm, I might misunderstand.
So right now at first I have:

bool interruptState = 0;

I am playing intro.wav. Until interruptState is changed to 1 by the interrupt pin(s):

void interruptToggle() {
  interruptState = 1;
}

Then we go to phone number dial. And from there - to a player where selected .wav will be playing. After playing I set the state again to 0.

case STATE_PLAYER:
        //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      interruptState = 0; //<--set to zero
      state = STATE_LISTEN_KEY;
      break;

But of course, it does not work, since my interruptPins won't interrupt the loop with playSound("intro.wav");
I've just tried one, regular button - not reusing keypad pins. Same result.

I'm confused in post 17 the OP indicates that 'it' does work, in post 19 it does not work. Which it is it in post 17 and which it is it in post 19?