// diskTest.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "diskTest.h"
#include "McStarMX31.h"
#include "cspi_1.h"
#include "cspi_1_registers.h"
#include "gpio.h"
#include "gpioRegisters.h"
#include "iomux.h"

#include <stdio.h>
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include <winbase.h>

/*void CreateFilename( char fileName[80], BOOL Flash, int fileNum );
int WriteToFlash(unsigned int* data, int numValues, int fileNum);
int WriteToUSBDisk(unsigned int* data, int numValues, int fileNum);
*/

CFGDATA	configData;

typedef BOOL (WINAPI *PGETDISKFREESPACEEX)(LPCSTR,
   PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);

BOOL MyGetDiskFreeSpaceEx(LPCSTR pszDrive)
{
   PGETDISKFREESPACEEX pGetDiskFreeSpaceEx;
   __int64 i64FreeBytesToCaller, i64TotalBytes, i64FreeBytes;
   
    BOOL fResult;

   pGetDiskFreeSpaceEx = (PGETDISKFREESPACEEX) GetProcAddress( 
                           GetModuleHandle((LPCWSTR)"kernel32.dll"),
                          (LPCWSTR)"GetDiskFreeSpaceExA");

   if (pGetDiskFreeSpaceEx)
   {
      fResult = pGetDiskFreeSpaceEx (pszDrive,
                 (PULARGE_INTEGER)&i64FreeBytesToCaller,
                 (PULARGE_INTEGER)&i64TotalBytes,
                 (PULARGE_INTEGER)&i64FreeBytes);

   // Process GetDiskFreeSpaceEx results.
      if(fResult) 
      {
         printf("Total free bytes = %I64d\n", i64FreeBytes);
      }
      return fResult;
   }
   return 0;
}




int WINAPI WinMain(	HINSTANCE hInstance,
					HINSTANCE hPrevInstance,
					LPTSTR    lpCmdLine,
					int       nCmdShow)
{
	int		USBWriteCount,
			fileCount,
			ffFileCount,
			numSamples1, numSamples2;
	unsigned int*	pData = 0;
	char			cTemp[200];
	DWORD			time1, time2, dwTemp;
	uint			errorCode;
	FILE			*killFile;
	WIN32_FIND_DATA ffData;
	HANDLE			hFind;

	printf("Disk function test program\n");
	printf("Built %s %s\n\n",__DATE__,__TIME__); 

//	Set division between program and object memory to maximize program/data memory data space
	CheckMemory( "Before SetSystem ...");
	SetSystemMemoryDivision( 0x0400 );
	CheckMemory( "After SetSystem...");

//	MyGetDiskFreeSpaceEx ("C");
	
	ReadConfig( configData );

	configData.numSamples = 1000000;
	configData.USBWrites = 1;
	pData = new unsigned int[configData.numSamples];

	//pData = (unsigned int *)malloc(configData.numSamples);
	if(pData == NULL)
	{
		errorCode = GetLastError();
		WriteLog(1,1,1, "error allocating pData");
		exit(-2);
	}
	CheckMemory( "After allocating pData...");

	Polled_CSPI_1::InitializeMasterMode();
	GPIO::InitializeGPIO();
	Polled_CSPI_1::Enable();
	Polled_CSPI_1::DisableLoopback();

// Make sure Hard Disks have enumerated
	GPIO::ClearGPIO(gpio1::GPIO0);	//ClearGPIO turns ON Hard Disks 
 	for(ffFileCount=0; ffFileCount<20; ffFileCount++)
	{
		hFind = FindFirstFile((TEXT("\\Hard Disk\\")), &ffData);
		errorCode = GetLastError();
		sprintf(cTemp, "%d FindFirstFile Error Code = %d", ffFileCount, errorCode);
		WriteLog(1,1,1, cTemp);
		if(errorCode == 0)
			break;
		Sleep(1000);
	}

	//Decide if the configuration allows enough time to turn off hard disks
	if( (int)(configData.numSamples / configData.sampleRate) > (2 * configData.diskPwrUpTime) )
	{
		numSamples2 = (int)(configData.diskPwrUpTime * configData.sampleRate);
		numSamples1 = configData.numSamples - numSamples2;
		GPIO::SetGPIO(gpio1::GPIO0);	//SetGPIO turns OFF Hard Disks
		sprintf(cTemp, "Turn off Hard Disk");
		WriteLog(1,1,1, cTemp);
	} else
	{
		numSamples2 = 0;
		numSamples1 = 0;
	}
	
	for(USBWriteCount=0; USBWriteCount<configData.USBWrites; USBWriteCount++)  
	{
		for(fileCount=0; fileCount<configData.numFlashFiles; fileCount++)
		{
			if( (killFile = fopen("\\Storage Card\\McStar\\killMcStar.txt", "r")) != NULL)
			{
				fclose(killFile);
				exit(-1);
			}

			if(numSamples1 == 0) //hard disk on all the time
			{
				sprintf(cTemp, "\nStarting 1 step Sample Acq %d samples", configData.numSamples);
				WriteLog(1,1,1, cTemp);
				time1 = GetTickCount();
				Polled_CSPI_1::GetNSamples( pData, configData.numSamples );	
				time2 = GetTickCount();
			}
			else //turn on and off hard disk
			{
				sprintf(cTemp, "\nStarting 2 step Sample Acq %d samples", configData.numSamples);
				WriteLog(1,1,1, cTemp);
				time1 = GetTickCount();
				Polled_CSPI_1::GetNSamples( pData, numSamples1 );
				GPIO::ClearGPIO(gpio1::GPIO0);	//ClearGPIO turns ON Hard Disks 
				sprintf(cTemp, "Turn on Hard Disk");
				WriteLog(1,1,1, cTemp);
				Polled_CSPI_1::GetNSamples( pData, numSamples2 );
				time2 = GetTickCount();

				// Make sure Hard Disks have enumerated
				for(ffFileCount=0; ffFileCount<20; ffFileCount++)
				{
					hFind = FindFirstFile((TEXT("\\Hard Disk\\")), &ffData);
					errorCode = GetLastError();
					sprintf(cTemp, "%d FindFirstFile Error Code = %d", ffFileCount, errorCode);
					WriteLog(1,1,1, cTemp);
					if(errorCode == 0)
						break;
					Sleep(1000);
				}
			}
			dwTemp = time2 - time1;
			sprintf(cTemp, "Acq Done   Acquire Time %d mSec", dwTemp);	
			WriteLog(1,1,1, cTemp);

			time1 = GetTickCount();
 			WriteToUSBDisk(pData, configData.numSamples, USBWriteCount);
			if(numSamples1 != 0)
			{
//				GPIO::SetGPIO(gpio1::GPIO0);	//SetGPIO turns OFF Hard Disks
				sprintf(cTemp, "Turn off Hard Disk");
				WriteLog(1,1,1, cTemp);
			}
			time2 = GetTickCount();
			dwTemp = time2 - time1;
			DEBUGMSG(1, (TEXT("File %d Write to USB Disk time  = %d mSec\n"), USBWriteCount, dwTemp));	
		}
	}

//	GPIO::SetGPIO(gpio1::GPIO0);	//SetGPIO turns OFF Hard Disks
	VirtualFree((PVOID)CSPI_1::virtualAddress, 0, MEM_RELEASE);
	VirtualFree((PVOID)IOMUX::virtualAddress, 0, MEM_RELEASE);
	VirtualFree((PVOID)gpio1::virtualAddress, 0, MEM_RELEASE);
	free(pData);
	delete [] pData;

	return 0;
}


