here is a code built "upon dsk_app" of calling FFT function. the problems are: 1- there is over flow when i call absx witch is abs of FFT out put. 2- i dont know if calling FFT is in the right place. 3- changing output frequency and input one. /* * Copyright 2003 by Spectrum Digital Incorporated. * All rights reserved. Property of Spectrum Digital Incorporated. */ /* * ======== dsk_app.c ======== * * Version 1.00 * * This example digitally processes audio data from the line input on the * AIC23 codec and plays the result on the line output. It uses the McBSP * and EDMA to efficiently handle the data transfer without intervention from * the DSP. * * Data transfer * * Audio data is transferred back and forth from the codec through McBSP2, * a bidirectional serial port. The EDMA is configured to take every 16-bit * signed audio sample arriving on McBSP1 and store it in a buffer in memory * until it can be processed. Once it has been processed, the EDMA * controller sends the data back to McBSP1 for transmission. * * A second serial port, McBSP0 is used to control/configure the AIC23. The * codec receives serial commands through McBSP0 that set configuration * parameters such as volume, sample rate and data format. * * In addition to basic EDMA transfers, this example uses 2 special * techniques to make audio processing more convenient and efficient: * * 1) Ping-pong data buffering in memory * 2) Linked EDMA transfers * * Applications with single buffers for receive and transmit data are * very tricky and timing dependent because new data constantly overwrites * the data being transmitted. Ping-pong buffering is a technique where two * buffers (referred to as the PING buffer and the PONG buffer) are used for * a data transfer instead of only one. The EDMA is configured to fill the * PING buffer first, then the PONG buffer. While the PONG buffer is being * filled, the PING buffer can be processed with the knowledge that the * current EDMA transfer won't overwrite it. This example uses ping-pong * buffers on both transmit and receive ends for a total of four buffers. * * The EDMA controller must be configured slightly differently for each * buffer. When a buffer is filled, the EDMA controller generates an * interrupt. The interrupt handler must reload the configuration * for the next buffer before the next audio sample arrives. An EDMA * feature called linked transfers is used to make this event less time * critical. Each configuration is created in advance and the EDMA * controller automatically links to the next configuration when the * current configuration is finished. An interrupt is still generated, * but it serves only to signal the DSP that it can process the data. * The only time constraint is that all the audio data must be processed * before the the active buffer fills up, which is much longer than the * time between audio samples. It is much easier to satisfy real-time * constraints with this implementation. * * Program flow * * When the program is run, the individual DSP/BIOS modules are initialized * as configured in dsk_app.cdb with the DSP/BIOS configuration tool. The * main() function is then called as the main user thread. In this example * main() performs application initialization and starts the EDMA data * transfers. When main exits, control passes back entirely to DSP/BIOS * which services any interrupts or threads on an as-needed basis. * * The edmaHwi() interrupt service routine is called when a buffer has been * filled. It contains a state variable named pingOrPong that indicates * whether the buffer is a PING or PONG buffer. dmaHwi switches the buffer * state to the opposite buffer and calls the SWI thread processBuffer to * process the audio data. * * Other Functions * * The example includes a few other functions that are executed in the * background as examples of the multitasking that DSP/BIOS is capable of: * * 1) blinkLED() toggles LED #0 every 500ms if DIP switch #0 is depressed. * It is a periodic thread with a period of 500 ticks. * * 2) load() simulates a 20-25% dummy load if DIP switch #1 is depressed. * It represents other computation that may need to be done. It is a * periodic thread with a period of 10ms. * * Please see the 6713 DSK help file under Software/Examples for more * detailed information on this example. */ /* * DSP/BIOS is configured using the DSP/BIOS configuration tool. Settings * for this example are stored in a configuration file called dsk_app.cdb. * At compile time, Code Composer will auto-generate DSP/BIOS related files * based on these settings. A header file called dsk_appcfg.h contains the * results of the autogeneration and must be included for proper operation. * The name of the file is taken from dsk_app.cdb and adding cfg.h. */ #include "dsk_appcfg.h" /* * These are include files that support interfaces to BIOS and CSL modules * used by the program. */ #include <std.h> #include <swi.h> #include <log.h> #include <c6x.h> #include <csl.h> #include <csl_edma.h> #include <csl_irq.h> #include <csl_mcbsp.h> #include<math.h> #include<stdlib.h> /* * The 6713 DSK Board Support Library is divided into several modules, each * of which has its own include file. The file dsk6713.h must be included * in every program that uses the BSL. This example also uses the * DIP, LED and AIC23 modules. */ #include "dsk6713.h" #include "dsk6713_led.h" #include "dsk6713_dip.h" #include "dsk6713_aic23.h" /* Function prototypes */ void initIrq(void); void initMcbsp(void); void initEdma(void); void copyData(Int16 *inbuf, Int16 *outbuf, Int16 length); void processBuffer(void); void edmaHwi(void); typedef struct {float real,imag;} complex; void FFT(complex *Y, int n); //FFT prototype void absx(complex *c);// /* Constants for the buffered ping-pong transfer */ #define BUFFSIZE 512 #define PING 0 #define PONG 1 #define pi 3.14159265358979 #define N 512 #define PTS 512 //# of points for FFT short index[N]; //#define NDELBUFF 60000 // delay buffer length /* * Data buffer declarations - the program uses four logical buffers of size * BUFFSIZE, one ping and one pong buffer on both receive and transmit sides. */ Int16 gBufferXmtPing[BUFFSIZE]; // Transmit PING buffer Int16 gBufferXmtPong[BUFFSIZE]; // Transmit PONG buffer Int16 gBufferRcvPing[BUFFSIZE]; // Receive PING buffer Int16 gBufferRcvPong[BUFFSIZE]; // Receive PONG buffer EDMA_Handle hEdmaXmt; // EDMA channel handles EDMA_Handle hEdmaReloadXmtPing; EDMA_Handle hEdmaReloadXmtPong; EDMA_Handle hEdmaRcv; EDMA_Handle hEdmaReloadRcvPing; EDMA_Handle hEdmaReloadRcvPong; MCBSP_Handle hMcbsp1; // McBSP1 (codec data) handle Int16 gXmtChan; // TCC codes (see initEDMA()) Int16 gRcvChan; Uint16 count; complex w[N]; complex x[N]; Int16 abss[N]; /* * EDMA Config data structure */ /* Transmit side EDMA configuration */ EDMA_Config gEdmaConfigXmt = { EDMA_FMKS(OPT, PRI, HIGH) | // Priority EDMA_FMKS(OPT, ESIZE, 16BIT) | // Element size EDMA_FMKS(OPT, 2DS, NO) | // 2 dimensional source? EDMA_FMKS(OPT, SUM, INC) | // Src update mode EDMA_FMKS(OPT, 2DD, NO) | // 2 dimensional dest EDMA_FMKS(OPT, DUM, NONE) | // Dest update mode EDMA_FMKS(OPT, TCINT, YES) | // Cause EDMA interrupt? EDMA_FMKS(OPT, TCC, OF(0)) | // Transfer complete code EDMA_FMKS(OPT, LINK, YES) | // Enable link parameters? EDMA_FMKS(OPT, FS, NO), // Use frame sync? (Uint32)&gBufferXmtPing, // Src address EDMA_FMK (CNT, FRMCNT, NULL) | // Frame count EDMA_FMK (CNT, ELECNT, BUFFSIZE), // Element count EDMA_FMKS(DST, DST, OF(0)), // Dest address EDMA_FMKS(IDX, FRMIDX, DEFAULT) | // Frame index value EDMA_FMKS(IDX, ELEIDX, DEFAULT), // Element index value EDMA_FMK (RLD, ELERLD, NULL) | // Reload element EDMA_FMK (RLD, LINK, NULL) // Reload link }; /* Receive side EDMA configuration */ EDMA_Config gEdmaConfigRcv = { EDMA_FMKS(OPT, PRI, HIGH) | // Priority EDMA_FMKS(OPT, ESIZE, 16BIT) | // Element size EDMA_FMKS(OPT, 2DS, NO) | // 2 dimensional source? EDMA_FMKS(OPT, SUM, NONE) | // Src update mode EDMA_FMKS(OPT, 2DD, NO) | // 2 dimensional dest EDMA_FMKS(OPT, DUM, INC) | // Dest update mode EDMA_FMKS(OPT, TCINT, YES) | // Cause EDMA interrupt? EDMA_FMKS(OPT, TCC, OF(0)) | // Transfer complete code EDMA_FMKS(OPT, LINK, YES) | // Enable link parameters? EDMA_FMKS(OPT, FS, NO), // Use frame sync? EDMA_FMKS(SRC, SRC, OF(0)), // Src address EDMA_FMK (CNT, FRMCNT, NULL) | // Frame count EDMA_FMK (CNT, ELECNT, BUFFSIZE), // Element count (Uint32)&gBufferRcvPing, // Dest address EDMA_FMKS(IDX, FRMIDX, DEFAULT) | // Frame index value EDMA_FMKS(IDX, ELEIDX, DEFAULT), // Element index value EDMA_FMK (RLD, ELERLD, NULL) | // Reload element EDMA_FMK (RLD, LINK, NULL) // Reload link }; /* McBSP codec data channel configuration */ static MCBSP_Config mcbspCfg1 = { MCBSP_FMKS(SPCR, FREE, NO) | MCBSP_FMKS(SPCR, SOFT, NO) | MCBSP_FMKS(SPCR, FRST, YES) | MCBSP_FMKS(SPCR, GRST, YES) | MCBSP_FMKS(SPCR, XINTM, XRDY) | MCBSP_FMKS(SPCR, XSYNCERR, NO) | MCBSP_FMKS(SPCR, XRST, YES) | MCBSP_FMKS(SPCR, DLB, OFF) | MCBSP_FMKS(SPCR, RJUST, RZF) | MCBSP_FMKS(SPCR, CLKSTP, DISABLE) | MCBSP_FMKS(SPCR, DXENA, OFF) | MCBSP_FMKS(SPCR, RINTM, RRDY) | MCBSP_FMKS(SPCR, RSYNCERR, NO) | MCBSP_FMKS(SPCR, RRST, YES), MCBSP_FMKS(RCR, RPHASE, SINGLE) | MCBSP_FMKS(RCR, RFRLEN2, DEFAULT) | MCBSP_FMKS(RCR, RWDLEN2, DEFAULT) | MCBSP_FMKS(RCR, RCOMPAND, MSB) | MCBSP_FMKS(RCR, RFIG, NO) | MCBSP_FMKS(RCR, RDATDLY, 0BIT) | MCBSP_FMKS(RCR, RFRLEN1, OF(1)) | MCBSP_FMKS(RCR, RWDLEN1, 16BIT) | MCBSP_FMKS(RCR, RWDREVRS, DISABLE), MCBSP_FMKS(XCR, XPHASE, SINGLE) | MCBSP_FMKS(XCR, XFRLEN2, DEFAULT) | MCBSP_FMKS(XCR, XWDLEN2, DEFAULT) | MCBSP_FMKS(XCR, XCOMPAND, MSB) | MCBSP_FMKS(XCR, XFIG, NO) | MCBSP_FMKS(XCR, XDATDLY, 0BIT) | MCBSP_FMKS(XCR, XFRLEN1, OF(1)) | MCBSP_FMKS(XCR, XWDLEN1, 16BIT) | MCBSP_FMKS(XCR, XWDREVRS, DISABLE), MCBSP_FMKS(SRGR, GSYNC, DEFAULT) | MCBSP_FMKS(SRGR, CLKSP, DEFAULT) | MCBSP_FMKS(SRGR, CLKSM, DEFAULT) | MCBSP_FMKS(SRGR, FSGM, DEFAULT) | MCBSP_FMKS(SRGR, FPER, DEFAULT) | MCBSP_FMKS(SRGR, FWID, DEFAULT) | MCBSP_FMKS(SRGR, CLKGDV, DEFAULT), MCBSP_MCR_DEFAULT, MCBSP_RCER_DEFAULT, MCBSP_XCER_DEFAULT, MCBSP_FMKS(PCR, XIOEN, SP) | MCBSP_FMKS(PCR, RIOEN, SP) | MCBSP_FMKS(PCR, FSXM, EXTERNAL) | MCBSP_FMKS(PCR, FSRM, EXTERNAL) | MCBSP_FMKS(PCR, CLKXM, INPUT) | MCBSP_FMKS(PCR, CLKRM, INPUT) | MCBSP_FMKS(PCR, CLKSSTAT, DEFAULT) | MCBSP_FMKS(PCR, DXSTAT, DEFAULT) | MCBSP_FMKS(PCR, FSXP, ACTIVEHIGH) | MCBSP_FMKS(PCR, FSRP, ACTIVEHIGH) | MCBSP_FMKS(PCR, CLKXP, FALLING) | MCBSP_FMKS(PCR, CLKRP, RISING) }; /* Codec configuration settings */ DSK6713_AIC23_Config config = { \ 0x0017, /* 0 DSK6713_AIC23_LEFTINVOL Left line input channel volume */ \ 0x0017, /* 1 DSK6713_AIC23_RIGHTINVOL Right line input channel volume */\ 0x01f9, /* 2 DSK6713_AIC23_LEFTHPVOL Left channel headphone volume */ \ 0x01f9, /* 3 DSK6713_AIC23_RIGHTHPVOL Right channel headphone volume */ \ 0x0011, /* 4 DSK6713_AIC23_ANAPATH Analog audio path control */ \ 0x0000, /* 5 DSK6713_AIC23_DIGPATH Digital audio path control */ \ 0x0000, /* 6 DSK6713_AIC23_POWERDOWN Power down control */ \ 0x0043, /* 7 DSK6713_AIC23_DIGIF Digital audio interface format */ \ 0x0001, /* 8 DSK6713_AIC23_SAMPLERATE Sample rate control */ \ 0x0001 /* 9 DSK6713_AIC23_DIGACT Digital interface activation */ \ }; float inBuff[2*N];// input delay buffer float OutBuff[2*N];// output delay buffer /* --------------------------- main() function -------------------------- */ /* * main() - The main user task. Performs application initialization and * starts the data transfer. */ void main() { Uint16 ii; /* Initialize Board Support Library */ DSK6713_init(); /* Initialize LEDs and DIP switches */ DSK6713_LED_init(); DSK6713_DIP_init(); /* Clear buffers */ memset((void *)gBufferXmtPing, 0, BUFFSIZE * 4 * 2); for (ii=0 ; ii<2*N ; ii++) { inBuff[ii]=0.0; OutBuff[ii]=0.0; } AIC23_setParams(&config); // Configure the codec initMcbsp(); // Initialize McBSP1 for audio transfers IRQ_globalDisable(); // Disable global interrupts during setup initEdma(); // Initialize the EDMA controller initIrq(); // Initialize interrupts IRQ_globalEnable(); // Re-enable global interrupts } /* ------------------------Helper Functions ----------------------------- */ /* * initMcbsp() - Initialize the McBSP for codec data transfers using the * configuration define at the top of this file. */ void initMcbsp() { /* Open the codec data McBSP */ hMcbsp1 = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET); /* Configure the codec to match the AIC23 data format */ MCBSP_config(hMcbsp1, &mcbspCfg1); /* Start the McBSP running */ MCBSP_start(hMcbsp1, MCBSP_XMIT_START | MCBSP_RCV_START | MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC, 220); } /* * initIrq() - Initialize and enable the DMA receive interrupt using the CSL. * The interrupt service routine for this interrupt is edmaHwi. */ void initIrq(void) { /* Enable EDMA interrupts to the CPU */ IRQ_clear(IRQ_EVT_EDMAINT); // Clear any pending EDMA interrupts IRQ_enable(IRQ_EVT_EDMAINT); // Enable EDMA interrupt } /* * initEdma() - Initialize the DMA controller. Use linked transfers to * automatically transition from ping to pong and visa-versa. */ void initEdma(void) { /* Configure transmit channel */ hEdmaXmt = EDMA_open(EDMA_CHA_XEVT1, EDMA_OPEN_RESET); // get hEdmaXmt handle and reset channel hEdmaReloadXmtPing = EDMA_allocTable(-1); // get hEdmaReloadXmtPing handle hEdmaReloadXmtPong = EDMA_allocTable(-1); // get hEdmaReloadXmtPong handle gEdmaConfigXmt.dst = MCBSP_getXmtAddr(hMcbsp1); // set the desination address to McBSP1 DXR gXmtChan = EDMA_intAlloc(-1); // get an open TCC gEdmaConfigXmt.opt |= EDMA_FMK(OPT,TCC,gXmtChan); // set TCC to gXmtChan EDMA_config(hEdmaXmt, &gEdmaConfigXmt); // then configure the registers EDMA_config(hEdmaReloadXmtPing, &gEdmaConfigXmt); // and the reload for Ping gEdmaConfigXmt.src = EDMA_SRC_OF(gBufferXmtPong); // change the structure to have a source of Pong EDMA_config(hEdmaReloadXmtPong, &gEdmaConfigXmt); // and configure the reload for Pong EDMA_link(hEdmaXmt,hEdmaReloadXmtPong); // link the regs to Pong EDMA_link(hEdmaReloadXmtPong,hEdmaReloadXmtPing); // link Pong to Ping EDMA_link(hEdmaReloadXmtPing,hEdmaReloadXmtPong); // and link Ping to Pong /* Configure receive channel */ hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET); // get hEdmaRcv handle and reset channel hEdmaReloadRcvPing = EDMA_allocTable(-1); // get hEdmaReloadRcvPing handle hEdmaReloadRcvPong = EDMA_allocTable(-1); // get hEdmaReloadRcvPong handle gEdmaConfigRcv.src = MCBSP_getRcvAddr(hMcbsp1); // and the desination address to McBSP1 DXR gRcvChan = EDMA_intAlloc(-1); // get an open TCC gEdmaConfigRcv.opt |= EDMA_FMK(OPT,TCC,gRcvChan); // set TCC to gRcvChan EDMA_config(hEdmaRcv, &gEdmaConfigRcv); // then configure the registers EDMA_config(hEdmaReloadRcvPing, &gEdmaConfigRcv); // and the reload for Ping gEdmaConfigRcv.dst = EDMA_DST_OF(gBufferRcvPong); // change the structure to have a destination of Pong EDMA_config(hEdmaReloadRcvPong, &gEdmaConfigRcv); // and configure the reload for Pong EDMA_link(hEdmaRcv,hEdmaReloadRcvPong); // link the regs to Pong EDMA_link(hEdmaReloadRcvPong,hEdmaReloadRcvPing); // link Pong to Ping EDMA_link(hEdmaReloadRcvPing,hEdmaReloadRcvPong); // and link Ping to Pong /* Enable interrupts in the EDMA controller */ EDMA_intClear(gXmtChan); EDMA_intClear(gRcvChan); // clear any possible spurious interrupts EDMA_intEnable(gXmtChan); // enable EDMA interrupts (CIER) EDMA_intEnable(gRcvChan); // enable EDMA interrupts (CIER) EDMA_enableChannel(hEdmaXmt); // enable EDMA channel EDMA_enableChannel(hEdmaRcv); // enable EDMA channel /* Do a dummy write to generate the first McBSP transmit event */ MCBSP_write(hMcbsp1, 0); } /* ---------------------- Interrupt Service Routines -------------------- */ /* * edmaHwi() - Interrupt service routine for the DMA transfer. It is * triggered when a complete DMA receive frame has been * transferred. The edmaHwi ISR is inserted into the interrupt * vector table at compile time through a setting in the DSP/BIOS * configuration under Scheduling --> HWI --> HWI_INT8. edmaHwi * uses the DSP/BIOS Dispatcher to save register state and make * sure the ISR co-exists with other DSP/BIOS functions. */ void edmaHwi(void) { static Uint32 pingOrPong = PING; // Ping-pong state variable static Int16 xmtdone = 0, rcvdone = 0; /* Check CIPR to see which transfer completed */ if (EDMA_intTest(gXmtChan)) { EDMA_intClear(gXmtChan); xmtdone = 1; } if (EDMA_intTest(gRcvChan)) { EDMA_intClear(gRcvChan); rcvdone = 1; } /* If both transfers complete, signal processBufferSwi to handle */ if (xmtdone && rcvdone) { if (pingOrPong==PING) { SWI_or(&processBufferSwi, PING); pingOrPong = PONG; } else { SWI_or(&processBufferSwi, PONG); pingOrPong = PING; } rcvdone = 0; xmtdone = 0; } } /* ------------------------------- Threads ------------------------------ */ /* * processBuffer() - Process audio data once it has been received. */ void copyData(Int16 *inbuf, Int16 *outbuf, Int16 length) { Uint16 i=0; for(i=0;i<length;i++) outbuf[i]=inbuf[i]; } void processBuffer(void) { Uint16 i=0; static Uint16 j=0; Int16 temp ; Uint32 pingPong; /* Get contents of mailbox posted by edmaHwi */ pingPong = SWI_getmbox(); //??????????????????????????????????????????????? /* Copy data from transmit to receive, could process audio here */ if (pingPong == PING) { /* Toggle LED #3 as a visual cue */ DSK6713_LED_toggle(3); for(i=0 ; i<N ; i++) { inBuff[j] = (float)gBufferRcvPing[i];// get left sample x[j].real=inBuff[j]; x[j].imag=0.0; i++; temp=(float)gBufferRcvPing[i];//get right sample x[i].real=inBuff[j]; x[i].imag=0.0; if(j<2*N -1) j++; else j=0; } FFT(x,N); absx(x); for(i=0 ; i<N ; i++) { inBuff[j] = (float)abss[i];// get left sample OutBuff[j]=inBuff[j]; gBufferXmtPing[i]=(Int16)OutBuff[j];// output left sample i++; temp=(float)abss[i];//get right sample gBufferXmtPing[i]=(Int16)OutBuff[j];// output left sample(forget right) if(j<2*N -1) j++; else j=0; } } else { /* Toggle LED #2 as a visual cue */ DSK6713_LED_toggle(2); for(i=0 ; i<N ; i++) { inBuff[j] = (float)gBufferRcvPong[i];// get left sample x[j].real=inBuff[j]; x[j].imag=0.0; i++; temp=(float)gBufferRcvPong[i];//get right sample x[i].real=inBuff[j]; x[i].imag=0.0; if(j<2*N -1) j++; else j=0; } FFT(x,N); absx(x); for(i=0 ; i<N ; i++) { inBuff[j] = (float)abss[i];// get left sample OutBuff[j]=inBuff[j]; gBufferXmtPong[i]=(Int16)OutBuff[j];// output left sample i++; temp=(float)abss[i];//get right sample gBufferXmtPong[i]=(Int16)OutBuff[j];// output left sample(forget right) if(j<2*N -1) j++; else j=0; } } } /* * blinkLED() - Periodic thread (PRD) that toggles LED #0 every 500ms if * DIP switch #0 is depressed. The thread is configured * in the DSP/BIOS configuration tool under Scheduling --> * PRD --> PRD_blinkLed. The period is set there at 500 * ticks, with each tick corresponding to 1ms in real * time. */ void blinkLED(void) { /* Toggle LED #0 if DIP switch #0 is off (depressed) */ if (!DSK6713_DIP_get(0)) DSK6713_LED_toggle(0); } /* * load() - PRD that simulates a 20-25% dummy load on a 225MHz 6713 if * DIP switch #1 is depressed. The thread is configured in * the DSP/BIOS configuration tool under Scheduling --> PRD * PRD_load. The period is set there at 10 ticks, which each tick * corresponding to 1ms in real time. */ void load(void) { volatile Uint32 i; if (!DSK6713_DIP_get(1)) for (i = 0; i < 30000; i++); } void absx(complex *c) { Uint16 i=0; double tmp; for(i=0;i<N; i++) { tmp= (( c[i].real)*( c[i].real))+(( c[i].imag)*( c[i].imag)); abss[i] = (Int16) sqrt(tmp); } //abss[0] = 32000.0; //negative spike for reference }