//-------------------------------------------------------------------
// NSSP.CPP
//
// 16-Jun-2006 ADS/ak
//  Updated to work with PXA270 NSSP port
//-------------------------------------------------------------------

#include "stdafx.h"
#include <windows.h>
#include "gpio.h"
#include "ssp.h"
#include "clk.h"
#include "McStar.h"
#include "MapIO.hpp"
#include "resource.h"
#include <stdlib.h>
#include <iostream>

#define LOOP_COUNTER	0x3ffff

extern volatile GPIO_REGS	*GpioRegPtr;
extern volatile GPDR3_REG	*GPDR3RegPtr;
extern volatile GPSR3_REG	*GPSR3RegPtr;
extern volatile GPCR3_REG	*GPCR3RegPtr;
extern volatile SSP_REGS	*SspRegPtr;
extern volatile CLKMAN_REGS	*v_pClkRegs;

void InitRegisters( VOID )
{
	ULONG	sscr0,
			sscr1,
			sspsp,
			gafr,
			gpdr,
			pcon=0,
			cken;

	DEBUGMSG(1,(TEXT(" InitNSSP: + \r\n")));
	DEBUGMSG(1,(TEXT("Initial Register values before InitNSP \r\n")));
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GAFR2_U= 0x%x \r\n"),gafr));
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GPDR_2= 0x%x \r\n"),gpdr));
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR0= 0x%x \r\n"),sscr0));
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR1= 0x%x \r\n"),sscr1));
	sspsp = READ_REGISTER_ULONG(&SspRegPtr->SSPSP);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSPSP= 0x%x \r\n"),sspsp));

	GpioRegPtr = (GPIO_REGS *)MapPhysicalAddr((GPIO_REGS *)GPIO_BASE_PHYSICAL,sizeof(GPIO_REGS));	// 1 Page
	if(GpioRegPtr == NULL)
		DEBUGMSG(1,(L" Error 'cause GpioRegPtr == NULL \r\n"));

	GPDR3RegPtr = (GPDR3_REG *)MapPhysicalAddr((GPDR3_REG *)GPDR3_BASE_PHYSICAL,sizeof(GPDR3_REG));	// 1 Page
	if(GpioRegPtr == NULL)
		DEBUGMSG(1,(L" Error 'cause GPDR3RegPtr == NULL \r\n"));

	GPSR3RegPtr = (GPSR3_REG *)MapPhysicalAddr((GPSR3_REG *)GPSR3_BASE_PHYSICAL,sizeof(GPSR3_REG));	// 1 Page
	if(GPSR3RegPtr == NULL)
		DEBUGMSG(1,(L" Error 'cause GPSR3RegPtr == NULL \r\n"));

	GPCR3RegPtr = (GPCR3_REG *)MapPhysicalAddr((GPCR3_REG *)GPCR3_BASE_PHYSICAL,sizeof(GPCR3_REG));	// 1 Page
	if(GPCR3RegPtr == NULL)
		DEBUGMSG(1,(L" Error 'cause GPCR3RegPtr == NULL \r\n"));

	SspRegPtr = (SSP_REGS *)MapPhysicalAddr((SSP_REGS *)NSSP_BASE_PHYSICAL,sizeof(SSP_REGS));	// 1 Page
	if(SspRegPtr == NULL)
		DEBUGMSG(1,(L" Error 'cause SspRegPtr == NULL \r\n"));

	v_pClkRegs = (CLKMAN_REGS *)MapPhysicalAddr((CLKMAN_REGS *)CLK_BASE_PHYSICAL,sizeof(CLKMAN_REGS));	// 1 Page
	if(v_pClkRegs == NULL)
		DEBUGMSG(1,(L" Error 'cause v_pClkRegs == NULL \r\n"));

	// Disable SSP Clock
	cken = READ_REGISTER_ULONG(&v_pClkRegs->cken);
	cken &= ~CLK_NSSP;
	WRITE_REGISTER_ULONG(&v_pClkRegs->cken,cken);

	ULONG altFcn1 = 0x01;  // use 0x01 to enable Alternate Fuction 1 of the pin

	// Set GPIO 81 Alternate Functions : NSSP Transmit (Output Mode)
	ULONG pin81mask = 0x03 << 2;
	ULONG pin81AltFcn1 = (0x03 & altFcn1) << 2;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin81mask;								// Clear bits
	gafr |= pin81AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	// Set GPIO 82 Alternate Functions : NSSP Receive (Input Mode)
	ULONG pin82mask = 0x03 << 4;
	ULONG pin82AltFcn1 = (0x03 & altFcn1) << 4;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin82mask;								// Clear bits
	gafr |= pin82AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	/*
	// Set GPIO 83 Alternate Functions : NSSP Frame (Output Mode)
	ULONG pin83mask = 0x03 << 6;
	ULONG pin83AltFcn1 = (0x03 & altFcn1) << 6;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin83mask;								// Clear bits
	gafr |= pin83AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);
    */

	// Set GPIO 83 Alternate Functions : NSSP Frame (Input Mode)
	ULONG pin83mask = 0x03 << 6;
	ULONG pin83AltFcn1 = (0x03 & altFcn1) << 6;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin83mask;								// Clear bits
	gafr |= pin83AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);
    
	// Set GPIO 84 Alternate Functions : NSSP Clock (Output Mode)
	ULONG pin84mask = 0x03 << 8;
	ULONG pin84AltFcn1 = (0x03 & altFcn1) << 8;
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	gafr &= ~pin84mask;								// Clear bits
	gafr |= pin84AltFcn1;							// Enable pin Alternate Function 1
	WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR2_U, gafr);

	//Clear RX FIFO Overrun bit
	WRITE_REGISTER_ULONG(&SspRegPtr->SSSR,  SSPSR_ROR);
	//Clear all bits in SSCR1
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, DEFAULT_SSPCR1);

	//Set PSP mode
	//GM Mar14-08
	if (1 == 1)
	{
		DEBUGMSG(1,(TEXT("Setting PSP mode \n")));
		ULONG FRFMask = 0x03 << 4;
		ULONG PSPMode = 0x03 << 4;
		sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
		sscr0 &= ~FRFMask;			// Clear bits
		sscr0 |= PSPMode;			// Register SSCR0 bits 5:4
		WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);

		DEBUGMSG(1,(TEXT("Setting Frame Slave mode \n")));
		ULONG SFRMDIRMask = 0x01 << 24;
		ULONG FRMSlaveMode = 0x01 << 24;
		sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
		sscr1 &= ~SFRMDIRMask;			// Clear bits
		sscr1 |= FRMSlaveMode;			// Register SSCR1 bits 24
		WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, sscr1);

		DEBUGMSG(1,(TEXT("Setting receive without transmit mode \n")));
		ULONG RWOTMask = 0x01 << 23;
		ULONG RWOTMode = 0x01 << 23;
		sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
		sscr1 &= ~RWOTMask;			// Clear bits
		sscr1 |= RWOTMode;			// Register SSCR1 bits 24
		WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, sscr1);

		DEBUGMSG(1,(TEXT("Setting Serial Clock Rate \n")));
		ULONG SCRMask = 0xfff << 24;
		ULONG SCR13e6 = 0x00;		// Serial Clock Rate = 13e6 MHz
		sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
		sscr0 &= ~SCRMask;			// Clear bits
		sscr0 |= SCR13e6;			// Register SSCR0 bits 19:8
		WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);

		DEBUGMSG(1,(TEXT("Setting Data Size \n")));
		ULONG DSSMask = 0x0f;
		ULONG DSSMode = SSCR0_DSS_24;
		sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
		sscr0 &= ~DSSMask;			// Clear bits
		sscr0 |= DSSMode;			// Register SSCR0 bits 3:0
		WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);

		DEBUGMSG(1,(TEXT("Setting GPIO106 & 107 Alt Fcn 00 \n")));
		ULONG GPIO1067Mask = 0x00 << 20;
		ULONG GPIO1067Mode = 0x00 << 20;
		gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR3_L);
		gafr &= ~GPIO1067Mask;			// Clear bits
		gafr |= GPIO1067Mode;			// Register SSCR0 bits 3:0
		WRITE_REGISTER_ULONG(&GpioRegPtr->GAFR3_L, gafr);
	}

	//NOTE GPIO direction register must be written after PSP bits are set
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	gpdr |= (GPIO_81 | GPIO_83 | GPIO_84);
	gpdr &= (~GPIO_82);
	WRITE_REGISTER_ULONG(&GpioRegPtr->GPDR_2, gpdr);

	//Motorola, 
