LPCOpen Platform for LPC18XX/43XX microcontrollers: C:/w/lpcopen_docs/software/lpc_core/lpc_chip/chip_18xx_43xx/i2s_18xx_43xx.c Source File

| LPCOpen Platform for LPC18XX/43XX microcontrollers 18XX43XX LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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 "chip.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
38 /*****************************************************************************
39 * Public types/enumerations/variables
40 ****************************************************************************/
41
42 /*****************************************************************************
43 * Private functions
44 ****************************************************************************/
45
46 /* Get divider value */
47 STATIC Status getClkDiv(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format, uint16_t *pxDiv, uint16_t *pyDiv, uint32_t *pN)
48 {
49 uint32_t pClk;
50 uint32_t x, y;
51 uint64_t divider;
52 uint16_t dif;
53 uint16_t xDiv = 0, yDiv = 0;
54 uint32_t N;
55 uint16_t err, ErrorOptimal = 0xFFFF;
56
57 pClk = Chip_Clock_GetRate(CLK_APB1_I2S);
58
59 /* divider is a fixed point number with 16 fractional bits */
60 divider = (((uint64_t) (format->SampleRate) * 2 * (format->WordWidth) * 2) << 16) / pClk;
61 /* find N that make x/y <= 1 -> divider <= 2^16 */
62 for (N = 64; N > 0; N--) {
63 if ((divider * N) < (1 << 16)) {
64 break;
65 }
66 }
67 if (N == 0) {
68 return ERROR;
69 }
70 divider *= N;
71 for (y = 255; y > 0; y--) {
72 x = y * divider;
73 if (x & (0xFF000000)) {
74 continue;
75 }
76 dif = x & 0xFFFF;
77 if (dif > 0x8000) {
78 err = 0x10000 - dif;
79 }
80 else {
81 err = dif;
82 }
83 if (err == 0) {
84 yDiv = y;
85 break;
86 }
87 else if (err < ErrorOptimal) {
88 ErrorOptimal = err;
89 yDiv = y;
90 }
91 }
92 xDiv = ((uint64_t) yDiv * (format->SampleRate) * 2 * (format->WordWidth) * N * 2) / pClk;
93 if (xDiv >= 256) {
94 xDiv = 0xFF;
95 }
96 if (xDiv == 0) {
97 xDiv = 1;
98 }
99
100 *pxDiv = xDiv;
101 *pyDiv = yDiv;
102 *pN = N;
103 return SUCCESS;
104 }
105
106 /*****************************************************************************
107 * Public functions
108 ****************************************************************************/
109
110 /* Initialize the I2S interface */
111 void Chip_I2S_Init(LPC_I2S_T *pI2S)
112 {
113 Chip_Clock_Enable(CLK_APB1_I2S);
114 }
115
116 /* Shutdown I2S */
117 void Chip_I2S_DeInit(LPC_I2S_T *pI2S)
118 {
119 pI2S->DAI = 0x07E1;
120 pI2S->DAO = 0x87E1;
121 pI2S->IRQ = 0;
122 pI2S->TXMODE = 0;
123 pI2S->RXMODE = 0;
124 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] = 0;
125 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] = 0;
126 Chip_Clock_Disable(CLK_APB1_I2S);
127 }
128
129 /* Configure I2S for Audio Format input */
130 Status Chip_I2S_TxConfig(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format)
131 {
132 uint32_t temp;
133 uint16_t xDiv, yDiv;
134 uint32_t N;
135
136 if (getClkDiv(pI2S, format, &xDiv, &yDiv, &N) == ERROR) {
137 return ERROR;
138 }
139
140 temp = pI2S->DAO & (~(I2S_DAO_WORDWIDTH_MASK | I2S_DAO_MONO | I2S_DAO_SLAVE | I2S_DAO_WS_HALFPERIOD_MASK));
141 if (format->WordWidth <= 8) {
142 temp |= I2S_WORDWIDTH_8;
143 }
144 else if (format->WordWidth <= 16) {
145 temp |= I2S_WORDWIDTH_16;
146 }
147 else {
148 temp |= I2S_WORDWIDTH_32;
149 }
150
151 temp |= (format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO;
152 temp |= I2S_MASTER_MODE;
153 temp |= I2S_DAO_WS_HALFPERIOD(format->WordWidth - 1);
154 pI2S->DAO = temp;
155 pI2S->TXMODE = I2S_TXMODE_CLKSEL(0);
156 pI2S->TXBITRATE = N - 1;
157 pI2S->TXRATE = yDiv | (xDiv << 8);
158 return SUCCESS;
159 }
160
161 /* Configure I2S for Audio Format input */
162 Status Chip_I2S_RxConfig(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format)
163 {
164 uint32_t temp;
165 uint16_t xDiv, yDiv;
166 uint32_t N;
167
168 if (getClkDiv(pI2S, format, &xDiv, &yDiv, &N) == ERROR) {
169 return ERROR;
170 }
171 temp = pI2S->DAI & (~(I2S_DAI_WORDWIDTH_MASK | I2S_DAI_MONO | I2S_DAI_SLAVE | I2S_DAI_WS_HALFPERIOD_MASK));
172 if (format->WordWidth <= 8) {
173 temp |= I2S_WORDWIDTH_8;
174 }
175 else if (format->WordWidth <= 16) {
176 temp |= I2S_WORDWIDTH_16;
177 }
178 else {
179 temp |= I2S_WORDWIDTH_32;
180 }
181
182 temp |= (format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO;
183 temp |= I2S_MASTER_MODE;
184 temp |= I2S_DAI_WS_HALFPERIOD(format->WordWidth - 1);
185 pI2S->DAI = temp;
186 pI2S->RXMODE = I2S_RXMODE_CLKSEL(0);
187 pI2S->RXBITRATE = N - 1;
188 pI2S->RXRATE = yDiv | (xDiv << 8);
189 return SUCCESS;
190 }
191
192 /* Enable/Disable Interrupt with a specific FIFO depth */
193 void Chip_I2S_Int_TxCmd(LPC_I2S_T *pI2S, FunctionalState newState, uint8_t depth)
194 {
195 uint32_t temp;
196 depth &= 0x0F;
197 if (newState == ENABLE) {
198 temp = pI2S->IRQ & (~I2S_IRQ_TX_DEPTH_MASK);
199 pI2S->IRQ = temp | (I2S_IRQ_TX_DEPTH(depth));
200 pI2S->IRQ |= 0x02;
201 }
202 else {
203 pI2S->IRQ &= (~0x02);
204 }
205 }
206
207 /* Enable/Disable Interrupt with a specific FIFO depth */
208 void Chip_I2S_Int_RxCmd(LPC_I2S_T *pI2S, FunctionalState newState, uint8_t depth)
209 {
210 uint32_t temp;
211 depth &= 0x0F;
212 if (newState == ENABLE) {
213 temp = pI2S->IRQ & (~I2S_IRQ_RX_DEPTH_MASK);
214 pI2S->IRQ = temp | (I2S_IRQ_RX_DEPTH(depth));
215 pI2S->IRQ |= 0x01;
216 }
217 else {
218 pI2S->IRQ &= (~0x01);
219 }
220 }
221
222 /* Enable/Disable DMA with a specific FIFO depth */
223 void Chip_I2S_DMA_TxCmd(LPC_I2S_T *pI2S,
224 I2S_DMA_CHANNEL_T dmaNum,
225 FunctionalState newState,
226 uint8_t depth)
227 {
228 /* Enable/Disable I2S transmit*/
229 if (newState == ENABLE) {
230 /* Set FIFO Level */
231 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] &= ~(0x0F << 16);
232 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] |= depth << 16;
233 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] |= 0x02;
234 }
235 else {
236 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_1] &= ~0x02;
237 }
238 }
239
240 /* Enable/Disable DMA with a specific FIFO depth */
241 void Chip_I2S_DMA_RxCmd(LPC_I2S_T *pI2S,
242 I2S_DMA_CHANNEL_T dmaNum,
243 FunctionalState newState,
244 uint8_t depth)
245 {
246
247 /* Enable/Disable I2S Receive */
248 if (newState == ENABLE) {
249 /* Set FIFO Level */
250 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] &= ~(0x0F << 8);
251 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] |= depth << 8;
252 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] |= 0x01;
253 }
254 else {
255 pI2S->DMA[I2S_DMA_REQUEST_CHANNEL_2] &= ~0x01;
256 }
257 }
258