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.
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_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 SSC_I2S_TIMEOUT_VALUE 10000 |
anonymous enum |
Error codes used by SSC I2S driver.
SSC_I2S_ERROR | |
SSC_I2S_OK | |
SSC_I2S_TIMEOUT | |
SSC_I2S_ERROR_ARGUMENT | |
SSC_I2S_ERROR_RX | |
SSC_I2S_ERROR_TX |
Definition at line 57 of file ssc_i2s.h.
00058 { 00059 SSC_I2S_ERROR = -1, 00060 SSC_I2S_OK = 0, 00061 SSC_I2S_TIMEOUT = 1, 00062 SSC_I2S_ERROR_ARGUMENT, 00063 SSC_I2S_ERROR_RX, 00064 SSC_I2S_ERROR_TX 00065 };
anonymous enum |
SSC I2S modes.
SSC_I2S_MODE_STEREO_OUT | |
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 68 of file ssc_i2s.h.
00069 { 00070 SSC_I2S_MODE_STEREO_OUT = 1, 00071 SSC_I2S_MODE_SLAVE_STEREO_OUT, 00072 SSC_I2S_MODE_STEREO_OUT_MONO_IN, 00073 SSC_I2S_MODE_RIGHT_IN, 00074 SSC_I2S_MODE_STEREO_IN, 00075 SSC_I2S_MODE_STEREO_OUT_STEREO_IN 00076 };
void ssc_i2s_disable_interrupts | ( | volatile avr32_ssc_t * | ssc, | |
unsigned long | int_mask | |||
) |
Disables the specified SSC interrupts.
ssc | Base address of the SSC instance. | |
int_mask | Bit-mask of SSC interrupts (AVR32_SSC_IDR_x_MASK ). |
Definition at line 309 of file ssc_i2s.c.
00310 { 00311 Bool global_interrupt_enabled = Is_global_interrupt_enabled(); 00312 00313 if (global_interrupt_enabled) Disable_global_interrupt(); 00314 ssc->idr = int_mask; 00315 ssc->sr; 00316 if (global_interrupt_enabled) Enable_global_interrupt(); 00317 }
void ssc_i2s_enable_interrupts | ( | volatile avr32_ssc_t * | ssc, | |
unsigned long | int_mask | |||
) |
unsigned long ssc_i2s_get_status | ( | volatile avr32_ssc_t * | ssc | ) |
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.
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
| |
pba_hz | The clock speed of the PBA bus in Hz. |
SSC_I2S_OK | when no error occured. | |
SSC_I2S_ERROR_ARGUMENT | when invalid arguments are passed |
Definition at line 86 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_MONO_IN, SSC_I2S_OK, and ssc_i2s_reset().
Referenced by main().
00092 { 00095 /* Reset */ 00096 ssc_i2s_reset(ssc); 00097 00098 if (mode == SSC_I2S_MODE_SLAVE_STEREO_OUT) 00099 { 00100 ssc->cmr = AVR32_SSC_CMR_DIV_NOT_ACTIVE << AVR32_SSC_CMR_DIV_OFFSET; 00101 00102 ssc->tcmr = AVR32_SSC_TCMR_CKS_TK_PIN << AVR32_SSC_TCMR_CKS_OFFSET | 00103 AVR32_SSC_TCMR_CKO_INPUT_ONLY << AVR32_SSC_TCMR_CKO_OFFSET | 00104 0 << AVR32_SSC_TCMR_CKI_OFFSET | 00105 AVR32_SSC_TCMR_CKG_NONE << AVR32_SSC_TCMR_CKG_OFFSET | 00106 AVR32_SSC_TCMR_START_DETECT_ANY_EDGE_TF << AVR32_SSC_TCMR_START_OFFSET | 00107 1 << AVR32_SSC_TCMR_STTDLY_OFFSET | 00108 0 << AVR32_SSC_TCMR_PERIOD_OFFSET; 00109 #ifdef AVR32_SSC_220_H_INCLUDED 00110 ssc->tfmr = (data_bit_res - 1) << AVR32_SSC_TFMR_DATLEN_OFFSET | 00111 0 << AVR32_SSC_TFMR_DATDEF_OFFSET | 00112 1 << AVR32_SSC_TFMR_MSBF_OFFSET | 00113 (1 - 1) << AVR32_SSC_TFMR_DATNB_OFFSET | 00114 0 << AVR32_SSC_TFMR_FSLEN_OFFSET | 00115 AVR32_SSC_TFMR_FSOS_INPUT_ONLY << AVR32_SSC_TFMR_FSOS_OFFSET | 00116 0 << AVR32_SSC_TFMR_FSDEN_OFFSET | 00117 0 << AVR32_SSC_TFMR_FSEDGE_OFFSET; 00118 #else 00119 ssc->tfmr = (data_bit_res - 1) << AVR32_SSC_TFMR_DATLEN_OFFSET | 00120 0 << AVR32_SSC_TFMR_DATDEF_OFFSET | 00121 1 << AVR32_SSC_TFMR_MSBF_OFFSET | 00122 (1 - 1) << AVR32_SSC_TFMR_DATNB_OFFSET | 00123 0 << AVR32_SSC_TFMR_FSLEN_OFFSET | 00124 AVR32_SSC_TFMR_FSOS_INPUT_ONLY << AVR32_SSC_TFMR_FSOS_OFFSET | 00125 0 << AVR32_SSC_TFMR_FSDEN_OFFSET | 00126 0 << AVR32_SSC_TFMR_FSEDGE_OFFSET | 00127 0 << AVR32_SSC_TFMR_FSLENHI_OFFSET; 00128 #endif 00129 ssc->cr = AVR32_SSC_CR_TXEN_MASK; 00130 } 00131 else 00132 { 00133 unsigned long txen_mask = 0x00000000, 00134 rxen_mask = 0x00000000; 00135 00136 /* Set clock divider */ 00137 set_clock_divider(ssc, 2 * sample_frequency * frame_bit_res, pba_hz); 00138 00139 /* SSC can only receive one channel of audio input. In order 00140 * to use two inputs, two SSC's must be used. The first (master) 00141 * deals with both output channels and the left input, and should 00142 * be set to mode=I2S_STEREO_OUT_MONO_IN, and the second to 00143 * mode=I2S_RIGHT_IN. The second SSC should be connected to the 00144 * first SSC's in the following way: 00145 * master-ssc:TF -> slave-ssc:RF, 00146 * master-ssc:TK -> slave-ssc:RK 00147 */ 00148 00149 /* If only slave I2S SSC, do not set transmit registers */ 00150 if (mode != SSC_I2S_MODE_RIGHT_IN) 00151 { 00152 00153 /* Set transmit clock mode: 00154 * CKS - use divided clock, 00155 * CKO - transmit continous clock on TK 00156 * CKI - shift data on falling clock 00157 * CKG - transmit continous clock on TK 00158 * START - on falling TF(WS) edge 00159 * STTDLY - TF toggles before last bit of last word, not before 00160 * first bit on next word. Therefore: delay one cycle. 00161 * PERIOD - generate framesync for each sample (FS is generated 00162 * every (PERIOD + 1) * 2 clock) 00163 */ 00164 ssc->tcmr = AVR32_SSC_TCMR_CKS_DIV_CLOCK << AVR32_SSC_TCMR_CKS_OFFSET | 00165 AVR32_SSC_TCMR_CKO_CONTINOUS_CLOCK_OUTPUT << AVR32_SSC_TCMR_CKO_OFFSET | 00166 0 << AVR32_SSC_TCMR_CKI_OFFSET | 00167 AVR32_SSC_TCMR_CKG_NONE << AVR32_SSC_TCMR_CKG_OFFSET | 00168 AVR32_SSC_TCMR_START_DETECT_ANY_EDGE_TF << AVR32_SSC_TCMR_START_OFFSET | 00169 1 << AVR32_SSC_TCMR_STTDLY_OFFSET | 00170 (frame_bit_res - 1) << AVR32_SSC_TCMR_PERIOD_OFFSET; 00171 00172 /* Set transmit frame mode: 00173 * DATLEN - one sample for one channel 00174 * DATDEF - Default to zero, 00175 * MSBF - transmit msb first, 00176 * DATNB - Transfer two words (left+right), 00177 * FSLEN - Frame sync is entire left channel 00178 * FSOS - transmit negative pulse on WS (start sync on left channel) 00179 * FSDEN - Do not use transmit frame sync data 00180 * FSEDGE - detect frame sync positive edge 00181 */ 00182 #ifdef AVR32_SSC_220_H_INCLUDED 00183 ssc->tfmr = (data_bit_res - 1) << AVR32_SSC_TFMR_DATLEN_OFFSET | 00184 0 << AVR32_SSC_TFMR_DATDEF_OFFSET | 00185 1 << AVR32_SSC_TFMR_MSBF_OFFSET | 00186 (1 - 1) << AVR32_SSC_TFMR_DATNB_OFFSET | 00187 (((frame_bit_res - 1) << AVR32_SSC_TFMR_FSLEN_OFFSET) & AVR32_SSC_TFMR_FSLEN_MASK) | 00188 AVR32_SSC_TFMR_FSOS_NEG_PULSE << AVR32_SSC_TFMR_FSOS_OFFSET | 00189 0 << AVR32_SSC_TFMR_FSDEN_OFFSET | 00190 1 << AVR32_SSC_TFMR_FSEDGE_OFFSET; 00191 #else 00192 ssc->tfmr = (data_bit_res - 1) << AVR32_SSC_TFMR_DATLEN_OFFSET | 00193 0 << AVR32_SSC_TFMR_DATDEF_OFFSET | 00194 1 << AVR32_SSC_TFMR_MSBF_OFFSET | 00195 (1 - 1) << AVR32_SSC_TFMR_DATNB_OFFSET | 00196 (((frame_bit_res - 1) << AVR32_SSC_TFMR_FSLEN_OFFSET) & AVR32_SSC_TFMR_FSLEN_MASK) | 00197 AVR32_SSC_TFMR_FSOS_NEG_PULSE << AVR32_SSC_TFMR_FSOS_OFFSET | 00198 0 << AVR32_SSC_TFMR_FSDEN_OFFSET | 00199 1 << AVR32_SSC_TFMR_FSEDGE_OFFSET | 00200 ((frame_bit_res - 1) >> AVR32_SSC_TFMR_FSLEN_SIZE) << AVR32_SSC_TFMR_FSLENHI_OFFSET; 00201 #endif 00202 txen_mask = AVR32_SSC_CR_TXEN_MASK; 00203 } 00204 00205 /* If receiving data, set receiving clock register */ 00206 if (mode != SSC_I2S_MODE_STEREO_OUT) 00207 { 00208 if ( (mode == SSC_I2S_MODE_STEREO_OUT_MONO_IN) || (mode == SSC_I2S_MODE_RIGHT_IN) ) 00209 { 00210 /* Set receive clock mode: 00211 * CKS - left ch uses TK, right (slave) uses RK pin 00212 * CKO - No clock output, 00213 * CKI - shift data on rising edge, 00214 * CKG - No clock output, 00215 * START - left ch starts when transmit starts, right starts on 00216 * word-select (RF) rising edge 00217 * STTDLY - RF toggles before last bit of last word, not before 00218 * first bit on next word. Therefore, delay one cycle. 00219 * PERIOD - No FS generation 00220 */ 00221 ssc->rcmr = 00222 (( mode == SSC_I2S_MODE_RIGHT_IN ? AVR32_SSC_RCMR_CKS_RK_PIN : AVR32_SSC_RCMR_CKS_TK_CLOCK ) 00223 << AVR32_SSC_RCMR_CKS_OFFSET)| 00224 (AVR32_SSC_RCMR_CKO_INPUT_ONLY << AVR32_SSC_RCMR_CKO_OFFSET)| 00225 (1 << AVR32_SSC_RCMR_CKI_OFFSET)| 00226 (AVR32_SSC_RCMR_CKG_NONE << AVR32_SSC_RCMR_CKG_OFFSET)| 00227 (( mode == SSC_I2S_MODE_RIGHT_IN ? AVR32_SSC_RCMR_START_DETECT_RISING_RF : AVR32_SSC_RCMR_START_TRANSMIT_START ) 00228 << AVR32_SSC_RCMR_START_OFFSET)| 00229 (1 << AVR32_SSC_RCMR_STTDLY_OFFSET)| 00230 (0 << AVR32_SSC_RCMR_PERIOD_OFFSET); 00231 00232 /* Set receive frame mode: 00233 * DATLEN - bits per sample 00234 * LOOP - no loopback 00235 * MSBF - msb first 00236 * DATNB - transmit one per sync 00237 * FSLEN - no generate framesync 00238 * FSOS - do not generate framesync 00239 * FSEDGE - detect frame sync positive edge 00240 */ 00241 ssc->rfmr = 00242 ((data_bit_res-1) << AVR32_SSC_RFMR_DATLEN_OFFSET)| 00243 (0 << AVR32_SSC_RFMR_LOOP_OFFSET)| 00244 (1 << AVR32_SSC_RFMR_MSBF_OFFSET)| 00245 (0 << AVR32_SSC_RFMR_DATNB_OFFSET)| 00246 (0 << AVR32_SSC_RFMR_FSLEN_OFFSET)| 00247 (AVR32_SSC_RFMR_FSOS_INPUT_ONLY << AVR32_SSC_RFMR_FSOS_OFFSET)| 00248 (0 << AVR32_SSC_RFMR_FSEDGE_OFFSET); 00249 00250 rxen_mask = AVR32_SSC_CR_RXEN_MASK; 00251 } 00252 else 00253 { 00254 ssc->rcmr = AVR32_SSC_RCMR_CKS_TK_CLOCK << AVR32_SSC_RCMR_CKS_OFFSET | 00255 AVR32_SSC_RCMR_CKO_CONTINOUS_CLOCK_OUTPUT << AVR32_SSC_RCMR_CKO_OFFSET | 00256 0 << AVR32_SSC_RCMR_CKI_OFFSET | 00257 AVR32_SSC_RCMR_CKG_NONE << AVR32_SSC_RCMR_CKG_OFFSET | 00258 AVR32_SSC_RCMR_START_DETECT_ANY_EDGE_RF << AVR32_SSC_RCMR_START_OFFSET | 00259 1 << AVR32_SSC_RCMR_STTDLY_OFFSET | 00260 (frame_bit_res - 1) << AVR32_SSC_RCMR_PERIOD_OFFSET; 00261 00262 #ifdef AVR32_SSC_220_H_INCLUDED 00263 ssc->rfmr = (data_bit_res - 1) << AVR32_SSC_RFMR_DATLEN_OFFSET | 00264 1 << AVR32_SSC_RFMR_MSBF_OFFSET | 00265 (1 - 1) << AVR32_SSC_RFMR_DATNB_OFFSET | 00266 (((frame_bit_res - 1) << AVR32_SSC_RFMR_FSLEN_OFFSET) & AVR32_SSC_TFMR_FSLEN_MASK) | 00267 AVR32_SSC_RFMR_FSOS_NEG_PULSE << AVR32_SSC_RFMR_FSOS_OFFSET | 00268 1 << AVR32_SSC_RFMR_FSEDGE_OFFSET; 00269 #else 00270 ssc->rfmr = (data_bit_res - 1) << AVR32_SSC_RFMR_DATLEN_OFFSET | 00271 1 << AVR32_SSC_RFMR_MSBF_OFFSET | 00272 (1 - 1) << AVR32_SSC_RFMR_DATNB_OFFSET | 00273 (((frame_bit_res - 1) << AVR32_SSC_RFMR_FSLEN_OFFSET) & AVR32_SSC_TFMR_FSLEN_MASK) | 00274 AVR32_SSC_RFMR_FSOS_NEG_PULSE << AVR32_SSC_RFMR_FSOS_OFFSET | 00275 1 << AVR32_SSC_RFMR_FSEDGE_OFFSET | 00276 ((frame_bit_res - 1) >> AVR32_SSC_RFMR_FSLEN_SIZE) << AVR32_SSC_RFMR_FSLENHI_OFFSET; 00277 #endif 00278 rxen_mask = AVR32_SSC_CR_RXEN_MASK; 00279 } 00280 00281 } 00282 /* Enable transceiver and/or receiver */ 00283 ssc->cr = txen_mask | rxen_mask; 00284 } 00285 00286 return SSC_I2S_OK; 00287 }
void ssc_i2s_reset | ( | volatile avr32_ssc_t * | ssc | ) |
Resets the SSC module.
ssc | pointer to the correct volatile avr32_ssc_t struct |
Definition at line 79 of file ssc_i2s.c.
Referenced by ssc_i2s_init().
int ssc_i2s_transfer | ( | volatile avr32_ssc_t * | ssc, | |
unsigned int | data | |||
) |
Transfers a single message of data.
ssc | Pointer to the correct volatile avr32_ssc_t struct | |
data | The data to transfer |
SSC_I2S_OK | when no error occured. | |
SSC_I2S_TIMEOUT | when a timeout occured while trying to transfer |
Definition at line 290 of file ssc_i2s.c.
References SSC_I2S_OK, SSC_I2S_TIMEOUT, and SSC_I2S_TIMEOUT_VALUE.
Referenced by main().
00291 { 00292 unsigned int timeout = SSC_I2S_TIMEOUT_VALUE; 00293 00294 while( ( ssc->sr & (1<<AVR32_SSC_SR_TXRDY_OFFSET) ) == 0 && 00295 timeout > 0 ) { 00296 timeout--; 00297 } 00298 00299 if( timeout <= 0 ) { 00300 return SSC_I2S_TIMEOUT; 00301 } 00302 00303 ssc->thr = data; 00304 00305 return SSC_I2S_OK; 00306 }