📄 audio_test.c
字号:
/*****************************************************************************
** **
** Name: Audio_test.c **
** **
******************************************************************************
(C) Copyright 2006 - Analog Devices, Inc. All rights reserved.
Project Name: BF538F POST ATE
Date Modified: 01 Sept 2006
Software: VisualDSP++ 4.5
Hardware: ADSP-BF538F EZ-KIT Lite
Purpose: This program sets up the ADSP-BF538F to reset the ADC and DAC.
The data to/from the DAC/ADC are transfered over SPORT0 in I2S mode.
*****************************************************************************/
#include <math.h>
#include <sysreg.h>
#include <ccblkfn.h>
#include <signal.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <filter.h>
#include "post_common.h"
#include "Pll.h"
#include "Timer_ISR.h"
//--------------------------------------------------------------------------//
// function prototypes
//--------------------------------------------------------------------------//
EX_INTERRUPT_HANDLER(Sport0_RX_ISR);
//--------------------------------------------------------------------------//
// Symbolic constants //
//--------------------------------------------------------------------------//
// names for registers in AD1854/AD187 converters
#define INTERNAL_ADC_L0 0
#define INTERNAL_ADC_R0 1
#define INTERNAL_DAC_L0 0
#define INTERNAL_DAC_R0 1
#define SLEN_24 0x0017// SPORT0 word length
#define FLOW_1 0x1000// DMA flow mode
//--------------------------------------------------------------------------//
// Test paramaters //
//--------------------------------------------------------------------------//
#define MAX_SAMPLES 256
#define REQUIRED_SAMPLES ((MAX_SAMPLES) * 250)
#define DESIRED_FREQ ((float)3000.0)
#define SAMPLE_RATE ((float)48000.0)
#define AMPLITUDE ((float)8388607)
#define PI ((float)3.141592765309)
#define ACCEPTABLE_DEVIATION_PCT ((float)0.015)
#define ACCEPTABLE_DEVIATION (DESIRED_FREQ * ACCEPTABLE_DEVIATION_PCT)
#define MAX_DESIRED_FREQ (DESIRED_FREQ + ACCEPTABLE_DEVIATION)
#define MIN_DESIRED_FREQ (DESIRED_FREQ - ACCEPTABLE_DEVIATION)
#define MIN_SIGNAL_STRENGTH (float)30.0
#define MAX_NOISE_THRESHOLD (float)10.0
//--------------------------------------------------------------------------//
// Variables used for test
//--------------------------------------------------------------------------//
volatile int g_iSampleIndex = 1;
volatile int g_iSampleCount = 0;
short g_fSineWaveIn_Left[MAX_SAMPLES];
short g_fSineWaveIn_Right[MAX_SAMPLES];
int iTxBuffer1[2];// SPORT0 DMA transmit buffer
int iRxBuffer1[2];// SPORT0 DMA receive buffer
//--------------------------------------------------------------------------//
// Function: Init_Sport0 //
// //
// Description: Configure PORTD flags to control ADC and DAC RESETs
//--------------------------------------------------------------------------//
void Init_Flags(void)
{
//set PORTD config register
*pPORTDIO_FER = 0x0010; // setup port for PD4 GPIO
// set PORTD direction register
*pPORTDIO_DIR = 0x0010; // PD4 output
}
//--------------------------------------------------------------------------//
// Function: Init_Sport0 //
// //
// Description: This function Resets the ADC and DAC.
//--------------------------------------------------------------------------//
void Audio_Reset(void)
{
int i;
// set PORTF clear register
*pPORTDIO_CLEAR = 0x0010;
// give some time for reset to take affect
for(i = 0; i< 0xf00;i++){};
// set port D set register
*pPORTDIO_SET = 0x0010;
}
//--------------------------------------------------------------------------//
// Function: Init_Sport0 //
// //
// Description: Configure Sport0 for I2S mode, to transmit/receive data //
// to/from the ADC/DAC.Configure Sport for external clocks and //
// frame syncs. //
//--------------------------------------------------------------------------//
void Init_Sport0(void)
{
// Sport0 receive configuration
// External CLK, External Frame sync, MSB first, Active Low
// 24-bit data, Secondary side enable, Stereo frame sync enable
*pSPORT0_RCR1 = RFSR | LRFS | RCKFE;
*pSPORT0_RCR2 = SLEN_24 | RSFSE;
// Sport0 transmit configuration
// External CLK, External Frame sync, MSB first, Active Low
// 24-bit data, Secondary side enable, Stereo frame sync enable
*pSPORT0_TCR1 = TFSR | LTFS | TCKFE;
*pSPORT0_TCR2 = SLEN_24 | TSFSE;
}
//--------------------------------------------------------------------------//
// Function: Init_DMA //
// //
// Description: Initialize DMA1 in autobuffer mode to receive and DMA2 in //
// autobuffer mode to transmit //
//--------------------------------------------------------------------------//
void Init_DMA(void)
{
// Configure DMA3
// 32-bit transfers, Interrupt on completion, Autobuffer mode
*pDMA1_CONFIG = WNR | WDSIZE_32 | DI_EN | FLOW_1;
// Start address of data buffer
*pDMA1_START_ADDR = iRxBuffer1;
// DMA loop count
*pDMA1_X_COUNT = 2;
// DMA loop address increment
*pDMA1_X_MODIFY = 4;
// Configure DMA4
// 32-bit transfers, Autobuffer mode
*pDMA2_CONFIG = WDSIZE_32 | FLOW_1;
// Start address of data buffer
*pDMA2_START_ADDR = iTxBuffer1;
// DMA loop count
*pDMA2_X_COUNT = 2;
// DMA loop address increment
*pDMA2_X_MODIFY = 4;
}
//--------------------------------------------------------------------------//
// Function: Enable_DMA_Sport //
// //
// Description: Enable DMA1, DMA2, Sport0 TX and Sport0 RX //
//--------------------------------------------------------------------------//
void Enable_DMA_Sport0(void)
{
// enable DMAs
*pDMA2_CONFIG = (*pDMA2_CONFIG | DMAEN);
*pDMA1_CONFIG = (*pDMA1_CONFIG | DMAEN);
// enable Sport0 TX and RX
*pSPORT0_TCR1 = (*pSPORT0_TCR1 | TSPEN);
*pSPORT0_RCR1 = (*pSPORT0_RCR1 | RSPEN);
}
//--------------------------------------------------------------------------//
// Function: Init_Interrupts //
// //
// Description: Initialize Interrupt for Sport0 RX //
//--------------------------------------------------------------------------//
void Init_Interrupts(void)
{
// Set Sport0 RX (DMA1) interrupt priority to 2 = IVG9
*pSIC_IAR1 &= 0xffffff0f;
*pSIC_IAR1 |= 0x00000020;
// assign ISRs to interrupt vectors
// Sport0 RX ISR -> IVG 9
register_handler(ik_ivg9, Sport0_RX_ISR);
// enable Sport0 RX interrupt
*pSIC_IMASK0 |= 0x00000200;
}
//--------------------------------------------------------------------------//
// Function: Sport0_RX_ISR //
// //
// Description: This ISR is executed after a complete frame of input data //
// has been received. The new samples are stored in //
// iChannel0LeftIn and iChannel0RightIn. Then the function //
// Process_Data() is called in which user code can be executed.//
// After that the processed values are copied from the //
// variables iChannel0LeftOut and iChannel0RightOut into the //
// DMA transmit buffer. //
//--------------------------------------------------------------------------//
EX_INTERRUPT_HANDLER(Sport0_RX_ISR)
{
int iChannelX;
float fIn;
// confirm interrupt handling
*pDMA1_IRQ_STATUS = 0x0001;
// right channel in
iChannelX = iRxBuffer1[INTERNAL_ADC_L0];
iChannelX = (iChannelX >> 8);
g_fSineWaveIn_Right[g_iSampleIndex] = (short)iChannelX;
iChannelX = iRxBuffer1[INTERNAL_ADC_R0];
iChannelX = (iChannelX >> 8);
g_fSineWaveIn_Left[ g_iSampleIndex ] = (short)iChannelX;
// send data to output
iChannelX = (int)(AMPLITUDE * sin( (2.0 * PI * DESIRED_FREQ * ( ((float)(g_iSampleCount+1)) / SAMPLE_RATE))) );
iTxBuffer1[INTERNAL_DAC_L0] = iChannelX;
iTxBuffer1[INTERNAL_DAC_R0] = iChannelX;
g_iSampleIndex++; // only increment the index when both channels have been sent.
if( g_iSampleIndex > MAX_SAMPLES-1 )
g_iSampleIndex = 0;
g_iSampleCount++;
}
//--------------------------------------------------------------------------//
// Function: Test_Channel //
// //
// Description: Takes a buffer of data and determines if the frequecny is
// and amplitude are within acceptable limits
//--------------------------------------------------------------------------//
int Test_Channel(short* psRealIn)
{
short nSampleNumber;
short iTempFreq;
short nHighestFreqIndex;
float fSampledFrequency;
short iAllFreqs[MAX_SAMPLES/2];
int i = 0;
// twiddle factors
complex_fract16 w[MAX_SAMPLES];
complex_fract16 out[MAX_SAMPLES];
complex_fract16 t[MAX_SAMPLES];
fract16 in[MAX_SAMPLES];
// create the input sinewave 3000 hz at 48000 sample rate amplitude is 24-bit's max
for( nSampleNumber = 0; nSampleNumber < MAX_SAMPLES; nSampleNumber++ )
{
in[nSampleNumber] = (short)psRealIn[nSampleNumber];
}
// generate twiddle factors
twidfftrad2_fr16(w, MAX_SAMPLES);
// perform real fft
rfft_fr16( in, t, out, w, 1, MAX_SAMPLES, 0, 0 );
// expect one of the index's of the array to contain a
// 'spike' or high value such that frequency == index * (SAMPLE_RATE/MAX_SAMPLES) == 3000
iTempFreq = (short)sqrt(out[0].re*out[0].re+out[0].im*out[0].im);
iAllFreqs[0] = iTempFreq;
for( nSampleNumber = 1; nSampleNumber < (MAX_SAMPLES / 2); nSampleNumber++ )
{
iAllFreqs[nSampleNumber] = (short)sqrt(out[nSampleNumber].re*out[nSampleNumber].re+out[nSampleNumber].im*out[nSampleNumber].im);
if( ((short)sqrt(out[nSampleNumber].re*out[nSampleNumber].re+out[nSampleNumber].im*out[nSampleNumber].im)) > iTempFreq )
{
iTempFreq = (short)sqrt(out[nSampleNumber].re*out[nSampleNumber].re+out[nSampleNumber].im*out[nSampleNumber].im);
nHighestFreqIndex = nSampleNumber;
}
}
// multiply the index of the array of the highest value with the sample rate value
fSampledFrequency = nHighestFreqIndex * (SAMPLE_RATE / MAX_SAMPLES);
// make sure frequency is within acceptable ranges
if( (fSampledFrequency < MAX_DESIRED_FREQ) && (fSampledFrequency > MIN_DESIRED_FREQ) )
{
// check the signal streangth
float fDB = 10 * log10( (float)iTempFreq );
if( fDB < MIN_SIGNAL_STRENGTH )
{
return 0; // test failed
}
float fSigStrength = 0.0;
for( i = 1; i < (MAX_SAMPLES / 2); i++)
{
fSigStrength = 10 * log10( (float)iAllFreqs[i] );
if( (fSigStrength > MAX_NOISE_THRESHOLD) && (i != nHighestFreqIndex) )
return 0; // test failed
}
return 1;
}
return 0; // test failed
}
int TEST_AUDIO(void)
{
int nResult = 0;
g_iSampleCount = 0;
Init_Timers();
Init_Timer_Interrupts();
Init_Flags();
Audio_Reset();
Init_Sport0();
Init_DMA();
Init_Interrupts();
Enable_DMA_Sport0();
unsigned int nTimer = SetTimeout(0x50000);
if( ((unsigned int)-1) != nTimer )
{
// once the required number of samples has been collected,
// process the signal.
do{
asm("nop;");
}while( (g_iSampleCount < REQUIRED_SAMPLES) && (!IsTimedout(nTimer)) );
}
ClearTimeout(nTimer);
// turn off interrupts so that the data is stable.
interrupt(ik_ivg9, SIG_IGN);
// disable Sport0 RX interrupt
*pSIC_IMASK &= (~0x00000200);
// test the right channel
nResult = Test_Channel(g_fSineWaveIn_Right);
if( 1 == nResult ) // Right channel was OK, test left channel
{
nResult = Test_Channel(g_fSineWaveIn_Left);
}
// turn off any of the interrupts used
return nResult;
}
//--------------------------------------------------------------------------//
// Function: main //
// //
// Description: After calling a few initalization routines, main() just //
// waits in a loop forever. The code to process the incoming //
// data can be placed in the function Process_Data() in the //
// file "Process_Data.c". //
//--------------------------------------------------------------------------//
#ifdef _STANDALONE_ // use this to run standalone tests
void main(void)
{
int n;
TEST_AUDIO();
}
#endif //_STANDALONE_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -