SimpleCom.c

/*********************************************************************
 	 SimpleCom. 	Basic interactive CL serial communication.
 
	© Copyright 2013, BitFlow, Inc. All rights reserved.

	2012	BitFlow/Tim original entry

	$Author: steve $

	$Date: 2015/06/23 17:11:03 $

	$Id: SimpleCom.c,v 1.3 2015/06/23 17:11:03 steve Exp $
*********************************************************************/

/*==================================================================*/
/*
 ** 	For access to command line display.
 */
#include	<stdio.h>
#include 	<stdlib.h>
#include 	<string.h>
/*	
 **		For checking keypress 
 */
#include	<sys/time.h>
#include	<sys/types.h>
/*
 **		For access to Bitflow camera interface
 */
#include	"BFciLib.h"
#include	"BF_Karbon_field.h"
/*====================================================================*/
static tCIp sCIp = NULL;		/* device open token */
static int sExitAns;			/* program exit code */
/*--------------------------------------------------------------------*/
#define SHOW(x) { (void)printf x ; (void)fflush(stdout); }
#define ERR(x) 	{ SHOW(("ERR: ")); SHOW(x); }

static char *sArgv0 = NULL;		/* name of executable */
static void ShowHelp(void)
{
	SHOW(("%s \n\n", sArgv0));
	SHOW(("Simple interactive CL serial comm.\n"));
	SHOW(("Opens VFGx and initializes if needed.\n\n"));
	SHOW(("Default settings are 9600 baud, 1 stop bit, no parity.\n"));
	SHOW(("\t-h	Show this message and exit.\n"));
	SHOW(("\t-x	VFG number to open.\n"));
	SHOW(("\t-s D P S B	Serial settings. Data bits, parity. stopbits, baud.\n"));
}

/*=====================================================================*/
static int CheckForKeyboardInput(char *buff)
/*
** 	Return 0 if no input available from stdin, 1 else
**
**	Note: console needs a newline in order to post input.
*/
{
	fd_set exceptfds, readfds, writefds;
	struct timeval tv;
	int ans;

	FD_ZERO(&exceptfds);
	FD_ZERO(&readfds);
	FD_ZERO(&writefds);
	FD_SET(fileno(stdin), &readfds);
	(void)memset(&tv, '\0', sizeof(struct timeval));

	ans = select(1, &readfds, &writefds, &exceptfds, &tv);

	if ((ans == 1) && FD_ISSET(fileno(stdin), &readfds))
	{
		//get the line
		(void)fgets(buff, 1024, stdin);
		return (1);
	}

	return (0);
}

/*---------------------------------------------------------------------*/
void WriteMsg(char *msg)
{
	tCIRC circ;
	int len = strlen(msg);
	char CR = '\r';


	//need to replace LF with CR
	msg[len - 1] = CR;

	len = strlen(msg);

	circ = CiCLwriteBytes(sCIp, len, (tCIU8 *) msg);
	if (circ != kCIEnoErr)
	{

		ERR(("CiCLwriteByes gave '%s'\n", CiErrStr(circ)));
		sExitAns = 1;
		return;
	}

}

void ReadMsg(char *buff, int buffsize)
{
	tCIRC circ;
	tCIU32 size = 0;

	circ = CiCLreadBytes(sCIp, buffsize - 1, &size, (tCIU8 *) buff);
	buff[size] = '\0';
	if (circ != kCIEnoErr)
	{
		ERR(("CiCLreadByes gave '%s'\n", CiErrStr(circ)));
		sExitAns = 1;
		return;
	}
}

int OpenAndInit(int bd, int flag)
{
	tCIU32 circ;
	tCIU32 init_state;

	circ = CiVFGopen(bd, flag, &(sCIp));
	if (circ != kCIEnoErr)
	{
		ERR(("CiVFGopen gave '%s'\n", CiErrStr(circ)));
	}

	//Check if the board needs fw and initialze.
	//Serial com will not work if fw is not loaded.
	circ = CiVFGqueryState(sCIp, &init_state);
	if (circ != kCIEnoErr)
	{
		ERR(("CiVFGqueryState gave '%s'\n", CiErrStr(circ)));
		return circ;
	}

	if (init_state == kCIBQ_needsFirmware)
	{
		SHOW(("Initializing...\n"))
			circ = CiVFGinitialize(sCIp, kBFDEFAULTCFGFILE);
		if (circ != kCIEnoErr)
		{
			ERR(("CiVFGinitialize gave '%s'\n", CiErrStr(circ)));
			return circ;
		}
	}

	return circ;

}

int Close(void)
{
	tCIU32 circ;

	circ = CiCLterm(sCIp);
	if (circ != kCIEnoErr)
	{
		ERR(("CiCLterm gave '%s'\n", CiErrStr(circ)));
		return circ;
	}


	circ = CiVFGclose(sCIp);
	if (circ != kCIEnoErr)
	{
		ERR(("CiVFGclose gave '%s'\n", CiErrStr(circ)));
		return circ;
	}

	SHOW(("Closed board. Goodbye.\n"));

	return 0;
}

int main(int argc, char **argv)
{

	int x = 0, y = 1, z = 0;	//default to VFG 0(x=0) with flag = 1.
	int baud9600 = 1, dataBits = 8, parity = 0, stopBits = 1;	//baud rate equal to 9600*baud9600. 
	char *str;
	tCIRC circ;
	tCIU32 avail;
	tCIU8 buff[1024];
	tCIU8 msg[1024];
	tCIU8 exitcode[2];

	sArgv0 = *argv;

	//Parse arguments
	argv += 1;
	argc -= 1;					/*Skip the program name */

	while (argc-- > 0)
	{
		str = *argv++;
		if (str[0] != '-')
		{
			ERR(("Do not know '%s' arg\n", str));
			ShowHelp();
			exit(1);
		}
		switch (str[1])
		{
		case 'h':
			ShowHelp();
			exit(0);
		case 'x':
			x = atoi(*argv);
			argv += 1;
			argc -= 1;
			break;
		case 's':
			dataBits = atoi(*argv);
			argv += 1;
			argc -= 1;
			parity = atoi(*argv);
			argv += 1;
			argc -= 1;
			stopBits = atoi(*argv);
			argv += 1;
			argc -= 1;
			baud9600 = atoi(*argv);
			argv += 1;
			argc -= 1;
			break;
		default:
			ERR(("Invalid input argument '%s'\n", str));
			ShowHelp();
			break;

		}
	}


	SHOW(("Opening board...\n"));
	//Check if the board is initialized and init if needed.
	circ = OpenAndInit(x, y);

	//Initialize serial interface
	circ = CiCLinit(sCIp, dataBits, parity, stopBits, baud9600);
	if (circ != kCIEnoErr)
	{
		ERR(("CiCLinit gave '%s'\n", CiErrStr(circ)));
	}

	//for comparison
	strncpy((char *)exitcode, "x\r", 2);

	SHOW(("Ready for Serial write and read\n"));
	SHOW(("Press x to exit\n"));

	while (!circ)
	{
		z = CheckForKeyboardInput((char *)msg);
		if (z)
		{
			//SHOW(("%s \n", msg));
			if (!(strncmp((char *)msg, (char *)exitcode, 1)))
			{
				break;
			}

			WriteMsg((char *)msg);
		}
		else
		{

			circ = CiCLgetBytesAvail(sCIp, &avail);

			if (avail != 0)
			{
				ReadMsg((char *)buff, sizeof(buff));
				SHOW(("%s", buff));
			}
		}
	}

	sExitAns = Close();

	return sExitAns;
}

/*==================================================================*/
/*
	$Log: SimpleCom.c,v $
	Revision 1.3  2015/06/23 17:11:03  steve
	Ready for ndif and cxp2

	Revision 1.2  2015-01-15 17:24:40  steve
	Cyton available

	Revision 1.1  2013-03-03 18:58:11  steve
	Ready w/CXP

*/