/************************************************************************/
/*																		*/
/* Mem_Test.c                                                           */
/*																		*/
/* Example that tests all SDRAM locations on the HERON-FPGA7.			*/
/*																		*/
/* The tests include writing all zeros, all ones, the value 55h, the 	*/
/* value AAh, writing with the address and writing with a walking one.  */
/*																		*/
/* 2003 Hunt Engineering			   					 	  	    	*/
/* All Rights Reserved												    */
/*																		*/
/* Ver	   Date	 	Author	Comments									*/
/* ---	   ----		-------	--------									*/
/*																		*/
/* 1.0	 10/09/03	  RW	First written.								*/
/* 1.1	 22/03/05	  RW	Changed address information when displaying	*/
/* 							error messages.								*/
/* 																		*/
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include "heapi.h"



/* Message Type Definitions */
#define MODULE_TYPE_QUERY	1
#define MODULE_TYPE_REPLY	2
#define SEND_BITSTREAM		3
#define USER_WRITE			8
#define USER_READ			9
#define USER_READ_REPLY		10


#define TOTAL_MEMORY_SIZE	128
//#define TOTAL_MEMORY_SIZE	256


#define NO_OF_BLOCKS_128M	1024
#define NO_OF_BLOCKS_256M	2048


/* Definition for SDRAM data read operation */
#define BLOCK_SIZE			32768


/* Function Prototypes */
HE_BYTE Search_For_Modules(void);
void Print_Device_Statistics(char *dev_str);
int  Query_Module_Type(HE_BYTE slot, HE_BYTE *reply, int buffer_size);
int  Initialise_Host_HSB(char *dev_name, HE_WORD board);
void Print_Win32_Error(HE_DWORD errorcode);
void error(char *string, int Status);
void Display_Help(void);
int  Test_If_Proc_Module(char *dev_name, HE_WORD board, int slot);
void SendUserData(char *devname, HE_WORD Board, HE_BYTE slot, HE_BYTE Address, int Data);
void Error(HE_DWORD errorcode);
void Check_Module(HE_BYTE slot);
int  readback_user(HE_BYTE slot, HE_BYTE *reply, int buffer_size, HE_BYTE send_data);


/* Global Variables */
HE_HANDLE   hDevice			= NULL;
HE_IOSTATUS ReadIoStatus	= NULL;
HE_IOSTATUS WriteIoStatus	= NULL;
HE_HANDLE   hsbDevice		= NULL;
HE_DWORD 	Status;

char command[70];


HE_DWORD control[1];
HE_DWORD results[BLOCK_SIZE];

HE_BYTE Slot;
HE_WORD Board=0; // The board number we will be using

int  verbose;
char devname[255]; // The Host Interface Type we will be using


