#include "PeripheralHeaderIncludes.h"
#include "Codec.h"
#include "DSP2833x_Device.h"

//AUDIO DATA TRANSMISSION

// AIC23_DSP_SPI_control.c External Function Prototypes
void spia_init(void);
void aic23_init();
void spia_xmit(int16 spiaTxData);
void InitMcbspGpio(void);
int16 i;
extern void InitSysCtrl();
extern void InitPieCtrl();
void delay_loop();

// Prototype statements for functions found within this file.
void init_dma(void);
void init_mcbspa(void);
interrupt void local_D_INTCH1_ISR(void); // Channel 1 Rx ISR
interrupt void local_D_INTCH2_ISR(void); // Channel 2 Tx ISR

#pragma DATA_SECTION (ping_buffer, "RAMLP1"); // Place ping and pong in DMA RAM L5
#pragma DATA_SECTION (pong_buffer, "RAMLP1");

Uint32 ping_buffer[1024];     // Note that Uint32 is used, not Uint16
Uint32 pong_buffer[1024];

Uint32 ping_buff_offset = (Uint32) &ping_buffer[0];
Uint32 pong_buff_offset = (Uint32) &pong_buffer[0];

Uint16 first_interrupt = 1;   // 1 indicates first interrupt
Uint32 k2 = 0;

void main(void)
{
   EALLOW;

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
    InitSysCtrl();
// Step 2. Initalize GPIO:
// For this example, enable the GPIO PINS for McBSP operation.
   InitMcbspGpio();
   for(k2=0; k2<1024; k2++) { ping_buffer[k2] = 0xDEADDEAD; }
   for(k2=0; k2<1024; k2++) { pong_buffer[k2] = 0xDEADDEAD; }


// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2833x_PieCtrl.c file.
   InitPieCtrl();
   EALLOW;
   DINT;         // Disable interrupts again (for now)

// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Step 4. Initialize the Peripherals

   ping_buff_offset++;    // Start at location 1 (32-bit r/w from loc. 1, then 0)
   pong_buff_offset++;    // Start at location 1 (32-bit r/w from loc. 1, then 0)
   spia_init();       // Initialize
   aic23_init();  // Set up AIC23

   init_dma();            // Initialize the DMA before McBSP, so that DMA is ready to transfer the McBSP data
   init_mcbspa();         // Initalize McBSP-A
   delay_loop();

   EALLOW;
   DmaRegs.CH1.CONTROL.bit.RUN = 1; // Start rx on Channel 1

   PieVectTable.DINTCH1 = &local_D_INTCH1_ISR;
   PieVectTable.DINTCH2 = &local_D_INTCH2_ISR;

   PieCtrlRegs.PIECTRL.bit.ENPIE = 1;  // Enable vector fetching from PIE block
   PieCtrlRegs.PIEACK.all = 0xFFFF;    // Enables PIE to drive a pulse into the CPU

// The interrupt can be asserted in the following interrupt lines

   PieCtrlRegs.PIEIER7.bit.INTx1 = 1;   // Enable INTx.1 of INT7 (DMA CH1)
   PieCtrlRegs.PIEIER7.bit.INTx2 = 1;  // Enable INTx.2 of INT7 (DMA CH2)

   IER |= 0x0040;                   // Enable  INT7
   EINT;                             // Global enable of interrupts
   EDIS;

     while(1) {
     }                  // Code loops here all the time
}

//===========================================================================
// End of main()
//===========================================================================

// INT7.1 -
interrupt void local_D_INTCH1_ISR(void)      // DMA Ch1 - McBSP-A Rx
{
	EALLOW;

	    if(first_interrupt==1) // No processing needs to be done (B/c interrupt occurs
	   {                      // at beginning of DMA transfers to ping buffer - no data received yet)
	       first_interrupt=0; // Turn flag off and exit interrupt
	   } else
	   {
	   // Do whatever processing is needed on the buffered data here
	     // Once that is done, switch to the other buffer
	       DmaRegs.CH2.CONTROL.bit.RUN = 1; // Start tx on CH2 after CH1 has finished ping buffer
	   }
	    // When DMA first starts working on ping buffer, set the shadow registers
	    //   to start at pong buffer next time and vice versa
	    if(DmaRegs.CH1.DST_ADDR_SHADOW == ping_buff_offset)
	   {
	      DmaRegs.CH1.DST_ADDR_SHADOW = pong_buff_offset;
	        DmaRegs.CH1.DST_BEG_ADDR_SHADOW = pong_buff_offset;
	   }

	   else
	   {
	      DmaRegs.CH1.DST_ADDR_SHADOW = ping_buff_offset;
	        DmaRegs.CH1.DST_BEG_ADDR_SHADOW = ping_buff_offset;
	   }
	// To receive more interrupts from this PIE group, acknowledge this interrupt
	    PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
	    EDIS;
}

