/*
 *  Copyright 2000 by Texas Instruments Incorporated.
 *  All rights reserved. Property of Texas Instruments Incorporated.
 *  Restricted rights to use, duplicate or disclose this code are
 *  granted through contract.
 *  U.S. Patent Nos. 5,283,900  5,392,448
 */
/* "@(#) DSP/BIOS 4.00 09-15-00 (barracuda-e16)" */
/*
 *  ======== audio.c ========
 */

#include <std.h>
#include <stdio.h>

#include <pip.h>    
#include <swi.h>
#include <log.h>
#include <trc.h>
#include <math.h>
#include "ComplexMath.h"
#include "Math2.h"
#include "BeauregardFFT.h"
#include "permute.h"

/* The following external objects are defined in the config file audio.cdb */
extern far LOG_Obj trace;           /* application printf() log */ 

static Void error(Void);        /* called if an error occurs */
extern Void DSS_init(Void);     /* Initialize codec and serial port */
extern Void AUDIO_load(Int);    /* */
Void load(Int );                /* simulate CPU load */


Int loadVal = 0;


/*
 *  ======== main ========
 */
Void main()
{

    DSS_init();
    LOG_printf(&trace, "Audio example started!!\n");
    
    /* fall into BIOS idle loop */
    return;                 
}

/*
 *  ======== audio ========
 */
Complex	srcComplex	[512];
Complex	dstComplex	[512];

int trips=0;
Void audio(PIP_Obj *in, PIP_Obj *out)
{
    Uns *src, *dst;
    Int size;
    Int	i;	

    if (PIP_getReaderNumFrames(in) == 0 || PIP_getWriterNumFrames(out) == 0)
    {
        error();
    }

    /* get input data and allocate output buffer */
    PIP_get(in);
    PIP_alloc(out);

    /* copy input data to output buffer */
    src = PIP_getReaderAddr(in);
    dst = PIP_getWriterAddr(out);
    
    size = PIP_getReaderSize(in);
    PIP_setWriterSize(out,size);
 
    for(i = 0; i < size; i++)
    {
    	srcComplex[i].Re = REAL(src[i]);
    	srcComplex[i].Im = 0.0;
    }  

	BeauregardFFT(srcComplex, 9, FORWARD); /* keep logN updated!!! */
	
	srcComplex[0].Re = 0.0; /* DC component will hum if shifted */
	srcComplex[0].Im = 0.0;
	
	for(i = 0; i < size/2; i++)
	{
		dstComplex[unBitReversed[i]].Re = 0.0;
		dstComplex[unBitReversed[i]].Im = 0.0;
		
		dstComplex[unBitReversed[size/2 + i]] =     /* shift AND condense */
		CAvg
		(
			srcComplex[unBitReversed[2*i    ]],
			srcComplex[unBitReversed[2*i + 1]]
		);
	}
	
	BeauregardFFT(dstComplex, 9, INVERSE); /* keep logN updated!!! */
	
    for(i = 0; i < size; i++)
    {
    	dst[i] = (Uns)(dstComplex[i].Re);
    }

    /* output copied data and free input buffer */
    PIP_put(out);
    PIP_free(in);
}


/*
 *  ======== error ========
 */
static Void error(Void)
{
    LOG_printf(&trace, "Error: audio signal falsely triggered!");
    
    for (;;) {
        ;       /* loop for ever */
    }
}


/*
 *  ======== load ========
 */
Void load(Int prd_ms)
{
    static int oldLoad = 0;

    /* display confirmation of load changes */
    if (oldLoad != loadVal ) {
        oldLoad = loadVal;
        LOG_printf(&trace,
           "load: new load = %d000 instructions every %d ms", loadVal, prd_ms);
    }
    
    if (loadVal) {
        AUDIO_load(loadVal);
    }   
}

/*
 *  ======== step ========
 */
Void step(void)
{
    static Int direction = 1;

    if (loadVal > 800) {
        direction = -1;
    }
    if (loadVal <= 0) {
        direction = 1;
    }

    loadVal = loadVal + (100 * direction);
}

#ifdef CODE_POOL
	Real	min=HUGE, max=-min;	
	
	max = MAX(srcComplex[i].Re, max);
	min = MIN(srcComplex[i].Re, min);
		
    if(!(trips%100))
	{
		for(i = 0; i < size; i++)
	    {
			LOG_printf(&trace, "%6.4f", (srcComplex[i].Re - min)/(max - min));
	    }
		LOG_printf(&trace, "\n\n");
	}
	trips++;
	
	for(i = 0; i < size/2; i++)
	{
		dstComplex[unBitReversed[         i]].Re = 0.0;
		dstComplex[unBitReversed[         i]].Im = 0.0;
		
		dstComplex[unBitReversed[size/2 + i]] =
		srcComplex[unBitReversed[         i]];
	}

	
	for(i = 0; i < size/2; i++)
    {
    	dst[i] = (src[2*i] + src[2*i+1])/2;
    	dst[size/2 + i] = dst[i];
    }
#endif
