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