Step 4.1: Replace main.c with audio_sine_tone.c
1
The audio_sine_tone.c file is included in the ZIP file you downloaded. Under the Solution Explorer > audio_sine_tone_lab > src folder, add this file by right clicking and selecting Add > Existing Item….
Locate the source file to be added by navigating to the folder audio_sine_tone/audio_sine_tone_lab/dev_files
Step 4.2: Implement SSC configuration
In the source file audio_sine_tone.c, locate the function configure_ssc. As the name would suggest, this file configures the SSC (for I2S). The following steps discuss this function.
3
When the SAM V71 is acting as I2S slave, Setup the transmission parameters of SSC as follows.
- When the SAM V71 is acting as I2S slave, The Macro PCK2 is set to value PMC_MCKR_CSS_SLOW_CLK
- The value of Macro PCK2 indicates the reference clock given to the audio codec WM8904. When PCK2 is PMC_MCKR_CSS_SLOW_CLK, it indicates that a slow clock of 32768 Hz is provided as a reference to the audio codec WM8904.
The Transmitter Clock Mode (numbers 1-7) and Transmitter Frame Mode (numbers 8-14) configurations are set as follows. The following numbers refer to those found in Figure_SSC1 below.
- The Clock source CKS to the SSC peripheral is the TK signal from the master (audio codec WM8904).
- The Clock Output mode CKO is set to 0, indicating that no TK signal is generated by SSC. Instead, SSC receives TK signal from the master (audio codec WM8904).
- The Transmit clock inversion CKI is set to 0, indicating that the data is shifted out on the falling edge of the input TK signal.
- The Transmit clock gating CKG is set to 0, indicating that no gating for input TK signal, it is always enabled.
- The Transmit start selection START is set to 7, indicating that the data transmission is started on the detection of an edge.
- The Transmit start delay STTDLY is set to 1, indicating that 1 clock cycle delay is inserted before transmission could start (corresponds to I2S protocol).
- The Transmit period divider selection PERIOD is set to 15 (Bit width(16) – 1), so that a frame length (Left and right Channels) of 32-bit width is achieved.
- The Data length DATLEN is set to 15 so that DATLEN+1 corresponds to the word length (16 bits).
- The Most significant bit first MSBF of the data is sent first.
- The number of data bytes DATNB is set to 0. DATNB+1 are the number of words (of size DATLEN+1) per frame.
- The transmit frame sync length FSLEN is set to 15. FSLEN+1 clock cycles is the length of each frame sync pulse.
- The transmit frame sync length FSLEN extended is set to 0 (disabled).
- The transmit frame sync output FSOS is disabled.
- The transmit frame sync edge FSEDGE is enabled for the positive edge.
Figure_SSC1: SSC configuration when SAM V71 is slave
4
When the SAM V71 is acting as I2S master, set up the transmission parameters of SSC as follows.
- When the SAM V71 is acting as I2S master, The Macro PCK2 is set to value PMC_MCKR_CSS_MAIN_CLK
- The value of Macro PCK2 indicates the reference clock given to the audio codec WM8904. When PCK2 is PMC_MCKR_CSS_MAIN_CLK, it indicates that main clock of 12 MHz is provided as a reference to the audio codec WM8904.
Below is the pictorial representation of SSC clock divider to achieve the desired output clock.
The Clock Mode register SSC_CMR configuration is set to value 39 by calling the API ssc_set_clock_divider. The value 39 is arrived based on the following deductions.
In the master mode of operations, when the SSC is interfaced with an I2S device, the Transmit Clock (TK) signal corresponds to the bit rate for the desired audio data.
I2S bitrate = Number of bits per Channel x Number of Channels x Sampling Frequency.
In this application, The following macros define the values to the birate computation parameters
- BITS_BY_SLOT (Number of bits per Channel) = 16
- SLOT_BY_FRAME (Number of Channels) = 2
- SAMPLE_RATE (Sampling Frequency) = 48000 Hz
- I2S bitrate =16 x 2 x 48000 = 1536000 Hz.
Therefore, SSC needs to produce a Transmit clock (TK) of 1536000 Hz. To generate the required TK, the SSC peripheral provides an option to divide its peripheral clock by an integer factor. The peripheral clock to the SSC is denoted by MCK.
Integer Factor Divisor => MCK/TK
In this application, the macro INPUT_MCK_TO_SSC (defined as 120000000) represents MCK (SSC input peripheral clock) frequency.
Integer Factor Divisor => 120000000/1536000 => 78.12 (~78)
By default, SSC divides the input clock by two. Therefore, the factor to be programmed in the SSC_CMR is 39.
The Transmitter Clock Mode (numbers 2-8) and Transmitter Frame Mode (numbers 9-15) configurations are set as follows. The following numbers refer to those found in Figure_SSC2 below.
- ssc_set_clock_divider function.
- The clock source CKS to the SSC peripheral is the peripheral divided clock (MCK) so that SSC is the I2S master.
- The clock Output mode CKO is set to 1, indicating a Continuous TK clock so as to toggle. SSC provides TK signal to the client (audio codec WM8904).
- The transmit clock inversion CKI is set to 0, indicating that the data is shifted out on the falling edge of the TK signal.
- The transmit clock gating CKG is set to 0, indicating that no gating for TK signal, it is always enabled.
- The transmit start selection START is set to 7, indicating that the data transmission is started on the detection of an edge.
- The transmit start delay STTDLY is set to 1, indicating that 1 clock cycle delay is inserted before transmission could start (corresponds to I2S protocol).
- The transmit period divider selection PERIOD is set to 15 (Bit width(16) – 1), so that frame length (Left and right Channels) of 32-bit width is achieved.
- The data length DATLEN is set to 15 so that DATLEN+1 corresponds to the word length (16 bits).
- The most significant bit first MSBF of the data is sent first.
- The number of data bytes DATNB is set to 1. DATNB+1 are the number of words (of size DATLEN+1) per frame.
- The transmit frame sync length FSLEN is set to 15. FSLEN+1 clock cycles is the length of each frame sync pulse.
- The transmit frame sync length FSLEN extended is set to 0 (disabled).
- The transmit frame sync output FSOS is enabled on the negative TK pulse.
- The transmit frame sync edge FSEDGE is enabled for the positive edge.
Figure_SSC2: SSC configuration when SAM V71 is master
Step 4.3: Implement XDMAC configuration
In the source file audio_sine_tone.c, locate the function configure_xdma that configures XDMAC. The following steps discuss the implemetation of function configure_xdma.
2
Initialize the XDMAC transfer channel (Identified by macro XDMA_CH_SSC_TX) as follows. The following numbers refer to those found in Figure_XDMAC below.
- The Type TYPE of data transfer is set to memory to peripheral transfer as the data source is the address of a memory buffer (a lookup table of sine tone data), and the destination is the transmit holding the register of SSC peripheral.
- The memory burst size MBSIZE is set to 1, indicating a burst of 1 word length (corresponding to the width of SSC transmit register) is transferred every transaction.
- The channel synchronization DSYNC is set to 1 as the transfer TYPE is from memory to peripheral.
- The chunk CSIZE is set to 1, similar to the MSIZE.
- The size of each data word DWIDTH is set to 16, corresponding to the audio data width.
- The source identifier SIF for the transfer channel is set to 0 as the internal memory lies on the system bus interface 0.
- The destination identifier DIF for the transfer channel is set to 1 as the peripheral SSC lies on the system bus interface 1.
- The source address mode SAM is set to incrementing as the source address increments for every data word transfer.
- The destination address mode DAM is set to a fixed value as the destination source address (SSC_THR) remains same across transfers.
- The peripheral identification PERID is set to 32, corresponding to the ID of SSC peripheral.
Figure_XDMAC: XDMAC Configuration
4
Build an XDMAC circular linked list of two transfer descriptors with view 1 structure. The view 1 structure descriptor contains 4 members.
- MBR_NDA: Next Descriptor Address Member
- MBR_SA: Source Address Member
- MBR_DA: Destination Address Member
- MBR_UBC: Microblock Control Member
MBR_UBC contains the following fields
- UBLEN: This field indicates the number of data (bytes or half words or words) in the microblock.
- NDE: Next Descriptor Enable
- NSEN: Next Descriptor Source Update
- NDEN: Next Descriptor Destination Update
- NVIEW: Next Descriptor View
First Descriptor
- MBR_NDA: Points to the Second Descriptor
- MBR_SA: Address of the audio tone buffer AudioBuffer
- MBR_DA: Address of the SSC Transmit holding register
- MBR_UBC
- UBLEN: 240 (Size of the audio tone buffer AudioBuffer in 16 bit words)
- NDE: 1 (Enabled)
- NSEN: 1 (Channel source address is updated from MBR_SA)
- NDEN: 0 (Channel destination address is not updated from MBR_DA)
- NVIEW: 1 (View 1 structure)
Second Descriptor
- MBR_NDA: Points to the First Descriptor
- MBR_SA: Address of the audio tone buffer AudioBuffer
- MBR_DA: Address of the SSC transmit holding register
- MBR_UBC
- UBLEN: 240 (Size of the audio tone buffer AudioBuffer in 16 bit words)
- NDE: 1 (Enabled)
- NSEN: 1 (Channel source address is updated from MBR_SA)
- NDEN: 0 (Channel destination address is not updated from MBR_DA)
- NVIEW: 1 (View 1 structure)
- The channel source address XDMAC_CSAx is incremented for every burst size (due to the setting SAM in XDMAC_CCx). At the end of the last transfer, the channel source address XDMAC_CSAx would be pointing to the end of audio tone buffer AudioBuffer. This has to be reset to point to the start of audio tone buffer AudioBuffer so that the next transfer fetches data from the start of the buffer. When NSEN is made 1 the channel source address XDMAC_CSAx is updated from the MBR_SA of the next descriptor.
- The channel destination address(XDMAC_CDAx) is fixed (due to the setting DAM in XDMAC_CCx). At the end of the last transfer, the channel destination address (XDMAC_CDAx) is pointing to the correct SSC transmit holding register. Therefore NDEN is made 0 and the Channel destination address XDMAC_CDAx is not updated from the MBR_DA of the next descriptor.
5
Enable the linked list by updating the next descriptor control XDMAC_CNDC and address XDMAC_CNDA registers with first descriptor of the linked list implemented above.

