⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmxscaledmatest.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-----------------------------------------------------------------------------
 * Copyright (c) Wolfson Microelectronics plc.  All rights reserved.
 *
 * This software as well as any related documentation is furnished under 
 * license and may only be used or copied in accordance with the terms of the 
 * license. The information in this file is furnished for informational use 
 * only, is subject to change without notice, and should not be construed as 
 * a commitment by Wolfson Microelectronics plc. Wolfson Microelectronics plc
 * assumes no responsibility or liability for any errors or inaccuracies that
 * may appear in this document or any software that may be provided in
 * association with this document. 
 *
 * Except as permitted by such license, no part of this document may be 
 * reproduced, stored in a retrieval system, or transmitted in any form or by 
 * any means without the express written consent of Wolfson Microelectronics plc. 
 *
 * $Id: WMXScaleDMATest.c 2985 2006-04-24 08:55:38Z fb $
 *
 * This file contains XScale routines for testing the DMA functionality for
 * the drivers for the Wolfson chips.
 *
 * Warning:
 *  This driver is specifically written for Wolfson Codecs. It is not a 
 *  general CODEC device driver.
 *
 * -----------------------------------------------------------------------------*/

/*
 * Include files
 */
#include "WMCommon.h"
#include "WMWaveGen.h"
#include "WMACLink.h"
#include "WMPlatformDeviceContext.h"
#include "WMDMAContext.h"
#include "WMPlatform_OS.h"
#include "WMPlatform_Raw.h"
#include "WMAudioDefs.h"
#include "WMVoice.h"
#include "WMAudioPaths.h"
#include "Test/WMTestCommon.h"
#include "Test/WMPlatformTests.h"
#include "Test/WMLinkTests.h"
#include "Test/WMAudioTestHelpers.h"

/*
 * Only build this if we are asked to.
 */
#if WM_AUDIO_STREAM && WM_TESTING

/*
 * Global definitions
 */
#define TEST_SAMPLE_RATE_HIFI   48000
#define TEST_SAMPLE_RATE_MONO   48000
#define TEST_SAMPLE_RATE_VOICE  8000
#define TEST_BUFFER_TIMESTAMPS  200   /* Needed for timing.  This will cover about 4s @ 48kHz */
#define TEST_MILLISECOND_SLOP   5       /* Error bounds for allowable time discrepancy */

/*
 * Define these to TRUE to run the tests forever.
 */
#define CONTINUAL_HIFI          FALSE
#define CONTINUAL_MONO          FALSE
#define CONTINUAL_VOICE         FALSE

/*
 * Define this to TRUE to verify the timing of the DMA.
 * Note: if you're debugging this is probably _not_ a good idea.
 */
#define VERIFY_DMA_TIMING   FALSE

/* Number of descriptors per channel */
#define WMDMA_DESCRIPTORS_PER_CHANNEL	2

/* Number of buffers per channel */
#define WMDMA_BUFFERS_PER_CHANNEL 	WMDMA_DESCRIPTORS_PER_CHANNEL

/* How long to wait (in ms) before giving up in disgust */
#define MAX_PATIENCE        1000

/*
 * Private data
 */
static volatile XLLP_DMAC_DESCRIPTOR_T  *v_pAudioXmitA_Virtual   = NULL; /* VA: Audio transmit buffer A     128 bits (16 byte aligned) */
static volatile XLLP_DMAC_DESCRIPTOR_T  *v_pAudioXmitA_Physical  = NULL; /* PA: Audio transmit buffer A     128 bits (16 byte aligned) */
static volatile XLLP_DMAC_DESCRIPTOR_T  *v_pAudioXmitB_Virtual   = NULL; /* VA: Audio transmit buffer B     128 bits (16 byte aligned) */
static volatile XLLP_DMAC_DESCRIPTOR_T  *v_pAudioXmitB_Physical  = NULL; /* PA: Audio transmit buffer B     128 bits (16 byte aligned) */
WM_AUDIO_STEREO_SAMPLE                  *v_pDMABufXmitA_Virtual  = NULL;
WM_AUDIO_STEREO_SAMPLE                  *v_pDMABufXmitA_Physical = NULL;
WM_AUDIO_STEREO_SAMPLE                  *v_pDMABufXmitB_Virtual  = NULL;
WM_AUDIO_STEREO_SAMPLE                  *v_pDMABufXmitB_Physical = NULL;
static WM_BOOL                          s_Initialised            = FALSE;

