import basic-ssc-i2s-wm8731-project from at91sam3-ek

ported to at91lib-1.9
This commit is contained in:
Harald Welte 2011-12-01 19:56:39 +01:00
parent eebb6cc121
commit 70285f225b
7 changed files with 929 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,227 @@
# ----------------------------------------------------------------------------
# ATMEL Microcontroller Software Support
# ----------------------------------------------------------------------------
# Copyright (c) 2008, Atmel Corporation
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the disclaimer below.
#
# Atmel's name may not be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
# DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ----------------------------------------------------------------------------
# Makefile for compiling basic-ssc-i2s-at73c213-project
#-------------------------------------------------------------------------------
# User-modifiable options
#-------------------------------------------------------------------------------
# Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
CHIP = at91sam3u4
BOARD = at91sam3u-ek
# Trace level used for compilation
# (can be overriden by adding TRACE_LEVEL=#number to the command-line)
# TRACE_LEVEL_DEBUG 5
# TRACE_LEVEL_INFO 4
# TRACE_LEVEL_WARNING 3
# TRACE_LEVEL_ERROR 2
# TRACE_LEVEL_FATAL 1
# TRACE_LEVEL_NO_TRACE 0
TRACE_LEVEL = 5
# Optimization level, put in comment for debugging
#OPTIMIZATION = -Os
# AT91 library directory
AT91LIB = ../../at91lib
# External library
EXT_LIBS= ../external_libs
# Output file basename
OUTPUT = basic-ssc-i2s-wm8731-project-$(BOARD)-$(CHIP)
# Compile with chip specific features
include $(AT91LIB)/boards/$(BOARD)/$(CHIP)/chip.mak
# Compile for all memories available on the board (this sets $(MEMORIES))
include $(AT91LIB)/boards/$(BOARD)/board.mak
# Output directories
BIN = bin
OBJ = obj
#-------------------------------------------------------------------------------
# Tools
#-------------------------------------------------------------------------------
# Tool suffix when cross-compiling
CROSS_COMPILE = arm-none-eabi-
# Compilation tools
CC = $(CROSS_COMPILE)gcc
SIZE = $(CROSS_COMPILE)size
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
# Flags
INCLUDES += -I$(AT91LIB)/boards/$(BOARD)
INCLUDES += -I$(AT91LIB)/peripherals
INCLUDES += -I$(AT91LIB)/components
INCLUDES += -I$(AT91LIB)/drivers
INCLUDES += -I$(AT91LIB)
INCLUDES += -I$(EXT_LIBS)/fat
INCLUDES += -I$(AT91LIB)/memories
INCLUDES += -I.
INCLUDES += -I$(EXT_LIBS)
INCLUDES += -I$(EXT_LIBS)/cmsis
ifeq ($(CHIP_CORE), cortexm3)
TARGET_OPTS = -mcpu=cortex-m3 -mthumb
else
TARGET_OPTS =
endif
CFLAGS += $(TARGET_OPTS)
CFLAGS += -Wall -mlong-calls -ffunction-sections
CFLAGS += -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL)
ASFLAGS = $(TARGET_OPTS) -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__
LDFLAGS = -g $(OPTIMIZATION) -nostartfiles $(TARGET_OPTS) -Wl,--gc-sections
#-------------------------------------------------------------------------------
# Files
#-------------------------------------------------------------------------------
# Directories where source files can be found
PERIPH = $(AT91LIB)/peripherals
BOARDS = $(AT91LIB)/boards
UTILITY = $(AT91LIB)/utility
COMP = $(AT91LIB)/components
DRIVER = $(AT91LIB)/drivers
FATFS = $(EXT_LIBS)/fat/fatfs
MEM = $(AT91LIB)/memories
VPATH += $(COMP)/codec-wm8731
VPATH += $(UTILITY)
VPATH += $(PERIPH)/dbgu
VPATH += $(PERIPH)/pio
VPATH += $(PERIPH)/irq
VPATH += $(PERIPH)/ssc
VPATH += $(PERIPH)/twi
VPATH += $(PERIPH)/pmc
VPATH += $(PERIPH)/cp15
VPATH += $(BOARDS)/$(BOARD)
VPATH += $(BOARDS)/$(BOARD)/$(CHIP)
VPATH += $(PERIPH)/mci
VPATH += $(DRIVER)/twi
VPATH += $(MEM)/sdmmc
VPATH += $(PERIPH)/dma
VPATH += $(DRIVER)/dmad
VPATH += $(FATFS)/src
VPATH += $(MEM)
VPATH += $(EXT_LIBS)/cmsis
# Objects built from C source files
C_OBJECTS += main.o
C_OBJECTS += wm8731.o
C_OBJECTS += wav.o
C_OBJECTS += stdio.o
C_OBJECTS += math.o
C_OBJECTS += dbgu.o
C_OBJECTS += pio.o
C_OBJECTS += ssc.o
C_OBJECTS += twi.o
C_OBJECTS += pmc.o
C_OBJECTS += twid.o
C_OBJECTS += board_lowlevel.o
C_OBJECTS += trace.o
C_OBJECTS += board_memories.o
C_OBJECTS += Media.o
C_OBJECTS += MEDSdcard.o
C_OBJECTS += diskio.o
C_OBJECTS += ff_util.o
C_OBJECTS += tff.o
C_OBJECTS += ff.o
C_OBJECTS += sdmmc_mci.o
# Objects for different chips
ifeq ($(CHIP_CORE), cortexm3)
C_OBJECTS += nvic.o
C_OBJECTS += exceptions.o
C_OBJECTS += board_cstartup_gnu.o
C_OBJECTS += core_cm3.o
else
C_OBJECTS += aic.o
C_OBJECTS += cp15.o
C_OBJECTS += pit.o
endif
ifeq ($(CHIP_IP_MCI), MCI_DMA)
C_OBJECTS += dmad.o
C_OBJECTS += dma.o
C_OBJECTS += mci_hs.o
else
C_OBJECTS += mci.o
endif
# Objects built from Assembly source files
ifneq ($(CHIP_CORE), cortexm3)
ASM_OBJECTS += board_cstartup.o
ASM_OBJECTS += cp15_asm.o
endif
# Append OBJ and BIN directories to output filename
OUTPUT := $(BIN)/$(OUTPUT)
#-------------------------------------------------------------------------------
# Rules
#-------------------------------------------------------------------------------
all: $(BIN) $(OBJ) $(MEMORIES)
$(BIN) $(OBJ):
mkdir $@
define RULES
C_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(C_OBJECTS))
ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS))
$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1))
$(CC) $(LDFLAGS) -T"$(AT91LIB)/boards/$(BOARD)/$(CHIP)/$$@.lds" -o $(OUTPUT)-$$@.elf $$^
$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin
$(SIZE) $$^ $(OUTPUT)-$$@.elf
$$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN)
$(CC) $(CFLAGS) -D$(1) -c -o $$@ $$<
$$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN)
$(CC) $(ASFLAGS) -D$(1) -c -o $$@ $$<
debug_$(1): $(1)
perl ../resources/gdb/debug.pl $(OUTPUT)-$(1).elf
endef
$(foreach MEMORY, $(MEMORIES), $(eval $(call RULES,$(MEMORY))))
clean:
-rm -f $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf

