/***************************************************************************
* Company: Microsemi Corporation
*
* File: main.c
* File history:
*      Revision: 0.0 Date: November 4, 2011
*
* Description:
*
* This application is Multichannel_FFT.
* to print the values on HyperTerminal comment "#define continuous".
* It uses PDMA
* Author: Sathish Kumar Donthu
*         sathish.donthu@microsemi.com
*         Corporate Applications Engineering
*
***************************************************************************/

/**************************************************************************/
/* Standard Includes */
/**************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/**************************************************************************/
/* Firmware Includes */
/**************************************************************************/

//#define continuous 		//to print the values on HyperTerminal comment the line.

#include "a2fxxxm3.h"
#include "mss_gpio.h"
#include "mss_pdma.h"
#include "mss_ace.h"
#include "mss_uart.h"

/**************************************************************************/
/* Preprocessor Macros*/
/**************************************************************************/

#define fabric_address 0x40050000
#define NUM_SAMPLES 512
#define NUM_CHANNELS 6

/**************************************************************************/
/* Function Prototype*/
/**************************************************************************/

void init_system();

/**************************************************************************/
/* Global variable to store the digital signal samples */
/**************************************************************************/
int8_t half,flag,interrupt;
int lut[NUM_CHANNELS][2*NUM_SAMPLES];
volatile uint32_t rdata[NUM_CHANNELS][NUM_SAMPLES];
void  CALL_FFT(int *);
void Read_FFT();
/**************************************************************************/
/* Function to initialization all necessary hardware components for this*/
/* demo*/
/**************************************************************************/
void GPIO1_IRQHandler( void )
   {
       Read_FFT();
       interrupt++;
   }

void init_system()
{
   /* Initialize the GPIO */
   MSS_GPIO_init();
   PDMA_init();
   PDMA_configure
       (
          PDMA_CHANNEL_0,
          PDMA_MEM_TO_MEM,
          PDMA_LOW_PRIORITY | PDMA_WORD_TRANSFER | PDMA_INC_SRC_FOUR_BYTES,
          PDMA_DEFAULT_WRITE_ADJ
       );
   PDMA_configure
       (
          PDMA_CHANNEL_1,
          PDMA_MEM_TO_MEM,
          PDMA_LOW_PRIORITY | PDMA_WORD_TRANSFER |PDMA_NO_INC |PDMA_INC_DEST_FOUR_BYTES,
          PDMA_DEFAULT_WRITE_ADJ
       );

   ACE_init( );

   /* Configuration of GPIO's */
      MSS_GPIO_config( MSS_GPIO_0, MSS_GPIO_INPUT_MODE);
      MSS_GPIO_config( MSS_GPIO_1, MSS_GPIO_INPUT_MODE);
      MSS_GPIO_config( MSS_GPIO_2, MSS_GPIO_INPUT_MODE);
      MSS_GPIO_config( MSS_GPIO_3, MSS_GPIO_INPUT_MODE);
      MSS_GPIO_enable_irq   (  MSS_GPIO_1  );

}

/**************************************************************************/
/* Function to call FFT*/
/**************************************************************************/

void CALL_FFT(int *val)
{
    uint32_t gpio_inputs;
    volatile uint32_t j;

    gpio_inputs = MSS_GPIO_get_inputs();
    for(;;)
      {
      /* Below statement test that FFT is Ready to accept In Put and output FIFO empty*/
          if((gpio_inputs & 0x0000000b) == 9)
          {
              break;
          }
         gpio_inputs = MSS_GPIO_get_inputs();
      }
    PDMA_start
    (
       PDMA_CHANNEL_0,
       (uint32_t)val,
       (uint32_t)fabric_address,
       NUM_SAMPLES
    );

}


void Read_FFT()
 {

	int i,j;
	int16_t rdata1;
	volatile uint32_t status_pdma = 0;
    PDMA_start
    (
       PDMA_CHANNEL_1,
       (uint32_t)fabric_address,
       (uint32_t)&rdata[flag],
       NUM_SAMPLES
    );

        do
           {
               status_pdma = PDMA_status (PDMA_CHANNEL_1);
           }while (status_pdma == 0);

    flag++;
    if(flag<NUM_CHANNELS)
    {
    	if(half==0)
    	{
    		MSS_GPIO_clear_irq( MSS_GPIO_1 );
    		CALL_FFT(lut[flag]);
    	}
    	else
    	{
    		MSS_GPIO_clear_irq( MSS_GPIO_1 );
    		CALL_FFT(&lut[flag][NUM_SAMPLES]);
    	}
    }
    else
    {
#ifndef continuous
    	 /* printing the FFT output on hyper terminal */
    	for(i=0;i<NUM_CHANNELS;i++)
    	{
    	   printf("******************%d\n\r",i);
    		for( j = 0; j<=NUM_SAMPLES; j++)
    	   {
    		   rdata1=rdata[i][j]&0x0000ffff;//16-bit fft
    		   printf("%u-->rdata = %6d   +  i * %d\n\r",j,rdata1,(int16_t)(rdata[i][j]>>16));//16-bit fft
    	   }
    	}
#endif
    }
}

/**************************************************************************/
/*Main Program*/
/**************************************************************************/

int main()
{
    volatile uint32_t i=0;

   /* Call of function to initialize the peripheral */
   init_system();
   fprintf(stderr," start fft");
   flag=NUM_CHANNELS;
   do
   {
	   lut[0][i] = ACE_get_ppe_sample( ADC0_ch0);
	   lut[1][i] = ACE_get_ppe_sample( ADC0_ch1);
	   lut[2][i] = ACE_get_ppe_sample( ADC1_ch0);
	   lut[3][i] = ACE_get_ppe_sample( ADC1_ch1);
	   lut[4][i] = ACE_get_ppe_sample( ADC2_ch0);
	   lut[5][i] = ACE_get_ppe_sample( ADC2_ch1);
       i++;
       if(i==NUM_SAMPLES)
          {
    	   if(flag!=NUM_CHANNELS)
    	   {
    		   i--;
    		   continue;
    	   }
    	 half=0;flag=0;
    	 MSS_GPIO_clear_irq( MSS_GPIO_1 );
    	 CALL_FFT(lut[0]);
          }
       if(i==2*(NUM_SAMPLES))
          {
    	   if(flag!=NUM_CHANNELS)
    	       	   {
    	       		   i--;
    	       		   continue;
    	       	   }
    	 half=1;flag=0;
    	 MSS_GPIO_clear_irq( MSS_GPIO_1 );
    	 CALL_FFT(&lut[0][NUM_SAMPLES]);
    	 i=0;
          }

   } while (1);
}


