ssc_i2s.h File Reference


Detailed Description

SSC I2S example driver.

This file defines a useful set of functions for the SSC I2S interface on AVR32 devices. The driver handles normal polled usage and direct memory access (PDC) usage.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file ssc_i2s.h.

#include <avr32/io.h>

Go to the source code of this file.

Defines

#define SSC_I2S_TIMEOUT_VALUE   10000

Enumerations

enum  {
  SSC_I2S_ERROR = -1, SSC_I2S_OK = 0, SSC_I2S_TIMEOUT = 1, SSC_I2S_ERROR_ARGUMENT,
  SSC_I2S_ERROR_RX, SSC_I2S_ERROR_TX
}
 Error codes used by SSC I2S driver. More...
enum  {
  SSC_I2S_MODE_STEREO_OUT = 1, SSC_I2S_MODE_STEREO_OUT_EXT_CLK, SSC_I2S_MODE_SLAVE_STEREO_OUT, SSC_I2S_MODE_STEREO_OUT_MONO_IN,
  SSC_I2S_MODE_RIGHT_IN, SSC_I2S_MODE_STEREO_IN, SSC_I2S_MODE_STEREO_OUT_STEREO_IN
}
 SSC I2S modes. More...

Functions

void ssc_i2s_disable_interrupts (volatile avr32_ssc_t *ssc, unsigned long int_mask)
 Disables the specified SSC interrupts.
void ssc_i2s_enable_interrupts (volatile avr32_ssc_t *ssc, unsigned long int_mask)
 Enables the specified SSC interrupts.
unsigned long ssc_i2s_get_status (volatile avr32_ssc_t *ssc)
 Returns the SSC status.
int ssc_i2s_init (volatile avr32_ssc_t *ssc, unsigned int sample_frequency, unsigned int data_bit_res, unsigned int frame_bit_res, unsigned char mode, unsigned int pba_hz)
 Sets up registers and intializes SSC for use as I2S.
void ssc_i2s_reset (volatile avr32_ssc_t *ssc)
 Resets the SSC module.
int ssc_i2s_transfer (volatile avr32_ssc_t *ssc, unsigned int data)
 Transfers a single message of data.


Define Documentation

#define SSC_I2S_TIMEOUT_VALUE   10000

Definition at line 56 of file ssc_i2s.h.

Referenced by ssc_i2s_transfer().


Enumeration Type Documentation

anonymous enum

Error codes used by SSC I2S driver.

Enumerator:
SSC_I2S_ERROR 
SSC_I2S_OK 
SSC_I2S_TIMEOUT 
SSC_I2S_ERROR_ARGUMENT 
SSC_I2S_ERROR_RX 
SSC_I2S_ERROR_TX 

Definition at line 68 of file ssc_i2s.h.

00069 {
00070   SSC_I2S_ERROR = -1,
00071   SSC_I2S_OK = 0,
00072   SSC_I2S_TIMEOUT = 1,
00073   SSC_I2S_ERROR_ARGUMENT,
00074   SSC_I2S_ERROR_RX,
00075   SSC_I2S_ERROR_TX
00076 };

anonymous enum

SSC I2S modes.

Enumerator:
SSC_I2S_MODE_STEREO_OUT 
SSC_I2S_MODE_STEREO_OUT_EXT_CLK 
SSC_I2S_MODE_SLAVE_STEREO_OUT 
SSC_I2S_MODE_STEREO_OUT_MONO_IN 
SSC_I2S_MODE_RIGHT_IN 
SSC_I2S_MODE_STEREO_IN 
SSC_I2S_MODE_STEREO_OUT_STEREO_IN 

Definition at line 79 of file ssc_i2s.h.


Function Documentation

void ssc_i2s_disable_interrupts ( volatile avr32_ssc_t *  ssc,
unsigned long  int_mask 
)

Disables the specified SSC interrupts.

Parameters:
ssc Base address of the SSC instance.
int_mask Bit-mask of SSC interrupts (AVR32_SSC_IDR_x_MASK).

Definition at line 342 of file ssc_i2s.c.

00343 {
00344   Bool global_interrupt_enabled = Is_global_interrupt_enabled();
00345 
00346   if (global_interrupt_enabled) Disable_global_interrupt();
00347   ssc->idr = int_mask;
00348   ssc->sr;
00349   if (global_interrupt_enabled) Enable_global_interrupt();
00350 }

void ssc_i2s_enable_interrupts ( volatile avr32_ssc_t *  ssc,
unsigned long  int_mask 
)

Enables the specified SSC interrupts.

Parameters:
ssc Base address of the SSC instance.
int_mask Bit-mask of SSC interrupts (AVR32_SSC_IER_x_MASK).

Definition at line 353 of file ssc_i2s.c.

00354 {
00355   ssc->ier = int_mask;
00356 }

unsigned long ssc_i2s_get_status ( volatile avr32_ssc_t *  ssc  ) 

Returns the SSC status.

Parameters:
ssc Base address of the SSC instance.
Returns:
The SSC Status Register.

Definition at line 359 of file ssc_i2s.c.

Referenced by main().

00360 {
00361   return ssc->sr;
00362 }

int ssc_i2s_init ( volatile avr32_ssc_t *  ssc,
unsigned int  sample_frequency,
unsigned int  data_bit_res,
unsigned int  frame_bit_res,
unsigned char  mode,
unsigned int  pba_hz 
)

Sets up registers and intializes SSC for use as I2S.

Parameters:
ssc Pointer to the correct volatile avr32_ssc_t struct
sample_frequency The sample frequency given in Hz
data_bit_res Number of significant data bits in an I2S channel frame
frame_bit_res Total number of bits in an I2S channel frame
mode I2S-mode
  • SSC_I2S_MODE_STEREO_OUT Two output channels.
  • SSC_I2S_MODE_STEREO_OUT_EXT_CLK Two output channels sampled with an external clock received from the SSC_RX_CLOCK line.
  • SSC_I2S_MODE_SLAVE_STEREO_OUT Two output channels controlled by the DAC.
  • SSC_I2S_MODE_STEREO_OUT_MONO_IN Two output, one input channel.
  • SSC_I2S_MODE_RIGHT_IN. Right channel in. Used because one SSC only can manage one input channel at a time.
pba_hz The clock speed of the PBA bus in Hz.
Returns:
Status
Return values:
SSC_I2S_OK when no error occured.
SSC_I2S_ERROR_ARGUMENT when invalid arguments are passed

Todo:
check input values

Definition at line 89 of file ssc_i2s.c.

References set_clock_divider(), SSC_I2S_MODE_RIGHT_IN, SSC_I2S_MODE_SLAVE_STEREO_OUT, SSC_I2S_MODE_STEREO_OUT, SSC_I2S_MODE_STEREO_OUT_EXT_CLK, SSC_I2S_MODE_STEREO_OUT_MONO_IN, SSC_I2S_OK, and ssc_i2s_reset().

Referenced by main().