int main(int argc, char *argv[])
{
char *arg;
char tmp[255]; 
int  i,n,ask;
char *string; 
char *fifodev;
int  start, length;
int  a,b,errors;
int  no_of_blocks;
int  burst_length;
int  loop;
int  hsb_open;
HE_DWORD compare;
HE_DWORD test_data;
FILE *fptr;


/* Check the number of program arguments */;
if (argc > 3) 
{
	Display_Help();
	exit(-1);
}

/* Check arguments are valid */
i = 1;
verbose = 0;
ask=0;
while (i < argc) 
{
	arg = argv[i++];
	if (arg[0] == '-') 
	{
		/* Program options */
		n = strlen(arg);
		if ((n == 2) && ((arg[1] == 'v') || (arg[1] == 'V'))) 
		{
			verbose = 1;
		}
		else if ((n == 2) && ((arg[1] == 'a') || (arg[1] == 'A'))) 
		{
			ask=1;
		}
		else 
		{
			Display_Help();
			exit(-1);
		}
	}
	else
	{
		Display_Help();
		exit(-1);
	}
}

string = NULL;
if (ask==0)
{
	/* Set up for board we're going to open */
	string=getenv("HEAPIHSB");
	if (string==NULL)
	{	
		if (verbose)printf("No HEAPIHSB variable found, using HEAPIJTAG\n");
		string=getenv("HEAPIJTAG");
		if (string==NULL)
		{
			if (verbose)printf("No HEAPIJTAG variable found\n");
		}
	}
}

if (string != NULL)
{
	i = 0;
	while ((string[i]==' ') || (string[i]=='\t'))i++;
	start=i;
	while ((string[i]!=' ') && (string[i]!='\t'))i++;
	length=i-start; 
	strncpy(devname,&string[start] , length);
	i++;
	while ((string[i]==' ') || (string[i]=='\t'))i++;
	start=i;
	while ((string[i]!=' ') && (string[i]!='\t'))i++;
	length=i=start; 
	strncpy(tmp,&string[start] , length);
    Board   = (HE_WORD)atoi(tmp);
}
else
{
printf("What board do you want to open (eg hep8a, hep9a)? ");
gets(devname);
printf("Which board do you want to open? (eg 0,1,2...) ");
gets(tmp);
Board = atoi(tmp);
}

if( (Board<0) || (Board>15)) error("Bad Board Number",-1);
if (verbose)printf("using device %s number %x \n",devname,Board);

hsb_open = 0;

/* Open Board */
Status = Initialise_Host_HSB(devname,Board);
if(Status != HE_OK) error("Can't init HSB, exiting\n", Status);
else hsb_open = 1;

if (ask==1)
{
	printf("Which slot is the FPGA module in? (1,2, 3 or 4) ");
	gets(tmp);
	Slot = atoi(tmp);
	if( (Slot<1)||(Slot>4)) error("Bad Slot Number",-1);
	if (verbose)printf("you entered slot %x\n",Slot);
    Check_Module(Slot); 
}
else
{
	/* nothing specified, search for possible modules and ask for choices*/
	Slot=Search_For_Modules();
}

/* open the board and reset it */
Status = HeOpen1(devname, (HE_WORD)Board, "FifoA", &hDevice);
if (Status != HE_OK) error("Open Failed, exiting\n", Status);

/* reset the hardware */
HeReset(hDevice);

if (stricmp(devname,"hep8a")==0) {
	if (Slot!=1) {
		printf("ERROR: For an HEPC8 the FPGA module must be in slot1\n");
		getchar();
		exit(0);
	}
	else {
		printf("Module is in slot1 and FIFO 1 will be used to connect to the Host\n");
		fifodev="FifoA";
	}
}
else {
	switch (Slot) {
		case 2:  fifodev="FifoB";
			     break;
		case 3:  fifodev="FifoC";
			     break;
		case 4:  fifodev="FifoD";
			     break;
		default: fifodev="FifoA";
			     break;
	}
	if (fifodev!="FifoA") {
		Status = HeClose(&hDevice);
		if(Status != HE_OK) error("Failed close..., exiting\n", Status);
		Status = HeOpen1(devname, (HE_WORD)Board, fifodev, &hDevice);
		if(Status != HE_OK) error("Open Failed, exiting\n", Status);
	}
}

Status = HeInitIoStatus(hDevice, &ReadIoStatus); // Initialise read IoStatus
if (Status != HE_OK) error("Can't init Read I/O, exiting\n", Status);
Status = HeInitIoStatus(hDevice, &WriteIoStatus); // Initialise write IoStatus
if (Status != HE_OK) error("Can't init Write I/O, exiting\n", Status);
if (verbose) printf("Board Opened\n");

/* if its not an HEPC8 then set the HEART connections so that one host FIFO */
/* connects to each module slot. Then the host FIFO number determines which */
/* module is being used */
if(stricmp(devname,"hep8a")!=0)
{
	printf("Setting the HEART configuration on HEPC9\n");
	Status = HeClose(&hsbDevice);
	hsb_open = 0;
	string=getenv("HEAPI_DIR");
	/* check to see if a network file exists in this directory*/
	fptr=fopen("network", "r");	
	if (fptr!=NULL)
	{
		fclose(fptr);
		sprintf(command,"%s\\heartconf\\heartconf network\n",string);
    }
	else 
	{
	/* if not then look in the directory above in case we are running from a debig or release directory*/ 
		fptr=fopen("..\\network", "r");
		if (fptr!=NULL)
		{
			fclose(fptr);
			sprintf(command,"%s\\heartconf\\heartconf ..\\network\n",string);
		}
		else
		{
			printf("ERROR cannot locate the network file in this or the directory above\n");
			getchar();
			exit(0);
		}
	}
	/* call heart conf to set the network up */		
	system(command);
}

/* Ask user if they want to proceed */
printf("Hit a key to begin the SDRAM Memory Test...");
getchar();
printf("OK, testing...\n\n");

loop = 0;
errors = 0;

if (TOTAL_MEMORY_SIZE == 128) {
	no_of_blocks = NO_OF_BLOCKS_128M;
	burst_length = BLOCK_SIZE;
}
if (TOTAL_MEMORY_SIZE == 256) {
	no_of_blocks = NO_OF_BLOCKS_256M;
	burst_length = BLOCK_SIZE;
}

while ((errors == 0) && (loop <5)) {
	control[0] = 0x00000030;

	Status = HeWrite(hDevice, control, 1 * sizeof(HE_DWORD), WriteIoStatus);
	HeWaitForIo(hDevice, WriteIoStatus); 

	test_data = 0x00000000;
	printf("Testing SDRAM with data pattern: %08lx\n",test_data);

	b = 0;
	for (i=0;i<no_of_blocks;i++) {
		Status = HeRead(hDevice, results, burst_length * sizeof(HE_DWORD), ReadIoStatus);
		HeWaitForIo(hDevice, ReadIoStatus); 

		for (a=0;a<burst_length;a++) {
			if (results[a] != test_data) {
				printf("Error!!!\n");
				printf("Address  %08lx\n",((i * burst_length) + a));
				printf("Expected %08lx\n",test_data);
				printf("Received %08lx\n",results[a]);
				errors++;
				getchar();
			}
		}
		b += burst_length;
	}
	if (errors == 0) printf("Tested %d locations successfully\n\n",b);
	else             printf("Errors found with test\n\n");

	control[0] = 0x00000031;

	Status = HeWrite(hDevice, control, 1 * sizeof(HE_DWORD), WriteIoStatus);
	HeWaitForIo(hDevice, WriteIoStatus); 

	test_data = 0xffffffff;
	printf("Testing SDRAM with data pattern: %08lx\n",test_data);

	b = 0;
	for (i=0;i<no_of_blocks;i++) {
		Status = HeRead(hDevice, results, burst_length * sizeof(HE_DWORD), ReadIoStatus);
		HeWaitForIo(hDevice, ReadIoStatus); 

		for (a=0;a<burst_length;a++) {
			if (results[a] != test_data) {
				printf("Error!!!\n");
				printf("Address  %08lx\n",((i * burst_length) + a));
				printf("Expected %08lx\n",test_data);
				printf("Received %08lx\n",results[a]);
				errors++;
				getchar();
			}
		}
		b += burst_length;
	}
	if (errors == 0) printf("Tested %d locations successfully\n\n",b);
	else             printf("Errors found with test\n\n");

	control[0] = 0x00000032;

	Status = HeWrite(hDevice, control, 1 * sizeof(HE_DWORD), WriteIoStatus);
	HeWaitForIo(hDevice, WriteIoStatus); 

	test_data = 0x55555555;
	printf("Testing SDRAM with data pattern: %08lx\n",test_data);

	b = 0;
	for (i=0;i<no_of_blocks;i++) {
		Status = HeRead(hDevice, results, burst_length * sizeof(HE_DWORD), ReadIoStatus);
		HeWaitForIo(hDevice, ReadIoStatus); 

		for (a=0;a<burst_length;a++) {
			if (results[a] != test_data) {
				printf("Error!!!\n");
				printf("Address  %08lx\n",((i * burst_length) + a));
				printf("Expected %08lx\n",test_data);
				printf("Received %08lx\n",results[a]);
				errors++;
				getchar();
			}
		}
		b += burst_length;
	}
	if (errors == 0) printf("Tested %d locations successfully\n\n",b);
	else             printf("Errors found with test\n\n");

	control[0] = 0x00000033;

	Status = HeWrite(hDevice, control, 1 * sizeof(HE_DWORD), WriteIoStatus);
	HeWaitForIo(hDevice, WriteIoStatus); 

	test_data = 0xAAAAAAAA;
	printf("Testing SDRAM with data pattern: %08lx\n",test_data);

	b = 0;
	for (i=0;i<no_of_blocks;i++) {
		Status = HeRead(hDevice, results, burst_length * sizeof(HE_DWORD), ReadIoStatus);
		HeWaitForIo(hDevice, ReadIoStatus); 

		for (a=0;a<burst_length;a++) {
			if (results[a] != test_data) {
				printf("Error!!!\n");
				printf("Address  %08lx\n",((i * burst_length) + a));
				printf("Expected %08lx\n",test_data);
				printf("Received %08lx\n",results[a]);
				errors++;
				getchar();
			}
		}
		b += burst_length;
	}
	if (errors == 0) printf("Tested %d locations successfully\n\n",b);
	else             printf("Errors found with test\n\n");

	control[0] = 0x00000034;

	Status = HeWrite(hDevice, control, 1 * sizeof(HE_DWORD), WriteIoStatus);
	HeWaitForIo(hDevice, WriteIoStatus); 

	compare = 0;
	printf("Testing SDRAM with data pattern: ADDRESS\n");

	b = 0;
	for (i=0;i<no_of_blocks;i++) {
		Status = HeRead(hDevice, results, burst_length * sizeof(HE_DWORD), ReadIoStatus);
		HeWaitForIo(hDevice, ReadIoStatus); 

		for (a=0;a<burst_length;a++) {
			if (results[a] != compare) {
				printf("Error!!!\n");
				printf("Address  %08lx\n",((i * burst_length) + a));
				printf("Expected %08lx\n",compare);
				printf("Received %08lx\n",results[a]);
				errors++;
				getchar();
			}
			compare++;
		}
		b += burst_length;
	}
	if (errors == 0) printf("Tested %d locations successfully\n\n",b);
	else             printf("Errors found with test\n\n");

	control[0] = 0x00000038;

	Status = HeWrite(hDevice, control, 1 * sizeof(HE_DWORD), WriteIoStatus);
	HeWaitForIo(hDevice, WriteIoStatus); 

	compare = 0;
	printf("Testing SDRAM with data pattern: WALKING ONE\n");

	b = 0;
	for (i=0;i<no_of_blocks;i++) {
		Status = HeRead(hDevice, results, burst_length * sizeof(HE_DWORD), ReadIoStatus);
		HeWaitForIo(hDevice, ReadIoStatus); 

		for (a=0;a<burst_length;a++) {
			if (results[a] != compare) {
				printf("Error!!!\n");
				printf("Address  %08lx\n",((i * burst_length) + a));
				printf("Expected %08lx\n",compare);
				printf("Received %08lx\n",results[a]);
				errors++;
				getchar();
			}
			if (compare==0) compare = 1;
			else            compare = compare << 1;
		}
		b += burst_length;
	}
	if (errors == 0) printf("Tested %d locations successfully\n\n",b);
	else             printf("Errors found with test\n\n");

	if (errors == 0) loop++;
	else loop = 5;
}

if (errors == 0) {
	printf("Performed %d iterations of the SDRAM memory test\n",loop);
	printf("Exiting from program with 0 errors\n");
}
else {
	printf("Test finished with errors\n");
}
getchar();

/* Close down API and return */
Status = HeClose(&hDevice);
if(Status != HE_OK) error("Failed close..., exiting\n", Status);
/* Close down HSB device */
if (hsb_open) {
	Status = HeClose(&hsbDevice);
	if(Status != HE_OK) error("Failed close..., exiting\n", Status);
}

return(0);
}