//	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, SSPCR0_FRF_Motorola | SSPCR0_SCR | SSPCR0_DSS_8 | SSPCR0_SSE);

	DEBUGMSG(1,(TEXT(" InitNSSP: Enable Clock \r\n")));
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	sscr0 |= SSPCR0_SSE;
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);

	// Enable SSP Clock 
	cken = READ_REGISTER_ULONG(&v_pClkRegs->cken);
	cken |= (CLK_NSSP);
	WRITE_REGISTER_ULONG(&v_pClkRegs->cken,cken);;

	DEBUGMSG(1,(TEXT("Register values after InitNSP \r\n")));
	gafr = READ_REGISTER_ULONG(&GpioRegPtr->GAFR2_U);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GAFR2_U= 0x%8x \r\n"),gafr));
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	DEBUGMSG(1,(TEXT(" SspRegPtr->GPDR_2= 0x%8x \r\n"),gpdr));
	sscr0 = READ_REGISTER_ULONG(&SspRegPtr->SSCR0);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR0= 0x%8x \r\n"),sscr0));
	sscr1 = READ_REGISTER_ULONG(&SspRegPtr->SSCR1);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSCR1= 0x%8x \r\n"),sscr1));
	sspsp = READ_REGISTER_ULONG(&SspRegPtr->SSPSP);
	DEBUGMSG(1,(TEXT(" SspRegPtr->SSPSP= 0x%8x \r\n"),sspsp));

	DEBUGMSG(1,(TEXT(" InitNSSP: - \r\n")));

	return ;
}