// INT7.2
interrupt void local_D_INTCH2_ISR(void)      // DMA Ch2 - McBSP-A Tx
{
	EALLOW;
	   // When DMA first starts working on ping buffer, set the shadow registers
	    //   to start at pong buffer next time and vice versa
	      if(DmaRegs.CH2.SRC_ADDR_SHADOW == ping_buff_offset)
	   {
	       DmaRegs.CH2.SRC_ADDR_SHADOW = pong_buff_offset;
	       DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = pong_buff_offset;
	   }
	   else
	   {
	       DmaRegs.CH2.SRC_ADDR_SHADOW = ping_buff_offset;
	       DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = ping_buff_offset;
	   }

	      PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // To receive more interrupts from this PIE group, acknowledge this interrupt
	    EDIS;
}

void init_dma()
{
	EALLOW;
		DmaRegs.DMACTRL.bit.HARDRESET = 1;
		asm("     NOP");

		DmaRegs.PRIORITYCTRL1.bit.CH1PRIORITY = 0;

		DmaRegs.CH1.BURST_SIZE.all = 1;	// 2 16-bit words/burst (1 32-bit word per RRDY) - memory address bumped up by 1 internally
		DmaRegs.CH1.SRC_BURST_STEP = 1;	// DRR2 must be read first & then DRR1. Increment by 1. Hence a value of +1. (This is a 2's C #)
		DmaRegs.CH1.DST_BURST_STEP = -1;	// Copy DRR2 data to address N+1 and DRR1 data to N. Hence -1 (32-bit read= read addr N+1 as MSB, then N as LSB)
		DmaRegs.CH1.TRANSFER_SIZE = 1023;	// Interrupt every 1024 (n+1) bursts. McBSP handles 16-bit data only (DRR2 and DRR1 are 16-bit registers)

		DmaRegs.CH1.SRC_TRANSFER_STEP = -1; // Decrement source address by 1 (from DRR1 back to DRR2) after processing a burst of data
		DmaRegs.CH1.DST_TRANSFER_STEP = 1025; // After copying L-C data, move down to R-C data in a given buffer

		DmaRegs.CH1.SRC_ADDR_SHADOW = (Uint32) &McbspaRegs.DRR2.all;  // First read from DRR2
		DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32) &McbspaRegs.DRR2.all;
		DmaRegs.CH1.DST_ADDR_SHADOW = ping_buff_offset;               // First write to ping_buffer[1]
		DmaRegs.CH1.DST_BEG_ADDR_SHADOW = ping_buff_offset;

		DmaRegs.CH1.DST_WRAP_SIZE = 1;	  // After LEFT(1) and then RIGHT(2), go back to LEFT buffer
		DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF; // Arbitary large value. We'll never hit this.....
		DmaRegs.CH1.DST_WRAP_STEP = 2;      // From starting address, move down 2 16-bit addresses to write nxt 32-bit word

		DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1;		// Clears peripheral interrupt, sync and sycn error flags
		DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1;
		DmaRegs.CH1.CONTROL.bit.ERRCLR = 1;

		DmaRegs.CH1.MODE.bit.CHINTE = 1;			// Channel Interrupt Enable
		DmaRegs.CH1.MODE.bit.CHINTMODE = 0;			// Generates Interrupt at beginning of transfer
		DmaRegs.CH1.MODE.bit.PERINTE = 1;			// Peripheral Interrupt Enable
		DmaRegs.CH1.MODE.bit.PERINTSEL = 15;		// McBSP MREVTA
		DmaRegs.CH1.MODE.bit.CONTINUOUS = 1;		// Continuous mode


		DmaRegs.CH2.BURST_SIZE.all = 1;	// 2 16-bit words/burst (1 32-bit word per XRDY) - value bumped up by 1 internally
		DmaRegs.CH2.SRC_BURST_STEP = -1;	// Copy data at address N+1 to DXR2 first then data at N to DXR1. Hence -1
		DmaRegs.CH2.DST_BURST_STEP = 1;	// DXR2 must be written to first & then DXR1. Increment by 1. Hence a value of +1. (This is a 2's C #)
		DmaRegs.CH2.TRANSFER_SIZE = 1023;	// Interrupt every 1024 (n+1) 16-bit words. McBSP still handles 16-bit data only in registers

		DmaRegs.CH2.SRC_TRANSFER_STEP = 1025; // After copying L-C data, move down to R-C data in a given buffer
		DmaRegs.CH2.DST_TRANSFER_STEP = -1;   // Decrement dest. address by 1 (DXR1 back to DXR2) after processing a burst of data

		DmaRegs.CH2.SRC_ADDR_SHADOW = ping_buff_offset;               // First read from ping_buffer[1]
		DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = ping_buff_offset;
		DmaRegs.CH2.DST_ADDR_SHADOW = (Uint32) &McbspaRegs.DXR2.all;  // First write to DXR2
		DmaRegs.CH2.DST_BEG_ADDR_SHADOW = (Uint32) &McbspaRegs.DXR2.all;

		DmaRegs.CH2.SRC_WRAP_SIZE = 1;	     // After LEFT(1) and then RIGHT(2), go back to LEFT buffer
		DmaRegs.CH2.DST_WRAP_SIZE = 0xFFFF;  	 // Arbitary large value. We'll never hit this.....
		DmaRegs.CH2.SRC_WRAP_STEP = 2;         // From starting address, move down 2 16-bit addresses to read next 32-bit word

		DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1;		// Clears peripheral interrupt, sync and sync error flags
		DmaRegs.CH2.CONTROL.bit.SYNCCLR = 1;
		DmaRegs.CH2.CONTROL.bit.ERRCLR = 1;

		DmaRegs.CH2.MODE.bit.CHINTE = 1;			// Channel Interrupt Enable
		DmaRegs.CH2.MODE.bit.CHINTMODE = 0;			// Generates Interrupt at beginning of transfer
		DmaRegs.CH2.MODE.bit.PERINTE = 1;			// Peripheral Interrupt Enable
		DmaRegs.CH2.MODE.bit.PERINTSEL = 14;		// McBSP MXEVTA
		DmaRegs.CH2.MODE.bit.CONTINUOUS = 1;		// Continuous mode
		EDIS;

		EALLOW;
		DmaRegs.CH1.CONTROL.bit.RUN = 1;			// Starts up Channel 1
		EDIS;
}