View File

@ -0,0 +1,164 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef FATFS_CONFIG_H
#define FATFS_CONFIG_H
//------------------------------------------------------------------------------
// General Definitions (previously in ff.h)
//------------------------------------------------------------------------------
#define _FATFS_TINY 1
/* When _FATFS_TINY is set to 1, fatfs is compiled in Tiny mode
/ Else, it is compiled in normal mode
/ Tiny FatFs feature : Very low memory consumption, suitable for small memory
/ system. (1KB RAM) : Supports only single drive, no disk format,
/ only read functions, no write functions */
//------------------------------------------------------------------------------
// Definitions for normal FATFS (previously in ff.h)
//------------------------------------------------------------------------------
#if _FATFS_TINY == 0
#define _MCU_ENDIAN 2
/* The _MCU_ENDIAN defines which access method is used to the FAT structure.
/ 1: Enable word access.
/ 2: Disable word access and use byte-by-byte access instead.
/ When the architectural byte order of the MCU is big-endian and/or address
/ miss-aligned access results incorrect behavior, the _MCU_ENDIAN must be set to 2.
/ If it is not the case, it can also be set to 1 for good code efficiency. */
#define _FS_READONLY 0
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate and useless f_getfree. */
#define _FS_MINIMIZE 0
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename are removed.
/ 2: f_opendir and f_readdir are removed in addition to level 1.
/ 3: f_lseek is removed in addition to level 2. */
#define _USE_STRFUNC 0
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
#define _USE_FSINFO 1
/* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */
#define _USE_SJIS 1
/* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
/ only US-ASCII(7bit) code can be accepted as file/directory name. */
#define _USE_NTFLAG 1
/* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved.
/ Note that the files are always accessed in case insensitive. */
#define _USE_MKFS 1
/* When _USE_MKFS is set to 1 and _FS_READONLY is set to 0, f_mkfs function is
/ enabled. */
#define _DRIVES 2
/* Number of logical drives to be used. This affects the size of internal table. */
#define _MULTI_PARTITION 0
/* When _MULTI_PARTITION is set to 0, each logical drive is bound to same
/ physical drive number and can mount only 1st primaly partition. When it is
/ set to 1, each logical drive can mount a partition listed in Drives[]. */
//------------------------------------------------------------------------------
// Definitions for normal FATFS TINY (previously in tff.h)
//------------------------------------------------------------------------------
#else
#define _MCU_ENDIAN 2
/* The _MCU_ENDIAN defines which access method is used to the FAT structure.
/ 1: Enable word access.
/ 2: Disable word access and use byte-by-byte access instead.
/ When the architectural byte order of the MCU is big-endian and/or address
/ miss-aligned access results incorrect behavior, the _MCU_ENDIAN must be set to 2.
/ If it is not the case, it can also be set to 1 for good code efficiency. */
#define _FS_READONLY 1
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
/ f_truncate, f_getfree and internal writing codes. */
#define _FS_MINIMIZE 0
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
/ 0: Full function.
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename are removed.
/ 2: f_opendir and f_readdir are removed in addition to level 1.
/ 3: f_lseek is removed in addition to level 2. */
#define _USE_STRFUNC 0
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
#define _USE_FSINFO 1
/* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */
#define _USE_SJIS 1
/* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
/ only US-ASCII(7bit) code can be accepted as file/directory name. */
#define _USE_NTFLAG 1
/* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved.
/ Note that the files are always accessed in case insensitive. */
#define _USE_FORWARD 0
/* To enable f_forward function, set _USE_FORWARD to 1. */
#define _FAT32 1
/* To enable FAT32 support in addition of FAT12/16, set _FAT32 to 1. */
#endif
//------------------------------------------------------------------------------
// Other definitions
//------------------------------------------------------------------------------
/*-----------------------------------------------------------------------*/
/* Correspondence between drive number and physical drive */
/* Note that Tiny-FatFs supports only single drive and always */
/* accesses drive number 0. */
#define DRV_MMC 0
#define DRV_SDRAM 1
#define DRV_ATA 2
#define DRV_USB 3
#define DRV_NAND 4
#define SECTOR_SIZE_DEFAULT 512
#define SECTOR_SIZE_SDRAM 512
#define SECTOR_SIZE_SDCARD 512
#endif // FATFS_CONFIG_H

