1

I would need a quick help if possible because I have a project with the deadline tomorrow night. On my Uno (atmega328p in fact), I need to communicate with a SPI flash to transfer music and then, take this music (part by part) to play with the PCM library. But, both libraries are using pin 11 (MOSI and speakPin) to work.

That's why I tried to change the source code in PCM.c https://github.com/damellis/PCM/blob/master/PCM.c, I just changed the timer 2 in timer 0. That works but only for one song. With the timer 2 you can use several times the startPlayback() function but with the timer 0 it will work with only song.... I guess it's because timer 2 is asynchronous but not the timer 0.

I found this website : http://www.renar.net/?p=73&lang=en, that's why I hope it's possible with a synchronous timer and several song.

I hope you'll have some clues for me !

Here below my new code in PCM.c :

int speakerPin = 6;
volatile unsigned char *sounddata_data;
int sounddata_length=0;
volatile uint16_t sample;
byte lastSample;
volatile boolean counterReady;

// This is called at 8000 Hz to load the next sample.
ISR(TIMER1_COMPA_vect) {
if (sample >= sounddata_length) {
   if (sample == sounddata_length + lastSample) {
    stopPlayback();
    counterReady = true;
   }
   else {
    // Ramp down to zero to reduce the click at the end of playback.
    OCR0A = sounddata_length + lastSample - sample;
   }
 }
 else {
    OCR0A = pgm_read_byte(&sounddata_data[sample]);
 }

 ++sample;
}

void startPlayback(unsigned char *data, int length)
{
   sounddata_data = data;
   sounddata_length = length;

   pinMode(speakerPin, OUTPUT);

   // Set up Timer 2 to do pulse width modulation on the speaker
   // pin.

  // Use internal clock (datasheet p.160)
  ASSR &= ~(_BV(EXCLK) | _BV(AS2));

  // Set fast PWM mode  (p.157)
   TCCR0A |= _BV(WGM01) | _BV(WGM00);
   TCCR0B &= ~_BV(WGM02);

   // Do non-inverting PWM on pin OC2A (p.155)
   // On the Arduino this is pin 11.
   TCCR0A = (TCCR0A | _BV(COM0A1)) & ~_BV(COM0A0);
   TCCR0A &= ~(_BV(COM0B1) | _BV(COM0B0));

   // No prescaler (p.158)
   TCCR0B = (TCCR0B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);

   // Set initial pulse width to the first sample.
   OCR0A = pgm_read_byte(&sounddata_data[0]);


   // Set up Timer 1 to send a sample every interrupt.

   cli();

   // Set CTC mode (Clear Timer on Compare Match) (p.133)
   // Have to set OCR1A *after*, otherwise it gets reset to 0!
   TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
   TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));

   // No prescaler (p.134)
   TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);

   // Set the compare register (OCR1A).
   // OCR1A is a 16-bit register, so we have to do this with
   // interrupts disabled to be safe.
   OCR1A = F_CPU / SAMPLE_RATE;    // 16e6 / 8000 = 2000

  // Enable interrupt when TCNT1 == OCR1A (p.136)
  TIMSK1 |= _BV(OCIE1A);

   lastSample = pgm_read_byte(&sounddata_data[sounddata_length-1]);
   sample = 0;
   sei();
}

void stopPlayback()
{
    // Disable playback per-sample interrupt.
    TIMSK1 &= ~_BV(OCIE1A);

   // Disable the per-sample timer completely.
   TCCR1B &= ~_BV(CS10);

   // Disable the PWM timer.
   TCCR0B &= ~_BV(CS10);

   digitalWrite(speakerPin, LOW);
}
6
  • 1
    Or is it maybe cause the Timer0 remapping destryys millis and delay, causing hickups in your SPI driver? If you do load the music data chunkwise via SPI (from an SD card I presume), does it play the entire song correctly or only the first chunk? – Maximilian Gerhardt May 16 '18 at 8:32
  • I guess it's because timer 2 is asynchronous but not the timer 0 - what do you mean by that? I don't think the timers differ in asynchronousity (if that is a word, which I gather it isn't). – Nick Gammon May 16 '18 at 8:35
  • 1
    @NickGammon: Unlike Timer 0, Timer 2 can be operated in asynchronous mode (independent of the main clock). But this mode is not used here, so this is not relevant. – Edgar Bonet May 16 '18 at 8:43
  • 2
    Try keeping Timer 2, but switchin to pin OC2B (Arduino pin 3). Just replace in the original code OCR2AOCR2B, and swap COM2A0COM2B0, COM2A1COM2B1. – Edgar Bonet May 16 '18 at 8:48
  • @NickGammon synchronicity is a word. Not sure about its opposite though... (asynchronicity ... yes, Grammarly likes it. ) – Majenko May 16 '18 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.