void init_mcbspa()
{
	 EALLOW;
	    McbspaRegs.SPCR2.all=0x0000;		// Reset FS generator, sample rate generator & transmitter
		McbspaRegs.SPCR1.all=0x0000;		// Reset Receiver, Right justify word

	    McbspaRegs.SPCR1.bit.RJUST = 2;		// left-justify word in DRR and zero-fill LSBs

	 	McbspaRegs.MFFINT.all=0x0;			// Disable all interrupts

	    McbspaRegs.SPCR1.bit.RINTM = 0;		// Configure McBSP interrupts
		McbspaRegs.SPCR2.bit.XINTM = 0;

	    McbspaRegs.RCR2.all=0x0;			// Single-phase frame, 1 word/frame, No companding	(Receive)
	    McbspaRegs.RCR1.all=0x0;

	    McbspaRegs.XCR2.all=0x0;			// Single-phase frame, 1 word/frame, No companding	(Transmit)
	    McbspaRegs.XCR1.all=0x0;

	    McbspaRegs.RCR2.bit.RWDLEN2 = 5;	// 32-BIT OPERATION
	    McbspaRegs.RCR1.bit.RWDLEN1 = 5;
	    McbspaRegs.XCR2.bit.XWDLEN2 = 5;
	    McbspaRegs.XCR1.bit.XWDLEN1 = 5;

	    McbspaRegs.RCR2.bit.RPHASE = 1;		// Dual-phase frame
		McbspaRegs.RCR2.bit.RFRLEN2 = 0;	// Recv frame length = 1 word in phase2
		McbspaRegs.RCR1.bit.RFRLEN1 = 0;	// Recv frame length = 1 word in phase1

		McbspaRegs.XCR2.bit.XPHASE = 1;		// Dual-phase frame
		McbspaRegs.XCR2.bit.XFRLEN2 = 0;	// Xmit frame length = 1 word in phase2
		McbspaRegs.XCR1.bit.XFRLEN1 = 0;	// Xmit frame length = 1 word in phase1

		McbspaRegs.RCR2.bit.RDATDLY = 1;	// n = n-bit data delay (max 2) CRITICAL PARAMETER !!!
		McbspaRegs.XCR2.bit.XDATDLY = 1;    // If LRP (AIC23) = 0, X/RDATDLY=0, if LRP=1, X/RDATDLY=1


	    McbspaRegs.SRGR2.bit.FPER = 0x0002;	// Does not matter
	    McbspaRegs.SRGR1.all=0x0001;		// Frame Width = 1 CLKG period, CLKGDV must be 1 as slave!!
	                                        // SRG clocked by LSPCLK - SRG clock MUST be at least 2x external data shift clk

	    McbspaRegs.PCR.all=0x0000;			// Frame sync generated externally, CLKX/CLKR driven
	    McbspaRegs.PCR.bit.FSXM = 0;		// FSX is always an i/p signal
		McbspaRegs.PCR.bit.FSRM = 0;		// FSR is always an i/p signal
		McbspaRegs.PCR.bit.SCLKME = 0;

	    McbspaRegs.PCR.bit.FSRP = 0;		// 1-FSRP is active low 0-FSRP is active high
		McbspaRegs.PCR.bit.FSXP = 0;        // 0-FSXP is active low
	    McbspaRegs.PCR.bit.CLKRP  = 1;		// 1-Rcvd data sampled on rising edge of CLKR
		McbspaRegs.PCR.bit.CLKXP  = 0;      // 0- Tx data sampled on falling edge of CLKX
		McbspaRegs.SRGR2.bit.CLKSM = 1;		// LSPCLK is clock source for SRG

		McbspaRegs.PCR.bit.CLKXM = 0;		// 0-MCLKXA is an i/p driven by an external clock
	    McbspaRegs.PCR.bit.CLKRM = 0;		// MCLKRA is an i/p signal

	    McbspaRegs.SPCR2.all |=0x00C0;     	// Frame sync & sample rate generators pulled out of reset

	    delay_loop();

		McbspaRegs.SPCR2.bit.XRST=1;       	// Enable Transmitter
	    McbspaRegs.SPCR1.bit.RRST=1;		// Enable Receiver

	    EDIS;
	    delay_loop();
}

