📄 test_ez_audio.c
字号:
/*********************************************************************************
Copyright(c) 2005 Analog Devices, Inc. All Rights Reserved.
This software is proprietary and confidential. By using this software you agree
to the terms of the associated Analog Devices License Agreement.
Description:
This is the source code for the Blackfin EZ-Audio Power On Self Test
(POST).
*********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sysreg.h>
#include <ccblkfn.h>
#include <math.h>
#include <filter.h>
#include <signal.h>
#include <string.h>
#include "Test_EZ_Audio.h"
#include "AD1938_Test.h"
#include "ADAV801_Test.h"
//////////////////////////////////////////////////////////////////////////////
// Common defines
//////////////////////////////////////////////////////////////////////////////
typedef struct CODEC_NAMES_tag
{
char *pName;
int iChannel;
}CODEC_NAMES;
//////////////////////////////////////////////////////////////////////////////
// Globals
//////////////////////////////////////////////////////////////////////////////
volatile float g_fDesired_Freq = ((float)5000.0);
volatile float g_fSamplesPerSin = 1;
volatile int g_iBufferSampleSize = 1;
volatile unsigned char g_ucAudioInEnable = 0;
volatile int g_iSampleIndex = 0;
volatile long g_lSampleCount = 0;
unsigned int g_uiOutputSampleIndex = 0;
volatile long g_lAudioInputBufferL[AUDIO_IN_BUF_LEN];
volatile long g_lAudioInputBufferR[AUDIO_IN_BUF_LEN];
volatile long g_lAudioOutputBufferRef[AUDIO_IN_BUF_LEN];
//--------------------------------------------------------------------------//
// Function: int TEST_1938(void)
// //
// Description: Perform frequency and amplitude test on AD1938
//--------------------------------------------------------------------------//
int TEST_1938(void)
{
int i;
int j;
int iResult = 1;
int nIndex;
int nFreqIndex;
const float fFreq[NUM_TEST_FREQUENCIES] = {440.0, 1000.0, 2000.0, 3000.0, 5000.0, 8000.0, 16000};
const CODEC_NAMES g_cstADC_Names[] =
{
{"ADC Channel1", INTERNAL_ADC_L1},
{"ADC Channel2", INTERNAL_ADC_L2},
{"ADC Channel3", INTERNAL_ADC_L3},
{"ADC Channel4", INTERNAL_ADC_L4} };
const CODEC_NAMES g_cstDAC_Names[] =
{
{"DAC Channel1", INTERNAL_DAC_L1},
{"DAC Channel3", INTERNAL_DAC_L3},
{"DAC Channel5", INTERNAL_DAC_L5},
{"DAC Channel7", INTERNAL_DAC_L7},
{"DAC Channel2", INTERNAL_DAC_L2},
{"DAC Channel4", INTERNAL_DAC_L4},
{"DAC Channel6", INTERNAL_DAC_L6},
{"DAC Channel8", INTERNAL_DAC_L8} };
*pFIO_DIR = 0x0003;
*pFIO_FLAG_S = 0x0003;
Init1938_B();
Init1938_A();
Init_Sport1();
Init_Sport1_DMA();
Init_Sport1_Interrupts();
Enable_Sport1_DMA();
// check each channel individually
for( nIndex = 0; nIndex < 4; nIndex++ )
//for( nIndex = 0; nIndex < 1; nIndex++ )
{
for(nFreqIndex = 0; nFreqIndex < NUM_TEST_FREQUENCIES; nFreqIndex++)
//for(nFreqIndex = 0; nFreqIndex < 1; nFreqIndex++)
{
g_fDesired_Freq = fFreq[nFreqIndex];
g_fSamplesPerSin = SAMPLES_PER_SIN;
g_iBufferSampleSize = (AUDIO_IN_BUF_LEN / g_fSamplesPerSin); // convert to int (for rounding)
g_iBufferSampleSize = (g_iBufferSampleSize * (float)(g_fSamplesPerSin));
// generate the sin table
memset((void*)g_lAudioOutputBufferRef, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
for( j = 0; j < (int)g_fSamplesPerSin*2; j++ )
{
g_lAudioOutputBufferRef[j] = (long)(AMPLITUDE * sin( (2.0 * PI * g_fDesired_Freq * ( ((float)(j)) / SAMPLE_RATE_T))));
}
memset((void*)g_lAudioInputBufferL, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
memset((void*)g_lAudioInputBufferR, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
g_lADC_TestChannel = g_cstADC_Names[nIndex].iChannel;
g_lDAC_TestChannel = g_cstDAC_Names[nIndex].iChannel;
// test channel
#ifdef _DEBUG
printf("\nTesting %s + %s at: %fhz\n", g_cstADC_Names[nIndex].pName, g_cstDAC_Names[nIndex].pName, g_fDesired_Freq );
printf("\tleft\n");
#endif
g_iSampleIndex = 0;
g_lSampleCount = 0;
g_ucAudioInEnable = 1;
do{
asm("nop;");
}while( (g_lSampleCount < REQUIRED_SAMPLES) );
g_ucAudioInEnable = 0;
iResult = Test_Channel( (long*)g_lAudioInputBufferL);
if( iResult )
{ // test right channel
#ifdef _DEBUG
printf("\tright\n");
#endif
iResult = Test_Channel( (long*)g_lAudioInputBufferR);
}
if( 0 == iResult )
{
break;
}
}
if( 0 == iResult )
{
break;
}
}
// check each channel individually
for( nIndex = 0; nIndex < 4; nIndex++ )
//for( nIndex = 0; nIndex < 1; nIndex++ )
{
for(nFreqIndex = 0; nFreqIndex < NUM_TEST_FREQUENCIES; nFreqIndex++)
//for(nFreqIndex = 0; nFreqIndex < 1; nFreqIndex++)
{
g_fDesired_Freq = fFreq[nFreqIndex];
g_fSamplesPerSin = SAMPLES_PER_SIN;
g_iBufferSampleSize = (AUDIO_IN_BUF_LEN / g_fSamplesPerSin); // convert to int (for rounding)
g_iBufferSampleSize = (g_iBufferSampleSize * (float)(g_fSamplesPerSin));
// generate the sin table
memset((void*)g_lAudioOutputBufferRef, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
for( j = 0; j < (int)g_fSamplesPerSin*2; j++ )
{
g_lAudioOutputBufferRef[j] = (long)(AMPLITUDE * sin( (2.0 * PI * g_fDesired_Freq * ( ((float)(j)) / SAMPLE_RATE_T))));
}
memset((void*)g_lAudioInputBufferL, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
memset((void*)g_lAudioInputBufferR, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
g_lADC_TestChannel = g_cstADC_Names[nIndex].iChannel;
g_lDAC_TestChannel = g_cstDAC_Names[nIndex+4].iChannel;
// test channel
#ifdef _DEBUG
printf("\nTesting %s + %s at: %fhz\n", g_cstADC_Names[nIndex].pName, g_cstDAC_Names[nIndex+4].pName, g_fDesired_Freq );
printf("\tleft\n");
#endif
g_iSampleIndex = 0;
g_lSampleCount = 0;
g_ucAudioInEnable = 1;
do{
asm("nop;");
}while( (g_lSampleCount < REQUIRED_SAMPLES) );
g_ucAudioInEnable = 0;
iResult = Test_Channel( (long*)g_lAudioInputBufferL);
if( iResult )
{ // test right channel
#ifdef _DEBUG
printf("\tright\n");
#endif
iResult = Test_Channel( (long*)g_lAudioInputBufferR);
}
if( 0 == iResult )
{
break;
}
}
if( 0 == iResult )
{
break;
}
}
// disable DMAs
*pDMA4_CONFIG = 0;
*pDMA3_CONFIG = 0;
// disable Sport1 TX and RX
*pSPORT1_TCR1 = 0;
*pSPORT1_RCR1 = 0;
// turn off interrupts so that the data is stable.
register_handler(ik_ivg9, EX_INT_DEFAULT);
// disable Sport0 RX interrupt
*pSIC_IMASK &= (~0x00000800);
return iResult;
}
//--------------------------------------------------------------------------//
// Function: int TEST_ADAV801(void)
// //
// Description: Perform frequency and amplitude test on ADAV801
//--------------------------------------------------------------------------//
int TEST_ADAV801(void)
{
int i;
int j;
int iResult = 1;
// int nIndex;
int nFreqIndex;
const float fFreq[NUM_TEST_FREQUENCIES] = {440.0, 1000.0, 2000.0, 3000.0, 5000.0, 8000.0, 16000};
InitADAV801();
Init_Sport0();
Init_Sport0_DMA();
Init_Sport0_Interrupts();
Enable_Sport0_DMA();
// check each channel individually
// for( nIndex = 0; nIndex < 4; nIndex++ )
// {
for(nFreqIndex = 0; nFreqIndex < NUM_TEST_FREQUENCIES; nFreqIndex++)
{
g_fDesired_Freq = fFreq[nFreqIndex];
g_fSamplesPerSin = SAMPLES_PER_SIN;
g_iBufferSampleSize = (AUDIO_IN_BUF_LEN / g_fSamplesPerSin); // convert to int (for rounding)
g_iBufferSampleSize = (g_iBufferSampleSize * (float)(g_fSamplesPerSin));
// generate the sin table
memset((void*)g_lAudioOutputBufferRef, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
for( j = 0; j < (int)g_fSamplesPerSin*2; j++ )
{
g_lAudioOutputBufferRef[j] = (long)((AMPLITUDE/0x100) * sin( (2.0 * PI * g_fDesired_Freq * ( ((float)(j)) / SAMPLE_RATE_T))));
}
memset((void*)g_lAudioInputBufferL, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
memset((void*)g_lAudioInputBufferR, 0x00, (sizeof(long) * AUDIO_IN_BUF_LEN) );
// test channel
#ifdef _DEBUG
printf("\nTesting %s at: %fhz\n", "SPDIF RX/TX", g_fDesired_Freq );
printf("\tleft\n");
#endif
g_iSampleIndex = 0;
g_lSampleCount = 0;
g_ucAudioInEnable = 1;
do{
asm("nop;");
}while( (g_lSampleCount < REQUIRED_SAMPLES/200) );
g_ucAudioInEnable = 0;
iResult = Test_Channel( (long*)g_lAudioInputBufferL);
if( iResult )
{ // test right channel
#ifdef _DEBUG
printf("\tright\n");
#endif
iResult = Test_Channel( (long*)g_lAudioInputBufferR);
}
if( 0 == iResult )
{
break;
}
}
// if( 0 == iResult )
// {
// break;
// }
// }
// disable DMAs
*pDMA1_CONFIG = 0;
*pDMA2_CONFIG = 0;
// disable Sport1 TX and RX
*pSPORT0_TCR1 = 0;
*pSPORT0_RCR1 = 0;
// turn off interrupts so that the data is stable.
register_handler(ik_ivg9, EX_INT_DEFAULT);
// disable Sport0 RX interrupt
*pSIC_IMASK &= (~0x00000200);
return iResult;
}
//--------------------------------------------------------------------------//
// Function: Test_Channel //
// //
// Description: Takes a buffer of data and determines if the frequecny
// and amplitude are within acceptable limits
//--------------------------------------------------------------------------//
int Test_Channel(long* psRealIn)
{
int bSuccess = 0;
short nSampleNumber;
short iTempFreq;
short nHighestFreqIndex;
float fSampledFrequency;
// twiddle factors
complex_fract16 w[AUDIO_IN_BUF_LEN];
complex_fract16 out[AUDIO_IN_BUF_LEN];
complex_fract16 t[AUDIO_IN_BUF_LEN];
fract16 in[AUDIO_IN_BUF_LEN];
// create the input sinewave 3000 hz at 48000 sample rate amplitude is 24-bit's max
for( nSampleNumber = 0; nSampleNumber < g_iBufferSampleSize; nSampleNumber++ )
{
in[nSampleNumber] = (psRealIn[nSampleNumber] >> 16 );
}
// generate twiddle factors
twidfftrad2_fr16(w, AUDIO_IN_BUF_LEN);
// perform real fft
rfft_fr16( in, t, out, w, 1, AUDIO_IN_BUF_LEN, 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);
for( nSampleNumber = 1; nSampleNumber < (g_iBufferSampleSize / 2); nSampleNumber++ )
{
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_T / g_iBufferSampleSize);
#ifdef _DEBUG
printf("\t\t-Sampled Freqyency: Min: %fhz Sampled:%fhz Max:%fhz \n", MIN_DESIRED_FREQ, fSampledFrequency, MAX_DESIRED_FREQ );
#endif
// 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 );
#ifdef _DEBUG
printf("\t\t-Sampled Amplitude: Min:%fdb Sampled:%fdb \n", MIN_SIGNAL_STRENGTH, fDB );
#endif
if( fDB < MIN_SIGNAL_STRENGTH )
{
bSuccess = 0;
}
else
{ // passed
bSuccess = 1;
}
}
#ifdef _DEBUG
if( bSuccess )
{
printf("\t\t-PASSED\n");
}
else
{
fprintf(stderr, "\t\t-FAILED\n");
}
#endif
return bSuccess; // test failed
}
#ifdef _STANDALONE_
void main(void)
{
// init the pll
volatile int test=0;
sysreg_write(reg_SYSCFG, 0x32); //Initialize System Configuration Register
*pSIC_IWR = 0x1;
*pPLL_CTL = 0x2C00;
ssync();
idle();
*pFIO_DIR = 0x000B;
*pFIO_FLAG_S = 0x0003;
*pFIO_FLAG_C = 0x0008;
// for now, do the ADAV801 test as a one time test.
if( 0 == TEST_ADAV801() )
{
asm("emuexcpt;");
}
do{
if( 0 == TEST_1938() )
{
asm("emuexcpt;");
}
}while(1);
}
#endif //_STANDALONE_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -