CC13xx Driver Library
i2s.c
Go to the documentation of this file.
1 /******************************************************************************
2 * Filename: i2s.c
3 * Revised: 2015-05-11 13:56:01 +0200 (Mon, 11 May 2015)
4 * Revision: 43476
5 *
6 * Description: Driver for the I2S.
7 *
8 * Copyright (c) 2015, Texas Instruments Incorporated
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 *
14 * 1) Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 *
17 * 2) Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 *
21 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38 
39 #include <driverlib/i2s.h>
40 
41 //*****************************************************************************
42 //
43 // Handle support for DriverLib in ROM:
44 // This section will undo prototype renaming made in the header file
45 //
46 //*****************************************************************************
47 #if !defined(DOXYGEN)
48  #undef I2SEnable
49  #define I2SEnable NOROM_I2SEnable
50  #undef I2SAudioFormatConfigure
51  #define I2SAudioFormatConfigure NOROM_I2SAudioFormatConfigure
52  #undef I2SChannelConfigure
53  #define I2SChannelConfigure NOROM_I2SChannelConfigure
54  #undef I2SBufferConfig
55  #define I2SBufferConfig NOROM_I2SBufferConfig
56  #undef I2SPointerUpdate
57  #define I2SPointerUpdate NOROM_I2SPointerUpdate
58  #undef I2SPointerSet
59  #define I2SPointerSet NOROM_I2SPointerSet
60  #undef I2SSampleStampConfigure
61  #define I2SSampleStampConfigure NOROM_I2SSampleStampConfigure
62  #undef I2SSampleStampGet
63  #define I2SSampleStampGet NOROM_I2SSampleStampGet
64 #endif
65 
66 //*****************************************************************************
67 //
68 // Global pointer to the current I2S data structure
69 //
70 //*****************************************************************************
72 
73 //*****************************************************************************
74 //
76 //
77 //*****************************************************************************
78 void
79 I2SEnable(uint32_t ui32Base)
80 {
81  //
82  // Check the arguments.
83  //
84  ASSERT(I2SBaseValid(ui32Base));
85 
86  //
87  // Make sure the control table pointer is setup to a memory location.
88  //
89  if(!(g_pControlTable))
90  {
91  return;
92  }
93 
94  //
95  // Write the address to the first input/output buffer.
96  //
97  HWREG(I2S0_BASE + I2S_O_AIFINPTRNEXT) = g_pControlTable->ui32InBase;
98  g_pControlTable->ui32InOffset = 0;
99  HWREG(I2S0_BASE + I2S_O_AIFOUTPTRNEXT) = g_pControlTable->ui32OutBase;
100  g_pControlTable->ui32OutOffset = 0;
101 
102  //
103  // Enable the I2S module.
104  //
105  HWREG(I2S0_BASE + I2S_O_AIFDMACFG) = (uint32_t)g_pControlTable->ui16DMABufSize - 1;
106 }
107 
108 //*****************************************************************************
109 //
111 //
112 //*****************************************************************************
113 void
114 I2SAudioFormatConfigure(uint32_t ui32Base, uint32_t ui32FmtCfg,
115  uint32_t ui32BitClkDelay)
116 {
117  //
118  // Check the arguments.
119  //
120  ASSERT(I2SBaseValid(ui32Base));
121  ASSERT(ui32BitClkDelay <= 255);
122 
123  //
124  // Save the length of the audio words stored in memory.
125  //
126  g_pControlTable->ui16MemLen = (ui32FmtCfg & I2S_MEM_LENGTH_24) ? 24 : 16;
127 
128  //
129  // Write the configuration.
130  //
131  HWREG(I2S0_BASE + I2S_O_AIFFMTCFG) = ui32FmtCfg | (ui32BitClkDelay << I2S_AIFFMTCFG_DATA_DELAY_S);
132 }
133 
134 //****************************************************************************
135 //
137 //
138 //****************************************************************************
139 void
140 I2SChannelConfigure(uint32_t ui32Base, uint32_t ui32Chan0Cfg,
141  uint32_t ui32Chan1Cfg, uint32_t ui32Chan2Cfg)
142 {
143  uint32_t ui32InChan;
144  uint32_t ui32OutChan;
145  uint32_t ui32ChanMask;
146 
147  //
148  // Check the arguments.
149  //
150  ASSERT(I2SBaseValid(ui32Base));
151  ASSERT(ui32Chan0Cfg & (I2S_CHAN_CFG_MASK | I2S_LINE_MASK))
152  ASSERT(ui32Chan1Cfg & (I2S_CHAN_CFG_MASK | I2S_LINE_MASK))
153  ASSERT(ui32Chan2Cfg & (I2S_CHAN_CFG_MASK | I2S_LINE_MASK))
154 
155  ui32InChan = 0;
156  ui32OutChan = 0;
157 
158  //
159  // Configure input/output channels.
160  //
161  HWREG(I2S0_BASE + I2S_O_AIFDIRCFG) = ((ui32Chan0Cfg << I2S_AIFDIRCFG_AD0_S)
163  ((ui32Chan1Cfg << I2S_AIFDIRCFG_AD1_S)
165  ((ui32Chan2Cfg << I2S_AIFDIRCFG_AD2_S)
167 
168  //
169  // Configure the valid channel mask.
170  //
171  HWREG(I2S0_BASE + I2S_O_AIFWMASK0) = (ui32Chan0Cfg >> 8) & I2S_AIFWMASK0_MASK_M;
172  HWREG(I2S0_BASE + I2S_O_AIFWMASK1) = (ui32Chan1Cfg >> 8) & I2S_AIFWMASK1_MASK_M;
173  HWREG(I2S0_BASE + I2S_O_AIFWMASK2) = (ui32Chan2Cfg >> 8) & I2S_AIFWMASK2_MASK_M;
174 
175  //
176  // Resolve and save the number of input and output channels.
177  //
178  ui32ChanMask = (ui32Chan0Cfg & I2S_CHAN_CFG_MASK) >> 8;
179  if(ui32Chan0Cfg & I2S_LINE_INPUT)
180  {
181  while(ui32ChanMask)
182  {
183  if(ui32ChanMask & 0x1)
184  {
185  ui32InChan++;
186  }
187  //
188  // Shift down channel mask
189  //
190  ui32ChanMask >>= 1;
191  }
192 
193  }
194  else if(ui32Chan0Cfg & I2S_LINE_OUTPUT)
195  {
196  while(ui32ChanMask)
197  {
198  if(ui32ChanMask & 0x1)
199  {
200  ui32OutChan++;
201  }
202  //
203  // Shift down channel mask
204  //
205  ui32ChanMask >>= 1;
206  }
207  }
208 
209  ui32ChanMask = (ui32Chan1Cfg & I2S_CHAN_CFG_MASK) >> 8;
210  if(ui32Chan1Cfg & I2S_LINE_INPUT)
211  {
212  while(ui32ChanMask)
213  {
214  if(ui32ChanMask & 0x1)
215  {
216  ui32InChan++;
217  }
218  //
219  // Shift down channel mask
220  //
221  ui32ChanMask >>= 1;
222  }
223  }
224  else if(ui32Chan1Cfg & I2S_LINE_OUTPUT)
225  {
226  while(ui32ChanMask)
227  {
228  if(ui32ChanMask & 0x1)
229  {
230  ui32OutChan++;
231  }
232  //
233  // Shift down channel mask
234  //
235  ui32ChanMask >>= 1;
236  }
237  }
238 
239  ui32ChanMask = (ui32Chan2Cfg & I2S_CHAN_CFG_MASK) >> 8;
240  if(ui32Chan2Cfg & I2S_LINE_INPUT)
241  {
242  while(ui32ChanMask)
243  {
244  if(ui32ChanMask & 0x1)
245  {
246  ui32InChan++;
247  }
248  //
249  // Shift down channel mask
250  //
251  ui32ChanMask >>= 1;
252  }
253  }
254  else if(ui32Chan2Cfg & I2S_LINE_OUTPUT)
255  {
256  while(ui32ChanMask)
257  {
258  if(ui32ChanMask & 0x1)
259  {
260  ui32OutChan++;
261  }
262  //
263  // Shift down channel mask
264  //
265  ui32ChanMask >>= 1;
266  }
267  }
268 
269  g_pControlTable->ui8InChan = (uint8_t)ui32InChan;
270  g_pControlTable->ui8OutChan = (uint8_t)ui32OutChan;
271 }
272 
273 //****************************************************************************
274 //
276 //
277 //****************************************************************************
278 void
279 I2SBufferConfig(uint32_t ui32Base, uint32_t ui32InBufBase,
280  uint32_t ui32OutBufBase, uint16_t ui16DMABufSize,
281  uint16_t ui16ChanBufSize)
282 {
283  //
284  // Check the arguments.
285  //
286  ASSERT(I2SBaseValid(ui32Base));
287  ASSERT(ui16DMABufSize > 0);
288 
289  //
290  // Setup the input data pointer and buffer sizes.
291  //
292  g_pControlTable->ui16DMABufSize = ui16DMABufSize;
293  g_pControlTable->ui16ChBufSize = ui16ChanBufSize;
294  g_pControlTable->ui32InBase = ui32InBufBase;
295  g_pControlTable->ui32OutBase = ui32OutBufBase;
296 }
297 
298 //****************************************************************************
299 //
301 //
302 //****************************************************************************
303 void
304 I2SPointerSet(uint32_t ui32Base, bool bInput, void * pNextPointer)
305 {
306  //
307  // Check the arguments.
308  //
309  ASSERT(I2SBaseValid(ui32Base));
310 
311  //
312  // Update the next input/output pointer with the correct address.
313  //
314  if(bInput == true)
315  {
316  HWREG(I2S0_BASE + I2S_O_AIFINPTRNEXT) = (uint32_t)pNextPointer;
317  }
318  else
319  {
320  HWREG(I2S0_BASE + I2S_O_AIFOUTPTRNEXT) = (uint32_t)pNextPointer;
321  }
322 }
323 
324 //****************************************************************************
325 //
327 //
328 //****************************************************************************
329 void
330 I2SPointerUpdate(uint32_t ui32Base, bool bInput)
331 {
332  uint32_t ui32NextPtr;
333 
334  //
335  // Check the arguments.
336  //
337  ASSERT(I2SBaseValid(ui32Base));
338 
339  //
340  // Update the next input/output pointer with the correct address.
341  //
342  if(bInput == true)
343  {
344  ui32NextPtr = (g_pControlTable->ui8InChan *
345  (g_pControlTable->ui16MemLen >> 3)) *
346  g_pControlTable->ui16DMABufSize;
347  g_pControlTable->ui32InOffset = ((g_pControlTable->ui32InOffset +
348  ui32NextPtr) %
349  g_pControlTable->ui16ChBufSize);
350  HWREG(I2S0_BASE + I2S_O_AIFINPTRNEXT) = g_pControlTable->ui32InOffset +
351  g_pControlTable->ui32InBase;
352  }
353  else
354  {
355  ui32NextPtr = (g_pControlTable->ui8OutChan *
356  (g_pControlTable->ui16MemLen >> 3)) *
357  g_pControlTable->ui16DMABufSize;
358  g_pControlTable->ui32OutOffset = ((g_pControlTable->ui32OutOffset +
359  ui32NextPtr) %
360  g_pControlTable->ui16ChBufSize);
361  HWREG(I2S0_BASE + I2S_O_AIFOUTPTRNEXT) =
362  g_pControlTable->ui32OutOffset +
363  g_pControlTable->ui32OutBase;
364  }
365 }
366 
367 //*****************************************************************************
368 //
370 //
371 //*****************************************************************************
372 void
373 I2SSampleStampConfigure(uint32_t ui32Base, bool bInput, bool bOutput)
374 {
375  uint32_t ui32Trigger;
376 
377  //
378  // Check the arguments.
379  //
380  ASSERT(I2SBaseValid(ui32Base));
381 
382  ui32Trigger = HWREG(I2S0_BASE + I2S_O_STMPWCNT);
383  ui32Trigger = (ui32Trigger + 2) % g_pControlTable->ui16ChBufSize;
384 
385  //
386  // Setup the sample stamp trigger for input streams.
387  //
388  if(bInput)
389  {
390  HWREG(I2S0_BASE + I2S_O_STMPINTRIG) = ui32Trigger;
391  }
392 
393  //
394  // Setup the sample stamp trigger for output streams.
395  //
396  if(bOutput)
397  {
398  HWREG(I2S0_BASE + I2S_O_STMPOUTTRIG) = ui32Trigger;
399  }
400 
401 }
402 
403 //*****************************************************************************
404 //
406 //
407 //*****************************************************************************
408 uint32_t
409 I2SSampleStampGet(uint32_t ui32Base, uint32_t ui32Channel)
410 {
411  uint32_t ui32FrameClkCnt;
412  uint32_t ui32SysClkCnt;
413  uint32_t ui32PeriodSysClkCnt;
414  uint32_t ui32SampleStamp;
415 
416  //
417  // Get the number of Frame clock counts since last stamp.
418  //
419  ui32FrameClkCnt = HWREG(I2S0_BASE + I2S_O_STMPWCNTCAPT0);
420 
421  //
422  // Get the number of system clock ticks since last frame clock edge.
423  //
424  ui32SysClkCnt = HWREG(I2S0_BASE + I2S_O_STMPXCNTCAPT0);
425 
426  //
427  // Get the number system clock ticks in the last frame clock period.
428  //
429  ui32PeriodSysClkCnt = HWREG(I2S0_BASE + I2S_O_STMPXPER);
430 
431  //
432  // Calculate the sample stamp.
433  //
434  ui32SampleStamp = (ui32SysClkCnt << 16) / ui32PeriodSysClkCnt;
435  ui32SampleStamp = (ui32SampleStamp > I2S_STMP_SATURATION) ?
436  I2S_STMP_SATURATION : ui32SampleStamp;
437  ui32SampleStamp |= (ui32FrameClkCnt << 16);
438 
439  return (ui32SampleStamp);
440 }
void I2SSampleStampConfigure(uint32_t ui32Base, bool bInput, bool bOutput)
Configure the sample stamp generator.
Definition: i2s.c:373
void I2SPointerSet(uint32_t ui32Base, bool bInput, void *pNextPointer)
Set the buffer pointers.
Definition: i2s.c:304
#define I2S_LINE_MASK
Definition: i2s.h:169
void I2SBufferConfig(uint32_t ui32Base, uint32_t ui32InBufBase, uint32_t ui32OutBufBase, uint16_t ui16DMABufSize, uint16_t ui16ChanBufSize)
Set the input buffer pointers.
Definition: i2s.c:279
#define I2S_CHAN_CFG_MASK
Definition: i2s.h:186
#define I2S_LINE_INPUT
Definition: i2s.h:167
uint16_t ui16DMABufSize
Size of DMA buffer in number of samples.
Definition: i2s.h:118
#define I2S_MEM_LENGTH_24
Definition: i2s.h:194
uint32_t ui32InOffset
Value of the current input pointer offset.
Definition: i2s.h:124
uint32_t I2SSampleStampGet(uint32_t ui32Base, uint32_t ui32Channel)
Get the current value of a sample stamp counter.
Definition: i2s.c:409
uint32_t ui32OutOffset
Value of the current output pointer offset.
Definition: i2s.h:126
uint32_t ui32OutBase
Base address of the output buffer.
Definition: i2s.h:125
void I2SPointerUpdate(uint32_t ui32Base, bool bInput)
Update the buffer pointers.
Definition: i2s.c:330
uint16_t ui16MemLen
Length of the audio words stored in memory.
Definition: i2s.h:122
A structure that defines an audio control table. Note: Memory for this structure must be initialized ...
Definition: i2s.h:116
uint8_t ui8InChan
Input Channel.
Definition: i2s.h:120
#define ASSERT(expr)
Definition: debug.h:74
void I2SEnable(uint32_t ui32Base)
Enables the I2S module for operation.
Definition: i2s.c:79
uint32_t ui32InBase
Base address of the input buffer.
Definition: i2s.h:123
void I2SAudioFormatConfigure(uint32_t ui32Base, uint32_t ui32FmtCfg, uint32_t ui32BitClkDelay)
Configures the I2S module.
Definition: i2s.c:114
uint8_t ui8OutChan
Output Channel.
Definition: i2s.h:121
#define I2S_LINE_OUTPUT
Definition: i2s.h:168
#define I2S_STMP_SATURATION
Definition: i2s.h:210
void I2SChannelConfigure(uint32_t ui32Base, uint32_t ui32Chan0Cfg, uint32_t ui32Chan1Cfg, uint32_t ui32Chan2Cfg)
Setup the audio channel configuration.
Definition: i2s.c:140
I2SControlTable * g_pControlTable
Definition: i2s.c:71
uint16_t ui16ChBufSize
Size of Channel buffer.
Definition: i2s.h:119