void CreateFilename(char fileName[80], int fileType, int fileNum)
{
	char		cTemp[100];
	__time64_t	t64Time;
	struct tm	timeNow;
	static int	dirCount = 0,
				filesInDir = 0;
	size_t		stRet;
	BOOL		ret;
	TCHAR		tcTemp[200];
	PULARGE_INTEGER BytesAvail = 0, 
					TotalBytes = 0, 
					TotalFreeBytes = 0;
/*
	ret = GetDiskFreeSpaceEx( (LPCWSTR)"Hard Disk", BytesAvail, TotalBytes, TotalFreeBytes );
	sprintf(cTemp, "Bytes Avail = %I64d   Total Bytes = %I64d   Total Free Bytes = %I64d\n", fileName);
	WriteLog(1,1,1, cTemp);
 */  
	_time64( &t64Time );
	if( (_localtime64_s(&timeNow, &t64Time)) !=0)
	{
		// process error
	}

	if(filesInDir == configData.filesPerDirectory)
	{
		dirCount = dirCount + 1;
		filesInDir = 0;
	}

	switch( fileType)
	{
		case 0:	//USB file
			strcpy(fileName, "\\Hard Disk\\McStar\\Data");
			strcat(fileName, _itoa(dirCount, cTemp, 10)); 
			strcat(fileName, "\\");
			stRet = mbstowcs(tcTemp, fileName, 200); 
			ret = CreateDirectory( tcTemp, NULL);
			ret = GetLastError();
			filesInDir = filesInDir + 1;
			break;  
		case 1:	//Flash File
			strcpy(fileName, "\\Storage Card\\McStar\\Data");
			strcat(fileName, _itoa(dirCount, cTemp, 10)); 
			strcat(fileName, "\\");
			stRet = mbstowcs(tcTemp, fileName, 200); 
			ret = CreateDirectory( tcTemp, NULL);
			ret = GetLastError();
			CreateDirectory((LPCTSTR)fileName, NULL);
			filesInDir = filesInDir + 1;
			break;  
		case 2:	//Log File
			strcpy(fileName, "\\Storage Card\\McStar\\LogFiles\\log");
			break;
	}

	sprintf(cTemp, "%03d-",timeNow.tm_year);
	strcat(fileName, cTemp);
	sprintf(cTemp, "%03d-",timeNow.tm_yday);
	strcat(fileName, cTemp);
	sprintf(cTemp, "%02d-",timeNow.tm_hour);
	strcat(fileName, cTemp);
	sprintf(cTemp, "%02d-",timeNow.tm_min);
	strcat(fileName, cTemp);
	sprintf(cTemp, "%02d",timeNow.tm_sec);
	strcat(fileName, cTemp);

	if( fileType == 2 )
		strcat(fileName, ".txt");

	return;
}

int WriteToFlash(unsigned int* data, int numValues, int fileNum)
{
	char	fileName[80];
	int		numWritten;
	FILE	*outFile;

	CreateFilename( fileName, TRUE, fileNum );
	outFile = fopen( fileName, "ab" );

	numWritten = fwrite(data, sizeof(int), numValues, outFile);
//	DEBUGMSG(1, (_T("Wrote %d samples to flash \n"), numWritten));

	fclose(outFile);

	return numWritten;
}

int WriteToUSBDisk(unsigned int* data, int numValues, int fileNum)
{
	char	fileName[80],
			cTemp[100];
	int		numWritten;
	FILE	*outFile;

	CreateFilename( fileName, FALSE, fileNum );
	outFile = fopen( fileName, "ab");
	sprintf(cTemp, "USB Disk file name = %s", fileName);
	WriteLog(1,1,1, cTemp);

	numWritten = fwrite(data, sizeof(int), numValues, outFile);
	fclose(outFile);

	return numWritten;
}

