Playing WAV Files with a DAC Tutorial
Arduino Sketch Version of WAV Files from SD Card
SparkFun Electronics
Written by Ryan Owens
3/16/2010
this is the first part of my code...(9500characters max)
//Add libraries to support FAT16 on the SD Card.
//(Note: If you already have these libraries installed in the directory, they'll have to remove in order to compile this.)
#include <byteordering.h>
#include <fat.h>
#include <fat_config.h>
#include <partition.h>
#include <partition_config.h>
#include <sd-reader_config.h>
#include <sd_raw.h>
#include <sd_raw_config.h>
//This is the amount of data to be fetched from the SD card for each read.
#define BUFFERSIZE 256
//Define the pin connections from the Arduino to the AD5330
#define CS 18
#define WR 17
#define LDAC 16
#define CLR 15
#define PD 10
#define BUF 9
#define GAIN 14
//This struct will hold information related to the WAV file that's being read.
typedef struct
{
int format;
int sample_rate;
int bits_per_sample;
}wave_format;
wave_format wave_info;
volatile unsigned char note=0; //Holds the current voltage value to be sent to the AD5330.
unsigned char header[44]; //Holds the WAV file header
unsigned char buffer1[BUFFERSIZE], buffer2[BUFFERSIZE]; //Two cycling buffers which contain the WAV data.
char file_name[30]; //WAV file name.
char play_buffer=0; //Keeps track of which buffer is currently being used
char new_buffer_ready=0; //Flag used by 'Loop' code to tell the Interrupt that new data is ready in the buffer.
volatile unsigned int byte_count=0; //Keeps track of the number of bytes read from the current buffer.
volatile char need_new_data=0; //Flag used by Interrupt to tell 'Loop' code that a buffer is empty and needs to be refilled.
struct fat_dir_struct* dd; //FAT16 directory
struct fat_dir_entry_struct dir_entry; //FAT16 directory entry (A.K.A. a file)
struct fat_fs_struct* fs; //FAT16 File System
struct partition_struct* partition; //FAT16 Partition
struct fat_file_struct * file_handle; //FAT16 File Handle
void setup()
{
//Pins D0-D8 go to parallel control pins on AD5330
for(int pin=0; pin<8; pin++)
{
pinMode(pin, OUTPUT);
}
pinMode(CS, OUTPUT);
pinMode(WR, OUTPUT);
pinMode(LDAC, OUTPUT);
pinMode(CLR, OUTPUT);
pinMode(PD, OUTPUT);
pinMode(BUF, OUTPUT);
digitalWrite(PD, HIGH); //Enable the AD5330
digitalWrite(GAIN, LOW); //Set Gain to 1
digitalWrite(BUF, LOW); //Don't buffer the input
digitalWrite(CS, HIGH); //Set the CS high by default
digitalWrite(WR, HIGH); //Set the WR pin high by default
digitalWrite(CLR, HIGH); //Make sure Clear pin is disabled
digitalWrite(LDAC, LOW);
//Clock in Gain and Buffer Values
digitalWrite(CS, LOW);
delayMicroseconds(10);
digitalWrite(WR, LOW);
delayMicroseconds(10);
digitalWrite(CS, LOW);
delayMicroseconds(10);
digitalWrite(WR, LOW);
delayMicroseconds(10);
//Serial.begin(9600);
}
//This timer interrupt will run every 45uS. A 45uS period equals a frequency of 22.222kHz. This is frequency of the WAV
//files that will be played by this sketch.
ISR(TIMER1_COMPA_vect){
cli(); //Disable interrupts
//Check to see if we've read all of the data in the current buffer
if(byte_count==BUFFERSIZE)
{
need_new_data=1; //Set a flag to tell the 'loop' code to refill the current buffer.
byte_count=0; //Reset the count
//Check to see if new data exists in the alternate buffer
if(new_buffer_ready==1)
{
//If new data is available, reassign the play buffer.
if(play_buffer==0)play_buffer=1;
else play_buffer=0;
}
else
{
//If no new data is available then wait for it!
sei();
return;
}
}
//Find out which buffer is being used, and get data from it.
if(play_buffer==0)note=buffer1[byte_count];
else note=buffer2[byte_count];
//Increase the byte_count since we've taken the current data.
byte_count +=1;
//Clock in the current value that was retrieved from the play buffer.
digitalWrite(CS, LOW);
digitalWrite(WR, LOW);
PORTD = note; //Writing 'note' to PORTD is a much faster way to perform a digitalWrite() to D0-D7.
digitalWrite(WR, HIGH);
digitalWrite(CS, HIGH);
sei(); //Re-enable interrupts
}
void loop()
{
int bytes_read=0; //Keeps track of how many bytes are read when accessing a file on the SD card.
//Init Timer 1
//Used for 45uS Interrupt
TCCR1A = 0; //Set Timer to normal mode
TCCR1B = 0x0A; //Set Timer clock to 2 MHz. Clear timer on compare
TIMSK1 = 0x02; //Enable Timer 1 Compare A Interrupt;
OCR1AH = 0X00; //Count to 90 before triggering an interrupt. Counting to 90 with a 2MHz clock makes
OCR1AL = 0x5A; //the interrupt trigger at 22.222kHz
init_filesystem(); //Initialize the FAT16 file system on the SD card.
if(get_wav_filename(dd, file_name)); //Find the first WAV file on the SD card (must be in the root directory)
else while(1); //If a WAV file isn't found then the sketch is stopped here.
I post my errors in the next post, please help me i'm a beginner!