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

📄 amf_delayntapnoutoffchip_262ezkit.c

📁 ADI SHARC DSP 音频算法标准模块库
💻 C
字号:

// Copyright(c) 2005 Analog Devices, Inc. All Rights Reserved. ADI Confidential.

#include "AMF_DelayNTapNOutOffChip_262EzKit.h"

/** Read a named integer port. */
#define RDPORT(name)	(*(const int*)(name))

/** Write a named integer port. */
#define WRPORT(name)	(*(volatile int*)(name))

#define PPDMA_READING 0
#define PPDMA_WRITING 1

#define EXT_MEMORY_WIDTH 8
#define EXT_DECODER_MASK 0xFFE00000
#define EXT_ADDRESS_MASK 0x001FFFFF

/*** external symbol address fixup ***/
#define EXTERNAL_ADDRESS(x) ((void *)(((unsigned int)x & EXT_DECODER_MASK) |\
    (((unsigned int)x & EXT_ADDRESS_MASK)*(32/EXT_MEMORY_WIDTH))))

#define EXT_FLOAT_WORDS (32/EXT_MEMORY_WIDTH)
    
#pragma optimize_off
 void waitForPPDMA(void)
{
	asm("nop; nop;"); // wait 2 cycles before checking PPCTL, due to it's latency
	while (RDPORT(PPCTL) & PPDS) {};
}

 inline startPPDMA(void)
{
	WRPORT(PPCTL) |= (PPDEN|PPEN);
}

//#pragma optimize_for_space
#pragma optimize_off
 void setupDMATransfer(int direction, float *internalPointer, float *externalPointer, int internalWordCount)
{
//	WRPORT(PPCTL) =  PPBHC | PPDUR4 | (direction == PPDMA_WRITING ? PPTRAN : 0); 
	WRPORT(PPCTL) =  PPDUR4 | (direction == PPDMA_WRITING ? PPTRAN : 0); 
	WRPORT(IIPP) = (int)internalPointer; // internal buffer start
	WRPORT(IMPP) = 1; // internal address modifier
	WRPORT(ICPP) = internalWordCount; // internal word count
	WRPORT(EIPP) = (int)externalPointer; // external buffer start
	WRPORT(EMPP) = 1; // external address modifier
	WRPORT(ECPP) = internalWordCount*EXT_FLOAT_WORDS; // external word count
}

void AMF_DelayNTapNOutOffChip_262EzKit_Render(AMF_DelayNTapNOutOffChip_262EzKit * restrict instance,float * restrict * buffers,int tickSize);

#if 1

/******************************************
 * Algorithm:
 *
 * Restrictions due to this algorithm:
 * - i/o pointer aliasing not allowed. This is because it reads-before-writes
 * - this is a read-before-write method which reads/writes a whole tick
 *   at a time, so the minimum delay of this module is equal to the
 *   tick size.  Of course, delays going all they way down to zero are
 *   probably valid to do on-chip anyways.
 *
 * *****************************************/
