//*****************************************************************************
//
// ti_master.c - Example demonstrating how to configure SSI0 in TI master mode.
//
// Copyright (c) 2010-2014 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
//   Redistribution and use in source and binary forms, with or without
//   modification, are permitted provided that the following conditions
//   are met:
//
//   Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the
//   distribution.
//
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package.
//
//*****************************************************************************

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "driverlib/timer.h"

//*****************************************************************************
//
//! \addtogroup ssi_examples_list
//! <h1>TI Master (ti_master)</h1>
//!
//! This example shows how to configure the SSI0 as TI Master.  The code will
//! send three characters on the master Tx then poll the receive FIFO until
//! 3 characters are received on the master Rx.
//!
//! This example uses the following peripherals and I/O signals.  You must
//! review these and change as needed for your own board:
//! - SSI0 peripheral
//! - GPIO Port A peripheral (for SSI0 pins)
//! - SSI0Clk - PA2
//! - SSI0Fss - PA3
//! - SSI0Rx  - PA4
//! - SSI0Tx  - PA5
//!
//! The following UART signals are configured only for displaying console
//! messages for this example.  These are not required for operation of I2C0.
//! - UART0 peripheral
//! - GPIO Port A peripheral (for UART0 pins)
//! - UART0RX - PA0
//! - UART0TX - PA1
//!
//! This example uses the following interrupt handlers.  To use this example
//! in your own application you must add these interrupt handlers to your
//! vector table.
//! - None.
//
//*****************************************************************************

//*****************************************************************************
//
// Number of bytes to send and receive.
//
//*****************************************************************************
#define NUM_SSI_DATA            3

uint32_t g_ui32SysClock;
uint32_t g_ulDataRx1[4],g_ulDataRx2;
uint8_t  g_ulSSI2RXTO;
uint8_t flag =0;
uint8_t temp_data = 0;
uint32_t Count = 0;
uint8_t Send_flag = 0;
volatile uint32_t millis = 0;
uint32_t g_uc_timer = 0;

/*
  Interrupt handler for the timer
*/
void SysTickInt(void)
{
  uint32_t status=0;

  status = TimerIntStatus(TIMER5_BASE,true);
  TimerIntClear(TIMER5_BASE,status);
  millis++;
}
void
SSI0IntHandler(void)
{
	unsigned long ulStatus, ulIndex;

	//
	// Read interrupt status.
	//
	ulStatus = SSIIntStatus(SSI0_BASE, 1);

	//
	// Check the reason for the interrupt.
	//
//	if(ulStatus & SSI_RXFF)
	UARTprintf("\n\nulStatus %x:%x\n",ulStatus,ulStatus & SSI_RXFF);
//	if(ulStatus & SSI_RXTO)
	if(ulStatus & SSI_RXFF)
	{
		//
		// Interrupt is because of RX time out.  So increment counter to tell
		// main loop that RX timeout interrupt occurred.
		//


		//
		// Read NUM_SSI_DATA bytes of data from SSI2 RX FIFO.
		//
	//	SSIDataGet(SSI0_BASE, &g_ulDataRx1[0]);
	//	SSIDataPut(SSI0_BASE, 0x1111);//Dummy Write
		//sendTxSSI();
				  while(!SSIDataGetNonBlocking(SSI0_BASE, &g_ulDataRx1[0]))
				 		    {
				 		    }
				  while(!SSIDataGetNonBlocking(SSI0_BASE, &g_ulDataRx1[1]))
				 				 		    {
				 				 		    }

				  while(!SSIDataGetNonBlocking(SSI0_BASE, &g_ulDataRx1[2]))
				 				 		    {
				 				 		    }
				  while(!SSIDataGetNonBlocking(SSI0_BASE, &g_ulDataRx1[3]))
				 				 		    {
				 				 		    }


				  g_ulSSI2RXTO = 1;
		//temp_data-=2;
		//SSIDataGet(SSI0_BASE, &g_ulDataRx2);



	}

	//
	// Clear interrupts.
	//
	UARTprintf("\n\nCLear ulStatus %x\n",ulStatus);
	SSIIntClear(SSI0_BASE, ulStatus);
	//SSIIntClear(SSI0_BASE, SSI_RXFF);
}
//*****************************************************************************
//
// This function sets up UART0 to be used for a console to display information
// as the example is running.
//
//*****************************************************************************
void
InitConsole(void)
{
    //
    // Enable GPIO port A which is used for UART0 pins.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the pin muxing for UART0 functions on port A0 and A1.
    // This step is not necessary if your part does not support pin muxing.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    //
    // Enable UART0 so that we can configure the clock.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    //
    // Select the alternate (UART) function for these pins.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
}