00095 { 
00097 
00098   /* Reset */
00099   ssc_i2s_reset(ssc);
00100 
00101   if (mode == SSC_I2S_MODE_SLAVE_STEREO_OUT)
00102   {
00103     ssc->cmr = AVR32_SSC_CMR_DIV_NOT_ACTIVE << AVR32_SSC_CMR_DIV_OFFSET;
00104 
00105     ssc->tcmr = AVR32_SSC_TCMR_CKS_TK_PIN               << AVR32_SSC_TCMR_CKS_OFFSET    |
00106                 AVR32_SSC_TCMR_CKO_INPUT_ONLY           << AVR32_SSC_TCMR_CKO_OFFSET    |
00107                 0                                       << AVR32_SSC_TCMR_CKI_OFFSET    |
00108                 AVR32_SSC_TCMR_CKG_NONE                 << AVR32_SSC_TCMR_CKG_OFFSET    |
00109                 AVR32_SSC_TCMR_START_DETECT_ANY_EDGE_TF << AVR32_SSC_TCMR_START_OFFSET  |
00110                 1                                       << AVR32_SSC_TCMR_STTDLY_OFFSET |
00111                 0                                       << AVR32_SSC_TCMR_PERIOD_OFFSET;
00112 #ifdef AVR32_SSC_220_H_INCLUDED
00113     ssc->tfmr = (data_bit_res - 1)             << AVR32_SSC_TFMR_DATLEN_OFFSET  |
00114                 0                              << AVR32_SSC_TFMR_DATDEF_OFFSET  |
00115                 1                              << AVR32_SSC_TFMR_MSBF_OFFSET    |
00116                 (1 - 1)                        << AVR32_SSC_TFMR_DATNB_OFFSET   |
00117                 0                              << AVR32_SSC_TFMR_FSLEN_OFFSET   |
00118                 AVR32_SSC_TFMR_FSOS_INPUT_ONLY << AVR32_SSC_TFMR_FSOS_OFFSET    |
00119                 0                              << AVR32_SSC_TFMR_FSDEN_OFFSET   |
00120                 0                              << AVR32_SSC_TFMR_FSEDGE_OFFSET;
00121 #else
00122     ssc->tfmr = (data_bit_res - 1)             << AVR32_SSC_TFMR_DATLEN_OFFSET  |
00123                 0                              << AVR32_SSC_TFMR_DATDEF_OFFSET  |
00124                 1                              << AVR32_SSC_TFMR_MSBF_OFFSET    |
00125                 (1 - 1)                        << AVR32_SSC_TFMR_DATNB_OFFSET   |
00126                 0                              << AVR32_SSC_TFMR_FSLEN_OFFSET   |
00127                 AVR32_SSC_TFMR_FSOS_INPUT_ONLY << AVR32_SSC_TFMR_FSOS_OFFSET    |
00128                 0                              << AVR32_SSC_TFMR_FSDEN_OFFSET   |
00129                 0                              << AVR32_SSC_TFMR_FSEDGE_OFFSET  |
00130                 0                              << AVR32_SSC_TFMR_FSLENHI_OFFSET;
00131 #endif
00132     ssc->cr = AVR32_SSC_CR_TXEN_MASK;
00133   }
00134   else
00135   {
00136     unsigned long txen_mask = 0x00000000,
00137                   rxen_mask = 0x00000000;
00138 
00139     if (mode != SSC_I2S_MODE_STEREO_OUT_EXT_CLK)
00140     {
00141       /* Set clock divider */
00142       set_clock_divider(ssc, 2 * sample_frequency * frame_bit_res, pba_hz);
00143     }
00144 
00145     /* SSC can only receive one channel of audio input.  In order
00146      * to use two inputs, two SSC's must be used. The first (master)
00147      * deals with both output channels and the left input, and should
00148      * be set to mode=I2S_STEREO_OUT_MONO_IN, and the second to
00149      * mode=I2S_RIGHT_IN. The second SSC should be connected to the
00150      * first SSC's in the following way:
00151      * master-ssc:TF -> slave-ssc:RF,
00152      * master-ssc:TK -> slave-ssc:RK
00153      */
00154 
00155     /* If only slave I2S SSC, do not set transmit registers */
00156     if (mode != SSC_I2S_MODE_RIGHT_IN)
00157     {
00158       if (mode != SSC_I2S_MODE_STEREO_OUT_EXT_CLK)
00159       {
00160         /* Set transmit clock mode:
00161          *   CKS - use divided clock,
00162          *   CKO - transmit continous clock on TK
00163          *   CKI - shift data on falling clock
00164          *   CKG - transmit continous clock on TK
00165          *   START - on falling TF(WS) edge
00166          *   STTDLY - TF toggles before last bit of last word, not before
00167          *            first bit on next word. Therefore: delay one cycle.
00168          *   PERIOD - generate framesync for each sample (FS is generated
00169          *            every (PERIOD + 1) * 2 clock)
00170          */
00171         ssc->tcmr = AVR32_SSC_TCMR_CKS_DIV_CLOCK              << AVR32_SSC_TCMR_CKS_OFFSET    |
00172                     AVR32_SSC_TCMR_CKO_CONTINOUS_CLOCK_OUTPUT << AVR32_SSC_TCMR_CKO_OFFSET    |
00173                     0                                         << AVR32_SSC_TCMR_CKI_OFFSET    |
00174                     AVR32_SSC_TCMR_CKG_NONE                   << AVR32_SSC_TCMR_CKG_OFFSET    |
00175                     AVR32_SSC_TCMR_START_DETECT_ANY_EDGE_TF   << AVR32_SSC_TCMR_START_OFFSET  |
00176                     1                                         << AVR32_SSC_TCMR_STTDLY_OFFSET |
00177                     (frame_bit_res - 1)                       << AVR32_SSC_TCMR_PERIOD_OFFSET;
00178       }
00179       else
00180       {
00181         /* Set transmit clock mode:
00182          *   CKS - use RX clock,
00183          *   CKO - transmit continous clock on TK
00184          *   CKI - shift data on falling clock
00185          *   CKG - transmit continous clock on TK
00186          *   START - on falling TF(WS) edge
00187          *   STTDLY - TF toggles before last bit of last word, not before
00188          *            first bit on next word. Therefore: delay one cycle.
00189          *   PERIOD - generate framesync for each sample (FS is generated
00190          *            every (PERIOD + 1) * 2 clock)
00191          */
00192         ssc->tcmr = AVR32_SSC_TCMR_CKS_RK_CLOCK               << AVR32_SSC_TCMR_CKS_OFFSET    |
00193                     AVR32_SSC_TCMR_CKO_CONTINOUS_CLOCK_OUTPUT << AVR32_SSC_TCMR_CKO_OFFSET    |
00194                     0                                         << AVR32_SSC_TCMR_CKI_OFFSET    |
00195                     AVR32_SSC_TCMR_CKG_NONE                   << AVR32_SSC_TCMR_CKG_OFFSET    |
00196                     AVR32_SSC_TCMR_START_DETECT_ANY_EDGE_TF   << AVR32_SSC_TCMR_START_OFFSET  |
00197                     1                                         << AVR32_SSC_TCMR_STTDLY_OFFSET |
00198                     (frame_bit_res - 1)                       << AVR32_SSC_TCMR_PERIOD_OFFSET;
00199         /* Set receive clock mode:
00200          *  CKS - uses RK pin
00201          */
00202         ssc->rcmr = (AVR32_SSC_RCMR_CKS_RK_PIN << AVR32_SSC_RCMR_CKS_OFFSET);
00203       }
00204 
00205       /* Set transmit frame mode:
00206        *  DATLEN - one sample for one channel
00207        *  DATDEF - Default to zero,
00208        *  MSBF - transmit msb first,
00209        *  DATNB - Transfer two words (left+right),
00210        *  FSLEN - Frame sync is entire left channel
00211        *  FSOS - transmit negative pulse on WS (start sync on left channel)
00212        *  FSDEN - Do not use transmit frame sync data
00213        *  FSEDGE - detect frame sync positive edge
00214        */
00215 #ifdef AVR32_SSC_220_H_INCLUDED
00216       ssc->tfmr = (data_bit_res - 1)                                 << AVR32_SSC_TFMR_DATLEN_OFFSET                              |
00217                   0                                                  << AVR32_SSC_TFMR_DATDEF_OFFSET                              |
00218                   1                                                  << AVR32_SSC_TFMR_MSBF_OFFSET                                |
00219                   (1 - 1)                                            << AVR32_SSC_TFMR_DATNB_OFFSET                               |
00220                   (((frame_bit_res - 1)                              << AVR32_SSC_TFMR_FSLEN_OFFSET) & AVR32_SSC_TFMR_FSLEN_MASK) |
00221                   AVR32_SSC_TFMR_FSOS_NEG_PULSE                      << AVR32_SSC_TFMR_FSOS_OFFSET                                |
00222                   0                                                  << AVR32_SSC_TFMR_FSDEN_OFFSET                               |
00223                   1                                                  << AVR32_SSC_TFMR_FSEDGE_OFFSET;
00224 #else
00225       ssc->tfmr = (data_bit_res - 1)                                 << AVR32_SSC_TFMR_DATLEN_OFFSET                              |
00226                   0                                                  << AVR32_SSC_TFMR_DATDEF_OFFSET                              |
00227                   1                                                  << AVR32_SSC_TFMR_MSBF_OFFSET                                |
00228                   (1 - 1)                                            << AVR32_SSC_TFMR_DATNB_OFFSET                               |
00229                   (((frame_bit_res - 1)                              << AVR32_SSC_TFMR_FSLEN_OFFSET) & AVR32_SSC_TFMR_FSLEN_MASK) |
00230                   AVR32_SSC_TFMR_FSOS_NEG_PULSE                      << AVR32_SSC_TFMR_FSOS_OFFSET                                |
00231                   0                                                  << AVR32_SSC_TFMR_FSDEN_OFFSET                               |
00232                   1                                                  << AVR32_SSC_TFMR_FSEDGE_OFFSET                              |
00233                   ((frame_bit_res - 1) >> AVR32_SSC_TFMR_FSLEN_SIZE) << AVR32_SSC_TFMR_FSLENHI_OFFSET;
00234 #endif
00235       txen_mask = AVR32_SSC_CR_TXEN_MASK;
00236     }
00237 
00238     /* If receiving data, set receiving clock register */
00239     if ( (mode != SSC_I2S_MODE_STEREO_OUT) && (mode != SSC_I2S_MODE_STEREO_OUT_EXT_CLK) )
00240     {
00241       if ( (mode == SSC_I2S_MODE_STEREO_OUT_MONO_IN) || (mode == SSC_I2S_MODE_RIGHT_IN) )
00242       {
00243           /* Set receive clock mode:
00244            *  CKS - left ch uses TK, right (slave) uses RK pin
00245            *  CKO - No clock output,
00246            *  CKI - shift data on rising edge,
00247            *  CKG - No clock output,
00248            *  START - left ch starts when transmit starts, right starts on
00249            *          word-select (RF) rising edge
00250            *  STTDLY - RF toggles before last bit of last word, not before
00251            *           first bit on next word. Therefore, delay one cycle.
00252            *  PERIOD - No FS generation
00253            */
00254           ssc->rcmr =
00255             (( mode == SSC_I2S_MODE_RIGHT_IN ? AVR32_SSC_RCMR_CKS_RK_PIN : AVR32_SSC_RCMR_CKS_TK_CLOCK )
00256                                            << AVR32_SSC_RCMR_CKS_OFFSET)|
00257             (AVR32_SSC_RCMR_CKO_INPUT_ONLY << AVR32_SSC_RCMR_CKO_OFFSET)|
00258             (1                             << AVR32_SSC_RCMR_CKI_OFFSET)|
00259             (AVR32_SSC_RCMR_CKG_NONE       << AVR32_SSC_RCMR_CKG_OFFSET)|
00260             (( mode == SSC_I2S_MODE_RIGHT_IN ? AVR32_SSC_RCMR_START_DETECT_RISING_RF : AVR32_SSC_RCMR_START_TRANSMIT_START )
00261                                            << AVR32_SSC_RCMR_START_OFFSET)|
00262             (1                             << AVR32_SSC_RCMR_STTDLY_OFFSET)|
00263             (0                             << AVR32_SSC_RCMR_PERIOD_OFFSET);
00264     
00265           /* Set receive frame mode:
00266            *  DATLEN - bits per sample
00267            *  LOOP - no loopback
00268            *  MSBF - msb first
00269            *  DATNB - transmit one per sync
00270            *  FSLEN - no generate framesync
00271            *  FSOS - do not generate framesync
00272            *  FSEDGE - detect frame sync positive edge
00273            */
00274           ssc->rfmr =
00275             ((data_bit_res-1)               << AVR32_SSC_RFMR_DATLEN_OFFSET)|
00276             (0                              << AVR32_SSC_RFMR_LOOP_OFFSET)|
00277             (1                              << AVR32_SSC_RFMR_MSBF_OFFSET)|
00278             (0                              << AVR32_SSC_RFMR_DATNB_OFFSET)|
00279             (0                              << AVR32_SSC_RFMR_FSLEN_OFFSET)|
00280             (AVR32_SSC_RFMR_FSOS_INPUT_ONLY << AVR32_SSC_RFMR_FSOS_OFFSET)|
00281             (0                              << AVR32_SSC_RFMR_FSEDGE_OFFSET);
00282           
00283             rxen_mask = AVR32_SSC_CR_RXEN_MASK;
00284         }
00285         else
00286         {
00287             ssc->rcmr = AVR32_SSC_RCMR_CKS_TK_CLOCK               << AVR32_SSC_RCMR_CKS_OFFSET    |
00288                         AVR32_SSC_RCMR_CKO_CONTINOUS_CLOCK_OUTPUT << AVR32_SSC_RCMR_CKO_OFFSET    |
00289                         0                                         << AVR32_SSC_RCMR_CKI_OFFSET    |
00290                         AVR32_SSC_RCMR_CKG_NONE                   << AVR32_SSC_RCMR_CKG_OFFSET    |
00291                         AVR32_SSC_RCMR_START_DETECT_ANY_EDGE_RF   << AVR32_SSC_RCMR_START_OFFSET  |
00292                         1                                         << AVR32_SSC_RCMR_STTDLY_OFFSET |
00293                         (frame_bit_res - 1)                       << AVR32_SSC_RCMR_PERIOD_OFFSET;
00294 
00295 #ifdef AVR32_SSC_220_H_INCLUDED
00296             ssc->rfmr = (data_bit_res - 1)                                 << AVR32_SSC_RFMR_DATLEN_OFFSET                              |
00297                         1                                                  << AVR32_SSC_RFMR_MSBF_OFFSET                                |
00298                         (1 - 1)                                            << AVR32_SSC_RFMR_DATNB_OFFSET                               |
00299                         (((frame_bit_res - 1)                              << AVR32_SSC_RFMR_FSLEN_OFFSET) & AVR32_SSC_TFMR_FSLEN_MASK) |
00300                         AVR32_SSC_RFMR_FSOS_NEG_PULSE                      << AVR32_SSC_RFMR_FSOS_OFFSET                                |
00301                         1                                                  << AVR32_SSC_RFMR_FSEDGE_OFFSET;                                          
00302 #else            
00303             ssc->rfmr = (data_bit_res - 1)                                 << AVR32_SSC_RFMR_DATLEN_OFFSET                              |
00304                         1                                                  << AVR32_SSC_RFMR_MSBF_OFFSET                                |
00305                         (1 - 1)                                            << AVR32_SSC_RFMR_DATNB_OFFSET                               |
00306                         (((frame_bit_res - 1)                              << AVR32_SSC_RFMR_FSLEN_OFFSET) & AVR32_SSC_TFMR_FSLEN_MASK) |
00307                         AVR32_SSC_RFMR_FSOS_NEG_PULSE                      << AVR32_SSC_RFMR_FSOS_OFFSET                                |
00308                         1                                                  << AVR32_SSC_RFMR_FSEDGE_OFFSET                              |
00309                         ((frame_bit_res - 1) >> AVR32_SSC_RFMR_FSLEN_SIZE) << AVR32_SSC_RFMR_FSLENHI_OFFSET;
00310 #endif              
00311             rxen_mask = AVR32_SSC_CR_RXEN_MASK;
00312         }
00313         
00314       }      
00315     /* Enable transceiver and/or receiver */
00316     ssc->cr = txen_mask | rxen_mask;
00317   }
00318 
00319   return SSC_I2S_OK;
00320 }

void ssc_i2s_reset ( volatile avr32_ssc_t *  ssc  ) 

Resets the SSC module.

Parameters:
ssc pointer to the correct volatile avr32_ssc_t struct

Definition at line 82 of file ssc_i2s.c.

Referenced by ssc_i2s_init().

00083 {
00084   /* Software reset SSC */
00085   ssc->cr = AVR32_SSC_CR_SWRST_MASK;
00086 }

int ssc_i2s_transfer ( volatile avr32_ssc_t *  ssc,
unsigned int  data 
)

Transfers a single message of data.

Parameters:
ssc Pointer to the correct volatile avr32_ssc_t struct
data The data to transfer
Returns:
Status
Return values:
SSC_I2S_OK when no error occured.
SSC_I2S_TIMEOUT when a timeout occured while trying to transfer

Definition at line 323 of file ssc_i2s.c.

References SSC_I2S_OK, SSC_I2S_TIMEOUT, and SSC_I2S_TIMEOUT_VALUE.

Referenced by main().

00324 {
00325   unsigned int timeout = SSC_I2S_TIMEOUT_VALUE;
00326 
00327   while( ( ssc->sr & (1<<AVR32_SSC_SR_TXRDY_OFFSET) ) == 0 &&
00328       timeout > 0 ) {
00329     timeout--;
00330   }
00331 
00332   if( timeout <= 0 ) {
00333     return SSC_I2S_TIMEOUT;
00334   }
00335 
00336   ssc->thr = data;
00337 
00338   return SSC_I2S_OK;
00339 }


Generated on Thu Dec 17 19:59:26 2009 for AVR32 UC3 - SSC Driver for I²S by  doxygen 1.5.5