/******************************************************************************\
**	genericQSPI2.c
**	
**	First release:			01/22/2001
**	Update release:			10/10/2002
*****************************************************************************
**	
**	Developed by:	Thomas P. Sullivan
**	tpsully@persistor.com - http://www.persistor.com
**	Copyright (C) 2000 Persistor Instruments Inc.	All rights reserved.
**	
*****************************************************************************
** 
** Copyright and License Information
** 
** Persistor Instruments Inc. (hereafter, PII) grants you (hereafter,
** Licensee) a non-exclusive, non-transferable license to use the software
** source code contained in this single source file with hardware products
** sold by PII. Licensee may distribute binary derivative works using this
** software and running on PII hardware products to third parties without
** fee or other restrictions.
** 
** PII MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
** SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
** IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
** OR NON-INFRINGEMENT. PII SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
** LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE OR
** ITS DERIVATIVES.
** 
** By using or copying this Software, Licensee agrees to abide by the
** copyright law and all other applicable laws of the U.S. including, but
** not limited to, export control laws, and the terms of this license. PII
** shall have the right to terminate this license immediately by written
** notice upon Licensee's breach of, or non-compliance with, any of its
** terms. Licensee may be held legally responsible for any copyright
** infringement or damages resulting from Licensee's failure to abide by
** the terms of this license. 
**	
**	
*****************************************************************************
**	
**	This program demonstrates the use of the QSPI in the Persistor
**	Instruments CF2.  A structure is set up to transfer 2 16-bit words
**	through the QSPI.  
**	
**	10/01/01 - Modification to support two SPI devices 
**	
**	10/01/01 - Split source files
**	
**	08/08/02 - Modified for the CF2 to get around an issue with the QSPI
**             and PicoDOS 2.27.
**	
**	10/10/02 - Made changes (cosmetic) before posting on the web
**	
\******************************************************************************/

#include	<cfxbios.h>		// Persistor BIOS and I/O Definitions
#include	<cfxpico.h>		// Persistor PicoDOS Definitions

#include	<stat.h>		// CF1 POSIX-like File Status Definitions
#include	<fcntl.h>		// CF1 POSIX-like File Access Definitions
#include	<unistd.h>		// CF1 POSIX-like UNIX Function Definitions
#include	<dirent.h>		// CF1 POSIX-like Directory Access Definitions
#include	<termios.h>		// CF1 POSIX-like Terminal I/O Definitions
#include	<dosdrive.h>	// CF1 DOS Drive and Directory Definitions

#include	<assert.h>
#include	<ctype.h>
#include	<errno.h>
#include	<float.h>
#include	<limits.h>
#include	<locale.h>
#include	<math.h>
#include	<setjmp.h>
#include	<signal.h>
#include	<stdarg.h>
#include	<stddef.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<time.h>

#include	<dirent.h>		// PicoDOS POSIX-like Directory Access Defines
#include	<dosdrive.h>	// PicoDOS DOS Drive and Directory Definitions
#include	<fcntl.h>		// PicoDOS POSIX-like File Access Definitions
#include	<stat.h>		// PicoDOS POSIX-like File Status Definitions
#include	<termios.h>		// PicoDOS POSIX-like Terminal I/O Definitions
#include	<unistd.h>		// PicoDOS POSIX-like UNIX Function Definitions

#include "exchange.h"

//	Our slot i.e. the pointer to the structure that will contain most of what we need
//	to perform a QSPI transfer to a given device/chip select
static QPB		*QPB_Slot1 = NULL;		//NULL to start
static QPB		*QPB_Slot2 = NULL;		//NULL to start

//	Lets create a device driver spec for our part...the structure usually holds information
//	about a particular part.
static QPBDev MyDevStructure1 = 
{
	NMPCS0,				// qslot			our qspi slot (non-multiplexed connection to PCS3 -- tps)
	"MAX147\0",			// devName			C string with device name (15 max)
	2000000,			// maxBaud			maximum baud rate in Hz for device
	16,					// bits				Bits Per Transfer
	iaHighSCK,			// clockPolar		SPI Clock Polarity (iaHighSCK,iaLowSCK) NOTE: Device dependent...check!
	captFall,			// clockPhase		SPI Clock Phase (captLead/captFall)		NOTE: Device dependent...check!
	false,				// contCSMulti		Continue CS assert between mult xfrs
	true,				// autoTiming		Auto adjust timing to clock flag
	1000000,			// psDelaySCK		Min. Delay Before SCK (picoSecs). A million is a microsecond
	1000000,			// psDelayTXFR		Min. Delay After Transfer
	0,					// *rcvData			pointer to received data buffer (filled in by QPBInitSlot)
	0					// xfrCount			words transferred
};

static QPBDev MyDevStructure2 = 
{
	NMPCS1,				// qslot			our qspi slot (non-multiplexed connection to PCS2 -- tps)
	"CS5509\0",			// devName			C string with device name (15 max)
	100000,				// maxBaud			maximum baud rate in Hz for device
	8,					// bits				Bits Per Transfer
	iaHighSCK,			// clockPolar		SPI Clock Polarity (iaHighSCK,iaLowSCK) NOTE: Device dependent...check!
	captFall,			// clockPhase		SPI Clock Phase (captLead/captFall)		NOTE: Device dependent...check!
	false,				// contCSMulti		Continue CS assert between mult xfrs
	true,				// autoTiming		Auto adjust timing to clock flag
	1000000,			// psDelaySCK		Min. Delay Before SCK (picoSecs). A million is a microsecond
	1000000,			// psDelayTXFR		Min. Delay After Transfer
	0,					// *rcvData			pointer to received data buffer (filled in by QPBInitSlot)
	0					// xfrCount			words transferred
};