void error(char *string, int Status)
{
	printf("Status %x\n", Status);
	printf("%s\n", string);
	Status = HeClose(&hDevice);
	getchar();
	exit(0);
}



void SendUserData(char *devname, HE_WORD Board, HE_BYTE slot, HE_BYTE Address, int Data)
{
HE_BYTE user[2];
HE_BYTE rec_data[3];
int reply;

	// Send user data
	user[0]=(HE_BYTE) Address;
	user[1]=(HE_BYTE) Data;

	Status = HeHSBSendMessage(hsbDevice, USER_WRITE, slot, &user[0], 2, 1000);
	if(Status != HE_OK) error("Write module failed, exiting\n", Status);
// read it back to check
    reply =readback_user(slot,rec_data,3,Address);
    if(reply!=Data)printf("error hsb readback failed with %x\n",reply); 

return;
}



/********************************************************************************/
/*																				*/
/*	Initialise_Host_HSB															*/
/*																				*/
/*	This function sets up the host HSB interface of each board in the system.	*/
/*																				*/
/********************************************************************************/
int Initialise_Host_HSB(char *dev_name, HE_WORD board)
{



	/* Check parameters */
	if ((board < 0) || (board > 15)) {
		printf("Error: board ID is out of range (0 to 15)\n");
		return(-1);
	}

	Status = HeOpen(dev_name, board, HSB, &hsbDevice);
	if (Status != HE_OK) return(1);


	return(0);
}



