everything stops after starting a timer

Hello,
I am writing here in search of fresh help because anything i tried last days it won't work and i doubt of anything. I hope a fresh mind will find my mistakes.
Thanks in advance.

An arduino uno (16MHz), a speaker, and a spi port to connect SD card.

I want to read a SD card to make pwm sound. Files are pcm, raw at this point. I tested some libraries with some advantages but i want make my own program and then change pwm frequence to hear myself if there is a difference of noise.

There is both buttons and serial usb to give order, because i test sometimes with serial and sometimes without it depending of where i am.
My program blocks just after starting the sampling timer. I added Serial displays to see loop and interrupt activity and nothing works after the timer 2 starts.

/***
Reads raw sound file on SD to make sound on digital pin 9 / OC1A.
Sample rate is 62500 while CPU=16MHz and TOP=255.
***/
#include <Arduino.h>
#include <SD.h>

#define ddd "8b/"
//just a directory to help quick maintenance

long int myfilesize;
int TopCounter;
boolean reading=false;
File mypcmsdfile;

int speakerPin=9; // must respect the timer , oc1a=digital9

void setup()
{ 
  TIMSK2 &= ~_BV(TOIE2); // deactivate sample interrupt just in case
  sei(); // global enable interrupt just in case

  Serial.begin(115200);
  
  Serial.print("Output is pin "); Serial.println(speakerPin); // a tip to remind the pin, in this program it is 9
  
  if (!SD.begin(4))
  {
    Serial.println("SD fail");
    return;
  }
  else
  {   
    Serial.println("SD ok");
  }
  
  DDRB |= 1 << DDB1; //portb OUT pin 1 , arduino pin 9, timer oc1a
  
  ConfigTim3(); // pwm with custom resolution
}

void loop(void)
{
  Serial.print("+");
  

//a command with buttons

  if(analogRead(A0)>1000)
    {
    letsPlay(ddd"recula.afm",1000,255); // 1000ms of delay and toppwm=255
    }
  if(analogRead(A1)>1000)
    {
    letsPlay(ddd"clochea.afm",2000,255);
    }
  if(analogRead(A2)>1000)
    {
    letsPlay(ddd"clochea.afm",1000,99);
    }
  if(analogRead(A3)>1000)
    {
    letsPlay(ddd"clochea.afm",2000,199);
    }

// a command with Serial monitor arduino

  switch(Serial.read())
  {
    case 'q':     letsPlay(ddd"recula.afm",1000,255);
                  break;
    case 'w':     letsPlay(ddd"recula.afm",1000,99);
                  break;
    case 'e':     letsPlay(ddd"clochea.afm",2000,255);
                  break;
    case 'r':     letsPlay(ddd"clochea.afm",2000,99);
                  break;
    case 't':     letsPlay(ddd"clochea.afm",2000,199);
                  break;
    default:break;
  }
}

void ConfigTim3(void)
{
//****** PWM t1
//wgm=1110 pwm top=icr1
  TCCR1B &= ~_BV(CS12) & ~_BV(CS11) & ~_BV(CS10); // deactivate pwm
  TCCR1A |= 1 << WGM11;
  TCCR1A &= ~(1 << WGM10);
  TCCR1B |= (1 << WGM13)|(1<<WGM12);//PWM en mode 14, fast pwm, TOP=ICR1, (voir doc page 133)
  TCCR1A |= (1 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0); // lazy of reset, setting this bit is enough
  //pin 9 , OC1A non inverting mode)
// f=F/(1+ICR)
  ICR1=99;//default top pwm
  OCR1A = 0; //rapport cyclique fixé à 0% par défaut

//****** sample t2
//normal top=0xff f=62500Hz : wgm=000
//nothing com=0000
//prescale=1 : cs=001 // but is set at start of play
  TCCR2B &= ~_BV(CS22) & ~_BV(CS21) & ~_BV(CS20); // deactivate sampling for begin
  TCCR2B &= ~_BV(WGM22) & ~_BV(WGM21) & ~_BV(WGM20);
  TCCR2A &= ~_BV(COM2A1) & ~_BV(COM2A0) & ~_BV(COM2B1) & ~_BV(COM2B0) ;
  TIMSK2 &= ~_BV(TOIE2);
}