/*
  Timer setup
*/
void TimerBegin(){

  //We set the load value so the timer interrupts each 1ms
  uint32_t Period;
// Period = 80000; //1ms
//  Period = 833;//10us
//  Period = 100;//2.5us
  Period = 1190;//us

  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5);
  SysCtlDelay(3);
  /*
    Configure the timer as periodic, by omission it's in count down mode.
    It counts from the load value to 0 and then resets back to the load value.
  REMEMBER: You need to configure the timer before setting the load and match
  */
  TimerConfigure(TIMER5_BASE, TIMER_CFG_PERIODIC);
  TimerLoadSet(TIMER5_BASE, TIMER_A, Period -1);


  TimerIntRegister(TIMER5_BASE, TIMER_A, SysTickInt);

  /*
    Enable the timeout interrupt. In count down mode it's when the timer reaches
  0 and resets back to load. In count up mode it's when the timer reaches load
  and resets back to 0.
  */
  TimerIntEnable(TIMER5_BASE, TIMER_TIMA_TIMEOUT);

  TimerEnable(TIMER5_BASE, TIMER_A);
}

/*
  This is the delay function.
*/
void Wait (uint32_t tempo) {
  volatile uint32_t temp = millis;
  while ( (millis-temp) < tempo);
}


void sendTxSSI()
{
    uint32_t ulDataTx;
    uint32_t ulDataRx;
    uint32_t ulDataTx1 =0;

		ulDataTx = 0x8001;
	    ulDataTx1 = 0x7FFC;

	    	//if(flag == 0)
	    	//{
	    if (SSIDataPutNonBlocking(SSI0_BASE,0x1111) != 0 )
	  	             {
	  	        	  UARTprintf("\nTX:%x\n\r", ulDataTx);
	  	       

	  	             }

	          if (SSIDataPutNonBlocking(SSI0_BASE,ulDataTx) != 0 )
	             {
	        	  UARTprintf("\nTX:%x\n\r", ulDataTx);

	             }

	               //Wait until SSI0 is done transferring all the data in the transmit FIFO.

//	                while( SSIBusy(SSI0_BASE) )
//	                  { ; }

	    //	}
	          ulDataTx++;
	        if ( SSIDataPutNonBlocking(SSI0_BASE, ulDataTx) != 0 )
	           {
	      	  UARTprintf("TX:%x\n\r", ulDataTx);

	           }

//	        while( SSIBusy(SSI0_BASE) )
//	                      { ; }

	        //	}

	            if ( SSIDataPutNonBlocking(SSI0_BASE, ulDataTx1) != 0 )
	               {
	          	  UARTprintf("TX:%x\n\r", ulDataTx1);

	               }

//	            while( SSIBusy(SSI0_BASE) )
//	                          { ; }

	            //	}
	           ulDataTx1++;
	                if ( SSIDataPutNonBlocking(SSI0_BASE, ulDataTx1) != 0 )
	                   {
	              	  UARTprintf("TX:%x\n\r", ulDataTx1);
	              	temp_data ++;
	                UARTprintf("\ntemp_data %d\n",temp_data);

	                   }
//	                while( SSIBusy(SSI0_BASE) )
//	                  { ; }


}
//*****************************************************************************
//
// Configure SSI0 in master TI mode.  This example will send out 3 bytes of
// data, then wait for 3 bytes of data to come in.  This will all be done using
// the polling method.
//
//*****************************************************************************
int
main(void)
{
    uint32_t pui32DataTx[NUM_SSI_DATA];
    uint32_t pui32DataRx[NUM_SSI_DATA];
    uint32_t ui32Index;
    uint32_t l_ui_Drivestrength = 0;
    uint32_t l_ui_Drivetype = 0;
    uint32_t ulDataTx;
    uint32_t ulDataRx;
    uint32_t ulDataTx1 =0;

    //
    // Set the clocking to run directly from the external crystal/oscillator.
    // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
    // crystal on your board.
    //

    g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_INT | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480),120000000);

    //
    // Set up the serial console to use for displaying messages.  This is
    // just for this example program and is not needed for SSI operation.
    //
    InitConsole();
    UARTprintf("64->g_ui32SysClock %d\n",g_ui32SysClock);



       UARTprintf("g_ui32SysClock %d\n",g_ui32SysClock);
    //
    // Display the setup on the console.
    //
    UARTprintf("SSI ->\n");
    UARTprintf("  Device: SLAVE\n");
    UARTprintf("    Mode: TI\n");
    UARTprintf("    Data: 8-bit\n\n");
    UARTprintf("   Speed: 10MHz\n\n");


    	TimerBegin();

      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
      SysCtlDelay(3);

      //Set the pin of your choise to output
      GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
    //
    // The SSI0 peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    //
    // For this example SSI0 is used with PortA[5:2].  The actual port and
    // pins used may be different on your part, consult the data sheet for
    // more information.  GPIO port A needs to be enabled so these pins can
    // be used.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
    // This step is not necessary if your part does not support pin muxing.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);
    GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);
