uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lpc17xx_i2s.c
Go to the documentation of this file.
1 /***********************************************************************/
20 /* Peripheral group ----------------------------------------------------------- */
25 /* Includes ------------------------------------------------------------------- */
26 #include "lpc17xx_i2s.h"
27 #include "lpc17xx_clkpwr.h"
28 
29 
30 /* If this source file built with example, the LPC17xx FW library configuration
31  * file in each example directory ("lpc17xx_libcfg.h") must be included,
32  * otherwise the default FW library configuration file must be included instead
33  */
34 #ifdef __BUILD_WITH_EXAMPLE__
35 #include "lpc17xx_libcfg.h"
36 #else
37 #include "lpc17xx_libcfg_default.h"
38 #endif /* __BUILD_WITH_EXAMPLE__ */
39 
40 
41 #ifdef _I2S
42 
43 /* Private Functions ---------------------------------------------------------- */
44 
45 static uint8_t i2s_GetWordWidth(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode);
46 static uint8_t i2s_GetChannel(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode);
47 
48 /********************************************************************/
56 static uint8_t i2s_GetWordWidth(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
57  uint8_t value;
58 
59  CHECK_PARAM(PARAM_I2Sx(I2Sx));
60  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
61 
62  if (TRMode == I2S_TX_MODE) {
63  value = (I2Sx->I2SDAO) & 0x03; /* get wordwidth bit */
64  } else {
65  value = (I2Sx->I2SDAI) & 0x03; /* get wordwidth bit */
66  }
67  switch (value) {
68  case I2S_WORDWIDTH_8:
69  return 8;
70  case I2S_WORDWIDTH_16:
71  return 16;
72  default:
73  return 32;
74  }
75 }
76 
77 /********************************************************************/
85 static uint8_t i2s_GetChannel(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
86  uint8_t value;
87 
88  CHECK_PARAM(PARAM_I2Sx(I2Sx));
89  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
90 
91  if (TRMode == I2S_TX_MODE) {
92  value = (I2Sx->I2SDAO) & 0x04; /* get bit[2] */
93  } else {
94  value = (I2Sx->I2SDAI) & 0x04; /* get bit[2] */
95  }
96  if(value == I2S_MONO) return 1;
97  return 2;
98 }
99 
100 /* End of Private Functions --------------------------------------------------- */
101 
102 
103 /* Public Functions ----------------------------------------------------------- */
108 /********************************************************************/
114 void I2S_Init(LPC_I2S_TypeDef *I2Sx) {
115  CHECK_PARAM(PARAM_I2Sx(I2Sx));
116 
117  // Turn on power and clock
119  LPC_I2S->I2SDAI = LPC_I2S->I2SDAO = 0x00;
120 }
121 
122 /********************************************************************/
135 void I2S_Config(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, I2S_CFG_Type* ConfigStruct)
136 {
137  uint32_t bps, config;
138 
139  CHECK_PARAM(PARAM_I2Sx(I2Sx));
140 
141  CHECK_PARAM(PARAM_I2S_WORDWIDTH(ConfigStruct->wordwidth));
142  CHECK_PARAM(PARAM_I2S_CHANNEL(ConfigStruct->mono));
143  CHECK_PARAM(PARAM_I2S_STOP(ConfigStruct->stop));
144  CHECK_PARAM(PARAM_I2S_RESET(ConfigStruct->reset));
145  CHECK_PARAM(PARAM_I2S_WS_SEL(ConfigStruct->ws_sel));
146  CHECK_PARAM(PARAM_I2S_MUTE(ConfigStruct->mute));
147 
148  /* Setup clock */
149  bps = (ConfigStruct->wordwidth +1)*8;
150 
151  /* Calculate audio config */
152  config = (bps - 1)<<6 | (ConfigStruct->ws_sel)<<5 | (ConfigStruct->reset)<<4 |
153  (ConfigStruct->stop)<<3 | (ConfigStruct->mono)<<2 | (ConfigStruct->wordwidth);
154 
155  if(TRMode == I2S_RX_MODE){
156  LPC_I2S->I2SDAI = config;
157  }else{
158  LPC_I2S->I2SDAO = config;
159  }
160 }
161 
162 /********************************************************************/
167 void I2S_DeInit(LPC_I2S_TypeDef *I2Sx) {
168  CHECK_PARAM(PARAM_I2Sx(I2Sx));
169 
170  // Turn off power and clock
172 }
173 
174 /********************************************************************/
182 uint8_t I2S_GetLevel(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode)
183 {
184  CHECK_PARAM(PARAM_I2Sx(I2Sx));
185  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
186 
187  if(TRMode == I2S_TX_MODE)
188  {
189  return ((I2Sx->I2SSTATE >> 16) & 0xFF);
190  }
191  else
192  {
193  return ((I2Sx->I2SSTATE >> 8) & 0xFF);
194  }
195 }
196 
197 /********************************************************************/
202 void I2S_Start(LPC_I2S_TypeDef *I2Sx)
203 {
204  //Clear STOP,RESET and MUTE bit
205  I2Sx->I2SDAO &= ~I2S_DAI_RESET;
206  I2Sx->I2SDAI &= ~I2S_DAI_RESET;
207  I2Sx->I2SDAO &= ~I2S_DAI_STOP;
208  I2Sx->I2SDAI &= ~I2S_DAI_STOP;
209  I2Sx->I2SDAO &= ~I2S_DAI_MUTE;
210 }
211 
212 /********************************************************************/
218 void I2S_Send(LPC_I2S_TypeDef *I2Sx, uint32_t BufferData) {
219  CHECK_PARAM(PARAM_I2Sx(I2Sx));
220 
221  I2Sx->I2STXFIFO = BufferData;
222 }
223 
224 /********************************************************************/
229 uint32_t I2S_Receive(LPC_I2S_TypeDef* I2Sx) {
230  CHECK_PARAM(PARAM_I2Sx(I2Sx));
231 
232  return (I2Sx->I2SRXFIFO);
233 
234 }
235 
236 /********************************************************************/
244 void I2S_Pause(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
245  CHECK_PARAM(PARAM_I2Sx(I2Sx));
246  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
247 
248  if (TRMode == I2S_TX_MODE) //Transmit mode
249  {
250  I2Sx->I2SDAO |= I2S_DAO_STOP;
251  } else //Receive mode
252  {
253  I2Sx->I2SDAI |= I2S_DAI_STOP;
254  }
255 }
256 
257 /********************************************************************/
265 void I2S_Mute(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
266  CHECK_PARAM(PARAM_I2Sx(I2Sx));
267  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
268 
269  if (TRMode == I2S_TX_MODE) //Transmit mode
270  {
271  I2Sx->I2SDAO |= I2S_DAO_MUTE;
272  } else //Receive mode
273  {
274  I2Sx->I2SDAI |= I2S_DAI_MUTE;
275  }
276 }
277 
278 /********************************************************************/
286 void I2S_Stop(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode) {
287  CHECK_PARAM(PARAM_I2Sx(I2Sx));
288  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
289 
290  if (TRMode == I2S_TX_MODE) //Transmit mode
291  {
292  I2Sx->I2SDAO &= ~I2S_DAO_MUTE;
293  I2Sx->I2SDAO |= I2S_DAO_STOP;
294  I2Sx->I2SDAO |= I2S_DAO_RESET;
295  } else //Receive mode
296  {
297  I2Sx->I2SDAI |= I2S_DAI_STOP;
298  I2Sx->I2SDAI |= I2S_DAI_RESET;
299  }
300 }
301 
302 /********************************************************************/
312 Status I2S_FreqConfig(LPC_I2S_TypeDef *I2Sx, uint32_t Freq, uint8_t TRMode) {
313 
314  /* Calculate bit rate
315  * The formula is:
316  * bit_rate = channel*wordwidth - 1
317  * 48kHz sample rate for 16 bit stereo date requires
318  * a bit rate of 48000*16*2=1536MHz (MCLK)
319  */
320  uint32_t i2sPclk;
321  uint64_t divider;
322  uint8_t bitrate, channel, wordwidth;
323  uint32_t x, y;
324  uint16_t dif;
325  uint16_t error;
326  uint8_t x_divide = 0, y_divide = 0;
327  uint16_t ErrorOptimal = 0xFFFF;
328 
329  CHECK_PARAM(PARAM_I2Sx(I2Sx));
330  CHECK_PARAM(PRAM_I2S_FREQ(Freq));
331  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
332 
334  if(TRMode == I2S_TX_MODE)
335  {
336  channel = i2s_GetChannel(I2Sx,I2S_TX_MODE);
337  wordwidth = i2s_GetWordWidth(I2Sx,I2S_TX_MODE);
338  }
339  else
340  {
341  channel = i2s_GetChannel(I2Sx,I2S_RX_MODE);
342  wordwidth = i2s_GetWordWidth(I2Sx,I2S_RX_MODE);
343  }
344  bitrate = channel * wordwidth - 1;
345  if (TRMode == I2S_TX_MODE)// Transmitter
346  {
347  I2Sx->I2STXBITRATE = bitrate;
348  } else //Receiver
349  {
350  I2Sx->I2SRXBITRATE = bitrate;
351  }
352  /* Calculate X and Y divider
353  * The MCLK rate for the I2S transmitter is determined by the value
354  * in the I2STXRATE/I2SRXRATE register. The required I2STXRATE/I2SRXRATE
355  * setting depends on the desired audio sample rate desired, the format
356  * (stereo/mono) used, and the data size.
357  * The formula is:
358  * I2S_MCLK = PCLK * (X/Y) / 2
359  * We have:
360  * I2S_MCLK = Freq * bit_rate;
361  * So: (X/Y) = (Freq * bit_rate)/PCLK*2
362  * We use a loop function to chose the most suitable X,Y value
363  */
364 
365  divider = ((uint64_t)(Freq *( bitrate+1)* 2)<<16) / i2sPclk;
366  for (y = 255; y > 0; y--) {
367  x = y * divider;
368  dif = x & 0xFFFF;
369  if(dif>0x8000) error = 0x10000-dif;
370  else error = dif;
371  if (error == 0)
372  {
373  y_divide = y;
374  break;
375  }
376  else if (error < ErrorOptimal)
377  {
378  ErrorOptimal = error;
379  y_divide = y;
380  }
381  }
382  x_divide = (y_divide * Freq *( bitrate+1)* 2)/i2sPclk;
383  if (TRMode == I2S_TX_MODE)// Transmitter
384  {
385  I2Sx->I2STXRATE = y_divide | (x_divide << 8);
386  } else //Receiver
387  {
388  I2Sx->I2SRXRATE = y_divide | (x_divide << 8);
389  }
390  return SUCCESS;
391 }
392 
393 /********************************************************************/
404 void I2S_SetBitRate(LPC_I2S_TypeDef *I2Sx, uint8_t bitrate, uint8_t TRMode)
405 {
406  CHECK_PARAM(PARAM_I2Sx(I2Sx));
407  CHECK_PARAM(PARAM_I2S_BITRATE(bitrate));
408  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
409 
410  if(TRMode == I2S_TX_MODE)
411  {
412  I2Sx->I2STXBITRATE = bitrate;
413  }
414  else
415  {
416  I2Sx->I2SRXBITRATE = bitrate;
417  }
418 }
419 
420 /********************************************************************/
430 void I2S_ModeConfig(LPC_I2S_TypeDef *I2Sx, I2S_MODEConf_Type* ModeConfig,
431  uint8_t TRMode)
432 {
433  CHECK_PARAM(PARAM_I2Sx(I2Sx));
434  CHECK_PARAM(PARAM_I2S_CLKSEL(ModeConfig->clksel));
435  CHECK_PARAM(PARAM_I2S_4PIN(ModeConfig->fpin));
436  CHECK_PARAM(PARAM_I2S_MCLK(ModeConfig->mcena));
437  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
438 
439  if (TRMode == I2S_TX_MODE) {
440  I2Sx->I2STXMODE &= ~0x0F; //clear bit 3:0 in I2STXMODE register
441  if (ModeConfig->clksel == I2S_CLKSEL_MCLK) {
442  I2Sx->I2STXMODE |= 0x02;
443  }
444  if (ModeConfig->fpin == I2S_4PIN_ENABLE) {
445  I2Sx->I2STXMODE |= (1 << 2);
446  }
447  if (ModeConfig->mcena == I2S_MCLK_ENABLE) {
448  I2Sx->I2STXMODE |= (1 << 3);
449  }
450  } else {
451  I2Sx->I2SRXMODE &= ~0x0F; //clear bit 3:0 in I2STXMODE register
452  if (ModeConfig->clksel == I2S_CLKSEL_MCLK) {
453  I2Sx->I2SRXMODE |= 0x02;
454  }
455  if (ModeConfig->fpin == I2S_4PIN_ENABLE) {
456  I2Sx->I2SRXMODE |= (1 << 2);
457  }
458  if (ModeConfig->mcena == I2S_MCLK_ENABLE) {
459  I2Sx->I2SRXMODE |= (1 << 3);
460  }
461  }
462 }
463 
464 /********************************************************************/
473 void I2S_DMAConfig(LPC_I2S_TypeDef *I2Sx, I2S_DMAConf_Type* DMAConfig,
474  uint8_t TRMode)
475 {
476  CHECK_PARAM(PARAM_I2Sx(I2Sx));
477  CHECK_PARAM(PARAM_I2S_DMA(DMAConfig->DMAIndex));
479  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
480 
481  if (TRMode == I2S_RX_MODE) {
482  if (DMAConfig->DMAIndex == I2S_DMA_1) {
483  LPC_I2S->I2SDMA1 = (DMAConfig->depth) << 8;
484  } else {
485  LPC_I2S->I2SDMA2 = (DMAConfig->depth) << 8;
486  }
487  } else {
488  if (DMAConfig->DMAIndex == I2S_DMA_1) {
489  LPC_I2S->I2SDMA1 = (DMAConfig->depth) << 16;
490  } else {
491  LPC_I2S->I2SDMA2 = (DMAConfig->depth) << 16;
492  }
493  }
494 }
495 
496 /********************************************************************/
510 void I2S_DMACmd(LPC_I2S_TypeDef *I2Sx, uint8_t DMAIndex, uint8_t TRMode,
511  FunctionalState NewState)
512 {
513  CHECK_PARAM(PARAM_I2Sx(I2Sx));
515  CHECK_PARAM(PARAM_I2S_DMA(DMAIndex));
516  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
517 
518  if (TRMode == I2S_RX_MODE) {
519  if (DMAIndex == I2S_DMA_1) {
520  if (NewState == ENABLE)
521  I2Sx->I2SDMA1 |= 0x01;
522  else
523  I2Sx->I2SDMA1 &= ~0x01;
524  } else {
525  if (NewState == ENABLE)
526  I2Sx->I2SDMA2 |= 0x01;
527  else
528  I2Sx->I2SDMA2 &= ~0x01;
529  }
530  } else {
531  if (DMAIndex == I2S_DMA_1) {
532  if (NewState == ENABLE)
533  I2Sx->I2SDMA1 |= 0x02;
534  else
535  I2Sx->I2SDMA1 &= ~0x02;
536  } else {
537  if (NewState == ENABLE)
538  I2Sx->I2SDMA2 |= 0x02;
539  else
540  I2Sx->I2SDMA2 &= ~0x02;
541  }
542  }
543 }
544 
545 /********************************************************************/
554 void I2S_IRQConfig(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, uint8_t level) {
555  CHECK_PARAM(PARAM_I2Sx(I2Sx));
556  CHECK_PARAM(PARAM_I2S_TRX(TRMode));
558 
559  if (TRMode == I2S_RX_MODE) {
560  I2Sx->I2SIRQ |= (level << 8);
561  } else {
562  I2Sx->I2SIRQ |= (level << 16);
563  }
564 }
565 
566 /********************************************************************/
577 void I2S_IRQCmd(LPC_I2S_TypeDef *I2Sx, uint8_t TRMode, FunctionalState NewState) {
578  CHECK_PARAM(PARAM_I2Sx(I2Sx));
580 
581  if (TRMode == I2S_RX_MODE) {
582  if (NewState == ENABLE)
583  I2Sx->I2SIRQ |= 0x01;
584  else
585  I2Sx->I2SIRQ &= ~0x01;
586  //Enable DMA
587 
588  } else {
589  if (NewState == ENABLE)
590  I2Sx->I2SIRQ |= 0x02;
591  else
592  I2Sx->I2SIRQ &= ~0x02;
593  }
594 }
595 
596 /********************************************************************/
607 {
608  CHECK_PARAM(PARAM_I2Sx(I2Sx));
609  if(TRMode == I2S_TX_MODE)
610  return ((I2Sx->I2SIRQ >> 1)&0x01);
611  else
612  return ((I2Sx->I2SIRQ)&0x01);
613 }
614 
615 /********************************************************************/
623 uint8_t I2S_GetIRQDepth(LPC_I2S_TypeDef *I2Sx,uint8_t TRMode)
624 {
625  CHECK_PARAM(PARAM_I2Sx(I2Sx));
626  if(TRMode == I2S_TX_MODE)
627  return (((I2Sx->I2SIRQ)>>16)&0xFF);
628  else
629  return (((I2Sx->I2SIRQ)>>8)&0xFF);
630 }
635 #endif /* _I2S */
636 
641 /* --------------------------------- End Of File ------------------------------ */
642