DWORD dwReadSSPNoPush( VOID )
{
	ULONG Count=LOOP_COUNTER;
	ULONG value;

	while((READ_REGISTER_ULONG(&SspRegPtr->SSSR) & SSSR_RNE) == 0)
	{
		DEBUGMSG(1,(TEXT("waiting for RNE\n")));
		if(Count-- == 0)
			break;
	}
	value = READ_REGISTER_ULONG(&SspRegPtr->SSDR);
	DEBUGMSG(1,(TEXT("SSSR Register = %08x \n"), value));
	return READ_REGISTER_ULONG(&SspRegPtr->SSDR);
}

BOOL SendSSPMessage(BYTE *pBuf, int num)
{
	int i;

	USHORT us;
	ULONG Count=LOOP_COUNTER;

	DEBUGMSG(1,(L"Data sent:     0x"));
	for (i=0;i<num;i++)
	{
		Count=LOOP_COUNTER;

		while((READ_REGISTER_ULONG(&SspRegPtr->SSSR) & SSSR_TNF) == 0)
		{
			if(Count-- == 0 )
			{
				break;
			}			
		}

		if(Count == 0 )
		{
			break;
		}			

		us = pBuf[i];

	    WRITE_REGISTER_ULONG(&SspRegPtr->SSDR, us);
		DEBUGMSG(1,(L" %04x",us));
	}
	DEBUGMSG(1,(L"\r\n"));

	if(Count == 0 )
	{
		goto error_return;
	}			

	// Show the bytes that were pushed out during the command sending

	DEBUGMSG(1,(TEXT("Data received: ")));
	for (i=0;i<num;i++)
	{
	//	DEBUGMSG(1,(TEXT(" %04x"),dwReadSSPNoPush()));
	}
	DEBUGMSG(1,(TEXT("\r\n")));

	return TRUE;

error_return:

	return FALSE;
}

