509c70409a434ba834a30dcd9a8ffe3bd9237ec2
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)
246 {
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 }
272 }
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)
287 {
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 }
311 }
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)
329 {
330 gblErrFlagXmt=1;
331 errCbStatusXmt=errCbStat;
332 }
333 /* Error handler for Rcv side */
334 void GblErrRcv(Mcasp_errCbStatus errCbStat)
335 {
336 gblErrFlagRcv=1;
337 errCbStatusRcv=errCbStat;
338 }
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)
350 {
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);
357 }
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()
365 {
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
393 #endif
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
449 }
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()
460 {
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 }
554 }
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));
560 }
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()
581 {
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);
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(¶ms);
628 /* Create semaphores to wait for buffer reclaiming */
629 semR = Semaphore_create(0, ¶ms, &eb);
630 semT = Semaphore_create(0, ¶ms, &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 ***************************/
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 }
948 }
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);
985 }