void spia_init()
{
	SpiaRegs.SPICCR.bit.SPISWRESET = 0;		// Hold SPI in reset
	SpiaRegs.SPIFFTX.bit.SPIRST = 0;		// Hold both FIFOs in reset
	SpiaRegs.SPIFFRX.bit.RXFIFORESET = 0;	// Hold RX FIFO in reset

	SpiaRegs.SPICCR.bit.SPICHAR = 15;		// 16 bit char
	SpiaRegs.SPICCR.bit.CLKPOLARITY = 1;	// Output on falling edge
	SpiaRegs.SPICCR.bit.SPILBK = 0;			// No Loopback
	SpiaRegs.SPIBRR = 99;					// Baud rate select

	SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;	// Master mode
	SpiaRegs.SPICTL.bit.CLK_PHASE = 0;		// No Delay
	SpiaRegs.SPICTL.bit.OVERRUNINTENA = 0;	// Disable
	SpiaRegs.SPICTL.bit.TALK = 1;			// Enable TX
	SpiaRegs.SPICTL.bit.SPIINTENA = 1;		// Enable Interrupt Request
    SpiaRegs.SPIPRI.bit.FREE = 0;			// Set so brkpts don't disturb xmission

	SpiaRegs.SPIFFRX.bit.RXFFIL = 1;		// Set flag after 3 bytes rcv'd
	SpiaRegs.SPIFFRX.bit.RXFFINTCLR = 1;	// Clear any spurious Int Flag
	SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1;	// Release RX FIFO from reset
	SpiaRegs.SPIFFTX.bit.SPIRST = 1;		// Release both FIFOs from reset
	SpiaRegs.SPIFFTX.bit.SPIFFENA = 0;		// Disable FIFOs feature
	SpiaRegs.SPICCR.bit.SPISWRESET = 1;		// Release SPI from reset
}

