C:/nxpdrv/LPC1700CMSIS/Drivers/source/lpc17xx_i2s.c
Go to the documentation of this file.00001 00020 /* Peripheral group ----------------------------------------------------------- */ 00025 /* Includes ------------------------------------------------------------------- */ 00026 #include "lpc17xx_i2s.h" 00027 #include "lpc17xx_clkpwr.h" 00028 00029 00030 /* If this source file built with example, the LPC17xx FW library configuration 00031 * file in each example directory ("lpc17xx_libcfg.h") must be included, 00032 * otherwise the default FW library configuration file must be included instead 00033 */ 00034 #ifdef __BUILD_WITH_EXAMPLE__ 00035 #include "lpc17xx_libcfg.h" 00036 #else 00037 #include "lpc17xx_libcfg_default.h" 00038 #endif /* __BUILD_WITH_EXAMPLE__ */ 00039 00040 00041 #ifdef _I2S 00042 00043 /* Private Variables ---------------------------------------------------------- */ 00044 static fnI2SCbs_Type *_apfnI2SCbs[2] = { 00045 NULL, // I2S transmit Call-back function pointer 00046 NULL, // I2S receive Call-back function pointer 00047 }; 00048 00049 00050 /* Private Functions ---------------------------------------------------------- */ 00055 /********************************************************************/ 00063 uint8_t I2S_GetWordWidth(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) { 00064 uint8_t value; 00065 00066 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00067 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00068 00069 if (TRMode == I2S_TX_MODE) { 00070 value = (I2Sx->I2SDAO) & 0x03; /* get wordwidth bit */ 00071 } else { 00072 value = (I2Sx->I2SDAI) & 0x03; /* get wordwidth bit */ 00073 } 00074 switch (value) { 00075 case I2S_WORDWIDTH_8: 00076 return 8; 00077 break; 00078 case I2S_WORDWIDTH_16: 00079 return 16; 00080 break; 00081 default: 00082 return 32; 00083 } 00084 } 00085 /********************************************************************/ 00093 uint8_t I2S_GetChannel(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) { 00094 uint8_t value; 00095 00096 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00097 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00098 00099 if (TRMode == I2S_TX_MODE) { 00100 value = (I2Sx->I2SDAO) & 0x04; /* get bit[2] */ 00101 } else { 00102 value = (I2Sx->I2SDAI) & 0x04; /* get bit[2] */ 00103 } 00104 switch (value) { 00105 case I2S_MONO: 00106 return 1; 00107 break; 00108 default: 00109 return 2; 00110 } 00111 } 00112 00118 /* Public Functions ----------------------------------------------------------- */ 00123 /********************************************************************/ 00130 void I2S_Init(LPC_I2S_TypeDef *I2Sx) { 00131 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00132 00133 // Turn on power and clock 00134 CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCI2S, ENABLE); 00135 LPC_I2S->I2SDAI = LPC_I2S->I2SDAO = 0x00; 00136 } 00137 00138 /********************************************************************/ 00151 void I2S_Config(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, I2S_CFG_Type* ConfigStruct) 00152 { 00153 uint32_t bps, config; 00154 00155 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00156 00157 CHECK_PARAM(PARAM_I2S_WORDWIDTH(ConfigStruct->wordwidth)); 00158 CHECK_PARAM(PARAM_I2S_CHANNEL(ConfigStruct->mono)); 00159 CHECK_PARAM(PARAM_I2S_STOP(ConfigStruct->stop)); 00160 CHECK_PARAM(PARAM_I2S_RESET(ConfigStruct->reset)); 00161 CHECK_PARAM(PARAM_I2S_WS_SEL(ConfigStruct->ws_sel)); 00162 CHECK_PARAM(PARAM_I2S_MUTE(ConfigStruct->mute)); 00163 00164 /* Setup clock */ 00165 bps = (ConfigStruct->wordwidth +1)*8; 00166 00167 /* Calculate audio config */ 00168 config = (bps - 1)<<6 | (ConfigStruct->ws_sel)<<5 | (ConfigStruct->reset)<<4 | 00169 (ConfigStruct->stop)<<3 | (ConfigStruct->mono)<<2 | (ConfigStruct->wordwidth); 00170 00171 if(TRMode == I2S_RX_MODE){ 00172 LPC_I2S->I2SDAI = config; 00173 }else{ 00174 LPC_I2S->I2SDAO = config; 00175 } 00176 } 00177 00178 /********************************************************************/ 00183 void I2S_DeInit(LPC_I2S_TypeDef *I2Sx) { 00184 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00185 00186 // Turn off power and clock 00187 CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCI2S, DISABLE); 00188 } 00189 00190 /********************************************************************/ 00198 uint8_t I2S_GetLevel(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) 00199 { 00200 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00201 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00202 00203 if(TRMode == I2S_TX_MODE) 00204 { 00205 return ((I2Sx->I2SSTATE >> 16) & 0xFF); 00206 } 00207 else 00208 { 00209 return ((I2Sx->I2SSTATE >> 8) & 0xFF); 00210 } 00211 } 00212 /********************************************************************/ 00217 void I2S_Start(LPC_I2S_TypeDef *I2Sx) 00218 { 00219 //Clear STOP,RESET and MUTE bit 00220 I2Sx->I2SDAO &= ~I2S_DAI_RESET; 00221 I2Sx->I2SDAI &= ~I2S_DAI_RESET; 00222 I2Sx->I2SDAO &= ~I2S_DAI_STOP; 00223 I2Sx->I2SDAI &= ~I2S_DAI_STOP; 00224 I2Sx->I2SDAO &= ~I2S_DAI_MUTE; 00225 } 00226 /********************************************************************/ 00232 void I2S_Send(LPC_I2S_TypeDef *I2Sx, uint32_t BufferData) { 00233 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00234 CHECK_PARAM(PARAM_I2S_DATA(BufferData)); 00235 00236 I2Sx->I2STXFIFO = BufferData; 00237 } 00238 00239 /********************************************************************/ 00244 uint32_t I2S_Receive(LPC_I2S_TypeDef* I2Sx) { 00245 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00246 00247 return (I2Sx->I2SRXFIFO); 00248 00249 } 00250 /********************************************************************/ 00258 void I2S_Pause(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) { 00259 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00260 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00261 00262 if (TRMode == I2S_TX_MODE) //Transmit mode 00263 { 00264 I2Sx->I2SDAO |= I2S_DAO_STOP; 00265 } else //Receive mode 00266 { 00267 I2Sx->I2SDAI |= I2S_DAI_STOP; 00268 } 00269 } 00270 /********************************************************************/ 00278 void I2S_Mute(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) { 00279 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00280 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00281 00282 if (TRMode == I2S_TX_MODE) //Transmit mode 00283 { 00284 I2Sx->I2SDAO |= I2S_DAO_MUTE; 00285 } else //Receive mode 00286 { 00287 I2Sx->I2SDAI |= I2S_DAI_MUTE; 00288 } 00289 } 00290 00291 /********************************************************************/ 00299 void I2S_Stop(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) { 00300 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00301 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00302 00303 if (TRMode == I2S_TX_MODE) //Transmit mode 00304 { 00305 I2Sx->I2SDAO &= ~I2S_DAO_MUTE; 00306 I2Sx->I2SDAO |= I2S_DAO_STOP; 00307 I2Sx->I2SDAO |= I2S_DAO_RESET; 00308 } else //Receive mode 00309 { 00310 I2Sx->I2SDAI |= I2S_DAI_STOP; 00311 I2Sx->I2SDAI |= I2S_DAI_RESET; 00312 } 00313 } 00314 00315 /********************************************************************/ 00325 Status I2S_FreqConfig(LPC_I2S_TypeDef *I2Sx, uint32_t Freq, uint8_t TRMode) { 00326 00327 /* Calculate bit rate 00328 * The formula is: 00329 * bit_rate = channel*wordwidth - 1 00330 * 48kHz sample rate for 16 bit stereo date requires 00331 * a bit rate of 48000*16*2=1536MHz (MCLK) 00332 */ 00333 uint32_t i2sPclk; 00334 uint64_t divider; 00335 uint8_t bitrate, channel, wordwidth; 00336 uint32_t x, y; 00337 uint16_t dif; 00338 uint16_t error; 00339 uint8_t x_divide, y_divide; 00340 uint16_t ErrorOptimal = 0xFFFF; 00341 00342 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00343 CHECK_PARAM(PRAM_I2S_FREQ(Freq)); 00344 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00345 00346 i2sPclk = CLKPWR_GetPCLK(CLKPWR_PCLKSEL_I2S); 00347 if(TRMode == I2S_TX_MODE) 00348 { 00349 channel = I2S_GetChannel(I2Sx,I2S_TX_MODE); 00350 wordwidth = I2S_GetWordWidth(I2Sx,I2S_TX_MODE); 00351 } 00352 else 00353 { 00354 channel = I2S_GetChannel(I2Sx,I2S_RX_MODE); 00355 wordwidth = I2S_GetWordWidth(I2Sx,I2S_RX_MODE); 00356 } 00357 bitrate = channel * wordwidth - 1; 00358 if (TRMode == I2S_TX_MODE)// Transmitter 00359 { 00360 I2Sx->I2STXBITRATE = bitrate; 00361 } else //Receiver 00362 { 00363 I2Sx->I2SRXBITRATE = bitrate; 00364 } 00365 /* Calculate X and Y divider 00366 * The MCLK rate for the I2S transmitter is determined by the value 00367 * in the I2STXRATE/I2SRXRATE register. The required I2STXRATE/I2SRXRATE 00368 * setting depends on the desired audio sample rate desired, the format 00369 * (stereo/mono) used, and the data size. 00370 * The formula is: 00371 * I2S_MCLK = PCLK * (X/Y) / 2 00372 * We have: 00373 * I2S_MCLK = Freq * bit_rate; 00374 * So: (X/Y) = (Freq * bit_rate)/PCLK*2 00375 * We use a loop function to chose the most suitable X,Y value 00376 */ 00377 00378 divider = ((uint64_t)(Freq *( bitrate+1)* 2)<<16) / i2sPclk; 00379 for (y = 255; y > 0; y--) { 00380 x = y * divider; 00381 dif = x & 0xFFFF; 00382 if(dif>0x8000) error = 0x10000-dif; 00383 else error = dif; 00384 if (error == 0) 00385 { 00386 y_divide = y; 00387 break; 00388 } 00389 else if (error < ErrorOptimal) 00390 { 00391 ErrorOptimal = error; 00392 y_divide = y; 00393 } 00394 } 00395 x_divide = (y_divide * Freq *( bitrate+1)* 2)/i2sPclk; 00396 if (TRMode == I2S_TX_MODE)// Transmitter 00397 { 00398 I2Sx->I2STXRATE = y_divide | (x_divide << 8); 00399 } else //Receiver 00400 { 00401 I2Sx->I2SRXRATE = y_divide | (x_divide << 8); 00402 } 00403 return SUCCESS; 00404 } 00405 /********************************************************************/ 00414 void I2S_SetBitRate(LPC_I2S_TypeDef *I2Sx, uint8_t bitrate, uint8_t TRMode) 00415 { 00416 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00417 CHECK_PARAM(PARAM_I2S_BITRATE(bitrate)); 00418 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00419 00420 if(TRMode == I2S_TX_MODE) 00421 { 00422 I2Sx->I2STXBITRATE = (bitrate -1); 00423 } 00424 else 00425 { 00426 I2Sx->I2SRXBITRATE = (bitrate -1); 00427 } 00428 } 00429 /********************************************************************/ 00439 void I2S_ModeConfig(LPC_I2S_TypeDef *I2Sx, I2S_MODEConf_Type* ModeConfig, 00440 uint8_t TRMode) 00441 { 00442 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00443 CHECK_PARAM(PARAM_I2S_CLKSEL(ModeConfig->clksel)); 00444 CHECK_PARAM(PARAM_I2S_4PIN(ModeConfig->fpin)); 00445 CHECK_PARAM(PARAM_I2S_MCLK(ModeConfig->mcena)); 00446 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00447 00448 if (TRMode == I2S_TX_MODE) { 00449 I2Sx->I2STXMODE &= ~0x0F; //clear bit 3:0 in I2STXMODE register 00450 if (ModeConfig->clksel == I2S_CLKSEL_1) { 00451 I2Sx->I2STXMODE |= 0x02; 00452 } 00453 if (ModeConfig->fpin == I2S_4PIN_ENABLE) { 00454 I2Sx->I2STXMODE |= (1 << 2); 00455 } 00456 if (ModeConfig->mcena == I2S_MCLK_ENABLE) { 00457 I2Sx->I2STXMODE |= (1 << 3); 00458 } 00459 } else { 00460 I2Sx->I2SRXMODE &= ~0x0F; //clear bit 3:0 in I2STXMODE register 00461 if (ModeConfig->clksel == I2S_CLKSEL_1) { 00462 I2Sx->I2SRXMODE |= 0x02; 00463 } 00464 if (ModeConfig->fpin == I2S_4PIN_ENABLE) { 00465 I2Sx->I2SRXMODE |= (1 << 2); 00466 } 00467 if (ModeConfig->mcena == I2S_MCLK_ENABLE) { 00468 I2Sx->I2SRXMODE |= (1 << 3); 00469 } 00470 } 00471 } 00472 00473 /********************************************************************/ 00482 void I2S_DMAConfig(LPC_I2S_TypeDef *I2Sx, I2S_DMAConf_Type* DMAConfig, 00483 uint8_t TRMode) 00484 { 00485 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00486 CHECK_PARAM(PARAM_I2S_DMA(DMAConfig->DMAIndex)); 00487 CHECK_PARAM(PARAM_I2S_DMA_DEPTH(DMAConfig->depth)); 00488 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00489 00490 if (TRMode == I2S_RX_MODE) { 00491 if (DMAConfig->DMAIndex == I2S_DMA_1) { 00492 LPC_I2S->I2SDMA1 = (DMAConfig->depth) << 8; 00493 } else { 00494 LPC_I2S->I2SDMA2 = (DMAConfig->depth) << 8; 00495 } 00496 } else { 00497 if (DMAConfig->DMAIndex == I2S_DMA_1) { 00498 LPC_I2S->I2SDMA1 = (DMAConfig->depth) << 16; 00499 } else { 00500 LPC_I2S->I2SDMA2 = (DMAConfig->depth) << 16; 00501 } 00502 } 00503 } 00504 00505 /********************************************************************/ 00519 void I2S_DMACmd(LPC_I2S_TypeDef *I2Sx, uint8_t DMAIndex, uint8_t TRMode, 00520 FunctionalState NewState) 00521 { 00522 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00523 CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState)); 00524 CHECK_PARAM(PARAM_I2S_DMA(DMAIndex)); 00525 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00526 00527 if (TRMode == I2S_RX_MODE) { 00528 if (DMAIndex == I2S_DMA_1) { 00529 if (NewState == ENABLE) 00530 I2Sx->I2SDMA1 |= 0x01; 00531 else 00532 I2Sx->I2SDMA1 &= ~0x01; 00533 } else { 00534 if (NewState == ENABLE) 00535 I2Sx->I2SDMA2 |= 0x01; 00536 else 00537 I2Sx->I2SDMA2 &= ~0x01; 00538 } 00539 } else { 00540 if (DMAIndex == I2S_DMA_1) { 00541 if (NewState == ENABLE) 00542 I2Sx->I2SDMA1 |= 0x02; 00543 else 00544 I2Sx->I2SDMA1 &= ~0x02; 00545 } else { 00546 if (NewState == ENABLE) 00547 I2Sx->I2SDMA2 |= 0x02; 00548 else 00549 I2Sx->I2SDMA2 &= ~0x02; 00550 } 00551 } 00552 } 00553 00554 /********************************************************************/ 00564 void I2S_IRQConfig(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, uint8_t level, fnI2SCbs_Type *pfnI2SCbs) { 00565 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00566 CHECK_PARAM(PARAM_I2S_TRX(TRMode)); 00567 CHECK_PARAM(PARAM_I2S_IRQ_LEVEL(level)); 00568 00569 if (TRMode == I2S_RX_MODE) { 00570 I2Sx->I2SIRQ |= (level << 8); 00571 } else { 00572 I2Sx->I2SIRQ |= (level << 16); 00573 } 00574 //setup Call-Back funtion for receive interrupt 00575 _apfnI2SCbs[TRMode] = pfnI2SCbs; 00576 } 00577 00578 /********************************************************************/ 00589 void I2S_IRQCmd(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, FunctionalState NewState) { 00590 CHECK_PARAM(PARAM_I2Sx(I2Sx)); 00591 CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState)); 00592 00593 if (TRMode == I2S_RX_MODE) { 00594 if (NewState == ENABLE) 00595 I2Sx->I2SIRQ |= 0x01; 00596 else 00597 I2Sx->I2SIRQ &= ~0x01; 00598 //Enable DMA 00599 00600 } else { 00601 if (NewState == ENABLE) 00602 I2Sx->I2SIRQ |= 0x02; 00603 else 00604 I2Sx->I2SIRQ &= ~0x02; 00605 } 00606 } 00607 /*********************************************************************/ 00614 void I2S_IntHandler(void) 00615 { 00616 uint8_t rx_level, 00617 tx_level, 00618 tx_depth_irq, 00619 rx_depth_irq; 00620 00621 00622 if((LPC_I2S->I2SIRQ)& 0x01){ //receive interrupt 00623 rx_level = ((LPC_I2S->I2SSTATE)>>8)&0xFF; 00624 rx_depth_irq = ((LPC_I2S->I2SIRQ)>>8)&0xFF; 00625 00626 if (rx_level >= rx_depth_irq)//receive interrupt 00627 { 00628 _apfnI2SCbs[1](); 00629 } 00630 } 00631 else if(((LPC_I2S->I2SIRQ)>>1)& 0x01) 00632 { 00633 tx_level = ((LPC_I2S->I2SSTATE)>>16)&0xFF; 00634 tx_depth_irq = ((LPC_I2S->I2SIRQ)>>16)&0xFF; 00635 if(tx_level <= tx_depth_irq)//transmit interrupt 00636 { 00637 _apfnI2SCbs[0](); 00638 } 00639 } 00640 } 00641 00646 #endif /* _I2S */ 00647 00652 /* --------------------------------- End Of File ------------------------------ */ 00653
Generated on Mon Feb 8 10:01:37 2010 for LPC1700CMSIS Standard Peripheral Firmware Library by
