#include <BeagleRT.h> 
#include <NetworkSend.h>
#include <ReceiveAudioThread.h>
#include <ClockSynchronizer.h>
#include <cmath>

float gPhase1, gPhase2;
float gFrequency1, gFrequency2;
float gInverseSampleRate;

//Scope scope(2);   //create a scope object with 2 channels
NetworkSend networkSend;

// initialise_render() is called once before the audio rendering starts.
// Use it to perform any initialisation and allocation which is dependent
// on the period size or sample rate.
//
// userData holds an opaque pointer to a data structure that was passed
// in from the call to initAudio().
//
// Return true on success; returning false halts the program.
ReceiveAudioThread receiveAudio0;
//ReceiveAudioThread receiveAudio1;
ClockSynchronizer clockSynchronizer;
extern I2c_Codec* gAudioCodec;
bool setup(BeagleRTContext *context, void *userData)
{
	receiveAudio0.init(10000, context->audioFrames, 0);
//	receiveAudio1.init(10000, context->audioFrames, 1);

//	scope.setup();  //call this once in setup to initialise the scope
//	scope.setPort(0, 9999);
//	scope.setPort(1, 10000);
	networkSend.setup(context->audioSampleRate, context->audioFrames, 0, 9999, "192.168.7.1");
	clockSynchronizer.setup();
	gInverseSampleRate = 1.0/context->audioSampleRate;
	
	gPhase1 = 0.0;
	gPhase2 = 0.0;
	
	gFrequency1 = 200.0;
	gFrequency2 = 201.0;

	return true; 
}

// render() is called regularly at the highest priority by the audio engine.
// Input and output are given from the audio hardware and the other
// ADCs and DACs (if available). If only audio is available, numMatrixFrames
// will be 0.

void render(BeagleRTContext *context, void *userData)
{
	static int count=0;
//	if((count&262143)==0){
//	static int nextCall=160000;
	if( ((count&(16384-1))==0 /*&& count>200000*/)){
//		rt_printf("b %d\n", count);
		clockSynchronizer.update(networkSend.getTimestamp(), receiveAudio0.getTimestamp(), receiveAudio0.getLastTime());
//		nextCall=count+100000;
//		rt_printf("a %d\n", count);
	}
//	if(count == nextCall){
//		clockSynchronizer.update(networkSend.getTimestamp(), receiveAudio0.getTimestamp(), receiveAudio0.getLastTime());
//	}
	if(count==0){
		gAudioCodec->setAudioSamplingRate(44080);
		printf("startHread\n");
		ReceiveAudioThread::startThread();
	}
	for(unsigned int n = 0; n < context->audioFrames; n++) {
	    
		float chn0 = sinf(gPhase1);
//		float chn1 = sinf(gPhase2);

    //  float chn2 = context->audioIn[n*2 + 0];
    //  float chn3 = context->audioIn[n*2 + 1];

    //  float chn4 = context->analogIn[(int)n/2*8 + 0];
    //  float chn5 = context->analogIn[(int)n/2*8 + 1];
//		networkSend.log(context->audioIn[n]);
		networkSend.log(chn0);
//		scope.log(0, chn0);
//		scope.log(1, chn1);
		//  scope.log(2, chn2);
		//  scope.log(3, chn3);
		//  scope.log(4, chn4);
		//  scope.log(5, chn5);
	    
//	    scope.log(chn1, chn2, chn3, chn4, chn5, chn6);
	    //call this once every audio frame
	    //takes six or fewer floats as parameters
	    //first parameter becomes channel 1 etc
	    //to view, click the 'oscilloscope' button on the toolbar while BeagleRT is NOT running
	    //then click the big red button on the toolbar on this page
	    
	    gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate * ((count&65535)/65535.0+1);
			gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
		if(gPhase1 > 2.0 * M_PI)
			gPhase1 -= 2.0 * M_PI;
		if(gPhase2 > 2.0 * M_PI)
			gPhase2 -= 2.0 * M_PI;
		count++;
	}
	if(count>0){
		float samplingRateRatio=1;
		int channelsInDestinationBuffer=2;
		int channelToWriteTo=0;
		int length=receiveAudio0.getSamplesSrc(context->audioOut, context->audioFrames,
				samplingRateRatio, channelsInDestinationBuffer, channelToWriteTo);
		if((unsigned int)length!=context->audioFrames){
			rt_printf("Length mismatch: %d\n", length);
		}
//		int readPointer1=receiveAudio1.getSamplesSrc(context->audioOut, context->audioFrames, 1, 2, 1);
	}
	for(unsigned int n=0; n<context->audioFrames; n++){
		context->audioOut[n*2+1]=context->audioOut[n*2];
	}
}

// cleanup_render() is called once at the end, after the audio has stopped.
// Release any resources that were allocated in initialise_render().

void cleanup(BeagleRTContext *context, void *userData)
{
    
}
