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