/*
 * main.c
 *
 *  Created on: March 04, 2013
 *
 */

/*******************************************************************************
 * (c) Copyright 2011 MicroSemi Corporation.  All rights reserved.
 *

********************************************************************************/
#include <stdio.h>
#include "mss_uart.h"
#include "mss_gpio.h"




 /****************************************
 * Global variables
 ****************************************/
 uint32_t gpio_outputs;
 uint32_t master_count;
 uint32_t master[10] ,weight[10];
 uint8_t master_buff[10],weight_buff[10];
 uint8_t rx_buff[10];
 size_t rx_size;
 int weight_count;
 int set_value1,set_value2;
 uint8_t weight_error1[] = "Enter weight values for 2 fabric masters \n\r";
uint32_t *g_buffer_a ,*g_buffer_b;

#define FM1_COUNTER 0x20009000
#define FM2_COUNTER 0x2000D000
#define FM3_COUNTER 0x20009008
#define FM4_COUNTER 0x2000D008

 int Fabric_Master1_Count=0,Fabric_Master2_Count=0;
 int Fabric_Master1_ResCount=0,Fabric_Master2_ResCount=0;
 int dummy_count=0;

/****************************************
 * Master enable functions
 ***************************************/

extern void master_select(uint32_t *master, uint32_t *weight, int mast_no);
extern void AHBBus_init();

/****************************************
 * Data conversion functions
 ***************************************/
int asciitodec(uint8_t *buff1,int size,uint32_t *buff2,int mast_weight);

/****************************************
 * Interrupt Handler Functions
 ***************************************/
void FabricIrq0_IRQHandler( void );
void FabricIrq1_IRQHandler( void );
int printnumber(int);


/***********Main Function Starts here***************/

int main()
{

 	const uint8_t greating[] = "\n\r********************************************************************************\n\r###                Welcome to SmartFusion2 SoC FPGA                ###\n\r********************************************************************************\n\r";
 	uint8_t master_config[] =  "This Application shows dynamic configuration of AHB Bus Matrix Masters weight\n\r";
    uint8_t master_menu[] = "******************************************************************************** \n\r2 Fabric Masters are implemented in this design to transfer data to eSRAM1 slave\r\n";
    uint8_t weight_menu[] = "Enter weight values(range is 1-32) for FabricMaster1(FM1),FabricMaster2(FM2)and \n\r press enter (Example: 3 6)  \n\r******************************************************************************** \n\r";
 	uint8_t weight_error[] = "Invalid option for Weight states. The range is from 1-32\n\r";
 	uint8_t Access_msg1[]= "\n\r No of accesses by Fabric Master1 to transfer 1024 words are : ";
 	uint8_t Access_msg2[]= "\n\r No of accesses by Fabric Master2 to transfer 1024 words are : ";
 	uint8_t Res_count_msg1[]= "\n\r No of residue clock transfers in the last access for Fabric Master1 are: ";
 	uint8_t Res_count_msg2[]= "\n\r No of residue clock transfers in the last access for Fabric Master2 are: ";
 	uint8_t master_Fabricmaster[]="\n\r###Two Fabric Masters completed transferring 1024 number of words to eSRAM1###\n\r";

 	unsigned int size=0;
 	unsigned int j=0;
 	unsigned int mast_weight, success;

 	/************Initialization Functions*****************/
 	 MSS_GPIO_init();


    /************** GPIO'S Configuration*****************/

 	MSS_GPIO_config( MSS_GPIO_0, MSS_GPIO_OUTPUT_MODE);
 	MSS_GPIO_config( MSS_GPIO_2, MSS_GPIO_OUTPUT_MODE);
 	MSS_UART_init( &g_mss_uart0, MSS_UART_115200_BAUD, MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT );




while(1)
{
	  /***************** Reset variables****************/
	  weight[1]=0;
	  weight[0]=0;
      *rx_buff = 0;
	  size = 0;
	  master_count = 2;
	  master[0]=1;
	  master[1]=2;
	  set_value1 = 1;
	  set_value2 = 1;
	  weight_count=0;
	  MSS_GPIO_set_outputs(0x00);
	  Fabric_Master1_Count=0;
	  Fabric_Master2_Count=0;



	  /************AHB Bus Matrix Initialization Function*****************/

	  MSS_UART_polled_tx( &g_mss_uart0,greating , sizeof(greating) );
	  MSS_UART_polled_tx( &g_mss_uart0,master_config, sizeof(master_config) );
	  MSS_UART_polled_tx( &g_mss_uart0,master_menu , sizeof(master_menu) );
	  MSS_UART_polled_tx( &g_mss_uart0,weight_menu , sizeof(weight_menu) );

	  AHBBus_init();
     /***************Fabric Interrupts Enable Functions***********/

     NVIC_EnableIRQ(34);


     /********************* Weights Selection ********************/
      size =0;
      *rx_buff = 0;
      mast_weight = 0;
      while( *rx_buff!= '\n')
     {
    	  rx_size = MSS_UART_get_rx ( &g_mss_uart0, rx_buff, sizeof(rx_buff) );
    	  if( rx_size > 0 )
    	  {
    		  weight_buff[size] = *rx_buff;
    		  size++;

    	  }
      }

    success = asciitodec(weight_buff,size,weight,mast_weight);
    if(success == 0)
         {
       	  MSS_UART_polled_tx( &g_mss_uart0,weight_error , sizeof(weight_error) );
       	  continue;
         }


    if(weight_count<1 )
               {
             	  MSS_UART_polled_tx( &g_mss_uart0,weight_error1 , sizeof(weight_error1) );
             	  continue;
               }



     /**************Weight configuration Function***************/
     master_select(master, weight, master_count);

		 while(j<=0xFFFF)
		 {
			 j++;
		 }

     /***********Starting Fabric Masters**********/


    	    MSS_GPIO_set_outputs(MSS_GPIO_0_MASK);


  while(set_value1);

	  MSS_UART_polled_tx( &g_mss_uart0,master_Fabricmaster, sizeof(master_Fabricmaster));
	  /*******************************Fabric_Master1 Access Count***************/
	  MSS_UART_polled_tx( &g_mss_uart0,Access_msg1 , sizeof(Access_msg1) );
	  printnumber(Fabric_Master1_Count);
	  /*****************************Fabric_Master2 Access Count****************/
	  MSS_UART_polled_tx( &g_mss_uart0,Access_msg2 , sizeof(Access_msg2) );
	  printnumber(Fabric_Master2_Count);
	  /*****************************Fabric_Master1 residue clock Count***************/
	  MSS_UART_polled_tx( &g_mss_uart0,Res_count_msg1 , sizeof(Res_count_msg1) );
	  printnumber(Fabric_Master1_ResCount);
	  /****************************Fabric_Master2 residue clock Count****************/
	 MSS_UART_polled_tx( &g_mss_uart0,Res_count_msg2, sizeof(Res_count_msg2) );
	 printnumber(Fabric_Master2_ResCount);

	  MSS_GPIO_set_outputs(0x00);

}
}

