1 /*\r
2 * Copyright (c) 2015, Texas Instruments Incorporated\r
3 * All rights reserved.\r
4 *\r
5 * Redistribution and use in source and binary forms, with or without\r
6 * modification, are permitted provided that the following conditions\r
7 * are met:\r
8 *\r
9 * * Redistributions of source code must retain the above copyright\r
10 * notice, this list of conditions and the following disclaimer.\r
11 *\r
12 * * Redistributions in binary form must reproduce the above copyright\r
13 * notice, this list of conditions and the following disclaimer in the\r
14 * documentation and/or other materials provided with the distribution.\r
15 *\r
16 * * Neither the name of Texas Instruments Incorporated nor the names of\r
17 * its contributors may be used to endorse or promote products derived\r
18 * from this software without specific prior written permission.\r
19 *\r
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31 *\r
32 */\r
33 \r
34 /**\r
35 * \file mcasp_config.c\r
36 *\r
37 * \brief Configures McASP module\r
38 *\r
39 */\r
40 \r
41 #include "mcasp_cfg.h"\r
42 #include "../include/cmbk2g.h"\r
43 \r
44 \r
45 /* The infamous xdc/std.h must come before any header file which uses XDC symbols */\r
46 #include <xdc/std.h> /* mandatory - have to include first, for BIOS types */\r
47 #include <ti/mas/types/types.h>\r
48 #include <ti/mas/aer/bf.h>\r
49 #include "../../../common/components/mss/mss.h" /* local version used */\r
50 #include <ti/mas/vpe/asnr.h>\r
51 \r
52 /*----------------------------------------\r
53 * BIOS header files\r
54 *----------------------------------------*/\r
55 #include <ti/sysbios/BIOS.h> /* mandatory - if you call APIs like BIOS_start() */\r
56 #include <xdc/cfg/global.h> /* header file for statically defined objects/handles */\r
57 #include <xdc/runtime/System.h> /* for System_printf, and similar */\r
58 #include <xdc/runtime/Timestamp.h> /* for benchmarking/profiling */\r
59 \r
60 #include <xdc/runtime/Log.h> /* for tracing */\r
61 #include <xdc/runtime/Diags.h>\r
62 #include <ti/uia/events/UIAEvt.h> /* and more tracing */\r
63 \r
64 #include <ti/sysbios/knl/Semaphore.h> /* this looks obvious */\r
65 \r
66 #include "fil.h" /* FILE I/O implementation */\r
67 #include "sys.h" /* System API and structures */\r
68 #include "sysbfflt.h" /* System support for BF filters */\r
69 \r
70 #define Timestamp_get Timestamp_get32 /* use 32-bit time stamps */\r
71 \r
72 #define MIN(a,b) (((a)>(b))?(b):(a)) /* Min/Max macros */\r
73 #define MAX(a,b) (((a)<(b))?(b):(a))\r
74 #define loop while(1) /* endless loop for the task */\r
75 \r
76 \r
77 /* Frame index for Rx and Tx buffers */\r
78 uint8_t rxFrameIndex = 1;\r
79 uint8_t txFrameIndex = 1;\r
80 uint32_t gtxFrameIndexCount = 0;\r
81 uint32_t grxFrameIndexCount = 0;\r
82 \r
83 /* Flags for counting Rx and Tx interrupts */\r
84 volatile uint32_t rxFlag = 0;\r
85 volatile uint32_t txFlag = 0;\r
86 \r
87 /* Semaphore handle for Tx and Rx */\r
88 Semaphore_Handle semR;\r
89 Semaphore_Handle semT;\r
90 Semaphore_Params params;\r
91 \r
92 /* McASP device handles */\r
93 Ptr hMcaspDevTx;\r
94 Ptr hMcaspDevRx;\r
95 \r
96 /* McASP channel handles */\r
97 Ptr hMcaspTxChan;\r
98 Ptr hMcaspRxChan;\r
99 \r
100 /* McASP channel parameters */\r
101 Mcasp_Params mcaspTxParams;\r
102 Mcasp_Params mcaspRxParams;\r
103 \r
104 /* McASP Callback function argument */\r
105 uint32_t txChanMode;\r
106 uint32_t rxChanMode;\r
107 uint32_t mcaspRxChanArg = 1;\r
108 uint32_t mcaspTxChanArg = 2;\r
109 \r
110 /* McASP Tx and Rx frame buffers */\r
111 MCASP_Packet rxFrame[NUM_BUFS];\r
112 MCASP_Packet txFrame[NUM_BUFS];\r
113 \r
114 /* McASP Tx and Rx frame buffer pointers */\r
115 Ptr txBuf[NUM_BUFS];\r
116 Ptr rxBuf[NUM_BUFS];\r
117 Ptr wkBuf[NUM_BUFS];\r
118 Ptr outBuf[NUM_BUFS];\r
119 \r
120 int chanToMicMapping[8] = {0, 1, 4, 5, 2, 3, 6, 7};\r
121 \r
122 /* Error flag */\r
123 uint32_t gblErrFlag = 0;\r
124 Error_Block eb;\r
125 \r
126 /* External function declarations */\r
127 void GblErr(int arg);\r
128 signed char* getGlobalAddr(signed char* addr);\r
129 \r
130 /* McASP HW setup for receive */\r
131 Mcasp_HwSetupData mcaspRcvSetup = {\r
132 /* .rmask = */ 0xFFFFFFFF, /* 16 bits are to be used */\r
133 /* .rfmt = */ 0x000180F0, /*\r
134 * 1 bit delay from framesync\r
135 * MSB first\r
136 * No extra bit padding\r
137 * Padding bit (ignore)\r
138 * slot Size is 32\r
139 * Reads from DMA port\r
140 * NO rotation\r
141 */\r
142 /* .afsrctl = */ 0X00000111, /* I2S mode - 2 slot TDM\r
143 * Frame sync is one word\r
144 * Externally generated frame sync\r
145 * Falling edge is start of frame\r
146 */\r
147 /* .rtdm = */ 0x00000003, /* slot 1 and 2 are active (I2S) */\r
148 /* .rintctl = */ 0x00000000, /* sync error and overrun error */\r
149 /* .rstat = */ 0x000001FF, /* reset any existing status bits */\r
150 /* .revtctl = */ 0x00000000, /* DMA request is enabled */\r
151 {\r
152 /* .aclkrctl = */ 0x00000080, /* Bit CLK Pol: falling edge, ACLKR is external */\r
153 /* .ahclkrctl = */ 0x00000000, /* AHCLKR is external */\r
154 /* .rclkchk = */ 0x00000000\r
155 }\r
156 };\r
157 \r
158 /* McASP HW setup for transmit */\r
159 #if (CMBK2G_AUDIO_DAC)\r
160 Mcasp_HwSetupData mcaspXmtSetup = {\r
161 /* .xmask = */ 0xFFFFFFFF, /* 16 bits are to be used */\r
162 /* .xfmt = */ 0x000180F0, /*\r
163 * 1 bit delay from framesync\r
164 * MSB first\r
165 * No extra bit padding\r
166 * Padding bit (ignore)\r
167 * slot Size is 32\r
168 * Reads from DMA port\r
169 * NO rotation\r
170 */\r
171 /* .afsxctl = */ 0x00000113, /* I2S mode - 2 slot TDM\r
172 * Frame sync is one word\r
173 * Falling edge is start of frame\r
174 * Externally generated frame sync\r
175 */\r
176 /* .xtdm = */ 0x00000003, /* slot 1 and 2 are active (I2S) */\r
177 /* .xintctl = */ 0x00000000, /* sync error,overrun error,clK error */\r
178 /* .xstat = */ 0x000001FF, /* reset any existing status bits */\r
179 /* .xevtctl = */ 0x00000000, /* DMA request is enabled or disabled */\r
180 {\r
181 #if (SYS_ADC_FS_HZ==16000)\r
182 /* .aclkxctl = */ 0X000000E3, /* Bit CLK Pol: falling edge, ASYNC is 1, ACLKX is internal, HF CLK to BCLK divider is 4 */\r
183 #else\r
184 /* .aclkxctl = */ 0X000000E7, /* Bit CLK Pol: falling edge, ASYNC is 1, ACLKX is internal, HF CLK to BCLK divider is 8 */\r
185 #endif\r
186 /* .ahclkxctl = */ 0x00000000, /* AHCLKX is external */\r
187 /* .xclkchk = */ 0x00000000\r
188 },\r
189 \r
190 };\r
191 #endif\r
192 \r
193 /* McAsp channel parameters for receive */\r
194 Mcasp_ChanParams mcaspRxChanParam =\r
195 {\r
196 0x0004, /* number of serializers */\r
197 {Mcasp_SerializerNum_0,\r
198 Mcasp_SerializerNum_1,\r
199 Mcasp_SerializerNum_2,\r
200 Mcasp_SerializerNum_3 }, /* serializer index */\r
201 &mcaspRcvSetup,\r
202 TRUE,\r
203 Mcasp_OpMode_TDM, /* Mode (TDM/DIT) */\r
204 Mcasp_WordLength_32,\r
205 NULL,\r
206 0,\r
207 NULL,\r
208 GblErr,\r
209 2, /* number of TDM channels */\r
210 ///Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1,\r
211 Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_2,\r
212 TRUE,\r
213 TRUE\r
214 };\r
215 \r
216 #if (CMBK2G_AUDIO_DAC)\r
217 /* McAsp channel parameters for transmit */\r
218 Mcasp_ChanParams mcaspTxChanParam =\r
219 {\r
220 0x0001, /* number of serializers */\r
221 {Mcasp_SerializerNum_2,}, /* serializer index for DAC0 */\r
222 &mcaspXmtSetup,\r
223 TRUE,\r
224 Mcasp_OpMode_TDM,\r
225 Mcasp_WordLength_32, /* word width */\r
226 NULL,\r
227 0,\r
228 NULL,\r
229 GblErr,\r
230 2, /* number of TDM channels */\r
231 Mcasp_BufferFormat_1SER_MULTISLOT_INTERLEAVED,\r
232 ///Mcasp_BufferFormat_1SER_MULTISLOT_NON_INTERLEAVED,\r
233 TRUE,\r
234 TRUE\r
235 };\r
236 #endif\r
237 \r
238 typedef struct txBfDebug_stc {\r
239 tulong frmcnt; /* normal frames */\r
240 tulong silcnt; /* silence frames */\r
241 tuint invsrc; /* no mic active, invalid output */\r
242 tuint invopt; /* >1 mic active, invalid output */\r
243 } txBfDebug_t;\r
244 \r
245 typedef struct txTaskDebug_stc {\r
246 tuint overrun; /* counts how many times we ran out of MIPS */\r
247 txBfDebug_t bf[SYS_VMICS_MAX]; /* beamformer statistics */\r
248 } txTaskDebug_t;\r
249 \r
250 txTaskDebug_t txTaskDebug; /* Tx task debug stats */\r
251 \r
252 /* Profiling/benchmarking information for the Tx task */\r
253 typedef struct txTaskProfileData_stc {\r
254 tulong min; /* Minimum number of cycles */\r
255 tulong max; /* Maximum number of cycles */\r
256 tulong n; /* Number of measurements */\r
257 float total; /* Total number of cycles */\r
258 } txTaskProfileData_t;\r
259 \r
260 typedef struct txTaskProfile_stc {\r
261 txTaskProfileData_t bf; /* Beamformer profile */\r
262 txTaskProfileData_t asnr; /* ASNR profile */\r
263 txTaskProfileData_t mss; /* MSS profile */\r
264 txTaskProfileData_t vau; /* VAU profile */\r
265 } txTaskProfile_t;\r
266 volatile txTaskProfile_t txTaskProfile = {\r
267 {~(0uL), 0, 0, 0.0f},\r
268 {~(0uL), 0, 0, 0.0f},\r
269 {~(0uL), 0, 0, 0.0f},\r
270 {~(0uL), 0, 0, 0.0f}\r
271 };\r
272 \r
273 /* To be used for debug trace */\r
274 mssSrc_t mssDbgCurSrc = {\r
275 -1, -1 /* Current source group/index */\r
276 };\r
277 mssSrc_t mssDbgNewSrc = {\r
278 -1, -1 /* New source group/index */\r
279 };\r
280 \r
281 /* Handle to eDMA */\r
282 extern EDMA3_DRV_Handle hEdma1;\r
283 \r
284 /**\r
285 * \brief Function called by McASP driver in case of error\r
286 *\r
287 * \return None\r
288 */\r
289 void GblErr(int arg)\r
290 {\r
291 gblErrFlag = 1;\r
292 }\r
293 \r
294 /**\r
295 * \brief McASP callback function called up on the data transfer completion\r
296 *\r
297 * \param arg [IN] - Application specific callback argument\r
298 * \param ioBuf [IN] - McASP IO buffer\r
299 *\r
300 * \return None\r
301 */\r
302 void mcaspAppCallback(void *arg, MCASP_Packet *ioBuf)\r
303 {\r
304 /* Callback is triggered by Rx completion */\r
305 if(ioBuf->cmd == MCASP_READ)\r
306 {\r
307 rxFlag++;\r
308 \r
309 if(rxFrameIndex == 0)\r
310 {\r
311 rxFrameIndex = 1;\r
312 }\r
313 else\r
314 {\r
315 rxFrameIndex = 0;\r
316 }\r
317 \r
318 /* Post semaphore */\r
319 Semaphore_post(semR);\r
320 }\r
321 \r
322 /* Callback is triggered by Tx completion */\r
323 if(ioBuf->cmd == MCASP_WRITE)\r
324 {\r
325 if(txFrameIndex == 0)\r
326 {\r
327 txFrameIndex = 1;\r
328 }\r
329 else\r
330 {\r
331 txFrameIndex = 0;\r
332 }\r
333 \r
334 txFlag++;\r
335 \r
336 /* Post semaphore */\r
337 Semaphore_post(semT);\r
338 }\r
339 }\r
340 \r
341 /**\r
342 * \brief Initializes McASP data buffers and submits to McASP driver\r
343 *\r
344 * \return Cmbk2g_EOK on Success or error code\r
345 */\r
346 Cmbk2g_STATUS initBuffers(void)\r
347 {\r
348 Error_Block eb;\r
349 uint32_t count = 0;\r
350 IHeap_Handle iheap;\r
351 Int status;\r
352 \r
353 iheap = HeapMem_Handle_to_xdc_runtime_IHeap(heapHandle);\r
354 Error_init(&eb);\r
355 \r
356 /* Allocate buffers for the McASP data exchanges */\r
357 for(count = 0; count < NUM_BUFS; count++)\r
358 {\r
359 rxBuf[count] = Memory_calloc(iheap, (BUFSIZE * RX_NUM_SERIALIZER),\r
360 BUFALIGN, &eb);\r
361 if(NULL == rxBuf[count])\r
362 {\r
363 IFPRINT(cmbk2g_write("\r\nMEM_calloc failed for Rx\n"));\r
364 }\r
365 }\r
366 \r
367 /* Allocate work buffers for signal processing */\r
368 for(count = 0; count < NUM_BUFS; count++)\r
369 {\r
370 wkBuf[count] = Memory_calloc(iheap, (BUFSIZE * RX_NUM_SERIALIZER/(SYS_FS_RATIO*2)),\r
371 BUFALIGN, &eb);\r
372 if(NULL == wkBuf[count])\r
373 {\r
374 IFPRINT(cmbk2g_write("\r\nMEM_calloc failed for Wk\n"));\r
375 }\r
376 }\r
377 \r
378 #if (CMBK2G_AUDIO_DAC)\r
379 /* Allocate buffers for the McASP data exchanges */\r
380 for(count = 0; count < NUM_BUFS; count++)\r
381 {\r
382 txBuf[count] = Memory_calloc(iheap, (BUFSIZE * TX_NUM_SERIALIZER),\r
383 BUFALIGN, &eb);\r
384 if(NULL == txBuf[count])\r
385 {\r
386 IFPRINT(cmbk2g_write("\r\nMEM_calloc failed for Tx\n"));\r
387 }\r
388 }\r
389 \r
390 /* Allocate output buffers for the MSS */\r
391 for(count = 0; count < NUM_BUFS; count++)\r
392 {\r
393 outBuf[count] = Memory_calloc(iheap, (BUFSIZE * TX_NUM_SERIALIZER/(SYS_FS_RATIO*2*2)),\r
394 BUFALIGN, &eb);\r
395 if(NULL == outBuf[count])\r
396 {\r
397 IFPRINT(cmbk2g_write("\r\nMEM_calloc failed for Out\n"));\r
398 }\r
399 }\r
400 #endif\r
401 for(count = 0; count < NUM_BUFS; count++)\r
402 {\r
403 /* Issue the first & second empty buffers to the input stream */\r
404 memset((uint8_t *)rxBuf[count], 0xAA, (BUFSIZE * RX_NUM_SERIALIZER));\r
405 memset((uint8_t *)wkBuf[count], 0xBB, (BUFSIZE * RX_NUM_SERIALIZER/(SYS_FS_RATIO*2)));\r
406 \r
407 /* RX frame processing */\r
408 rxFrame[count].cmd = MCASP_READ;\r
409 rxFrame[count].addr = (void*)(getGlobalAddr(rxBuf[count]));\r
410 rxFrame[count].size = BUFSIZE * RX_NUM_SERIALIZER;\r
411 rxFrame[count].arg = (uint32_t) mcaspRxChanArg;\r
412 rxFrame[count].status = 0;\r
413 rxFrame[count].misc = 1; /* reserved - used in callback to indicate asynch packet */\r
414 \r
415 /* Submit McASP packet for Rx */\r
416 status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[count]);\r
417 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))\r
418 {\r
419 IFPRINT(cmbk2g_write("mcaspSubmitChan for Rx Failed\n"));\r
420 return (Cmbk2g_EFAIL);\r
421 }\r
422 }\r
423 \r
424 #if (CMBK2G_AUDIO_DAC)\r
425 for(count = 0; count < NUM_BUFS; count++)\r
426 {\r
427 memset((uint8_t *)txBuf[count], 0xCC, (BUFSIZE * TX_NUM_SERIALIZER));\r
428 memset((uint8_t *)outBuf[count], 0xDD, (BUFSIZE * TX_NUM_SERIALIZER/(3*2*2)));\r
429 \r
430 /* TX frame processing */\r
431 txFrame[count].cmd = MCASP_WRITE;\r
432 txFrame[count].addr = (void*)(getGlobalAddr(txBuf[count]));\r
433 txFrame[count].size = BUFSIZE * TX_NUM_SERIALIZER;\r
434 txFrame[count].arg = (uint32_t) mcaspTxChanArg;\r
435 txFrame[count].status = 0;\r
436 txFrame[count].misc = 1; /* reserved - used in callback to indicate asynch packet */\r
437 \r
438 /* Submit McASP packet for Tx */\r
439 status = mcaspSubmitChan(hMcaspTxChan, &txFrame[count]);\r
440 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))\r
441 {\r
442 IFPRINT(cmbk2g_write("mcaspSubmitChan for Tx Failed\n"));\r
443 return (Cmbk2g_EFAIL);\r
444 }\r
445 }\r
446 #endif\r
447 return (Cmbk2g_EOK);\r
448 }\r
449 \r
450 /**\r
451 * \brief Configures McASP module and creates the channel\r
452 * for audio Tx and Rx\r
453 *\r
454 * \return Cmbk2g_EOK on Success or error code\r
455 */\r
456 Cmbk2g_STATUS mcaspAudioConfig(void)\r
457 {\r
458 Int status;\r
459 \r
460 #if (CMBK2G_AUDIO_DAC)\r
461 hMcaspDevTx = NULL;\r
462 hMcaspTxChan = NULL;\r
463 #endif\r
464 hMcaspDevRx = NULL;\r
465 hMcaspRxChan = NULL;\r
466 \r
467 /* Initialize McASP Tx and Rx parameters */\r
468 #if (CMBK2G_AUDIO_DAC)\r
469 mcaspTxParams = Mcasp_PARAMS;\r
470 #endif\r
471 mcaspRxParams = Mcasp_PARAMS;\r
472 \r
473 #if (CMBK2G_AUDIO_DAC)\r
474 mcaspTxParams.mcaspHwSetup.tx.clk.clkSetupClk = 0x63;\r
475 mcaspTxParams.mcaspHwSetup.rx.clk.clkSetupClk = 0x23;\r
476 #endif\r
477 mcaspRxParams.mcaspHwSetup.rx.clk.clkSetupClk = 0x23;\r
478 mcaspRxParams.mcaspHwSetup.tx.clk.clkSetupClk = 0x63;\r
479 \r
480 #if (CMBK2G_AUDIO_DAC)\r
481 mcaspTxParams.mcaspHwSetup.glb.pdir |= 0x2000000; //Set Amute pin as output for Tx channel\r
482 #endif\r
483 \r
484 /* Set the HW interrupt number */\r
485 #if (CMBK2G_AUDIO_DAC)\r
486 mcaspTxParams.hwiNumber = 8;\r
487 #endif\r
488 mcaspRxParams.hwiNumber = 8;\r
489 \r
490 /* Initialize eDMA handle */\r
491 mcaspRxChanParam.edmaHandle = hEdma1;\r
492 #if (CMBK2G_AUDIO_DAC)\r
493 mcaspTxChanParam.edmaHandle = hEdma1;\r
494 \r
495 /* Bind McASP2 for Tx */\r
496 status = mcaspBindDev(&hMcaspDevTx, CSL_MCASP_2, &mcaspTxParams);\r
497 if((status != MCASP_COMPLETED) || (hMcaspDevTx == NULL))\r
498 {\r
499 IFPRINT(cmbk2g_write("mcaspBindDev for Tx Failed\n"));\r
500 return (Cmbk2g_EFAIL);\r
501 }\r
502 #endif\r
503 /* Bind McASP1 for Rx */\r
504 status = mcaspBindDev(&hMcaspDevRx, CSL_MCASP_1, &mcaspRxParams);\r
505 if((status != MCASP_COMPLETED) || (hMcaspDevRx == NULL))\r
506 {\r
507 IFPRINT(cmbk2g_write("mcaspBindDev for Rx Failed\n"));\r
508 return (Cmbk2g_EFAIL);\r
509 }\r
510 \r
511 #if (CMBK2G_AUDIO_DAC)\r
512 /* Create McASP channel for Tx */\r
513 status = mcaspCreateChan(&hMcaspTxChan, hMcaspDevTx,\r
514 MCASP_OUTPUT,\r
515 &mcaspTxChanParam,\r
516 mcaspAppCallback, &txChanMode);\r
517 if((status != MCASP_COMPLETED) || (hMcaspTxChan == NULL))\r
518 {\r
519 IFPRINT(cmbk2g_write("mcaspCreateChan for Tx Failed\n"));\r
520 return (Cmbk2g_EFAIL);\r
521 }\r
522 \r
523 configAudioDAC();\r
524 #endif\r
525 \r
526 /* Create McASP channel for Rx */\r
527 status = mcaspCreateChan(&hMcaspRxChan, hMcaspDevRx,\r
528 MCASP_INPUT,\r
529 &mcaspRxChanParam,\r
530 mcaspAppCallback, &rxChanMode);\r
531 if((status != MCASP_COMPLETED) || (hMcaspRxChan == NULL))\r
532 {\r
533 IFPRINT(cmbk2g_write("mcaspCreateChan for Rx Failed\n"));\r
534 return (Cmbk2g_EFAIL);\r
535 }\r
536 \r
537 /* Initialize the buffers and submit for McASP Tx/Rx */\r
538 if(initBuffers() != Cmbk2g_EOK)\r
539 {\r
540 IFPRINT(cmbk2g_write("McASP Buffer Initialization Failed\n"));\r
541 return (Cmbk2g_EFAIL);\r
542 }\r
543 \r
544 return (Cmbk2g_EOK);\r
545 }\r
546 \r
547 /**\r
548 * \brief Function to exit the test\r
549 *\r
550 * \return None\r
551 */\r
552 void testRet(uint32_t status)\r
553 {\r
554 cmbk2g_write("\n\nAudio DC Analog Interface Test Completed!\n");\r
555 \r
556 testExit(status);\r
557 }\r
558 \r
559 /**\r
560 * \brief Task to echo the input data to output\r
561 *\r
562 * Waits for the McASP data transfer completion and copies the\r
563 * Rx data to Tx buffers\r
564 *\r
565 * \return Cmbk2g_EOK on Success or error code\r
566 */\r
567 #define DUMP_SEC 5\r
568 #define FRAME_PER_SEC 100\r
569 int gAudDumpBufIdx = 0;\r
570 unsigned char gAudDumpBuf[(BUFSIZE*RX_NUM_SERIALIZER)*FRAME_PER_SEC*DUMP_SEC];\r
571 unsigned char gAudOutDumpBuf[(BUFSIZE*TX_NUM_SERIALIZER)*FRAME_PER_SEC*DUMP_SEC];\r
572 Void Audio_echo_Task(void)\r
573 {\r
574 int32_t i, j, k;\r
575 unsigned char *tempTxPtr, *tempRxPtr, *tempWkPtr;\r
576 unsigned char *tempOutPtr, *tempMicPtr;\r
577 tint nmics, nvmics, err, angle;\r
578 volatile tulong t1, t2; /* for profiling */\r
579 tulong delta;\r
580 \r
581 void *inst_p;\r
582 linSample *in_r; /* pointer to current microphone input buffer */\r
583 linSample *frame_p; /* pointer to signal frame */\r
584 linSample *mics_in[SYS_MICS_MAX+1]; /* pointers to microphone inputs */\r
585 \r
586 mssDebugStat_t mssDbg;\r
587 \r
588 Semaphore_Params_init(¶ms);\r
589 \r
590 /* Create semaphores to wait for buffer reclaiming */\r
591 semR = Semaphore_create(0, ¶ms, &eb);\r
592 semT = Semaphore_create(0, ¶ms, &eb);\r
593 \r
594 /* Forever loop to continuously receive and transmit audio data */\r
595 while (1)\r
596 {\r
597 if(gblErrFlag)\r
598 {\r
599 break;\r
600 }\r
601 \r
602 /* Reclaim full buffer from the input stream */\r
603 Semaphore_pend(semR, BIOS_WAIT_FOREVER);\r
604 #if (CMBK2G_AUDIO_DAC)\r
605 Semaphore_pend(semT, BIOS_WAIT_FOREVER);\r
606 #endif\r
607 /* Reclaim full buffer from the input stream */\r
608 #if (CMBK2G_AUDIO_DAC)\r
609 gtxFrameIndexCount = txFrameIndex;\r
610 #endif\r
611 grxFrameIndexCount = rxFrameIndex;\r
612 \r
613 #if (CMBK2G_AUDIO_DAC)\r
614 \r
615 #if 0 // Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1\r
616 // copy RX mic 1 to TX left channel and RX mic 5 to right channel\r
617 // set the RX pointer to mic 1\r
618 tempRxPtr = (uint32_t *)rxBuf[grxFrameIndexCount];\r
619 // set the TX pointer to left cahhnel\r
620 tempTxPtr = (uint32_t *)txBuf[gtxFrameIndexCount];\r
621 // copy RX mic 1 to TX left channel\r
622 for (i=0; i<BUFLEN/2; i++)\r
623 {\r
624 // copy the left channel of first serializer to the left channel of TX buffer\r
625 *tempTxPtr = *tempRxPtr;\r
626 tempTxPtr++;\r
627 // copy the left channel of swecond serializer to the right channel of TX buffer\r
628 *tempTxPtr = *(tempRxPtr+BUFLEN+2);\r
629 tempTxPtr++;\r
630 tempRxPtr += RX_NUM_SERIALIZER*2;\r
631 }\r
632 \r
633 #else // Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_2\r
634 #if 1 // Signal Processing Path\r
635 // 48khz to 16khz, 24bit to 16bit conversion\r
636 nmics = sysContext.nmics; /* fetch number of mics */\r
637 // for each channel, convert and copy the RX buffer to WK buffer\r
638 for (j=0; j<(nmics+1); j++)\r
639 {\r
640 // set the RX pointer\r
641 tempRxPtr = (unsigned char *)rxBuf[grxFrameIndexCount] + (j/2)*BUFSIZE + (j&0x00000001)*sizeof(Ptr) + sizeof(short);\r
642 // set the WK pointer\r
643 tempWkPtr = (unsigned char *)wkBuf[grxFrameIndexCount] + j*BUFSIZE/(SYS_FS_RATIO*2*2);\r
644 // convert and copy RX to WK every third sample\r
645 for (i=0; i<BUFLEN/2; i+=SYS_FS_RATIO)\r
646 {\r
647 // only copy the two most significant bytes (Q31 to Q15 conversion)\r
648 memcpy(tempWkPtr, tempRxPtr, sizeof(short));\r
649 tempWkPtr += sizeof(short);\r
650 tempRxPtr += sizeof(Ptr)*2*SYS_FS_RATIO;\r
651 }\r
652 }\r
653 \r
654 // set the sysContext.in_r\r
655 sysContext.in_r = wkBuf[grxFrameIndexCount];\r
656 in_r = (linSample *)sysContext.in_r;\r
657 for (k = 0; k < (nmics+1); k++) {\r
658 mics_in[chanToMicMapping[k]] = &in_r[k*SYS_FRAME_LENGTH]; /* find the frame start for each microphone */\r
659 }\r
660 /* consume samples pointed to by read pointer in_r as provided in misc_in[] */\r
661 \r
662 // BF+ASNR+MSS processing\r
663 /* Here comes a lot of work */\r
664 /* We start with beamformers */\r
665 \r
666 // get the number of virtual mics\r
667 nvmics = sysContext.nvmics;\r
668 t1 = Timestamp_get();\r
669 for (k = 0; k < nvmics; k++) {\r
670 inst_p = sysContext.bfInst_p[k]; /* fetch the bf instance pointer */\r
671 frame_p = sysContext.vmicfrm[k]; /* point to the output frame buffer */\r
672 \r
673 err = bfProcess(inst_p, (void*)&mics_in[0], (void*)frame_p);\r
674 \r
675 if (err != bf_NOERR) {\r
676 SYS_CHECK_ERROR(SYS_ERR_BFERROR);\r
677 }\r
678 } /* for */\r
679 t2 = Timestamp_get();\r
680 delta = t2-t1;\r
681 txTaskProfile.bf.min = MIN(txTaskProfile.bf.min,delta);\r
682 txTaskProfile.bf.max = MAX(txTaskProfile.bf.max,delta);\r
683 txTaskProfile.bf.n++;\r
684 txTaskProfile.bf.total += (float)delta;\r
685 \r
686 /* At this point we have consumed all input samples. Currently we did not implement\r
687 * any protection to prevent the swiDataIn from stepping over while we were doing this.\r
688 * We could let this task to handle the read pointer and SWI to handle write pointer which\r
689 * could be used to detect if such overrun would happen. */\r
690 \r
691 /* Done with the beamformers */\r
692 /* Start ASNR's */\r
693 \r
694 t1 = Timestamp_get();\r
695 for (k = 0; k < nvmics; k++) {\r
696 inst_p = sysContext.asnrInst_p[k]; /* fetch the bf instance pointer */\r
697 frame_p = sysContext.vmicfrm[k]; /* point to the output frame buffer */\r
698 \r
699 err = asnrProcess(inst_p, (void*)frame_p, (void*)frame_p);\r
700 \r
701 if (err != asnr_NOERR) {\r
702 SYS_CHECK_ERROR(SYS_ERR_ASNRERROR);\r
703 } /* if */\r
704 } /* for */\r
705 t2 = Timestamp_get();\r
706 delta = t2-t1;\r
707 txTaskProfile.asnr.min = MIN(txTaskProfile.asnr.min,delta);\r
708 txTaskProfile.asnr.max = MAX(txTaskProfile.asnr.max,delta);\r
709 txTaskProfile.asnr.n++;\r
710 txTaskProfile.asnr.total += (float)delta;\r
711 \r
712 /* Done with the ASNR's */\r
713 /* Run MSS */\r
714 \r
715 t1 = Timestamp_get();\r
716 inst_p = sysContext.mssInst_p; /* fetch the MSS instance pointer */\r
717 frame_p = outBuf[gtxFrameIndexCount]; /* point to the output frame buffer */\r
718 \r
719 err = mssProcess(inst_p, /* instance */\r
720 (void*)frame_p, /* output frame pointers */\r
721 (void*)frame_p, /* WORKAROUND (not used, but no NULL) */\r
722 (void**)sysContext.vmicfrm, /* Virtual microphones (beams) */\r
723 NULL, /* No remote mics */\r
724 NULL, /* No clean mics */\r
725 (void**)mics_in, /* Raw microphone array inputs */\r
726 NULL); /* Beam not supported (see fixed inputs) */\r
727 \r
728 if (err != mss_NOERR) {\r
729 SYS_CHECK_ERROR(SYS_ERR_MSSERROR);\r
730 } /* if */\r
731 t2 = Timestamp_get();\r
732 delta = t2-t1;\r
733 txTaskProfile.mss.min = MIN(txTaskProfile.mss.min,delta);\r
734 txTaskProfile.mss.max = MAX(txTaskProfile.mss.max,delta);\r
735 txTaskProfile.mss.n++;\r
736 txTaskProfile.mss.total += (float)delta;\r
737 \r
738 /* Trace source selection */\r
739 /* Write Args:\r
740 * arg2: (value) Angle in degrees\r
741 * arg3: (aux1) 0 - current source, 1 - new source\r
742 * arg4: (aux2) source index\r
743 */\r
744 err = mssDebugStat(inst_p, &mssDbg);\r
745 if (err !=mss_NOERR) {\r
746 SYS_CHECK_ERROR(SYS_ERR_MSSDEBUG);\r
747 }\r
748 /* mssDbg.cur_src.group/.index has the current source */\r
749 /* mssDbg.new_src.group/.index has "proposed" source */\r
750 if (mssDbg.cur_src.group != mssDbgCurSrc.group ||\r
751 mssDbg.cur_src.index != mssDbgCurSrc.index)\r
752 {\r
753 mssDbgCurSrc = mssDbg.cur_src;\r
754 angle = sysBfFilterAngles[sysBfVMicAngles[mssDbgCurSrc.index]];\r
755 ///Log_write6(UIAEvt_intWithKey, angle, 0, mssDbgCurSrc.index, (IArg)"MSS-C: %d, G:%d", 0, mssDbgCurSrc.group);\r
756 }\r
757 if (mssDbg.new_src.group != mssDbgNewSrc.group ||\r
758 mssDbg.new_src.index != mssDbgNewSrc.index)\r
759 {\r
760 mssDbgNewSrc = mssDbg.new_src;\r
761 angle = sysBfFilterAngles[sysBfVMicAngles[mssDbgNewSrc.index]];\r
762 ///Log_write6(UIAEvt_intWithKey, angle, 1, mssDbgNewSrc.index, (IArg)"MSS-N: %d, G:%d", 1, mssDbgNewSrc.group);\r
763 }\r
764 \r
765 /* Done with MSS */\r
766 \r
767 /*---------------------------------*/\r
768 /* Save samples to the TX buffer */\r
769 /*---------------------------------*/\r
770 // copy MSS output to TX left channel and RX mic 5 to TX right channel\r
771 // set the tempOutPtr to MSS output\r
772 tempOutPtr = outBuf[gtxFrameIndexCount];\r
773 // set the tempMicPtr to mic_in[4]\r
774 tempMicPtr = (unsigned char *)mics_in[4];\r
775 // set the TX pointer to left cahhnel\r
776 tempTxPtr = txBuf[gtxFrameIndexCount];\r
777 // copy upsampled and Q15 to Q31 converted MSS output to TX left channel\r
778 // copy upsampled and Q15 to Q31 converted mics_in[4] to TX right channel\r
779 for (i=0; i<BUFLEN/(SYS_FS_RATIO*2); i++)\r
780 {\r
781 // up sampling by SYS_FS_RATIO (16khz to 48khz)\r
782 for (k=0; k<SYS_FS_RATIO; k++)\r
783 {\r
784 // MSS output\r
785 // Q15 to Q31\r
786 memset(tempTxPtr, 0, sizeof(short));\r
787 tempTxPtr += sizeof(short);\r
788 // copy the MSS output to the left channel of TX buffer\r
789 memcpy(tempTxPtr, tempOutPtr, sizeof(short));\r
790 tempTxPtr += sizeof(short);\r
791 \r
792 // mics_in[4]\r
793 // Q15 to Q31\r
794 memset(tempTxPtr, 0, sizeof(short));\r
795 tempTxPtr += sizeof(short);\r
796 // copy the mics_in[4] to the right channel of TX buffer\r
797 memcpy(tempTxPtr, tempMicPtr, sizeof(short));\r
798 tempTxPtr += sizeof(short);\r
799 }\r
800 // move to next sample\r
801 tempOutPtr += sizeof(short);\r
802 tempMicPtr += sizeof(short);\r
803 }\r
804 #else // 7 to 2 Loopback Path\r
805 // copy RX mic 1 to TX left channel and RX mic 5 to TX right channel\r
806 // set the RX pointer to mic 1\r
807 tempRxPtr = rxBuf[grxFrameIndexCount];\r
808 // set the TX pointer to left cahhnel\r
809 tempTxPtr = txBuf[gtxFrameIndexCount];\r
810 // copy RX mic 1 to TX left channel\r
811 for (i=0; i<BUFLEN/2; i++)\r
812 {\r
813 // copy the left channel of first serializer to the left channel of TX buffer\r
814 memcpy(tempTxPtr, tempRxPtr, 4);\r
815 tempTxPtr += 4;\r
816 // copy the left channel of second serializer to the right channel of TX buffer\r
817 memcpy(tempTxPtr, tempRxPtr+BUFSIZE, 4);\r
818 tempTxPtr += 4;\r
819 tempRxPtr += RX_NUM_SERIALIZER*2;\r
820 }\r
821 #endif // Signal Processing Path\r
822 #endif // Mcasp_BufferFormat\r
823 #endif // CMBK2G_AUDIO_DAC\r
824 \r
825 // Audio debug dump\r
826 if (gAudDumpBufIdx<FRAME_PER_SEC*DUMP_SEC)\r
827 {\r
828 // copy the MSS output\r
829 ///memcpy((Ptr)(&gAudDumpBuf[gAudDumpBufIdx*BUFSIZE/(SYS_FS_RATIO*2*2)]), outBuf[gtxFrameIndexCount], (BUFSIZE/(SYS_FS_RATIO*2*2)));\r
830 \r
831 // copy first down-sampled and converted channel (L channel for first serializer)\r
832 ///memcpy((Ptr)(&gAudDumpBuf[gAudDumpBufIdx*BUFSIZE/(SYS_FS_RATIO*2*2)]), mics_in[0], (BUFSIZE/(SYS_FS_RATIO*2*2)));\r
833 \r
834 // copy RX all 8 channels (L/R channels for all 4 serializers)\r
835 ///memcpy((Ptr)(&gAudDumpBuf[gAudDumpBufIdx*BUFSIZE*RX_NUM_SERIALIZER]), rxBuf[grxFrameIndexCount], (BUFSIZE * RX_NUM_SERIALIZER));\r
836 \r
837 // copy RX first channel (L channel for the first serializer)\r
838 ///memcpy((Ptr)(&gAudDumpBuf[gAudDumpBufIdx*(BUFSIZE/2)]), rxBuf[grxFrameIndexCount], (BUFSIZE/2));\r
839 \r
840 // copy TX buffer\r
841 ///memcpy((Ptr)(&gAudDumpBuf[gAudDumpBufIdx*(BUFSIZE)]), txBuf[gtxFrameIndexCount], BUFSIZE);\r
842 \r
843 gAudDumpBufIdx++;\r
844 }\r
845 \r
846 #if (CMBK2G_AUDIO_DAC)\r
847 /* Issue full buffer to the output stream */\r
848 /* TX frame processing */\r
849 txFrame[gtxFrameIndexCount].cmd = MCASP_WRITE;\r
850 txFrame[gtxFrameIndexCount].addr = (void*)(getGlobalAddr(txBuf[gtxFrameIndexCount]));\r
851 txFrame[gtxFrameIndexCount].size = (BUFSIZE * TX_NUM_SERIALIZER);\r
852 txFrame[gtxFrameIndexCount].arg = (uint32_t) mcaspTxChanArg;\r
853 txFrame[gtxFrameIndexCount].status = 0;\r
854 txFrame[gtxFrameIndexCount].misc = 1; /* reserved - used in callback to indicate asynch packet */\r
855 \r
856 mcaspSubmitChan(hMcaspTxChan, &txFrame[gtxFrameIndexCount]);\r
857 #endif\r
858 \r
859 /* Issue an empty buffer to the input stream */\r
860 rxFrame[grxFrameIndexCount].cmd = MCASP_READ;\r
861 rxFrame[grxFrameIndexCount].addr = (void*)(getGlobalAddr(rxBuf[grxFrameIndexCount]));\r
862 rxFrame[grxFrameIndexCount].size = (BUFSIZE * RX_NUM_SERIALIZER);\r
863 rxFrame[grxFrameIndexCount].arg = (uint32_t) mcaspRxChanArg;\r
864 rxFrame[grxFrameIndexCount].status = 0;\r
865 rxFrame[grxFrameIndexCount].misc = 1; /* reserved - used in callback to indicate asynch packet */\r
866 \r
867 mcaspSubmitChan(hMcaspRxChan, &rxFrame[grxFrameIndexCount]);\r
868 }\r
869 \r
870 testRet(0);\r
871 }\r
872 \r
873 /* Nothing past this point */\r