//#pragma optimize_for_space
#pragma optimize_off
SEG_MOD_FAST_CODE  void AMF_DelayNTapNOutOffChip_262EzKit_Render(AMF_DelayNTapNOutOffChip_262EzKit * restrict instance,float * restrict * buffers,int tickSize) {
    int delayBufferLength = instance->delayBufferLength;		// delay buffer length in samples
    int *taps = instance->taps;
    float *delayBuffer = EXTERNAL_ADDRESS(instance->delayBuffer);		// delay buffer
   	float *delayWritePtr = instance->delayWritePtr;
    float *delayReadPtr;
    int i,curTap;
    float tmp;
    float *in = buffers[0]; 
    float *out;
    //float *scr = buffers[2];
	float *endPtr;
	int firstCount;
	int secondCount;
    int initializedMemoryCount;
    int numTaps = instance->numTaps;

    endPtr = delayBuffer + EXT_FLOAT_WORDS * delayBufferLength; // the next word beyond end of buffer
    
	// handle "orphan write pointer"
	if (delayWritePtr >= endPtr || delayWritePtr < delayBuffer)
        delayWritePtr = delayBuffer;
	
	// wait for any running transfer to finish
    // I think this is not needed, if we assume that all PP access at user level disables interrupts.
    // This is true for the VA framework platforms.
	waitForPPDMA(); // Not needed?? FIXME

	///////////////////////////////// transfer from external buffer	
	
    initializedMemoryCount = delayBufferLength-instance->counter;

    for (curTap = 0; curTap < numTaps; curTap++) {
            out = buffers[1+curTap]; // + 1 because first one is input 
            if (initializedMemoryCount < taps[curTap]) {
                // Handle uninitialized external memory.
                // write out zeros for first time around
                for (i=0; i<tickSize; i++)
                    out[i] = 0.0;
            } else
            {
                delayReadPtr = delayWritePtr - EXT_FLOAT_WORDS*taps[curTap];
                if (delayReadPtr < delayBuffer)
                    delayReadPtr += delayBufferLength*EXT_FLOAT_WORDS;
                // if the "read pointer" will wrap around the buffer this tick, do a split read
                if (delayReadPtr + EXT_FLOAT_WORDS*(tickSize - 1) >= endPtr)
                {
                    // split transfer
                    firstCount = ((int)endPtr - (int)delayReadPtr)/EXT_FLOAT_WORDS; // internal word count
                    secondCount = tickSize - firstCount;
                    
                    // first transfer
                    setupDMATransfer(PPDMA_READING, out, delayReadPtr, firstCount);
                    startPPDMA();
                    waitForPPDMA();
			
                    // second transfer
                    setupDMATransfer(PPDMA_READING, out+firstCount, delayBuffer, secondCount);
                    startPPDMA();
                } else
                {
                    // single transfer
                    setupDMATransfer(PPDMA_READING, out, delayReadPtr, tickSize);
                    startPPDMA();
                }
                
                // wait for the transfer to finish...
                waitForPPDMA();
            }
    }

//	if (instance->counter > tickSize)
//		instance->counter -= tickSize; // delete if code works
		
	if (instance->counter > 0)
		instance->counter -= tickSize;
		
	// NOTE!!!!!!!!!!!!!!! since this delay doesn't interpret the data
	//   (it just copies it around) there is no need to worry about
	//   the right endian-ness on the reading and writing (which could be
	//   an issue since the transfers are only 8 bits at a time).
	//   HOWEVER, any module based on this code that does use that data
	//   in any way other than copying it directly to/from a buffer may
	//   need to do something about the ordering.
	// Note that copying to and from a scratch buffer shouldn't need any endian-ness handling

	
	///////////////////////////////// do the delay copies
	/*
	for (i=0; i<tickSize; i++) {
		tmp = scr[i];	// this ordering is so that we don't write out[i] before reading in[i], so that we can allow aliasing
		scr[i] = in[i];
 		out[i] = tmp;
    }    
	*/

	///////////////////////////////// transfer back to external buffer

    if (delayWritePtr + EXT_FLOAT_WORDS*(tickSize - 1) >= endPtr)
	{   // split transfer
		// first transfer

        firstCount = ((int)endPtr - (int)delayWritePtr)/EXT_FLOAT_WORDS; // internal word count
        secondCount = tickSize - firstCount;
		setupDMATransfer(PPDMA_WRITING, in, delayWritePtr, firstCount);
		startPPDMA();
		waitForPPDMA();

		// wait for it to "really" finish
        // DAJ - What is this?? FIXME
		asm("nop; nop; nop; nop; nop; nop; nop; nop;"); 
		asm("nop; nop; nop; nop; nop; nop;"); 
		
		// second transfer
		setupDMATransfer(PPDMA_WRITING, in+firstCount, delayBuffer, secondCount);
		startPPDMA();

   		instance->delayWritePtr = delayBuffer + EXT_FLOAT_WORDS*secondCount;
	} else
	{
		// single transfer
		setupDMATransfer(PPDMA_WRITING, in, delayWritePtr, tickSize);
		startPPDMA();

  		instance->delayWritePtr = delayWritePtr + EXT_FLOAT_WORDS*tickSize;
	}

	// NOTE: if we can make sure that any other code that wants to use the
	// parallel port will wait for any existing transfer to finish, then
	// we would not have to wait here, and possibly overlap the transfer 
	// with whatever processing happens next
	
	// wait for the transfer to finish...
	waitForPPDMA();
}
#endif



SEG_MOD_SLOW_CONST const AMF_ModuleClass AMFClassDelayNTapNOutOffChip_262EzKit = {
    
    /** Flags. This is not used, and the member should probably be removed. */
    AMFModuleClassFlag_VARIABLE_PIN_COUNT,

	/** Reference to render function. */
	(AMF_RenderFunction)AMF_DelayNTapNOutOffChip_262EzKit_Render,  // render function 

    /* Default bypass */
	(void *)0,
};


⌨️ 快捷键说明

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