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