LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
i2s_18xx_43xx.c
Go to the documentation of this file.
1 /*
2  * @brief LPC18xx/43xx I2S driver
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include "i2s_18xx_43xx.h"
33 #include "scu_18xx_43xx.h"
34 
35 /*****************************************************************************
36  * Private types/enumerations/variables
37  ****************************************************************************/
38 
39 /*****************************************************************************
40  * Public types/enumerations/variables
41  ****************************************************************************/
42 
43 /*****************************************************************************
44  * Private functions
45  ****************************************************************************/
46 
47 /*****************************************************************************
48  * Public functions
49  ****************************************************************************/
50 
51 /* Configure I2S for Audio Format input */
52 Status Chip_I2S_Config(LPC_I2S_Type *I2Sx, uint8_t TRMode, Chip_I2S_Audio_Format_Type *audio_format)
53 {
54  uint32_t pClk;
55  uint32_t x, y;
56  uint64_t divider;
57  uint16_t dif;
58  uint16_t x_divide = 0, y_divide = 0;
59  uint32_t N;
60  uint16_t err, ErrorOptimal = 0xFFFF;
61 
62  pClk = (uint64_t)Chip_Clock_GetRate(CLK_APB1_I2S);
63 
64  /* divider is a fixed point number with 16 fractional bits */
65  divider = (((uint64_t)(audio_format->SampleRate) * 2 * (audio_format->WordWidth) * 2) << 16) / pClk;
66  /* find N that make x/y <= 1 -> divider <= 2^16 */
67  for (N = 64; N > 0; N--) {
68  if ((divider * N) < (1 << 16)) {
69  break;
70  }
71  }
72  if (N == 0) {
73  return ERROR;
74  }
75  divider *= N;
76  for (y = 255; y > 0; y--) {
77  x = y * divider;
78  if (x & (0xFF000000)) {
79  continue;
80  }
81  dif = x & 0xFFFF;
82  if (dif > 0x8000) {
83  err = 0x10000 - dif;
84  }
85  else {
86  err = dif;
87  }
88  if (err == 0) {
89  y_divide = y;
90  break;
91  }
92  else if (err < ErrorOptimal) {
93  ErrorOptimal = err;
94  y_divide = y;
95  }
96  }
97  x_divide = ((uint64_t)y_divide * (audio_format->SampleRate) * 2 * (audio_format->WordWidth) * N * 2) / pClk;
98  if (x_divide >= 256) {
99  x_divide = 0xFF;
100  }
101  if (x_divide == 0) {
102  x_divide = 1;
103  }
104  if (audio_format->WordWidth <= 8) {
105  IP_I2S_SetWordWidth(I2Sx, TRMode, I2S_WORDWIDTH_8);
106  }
107  else if (audio_format->WordWidth <= 16) {
108  IP_I2S_SetWordWidth(I2Sx, TRMode, I2S_WORDWIDTH_16);
109  }
110  else {
111  IP_I2S_SetWordWidth(I2Sx, TRMode, I2S_WORDWIDTH_32);
112  }
113  IP_I2S_SetMono(I2Sx, TRMode, (audio_format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO);
115  IP_I2S_SetWS_Halfperiod(I2Sx, TRMode, audio_format->WordWidth - 1);
117  IP_I2S_SetBitRate(I2Sx, TRMode, N - 1);
118  IP_I2S_SetXYDivider(I2Sx, TRMode, x_divide, y_divide);
119  return SUCCESS;
120 }
121 
122 /* Enable/Disable Interrupt with a specific FIFO depth */
123 void Chip_I2S_Int_Cmd(LPC_I2S_Type *I2Sx, uint8_t TRMode, FunctionalState NewState, uint8_t FIFO_Depth)
124 {
125  IP_I2S_InterruptCmd(I2Sx, TRMode, NewState);
126  IP_I2S_SetFIFODepthIRQ(I2Sx, TRMode, FIFO_Depth);
127 }
128 
129 /* Enable/Disable DMA with a specific FIFO depth */
131  uint8_t TRMode,
132  uint8_t DMANum,
133  FunctionalState NewState,
134  uint8_t FIFO_Depth)
135 {
136  IP_I2S_SetFIFODepthDMA(I2Sx, TRMode, (IP_I2S_DMARequestNumber_Type) DMANum, FIFO_Depth);
137  IP_I2S_DMACmd(I2Sx, (IP_I2S_DMARequestNumber_Type) DMANum, TRMode, NewState);
138 }