ISR(TIMER2_OVF_vect) // overflow interrupt
{
  //static int i;
  //Serial.print(i++);
  Serial.print("*");
  
  if (mypcmsdfile.position() >= myfilesize)
  {
    stopPlayback();
  }
  else
  {
    OCR1A = mypcmsdfile.read();
    
    //OCR1A = mypcmsdfile.read()*(1+TopCounter)/256;
    //with thiswe could correct the cyclic rate even if top (so period) is changed
  }
}

void letsPlay(char str[], int time, int toppwm)
{
  stopPlayback(); // needed because SD.exists cannot find opened files
  Serial.print(str);
  if(SD.exists(str))
  {
    Serial.println("...ok.");
    startPlayback(str,toppwm);
    //if(time) {delay(time); stopPlayback();}
  }
  else
  {
    Serial.println("...not found.");
  }
}

void startPlayback(char filename[], int toppwm)
{
  if(reading)
  {
    return;
  }
  reading=true;
  mypcmsdfile=SD.open(filename);
  //if(mypcmsdfile){Serial.println("open");}else{Serial.println("error");}
  myfilesize=mypcmsdfile.size();
  mypcmsdfile.seek(0); // indice of start of data
  
  Serial.println(myfilesize);
  Serial.println(toppwm);
  
  ICR1=toppwm;
  TopCounter=toppwm;
  TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10); // prescale=1 : cs=001
  Serial.println("...");
// the last display which works fine !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  TCCR2B = (TCCR2B & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20); // prescale=1 : cs=001
  Serial.println("..");
  TIMSK2 |= _BV(TOIE2); // enable interrupt to sample (overflow)
  Serial.println(".");
  
}

void stopPlayback()
{
  TIMSK2 &= ~_BV(TOIE2); //disable interrupt sample
  TCCR2B &= ~( _BV(CS22) | _BV(CS21) | _BV(CS20) ); //stop sampling
  OCR1A=0;
  TCCR1B &= ~( _BV(CS12) | _BV(CS11) | _BV(CS10) );  //stop pwm
  digitalWrite(speakerPin, LOW);
  mypcmsdfile.close();
  reading=false;
}

EDIT: removed the useless call to a missing function which ramped the compare value between zero and the actual value, to begin or stop.

Serial.print("*");

You can not use serial print inside an ISR.

I suspect you shouldn't be reading a file in an ISR either

OCR1A = mypcmsdfile.read();

...R

The serial is just for test purpose but now i will know it just does not work.
The sd reading must be my problem so... but i really do not know how reading another way but synchronize with my timer...

Why am i not able to write or read ports with this kind of libraries in ISR ? Is it a delay problem or worse ?

If there is not good and simple solutions i will need to copy libraries with advanced buffer/spi code and only change the timer before be able to test the change of pwm frequence. What a shame i cannot customize resolution of timer2 to use the previous projects. And prescale would slow and so be useless.

By the way if someone know well about pwm noise so it could spare me my noob tests.

Thank you all.

but i really do not know how reading another way but synchronize with my timer...

You use the timer to set a flag.
Then in the main loop you look for the flag to be set, if it is you do your write and then clear the flag.

If your ISR finds the flag already set then this means you have not had time to do the previous write and your interrupts are therefore too fast for the SD card.

Its really important to keep an ISR down to the absolute bare-bones - calling
anything complicated may lead to lock-up if the library involved itself uses
delay or interrupts in some fashion. Whilst in an ISR all interrupts are deferred.

Because interrupts run asynchronously to the main code you have to be careful
not to foul up state used by both - unless the function / library being called has
been coded to be fully re-entrant.

I will think to extract everything with flags for now.
The algorithm works now and yes the timer is to much quick. So my high level programming cannot use my settings and i need to study more advanced programs like TmrPcm library before trying to make my own settings.
Thank you much, error solved and well explained.

Use the technique in the Blink Without Delay example sketch to manage your timing. It will be easier than using any timing library. I wrote and extended demo in the first post of this Thread.

...R