//    GPIOPinConfigure(GPIO_PA4_SSI0XDAT3);
//    GPIOPinConfigure(GPIO_PA5_SSI0XDAT4);

    //
    // Configure the GPIO settings for the SSI pins.  This function also gives
    // control of these pins to the SSI hardware.  Consult the data sheet to
    // see which functions are allocated per pin.
    // The pins are assigned as follows:
    //      PA4 - SSI0Tx
    //      PA5 - SSI0Rx
    //      PA3 - SSI0Fss
    //      PA2 - SSI0CLK
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
                   GPIO_PIN_2);

    //
    // Configure and enable the SSI port for TI master mode.  Use SSI0, system
    // clock supply, master mode, 1MHz SSI frequency, and 8-bit data.
    //
   // g_ui32SysClock =  SysCtlClockGet();

    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_STRENGTH_4MA, GPIO_PIN_TYPE_STD);//CLK
    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_4, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD);//MOSI
    GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_5, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);//MISO



    UARTprintf("g_ui32SysClock %d\n",g_ui32SysClock);

    GPIOPadConfigGet(GPIO_PORTA_BASE, GPIO_PIN_4,&l_ui_Drivestrength,&l_ui_Drivetype);
    UARTprintf("\nl_ui_Drivestrength:%x\n",l_ui_Drivestrength);
    UARTprintf("\nl_ui_Drivetype:%x\n",l_ui_Drivetype);

//    SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0,
//                       SSI_MODE_MASTER, 60000000, 16);
    SSIConfigSetExpClk(SSI0_BASE, g_ui32SysClock, SSI_FRF_MOTO_MODE_0,
                          SSI_MODE_SLAVE, 10000000, 16);

    UARTprintf("SSI Clock Set success\n");
    //
    // Enable the SSI0 module.
    //
    SSIEnable(SSI0_BASE);


   // SSIIntEnable(SSI0_BASE, SSI_RXFF);
  //  SSIIntEnable(SSI0_BASE, SSI_RXTO);
 //   SSIIntEnable(SSI0_BASE, SSI_RXOR);


    SSIIntEnable(SSI0_BASE, SSI_RXFF);
       // SSIIntDisable(SSI0_BASE, SSI_TXFF);
    	SSIIntDisable(SSI0_BASE, SSI_TXEOT);
    	SSIIntDisable(SSI0_BASE, SSI_RXTO);
    	SSIIntDisable(SSI0_BASE, SSI_RXOR);

    SSIIntClear(SSI0_BASE, SSI_RXFF);
   // SSIIntClear(SSI0_BASE, SSI_TXFF);
    // SSIIntClear(SSI0_BASE, SSI_RXTO);
    //SSIIntClear(SSI0_BASE, SSI_RXOR);

    IntEnable(INT_SSI0);

    //
    // Read any residual data from the SSI port.  This makes sure the receive
    // FIFOs are empty, so we don't read any unwanted junk.  This is done here
    // because the TI SSI mode is full-duplex, which allows you to send and
    // receive at the same time.  The SSIDataGetNonBlocking function returns
    // "true" when data was returned, and "false" when no data was returned.
    // The "non-blocking" function checks if there is any data in the receive
    // FIFO and does not "hang" if there isn't.
    //
    while(SSIDataGetNonBlocking(SSI0_BASE, &pui32DataRx[0]))
    {
    }

    //
    // Initialize the data to send.
    //
    IntEnable(INT_SSI0);
    g_uc_timer = millis;
                UARTprintf("\ntemp_data %d\n",temp_data);
               while(1)
                {
                	 //UARTprintf("\n1.temp_data %d\n",temp_data);
					if(g_ulSSI2RXTO != 0)
					{
						UARTprintf("\ng_ulSSI2RXTO %d Count %d\n",g_ulSSI2RXTO,Count);
						g_ulSSI2RXTO = 0;
						Count++;
						UARTprintf("\nRX.%x\n\r", g_ulDataRx1[0]);
						UARTprintf("RX.%x\n\r", g_ulDataRx1[1]);
						UARTprintf("RX.%x\n\r", g_ulDataRx1[2]);
						UARTprintf("RX.%x\n\r", g_ulDataRx1[3]);
						UARTprintf("\nSEND DATA BACK TO MASTER\n");
					
				    	sendTxSSI();
					}
                }


    return(0);
}
