#include "h/dac.h"
#include "h/p33FJ64GP802.h"
#include "h/g711.h"
#include "h/adc.h"

__attribute__((far)) short dataBuffer[DAC_BUFFER_SIZE];
volatile unsigned int 	dacDataPlay;               // =0 when paused, =1 when playing
volatile unsigned int 	dacDataPlayReq;			   // =0 to request stop
volatile unsigned int 	dacDataReady;              // =0 when data is not ready to be played =1 when data is in buffer ready to be played
volatile unsigned int 	dacDataReadyPtr;           // data ping pong pointer
volatile unsigned int 	dacDataBufferSample;       // sample pointer
volatile int 		 	dacVolume;
volatile int 		 	daciVolume;
volatile long		 	dacAmplitude;
volatile unsigned char 	dacVolumeLock;
volatile unsigned int	dacTemp;
volatile unsigned int 	dacTempR;
volatile unsigned int 	dacCh;

void initDAC(void)
{
	DAC1CONbits.DACEN=0;		// disable module
	DAC1STATbits.ROEN = 1; 		// Right Channel DAC Output Enabled  
	DAC1STATbits.LOEN = 1; 		// Left Channel DAC Output Enabled 
	DAC1STATbits.RITYPE = 1; 	// Right Channel Interrupt if FIFO is empty
	DAC1STATbits.LITYPE = 1; 	// Left Channel Interrupt if FIFO is empty 
	DAC1CONbits.AMPON = 0; 		// Amplifier Disabled During Sleep and Idle Modes 
	ACLKCON=0x0700;				// choose Output of PLLCLK (around 80Mhz) divided by 2 as the DAC clock input 
	DAC1CONbits.DACFDIV = 13;	// 14: 22000 19: 16000 samples per second 38: 80000 samples per second 36: 8.7kHz 28: 11000
	DAC1CONbits.FORM = 1; 		// 0: Data Format is Unsigned 1: signed 
	DAC1DFLT = 0x0000; 			// Default value 
	IFS4bits.DAC1RIF = 0; 		// Clear Right Channel Interrupt Flag 
	IFS4bits.DAC1LIF = 0;		// Clear Left Channel Interrupt Flag 
	IEC4bits.DAC1RIE = 1; 		// Right Channel Interrupt Enabled 
	IEC4bits.DAC1LIE = 1; 		// Left Channel Interrupt Enabled 
	dacDataPlay=0;
	dacDataPlayReq=0;
	dacDataReady=0;
	dacDataReadyPtr=0;
	dacVolume=DAC_FULL_VOLUME;
	daciVolume=DAC_FULL_VOLUME;
	dacVolumeLock=0;
	dacDataBufferSample=0;
	DAC1CONbits.DACEN = 1; 		// DAC1 Module Enabled 
}

void startPlay(unsigned int dacDivider, int channels)
{
	DAC1CONbits.DACFDIV=dacDivider;
	IFS4bits.DAC1RIF = 0; 		// Clear Right Channel Interrupt Flag 
	IFS4bits.DAC1LIF = 0;		// Clear Left Channel Interrupt Flag 
	DAC1STATbits.ROEN = 1; 		// Right Channel DAC Output Enabled  
	DAC1STATbits.LOEN = 1; 		// Left Channel DAC Output Enabled 
	dacDataReady=0;
	dacDataReadyPtr=DAC_HALF_BUFFER_SIZE;
	dacDataBufferSample=0;
	if(channels==1)
		{
		dacCh=1;
		}
		else 
		{
		dacCh=2;	
		}
	dacDataPlayReq=1;
	dacDataPlay=1;
}

void continuePlay(void)
{
	IFS4bits.DAC1RIF = 0; 		// Clear Right Channel Interrupt Flag 
	IFS4bits.DAC1LIF = 0;		// Clear Left Channel Interrupt Flag 
	DAC1STATbits.ROEN = 1; 		// Right Channel DAC Output Enabled  
	DAC1STATbits.LOEN = 1; 		// Left Channel DAC Output Enabled 
	dacDataPlayReq=1;
	dacDataPlay=1;
}

void endPlay(void)
{
	if(dacDataPlay)
	{
	dacDataPlayReq=0;
	dacDataPlay=1;
	while(dacDataPlay==1)
	{
	asm("nop");
	}
	IFS4bits.DAC1RIF = 0; 		// Clear Right Channel Interrupt Flag 
	IFS4bits.DAC1LIF = 0;		// Clear Left Channel Interrupt Flag 
//	DAC1STATbits.ROEN = 0; 		// Right Channel DAC Output Enabled  
//	DAC1STATbits.LOEN = 0; 		// Left Channel DAC Output Enabled 
	dacDataReady=0;
	dacDataReadyPtr=0;
	dacVolumeLock=0;
	dacDataBufferSample=0;
	}
}

void __attribute__((interrupt, no_auto_psv))_DAC1RInterrupt(void)
{
    IFS4bits.DAC1RIF = 0;  	/* Clear Left Channel Interrupt Flag */ 
    if(dacDataPlay)
    {
		DAC1RDAT=dacTempR;
	} else
	{
		DAC1RDAT=0x0000;
	}
}

void __attribute__((interrupt, no_auto_psv))_DAC1LInterrupt(void)
{
	IFS4bits.DAC1LIF = 0;  	/* Clear Left Channel Interrupt Flag */
    if(dacDataPlay)
    {
        if((dacDataBufferSample==0)||(dacDataBufferSample==DAC_HALF_BUFFER_SIZE))
        {
           	if(dacDataReady)
            {
				if(dacDataBufferSample==0)dacDataReadyPtr=DAC_HALF_BUFFER_SIZE; else dacDataReadyPtr=0;
                dacDataReady=0;
            } 
        	if(dacDataPlayReq==0)dacDataPlay=0;
		} 
		if(dacVolumeLock==0)
		{ 
			daciVolume=dacVolume;
		}
		dacAmplitude=__builtin_mulss(dataBuffer[dacDataBufferSample], daciVolume);
		dacTemp=__builtin_divsd(dacAmplitude, DAC_FULL_VOLUME);
		if(dacCh==1)
		{
			dacTempR=dacTemp; 
			if(dacDataBufferSample < (DAC_BUFFER_SIZE-1))dacDataBufferSample++; else dacDataBufferSample=0; 
		}
		else
		{
		dacAmplitude=__builtin_mulss(dataBuffer[dacDataBufferSample+1], daciVolume);
		dacTempR=__builtin_divsd(dacAmplitude, DAC_FULL_VOLUME);
		if(dacDataBufferSample<(DAC_BUFFER_SIZE-2))dacDataBufferSample+=2; else dacDataBufferSample=0;
		}
		DAC1LDAT=dacTemp;
    } else
	if(adcDataRecord && adcLoopBack)
	{
	dacTemp=adcResult[0];
	DAC1LDAT=dacTemp;
	}
	else
	{
	DAC1LDAT=0x0000;
	}
 	
}
