// McStar.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "MapIO.hpp"
#include "gpio.h"
#include "ssp.h"
#include "clk.h"
#include "resource.h"
#include "McStar.h"
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "ADSmartIO_load.h"

volatile GPIO_REGS		*GpioRegPtr = NULL;
volatile SSP_REGS		*SspRegPtr  = NULL;
volatile CLKMAN_REGS	*v_pClkRegs	= NULL;

float GetBatVoltage( int numAvgs )
{
	int i,
		sum;
	unsigned short ADCValue;
	float avg;

	sum = 0;
	for(i=0; i<numAvgs; i++)
	{
		ADCValue = SIOAnalogConversion( (byte)0 );
		sum = sum + ADCValue;
	}
	avg = sum / numAvgs;

	return(avg);
}


void WriteLog(BOOL print, BOOL debug, BOOL file, char logEntry[200])
{
	FILE	*logFile;
	TCHAR	tcharTemp[160];
	__time64_t	t64Time;
	struct tm	timeNow;
	static BOOL		firstCall = 1;
	static TCHAR	fileName[80];
	
	if(firstCall == 1)
	{
		CreateFilename(fileName, LOGFILE );
		firstCall = 0;
	}

	if(print == 1)
	{
		_time64( &t64Time );
		_localtime64_s(&timeNow, &t64Time);
		printf("%d-%d-%d\t%d:%d:%d\t%s\n", timeNow.tm_mon+1, timeNow.tm_mday, timeNow.tm_year+1900, timeNow.tm_hour, timeNow.tm_min, timeNow.tm_sec, logEntry);
	}
	if(debug == 1)
	{
		mbstowcs(tcharTemp, logEntry, 200);
		DEBUGMSG(1, (TEXT("%s\n"), tcharTemp));
	}
	if(file == 1)
	{ 
		logFile = _wfopen( fileName, L"a");
		_time64( &t64Time );
		_localtime64_s(&timeNow, &t64Time);
		fprintf(logFile, "%d-%d-%d\t%d:%d:%d\t%s\n", timeNow.tm_mon+1, timeNow.tm_mday, timeNow.tm_year+1900, timeNow.tm_hour, timeNow.tm_min, timeNow.tm_sec, logEntry);
		fclose(logFile);
	}
}

void CheckMemory( char comment[80] )
{
   // Program memory information
    MEMORYSTATUS	memInfo;
	char			cTemp[80];
	
	memInfo.dwLength = sizeof(memInfo);
    GlobalMemoryStatus(&memInfo);
    sprintf(cTemp, "%s Total RAM: %d bytes\n Free: %d \nUsed: %d\nMemory Load %d percent\n\n", comment, memInfo.dwTotalPhys, memInfo.dwAvailPhys, memInfo.dwTotalPhys-memInfo.dwAvailPhys, memInfo.dwMemoryLoad);
    WriteLog(1,1,1, cTemp);
}

void InitGPIO( VOID )
{
//	Note this function only works for GPIO bits 105, 106 & 107
//	Bitsy Xb EIO7 = GPIO105
//	Bitsy Xb EIO8 = GPIO106
//	Bitsy Xb EIO9 = GPIO107

	LPVOID	m_hGPIO;
	DWORD	*ptr;

	m_hGPIO = MapAddress(GPIO_BASE);

	//Set GPIO Set Register bits to 1
	ptr = (DWORD*)m_hGPIO;
	ptr += (GPSR3_OFFSET / sizeof(DWORD));
	*ptr |= (0x07 << 9);	// set the 3 bits to 1
	DEBUGMSG(1,(TEXT("GPSR3 = 0x%8x \n\n"),*ptr));

	//Set the direction register to output
	ptr = (DWORD*)m_hGPIO;
	ptr += (GPDR3_OFFSET / sizeof(DWORD));
	*ptr |= (0x07 << 9);	// set the 3 direction bits to 1 for output
	DEBUGMSG(1,(TEXT("GPDR3 = 0x%8x \r\n"),*ptr));

	//Set GPIO alternate function bit
	ptr = (DWORD*)m_hGPIO;
	ptr += (GAFR3_L_OFFSET / sizeof(DWORD));
	*ptr &= ~(0x3F << 18);	// clear the AF bits (2 per GPIO bit) to 0 for GPIO (no alternate function)
	DEBUGMSG(1,(TEXT("GAFR3_L = 0x%8x \r\n"),*ptr));
}

void SR_GPIOBit(int GPBitNum, int value)
{
//	Note this function only works for GPIO bits 96 to 120
//	Bitsy Xb EIO7 = GPIO105
//	Bitsy Xb EIO8 = GPIO106
//	Bitsy Xb EIO9 = GPIO107

	int		iTemp;
	LPVOID	m_hGPIO;
	DWORD	*ptr;

	m_hGPIO = MapAddress(GPIO_BASE);

	//Set GPIO Set or Clear Register
	if (value == 1)
	{
		ptr = (DWORD*)m_hGPIO;
		ptr += (GPSR3_OFFSET / sizeof(DWORD));
		iTemp = GPBitNum - 96;  // find the right bit in the GPSR3 register (bit0 = GPIO96)
		*ptr |= (0x1 << iTemp);	// set the bit
		DEBUGMSG(1,(TEXT("GPSR3 = 0x%8x \n\n"),*ptr));
	} else
	{
		ptr = (DWORD*)m_hGPIO;
		ptr += (GPCR3_OFFSET / sizeof(DWORD));
		iTemp = GPBitNum - 96;  // find the right bit in the GPSR3 register (bit0 = GPIO96)
		*ptr |= (0x1 << iTemp);	// set the bit
		DEBUGMSG(1,(TEXT("GPCR3 = 0x%8x \n\n"),*ptr));
	}
}

