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_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 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 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.
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.
00080 { 00081 SSC_I2S_MODE_STEREO_OUT = 1, 00082 SSC_I2S_MODE_STEREO_OUT_EXT_CLK, 00083 SSC_I2S_MODE_SLAVE_STEREO_OUT, 00084 SSC_I2S_MODE_STEREO_OUT_MONO_IN, 00085 SSC_I2S_MODE_RIGHT_IN, 00086 SSC_I2S_MODE_STEREO_IN, 00087 SSC_I2S_MODE_STEREO_OUT_STEREO_IN 00088 };
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 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 | |||
) |
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 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.
ssc | pointer to the correct volatile avr32_ssc_t struct |
Definition at line 82 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 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 }