View File

@ -0,0 +1,538 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//-----------------------------------------------------------------------------
/// \dir "Basic SSC-I2S WM8731 project"
///
/// !!!Purpose
///
/// This example uses the Synchronous Serial Controller (SSC) of an AT91 microcontroller
/// to output an audio steam through the on-board WM8731 CODEC.
///
///
/// !!!See
/// - ssc: SSC driver interface
///
/// !!!Description
///
/// This program plays a WAV file pre-loaded into the SDcard. The audio stream is sent through
/// the SSC interface connected to the on-board WM8731, enabling the sound to be audible using a pair of headphones.
///
/// Since the WM8731 DAC requires that it be feeded a master clock multiple of the sample rate,
/// it is difficult to handle any WAV file. As such, this example application is limited to playing files with the following format:
/// - Format: WAV
/// - Sample rate: 48 kHz
///
/// !!!Usage
///
/// -# Build the program and download it inside the evaluation board. Please
/// refer to the
/// <a href="http://www.atmel.com/dyn/resources/prod_documents/doc6224.pdf">
/// SAM-BA User Guide</a>, the
/// <a href="http://www.atmel.com/dyn/resources/prod_documents/doc6310.pdf">
/// GNU-Based Software Development</a> application note or to the
/// <a href="ftp://ftp.iar.se/WWWfiles/arm/Guides/EWARM_UserGuide.ENU.pdf">
/// IAR EWARM User Guide</a>, depending on your chosen solution.
/// -# On the computer, open and configure a terminal application
/// (e.g. HyperTerminal on Microsoft Windows) with these settings:
/// - 115200 bauds
/// - 8 bits of data
/// - No parity
/// - 1 stop bit
/// - No flow control
/// -# Start the application.
/// -# In the terminal window, the following text should appear:
/// \code
/// -- Basic SSC I2S WM8731 Project xxx --
/// -- AT91xxxxxx-xx
/// -- Compiled: xxx xx xxxx xx:xx:xx --
/// Menu :
/// ------
/// W: Play the WAV file pre-loaded in SD Card
/// I: Display the information of the WAV file
/// \endcode
/// The user can then choose any of the available options to perform the described action.
///
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// This file contains all the specific code for the
/// basic-ssc-i2s-wm8731-project
///
/// !Contents
///
/// The code can be roughly broken down as follows:
/// - Enable the clock
/// - Load WAV file information
/// - Configure and enable the Codec
/// - Configure and enable the SSC interrupt
/// - Play WAV file
///
/// Please refer to the list of functions in the #Overview# tab of this unit
/// for more detailed information.
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <board_memories.h>
#include <pio/pio.h>
#include <irq/irq.h>
#include <twi/twid.h>
#include <twi/twi.h>
#include <dbgu/dbgu.h>
#include <ssc/ssc.h>
#include <codec-wm8731/wm8731.h>
#include <utility/wav.h>
#include <utility/assert.h>
#include <utility/math.h>
#include <utility/trace.h>
#include <memories/MEDSdcard.h>
#include "fatfs_config.h"
#if _FATFS_TINY != 1
#include <fatfs/src/ff.h>
#else
#include <fatfs/src/tff.h>
#endif
#include <fatfs/src/ff_util.h>
#include <string.h>
#define AUDIO_USING_DMA
#if defined (AUDIO_USING_DMA)
#include <dmad/dmad.h>
#include <dma/dma.h>
#endif
//------------------------------------------------------------------------------
// Local constants
//------------------------------------------------------------------------------
/// Master clock frequency in Hz
#define SSC_MCK 49152000
/// Address at which the WAV file is located
#define WAV_FILE_ADDRESS (0x60000000 + 0x100)//0x8000)
/// Maximum size in bytes of the WAV file.
#define MAX_WAV_SIZE 0x100000
// TWI clock
#define TWI_CLOCK 100000
// PMC define
#define AT91C_CKGR_PLLR AT91C_CKGR_PLLAR
#define AT91C_PMC_LOCK AT91C_PMC_LOCKA
#define AT91C_CKGR_MUL_SHIFT 16
#define AT91C_CKGR_OUT_SHIFT 14
#define AT91C_CKGR_PLLCOUNT_SHIFT 8
#define AT91C_CKGR_DIV_SHIFT 0
/// Maximum number of LUNs which can be defined.
/// (Logical drive = physical drive = medium number)
#define MAX_LUNS 1
/// Available medias.
Media medias[MAX_LUNS];
#define ID_DRV DRV_MMC
#define SAMPLE_RATE (48000)
#define SLOT_BY_FRAME (2)
#define BITS_BY_SLOT (16)
#define AT91C_I2S_MASTER_TX_SETTING(nb_bit_by_slot, nb_slot_by_frame)( +\
AT91C_SSC_CKS_DIV +\
AT91C_SSC_CKO_CONTINOUS +\
AT91C_SSC_START_FALL_RF +\
((1<<16) & AT91C_SSC_STTDLY) +\
((((nb_bit_by_slot*nb_slot_by_frame)/2)-1) <<24))
#define AT91C_I2S_TX_FRAME_SETTING(nb_bit_by_slot, nb_slot_by_frame)( +\
(nb_bit_by_slot-1) +\
AT91C_SSC_MSBF +\
(((nb_slot_by_frame-1)<<8) & AT91C_SSC_DATNB) +\
(((nb_bit_by_slot-1)<<16) & AT91C_SSC_FSLEN) +\
AT91C_SSC_FSOS_NEGATIVE)
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// List of pins to configure.
static const Pin pins[] = {PINS_TWI0, PINS_SSC_CODEC, PIN_PCK0};
/// Pointer to the playback WAV file header.
static const WavHeader *userWav = (WavHeader *) (0x60000000);
/// Indicates if the WAV file is currently being played.
static unsigned char isWavPlaying;
#if defined (AUDIO_USING_DMA)
/// Number of samples which have already been transmitted.
static unsigned int transmittedSamples;
/// Number of samples that have not yet been transmitted.
static unsigned int remainingSamples;
#endif
#if _FATFS_TINY == 0
#define STR_ROOT_DIRECTORY "0:"
#else
#define STR_ROOT_DIRECTORY ""
#endif
#if defined(at91cap9stk)
#define MCI_ID 1 //no connector for MCIO/SPI0
#else
#define MCI_ID 0
#endif
const char* FileName = STR_ROOT_DIRECTORY "sample.wav";
static Twid twid;
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Display the information of the WAV file (sample rate, stereo/mono and frame
/// size) on the DBGU.
//------------------------------------------------------------------------------
static void DisplayWavInfo(void)
{
printf("%c[2J", 27);
printf( " Wave file header information\n\r");
printf( "--------------------------------\n\r");
printf( " - Chunk ID = 0x%08X\n\r", userWav->chunkID);
printf( " - Chunk Size = %d\n\r", userWav->chunkSize);
printf( " - Format = 0x%08X\n\r", userWav->format);
printf( " - SubChunk ID = 0x%08X\n\r", userWav->subchunk1ID);
printf( " - Subchunk1 Size = %d\n\r", userWav->subchunk1Size);
printf( " - Audio Format = 0x%04X\n\r", userWav->audioFormat);
printf( " - Num. Channels = %d\n\r", userWav->numChannels);
printf( " - Sample Rate = %d\n\r", userWav->sampleRate);
printf( " - Byte Rate = %d\n\r", userWav->byteRate);
printf( " - Block Align = %d\n\r", userWav->blockAlign);
printf( " - Bits Per Sample = %d\n\r", userWav->bitsPerSample);
printf( " - Subchunk2 ID = 0x%08X\n\r", userWav->subchunk2ID);
printf( " - Subchunk2 Size = %d\n\r", userWav->subchunk2Size);
printf("Press a key to return to the menu ...\n\r");
DBGU_GetChar();
}
//------------------------------------------------------------------------------
/// Displays the user menu on the DBGU.
//------------------------------------------------------------------------------
static void DisplayMenu(void)
{
printf("%c[2J-- Basic SSC I2S WM8731 Project xxx --\n\r", 27);
printf("Menu :\n\r");
printf("------\n\r");
// Play a WAV file pre-loaded in SDCARD using SAM-BA
if (!isWavPlaying) {
printf(" W: Play the WAV file pre-loaded in SDCARD\n\r");
}
// Display the information of the WAV file (sample rate, stereo/mono and frame size)
printf(" I: Display the information of the WAV file\n\r");
// Stop the current playback (if any)
if (isWavPlaying) {
printf(" S: Stop playback\n\r");
}
}
#if defined(AUDIO_USING_DMA)
void HDMA_IrqHandler(void)
{
unsigned int size;
unsigned intFlag;
// One buffer sent & more buffers to send
if (remainingSamples > 0 ) {
size = min(remainingSamples / (userWav->bitsPerSample / 8), BOARD_SSC_DMA_FIFO_SIZE * MAX_SSC_LLI_SIZE/2);
SSC_WriteBuffer(AT91C_BASE_SSC0, (void *) (WAV_FILE_ADDRESS + transmittedSamples), size);
remainingSamples -= size * (userWav->bitsPerSample / 8);
transmittedSamples += size * (userWav->bitsPerSample / 8);
intFlag = 1 << (BOARD_SSC_DMA_CHANNEL + 8) ;
DMA_EnableIt(intFlag);
DMA_EnableChannel(BOARD_SSC_DMA_CHANNEL);
}
else if (remainingSamples == 0){
DMA_DisableChannel(BOARD_SSC_DMA_CHANNEL);
intFlag = 1 << (BOARD_SSC_DMA_CHANNEL + 8) ;
DMA_DisableIt(intFlag);
isWavPlaying = 0;
DisplayMenu();
}
}
#endif
//------------------------------------------------------------------------------
/// Play a WAV file pre-loaded in SDCARD.
//------------------------------------------------------------------------------
void PlayLoop(unsigned short *pExtMem, unsigned int numSamples)
{
unsigned int i;
for (i = 0; i < numSamples; i++) {
SSC_Write(AT91C_BASE_SSC0, pExtMem[i]);
}
}
//------------------------------------------------------------------------------
/// Play a WAV file pre-loaded in SDCARD
//------------------------------------------------------------------------------
static void PlayWavFile(void)
{
#if !defined(AUDIO_USING_DMA)
unsigned int size;
size = userWav->subchunk2Size > MAX_WAV_SIZE ? MAX_WAV_SIZE : userWav->subchunk2Size;
SSC_EnableTransmitter(AT91C_BASE_SSC0);
PlayLoop((unsigned short *)WAV_FILE_ADDRESS, size >> 1);
#else
unsigned int size;
unsigned int intFlag = 0;
size = userWav->subchunk2Size > MAX_WAV_SIZE ? MAX_WAV_SIZE : userWav->subchunk2Size;
SSC_EnableTransmitter(AT91C_BASE_SSC0);
// Start transmitting WAV file to SSC
remainingSamples = userWav->subchunk2Size;
transmittedSamples = 0;
intFlag = 1 << (BOARD_SSC_DMA_CHANNEL + 8) ;
DMA_DisableIt(intFlag);
DMA_DisableChannel(BOARD_SSC_DMA_CHANNEL);
// Fill DMA buffer
size = min(remainingSamples / (userWav->bitsPerSample / 8), BOARD_SSC_DMA_FIFO_SIZE * MAX_SSC_LLI_SIZE/2);
SSC_WriteBuffer(AT91C_BASE_SSC0, (void *) (WAV_FILE_ADDRESS + transmittedSamples), size);
remainingSamples -= size * (userWav->bitsPerSample / 8);
transmittedSamples += size * (userWav->bitsPerSample / 8);
intFlag = 1 << (BOARD_SSC_DMA_CHANNEL + 8) ;
DMA_EnableIt(intFlag);
DMA_EnableChannel(BOARD_SSC_DMA_CHANNEL);
#endif
}
//------------------------------------------------------------------------------
/// Stop the current playback (if any).
//------------------------------------------------------------------------------
static void StopPlayback(void)
{
SSC_DisableTransmitter(AT91C_BASE_SSC0);
}
//------------------------------------------------------------------------------
/// Check wav file from sdcard
//------------------------------------------------------------------------------
unsigned char CheckWavFile()
{
FRESULT res;
FATFS fs; // File system object
FIL FileObject;
unsigned int numRead, pcmSize;
// Init Disk
printf("-I- Init media Sdcard\n\r");
MEDSdcard_Initialize(&medias[ID_DRV], MCI_ID);
// Mount disk
printf("-I- Mount disk %d\n\r", ID_DRV);
memset(&fs, 0, sizeof(FATFS)); // Clear file system object
res = f_mount(ID_DRV, &fs);
if( res != FR_OK ) {
printf("-E- f_mount pb: 0x%X (%s)\n\r", res, FF_GetStrResult(res));
return 0;
}
res = f_open(&FileObject, FileName, FA_OPEN_EXISTING|FA_READ);
if (res == FR_OK) {
printf("-I- File Found!\n\r");
//f_close(&FileObject);
// FilePlay();
}
else {
printf("-E- File Not Found!\n\r");
return 1;
}
// Read header
f_read(&FileObject, (void*)userWav, sizeof(WavHeader), &numRead);
DisplayWavInfo();
// Load PCM
pcmSize = userWav->subchunk2Size;
if (pcmSize > MAX_WAV_SIZE) {
pcmSize = MAX_WAV_SIZE;
}
f_read(&FileObject, (void*)WAV_FILE_ADDRESS, pcmSize, &numRead);
printf("-I- PCM Load to %x, size %d\n\r", WAV_FILE_ADDRESS, numRead);
f_close(&FileObject);
return 0;
}
//------------------------------------------------------------------------------
/// Main function
//------------------------------------------------------------------------------
int main(void)
{
unsigned char key;
unsigned char isValid;
// Configure all pins
PIO_Configure(pins, PIO_LISTSIZE(pins));
// Initialize the DBGU
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
// Initialize PSRAM
BOARD_ConfigurePsram();
// Switch to Main clock
AT91C_BASE_PMC->PMC_MCKR = (AT91C_BASE_PMC->PMC_MCKR & ~AT91C_PMC_CSS) | AT91C_PMC_CSS_MAIN_CLK;
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0);
// Configure PLL to 98.285MHz
*AT91C_CKGR_PLLR = ((1 << 29) | (171 << AT91C_CKGR_MUL_SHIFT) \
| (0x0 << AT91C_CKGR_OUT_SHIFT) |(0x3f << AT91C_CKGR_PLLCOUNT_SHIFT) \
| (21 << AT91C_CKGR_DIV_SHIFT));
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) == 0);
// Configure master clock in two operations
AT91C_BASE_PMC->PMC_MCKR = (( AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLLA_CLK) & ~AT91C_PMC_CSS) | AT91C_PMC_CSS_MAIN_CLK;
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0);
AT91C_BASE_PMC->PMC_MCKR = ( AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLLA_CLK);
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0);
// DBGU reconfiguration
DBGU_Configure(DBGU_STANDARD, 115200, SSC_MCK);
// Configure and enable the TWI (required for accessing the DAC)
*AT91C_PMC_PCER = (1<< AT91C_ID_TWI0);
TWI_ConfigureMaster(AT91C_BASE_TWI0, TWI_CLOCK, SSC_MCK);
TWID_Initialize(&twid, AT91C_BASE_TWI0);
// Enable the DAC master clock
AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLLA_CLK | AT91C_PMC_PRES_CLK_8;
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_PCKRDY0) == 0);
printf("-- Basic SSC I2S WM8731 Project %s --\n\r", SOFTPACK_VERSION);
printf("-- %s\n\r", BOARD_NAME);
printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
// Check and load wav file from sdcard
isValid = CheckWavFile();
if(isValid) {
printf("-E- Open wav file fail!\r\n");
return 1;
}
// Load WAV file information
isValid = WAV_IsValid(userWav);
ASSERT(isValid, "-F- Invalid WAV file provided\n\r");
isWavPlaying = 0;
// Sample rate must be 48kHz
printf("-I- Sample rate = %d Hz\n\r", userWav->sampleRate);
ASSERT(userWav->sampleRate == 48000, "-F- The WAV file must have a sample rate of 48kHz\n\r");
// Initialize the audio DAC
WM8731_DAC_Init(&twid, WM8731_SLAVE_ADDRESS);
// Configure SSC
SSC_Configure(AT91C_BASE_SSC0,
AT91C_ID_SSC0,
SAMPLE_RATE * BITS_BY_SLOT * 2,
SSC_MCK);
SSC_ConfigureReceiver(AT91C_BASE_SSC0, 0, 0);
SSC_ConfigureTransmitter(AT91C_BASE_SSC0,
AT91C_I2S_MASTER_TX_SETTING(BITS_BY_SLOT, SLOT_BY_FRAME),
AT91C_I2S_TX_FRAME_SETTING( BITS_BY_SLOT, SLOT_BY_FRAME));
SSC_DisableTransmitter(AT91C_BASE_SSC0);
#if defined(AUDIO_USING_DMA)
// Initialize DMA controller.
DMAD_Initialize(BOARD_SSC_DMA_CHANNEL, 0);
// Configure and enable the SSC interrupt
IRQ_ConfigureIT(AT91C_ID_HDMA, 0, HDMA_IrqHandler);
IRQ_EnableIT(AT91C_ID_HDMA);
#endif
// Enter menu loop
while (1) {
// Display menu
DisplayMenu();
// Process user input
key = DBGU_GetChar();
// Play WAV file
if ((key == 'W') && !isWavPlaying) {
PlayWavFile();
isWavPlaying = 1;
}
// Display WAV information
else if (key == 'I') {
DisplayWavInfo();
}
// Stop playback
else if ((key == 'S') && isWavPlaying) {
StopPlayback();
isWavPlaying = 0;
}
}
}

Binary file not shown.