int WINAPI WinMain(	HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	int				fileCount,
					numWritten,
					USBWriteCount,
					ADSIOError,
					PU_USBFileNum,
					i, j;
	unsigned int*	pData = 0;
	uint			temperature;
	float			totalAcqTime,
					flashFileTime,
					sampleAcqTime;
	bool			powerDownUSB;
	char			cTemp[200], cTemp2[200], cTemp3[200];
	DWORD			time1, time2, dwTemp;
	TCHAR			fileName[100],
					destFile[100],
					fileList[100][100];
 	CFGDATA			configData;

	WriteLog(1, 1, 1, "McSTAR Acoustic Receiver Data Acq program");
	sprintf(cTemp, "Built %s %s\n\n",__DATE__,__TIME__);
	WriteLog(1, 1, 1, cTemp);
	
	WriteLog(1, 1, 1, "Sleeping while USB disk(s) enumerate");
	Sleep(1000);
	
//	Set division between program and object memory to maximize program/data memory data space
	SetSystemMemoryDivision( 0x100 );

	ADSIOError = LoadADSmartIOFunctions();
				 
	ReadConfig( configData );
//	SetPowerState( LOW_POWER );
	MapRegisters();
	InitPSP();
	InitGPIO();

	//Figure out when to power up/down the USB disk(s)
	sampleAcqTime = configData.numSamples / configData.sampleRate;
	flashFileTime = 0.1 + ((float)configData.numSamples / 500000.0);
	totalAcqTime = (float)configData.numFlashFiles * (sampleAcqTime + flashFileTime);
	if( (totalAcqTime / (float)configData.USBSpinUpTime) > 2.0)
	{
//		SR_GPIOBit(107, 0);
		powerDownUSB = TRUE;
		PU_USBFileNum = configData.numFlashFiles - (int)(ceil((configData.USBSpinUpTime / (sampleAcqTime + flashFileTime)) + 0.5) + 2);
	} else
	{
		SR_GPIOBit(107, 1);
		powerDownUSB = FALSE;
		PU_USBFileNum = -1;
	}
	SR_GPIOBit(107, 1);

	temperature = SIOReadTemperature();
//	RETAILMSG(1,(L" TestAvr: Temperature = %d \r\n", temperature));

	CheckMemory( "Before new assignment");
	pData = new unsigned int[configData.numSamples];
	CheckMemory( "After new assignment");

	for(USBWriteCount=0; USBWriteCount<configData.USBWrites; USBWriteCount++)
	{
		for(fileCount=0; fileCount<configData.numFlashFiles; fileCount++)
		{
			sprintf(cTemp, "Starting Sample Acq = %d samples",configData.numSamples);
			WriteLog(1,1,1, cTemp);
			time1 = GetTickCount();
			dwReadSSP( pData, configData.numSamples );
			time2 = GetTickCount();
			dwTemp = time2 - time1;
			sprintf(cTemp, "Acq Done   Acquire Time = %d mSec", dwTemp);	
			WriteLog(1,1,1, cTemp);

			WriteLog(1,1,1, "Starting Flash Disk Write ");	
			time1 = GetTickCount();
			numWritten = WriteToFlash( pData, configData.numSamples, fileName );
			time2 = GetTickCount();
			wcscpy(fileList[fileCount], fileName);
			dwTemp = time2 - time1;
			sprintf(cTemp, "Wrote %d samples to File Number = %d of %d  Write Time = %d mSec", \
				numWritten, fileCount + 1, configData.numFlashFiles, dwTemp);
			WriteLog(1,1,1, cTemp);

			if(fileCount == PU_USBFileNum)
				SR_GPIOBit(107, 1);
		}
		WriteLog(1,1,1, "Starting File Moves from CF to USB");
		time1 = GetTickCount();
		for(i=0; i<configData.numFlashFiles; i++)
		{
			wcscpy(destFile, (TEXT("\\Hard Disk")));
			for(j=0; j<(int)wcslen(fileList[i]); j++)
				destFile[j+10] = fileList[i][j+13];
			destFile[j+10] = 0;
			CopyFile(fileList[i], destFile, FALSE);
			DeleteFile(fileList[i]);
			wcstombs(cTemp2, fileList[i], 80);
			wcstombs(cTemp3, destFile, 80);
			sprintf(cTemp, "Moved file %s to %s", cTemp2, cTemp3);
			WriteLog(1,1,1, cTemp); 
		}
		time2 = GetTickCount();
		dwTemp = time2 - time1;
		sprintf(cTemp, "File Moves Done   Move Time = %d mSec", dwTemp);
		WriteLog(1,1,1, cTemp);
		sprintf(cTemp, "Battery Voltage = %8.2f counts\n", GetBatVoltage( 10 ));
		WriteLog(1,1,1, cTemp);
		if(powerDownUSB)
			SR_GPIOBit(107, 0);
	}

	delete [] pData;
	VirtualFree((PVOID)v_pClkRegs,0,MEM_RELEASE);
	VirtualFree((PVOID)SspRegPtr,0,MEM_RELEASE);
	VirtualFree((PVOID)GpioRegPtr,0,MEM_RELEASE);

//	SetPowerState( HIGH_POWER );
	return 0;
}