void spia_xmit(int16 spiTxData)
{
	SpiaRegs.SPITXBUF = spiTxData;
	while (SpiaRegs.SPISTS.bit.INT_FLAG != 1) {}	// Wait until character has been transferred
	i = SpiaRegs.SPIRXBUF;				// Clears INT_FLAG
}


void aic23_init()
{
    Uint16 command;
    command = reset();
	spia_xmit (command);
    command = softpowerdown();       // Power down everything except device and clocks
	spia_xmit (command);
    command = linput_volctl(LIV);    // Unmute left line input and maintain default volume
	spia_xmit (command);
	command = rinput_volctl(RIV);    // Unmute right line input and maintain default volume
	spia_xmit (command);
	command = lhp_volctl(LHV);       // Left headphone volume control
	spia_xmit (command);
	command = rhp_volctl(RHV);       // Right headphone volume control
	spia_xmit (command);
#if MIC
    command = aaudpath();
#else
	command = nomicaaudpath();      // Turn on DAC, mute mic
#endif
	spia_xmit (command);
	command = digaudiopath();       // Disable DAC mute
	spia_xmit (command);
	command = DSPdigaudinterface();    // AIC23 master mode, DSP mode,32-bit data, LRP=1 to match with XDATADLY=1
	spia_xmit (command);
	command =USBsampleratecontrol (SRUSB44_1); // 12 MHz USB clock - 44.1 MHz sample rate in USB mode
	spia_xmit (command);
	command = digact();             // Activate digital interface
	spia_xmit (command);
#if MIC
    command = fullpowerup();
#else
	command = nomicpowerup();      // Turn everything on except Mic.
#endif
    spia_xmit (command);
}


void InitMcbspGpio(void)
{
EALLOW;
	   GpioCtrlRegs.GPAMUX1.all = 0;      // GPIO15 ... GPIO0 = General Puropse I/O
	   GpioCtrlRegs.GPAMUX2.all = 0;      // GPIO31 ... GPIO16 = General Purpose I/O
	   GpioCtrlRegs.GPBMUX1.all = 0;      // GPIO47 ... GPIO32 = General Purpose I/O
	   GpioCtrlRegs.GPBMUX2.all = 0;      // GPIO63 ... GPIO48 = General Purpose I/O
	   GpioCtrlRegs.GPCMUX1.all = 0;      // GPIO79 ... GPIO64 = General Purpose I/O
	   GpioCtrlRegs.GPCMUX2.all = 0;      // GPIO87 ... GPIO80 = General Purpose I/O

	   GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1;   // SPI-A SPISIMO for AIC23 "SDIN"
	   GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1;   // SPI-A SPICLK  for AIC23 "SCLK"
	   GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1;   // SPI-A SPISTE  for AIC23 "/CS"

	   GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 2;   // McBSP-A MDXA  for AIC23 "DIN"
	   GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 3;   // Asynch only
	   GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 2;   // McBSP-A MDRA  for AIC23 "DOUT"
	   GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 3;   // Asynch only
	   GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 2;   // McBSP-A MCLKXA for AIC23 "BCLK"
	   GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 3;   // Asynch only
	   GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 2;   // McBSP-A MFSXA for AIC23 "LRCIN"
	   GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 3;   // Asynch only
	   GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 1;   // McBSP-A MCLKRA for AIC23 "BCLK"
	   GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 1;   // McBSP-A MFSRA for AIC23 "LRCOUT"

	   GpioCtrlRegs.GPADIR.all = 0;
	   GpioCtrlRegs.GPADIR.bit.GPIO9 = 1;      // peripheral explorer: LED LD1 at GPIO9
	   GpioCtrlRegs.GPADIR.bit.GPIO11 = 1;      // peripheral explorer: LED LD2 at GPIO11

	   GpioCtrlRegs.GPBDIR.all = 0;         // GPIO63-32 as inputs
	   GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;      // peripheral explorer: LED LD3 at GPIO34
	   GpioCtrlRegs.GPBDIR.bit.GPIO49 = 1;    // peripheral explorer: LED LD4 at GPIO49

	   GpioCtrlRegs.GPCDIR.all = 0;         // GPIO87-64 as inputs
	   EDIS;
}

void delay_loop(void)
{
    volatile int      j;  //USO DE VOLATILE¿?
    for (j = 0; j < 8; j++) {} //delay in McBsp init. must be at least 2 SRG cycles
}
//===========================================================================
// End of file.
//===========================================================================