DWORD dwReadSSP( VOID )
{
	ULONG Count=LOOP_COUNTER;
	ULONG value;

	value = READ_REGISTER_ULONG(&SspRegPtr->SSSR);
	while((value & SSSR_RNE) == 0)
	{
		DEBUGMSG(1,(TEXT("waiting for RNE %0d  %08x \n"), Count, value));
		if(Count-- == 0)
			break;
	}
	value = READ_REGISTER_ULONG(&SspRegPtr->SSDR);
	DEBUGMSG(1,(TEXT("SSSR Register = %08x \n"), value));
	return READ_REGISTER_ULONG(&SspRegPtr->SSDR);
}

BOOL ToggleGPIO( VOID )
{
	int				i;
	unsigned long	ulTemp,
					set,
					clear;

	//Toggle EIO8 and EIO9 (GPIO 106 and 107)
	//Set bits to output
	ulTemp = READ_REGISTER_ULONG(&GPDR3RegPtr->GPDR_3);
	ulTemp |= 0x11 << 10;
	WRITE_REGISTER_ULONG(&GPDR3RegPtr->GPDR_3, ulTemp);
	set = READ_REGISTER_ULONG(&GPSR3RegPtr->GPSR_3);
	set |= 0x11 << 10;
	clear = READ_REGISTER_ULONG(&GPCR3RegPtr->GPCR_3);
	clear |= 0x11 << 10;
	
	for(i=0; i<100; i++)
	{
		WRITE_REGISTER_ULONG(&GPSR3RegPtr->GPSR_3, set);
		WRITE_REGISTER_ULONG(&GPCR3RegPtr->GPCR_3, clear);
	}
	return TRUE;
}

BOOL ReadConfig( CFGDATA& configData )
{
	FILE *configFile;
	char inString[80],
	 	 *label,
		 *value;
	

	if ( (configFile = fopen( "\\FlashFX Disk\\McStar\\McStarConfig.cfg", "r")) != NULL)
		DEBUGMSG(1,(TEXT("Opened Configuration File \n")));
	else
	{
		//process error
	}


	while( !feof(configFile) ) 
	{
		fgets(inString, 80, configFile);
		label = strtok(inString, ":");
		value = strtok(NULL, ":") ;

		if (strcmp(label, "Sample rate") == 0)
		{
			DEBUGMSG(1,(TEXT("Parsed Sample rate \n")));
			if ( (configData.sampleRate = atoi(value)) == 0)
			{
				// process error
			}
			label = "";
		}
		else if (strcmp(label, "Number of hydrophones") == 0)
		{
			DEBUGMSG(1,(TEXT("Parsed Number of hydrophones \n")));
			if ( (configData.numPhones = atoi(value)) == 0)
			{
				// process error
			}
			label = "";
		}
		else if (strcmp(label, "Number of Flash Disk files per USB write") == 0)
		{
			DEBUGMSG(1,(TEXT("Parsed Number of files \n")));
			if ( (configData.numFiles = atoi(value)) == 0)
			{
				// process error
			}
			label = "";
		}
		else if (strcmp(label, "Number of samples per Flash Disk file") == 0)
		{
			DEBUGMSG(1,(TEXT("Parsed Number of samples \n")));
			if ( (configData.numSamples = atoi(value)) == 0)
			{
				// process error
			}
			label = "";
		}
		else if (strcmp(label, "Seconds to sleep between acquisitions") == 0)
		{
			DEBUGMSG(1,(TEXT("Parsed sleep period \n")));
			if ( (configData.sleepPeriod = atoi(value)) == 0)
			{
				// process error
			}
			label = "";
		}
	}
	return TRUE;
}

BOOL WriteToDisk()
{
	// routine to write files stored on flash disk to USB disk
	return TRUE;
}

BOOL GetData( int numSamples, int sampleRate)
{
	// routine to read ADC for numSamples
/*
	int	 i;
	double* pData;
	double pi = 3.1415926535,
		   freq = 10000,
		   time;

	pData = new double[numSamples];

	for(i = 0; i < numSamples; i++)
	{
		time = i / sampleRate;
		*(pData + i)= sin( 2 * pi * freq * time );
	}
	
	delete [] pData;
	
	*/
	return TRUE;
}

VOID GoToSleep( int sleepPeriod )
{
	// routine to put Bitsy to sleep
}


