audio-preprocessing-fw: add UART_printf, change the CCS project file using relative...
[processor-sdk/audio-preprocessing.git] / realtime_demo_bios / k2g / src / mcasp_cfg.c
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 /* McASP HW setup for receive */\r
145 Mcasp_HwSetupData mcaspRcvSetup = {\r
146         /* .rmask    = */ 0xFFFFFFFF, /* 16 bits are to be used     */\r
147         /* .rfmt     = */ 0x000180F0, /*\r
148                                        * 1 bit delay from framesync\r
149                                        * MSB first\r
150                                        * No extra bit padding\r
151                                        * Padding bit (ignore)\r
152                                        * slot Size is 32\r
153                                        * Reads from DMA port\r
154                                        * NO rotation\r
155                                        */\r
156         /* .afsrctl  = */ 0X00000111, /* I2S mode - 2 slot TDM\r
157                                        * Frame sync is one word\r
158                                        * Externally generated frame sync\r
159                                        * Falling edge is start of frame\r
160                                        */\r
161         /* .rtdm     = */ 0x00000003, /* slot 1 and 2 are active (I2S)        */\r
162         /* .rintctl  = */ 0x00000000, /* sync error and overrun error         */\r
163         /* .rstat    = */ 0x000001FF, /* reset any existing status bits       */\r
164         /* .revtctl  = */ 0x00000000, /* DMA request is enabled               */\r
165         {\r
166              /* .aclkrctl  = */ 0x00000080, /* Bit CLK Pol: falling edge, ACLKR is external */\r
167              /* .ahclkrctl = */ 0x00000000, /* AHCLKR is external */\r
168              /* .rclkchk   = */ 0x00000000\r
169         }\r
170 };\r
171 \r
172 /* McASP HW setup for transmit */\r
173 #if (CMB_AUDIO_DAC)\r
174 Mcasp_HwSetupData mcaspXmtSetup = {\r
175         /* .xmask    = */ 0xFFFFFFFF, /* 16 bits are to be used     */\r
176         /* .xfmt     = */ 0x000180F0, /*\r
177                                        * 1 bit delay from framesync\r
178                                        * MSB first\r
179                                        * No extra bit padding\r
180                                        * Padding bit (ignore)\r
181                                        * slot Size is 32\r
182                                        * Reads from DMA port\r
183                                        * NO rotation\r
184                                        */\r
185         /* .afsxctl  = */ 0x00000113, /* I2S mode - 2 slot TDM\r
186                                        * Frame sync is one word\r
187                                        * Falling edge is start of frame\r
188                                        * Externally generated frame sync\r
189                                        */\r
190         /* .xtdm     = */ 0x00000003, /* slot 1 and 2 are active (I2S)               */\r
191         /* .xintctl  = */ 0x00000000, /* sync error,overrun error,clK error   */\r
192         /* .xstat    = */ 0x000001FF, /* reset any existing status bits       */\r
193         /* .xevtctl  = */ 0x00000000, /* DMA request is enabled or disabled   */\r
194         {\r
195              /* .aclkxctl  = */ 0X000000E3, /* Bit CLK Pol: falling edge, ASYNC is 1, ACLKX is internal, HF CLK to BCLK divider is 4 */\r
196              /* .ahclkxctl = */ 0x00000000, /* AHCLKX is external */\r
197              /* .xclkchk   = */ 0x00000000\r
198         },\r
199 \r
200 };\r
201 #endif\r
202 \r
203 /* McAsp channel parameters for receive                      */\r
204 Mcasp_ChanParams  mcaspRxChanParam =\r
205 {\r
206         0x0004,                    /* number of serializers      */\r
207         {Mcasp_SerializerNum_0,\r
208          Mcasp_SerializerNum_1,\r
209          Mcasp_SerializerNum_2,\r
210          Mcasp_SerializerNum_3 }, /* serializer index           */\r
211         &mcaspRcvSetup,\r
212         TRUE,\r
213         Mcasp_OpMode_TDM,          /* Mode (TDM/DIT)             */\r
214         Mcasp_WordLength_32,\r
215         NULL,\r
216         0,\r
217         NULL,\r
218         GblErr,\r
219         2,                        /* number of TDM channels      */\r
220         ///Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1,\r
221         Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_2,\r
222         TRUE,\r
223         TRUE\r
224 };\r
225 \r
226 #if (CMB_AUDIO_DAC)\r
227 /* McAsp channel parameters for transmit             */\r
228 Mcasp_ChanParams  mcaspTxChanParam =\r
229 {\r
230         0x0001,                   /* number of serializers       */\r
231         {Mcasp_SerializerNum_2,}, /* serializer index for DAC0    */\r
232         &mcaspXmtSetup,\r
233         TRUE,\r
234         Mcasp_OpMode_TDM,\r
235         Mcasp_WordLength_32,      /* word width                  */\r
236         NULL,\r
237         0,\r
238         NULL,\r
239         GblErr,\r
240         2,                        /* number of TDM channels      */\r
241         Mcasp_BufferFormat_1SER_MULTISLOT_INTERLEAVED,\r
242         ///Mcasp_BufferFormat_1SER_MULTISLOT_NON_INTERLEAVED,\r
243         TRUE,\r
244         TRUE\r
245 };\r
246 #endif\r
247 \r
248 #if (SYS_USE_DRC)\r
249 /* Output frame for MSS, input for DRC */\r
250 #pragma DATA_ALIGN(txOutFrame1,8)\r
251 linSample txOutFrame1[SYS_FRAME_LENGTH];\r
252 \r
253 /* Output frame for DRC, input for VAU */\r
254 #pragma DATA_ALIGN(txOutFrame2,8)\r
255 linSample txOutFrame2[SYS_FRAME_LENGTH];\r
256 #endif\r
257 \r
258 typedef struct txBfDebug_stc {\r
259  tulong frmcnt;     /* normal frames */\r
260  tulong silcnt;     /* silence frames */\r
261  tuint  invsrc;     /* no mic active, invalid output */\r
262  tuint  invopt;     /* >1 mic active, invalid output */\r
263 } txBfDebug_t;\r
264 \r
265 typedef struct txTaskDebug_stc {\r
266   tuint overrun;                    /* counts how many times we ran out of MIPS */\r
267   txBfDebug_t bf[SYS_VMICS_MAX];    /* beamformer statistics */\r
268 } txTaskDebug_t;\r
269 \r
270 txTaskDebug_t txTaskDebug;      /* Tx task debug stats */\r
271 \r
272 /* Profiling/benchmarking information for the Tx task */\r
273 typedef struct txTaskProfileData_stc {\r
274   tulong  min;              /* Minimum number of cycles */\r
275   tulong  max;              /* Maximum number of cycles */\r
276   tulong  n;                /* Number of measurements */\r
277   float   total;            /* Total number of cycles */\r
278 } txTaskProfileData_t;\r
279 \r
280 typedef struct txTaskProfile_stc {\r
281   txTaskProfileData_t   bf;       /* Beamformer profile */\r
282   txTaskProfileData_t   asnr;     /* ASNR profile */\r
283   txTaskProfileData_t   mss;      /* MSS profile */\r
284   txTaskProfileData_t   drc;      /* DRC profile */\r
285   txTaskProfileData_t   vau;      /* VAU profile */\r
286 } txTaskProfile_t;\r
287 volatile txTaskProfile_t  txTaskProfile = {\r
288   {~(0uL), 0, 0, 0.0f},\r
289   {~(0uL), 0, 0, 0.0f},\r
290   {~(0uL), 0, 0, 0.0f},\r
291   {~(0uL), 0, 0, 0.0f},\r
292   {~(0uL), 0, 0, 0.0f}\r
293 };\r
294 \r
295 /* To be used for debug trace */\r
296 mssSrc_t    mssDbgCurSrc = {\r
297   -1, -1                        /* Current source group/index */\r
298 };\r
299 mssSrc_t    mssDbgNewSrc = {\r
300   -1, -1                        /* New source group/index */\r
301 };\r
302 \r
303 /* Handle to eDMA */\r
304 extern EDMA3_DRV_Handle hEdma1;\r
305 \r
306 /**\r
307  *  \brief    Function called by McASP driver in case of error\r
308  *\r
309  *  \return    None\r
310  */\r
311 void GblErr(int arg)\r
312 {\r
313         gblErrFlag = 1;\r
314 }\r
315 \r
316 /**\r
317  *  \brief   McASP callback function called up on the data transfer completion\r
318  *\r
319  *  \param  arg   [IN]  - Application specific callback argument\r
320  *  \param  ioBuf [IN]  - McASP IO buffer\r
321  *\r
322  *  \return    None\r
323  */\r
324 void mcaspAppCallback(void *arg, MCASP_Packet *ioBuf)\r
325 {\r
326         /* Callback is triggered by Rx completion */\r
327         if(ioBuf->cmd == MCASP_READ)\r
328         {\r
329                 rxFlag++;\r
330 \r
331                 if(rxFrameIndex == 0)\r
332                 {\r
333                         rxFrameIndex = 1;\r
334                 }\r
335                 else\r
336                 {\r
337                         rxFrameIndex = 0;\r
338                 }\r
339 \r
340                 /* Post semaphore */\r
341                 Semaphore_post(semR);\r
342         }\r
343 \r
344         /* Callback is triggered by Tx completion */\r
345         if(ioBuf->cmd == MCASP_WRITE)\r
346         {\r
347                 if(txFrameIndex == 0)\r
348                 {\r
349                         txFrameIndex = 1;\r
350                 }\r
351                 else\r
352                 {\r
353                         txFrameIndex = 0;\r
354                 }\r
355 \r
356                 txFlag++;\r
357 \r
358                 /* Post semaphore */\r
359                 Semaphore_post(semT);\r
360         }\r
361 }\r
362 \r
363 /**\r
364  *  \brief   Initializes McASP data buffers and submits to McASP driver\r
365  *\r
366  *  \return    Cmb_EOK on Success or error code\r
367  */\r
368 Cmb_STATUS initBuffers(void)\r
369 {\r
370         Error_Block  eb;\r
371     uint32_t     count = 0;\r
372     IHeap_Handle iheap;\r
373     Int          status;\r
374 \r
375     iheap = HeapMem_Handle_to_xdc_runtime_IHeap(heapHandle);\r
376     Error_init(&eb);\r
377 \r
378     /* Allocate buffers for the McASP data exchanges */\r
379     for(count = 0; count < NUM_BUFS; count++)\r
380     {\r
381         rxBuf[count] = Memory_calloc(iheap, (BUFSIZE * RX_NUM_SERIALIZER),\r
382                                                              BUFALIGN, &eb);\r
383         if(NULL == rxBuf[count])\r
384         {\r
385             IFPRINT(cmb_write("\r\nMEM_calloc failed for Rx\n"));\r
386             IFPRINT(UART_printf("\r\nMEM_calloc failed for Rx\n"));\r
387         }\r
388     }\r
389 \r
390     /* Allocate work buffers for signal processing */\r
391     for(count = 0; count < NUM_BUFS; count++)\r
392     {\r
393         wkBuf[count] = Memory_calloc(iheap, (BUFSIZE * RX_NUM_SERIALIZER/(SYS_FS_RATIO*2)),\r
394                                                              BUFALIGN, &eb);\r
395         if(NULL == wkBuf[count])\r
396         {\r
397             IFPRINT(cmb_write("\r\nMEM_calloc failed for Wk\n"));\r
398             IFPRINT(UART_printf("\r\nMEM_calloc failed for Wk\n"));\r
399         }\r
400     }\r
401 \r
402 #if (CMB_AUDIO_DAC)\r
403     /* Allocate buffers for the McASP data exchanges */\r
404     for(count = 0; count < NUM_BUFS; count++)\r
405     {\r
406         txBuf[count] = Memory_calloc(iheap, (BUFSIZE * TX_NUM_SERIALIZER),\r
407                                                                  BUFALIGN, &eb);\r
408         if(NULL == txBuf[count])\r
409         {\r
410             IFPRINT(cmb_write("\r\nMEM_calloc failed for Tx\n"));\r
411             IFPRINT(UART_printf("\r\nMEM_calloc failed for Tx\n"));\r
412         }\r
413     }\r
414 \r
415     /* Allocate output buffers for the MSS */\r
416     for(count = 0; count < NUM_BUFS; count++)\r
417     {\r
418         outBuf[count] = Memory_calloc(iheap, (BUFSIZE * TX_NUM_SERIALIZER/(SYS_FS_RATIO*2*2)),\r
419                                                                  BUFALIGN, &eb);\r
420         if(NULL == outBuf[count])\r
421         {\r
422             IFPRINT(cmb_write("\r\nMEM_calloc failed for Out\n"));\r
423             IFPRINT(UART_printf("\r\nMEM_calloc failed for Out\n"));\r
424         }\r
425     }\r
426 #endif\r
427     for(count = 0; count < NUM_BUFS; count++)\r
428     {\r
429         /* Issue the first & second empty buffers to the input stream */\r
430         memset((uint8_t *)rxBuf[count], 0xAA, (BUFSIZE * RX_NUM_SERIALIZER));\r
431         memset((uint8_t *)wkBuf[count], 0xBB, (BUFSIZE * RX_NUM_SERIALIZER/(SYS_FS_RATIO*2)));\r
432 \r
433                 /* RX frame processing */\r
434                 rxFrame[count].cmd    = MCASP_READ;\r
435                 rxFrame[count].addr   = (void*)(getGlobalAddr(rxBuf[count]));\r
436                 rxFrame[count].size   = BUFSIZE * RX_NUM_SERIALIZER;\r
437                 rxFrame[count].arg    = (uint32_t) mcaspRxChanArg;\r
438                 rxFrame[count].status = 0;\r
439                 rxFrame[count].misc   = 1;   /* reserved - used in callback to indicate asynch packet */\r
440 \r
441                 /* Submit McASP packet for Rx */\r
442                 status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[count]);\r
443                 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))\r
444                 {\r
445                         IFPRINT(cmb_write("mcaspSubmitChan for Rx Failed\n"));\r
446                         IFPRINT(UART_printf("mcaspSubmitChan for Rx Failed\n"));\r
447                         return (Cmb_EFAIL);\r
448                 }\r
449     }\r
450 \r
451 #if (CMB_AUDIO_DAC)\r
452     for(count = 0; count < NUM_BUFS; count++)\r
453     {\r
454         memset((uint8_t *)txBuf[count], 0xCC, (BUFSIZE * TX_NUM_SERIALIZER));\r
455         memset((uint8_t *)outBuf[count], 0xDD, (BUFSIZE * TX_NUM_SERIALIZER/(3*2*2)));\r
456 \r
457                 /* TX frame processing */\r
458                 txFrame[count].cmd    = MCASP_WRITE;\r
459                 txFrame[count].addr   = (void*)(getGlobalAddr(txBuf[count]));\r
460                 txFrame[count].size   = BUFSIZE * TX_NUM_SERIALIZER;\r
461                 txFrame[count].arg    = (uint32_t) mcaspTxChanArg;\r
462                 txFrame[count].status = 0;\r
463                 txFrame[count].misc   = 1;   /* reserved - used in callback to indicate asynch packet */\r
464 \r
465                 /* Submit McASP packet for Tx */\r
466                 status = mcaspSubmitChan(hMcaspTxChan, &txFrame[count]);\r
467                 if((status != MCASP_COMPLETED) && (status != MCASP_PENDING))\r
468                 {\r
469                         IFPRINT(cmb_write("mcaspSubmitChan for Tx Failed\n"));\r
470                         IFPRINT(UART_printf("mcaspSubmitChan for Tx Failed\n"));\r
471                         return (Cmb_EFAIL);\r
472                 }\r
473     }\r
474 #endif\r
475     return (Cmb_EOK);\r
476 }\r
477 \r
478 /**\r
479  *  \brief   Configures McASP module and creates the channel\r
480  *           for audio Tx and Rx\r
481  *\r
482  *  \return    Cmb_EOK on Success or error code\r
483  */\r
484 Cmb_STATUS mcaspAudioConfig(void)\r
485 {\r
486         Int status;\r
487 \r
488 #if (CMB_AUDIO_DAC)\r
489         hMcaspDevTx  = NULL;\r
490         hMcaspTxChan = NULL;\r
491 #endif\r
492         hMcaspDevRx  = NULL;\r
493         hMcaspRxChan = NULL;\r
494 \r
495         /* Initialize McASP Tx and Rx parameters */\r
496 #if (CMB_AUDIO_DAC)\r
497         mcaspTxParams = Mcasp_PARAMS;\r
498 #endif\r
499         mcaspRxParams = Mcasp_PARAMS;\r
500 \r
501 #if (CMB_AUDIO_DAC)\r
502         mcaspTxParams.mcaspHwSetup.tx.clk.clkSetupClk = 0x63;\r
503         mcaspTxParams.mcaspHwSetup.rx.clk.clkSetupClk = 0x23;\r
504 #endif\r
505         mcaspRxParams.mcaspHwSetup.rx.clk.clkSetupClk = 0x23;\r
506         mcaspRxParams.mcaspHwSetup.tx.clk.clkSetupClk = 0x63;\r
507 \r
508 #if (CMB_AUDIO_DAC)\r
509         mcaspTxParams.mcaspHwSetup.glb.pdir |= 0x2000000; //Set Amute pin as output for Tx channel\r
510 #endif\r
511 \r
512         /* Set the HW interrupt number */\r
513 #if (CMB_AUDIO_DAC)\r
514         mcaspTxParams.hwiNumber = 8;\r
515 #endif\r
516         mcaspRxParams.hwiNumber = 8;\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                        5\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(&params);\r
624 \r
625         /* Create semaphores to wait for buffer reclaiming */\r
626     semR = Semaphore_create(0, &params, &eb);\r
627     semT = Semaphore_create(0, &params, &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 (CMB_AUDIO_DAC)\r
905         /* Issue full buffer to the output stream                             */\r
906         /* TX frame processing */\r
907                 txFrame[gtxFrameIndexCount].cmd    = MCASP_WRITE;\r
908                 txFrame[gtxFrameIndexCount].addr   = (void*)(getGlobalAddr(txBuf[gtxFrameIndexCount]));\r
909                 txFrame[gtxFrameIndexCount].size   = (BUFSIZE * TX_NUM_SERIALIZER);\r
910                 txFrame[gtxFrameIndexCount].arg    = (uint32_t) mcaspTxChanArg;\r
911                 txFrame[gtxFrameIndexCount].status = 0;\r
912                 txFrame[gtxFrameIndexCount].misc   = 1;   /* reserved - used in callback to indicate asynch packet */\r
913 \r
914                 mcaspSubmitChan(hMcaspTxChan, &txFrame[gtxFrameIndexCount]);\r
915 #endif\r
916 \r
917         /* Issue an empty buffer to the input stream                          */\r
918                 rxFrame[grxFrameIndexCount].cmd    = MCASP_READ;\r
919                 rxFrame[grxFrameIndexCount].addr   = (void*)(getGlobalAddr(rxBuf[grxFrameIndexCount]));\r
920                 rxFrame[grxFrameIndexCount].size   = (BUFSIZE * RX_NUM_SERIALIZER);\r
921                 rxFrame[grxFrameIndexCount].arg    = (uint32_t) mcaspRxChanArg;\r
922                 rxFrame[grxFrameIndexCount].status = 0;\r
923                 rxFrame[grxFrameIndexCount].misc   = 1;   /* reserved - used in callback to indicate asynch packet */\r
924 \r
925         mcaspSubmitChan(hMcaspRxChan, &rxFrame[grxFrameIndexCount]);\r
926         }\r
927 \r
928     testRet(0);\r
929 }\r
930 \r
931 /* Nothing past this point */\r