/********************************************************************************/
/*																				*/
/*	Search_For_Modules															*/
/*																				*/
/*	This function searches all slots for either HERON-FPGA modules or HERON-IO  */
/*	that have an FPGA fitted.													*/
/*																				*/
/********************************************************************************/
HE_BYTE Search_For_Modules(void)
{
int i,n;
int found;
char device[30];
HE_BYTE reply[30];
int mod_type;
char tmp[30];

/* Search for all HERON-FPGA or I/O modules on Board */
found = 0;
printf("Searching for HERON-FPGA modules with SDRAM memory\n");
for (Slot=1;Slot<5;Slot++) 
{
	mod_type = Test_If_Proc_Module(devname, Board, Slot);
	if (mod_type==-1) /*actually a non processor module with HSB*/
	{
		for (i=0;i<30;i++) reply[i] = 0;
		mod_type = Query_Module_Type(Slot,reply,30);
		if (mod_type < 0) exit(0);
		if ((mod_type == 2) || (mod_type == 4)) 
		{
			if (mod_type == 2) 
			{
				if (reply[1] >= 5) {
					/* A HERON-FPGA module has been found */
					printf("\nA HERON-FPGA%d has been found in slot ",reply[1]);
					printf("%d of board %d\n",Slot,Board);

					device[0] = '\0';
					strcpy(device,(char *)&reply[3]);
					Print_Device_Statistics(device);
					printf("Is this the module you want to use the example with?\n");
					gets(tmp);
					n = strlen(tmp);
					if (n == 1) {
						if ((tmp[0] == 'y') || (tmp[0] == 'Y')) {
							found=1;
							break;
						}
					}
				}
			}
		}
	}
}

if (!found) {
	printf("\nNo HERON-FPGA modules with SDRAM memory were found, exiting..\n");
	getchar();
	exit(0);
}

return(Slot);
}



/********************************************************************************/
/*																				*/
/*	Check_Module																*/
/*																				*/
/*	This function searches all slots for either HERON-FPGA modules or HERON-IO  */
/*	that have an FPGA fitted.													*/
/*																				*/
/********************************************************************************/
void Check_Module(HE_BYTE slot)
{
int i;
int found;
char device[30];
HE_BYTE reply[30];
int mod_type;

/* check for HERON-FPGA or I/O modules in Slot */
found = 0;
printf("Checking for HERON-FPGA and HERON-IO modules\n");
mod_type = Test_If_Proc_Module(devname, Board, slot);
if (mod_type==0) /*actually no module fitted*/
	{
	printf("Error: there is no module in slot %d of board %d\n",slot,Board);
	exit(0);
	}
if (mod_type==1)  /* module with processor */
	{
	printf("Error: the module in slot %d of board %d is a processor module\n",slot,Board);
	exit(0);
	}
if (mod_type==2)  /* module with no HSB */		
	{
	printf("Error: the module in slot %d of board %d does not have a serial bus\n",slot,Board);
	exit(0);
	}
if (mod_type==-1) /*actually a non processor module with HSB*/
{
	for (i=0;i<30;i++) reply[i] = 0;
	mod_type = Query_Module_Type(slot,reply,30);
	if (mod_type < 0) exit(0);
	if ((mod_type == 2) || (mod_type == 4)) 
	{
		if (mod_type == 2) 
		{
			/* A HERON-FPGA module has been found */
			printf("\nA HERON-FPGA%d has been found in slot ",reply[1]);
			printf("%d of board %d\n",slot,Board);
		}
		if (mod_type == 4) 
		{
			/* A HERON-IO with an FPGA has been found */
			printf("\nA HERON-IO%d has been found in slot ",reply[1]);
			printf("%d of board %d\n",slot,Board);
		}
		device[0] = '\0';
		strcpy(device,(char *)&reply[3]);
		Print_Device_Statistics(device);
		found=1;
	}
}

if (!found) 
	{
	printf("\nNo HERON-FPGA or HERON-IO modules were configured, exiting..\n");
	getchar();
	exit(0);
	}

return;
}



/********************************************************************************/
/*																				*/
/*	Test_If_Proc_Module															*/
/*																				*/
/*	This function is used to find out what kind of module is present in each	*/
/*  slot.																		*/
/*																				*/
/********************************************************************************/
int Test_If_Proc_Module(char *dev_name, HE_WORD board, int slot)
{
	HE_DWORD info[64];
	HE_DWORD status;

	info[0] = HE_Get_ModuleTypes;
	status  = HeGetBoardInfo(dev_name,board,info);
	if (status != HE_OK) printf("error from get board info %x\n",status);
		
	if (info[(5*(slot-1))+1] ==0) return(0); /* no module*/
	if (info[(5*(slot-1))+2] ==1) return(1); /* processor module*/
	if (info[(5*(slot-1))+3] ==0) return(2); /* has no serial bus*/

	return(-1);
}



/********************************************************************************/
/*																				*/
/*	readback_user																*/
/*																				*/
/*	This function is used to read back from the FPGA							*/
/*  slot.																		*/
/*																				*/
/********************************************************************************/
int readback_user(HE_BYTE slot, HE_BYTE *reply, int buffer_size, HE_BYTE user_addr)
{
	HE_BYTE  message_type;
	HE_DWORD bytes_read;
	HE_BYTE  send_data[5];

	send_data[0]=user_addr;
	send_data[1]=1;


	Status = HeHSBSendMessage(hsbDevice, USER_READ, slot, send_data, 2, 1000);
	Status = HeHSBReceiveMessage(hsbDevice, &message_type, slot, reply, buffer_size, &bytes_read, 1000);
	if (Status == HE_OK) 
	{
		if (message_type != USER_READ_REPLY) 
		{
			printf("Error: expected user read reply\n");
			return(-1);
		}
		else 
		{

			return(reply[0]);
		}
	}

	return(Status);
}



