]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/audio-preprocessing.git/blob - realtime_demo_bios/omapl137/src/audioSample_io.c
add UART terminal output "Test Passed", after 500 audio frames have been processed
[processor-sdk/audio-preprocessing.git] / realtime_demo_bios / omapl137 / src / audioSample_io.c
1 /*
2  * audioSample_io.c
3  *
4  * This file contains the test / demo code to demonstrate the Audio component
5  * driver functionality on SYS/BIOS 6.
6  *
7  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
8  *
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *
14  *    Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  *    Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the
20  *    distribution.
21  *
22  *    Neither the name of Texas Instruments Incorporated nor the names of
23  *    its contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38 */
40 /** \file     audioSample_io.c
41  *
42  *  \brief    sample application for demostration of audio playing
43  *
44  *  This file contains the implementation of the sample appliation for the
45  *  demonstration of audio playing through the audio interface layer.
46  *
47  *             (C) Copyright 2017, Texas Instruments, Inc
48  */
50 /* ========================================================================== */
51 /*                            INCLUDE FILES                                   */
52 /* ========================================================================== */
54 #include "fil.h"                      /* FILE I/O implementation */
55 #include "sys.h"                      /* System API and structures */
56 #include "sysbfflt.h"                 /* System support for BF filters */
58 #include "cmb.h"
60 #include <types.h>
61 #include <ti/mas/aer/bf.h>
62 #include "../../../common/components/mss/mss.h"              /* local version used */
63 #include <ti/mas/vpe/asnr.h>
64 #if (SYS_USE_DRC)
65 ///#include <ti/mas/vau/vau.h>
66 #include <ti/mas/aer/drc.h>
67 #endif
69 #include <xdc/std.h>
70 #include <ti/sysbios/io/IOM.h>
71 #include <xdc/runtime/Memory.h>
72 #include <ti/sysbios/heaps/HeapMem.h>
73 #include <xdc/runtime/IHeap.h>
74 #include <xdc/runtime/Error.h>
75 #include <xdc/runtime/Log.h>
76 #include <xdc/runtime/System.h>
77 #include <ti/sysbios/BIOS.h>
78 #include <ti/sysbios/knl/Semaphore.h>
79 #include <mcasp_drv.h>
80 #include <ti/csl/csl_chip.h>
81 #include <ti/sdo/edma3/drv/edma3_drv.h>
82 #include <ti/sdo/edma3/rm/edma3_rm.h>
83 #include <ti/sdo/edma3/drv/sample/bios6_edma3_drv_sample.h>
84 #include "mcasp_osal.h"
85 #include "ICodec.h"
86 #include "mcasp_cfg.h"
87 #include "MCASP_log.h"
88 #include "stdio.h"
89 #include "string.h"
91 #include <ti/csl/cslr_mcasp.h>
92 #ifdef MEASURE_TIME
93   #include "profiling.h"
94 #endif
96 #include <ti/sysbios/knl/Task.h>
97 #include <ti/sysbios/hal/Cache.h>
98 #include <xdc/runtime/System.h>       /* for System_printf, and similar */
99 #include <xdc/runtime/Timestamp.h>    /* for benchmarking/profiling */
101 #include "pcm186x_if.h"
103 /* ========================================================================== */
104 /*                          IMPORTED VARIABLES                                */
105 /* ========================================================================== */
107 extern EDMA3_DRV_Handle hEdma;
108 extern HeapMem_Handle myHeap;
109 /* ========================================================================== */
110 /*                          MACRO DEFINITIONS                                 */
111 /* ========================================================================== */
113 #define Timestamp_get Timestamp_get32 /* use 32-bit time stamps */
115 #define MIN(a,b)    (((a)>(b))?(b):(a))     /* Min/Max macros */
116 #define MAX(a,b)    (((a)<(b))?(b):(a))
117 #define loop        while(1)                /* endless loop for the task */
119 /*
120  * Buffers placed in external memory are aligned on a 128 bytes boundary.
121  * In addition, the buffer should be of a size multiple of 128 bytes for
122  * the cache work optimally on the C6x.
123  */
124 #define BUFLEN                  160*2         /* number of samples in the frame */
125 #define BUFALIGN                128 /* alignment of buffer for use of L2 cache */
128 /** Number of serializers configured for record */
130 #define BUFSIZE                 (BUFLEN * 4)    // 4 bytes per word
132 /* This is the number of buffers used by the application to be issued and reclaimed 
133    This number can be higher than 2 (Ping pong) also. The McASP driver puts them in 
134    a queue internally and process them in order and give back to the application */
135 #define NUM_BUFS                2
137 #if defined(AIC_CODEC)
138 #include <Aic31.h>
139 Ptr  hAicDev;
140 Ptr  hAicChannel;
141 #endif
144 /* Function prototype */
145 static Void createStreams();
146 static Void prime();
148 Ptr rxbuf[NUM_BUFS];
149 Ptr txbuf[NUM_BUFS];
150 Ptr wkbuf[NUM_BUFS];
151 Ptr outbuf[NUM_BUFS];
153 /* channel 0 (serilizer 1 left) - mic1 */
154 /* channel 1 (serilizer 1 right) - mic2 */
155 /* channel 2 (serilizer 2 left) - mic5 */
156 /* channel 3 (serilizer 2 right) - mic6 */
157 /* channel 4 (serilizer 3 left) - mic3 */
158 /* channel 5 (serilizer 3 right) - mic4 */
159 /* channel 6 (serilizer 4 left) - mic8 */
160 /* channel 7 (serilizer 4 right) - mic7 */
161 int chanToMicMapping[8] = {0, 4, 3, 7, 1, 5, 2, 6};
163 /* McASP Device handles */
164 Ptr  hMcaspDev0;
165 Ptr  hMcaspDev;
167 /* McASP Device parameters */
168 Mcasp_Params mcaspParams;
169 Mcasp_Params mcaspParams0;
172 /* Channel Handles */
173 Ptr hMcaspTxChan;
174 Ptr hMcaspRxChan;
175 Ptr hMcaspTxChan0;
176 Ptr hMcaspRxChan0;
178 int rxFrameIndex=(NUM_BUFS-1), txFrameIndex=(NUM_BUFS-1);
179 volatile int RxFlag=0,TxFlag=0;
180 Semaphore_Handle semR,semT;
181 Semaphore_Params params;
183 Error_Block eb;
185 typedef struct txBfDebug_stc {
186  tulong frmcnt;     /* normal frames */
187  tulong silcnt;     /* silence frames */
188  tuint  invsrc;     /* no mic active, invalid output */
189  tuint  invopt;     /* >1 mic active, invalid output */
190 } txBfDebug_t;
192 typedef struct txTaskDebug_stc {
193   tuint overrun;                    /* counts how many times we ran out of MIPS */
194   txBfDebug_t bf[SYS_VMICS_MAX];    /* beamformer statistics */
195 } txTaskDebug_t;
197 txTaskDebug_t txTaskDebug;      /* Tx task debug stats */
199 /* Profiling/benchmarking information for the Tx task */
200 typedef struct txTaskProfileData_stc {
201   tulong  min;              /* Minimum number of cycles */
202   tulong  max;              /* Maximum number of cycles */
203   tulong  n;                /* Number of measurements */
204   float   total;            /* Total number of cycles */
205 } txTaskProfileData_t;
207 typedef struct txTaskProfile_stc {
208   txTaskProfileData_t   bf;       /* Beamformer profile */
209   txTaskProfileData_t   asnr;     /* ASNR profile */
210   txTaskProfileData_t   mss;      /* MSS profile */
211   txTaskProfileData_t   drc;      /* DRC profile */
212   txTaskProfileData_t   vau;      /* VAU profile */
213 } txTaskProfile_t;
214 volatile txTaskProfile_t  txTaskProfile = {
215   {~(0uL), 0, 0, 0.0f},
216   {~(0uL), 0, 0, 0.0f},
217   {~(0uL), 0, 0, 0.0f},
218   {~(0uL), 0, 0, 0.0f},
219   {~(0uL), 0, 0, 0.0f}
220 };
222 /* To be used for debug trace */
223 mssSrc_t    mssDbgCurSrc = {
224   -1, -1                        /* Current source group/index */
225 };
226 mssSrc_t    mssDbgNewSrc = {
227   -1, -1                        /* New source group/index */
228 };
230 #if (SYS_USE_DRC)
231 /* Output frame for MSS, input for DRC */
232 #pragma DATA_ALIGN(txOutFrame1,8)
233 linSample txOutFrame1[SYS_FRAME_LENGTH];
235 /* Output frame for DRC, input for VAU */
236 #pragma DATA_ALIGN(txOutFrame2,8)
237 linSample txOutFrame2[SYS_FRAME_LENGTH];
238 #endif
240 /**************************************************************************************/
241 /*   FUNCTION DESCRIPTION: This utility function converts local GEM L2 address in to global
242     memory addresses used by the EDMA inside McASP
243 */
244 /**************************************************************************************/
245 static uint32_t getGlobalAddr (uint32_t addr)
247     if ((addr >= 0x800000) && (addr < 0x1000000))
248     {
249 #ifdef _TMS320C6X
250         uint32_t coreNum;
252         /* Get the core number. */
253         coreNum = CSL_chipReadReg(CSL_CHIP_DNUM);
255 #if defined(SOC_AM572x) || defined(SOC_AM571x)
256         /* Compute the global address. */
257         return ((1 << 30) | (coreNum << 24) | (addr & 0x00ffffff));
259 #else
260   /* Compute the global address. */
261         return ((1 << 28) | (coreNum << 24) | (addr & 0x00ffffff));
262 #endif
263 #else
264         return addr;
265 #endif
266     }
267     else
268     {
269         /* non-L2 address range */
270         return addr;
271     }
273 /*********************** APPLICATION DEFINED FUNCTIONS: Begin ****************************/
274 /* The below functions need to be defined by the application and are registered to the
275    McASP driver during instantiation 
276  */
277 /*
278  * This call back function is provided to the McASP driver during mcaspCreateChan()
279  * and is called at the end of a transaction. This example uses the same call back function
280  * for both TX and RX transfers and the call back argument is not being used in this
281  * application and hence we pass NULL during mcaspCreateChan() as the call back argument.
282  * This need not be the case for other applications where they could use a seperate
283  * call back function for TX and RX. Also they could provide a non-NULL argument as
284  * the call back argument and use it in their implementation of the call back function(s).
285  */
286 void mcaspAppCallback(void* arg, MCASP_Packet *ioBuf)
289         if(ioBuf->cmd == MCASP_READ)
290         {
291                 RxFlag++;
292                 rxFrameIndex=((rxFrameIndex+1) %NUM_BUFS);
294                 if(ioBuf->addr != (void *)getGlobalAddr((uint32_t)rxbuf[rxFrameIndex])) {
295                    MCASP_log("Rx Buf Address mismatch\n");
296                 }
297         /* post semaphore */
298         Semaphore_post(semR);
299         }
300         if(ioBuf->cmd == MCASP_WRITE)
301                 {
302                 txFrameIndex=((txFrameIndex+1) % NUM_BUFS);
303                 if(ioBuf->addr != (void *)getGlobalAddr((uint32_t)txbuf[txFrameIndex])) {
304                         MCASP_log("Tx Buf Address mismatch\n");
305                 }
306                 TxFlag++;
307                 /* post semaphore */
308                 Semaphore_post(semT);
309                 }
313 /*
314  * This call back is used during interrupt processing and is defined by the
315  * application for error handling. These functions are called back from within the
316  * mcasp driver when an error interrupt happens and macspIsr() is being called.
317  * The sample error handling functions just records these errors which
318  * are later used for analyzing the errors seen.
319  */
320 /* The below variables are used to quit the frame processing loop if an error occurs */
321 int gblErrFlagXmt=0;
322 int gblErrFlagRcv=0;
323 /* The below variables are used to analyze the errors if an error interrupt happens */
324 Mcasp_errCbStatus errCbStatusXmt;
325 Mcasp_errCbStatus errCbStatusRcv;
327 /* Error handler for Transmit side */
328 void GblErrXmt(Mcasp_errCbStatus errCbStat)
330         gblErrFlagXmt=1;
331         errCbStatusXmt=errCbStat;
333 /* Error handler for Rcv side */
334 void GblErrRcv(Mcasp_errCbStatus errCbStat)
336     gblErrFlagRcv=1;
337     errCbStatusRcv=errCbStat;
339 /*********************** APPLICATION DEFINED FUNCTIONS: End ****************************/
344 /**************************************************************************************/
345 /* FUNCTION DESCRIPTION: This function analyzes the result of error interrupts, if it
346  * happened
347 */
348 /**************************************************************************************/         
349 void mcaspAnalyzeErrors(Mcasp_errCbStatus *errCbStat)
351     MCASP_log("*****  --------- Error Interrupt details \n -----------");
352     MCASP_log("*****  Error Callback:isClkFailErr : %d\n",errCbStat->isClkFailErr);
353     MCASP_log("*****  Error Callback: isDMAErr    : %d\n",errCbStat->isDMAErr);
354     MCASP_log("*****  Error Callback: isSyncErr   : %d\n",errCbStat->isSyncErr);
355     MCASP_log("*****  Error Callback: retVal      : %d \n",errCbStat->retVal);
356     MCASP_log("*****  Error Callback: isRcvOvrRunOrTxUndRunErr : %d \n",errCbStat->isRcvOvrRunOrTxUndRunErr);
359 /**************************************************************************************/
360 /*   FUNCTION DESCRIPTION: This function creates the McASP channels for Tx and Rx 
361      This function also creates the codec channels (if any)
362 */
363 /**************************************************************************************/         
364 static Void createStreams()
366         int status;
368     int mode = IOM_INPUT;
369         char remName[10]="aic";
370 #if !defined(MCASP_MASTER)
371 /* Configure the external clock: In Slave mode, McASP is not the master, start initializing the external clock provider (AIC codec below),
372    before configuring McASP clocks (in mcaspCreateChan() below) 
373 */
374 #if defined(AIC_CODEC)
375 /* In this case AIC provides the frame clocks, hence we need to start it first */
376         status = aic31MdCreateChan(
377                 &hAicChannel,
378                 hAicDev,
379                 remName,
380                 mode,
381                 (Ptr)(&AIC31_config),
382                 mcaspAppCallback,
383                 NULL);
385         if ((NULL == hAicChannel) &&
386                         (IOM_COMPLETED != status))
387         {
388                 MCASP_log("AIC Create Channel Failed\n");
389                 BIOS_exit(0);
390         }
391 #endif
392         
393 #endif
394         
395         
396         mcasp_chanparam[0].edmaHandle = hEdma;
397     mcasp_chanparam[1].edmaHandle = hEdma;
399         /* Create Mcasp channel for Tx */
400         status = mcaspCreateChan(&hMcaspTxChan, hMcaspDev,
401                                                          MCASP_OUTPUT,
402                                                          &mcasp_chanparam[1],
403                                                          mcaspAppCallback, NULL);
405         if((status != MCASP_COMPLETED) || (hMcaspTxChan == NULL))
406         {
407                 MCASP_log("mcaspCreateChan for McASP1 Tx Failed\n");
408                 BIOS_exit(0);
409         }
411         /* Create Mcasp channel for Rx */
412         status = mcaspCreateChan(&hMcaspRxChan, hMcaspDev,
413                                  MCASP_INPUT,
414                                  &mcasp_chanparam[0],
415                                  mcaspAppCallback, NULL);
416         if((status != MCASP_COMPLETED) || (hMcaspRxChan == NULL))
417         {
418                 MCASP_log("mcaspCreateChan for McASP1 Rx Failed\n");
419                 BIOS_exit(0);
420         }
422 #if defined(MCASP_MASTER) 
423 /* If MCASP master, configure the clock of the slave device attached to McASP now.
424     In the below case, it is the AIC codec */
426 #if defined(AIC_CODEC)
427         status = aic31MdCreateChan(
428                 &hAicChannel,
429                 hAicDev,
430                 remName,
431                 mode,
432                 (Ptr)(&AIC31_config),
433                 (IOM_TiomCallback)&mcaspAppCallback,
434                 NULL);
436         if ((NULL == hAicChannel) &&
437                         (IOM_COMPLETED != status))
438         {
439                 MCASP_log("AIC Create Channel Failed\n");
440         }
441         else
442         {
444         }
445 #endif
447 #endif
451 /*
452  * ======== prime ========
453  */
454 MCASP_Packet rxFrame[NUM_BUFS];
455 MCASP_Packet txFrame[NUM_BUFS];
456 #include <ti/sysbios/family/c64p/Hwi.h>
458 Hwi_Handle myHwi;
459 static Void prime()
461         Error_Block  eb;
462     int32_t        count = 0, status;
463     IHeap_Handle iheap;
465     iheap = HeapMem_Handle_to_xdc_runtime_IHeap(myHeap);
466     Error_init(&eb);
468     /* Allocate buffers for the SIO buffer exchanges                          */
469     for(count = 0; count < (NUM_BUFS ); count ++)
470     {
471         rxbuf[count] = Memory_calloc(iheap, BUFSIZE * RX_NUM_SERIALIZER,
472                                                                 BUFALIGN, &eb);
473         if(NULL == rxbuf[count])
474         {
475             MCASP_log("\r\nMEM_calloc failed.\n");
476         }
477     }
479     /* Allocate work buffers for signal processing */
480     for(count = 0; count < NUM_BUFS; count++)
481     {
482         wkbuf[count] = Memory_calloc(iheap, (BUFSIZE * RX_NUM_SERIALIZER/(SYS_FS_RATIO*2)),
483                                                             BUFALIGN, &eb);
484         if(NULL == wkbuf[count])
485         {
486             IFPRINT(cmb_write("\r\nMEM_calloc failed for Wk\n"));
487             IFPRINT(UART_printf("\r\nMEM_calloc failed for Wk\n"));
488         }
489     }
491     /* Allocate buffers for the SIO buffer exchanges                          */
492     for(count = 0; count < (NUM_BUFS); count ++)
493     {
494         txbuf[count] = Memory_calloc(iheap, BUFSIZE * TX_NUM_SERIALIZER,
495                                                                 BUFALIGN, &eb);
496         if(NULL == txbuf[count])
497         {
498             MCASP_log("\r\nMEM_calloc failed.\n");
499         }
500     }
502     /* Allocate output buffers for the MSS */
503     for(count = 0; count < NUM_BUFS; count++)
504     {
505         outbuf[count] = Memory_calloc(iheap, (BUFSIZE * TX_NUM_SERIALIZER/(SYS_FS_RATIO*2)),
506                                                                 BUFALIGN, &eb);
507         if(NULL == outbuf[count])
508         {
509             IFPRINT(cmb_write("\r\nMEM_calloc failed for Out\n"));
510             IFPRINT(UART_printf("\r\nMEM_calloc failed for Out\n"));
511         }
512     }
514     for(count = 0; count < NUM_BUFS; count ++)
515     {
516                 /* Issue the first & second empty buffers to the input stream         */
517                 memset((uint8_t *)rxbuf[count], 0xFF, BUFSIZE * RX_NUM_SERIALIZER);
518         memset((uint8_t *)wkbuf[count], 0xBB, (BUFSIZE * RX_NUM_SERIALIZER/(SYS_FS_RATIO*2)));
520         /* RX frame processing */
521                 rxFrame[count].cmd = MCASP_READ;
522                 rxFrame[count].addr = (void*)(getGlobalAddr((uint32_t)rxbuf[count]));
523                 rxFrame[count].size = BUFSIZE * RX_NUM_SERIALIZER;
524                 rxFrame[count].arg = (uint32_t) hMcaspRxChan;
525                 rxFrame[count].status = 0;
526                 rxFrame[count].misc = 1;   /* reserved - used in callback to indicate asynch packet */
528                 /* Submit McASP packet for Rx */
529                 status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[count]);
530                 if((status != MCASP_PENDING))
531                         MCASP_log ("Debug: Error McASP2 RX : Prime  buffer  #%d submission FAILED\n", count);
534     }
536     for(count = 0; count < (NUM_BUFS); count ++)
537        {
538                         memset((uint8_t *)txbuf[count], 0xF0, BUFSIZE * TX_NUM_SERIALIZER);
539                         memset((uint8_t *)outbuf[count], 0xDD, (BUFSIZE * TX_NUM_SERIALIZER/(SYS_FS_RATIO*2)));
541                         /* TX frame processing */
542                         txFrame[count].cmd = MCASP_WRITE;
543                         txFrame[count].addr = (void*)(getGlobalAddr((uint32_t)txbuf[count]));
544                         txFrame[count].size = BUFSIZE * TX_NUM_SERIALIZER;
545                         txFrame[count].arg = (uint32_t) hMcaspTxChan;
546                         txFrame[count].status = 0;
547                         txFrame[count].misc = 1;   /* reserved - used in callback to indicate asynch packet */
548                         /* Submit McASP packet for Tx */
549                         status = mcaspSubmitChan(hMcaspTxChan, &txFrame[count]);
550                         if((status != MCASP_PENDING))
551                                 MCASP_log ("Debug: Error McASP2 TX : Prime  buffer  #%d submission FAILED\n", count);
552        }
556 extern EDMA3_DRV_GblConfigParams sampleEdma3GblCfgParams[];
557 /* EnableEDMA event in the SampleCfg*/
558 static void enableEDMAHwEvent(uint32_t edmaNum, uint32_t eventNo) {
559   sampleEdma3GblCfgParams[edmaNum].dmaChannelHwEvtMap[eventNo/32] |= (1 << (eventNo%32));
562 /*
563  * ======== echo ========
564  * This function copies from the input SIO to the output SIO. You could
565  * easily replace the copy function with a signal processing algorithm.
566  */
567 extern Int aic31MdBindDev(Ptr *, Int, Ptr);
569 int gtxFrameIndexCount=0;
570 int grxFrameIndexCount=0;
571 int itemp;
572 int result, pwr_status, fs_status, bck_status;
573 int total_frames_sent=0;
575 #define audDumpSec 10
576 #define sampNumSec 16000
577 #define audDumpSampleNum = audDumpSec*sampNumSec*TX_NUM_SERIALIZER
578 int *audDumpBufPtr = (int *)0xc3800000;
579 int audDumpBufIdx = 0;
580 Void Audio_echo_Task()
582     volatile int32_t i32Count, status = 0;
583         hMcaspDev  = NULL;
584         int count, serNum;
585     int32_t i, j, k;
586     int *tmpTxPtr, *tmpRxPtr;
587     unsigned char *tempTxPtr, *tempRxPtr, *tempWkPtr;
588     unsigned char *tempOutPtr, *tempMicPtr;
589     tint      nmics, nvmics, err, angle;
590     volatile tulong t1, t2;       /* for profiling */
591     tulong          delta;
593     void      *inst_p;
594     linSample *in_r;                      /* pointer to current microphone input buffer */
595     linSample *frame_p;                   /* pointer to signal frame */
596     linSample *outframe_p;                /* Output frame pointer for VAU */
597     linSample *mics_in[SYS_MICS_MAX+1];     /* pointers to microphone inputs */
599     mssDebugStat_t  mssDbg;
602 #ifdef MEASURE_TIME
603         profiling_init();
604 #endif
606     /* 1. EDMA Initializations */
607     EDMA3_DRV_Result edmaResult = 0;
609         enableEDMAHwEvent(EDMACC_NUM,MCASP_RX_DMA_CH);
610     enableEDMAHwEvent(EDMACC_NUM,MCASP_TX_DMA_CH);
611         
612     hEdma = edma3init(EDMACC_NUM, &edmaResult);
614     if (edmaResult != EDMA3_DRV_SOK)
615         {
616             /* Report EDMA Error
617              */
618             MCASP_log("\nEDMA driver initialization unsuccessful\n");
619         }
620         else
621         {
622            MCASP_log("\nEDMA driver initialization successful.\n");
623         }
625         /* 2. SEM Initializations */
626     Semaphore_Params_init(&params);
628         /* Create semaphores to wait for buffer reclaiming */
629     semR = Semaphore_create(0, &params, &eb);
630     semT = Semaphore_create(0, &params, &eb);
632         /* 3. McASP Initializations */
633         /* Initialize McASP Tx and Rx parameters */
635         mcaspParams = Mcasp_PARAMS;
637         status = mcaspBindDev(&hMcaspDev, MCASP_NUM, &mcaspParams);
638         if((status != MCASP_COMPLETED) || (hMcaspDev == NULL))
639         {
640                 MCASP_log("mcaspBindDev for McASP1 Failed\n");
641                 abort();
642         }
644 #if defined(AIC_CODEC)
645         /* Bind AIC Codec */
646     aic31MdBindDev(&hAicDev, 0, (Ptr)&Aic31_PARAMS);
647 #endif
649     /* Call createStream function to create I/O streams                       */
650     createStreams();
652     //  set up the CMB for audio input
653     PCM186XADCInit();
655     MCASP_log("Initialization complete. priming about to begin \n");
656     /* Call prime function to do priming                                      */
657     prime();
659     MCASP_log("priming complete.\n");
663     MCASP_log("\n******** Audio Loopback demo ********\n");
664     MCASP_log("Send audio signals in to the EVM's audio-in port and hear the same audio in the audio-out port\n");
666     /* Forever loop to continously receviec and transmit audio data           */
667     for (i32Count = 0; i32Count >= 0; i32Count++)
668     {
670         if(gblErrFlagXmt || gblErrFlagRcv)
671                 break;
673         Semaphore_pend(semR, BIOS_WAIT_FOREVER);
674         Semaphore_pend(semT, BIOS_WAIT_FOREVER);
676 #ifdef MEASURE_TIME
677     profiling_end();  
678 #endif
679         /* Reclaim full buffer from the input stream                          */
680         gtxFrameIndexCount=txFrameIndex;
681         grxFrameIndexCount=rxFrameIndex;
683         Cache_inv(rxbuf[grxFrameIndexCount],BUFSIZE * RX_NUM_SERIALIZER,Cache_Type_ALL, TRUE);
684         /******************************* Sample Processing Begins ***************************/
685             /* (BUFLEN* RX_NUM_SERIALIZER) 32-bit samples samples have been accumulated in rxbuf[grxFrameIndexCount] now.
686                Application specific processing on these samples, before sending it back to McASP via 
687                txbuf[grxFrameIndexCount].
688                    APPLICATION SPECIFIC PROCESSING could be done here. Below are the few audio demos and their
689                    application specific processing shown below.
690             */
692         /* DEFAULT CASE: Copy the frame received and send it back to Tx buffer.
693                    This way the audio received by McASP from the remote device, is loopbacked and sent back
694                    to the device here.
695                 */
696                 // dump RX buffer to TX buffer
697                 ///memcpy(txbuf[gtxFrameIndexCount],rxbuf[grxFrameIndexCount],BUFSIZE * RX_NUM_SERIALIZER);
699         // Mcasp_BufferFormat_MULTISER_MULTISLOT_SEMI_INTERLEAVED_1
700 #if 0
701                 // loopback one serilizer (0[mic1/5], 1[mic4/8], 2[mic2/6] or 3[mic3/7]) of RX to TX
702                 serNum = 0; // loopback mic1/5
703                 tmpRxPtr = (int *)rxbuf[grxFrameIndexCount];
704                 tmpRxPtr += serNum*2;
705                 tmpTxPtr = (int *)txbuf[gtxFrameIndexCount];
706                 for (count=0; count<BUFLEN/2; count++)
707                 {
708                         *tmpTxPtr = *tmpRxPtr;
709                         tmpTxPtr++;
710                         tmpRxPtr++;
711                         *tmpTxPtr = *tmpRxPtr;
712                         tmpTxPtr++;
713                         tmpRxPtr += RX_NUM_SERIALIZER*2-1;
714                 }
715 #else
716         // SYS_ADC_FS_HZ to SYS_FS_HZ, 24bit to 16bit conversion
717             nmics = sysContext.nmics;                   /* fetch number of mics */
718         // for each channel, convert and copy the RX buffer to WK buffer
719                 for (j=0; j<(nmics+1); j++)
720                 {
721                         // set the RX start pointer
722                         tempRxPtr = (unsigned char *)rxbuf[grxFrameIndexCount] + j*sizeof(Ptr) + sizeof(short);
723                         // set the WK start pointer
724                         tempWkPtr = (unsigned char *)wkbuf[grxFrameIndexCount] + j*BUFSIZE/(SYS_FS_RATIO*2*2);
725                         // convert and copy RX to WK every SYS_FS_RATIO sample
726                         for (i=0; i<BUFLEN/2; i+=SYS_FS_RATIO)
727                         {
728                                 // only copy the two most significant bytes (Q31 to Q15 conversion)
729                                 memcpy(tempWkPtr, tempRxPtr, sizeof(short));
730                                 tempWkPtr += sizeof(short);
731                                 tempRxPtr += sizeof(Ptr)*2*SYS_FS_RATIO*RX_NUM_SERIALIZER;
732                         }
733                 }
735                 // set the sysContext.in_r
736                 sysContext.in_r = wkbuf[grxFrameIndexCount];
737             in_r  = (linSample *)sysContext.in_r;
738             for (k = 0; k < (nmics+1); k++) {
739               mics_in[chanToMicMapping[k]] = &in_r[k*SYS_FRAME_LENGTH];   /* find the frame start for each microphone */
740             }
741             /* consume samples pointed to by read pointer in_r as provided in misc_in[] */
743             // BF+ASNR+MSS processing
744             /* Here comes a lot of work */
745             /* We start with beamformers */
747             /* Start the beamformers */
748             // get the number of virtual mics
749             nvmics = sysContext.nvmics;
750             t1 = Timestamp_get();
751             for (k = 0; k < nvmics; k++) {
752               inst_p  = sysContext.bfInst_p[k];     /* fetch the bf instance pointer */
753               frame_p = sysContext.vmicfrm[k];      /* point to the output frame buffer */
755               err = bfProcess(inst_p, (void*)&mics_in[0], (void*)frame_p);
757               if (err != bf_NOERR) {
758                 SYS_CHECK_ERROR(SYS_ERR_BFERROR);
759               }
760             } /* for */
761             t2 = Timestamp_get();
762             delta = t2-t1;
763             txTaskProfile.bf.min = MIN(txTaskProfile.bf.min,delta);
764             txTaskProfile.bf.max = MAX(txTaskProfile.bf.max,delta);
765             txTaskProfile.bf.n++;
766             txTaskProfile.bf.total += (float)delta;
768             /* At this point we have consumed all input samples. Currently we did not implement
769              * any protection to prevent the swiDataIn from stepping over while we were doing this.
770              * We could let this task to handle the read pointer and SWI to handle write pointer which
771              * could be used to detect if such overrun would happen. */
772             /* Done with the beamformers */
774             /* Start ASNR's */
775             t1 = Timestamp_get();
776             for (k = 0; k < nvmics; k++) {
777               inst_p  = sysContext.asnrInst_p[k];   /* fetch the bf instance pointer */
778               frame_p = sysContext.vmicfrm[k];      /* point to the output frame buffer */
780               err = asnrProcess(inst_p, (void*)frame_p, (void*)frame_p);
782               if (err != asnr_NOERR) {
783                 SYS_CHECK_ERROR(SYS_ERR_ASNRERROR);
784               } /* if */
785             } /* for */
786             t2 = Timestamp_get();
787             delta = t2-t1;
788             txTaskProfile.asnr.min = MIN(txTaskProfile.asnr.min,delta);
789             txTaskProfile.asnr.max = MAX(txTaskProfile.asnr.max,delta);
790             txTaskProfile.asnr.n++;
791             txTaskProfile.asnr.total += (float)delta;
792             /* Done with the ASNR's */
794             /* Run MSS */
795             t1 = Timestamp_get();
796             inst_p  = sysContext.mssInst_p;         /* fetch the MSS instance pointer */
797 #if (SYS_USE_DRC)
798             frame_p = txOutFrame1;                  /* point to the output frame buffer */
799 #else
800             frame_p = outbuf[gtxFrameIndexCount];    /* point to the output frame buffer */
801 #endif
803             err = mssProcess(inst_p,                            /* instance */
804                                          (void*)frame_p,                /* output frame pointers */
805                              (void*)frame_p,        /* WORKAROUND (not used, but no NULL) */
806                              (void**)sysContext.vmicfrm,  /* Virtual microphones (beams) */
807                              NULL,                        /* No remote mics */
808                              NULL,                        /* No clean mics */
809                              (void**)mics_in,             /* Raw microphone array inputs */
810                              NULL);                       /* Beam not supported (see fixed inputs) */
812             if (err != mss_NOERR) {
813               SYS_CHECK_ERROR(SYS_ERR_MSSERROR);
814             } /* if */
815             t2 = Timestamp_get();
816             delta = t2-t1;
817             txTaskProfile.mss.min = MIN(txTaskProfile.mss.min,delta);
818             txTaskProfile.mss.max = MAX(txTaskProfile.mss.max,delta);
819             txTaskProfile.mss.n++;
820             txTaskProfile.mss.total += (float)delta;
822             /* Trace source selection */
823             /*    Write Args:
824              *      arg2: (value) Angle in degrees
825              *      arg3: (aux1)  0 - current source, 1 - new source
826              *      arg4: (aux2)  source index
827              */
828             err = mssDebugStat(inst_p, &mssDbg);
829             if (err !=mss_NOERR) {
830               SYS_CHECK_ERROR(SYS_ERR_MSSDEBUG);
831             }
832             /* mssDbg.cur_src.group/.index has the current source */
833             /* mssDbg.new_src.group/.index has "proposed" source */
834             if (mssDbg.cur_src.group != mssDbgCurSrc.group ||
835                 mssDbg.cur_src.index != mssDbgCurSrc.index)
836             {
837               mssDbgCurSrc = mssDbg.cur_src;
838               angle = sysBfFilterAngles[sysBfVMicAngles[mssDbgCurSrc.index]];
839               ///Log_write6(UIAEvt_intWithKey, angle, 0, mssDbgCurSrc.index, (IArg)"MSS-C: %d, G:%d", 0, mssDbgCurSrc.group);
840             }
841             if (mssDbg.new_src.group != mssDbgNewSrc.group ||
842                 mssDbg.new_src.index != mssDbgNewSrc.index)
843             {
844               mssDbgNewSrc = mssDbg.new_src;
845               angle = sysBfFilterAngles[sysBfVMicAngles[mssDbgNewSrc.index]];
846               ///Log_write6(UIAEvt_intWithKey, angle, 1, mssDbgNewSrc.index, (IArg)"MSS-N: %d, G:%d", 1, mssDbgNewSrc.group);
847             }
848             /* Done with MSS */
850 #if (SYS_USE_DRC)
851                 /* Run DRC */
852                 t1 = Timestamp_get();
853                 inst_p      = sysContext.drcInst_p;     /* fetch the DRC instance pointer */
854                 frame_p     = txOutFrame1;              /* point to the MSS output frame buffer and use it as input */
855                 outframe_p  = txOutFrame2;              /* point to DRC output frame */
856                 err = drcProcess(inst_p, frame_p,       /* instance and input frame pointers */
857                                                                  outframe_p);  /* pointer to output buffer pointer */
858                 t2 = Timestamp_get();
859                 delta = t2-t1;
860                 txTaskProfile.drc.min = MIN(txTaskProfile.drc.min,delta);
861                 txTaskProfile.drc.max = MAX(txTaskProfile.drc.max,delta);
862                 txTaskProfile.drc.n++;
863                 txTaskProfile.drc.total += (float)delta;
864                 /* Done with DRC */
865 #endif
867             /*---------------------------------*/
868             /* Save samples to the TX buffer */
869             /*---------------------------------*/
870                 // copy MSS output to TX left channel and RX mic 5 to TX right channel
871                 // set the tempOutPtr to MSS output
872 #if (SYS_USE_DRC)
873         tempOutPtr = txOutFrame2;
874 #else
875         tempOutPtr = (unsigned char *)outbuf[gtxFrameIndexCount];
876 #endif
877                 // set the tempMicPtr to mic_in[7] (mic8)
878         tempMicPtr = (unsigned char *)mics_in[7];
879         // set the TX pointer to left channel
880                 tempTxPtr = txbuf[gtxFrameIndexCount];
881                 // copy upsampled and Q15 to Q31 converted MSS output to TX left channel
882                 // copy upsampled and Q15 to Q31 converted mics_in[4] to TX right channel
883                 for (i=0; i<BUFLEN/(SYS_FS_RATIO*2); i++)
884         {
885                         // up sampling by SYS_FS_RATIO (SYS_FS_HZ to SYS_ADC_FS_HZ)
886                         for (k=0; k<SYS_FS_RATIO; k++)
887                         {
888                                 // MSS output
889                                 // Q15 to Q31
890                                 memset(tempTxPtr, 0, sizeof(short));
891                                 tempTxPtr += sizeof(short);
892                                 // copy the MSS output to the left channel of TX buffer
893                                 memcpy(tempTxPtr, tempOutPtr, sizeof(short));
894                                 tempTxPtr += sizeof(short);
896                                 // mics_in[7]
897                                 // Q15 to Q31
898                                 memset(tempTxPtr, 0, sizeof(short));
899                                 tempTxPtr += sizeof(short);
900                                 // copy the mics_in[7] to the right channel of TX buffer
901                                 memcpy(tempTxPtr, tempMicPtr, sizeof(short));
902                                 tempTxPtr += sizeof(short);
903                         }
904                         // move to next sample
905                         tempOutPtr += sizeof(short);
906                         tempMicPtr += sizeof(short);
907         }
909 #endif
911                 /******************************* Sample Processing End ***************************/
912         
913                 Cache_wbInv(txbuf[gtxFrameIndexCount],BUFSIZE * TX_NUM_SERIALIZER,Cache_Type_ALL, TRUE);
915         /* Issue full buffer to the output stream                             */
916         /* TX frame processing */
917                 txFrame[gtxFrameIndexCount].cmd = MCASP_WRITE;
918                 txFrame[gtxFrameIndexCount].addr = (void*)getGlobalAddr((uint32_t)txbuf[gtxFrameIndexCount]);
919                 txFrame[gtxFrameIndexCount].size = BUFSIZE * TX_NUM_SERIALIZER;
920                 txFrame[gtxFrameIndexCount].arg = (uint32_t) hMcaspTxChan;
921                 txFrame[gtxFrameIndexCount].status = 0;
922                 txFrame[gtxFrameIndexCount].misc = 1;   /* reserved - used in callback to indicate asynch packet */
924                 status = mcaspSubmitChan(hMcaspTxChan, &txFrame[gtxFrameIndexCount]);
925                 if((status != MCASP_PENDING))
926                         MCASP_log ("Debug: Error McASP TX : Prime  buffer  #%d submission FAILED\n", i32Count);
928                 /* Issue an empty buffer to the input stream                          */
929                 rxFrame[grxFrameIndexCount].cmd = MCASP_READ;
930                 rxFrame[grxFrameIndexCount].addr = (void*)getGlobalAddr((uint32_t)rxbuf[grxFrameIndexCount]);
931                 rxFrame[grxFrameIndexCount].size = BUFSIZE * RX_NUM_SERIALIZER;
932                 rxFrame[grxFrameIndexCount].arg = (uint32_t) hMcaspRxChan;
933                 rxFrame[grxFrameIndexCount].status = 0;
934                 rxFrame[grxFrameIndexCount].misc = 1;   /* reserved - used in callback to indicate asynch packet */
936                 status = mcaspSubmitChan(hMcaspRxChan, &rxFrame[grxFrameIndexCount]);
937                 if((status != MCASP_PENDING))
938                         MCASP_log ("Debug: Error McASP RX :  buffer  #%d submission FAILED\n", i32Count);
940 #ifdef MEASURE_TIME
941                 profiling_start();
942 #endif
943                 total_frames_sent++;
944                 if (total_frames_sent==500)
945                 {
946                         UART_printf("\nTest Passed\n");
947                 }               
949        
950             MCASP_log("\nTotal %d frames sent",total_frames_sent);
951             if(gblErrFlagXmt) {
952                MCASP_log("\n Transmit ERROR occured\n");
953                mcaspAnalyzeErrors(&errCbStatusXmt);
954         }
956         if(gblErrFlagRcv) {
957             MCASP_log("\n Receive ERROR occured\n");
958             mcaspAnalyzeErrors(&errCbStatusRcv);
959         }
961         MCASP_log("\nDeleting Rx channel");
962         status = mcaspDeleteChan(hMcaspRxChan);
963         MCASP_log("\nDeleting Tx channel");
964         status = mcaspDeleteChan(hMcaspTxChan);
965         MCASP_log("\nUnBinding Mcasp");
966         status = mcaspUnBindDev(hMcaspDev);
968                 {
969                         IHeap_Handle iheap;
971                         iheap = HeapMem_Handle_to_xdc_runtime_IHeap(myHeap);
972                         Error_init(&eb);
973                         for(i32Count = 0; i32Count < (NUM_BUFS); i32Count ++)
974                                 {
975                                         Memory_free(iheap,rxbuf[i32Count],BUFSIZE * RX_NUM_SERIALIZER);
976                                         Memory_free(iheap,txbuf[i32Count],BUFSIZE * TX_NUM_SERIALIZER);
977                                 }
978                 }
979           /* Display profiling results */       
980 #ifdef MEASURE_TIME
981       profiling_display_results();
982 #endif
984     BIOS_exit(0);