//  *********************************
//  M   M     A      III    N   N
//  MM MM    A A      I     NN  N
//  M M M   A   A     I     NN  N
//  M   M   AAAAA     I     N N N
//  M   M   A   A     I     N N N
//  M   M   A   A     I     N  NN
//  M   M   A   A    III    N   N
//  *********************************

int main(int argc, char **argv)
	{
	ushort	i;
	char	c = '1';
//	To exit
	bool bExit;
//	Array of ints to hold the data we will transmit using the QSPI to our device
	ushort usCommand1[16] = {0xAAAA};
	ushort usCommand2[16] = {0x5555};
//	Array of ints to hold the data we will get back from a QSPI transaction
	ushort usData1[16] = {0};
	ushort usData2[16] = {0};

	// Identify the progam and build
	printf("\nProgram: %s: %s %s \n", __FILE__, __DATE__, __TIME__);
	// Identify the device and its firmware
	printf("Persistor CF1 SN:%ld   BIOS:%d.%d   PicoDOS:%d.%d\n",
		BIOSGVT.CF1SerNum, BIOSGVT.BIOSVersion, BIOSGVT.BIOSRelease, 
		BIOSGVT.PICOVersion, BIOSGVT.PICORelease);
	// Identify the arguments
	printf("\n%d Arguments:\n", argc);
	for (i = 0; i < argc; i++)
		printf("  argv[%d] = \"%s\"\n", i, argv[i]);

	cprintf("\n");
	cprintf("\n This is a generic QSPI program which has been updates to support");
	cprintf("\n two different SPI devices.  By default the devices are on PCS3 and");
	cprintf("\n PCS2.  This can be changed easily in the QPBDev structure above.");
	cprintf("\n");

//	Just in case you didn't see me make this NULL above
	QPB_Slot1 = NULL;
	QPB_Slot2 = NULL;

	bExit = false;
	while((!SCIRxBreak(2)) && (!bExit))	//Send a break or hit 'Q' to exit
	{
		cprintf("");
		QRchar("Press a 1, 2, 3 or Q (Quit)\n", "%c", true,&c, 0, true);
		switch(c)
		{
			case '1':
				//NOTE:	Only use QPBInitSlot on one device and then free it.  This is because of an issue
				//		in PicoDOS 2,.27.  This will be fixed in a future PicoDOS release.
				QPB_Slot1 = QPBInitSlot(&MyDevStructure1);	
				cprintf("\n\nSending four 16 bit words to device 1 through the QSPI\n");
				usCommand1[0] = 0xAAAA;	//Data (usually commands AND data) to send to the device
				usCommand1[1] = 0x5555;	//(NOTE: This tends to be specific with devices like the MAX146/147
				usCommand1[2] = 0xFFFF;	//and please also note that sometimes you won't get data back
				usCommand1[3] = 0x0000;	//in the corresponding array member but you will in the next)/
				ExchangeGeneric(QPB_Slot1, usCommand1, 4, usData1);
				cprintf("usData1[0] = [%u]\n",usData1[0]);	//Data we got back from the device
				cprintf("usData1[1] = [%u]\n",usData1[1]);
				cprintf("usData1[2] = [%u]\n",usData1[2]);
				cprintf("usData1[3] = [%u]\n",usData1[3]);
				//NOTE:	Only use QPBInitSlot on one device and then free it.  This is because of an issue
				//		in PicoDOS 2,.27.  This will be fixed in a future PicoDOS release.
				QPBFreeSlot(&MyDevStructure1);
				QPB_Slot1 = NULL;	//Just to be sure ExchangeGeneric doesn't try to use it after we free it.
				
			break;
			case '2':
				//NOTE:	Only use QPBInitSlot on one device and then free it.  This is because of an issue
				//		in PicoDOS 2,.27.  This will be fixed in a future PicoDOS release.
				QPB_Slot2 = QPBInitSlot(&MyDevStructure2);
				cprintf("\n\nSending four 16 bit words to device 2 through the QSPI\n");
				usCommand2[0] = 0xAAAA;	//Data (usually commands AND data) to send to the device
				usCommand2[1] = 0x5555;
				usCommand2[2] = 0xFFFF;
				usCommand2[3] = 0x0000;
				ExchangeGeneric(QPB_Slot2, usCommand2, 4, usData2);
				cprintf("usData2[0] = [%u]\n",usData2[0]);	//Data we got back from the device
				cprintf("usData2[1] = [%u]\n",usData2[1]);
				cprintf("usData2[2] = [%u]\n",usData2[2]);
				cprintf("usData2[3] = [%u]\n",usData2[3]);
				//NOTE:	Only use QPBInitSlot on one device and then free it.  This is because of an issue
				//		in PicoDOS 2,.27.  This will be fixed in a future PicoDOS release.
				QPBFreeSlot(&MyDevStructure2);
				QPB_Slot2 = NULL;	//Just to be sure ExchangeGeneric doesn't try to use it after we free it.

			break;
			case '3':
				cprintf("\n\nYour command here!\n");
			break;
			case 'Q':
				cprintf("\n\nQuit\n");
				bExit = true;
			break;
			default:
			break;
		}
	}

	// Various exit strategies
//	BIOSReset();			// full hardware reset
//	BIOSResetToPBM();		// full reset, but stay in Pesistor Boot Monitor
	BIOSResetToPicoDOS();	// full reset, but jump to 0xE10000 (PicoDOS)
	return 0;

	}	//____ main() ____//


