SAMV71 Xplained Ultra Software Package 1.3

main.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2014, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 /**
00031  * \page ssc_dma_audio SSC with DMA Audio Example
00032  *
00033  * \section Purpose
00034  * 
00035  * This example uses the Synchronous Serial Controller (SSC) of an SAMV7x
00036  * microcontroller to output an audio stream through the on-board WM8904 CODEC.
00037  *
00038  * \section Requirements
00039  *
00040  * This package can be used with SAM V71 Xplained Ultra board with external 
00041  * codec WM8904 components.
00042  *
00043  * \section Description
00044  * This program plays a WAV file from PC via Line-In. The audio stream is
00045  * sent through the SSC interface connected to the on-board WM8904, enabling 
00046  * the sound to be audible using a pair of headphones.
00047  *
00048  * \section Usage
00049  *  -# Build the program and download it inside the SAM V71 Xplained Ultra board. 
00050  *     Please refer to the Getting Started with SAM V71 Microcontrollers.pdf
00051  * -# On the computer, open and configure a terminal application
00052  *    (e.g. HyperTerminal on Microsoft Windows) with these settings:
00053  *   - 115200 baud rate
00054  *   - 8 bits of data
00055  *   - No parity
00056  *   - 1 stop bit
00057  *   - No flow control
00058  * -# Start the application.
00059  * -# In the terminal window, the following text should appear:
00060  *    \code
00061  *     -- SSC DMA Audio Example xxx --
00062  *      -- SAMxxxxx-xx
00063  *     -- Compiled: xxx xx xxxx xx:xx:xx --
00064  *    \endcode
00065  * The user can then choose any of the available options to perform the 
00066  * described action.
00067  *
00068  * \section References
00069  * - ssc_dma_audio/main.c
00070  * - ssc.c
00071  * - twi.c
00072  * - twid.c
00073  * - xdmac.c
00074  * - xdmad.c
00075  */
00076 
00077 /**
00078  * \file
00079  *
00080  * This file contains all the specific code for the SSC audio example.
00081  */
00082 
00083 
00084 /*----------------------------------------------------------------------------
00085  *        Headers
00086  *----------------------------------------------------------------------------*/
00087 
00088 #include "board.h"
00089 
00090 /*----------------------------------------------------------------------------
00091  *        Local macros
00092  *----------------------------------------------------------------------------*/
00093 
00094 #define min( a, b ) (((a) < (b)) ? (a) : (b))
00095 
00096 /*----------------------------------------------------------------------------
00097  *        Local definitions
00098  *----------------------------------------------------------------------------*/
00099 #define I2S_SLAVE_TX_SETTING     ((SSC_TCMR_CKS_TK) |     \
00100             (SSC_TCMR_CKO_NONE) |                        \
00101             (SSC_TCMR_START_TF_EDGE) |                   \
00102             (SSC_TCMR_STTDLY(1)) |                       \
00103             (SSC_TCMR_PERIOD(0)))
00104 
00105 #define I2S_SLAVE_TX_FRM_SETTING ((SSC_TFMR_DATLEN(BITS_BY_SLOT - 1)) | \
00106             (SSC_TFMR_MSBF) |                                          \
00107             (SSC_TFMR_DATNB(SLOT_BY_FRAME - 1)) |                      \
00108             (SSC_TFMR_FSOS_NONE))
00109 
00110 
00111 #define I2S_SLAVE_RX_SETTING     ((SSC_RCMR_CKS_TK) |   \
00112             (SSC_RCMR_CKO_NONE) |                      \
00113             (SSC_RCMR_CKI) |                           \
00114             (SSC_RCMR_START_RF_EDGE) |                 \
00115             (SSC_RCMR_STTDLY(1)) |                     \
00116             (SSC_RCMR_PERIOD(0)))
00117 
00118 #define I2S_SLAVE_RX_FRM_SETTING ((SSC_RFMR_DATLEN(BITS_BY_SLOT - 1)) | \
00119             (SSC_RFMR_MSBF) |                                          \
00120             (SSC_RFMR_DATNB(SLOT_BY_FRAME - 1)) |                      \
00121             (SSC_RFMR_FSOS_NONE))
00122 
00123 
00124 /** Master clock frequency in Hz */
00125 #define SSC_MCK                 BOARD_MCK
00126 
00127 /** MAX size of the recorded sound */
00128 #define MAX_RECORD_SIZE         0xFFFFFFFF
00129 
00130 /** MAX size of one DMA transfer */
00131 #define MAX_DMA_SIZE            0x1000
00132 
00133 /** TWI clock */
00134 #define TWI_CLOCK               400000
00135 
00136 /** WAV feature. */
00137 #define SAMPLE_RATE             (48000)
00138 #define SLOT_BY_FRAME           (1)
00139 #define BITS_BY_SLOT            (16)
00140 
00141 /** DMA Descriptor */
00142 #define TOTAL_Buffers            4
00143 #define AUDIO_IF                SSC
00144 
00145 /*----------------------------------------------------------------------------
00146  *        Local variables
00147  *----------------------------------------------------------------------------*/
00148 
00149 /** List of pins to configure. */
00150 static const Pin pinsSsc[] = {PIN_TWI_TWD0, PIN_TWI_TWCK0, PIN_SSC_TD, 
00151             PIN_SSC_TK, PIN_SSC_TF, PIN_SSC_RD,  PIN_SSC_RK, PIN_SSC_RF, PIN_PCK2};
00152 
00153 /** Global DMA driver for all transfer */
00154 static sXdmad dmad;
00155 /** DMA channel for RX */
00156 static uint32_t sscDmaRxChannel;
00157 /** DMA channel for TX */
00158 static uint32_t sscDmaTxChannel;
00159 
00160 static sXdmadCfg xdmadCfg;
00161 
00162 static LinkedListDescriporView1 dmaWriteLinkList[TOTAL_Buffers];
00163 static LinkedListDescriporView1 dmaReadLinkList[TOTAL_Buffers];
00164 
00165 /** TWI instance*/
00166 static Twid twid;
00167 
00168 static uint16_t AudioBuffer[TOTAL_Buffers*MAX_DMA_SIZE * (BITS_BY_SLOT/8)];
00169 
00170 /*----------------------------------------------------------------------------
00171  *        Local functions
00172  *----------------------------------------------------------------------------*/
00173 
00174 /**
00175  * ISR for DMA interrupt
00176  */
00177 void XDMAC_Handler(void)
00178 {
00179     XDMAD_Handler(&dmad);
00180 }
00181 
00182 /**
00183  * \brief TWI interrupt handler. Forwards the interrupt to the TWI driver handler.
00184  */
00185 void TWIHS0_Handler(void )
00186 {
00187     TWID_Handler( &twid ) ;
00188 }
00189 
00190 /**
00191  * \brief DMA driver configuration
00192  */
00193 static void Dma_configure(void)
00194 {
00195     sXdmad *pDmad = &dmad;
00196     /* Driver initialize */
00197     XDMAD_Initialize( pDmad, 0 );
00198     /* Configure TWI interrupts */
00199     NVIC_ClearPendingIRQ(XDMAC_IRQn);
00200     NVIC_EnableIRQ(XDMAC_IRQn);
00201     /* Allocate DMA channels for SSC */
00202     sscDmaTxChannel = XDMAD_AllocateChannel( pDmad, XDMAD_TRANSFER_MEMORY, ID_SSC);
00203     sscDmaRxChannel = XDMAD_AllocateChannel( pDmad, ID_SSC, XDMAD_TRANSFER_MEMORY);
00204     if ( sscDmaTxChannel == XDMAD_ALLOC_FAILED 
00205             || sscDmaRxChannel == XDMAD_ALLOC_FAILED ) {
00206         printf("xDMA channel allocation error\n\r");
00207         while(1);
00208     }
00209     XDMAD_PrepareChannel(pDmad, sscDmaTxChannel );
00210     XDMAD_PrepareChannel(pDmad, sscDmaRxChannel );
00211 }
00212 
00213 
00214 /**
00215  * \brief Receive and play audio with DMA.
00216  */
00217 static void PlayRecording(void)
00218 {
00219     uint16_t *src;
00220     uint8_t i;
00221     uint32_t xdmaCndc;
00222 
00223     src = &AudioBuffer[0];
00224     for(i = 0; i < TOTAL_Buffers; i++) {
00225         dmaReadLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 
00226             | XDMA_UBC_NDE_FETCH_EN
00227             | XDMA_UBC_NSEN_UPDATED 
00228             | XDMAC_CUBC_UBLEN(MAX_DMA_SIZE);
00229         dmaReadLinkList[i].mbr_sa  = (uint32_t)&(AUDIO_IF->SSC_RHR);
00230         dmaReadLinkList[i].mbr_da = (uint32_t)(src );
00231         if ( i == (TOTAL_Buffers - 1)) {
00232             dmaReadLinkList[i].mbr_nda = (uint32_t)&dmaReadLinkList[0];
00233         } else {
00234             dmaReadLinkList[i].mbr_nda = (uint32_t)&dmaReadLinkList[i + 1];
00235         }
00236         src += MAX_DMA_SIZE ;
00237     }
00238 
00239     xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN 
00240         | XDMAC_CC_MBSIZE_SINGLE 
00241         | XDMAC_CC_DSYNC_PER2MEM 
00242         | XDMAC_CC_CSIZE_CHK_1 
00243         | XDMAC_CC_DWIDTH_HALFWORD
00244         | XDMAC_CC_SIF_AHB_IF1 
00245         | XDMAC_CC_DIF_AHB_IF0 
00246         | XDMAC_CC_SAM_FIXED_AM 
00247         | XDMAC_CC_DAM_INCREMENTED_AM 
00248         | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_SSC, XDMAD_TRANSFER_RX ));
00249     xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 
00250         | XDMAC_CNDC_NDE_DSCR_FETCH_EN 
00251         | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
00252         | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ;
00253     
00254     memory_sync();
00255     XDMAD_ConfigureTransfer( &dmad, sscDmaRxChannel, &xdmadCfg, xdmaCndc,
00256             (uint32_t)&dmaReadLinkList[0],XDMAC_CIE_LIE);
00257     
00258     
00259     src = &AudioBuffer[0];
00260     for(i = 0; i < TOTAL_Buffers; i++) {
00261         dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1 
00262             | XDMA_UBC_NDE_FETCH_EN
00263             | XDMA_UBC_NSEN_UPDATED
00264             | XDMAC_CUBC_UBLEN(MAX_DMA_SIZE);
00265         dmaWriteLinkList[i].mbr_sa = (uint32_t)(src );
00266         dmaWriteLinkList[i].mbr_da = (uint32_t)&(AUDIO_IF->SSC_THR);
00267         if ( i == (TOTAL_Buffers - 1 )) {
00268             dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0];
00269         } else {
00270             dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i+1];
00271         }
00272         src += MAX_DMA_SIZE;
00273     }
00274 
00275     xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN 
00276         | XDMAC_CC_MBSIZE_SINGLE 
00277         | XDMAC_CC_DSYNC_MEM2PER 
00278         | XDMAC_CC_CSIZE_CHK_1 
00279         | XDMAC_CC_DWIDTH_HALFWORD
00280         | XDMAC_CC_SIF_AHB_IF0 
00281         | XDMAC_CC_DIF_AHB_IF1 
00282         | XDMAC_CC_SAM_INCREMENTED_AM 
00283         | XDMAC_CC_DAM_FIXED_AM 
00284         | XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(ID_SSC, XDMAD_TRANSFER_TX ));
00285     xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1 
00286         | XDMAC_CNDC_NDE_DSCR_FETCH_EN 
00287         | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
00288         | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED ;
00289     
00290     memory_sync();
00291     XDMAD_ConfigureTransfer( &dmad, sscDmaTxChannel, &xdmadCfg, xdmaCndc, 
00292             (uint32_t)&dmaWriteLinkList[0],XDMAC_CIE_LIE);
00293     
00294     SSC_EnableReceiver(AUDIO_IF);
00295     SCB_CleanInvalidateDCache();
00296     XDMAD_StartTransfer( &dmad, sscDmaRxChannel );
00297     
00298 
00299     Wait(300);
00300     /* Enable playback(SSC TX) */
00301     SSC_EnableTransmitter(AUDIO_IF);
00302     SCB_CleanInvalidateDCache();
00303     XDMAD_StartTransfer( &dmad, sscDmaTxChannel);
00304     
00305 }
00306 
00307 /*----------------------------------------------------------------------------
00308  *         Global functions
00309  *----------------------------------------------------------------------------*/
00310 /**
00311  * \brief Application entry point for ssc_dam_audio example.
00312  *
00313  * \return Unused (ANSI-C compatibility).
00314  */
00315 int main( void )
00316 {    
00317     uint16_t data = 0;
00318     /* Disable watchdog */
00319     WDT_Disable( WDT ) ;
00320  
00321     /* Enable I and D cache */
00322     SCB_EnableICache();
00323     SCB_EnableDCache();
00324 
00325     /* Output example information */
00326     printf("-- SSC DMA Audio Example %s --\n\r", SOFTPACK_VERSION);
00327     printf("-- %s\n\r", BOARD_NAME);
00328     printf( "-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ;
00329 
00330     /* Configure systick for 1 ms. */
00331     printf( "Configure system tick to get 1ms tick period.\n\r" ) ;
00332     if ( TimeTick_Configure( ) )
00333     {
00334         printf("-F- Systick configuration error\n\r" ) ;
00335     }
00336 
00337     /* Configure all pins */
00338     PIO_Configure(pinsSsc, PIO_LISTSIZE(pinsSsc));
00339 
00340     /* Configure SSC */
00341     SSC_Configure(AUDIO_IF , 0 , SSC_MCK );
00342     SSC_ConfigureReceiver(AUDIO_IF,I2S_SLAVE_RX_SETTING,I2S_SLAVE_RX_FRM_SETTING);
00343     SSC_DisableReceiver(AUDIO_IF);
00344     SSC_ConfigureTransmitter(AUDIO_IF,I2S_SLAVE_TX_SETTING,I2S_SLAVE_TX_FRM_SETTING);
00345     SSC_DisableTransmitter(AUDIO_IF);
00346 
00347     /* Configure DMA */
00348     Dma_configure();
00349 
00350     /* Configure and enable the TWI (required for accessing the DAC) */
00351     PMC_EnablePeripheral(ID_TWIHS0);
00352     TWI_ConfigureMaster(TWIHS0, TWI_CLOCK, BOARD_MCK);
00353     TWID_Initialize(&twid, TWIHS0);
00354     /* Configure TWI interrupts */
00355     NVIC_ClearPendingIRQ(TWIHS0_IRQn);
00356     NVIC_EnableIRQ(TWIHS0_IRQn);
00357 
00358     /* check that WM8904 is present */
00359     WM8904_Write(&twid, WM8904_SLAVE_ADDRESS, 22, 0);
00360     data=WM8904_Read(&twid, WM8904_SLAVE_ADDRESS, 0);
00361     if( data != 0x8904) {
00362         printf("WM8904 not found!\n\r");
00363         while(1);
00364     }
00365     /* Initialize the audio DAC */
00366     WM8904_Init(&twid, WM8904_SLAVE_ADDRESS, PMC_MCKR_CSS_SLOW_CLK); 
00367 
00368     /* Enable the DAC master clock */
00369     PMC_ConfigurePCK2(PMC_MCKR_CSS_SLOW_CLK, PMC_MCKR_PRES_CLK_1 );
00370     printf("Insert Line-in cable with PC Headphone output\n\r" );
00371     PlayRecording();
00372     while ( 1 );
00373 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines