//-------------------------------------------------------------------
// McStarSubs.cpp
//
// March 21, 2008
// Gene Massion
//-------------------------------------------------------------------

#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 <stdio.h>
#include <iostream>
#include <time.h>
#include <string.h>
#include <math.h>

extern volatile GPIO_REGS	*GpioRegPtr;
extern volatile SSP_REGS	*SspRegPtr;
extern volatile CLKMAN_REGS	*v_pClkRegs;

void MapRegisters( VOID )
{
	ULONG	sscr0,
			sscr1,
			sspsp,
			gafr,
			gpdr,
			pcon=0;

	GpioRegPtr = (GPIO_REGS *)MapPhysicalAddr((GPIO_REGS *)GPIO_BASE_PHYSICAL,sizeof(GPIO_REGS));	// 1 Page
	if(GpioRegPtr == NULL)
		RETAILMSG(1,(L" Error 'cause GpioRegPtr == NULL \r\n"));

	SspRegPtr = (SSP_REGS *)MapPhysicalAddr((SSP_REGS *)NSSP_BASE_PHYSICAL,sizeof(SSP_REGS));	// 1 Page
	if(SspRegPtr == NULL)
		RETAILMSG(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)
		RETAILMSG(1,(L" Error 'cause v_pClkRegs == NULL \r\n"));

	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));
}

void InitStdSPI( VOID )
{
	ULONG	sscr0=0,
			sscr1,
			sspsp,
			gafr,
			gpdr,
			pcon=0,
			cken;

	ULONG SerialClockRate=0x24;			// 36(0x24):13e6 / 24 Mbits/s

	// 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 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);

	//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);

	//Frame format FRF SPI, Serial Clock rate SCR 368, Data Size Select DSS 8 bit
	sscr0 = (SerialClockRate << 8) | SSCR0_DSS_8;
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	
	WRITE_REGISTER_ULONG(&SspRegPtr->SSSR,  SSPSR_ROR);
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, DEFAULT_SSPCR1);

	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 ;
}

VOID InitPSP( VOID )
{
	ULONG	sscr0=0,
			sscr1,
			sspsp,
			gafr,
			gpdr,
			pcon=0,
			cken;

	// 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 
	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);

	// Set PSP mode
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR1, DEFAULT_SSPCR1);

	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);

	// Set Frame Slave mode
	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);

	// Set receive without transmit mode 
	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);

	//NOTE GPIO direction register must be written after PSP bits are set
	gpdr = READ_REGISTER_ULONG(&GpioRegPtr->GPDR_2);
	gpdr |= (GPIO_81 | GPIO_84);
	gpdr &= (~GPIO_82);
	gpdr &= (~GPIO_83); //NSSP Frame will be an input in slave mode
	WRITE_REGISTER_ULONG(&GpioRegPtr->GPDR_2, gpdr);

	//Set Serial Clock rate SCR 368, Data Size Select DSS 8 bit
	ULONG SerialClockRate=0x0;			// 36(0x24):13e6 / 24 Mbits/s
	sscr0 = (SerialClockRate << 8) | SSCR0_DSS_24;
	WRITE_REGISTER_ULONG(&SspRegPtr->SSCR0, sscr0);
	
	//Not sure why they do this
	WRITE_REGISTER_ULONG(&SspRegPtr->SSSR,  SSPSR_ROR);

	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 ;
	
	/*
	//Set PSP mode
	//GM Mar14-08
	if (1 == 1)
	{
		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);
*/	}

DWORD dwReadSSPNoPush( VOID )
{
	ULONG Count=0x3ffff;

	while((READ_REGISTER_ULONG(&SspRegPtr->SSSR) & SSSR_RNE) == 0)
	{
		if(Count-- == 0)
			break;
	}

	return READ_REGISTER_ULONG(&SspRegPtr->SSDR);
}

DWORD dwReadSSP( VOID )
{
	int count=0x3ffff;
	ulong value;
	
	while((READ_REGISTER_ULONG(&SspRegPtr->SSSR) & SSSR_RNE) == 0)
	{
		if(count-- == 0)
			break;
	}
	
	if( count <= 0)
	{
		DEBUGMSG(1,(TEXT("Read SSP timed out with RNE = 0\n")));
		return 0xFFFFFFFF;
	}
	else
	{	
		value = READ_REGISTER_ULONG(&SspRegPtr->SSDR);
//		DEBUGMSG(1,(TEXT("Count = %08x SSDR Register = %08x \n"), count, value));
		return value;
	}
}

bool SendSSPMessage(BYTE *pBuf, int num)
{
	int i;

	USHORT us;
	ULONG Count=0x3ffff;

	DEBUGMSG(1,(L"Data sent:     0x"));
	for (i=0;i<num;i++)
	{
		Count=0x3ffff;

		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;
}

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( "\\Storage Card\\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 GetData( int numSamples, int sampleRate, int* pData)
{
	// routine to read ADC for numSamples
	int	 i;
	double pi = 3.1415926535,
		   freq = 10000,
		   time,
		   dTemp;

	for(i = 0; i < numSamples; i++)
	{
		time = i / sampleRate;
		dTemp = sin( 2 * pi * freq * time );
		*(pData + i) = int(dTemp * 50000);
	}

	return TRUE;
}


bool WriteToFlash(int* pData, int numSamples)
{
	// routine to write files to flash disk

	int		i;
	char	fileName[80] = "\0",
			cTemp[10];
	FILE	*outFile;
	
	__time64_t t64Time;

    WIN32_FIND_DATA FindFileData;
	HANDLE	hFind;

	struct tm timeNow;

    
	_time64( &t64Time );
	if( (_localtime64_s(&timeNow, &t64Time)) !=0)
	{
		// process error
	}
	
	strcpy(fileName, "\\Storage Card\\McStar\\");
	_itoa(timeNow.tm_year, cTemp, 10);
	strcat(cTemp, "-");
	strcat(fileName, cTemp);
	_itoa(timeNow.tm_yday, cTemp, 10);
	strcat(cTemp, "-");
	strcat(fileName, cTemp);
	_itoa(timeNow.tm_hour, cTemp, 10);
	strcat(fileName, cTemp);
	
	strcpy(fileName, "*.*");
	hFind = FindFirstFile((LPCWSTR)fileName, &FindFileData );
	if(hFind == INVALID_HANDLE_VALUE )
		outFile = fopen(fileName, "a");
	else
		printf("Found a file");

	FindClose( hFind );

	fprintf(outFile, "%i:%i:%i:%i ",timeNow.tm_yday, timeNow.tm_hour, timeNow.tm_min, timeNow.tm_sec);
    for( i = 0; i < numSamples; i++)
		fprintf(outFile, "%d ", i);
	fprintf(outFile, "\n");

	fclose(outFile);

	return TRUE;
}

bool WriteToUSBDisk()
{
	// routine to write files stored on flash disk to USB disk
	return TRUE;
}

void GoToSleep( int sleepPeriod )
{
	// routine to put Bitsy to sleep
}