/********************************************************************************/
/*																				*/
/*	Query_Module_Type															*/
/*																				*/
/*	This function is used to find out what kind of module is present in each	*/
/*  slot.																		*/
/*																				*/
/********************************************************************************/
int Query_Module_Type(HE_BYTE slot, HE_BYTE *reply, int buffer_size)
{
	HE_BYTE  message_type;
	HE_DWORD bytes_read;


	Status = HeHSBSendMessage(hsbDevice, MODULE_TYPE_QUERY, slot, NULL, 0, 1000);
	Status = HeHSBReceiveMessage(hsbDevice, &message_type, slot, reply, buffer_size, &bytes_read, 1000);
	if (Status == 0) {
		if (message_type != MODULE_TYPE_REPLY) {
			printf("Error: expected module type query reply\n");
			return(-1);
		}
		else return(reply[0]);
	}

	return(0);
}



/********************************************************************************/
/*																				*/
/*	Print_Device_Statistices													*/
/*																				*/
/*	This function displays information about each FPGA device that is found.	*/
/*																				*/
/********************************************************************************/
void Print_Device_Statistics(char *dev_str)
{
	int  i,a,b,c,d;
	char family[13];
	char size[8];
	char package[8];
	char speed[4];
	char v2pro;
	char v4;
	char v4_sx;
	char v4_lx;
	char v4_fx;


	/* Derive the FPGA family from the device string */
	i = 0;
	a = 0;
	v2pro = 0;
	v4 = 0;
	v4_sx = 0;
	v4_lx = 0;
	v4_fx = 0;
	if ((dev_str[i] == '2') || (dev_str[i] == '4')) {
		if (dev_str[i] == '4') v4 = 1;
		family[a++] = dev_str[i++];
	}
	family[a++] = dev_str[i++];
	if (dev_str[i] == 'p') {
		// We have a Virtex-II Pro
		family[a++] = dev_str[i++];
		v2pro = 1;
	}
	if (v4 == 1) {
		// We have a Virtex-4
		if (dev_str[i] == 's') v4_sx = 1;
		if (dev_str[i] == 'l') v4_lx = 1;
		if (dev_str[i] == 'f') v4_fx = 1;
		family[a++] = dev_str[i++];
		family[a++] = dev_str[i++];
	}
	family[a] = '\0';

	/* Derive the FPGA size from the device string */
	b = 0;
	while ((dev_str[i] >= '0') && (dev_str[i] <= '9')) {
		size[b++] = dev_str[i++];
	}
	size[b] = '\0';

	/* Derive the FPGA package from the device string */
	c = 0;
	if (dev_str[i] == 'e') {
		family[a++] = dev_str[i++];
		family[a] = '\0';
	}
	else if (dev_str[i] == 'x') {
		family[a++] = dev_str[i++];
		family[a++] = dev_str[i++];
		family[a] = '\0';
	}
	while (dev_str[i] != '-') {
		package[c++] = dev_str[i++];
	}
	i++;
	package[c] = '\0';

	/* Derive the FPGA speed from the device string */
	d = 0;
	while (dev_str[i] != '\0') {
		speed[d++] = dev_str[i++];
	}
	speed[d] = '\0';

	if      (strcmp(family,"s")    == 0) strcpy(family,"Spartan\0");
	else if (strcmp(family,"2s")   == 0) strcpy(family,"Spartan-2\0");
	else if (strcmp(family,"sxl")  == 0) strcpy(family,"Spartan-XL\0");
	else if (strcmp(family,"v")    == 0) strcpy(family,"Virtex\0");
	else if (strcmp(family,"2v")   == 0) strcpy(family,"Virtex-2\0");
	else if (strcmp(family,"2vp")  == 0) strcpy(family,"Virtex-2 Pro\0");
	else if (strcmp(family,"ve")   == 0) strcpy(family,"Virtex-E\0");
	else if (strcmp(family,"4vfx") == 0) strcpy(family,"Virtex-4 FX\0");
	else if (strcmp(family,"4vsx") == 0) strcpy(family,"Virtex-4 SX\0");
	else if (strcmp(family,"4vlx") == 0) strcpy(family,"Virtex-4 LX\0");

	if (verbose) printf("Found device: \"%s\"\n",dev_str);
	if ((v2pro == 0) && (v4 == 0)) {
		printf("The FPGA on this module is a %s device with %sK gates, ",family,size);
	}
	else if (v2pro == 1) {
		if      (strcmp(size,"4")   == 0) printf("The FPGA on this module is a %s device with 1 Power PC,\n",family);
		else if (strcmp(size,"7")   == 0) printf("The FPGA on this module is a %s device with 1 Power PC,\n",family);
		else if (strcmp(size,"20")  == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"30")  == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"40")  == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"50")  == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"70")  == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"100") == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"125") == 0) printf("The FPGA on this module is a %s device with 4 Power PCs,\n",family);
	}
	else if (v4_fx == 1) {
		if      (strcmp(size,"12")  == 0) printf("The FPGA on this module is a %s device with 1 Power PC,\n",family);
		else if (strcmp(size,"20")  == 0) printf("The FPGA on this module is a %s device with 1 Power PC,\n",family);
		else if (strcmp(size,"40")  == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"60")  == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"100") == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
		else if (strcmp(size,"140") == 0) printf("The FPGA on this module is a %s device with 2 Power PCs,\n",family);
	}
	else if (v4_sx == 1) {
		if      (strcmp(size,"25")  == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"35")  == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"55")  == 0) printf("The FPGA on this module is a %s device,\n",family);
	}
	else if (v4_lx == 1) {
		if      (strcmp(size,"15")  == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"25")  == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"40")  == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"60")  == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"80")  == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"100") == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"160") == 0) printf("The FPGA on this module is a %s device,\n",family);
		else if (strcmp(size,"200") == 0) printf("The FPGA on this module is a %s device,\n",family);
	}
	if (verbose) printf("in a %s package\n",package);
	else if ((v2pro == 0) && (v4 == 0)) printf("\n");
	printf("The FPGA speed grade is -%s\n",speed);

	return;
}



