/*---------------------------------------------------------------------- File: gtzsa.c Description: Perform goertzel algorithm on 205 samples of codec input. Sends goetzel value periodically to mailbox. Also sends the orginal sample modulated with the goertzel value out to both channel of codec. The program also uses double buffering techniques and auto-initializing dma to send and receive codec data. Similar with gtzdma.c except goertzel is in gtz_sa.sa. -----------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #define SAMPLING_RATE 8000 extern int inicodec (int sampling_rate); #pragma CODE_SECTION(DMA_Interrupt,".iprog") #pragma DATA_SECTION(InBuffer1,".edata") #pragma DATA_SECTION(InBuffer2,".edata") #pragma DATA_SECTION(OutBuffer1,".edata") #pragma DATA_SECTION(OutBuffer2,".edata") #pragma DATA_SECTION(ptrInBuffer,".edata") #pragma DATA_SECTION(ptrOutBuffer,".edata") #define BUFFER_SIZE 205 unsigned int InBuffer1 [BUFFER_SIZE]; // First of 2 alternate input buffer to store serial data. unsigned int InBuffer2 [BUFFER_SIZE]; // Second of 2 alternate input buffer to store serial data. unsigned int *ptrInBuffer; // Pointer (either == InBuffer1 or == InBuffer2) waiting to be filled. unsigned int OutBuffer1 [BUFFER_SIZE]; // First of 2 alternate output buffer to send serial data. unsigned int OutBuffer2 [BUFFER_SIZE]; // Second of 2 alternate output buffer to send serial data. unsigned int *ptrOutBuffer; // Pointer (either == OutBuffer1 or == OutBuffer2) yet to have data to send. extern int gz (unsigned int *input, int coef, int count); /* ----------------------------------------------------------------------- Configure DMA0 to perform autobuffering alternating between 2 buffers -------------------------------------------------------------------------- */ inline void Init_DMA (void) { DMA_GCR_A = BUFFER_SIZE; // Reload counter after block transfer. //================ DMA 2 for receiving codec data ========================== DMA_GADDR_B = (unsigned int) InBuffer2; // Set next buffer to 2nd alternate buffer. DMA2_PRIMARY_CTRL = (DMA_RELOAD_GARB << 30) // Reload destination address with global address B. | (DMA_RELOAD_NONE << 28) // Don't reload source address (fixed) | (0 << 27) // Emode, DMA halts(1) continues(0) during emulation. | (0 << 26) // FS=0, No frame sync. | (1 << 25) // TCINT=1, enable dma interrupt. | (DMA_DMA_PRI << 24) // DMA has priority of CPU on internal bus. | (SEN_NONE << 19) // No need Write Sync. write to buffer asap. | (SEN_REVT0 << 14) // Read Sync from receive-buffer-full of MCBSP0. | (DMA_GNDX_A << 13) // Use global index register A as programmable index. | (DMA_CNT_RELOADA << 12) // Use global count reload register A for auto reload. | (DMA_SPLIT_DIS << 10) // Disable split channel mode. | (DMA_ESIZE32 << 8) // Set element size to 32-bit. | (DMA_ADDR_INC << 6) // Auto-increment destination address after each transfer. | (DMA_ADDR_NO_MOD << 4) // Fix source address. | (DMA_STOP_VAL ); // Stop dma now. Start later, after configuration. DMA2_SECONDARY_CTRL = (1 << 15) // Clear any prior WSYNC status. | (1 << 13) // Clear any prior RSYNC status. | (1 << 7); // Enable block-transfer-end interrupt. DMA2_SRC_ADDR = (unsigned int) MCBSP_DRR_ADDR (0); // Source address is receive data of MCBSP0 DMA2_DEST_ADDR = (unsigned int) InBuffer1; // Destination address is 1st of 2 DMA buffers. DMA2_XFER_COUNTER = BUFFER_SIZE; // Set to transfer BUFFER_SIZE words of 32 bits each. ptrInBuffer = InBuffer1; // Set the current buffer to be filled. //================ DMA 1 for transmitting codec data ========================== DMA_GADDR_C = (unsigned int) OutBuffer2; // Set next buffer to 2nd alternate buffer. DMA1_PRIMARY_CTRL = (DMA_RELOAD_NONE << 30) // Don't reload destination address (fixed) | (DMA_RELOAD_GARC << 28) // Reload source address with global address C. | (0 << 27) // Emode, DMA halts(1) continues(0) during emulation. | (0 << 26) // FS=0, No frame sync. | (0 << 25) // TCINT=1 => enable dma interrupt. | (DMA_DMA_PRI << 24) // DMA has priority of CPU on internal bus. | (SEN_XEVT0 << 19) // Write Sync. from transmit buffer of MCBSP0. | (SEN_NONE << 14) // No need Read Sync. | (DMA_GNDX_A << 13) // Use global index register A as programmable index. | (DMA_CNT_RELOADA << 12) // Use global count reload register A for auto reload. | (DMA_SPLIT_DIS << 10) // Disable split channel mode. | (DMA_ESIZE32 << 8) // Set element size to 32-bit. | (DMA_ADDR_NO_MOD << 6) // Fixed destination. | (DMA_ADDR_INC << 4) // Auto-increment source address. | (DMA_STOP_VAL ); // Stop dma now. Start later, after configuration. DMA1_SECONDARY_CTRL = (1 << 15) // Clear any prior WSYNC status. | (1 << 13); // Clear any prior RSYNC status. DMA1_DEST_ADDR = (unsigned int) MCBSP_DXR_ADDR (0); // Source address is receive data of MCBSP0 DMA1_SRC_ADDR = (unsigned int) OutBuffer1; // Destination address is 1st of 2 DMA buffers. DMA1_XFER_COUNTER = BUFFER_SIZE; // Set to transfer BUFFER_SIZE words of 32 bits each. ptrOutBuffer = OutBuffer1; // Set the current buffer to be filled. /************************************************************************ Note: DMA2 interrupt to process data. In this implementation, channel 1 is started first and it has higher priority than channel 2. In this way, we are sure that by the time we process the data in DMA2 interrupt, both reload addresses has been used. ************************************************************************/ memset (OutBuffer1, 0, BUFFER_SIZE * sizeof (int)); memset (OutBuffer2, 0, BUFFER_SIZE * sizeof (int)); DMA_AUTO_START (1); // Start DMA1 with auto-reload. DMA_AUTO_START (2); // Start DMA2 with auto-reload. return; } interrupt void DMA_Interrupt (void) { // static int times = 0; // int delay_2 = 0; // int delay_1 = 0; // int delay; int input; int coef_1 = 0x4A70; int i; int Goertzel_Value; int prod1; //prod2, prod3, prod4; //============== evaluate goertzel value ================= // attenuate input to avoid overflow //======================================================== Goertzel_Value = gz (ptrInBuffer, coef_1, BUFFER_SIZE); Goertzel_Value=Goertzel_Value<<4 ; if (Goertzel_Value <0) Goertzel_Value = 0; // Value cannot be negative. (Magnitude) *(unsigned int *)(PCI_MAP1_BASE_ADDR+AMCC_AOMB1_OFFSET) = (unsigned int) Goertzel_Value; // Send value out to mailbox. //============ modulate sample with goertzel value ============= for (i=0; i>16; prod1 = ((short)input * (short)(Goertzel_Value)) >> 15; prod1 = prod1 & 0xffff; prod1 = (prod1<<16) | prod1; ptrOutBuffer[i] = prod1; } //============ send processed sample ============= DMA_GADDR_B = (unsigned int) ptrInBuffer; // Prepare reload address for next block. DMA_GADDR_C = (unsigned int) ptrOutBuffer; // Prepare reload address for next block. if (ptrInBuffer == InBuffer1) // Alternate the ptrCurrentBuffer between the { ptrInBuffer = InBuffer2; // two buffers viz. Buffer1 and Buffer2. ptrOutBuffer = OutBuffer2; // two buffers viz. Buffer1 and Buffer2. } else { ptrInBuffer = InBuffer1; ptrOutBuffer = OutBuffer1; } DMA2_SECONDARY_CTRL &= 0xffffffbf; // Clear block-transfer-end condition. } void Init_Interrupts () { intr_reset(); INTR_CLR_FLAG (CPU_INT9); intr_hook (DMA_Interrupt, CPU_INT9); intr_map (CPU_INT9, ISN_DMA_INT2); INTR_ENABLE (CPU_INT9); } void main(void) { evm_init(); // Initialise EVM board. Init_DMA (); // Initialise dma. inicodec (SAMPLING_RATE); // Initialise codec, adjust sampling rate. Init_Interrupts (); // Initialise interrupts and hook isr. INTR_GLOBAL_ENABLE(); // Enable global interrupt. for (;;); // Main loop, does nothing. }