/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
/* Hardware specific headers */
#include "common\board.h"
/*Modules Header files*/
#include "i2s\i2s.h"
#include "rtc\rtcTask.h"
#include "fatfs\ff.h"
#include "fatfs\diskio.h"
#include "audioFile\audioFile.h"
/*Global const*/
/*Defines*/
/*Global vars*/
//Data for the demo task
static xTaskHandle xAudioFileDemoHandle;
//For the Filesystem
static FATFS fs; // Work area (file system object) for logical drive
static FIL audioFile; // File object
static DIR dir; // Firectory object
static FILINFO fno; // File Information
static FRESULT res; // FatFs function common result code
static UINT br; // File R/W count
static portCHAR buffer[512];
#define SIZEOFBUFFER (sizeof(buffer) / 2)
//For Audio DAC I2S
static tI2sInitData xInitData;
static tI2sSendData xSendData;
//For AudioFile
portCHAR *pBuffer = NULL;
/*Functions and Tasks*/
static void prvSetupHardware( void );
static void vAudioFileDemo( void *pvParameters );
/*Main Program*/
int main( void )
{
/* Setup the ports */
prvSetupHardware();
/*Start and Init RTC*/
vRtcTaskStart();
/*Tasks Start-up*/
xTaskCreate( vAudioFileDemo, "AudioFileDemo", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &xAudioFileDemoHandle );
/*Start the scheduler.*/
vTaskStartScheduler();
/* Should never get here! */
return 0;
}
/*A Demo of the features in the Graphic LCD driver for FreeRTOS*/
static void vAudioFileDemo( void *pvParameters )
{
portCHAR cnt;
for ( ; ; )
{
// Register a work area for logical drive 0
res = f_mount(0, &fs);
if (res) goto vAudioFileDemo_finish;
//Open directory
res = f_opendir(&dir, "/");
if (res != FR_OK) goto vAudioFileDemo_umount;
while (1)
{
//Read a Directory entry
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) goto vAudioFileDemo_umount;
if (fno.fname[0] == '.') continue;
//Open a file
res = f_open(&audioFile, fno.fname, FA_OPEN_EXISTING | FA_READ);
if (res) goto vAudioFileDemo_close;
//Read file header
res = f_read(&audioFile, buffer, sizeof(tAfFormatChunk), &br);
if (res) goto vAudioFileDemo_close;
//Check for WAV file
if (!CHUNK_WAV_IS_RIFF(buffer) || !CHUNK_WAV_IS_WAVE(buffer)) continue;
//Prepare DAC
xInitData.config.slotByFrame = 2;
xInitData.config.bitsBySLot = CHUNK_WAV_GET_BITRES(buffer);
xInitData.config.samplingFreq = CHUNK_WAV_GET_FREQUENCY(buffer);
xInitData.config.rxEnabled = 0;
xInitData.config.txEnabled = 1;
//Because mono wav is going to be shared between 2 channel we lower the bitrate to the half
if (CHUNK_WAV_GET_CHANNELS(buffer) == 1) xInitData.config.samplingFreq /= 2;
//Init I2S Device with selected configuration
eI2sInit(&xInitData);
//Set I2s task Block time
xSendData.xBlockTime = 30;
//Loop the file n times
for (cnt = 0; cnt < 4; cnt ++)
{
//Seek to the begining of the audio data
res = f_lseek(&audioFile, sizeof(tAfFormatChunk));
if (res) goto vAudioFileDemo_close;
//Read data from file
do
{
if (pBuffer == buffer) pBuffer = &buffer[SIZEOFBUFFER];
else pBuffer = buffer;
res = f_read(&audioFile, pBuffer, SIZEOFBUFFER, &br);
if (res) goto vAudioFileDemo_close;
//Prepare data for audio buffer
xSendData.size = br/2;
xSendData.data = (const unsigned portCHAR *) pBuffer;
//Send frame to the i2s buffer
cSendFrame(&xSendData);
}
while (br == SIZEOFBUFFER);
}
vAudioFileDemo_close:
f_close(&audioFile);
}
vAudioFileDemo_umount:
// Unregister a work area before discard it
f_mount(0, NULL);
vAudioFileDemo_finish:
vTaskDelete(xAudioFileDemoHandle);
}
}
static void prvSetupHardware( void )
{
/* When using the JTAG debugger the hardware is not always initialised to
the correct default state. This line just ensures that this does not
cause all interrupts to be masked at the start. */
AT91C_BASE_AIC->AIC_EOICR = 0;
/* Enable the peripheral clock to the PIO */
AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_PIOA);
}