Fast pwm and a double buffer routine

Guys, Im very pleased with a bit of code I have made to output sound to OCR0A - it worked fine when I was running at 16Mhz, but now its not working. My debugging tells me that the “flag” i have set up to tell it to “read” more wav file info into a buffer is not changing state and therefore the buffer is not being filled. I wonder if anyone can see why:
This is the code in main that fills the buffers - there are two - fill one, while “playing” the other:

while(1) { 
printf("read_next = %d\n", read_next);
      if (read_next) { 
         PORTB ^= (1 << PB0); // toggle the LED 
		 printf("Active = %d\n", active);
         if (active == 1) { 
		 printf("reading into buffer2\n");
            // read to the "other" one... 
//            xputs(PSTR("Read to 2\n")); 
            res = f_read(&file1, buff2, 512, &s2); 
            if (res != FR_OK) { 
               printf("Read to 2 failed, res=%d\n", res); 
            } 
		
         } 
         else { 
//            xputs(PSTR("Read to 1\n")); 
            res = f_read(&file1, buff1, 512, &s2); 
            if (res != FR_OK) { 
               printf("Read to 1 failed, res=%d\n", res); 
            } 
			
		} 
         if (s2 != 512) { 
            //f_lseek(&file1, 0); // loop back to start of file
			TIMSK0 &= ~(1 << TOIE0); 
			break;
         } 
         read_next = 0; 
      } 

	  
   } 

when read_next is 1 it checks which buffer to fille (based on the value of active).
Th ISR that sends the info to the OCR0A is:

ISR(TIMER0_OVF_vect) { 
   div8++; 
   if (div8 == 3) { 
      if (active == 1) { 
         OCR0A = buff1[play_index++]; 
		 //printf("buffer1 = %d\n",buff1[play_index++]);
      } // if active == 1
      else { 
         OCR0A = buff2[play_index++]; 
		 //printf("buffer2 = %d\n",buff2[play_index++]);
      } //else
      if (play_index >= 512) { 
	  
         if (active == 1) { 
            active = 2; 
         } // if active == 1
         else { 
            active = 1; 
         } //else
         play_index = 0; 
      } //play_index >= 512
	  div8 = 0; 
   } // div8 == 3
      if (play_index == 100) { 

         // trigger read of the other buffer when one part used 
         read_next = 1; 
      }// if play_index == 100
      
} //function

however this is never happening:

     if (play_index == 100) { 

         // trigger read of the other buffer when one part used 
         read_next = 1; 
      }// if play_index == 100

i.e read_next now no longer gets set to 1 therefore the other buffer is never filled.

Hello,

Do you have read_next declared as volatile? What hardware is this code running on?

What frequency are you using now? Has anything else changed since you had it working?

- Kevin

Hi Kevin, thanks for your reply.
I changed the chip from the mega128 (smd) to the mega1284 40 pin dip.
After reading a bit, it seems that it could be related to the spi or the fuses. I am quite new to spi but I read that I might have to set some of the registers in the spi to allow 16Mhz to work?
It was reading and filling the buffers from an sd card. It worked fine on my last chip.
One other question is do I need to set MOSI/MISO etc when using those pins as data in/out lines?
I have done this:


PORTB = 0b00000000; // Port B PB5=MOSI, PB4=CS, PB3=0C0A, PB1=SCK, PB0=LED (reverse logic) 
  	DDRB  = 0b10111000; 

however Im not sure if its required? It hasnt changed the results anyway.

I am not familiar with the differences between the ATmega128 and ATmega1284 offhand, but in general, I would not expect code from one to work on the other without some changes. If you have not already, I suggest you compare the descriptions of corresponding peripherals (such as timers) and registers in both chips’ datasheets to look for any differences you might have missed.

Rather than trying to port your entire program over at once, you might also want to start with a simpler program and gradually add functionality back in, so you can more easily isolate problems.

SPI is a serial interface, so I don’t expect it to be relevant in this situation (it doesn’t look like you’re working with anything that uses an SPI interface).

- Kevin

Hi Kevin,
yeah i changed all the timer registers over to the mega1284 using the datasheets to compare.
I dont know if you have heard of Elm Chan’s fat file system, anyhow its freely available very well tested file system for sd cards on avr’s. really useful. I had it working perfectly at 16Mhz on the mega128, when I ported to the mega1284 I couldnt get it to work at 16Mhz.
Two things:
Firstly assume because only one pin is labaled miso, one mosi, one ss etc I have to connect to those pins on the mega1284. I have then set the ones I think need to be outputs for it to work - mentioned before.
But I swear sd does use spi - and the sd card would be the slave.
I wonder whether the spi therefore does need to be set up differently?

Sorry, I overlooked it when you mentioned you were using an SD card. You are right; the SD card does have an SPI interface.

For reference, you could try looking at the source code for the Pololu AVR library, specifically the SPI master functions. These can be used on an Orangutan SVP-1284, which uses an ATmega1284, so it might serve as an example of working SPI code (although the Orangutans run at 20 MHz).

- Kevin

Ah, you guys have written nice libraries!
Is there an example of reading/writing to an sd card here?

Unfortunately, we have not written any code examples for interfacing with SD cards (and I don’t think we have tried using the SPI functions in the library to do so).

- Kevin