/********************************************************************************/
/*																				*/
/*	Error																		*/
/*																				*/
/*	General Error Routine														*/
/*																				*/
/********************************************************************************/
void Error(HE_DWORD errorcode)
{
	char text[120];


	printf("In error routine\n");
	HeErr2Text(Status, text);
	printf("Failed - %s, OsError = %ld", text, errorcode);
	Print_Win32_Error(errorcode);
	printf("\n");

	Status = HeClose(&hDevice);
	exit(1);
}



/********************************************************************************/
/*																				*/
/*	Display_Help																*/
/*																				*/
/*	This function displays help information about this program.					*/
/*																				*/
/********************************************************************************/
void Display_Help()
{


	printf("\n            Heron-FPGA memory test\n\n"); 
	printf("        version 3.0 07/04/06 HUNT ENGINEERING\n\n");
	printf("Usage:  mem_test [options] \n\n\n");
	printf("Options:\n\n");
	printf("-v          Verbose mode\n");
	printf("-a          Ask me - don't use environmental variables\n");
	

	return;
}



/********************************************************************************/
/*																				*/
/*	Print_Win32_Error															*/
/*																				*/
/*	Win32 Error Function														*/
/*																				*/
/********************************************************************************/
void Print_Win32_Error(HE_DWORD errorcode)
{
#ifdef _WIN32			/* This level of error code is only on WIN32 */
						/* don't even compile it if not WIN32!*/
	LPVOID lpMsgBuf;

	if(errorcode != 0) {
		printf(" (%s)\n", strerror(errorcode));

		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
			NULL,
			errorcode, 
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language*/
			(LPTSTR) &lpMsgBuf,
			0,
			NULL);
		printf("Sys Error - %s", lpMsgBuf);
	}
#endif				/* end of WIN32 specific error codes*/
}

