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