In the API xdmac_channel_set_descriptor_control the parameters
- XDMAC_CNDC_NDVIEW_NDV1 specifies view 1 as view structure of the first descriptor of the linked list.
- XDMAC_CNDC_NDE_DSCR_FETCH_EN enables the first descriptor of the linked list.
- XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED updates the channel source address with the MBR_SA of the first descriptor.
- XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED updates the destination source address with the MBR_DA of the first descriptor.
Note that for the first time, when the linked list is created, both, the channel source and destination registers are updated with the values from MBR_SA and MBR_DA respectively.
The API xdmac_channel_set_descriptor_addr sets the address of the first descriptor as the next descriptor address to be fetched.
6
- Enable the XDMAC channel interrupt for the chosen transmit channel XDMA_CH_SSC_TX by calling the API xdmac_enable_interrupt.
- Enable End of Linked List interrupt on the XDMAC transmit channel XDMA_CH_SSC_TX by calling the API xdmac_channel_enable_interrupt.
- Set the XDMAC interrupt priority and enable XDMAC interrupt at the nested vectored interrupt controller (NVIC) by calling the APIs NVIC_SetPriority and NVIC_EnableIRQ
Step 4.4: Implement audio codec WM8904 configuration
In this application, the interface between SAM V71 and audio codec WM8904 is I2S. SAM V71 acts as I2S master or slave depending on the value of configuration macro PCK2.
When SAM V71 is acting as I2S master (audio codec WM8904 acts as I2S slave), it generates the BCLK (TK) and LRCK (TF) clocks.
When SAM V71 is acting as I2S slave (audio codec WM8904 acts as I2S master), audio codec WM8904 generates the BCLK (TK) and LRCK (TF) clocks.
The following figure shows the I2S interface when the SAM V71 is the master.
The following figure shows the I2S interface when the SAM V71 is the slave.
In the source file audio_sine_tone.c, locate the function configure_codec having the implementation to configure audio codec WM8904. The following steps discuss the implemetation of function configure_codec.
2
When the SAM V71 is acting as the I2S slave, The codec WM8904 is configured to operate as I2S master as below.
- When the SAM V71 is acting as the I2S slave, The Macro PCK2 is set to value PMC_MCKR_CSS_SLOW_CLK
- The value of Macro PCK2 indicates the reference clock given to the audio codec WM8904. When PCK2 is PMC_MCKR_CSS_SLOW_CLK, it indicates that a slow clock of 32768 Hz is provided as a reference to the audio codec WM8904.
The following figure shows the code that configures the codec.
- Section A generates and drives the bit clock BCLK and sampling clock LRCK using its internal PLL.
- Section B sets the clock and sampling rate.
- Section C sets the audio data format, word length and left/right channel.
Figure_CODEC1: Codec configuration when SAM V71 is slave
Each of these code sections is described in detail below.
A
When codec WM8904 is acting as I2S master, It generates the BCLK, fed as TK input to SSC and it also generates the LRCK, fed as TF to SSC.
Codec WM8904 has an internal Frequency Locked Loop FLL that generates the required BCLK and LRCK based on the input reference clock.
The FLL output frequency is generated according to the following equation
FOUT = (FVCO / FLL_OUTDIV)
The FLL operating frequency, FVCO is set according to the following equation
FVCO = (FREF x N.K x FLL_FRATIO)
FVCO must be in the range 90-100 MHz. Frequencies outside this range are not supported.
In order to follow the above requirements for FVCO, the value of FLL_OUTDIV is selected according to the desired output FOUT. The divider, FLL_OUTDIV, is set such that FVCO is in the range 90-100MHz. The available divisions are integers from 4 to 64. Some typical settings of FLL_OUTDIV are noted in the following table.
FLL_OUT
FLL_RATIO
Based on the above substitutions of FLL_RATIO and FLL_OUTDIV, the values of FLL_N and FLL_K are determined as
N.K = FVCO / (FLL_FRATIO x FREF)
In FLL Fractional Mode, the fractional portion of the N.K multiplier is held in the FLL_K register field. This field is coded as a fixed point quantity, where the MSB has a weighting of 0.5. When required, the value of this field may be calculated by multiplying K by 216 and treating FLL_K as an integer value, as illustrated in the following example:
If N.K = 8.192, then K = 0.192
Multiplying K by 216 gives 0.192 x 65536 = 12582.912 (decimal)
Apply rounding to the nearest integer = 12583 (decimal) = 3127 (hex)
FLL CALCULATION
- Set FLL_OUTDIV for the required output frequency as shown in table FLL_OUT above
- FOUT = 12.288 MHz, therefore FLL_OUTDIV = 07h (divide by 8)
- Set FLL_FRATIO for the given reference frequency as shown in table FLL_RATIO above
- FREF = 12MHz, therefore FLL_FRATIO = 0h (divide by 1)
- Calculate FVCO as given by FVCO = FOUT x FLL_OUTDIV:
- FVCO = 12.288 x 8 = 98.304 MHz
- Calculate N.K as given by N.K = FVCO / (FLL_FRATIO x FREF):
- N.K = 98.304 / (16 x 0.032768) = 187.5
- Determine FLL_N and FLL_K from the integer and fractional portions of N.K:
- FLL_N is 187. FLL_K is 0.5
- Confirm that N.K is a fractional quantity and set FLL_FRACN_ENA:
- N.K is fractional. Set FLL_FRACN_ENA = 1.
The following summarizes the FLL settings to generate the required clocks BCLK and LRCK
The above settings are configured by calling the API wm8904_write_register marked as A in Figure_CODEC1.
B
Codec WM8904 supports automatic clock configuration of the ADCs, DACs, DC servo and DSP core functions with the values determined by codec system clock (SYSCLK) and sampling rate. In the following table, the configuration registers (and related fields) are used to configure the SYSCLK and sampling rate.
The above settings are configured by calling the API wm8904_write_register marked as B in Figure_CODEC1.
3
When the SAM V71 is acting as I2S master, The codec WM8904 is configured to operate as I2S slave.
- When the SAM V71 is acting as I2S master, the Macro PCK2 is set to value PMC_MCKR_CSS_MAIN_CLK
- The value of Macro PCK2 indicates the reference clock given to the audio codec WM8904. When PCK2 is PMC_MCKR_CSS_MAIN_CLK, it indicates that main clock of 12 MHz is provided as a reference to the audio codec WM8904.
The following figure shows the code that configures the codec.
- Since the BCLK and LRCK are generated by SAM V71, the internal PLL of WM8904 is not enabled.
- Section A sets the clock and sampling rate.
- Section B sets the audio data format, word length and left/right channel.
Figure_CODEC2: CODEC configuration when SAM V71 is master
Each of these code sections is described in detail below.
A
Codec WM8904 supports automatic clocking configuration of the ADCs, DACs, DC servo and DSP core functions with the values determined by codec system clock (SYSCLK) and sampling rate. In the following table, the configuration registers (and related fields) are used to configure the SYSCLK and sampling rate.
The above settings are configured by calling the API wm8904_write_register marked as A in Figure_CODEC2 .