/*********************************************
 * Fabric Master Interrupt Handler
 *********************************************/

void FabricIrq0_IRQHandler( void )
 {

	NVIC_ClearPendingIRQ( 34 );
	NVIC_DisableIRQ(34);
	Fabric_Master1_Count = *(volatile uint32_t*)FM1_COUNTER ;
	Fabric_Master2_Count = *(volatile uint32_t*)FM2_COUNTER ;
	Fabric_Master1_ResCount = *(volatile uint32_t*)FM3_COUNTER ;
	Fabric_Master2_ResCount = *(volatile uint32_t*)FM4_COUNTER ;
	MSS_GPIO_set_outputs(MSS_GPIO_2_MASK);
	set_value1 = 0;
 }



/*************************************
 * ASCII to decimal conversion
 *************************************/

int asciitodec(uint8_t *buff1,int size,uint32_t *buff2,int mast_weight)
{
int base;
int started;
int i,space_size,value;
int spaces[4];


for(i=0,space_size=0, started = 0;i<size;i++)
{
 if(started == 0) {
    if(buff1[i] >= 0x30 && buff1[i] <= 0x39) {
    spaces[space_size++] = i;
    started = 1;
    }
 } else {
    if(!(buff1[i] >= 0x30 && buff1[i] <= 0x39))
    started = 0;

 }
}
for(i=0;i<space_size;i++)
{
 base = spaces[i];
 value = atoi(&buff1[base]);

 if(mast_weight == 0)
 {
	 if((value>0)&&(value <33))
	 {
		 buff2[i]= value;
		 weight_count = i;
	 }
	 else
		 return 0;

 }

}
return 1;
}
/*************************************
 * Printing Count Values
 *************************************/
int printnumber(int n)
{
	char ret[100];
	    int numChars = 0;
	    int isNegative = 0;
	    int temp;
	    // Determine if integer is negative

	    if (n < 0) {
	        n = -n;
	        isNegative = 1;
	        numChars++;
	    }
	    // Count how much space we will need for the string
	    temp = n;
	    do {
	        numChars++;
	        temp /= 10;
	    } while ( temp );
	    ret[numChars] = 0;

	    //Add the negative sign if needed
	    if (isNegative) ret[0] = '-';

	    // Copy digits to string in reverse order
	    int i = numChars - 1;
	    do {
	        ret[i--] = n%10 + '0';
	        n /= 10;
	    } while (n);
		MSS_UART_polled_tx( &g_mss_uart0, (const uint8_t*)ret,numChars);
		MSS_UART_polled_tx( &g_mss_uart0, (const uint8_t*)"\r\n", 2 );
		return 0;
}



