/*
 * Function prototypes
 */
void private_InitDMA(  WM_DEVICE_HANDLE hDevice, int channel, int channelId );
void private_CleanupDMA( WM_DEVICE_HANDLE hDevice, int channel, int channelId );
void private_ClearDescriptors();
WM_BOOL private_MapDMAMemory( WM_DEVICE_HANDLE hDevice );
void private_ReleaseDMAMemory();
void private_ClearDMABuffers();

void private_FillDescriptors( WM_DEVICE_HANDLE hDevice, int channel );
static WM_STATUS private_WaitForBuffer( WM_DEVICE_HANDLE hDevice,
                                        unsigned int channel
                                      );

/*-----------------------------------------------------------------------------
 * Function:    WMTestHiFiDACDMADirect
 *
 * Plays a sound directly to the HIFI DAC, using direct control of the
 * DMA buffers.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *
 * Returns:     WM_BOOL
 *      TRUE if it passed, FALSE if it failed in a way it could detect.
 *---------------------------------------------------------------------------*/
WMTEST_START( WMTestHiFiDACDMADirect( WM_DEVICE_HANDLE hDevice ) )
{
    WMSTATUS                        status;
    unsigned int                    repeat;
    unsigned int                    repeats;
    unsigned int                    samplesPerBuffer;
    unsigned int                    startTime, endTime, bufferStartTime;
    unsigned int                    expectedDuration;
    WM_AUDIO_STEREO_SAMPLE          *pNextBuffer;
    int                             channel = WMDMA_STEREO_OUT;
    int                             channelId;
    WM_WAVEGEN_CTX                  wavegenCtxLeft	= WM_START_OF_WAVE;
    WM_WAVEGEN_CTX                  wavegenCtxRight	= WM_START_OF_WAVE;
    const WM_TEST_SOUND             *pTestSound		= WMTestAudio_GetSound();
#if VERIFY_DMA_TIMING
    unsigned int                    timestampArray[TEST_BUFFER_TIMESTAMPS] = {0};
#endif
    WM_XSCALE_DEVICE_CONTEXT        *pDeviceContext =
										(WM_XSCALE_DEVICE_CONTEXT *) hDevice;
    VOLATILE_DMAC_T                 *v_pDmaReg		= 
										pDeviceContext->v_pDmaReg;
#if WM_AC97
    VOLATILE_AC97_T                 *v_pAC97Regs	=
										pDeviceContext->v_pAC97Regs;
#endif
#if WM_I2S
    VOLATILE_I2S_T                 *v_pI2SRegs	=
										pDeviceContext->v_pI2SRegs;
#endif

    /*
     * The following values are put into variables so they can be
     * altered in a debugger.
     */
    int                             loopForever = CONTINUAL_HIFI;
    WM_SAMPLE_RATE                  sampleRate = TEST_SAMPLE_RATE_HIFI;
    unsigned short                  frequency = pTestSound->frequency;
    unsigned short                  amplitude = pTestSound->amplitude;
    unsigned int                    duration = pTestSound->duration;

    /* 
     * Setup the DMA so that it is ready to run.
     */
#if WM_AC97
    if ( WM_IS_AC97( hDevice ) )
    {
        channelId = DMA_CHAN_AC97_STEREO_OUT;
    }
#endif
#if WM_I2S
    if ( WM_IS_I2S( hDevice ) )
    {
        channelId = DMA_CHAN_I2S_STEREO_OUT;
    }
#endif

    WMTEST_BOOLEAN( private_MapDMAMemory( hDevice ) );

    private_FillDescriptors( hDevice, channel );

    /*
     * Work out the number of repeats to get our duration.
     * One buffer contains WMAUDIO_MAX_BUFFER_SIZE bytes.
     */
    samplesPerBuffer = WMAUDIO_MAX_BUFFER_SIZE/sizeof(WM_AUDIO_STEREO_SAMPLE);
    repeats = WM_TEST_REPEATS( duration,
                               sampleRate,
                               samplesPerBuffer
                             );
#if VERIFY_DMA_TIMING
	WM_ASSERT( hDevice, repeats <= TEST_BUFFER_TIMESTAMPS );
#endif

    /*
     * Power up, enable and unmute the HiFi output path.
     */
    WMTEST_CALL( WMAudioPowerUp( hDevice,WM_POWER_AUDIO_PLAYBACK ) );

    WMTEST_CALL( WMAudioEnableOutputPaths( hDevice, WM_STREAM_HIFI_OUT, TRUE ) );

    WMTEST_CALL( WMAudioMuteAllOutputs( hDevice, FALSE ) );

    /*
     * Set the sample rate for the HIFI.
     */
    WMTEST_CALL( WMAudioSetSampleRate( hDevice,
                                       WM_STREAM_HIFI_OUT,
                                       sampleRate
                                     )
               );

    /* Make sure our buffers are cleared */
    private_ClearDMABuffers();

    /* Fill the first buffer and set up our "next" pointer */
    WMGenerateSineWave( v_pDMABufXmitA_Virtual,
                        samplesPerBuffer,
                        sampleRate,
                        frequency,
                        amplitude,
                        WM_WAVEGEN_LEFT,
                        &wavegenCtxLeft
                        );
    WMGenerateSineWave( v_pDMABufXmitA_Virtual,
                        samplesPerBuffer,
                        sampleRate,
                        frequency * 2,
                        amplitude,
                        WM_WAVEGEN_RIGHT,
                        &wavegenCtxRight
                        );
    pNextBuffer = v_pDMABufXmitB_Virtual;
                        
    /* Initialise the DMA */
    private_InitDMA( hDevice, channel, channelId );
    
    /*
     * Clear any interrupts, and any output FIFO errors.
     */
    v_pDmaReg->DCSR[channel] |= DCSR_DMA_INT_MASK;

#if WM_AC97
    if ( WM_IS_AC97( hDevice ) )
    {
        v_pAC97Regs->POSR =  0x10;
    }
#endif
#if WM_I2S
    if ( WM_IS_I2S( hDevice ) )
    {
        v_pI2SRegs->SAICR = XLLP_SAICR_TUR;
    }
#endif


    /*
     * Work out how long it should take:
     * 4 bytes per (stereo) sample = WMAUDIO_MAX_BUFFER_SIZE/4 samples per buffer.
     * repeats buffers.
     * sampleRate samples per second =>
     *      1000/sampleRate milliseconds per sample
     */
    expectedDuration = ( samplesPerBuffer * repeats * 1000 ) /
                                        sampleRate;

    /*
     * Start the DMA on the channel.
     */
    v_pDmaReg->DCSR[channel] |=  DCSR_RUN;          /* set the RUN bit */
    
    do
    {
        /* Get our start time for this loop */
        startTime = GetMillisecondTimestamp( hDevice );
        
        /* Send the buffer the requested number of times */
        for ( repeat = 0; repeat < repeats; repeat++ )
        {
            /* Get the start time for this buffer */
            bufferStartTime = GetMillisecondTimestamp( hDevice );

            /* Fill the next buffer */
            WMGenerateSineWave( pNextBuffer,
                                samplesPerBuffer,
                                sampleRate,
                                frequency,
                                amplitude,
                                WM_WAVEGEN_LEFT,
                                &wavegenCtxLeft
                                );
            WMGenerateSineWave( pNextBuffer,
                                samplesPerBuffer,
                                sampleRate,
                                frequency * 2,
                                amplitude,
                                WM_WAVEGEN_RIGHT,
                                &wavegenCtxRight
                                );

            if ( v_pDMABufXmitA_Virtual == pNextBuffer )
                pNextBuffer = v_pDMABufXmitB_Virtual;
            else
                pNextBuffer = v_pDMABufXmitA_Virtual;                

            /*
             * Wait for the current buffer to finish
             */
            status = private_WaitForBuffer( hDevice, channel );
            if ( WM_ERROR( status ) )
            {
                WM_TRACE( hDevice, ( "Timed out waiting for DMA to finish - skipping test" ) );
                WMTEST_SKIP();
            }

#if VERIFY_DMA_TIMING
            /* Remember how long this buffer took */
            timestampArray[repeat] = GetMillisecondTimestamp( hDevice ) - bufferStartTime;
#endif

            /*
             * Check the DMA status is correct - end interrupt and no errors.
             */
            WMTEST_BOOLEAN( DCSR_ENDINTR == ( v_pDmaReg->DCSR[channel] & DCSR_DMA_INT_MASK ) );
            WMTEST_BOOLEAN( v_pDmaReg->DINT & ( 1U << channel ) );

            /*
             * Clear the DMA interrupts
             */
            v_pDmaReg->DCSR[channel] |= DCSR_DMA_INT_MASK;
        }
        
        /* Now work out how long it all took */
        endTime = GetMillisecondTimestamp( hDevice );
        duration = endTime - startTime;
        WMTEST_TRACE(( "%d buffers of %d samples took %d ms (expected %dms)\n",
                       repeats,
                       samplesPerBuffer,
                       duration,
                       expectedDuration
                    ));
#if VERIFY_DMA_TIMING
        /* Make sure it's reasonably close to what we expect */
        WMTEST_GREATER( duration, expectedDuration - TEST_MILLISECOND_SLOP );
        WMTEST_LESS( duration, expectedDuration + TEST_MILLISECOND_SLOP );
#endif   /* VERIFY_DMA_TIMING */
    }
    while ( loopForever );

    /*
     * Mute, disable and power down the HiFi output path.
     */
    WMTEST_CALL( WMAudioMuteAllOutputs( hDevice, TRUE ) );

    WMTEST_CALL( WMAudioEnableOutputPaths( hDevice, WM_STREAM_HIFI_OUT, FALSE ) );

    WMTEST_CALL( WMAudioPowerDown( hDevice,WM_POWER_AUDIO_PLAYBACK ) );

	/* 
     * Clean up the DMA now that the test is finished.
     */
	private_CleanupDMA( hDevice, channel, channelId );
}
WMTEST_END

/*-----------------------------------------------------------------------------
 * Function:    WMTestMonoDACDMADirect
 *
 * Plays a sound directly to the Mono (AUX) DAC, using direct control of the
 * DMA buffers.
 *
 * Parameters:
 *      hDevice     handle to the device (from WMOpenDevice)
 *
 * Returns:     WM_BOOL
 *      TRUE if it passed, FALSE if it failed in a way it could detect.
 *---------------------------------------------------------------------------*/
WMTEST_START( WMTestMonoDACDMADirect( WM_DEVICE_HANDLE hDevice ) )
{
#if WM_MONODAC
    WMSTATUS                        status;
	unsigned int                    repeat;
	unsigned int                    repeats;
	unsigned int                    samplesPerBuffer;
	unsigned int                    startTime, endTime, bufferStartTime;
	unsigned int                    expectedDuration;
	WM_AUDIO_STEREO_SAMPLE          *pNextBuffer;
	int                             channel         = WMDMA_MONO_OUT;
	int                             channelId       = DMA_CHAN_AC97_MONO_OUT;
	WM_WAVEGEN_CTX                  wavegenCtxLeft  = WM_START_OF_WAVE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -