/* --COPYRIGHT--,BSD
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/

#include "console.h"									// All other required source files are declared here

#define CONSOLE_VERSION "2.0.0"

// MACROS
#define h2a(d) ((d>9)?(d-10+'A'):(d+'0'))

// File Constants
const char *scr_speed_norm_strings[16]={"2.5  ","5    ","10   ","16.6 ","20   ","50   ","60   ","100  ","400  ","1200 ","2400 ","4800 ","7200 ","14400"," 19200","38400"};
const char *scr_adc2speed_norm_strings[4]={" 10","100","400","800"};
const char *scr_adc2ref_norm_strings[5]={"INT   ","AIN0/1","AIN2/3","AIN4/5","AVDD "};
const char *scr_pga_norm_strings[8]={"1  ","2  ","4  ","8  ","16 ","32 ","64 ","128"};
const char *scr_gpio_norm_strings[8]={"AIN03  ", "AIN04  ", "AIN05  ", "AIN06  ", "AIN07  ", "AIN08  ", "AIN09  ", "AINCOM "};
const char scr_ch_strings[][2]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
const char *scr_refp_norm_strings[5]={"INT ", "AIN0", "AIN2", "AIN4", "AVDD"};
const char *scr_refn_norm_strings[5]={"INT ", "AIN1", "AIN3", "AIN5", "AVSS"};
const char *scr_filter_norm_strings[5]={"SINC1", "SINC2", "SINC3", "SINC4", "FIR  "};
const char *scr_mux_norm_strings[16]={"AIN0  ","AIN1  ","AIN2  ","AIN3  ","AIN4  ","AIN5  ","AIN6  ","AIN7  ","AIN8  ","AIN9  ","AINCOM","TEMP  ","AVDD/4","DVDD/4","TDAC  ","NOCONN"};
const char *scr_idacdir_norm_strings[12]={"AIN0  ","AIN1  ","AIN2  ","AIN3  ","AIN4  ","AIN5  ","AIN6  ","AIN7  ","AIN8  ","AIN9  ", "AINCOM", "NOCONN"};
const char *scr_idacmag_norm_strings[11]={"OFF","50uA", "100uA", "250uA", "500uA", "750uA", "1000uA", "1500uA", "2000uA", "2500uA", "3000uA"};
const char *ADS126xRegisterNames[ADS126x_NUM_REG]={"ID","POWER","INTERFACE","MODE0","MODE1","MODE2","INPMUX","OFCAL0","OFCAL1","OFCAL2","FSCAL0","FSCAL1","FSCAL2","IDACMUX","IDACMAG","REFMUX","TDACP","TDACN","GPIOCON","GPIODIR","GPIODAT","ADC2CFG","ADC2MUX","ADC2OFC0","ADC2OFC1","ADC2FSC0","ADC2FSC1"};

// Global variables
char outString[MAX_CONSOLE_STR_LEN] = "";		//Holds console output string
char tempString[MAX_CONSOLE_STR_LEN / 4] = "";	//Used to build console output string

// Global flags set by events
extern volatile uint8_t g_bCDCDataReceived_event;

//Internal function prototypes (not declared in "console.h")
void run_calibration(char c);
void set_bias(char c);
void set_chop(char c);
void set_conv_mode(char c);
void set_datarate(char c);
void set_exc(char x, char p2);					//Use with console (prints to console)
void set_filter(char c);
void set_gpio(char channel, char param1, char param2);
void set_idac(char p1, char p2, char p3);
void set_mux(char c, char d);
void set_pga(char g);
void set_register(char addr1, char addr2, char dat1, char dat2);
void set_vref(char c, char d);

//Print Console Info
void show_version(void);
void adc2(char cmd, char p1, char p2);
void adc2_datarate(char p1,char p2);
char adc2_startstop(char p1,char p2);
void adc2_reference(char p1,char p2);
void adc2_pga(char p1,char p2);
void adc2_mux(char p1,char p2);
void printHex(signed long d, int i);



void console(char *strbuf)
{
	/* This code section establishes what is seen as the console prompt.
	Depending on the options of the part, various settings could be used as options

		a – ADC2
			ae<0..4> – internal reference, AIN0/1, AIN2/3, AIN4/5, AVDD
			am – input mux
				amp<0..e> – positive input channel
				amn<0..e> – negative input channel
			ak – show calibration registers
				ak<g/o> – start system gain/offset calibration
				akos – start self offset calibration
			ap<0..7> – PGA setting
			ar<0..3> – data rate
			as<1/0> – start/stop ADC2

		b<1/0> – bias on/off
		c<1/0> – conversion mode pulse/continuous
		d – data read
		e<1/0> – internal reference on/off
			ep<0..4> – positive reference input
			en<0..4> – negative reference input
		f<0..4> – filter type
		g<0..7><1/0> – GPIO data channel <0..7> 1/0
			g<0..7>ei – enable channel <0..7> as input
			g<0..7>eo – enable channel <0..7> as output
			g<0..7>d – disable channel
		h =======================================
		i<1..2><0..b><0..a> – IDAC <1..2> mux input <0..b> magnitude <0..a>
		j =======================================
		k – show calibration registers
			k<g/o> – start system gain/offset calibration
			kos – start self offset calibration
		l =======================================
		m – input mux
			mp<0..f> – positive input channel
			mn<0..f> – negative input channel
		n =======================================
		o =======================================
		p<0..7> - PGA setting
		q – query settings
		q0 – readback register configurations
		qr – query settings in raw format (same as commands)
		r<0..f> – data rate
		rs - reset
		s<1/0> – stream on/off
		t =======================================
		u =======================================
		v – show version
		w =======================================
		x<0..2> – AC excitation selection: "OFF", "+", "-"
			xs<0..f> – sample 2^<0..f> data points before switching excitation voltage
		y =======================================
		z =======================================

	The various options will need to be defined depending on the options of the ADC. */
	

	switch(tolower(strbuf[0]))
	{
		case 'a':
			adc2(tolower(strbuf[1]), tolower(strbuf[2]), tolower(strbuf[3]));
			break;

		case 'b': // internal reference bias
			set_bias(tolower(strbuf[1]));
			break;

		case 'c': // conversion control
			if (tolower(strbuf[1] == 'c'))
				set_conv_mode(tolower(strbuf[2]));
			else
				set_chop(tolower(strbuf[1]));
			break;

		case 'e': //internal reference on/off
			set_vref(tolower(strbuf[1]), tolower(strbuf[2]));
			break;

		case 'f': //digital filter
			set_filter(tolower(strbuf[1]));
			break;

		case 'g':
			set_gpio(tolower(strbuf[1]), tolower(strbuf[2]), tolower(strbuf[3]));
			break;

		case 'i':
			set_idac(tolower(strbuf[1]), tolower(strbuf[2]), tolower(strbuf[3]));
			break;

		case 'm':
			set_mux(tolower(strbuf[1]), tolower(strbuf[2]));
			break;

		case 'p': // conversion control
			set_pga(tolower(strbuf[1]));
			break;

		case 'q': // query
			show_parms(tolower(strbuf[1]));
			break;

		case 'r': // data rate or DUT reset
			set_datarate(tolower(strbuf[1]));
			break;

		case 'v': // version
			show_version();
			break;

		case 'w': // WREG command
			set_register(tolower(strbuf[1]),tolower(strbuf[2]),tolower(strbuf[3]),tolower(strbuf[4]));
			break;

		case 'x': // internal reference bias
			set_exc(tolower(strbuf[1]),tolower(strbuf[2]));
			break;

		case 'y': // demo case
			run_adc2_demo(tolower(strbuf[1]));
			break;

		case 'z': // demo case
			run_demo(tolower(strbuf[1]));
			break;

		case 32: //Space symbol: " "
			strcpy(outString,"ADS126x>");
			print2Console(outString);
			//break;

		default:
			printError();
			break;
	}
}


/* Version info is printed to console. */
void show_version(void)
{
	strcpy(outString,"ADC Console ");
	strcat(outString, CONSOLE_VERSION);
	strcat(outString, " (c)2014 Texas Instruments");
	strcat(outString,"\r\n");

	print2Console(outString);
}

void print2Console(char *outString)
{
	assert(strlen(outString) <= MAX_CONSOLE_STR_LEN);					// Calls abort() if expression is FALSE
	cdcSendDataWaitTilDone((BYTE*)outString, strlen(outString), 0, 0);	// Use CDC interface to print to console
}

/* Print this string to console when an error occurs */
void printError(void)
{
	strcpy(outString,"\r\nData Entry Error\r\n");
	print2Console(outString);
}

void printCommandPrompt(void)
{
	strcpy(outString,"\r\nADS126x>");
	print2Console(outString);
}

void PressANYkeytoContinue(int output)
{
	if(output)
	{
		//Print Instructions to Console
		strcpy(outString,"PRESS ANY KEY TO CONTINUE...");
		print2Console(outString);
	}

	//Wait for User Input
	g_bCDCDataReceived_event = FALSE;
	while(!g_bCDCDataReceived_event);

	//Get input and clear event flag
	cdcReceiveDataInBuffer((uint8_t*)outString,64,CDC0_INTFNUM);
	g_bCDCDataReceived_event = FALSE;

}




// TODO: Clean functions below

void printhex(signed long d, int i)
{
	if (i==1)
		strcpy(outString,"\r\n");
	print2Console(outString);
	hex2asc(&d,8,2,outString,1);
	print2Console(outString);
}


void set_datarate(char c)
{
	int dRate;
	char temp_str[2] = {c,'\0'};
	char spd = strtoul(temp_str,NULL,16);
	unsigned char regMODE2;

	// the DataRate value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(MODE2, 1, &regMODE2);
	dRate = regMODE2 & DR_MASK;

	// If no data is sent, print out current value
	if (c == NULL)
	{
		strcpy(outString,"Data Rate = ");
		strcat(outString,scr_speed_norm_strings[dRate]);
		strcat(outString,"\r\n");
		print2Console(outString);
		return;
	}
	else if(spd < 16)
	{
		regMODE2 = (regMODE2 & 0xF0) | spd;
		ADS126xWriteRegister(MODE2, 1, &regMODE2);
		strcpy(outString,"Data Rate = ");
		strcat(outString,scr_speed_norm_strings[spd]);
		strcat(outString,"\r\n");
		print2Console(outString);
		return;
	}
	else
		printError();
}



void set_idac(char p1, char p2, char p3)
{
		char p3str[2]={p3,'\0'};
		char p3hex = strtoul(p3str,NULL,16);

		unsigned char Temp[2];

		// the Vref value is only part of the register, so we have to read it back
		// and massage the new value into it
		ADS126xReadRegister(IDACMUX, 0x02, Temp);

		// If no data is sent, print out current value
		switch (p1)
		{
			case NULL:
			{
				strcpy(outString,"\r\nIDAC1=");
				strcat(outString,scr_idacmag_norm_strings[Temp[1]&0x0F]);
				strcat(outString,"@");
				strcat(outString,scr_idacdir_norm_strings[Temp[0]&0x0F]);
				strcat(outString,"\r\nIDAC2=");
				strcat(outString,scr_idacmag_norm_strings[(Temp[1]&0xF0)>>4]);
				strcat(outString,"@");
				strcat(outString,scr_idacdir_norm_strings[(Temp[0]&0xF0)>>4]);
				print2Console(outString);
				break;
			case '1':
			case '2':
			{
				switch (p2)
				{
					case 'd':
					{
						if(p3hex<12)
						{
							Temp[0]=(Temp[0]&~(0xF<<((p1=='2')?4:0))) | p3hex<<((p1=='2')?4:0);
							ADS126xWriteRegister(IDACMUX, 2, Temp);
						}
						else
							printError();
					}
					break;
					case 'm':
					{
						if(p3hex<11)
						{
							Temp[1]=(Temp[1]&~(0xF<<((p1=='2')?4:0))) | p3hex<<((p1=='2')?4:0);
							ADS126xWriteRegister(IDACMUX, 2, Temp);
						}
						else
							printError();
					}
					break;
					default:
						printError();
						break;
				}
			}
			break;
			default:
				printError();
				break;
			}
		}

}

void set_pga(char g)
{
	int gain = (int) g - 48;
	int pga;

	unsigned char Temp;

	// the Vref value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(MODE2, 0x01, &Temp);
	pga = (Temp & GAIN_MASK) >> 4;

	// If no data is sent, print out current value
	if(NULL == g)
	{
			strcpy(outString,"PGA1 Gain =");
			strcat(outString,scr_pga_norm_strings[pga]);
			strcat(outString,"\r\n");
			print2Console(outString);
	}
	else
	{
		if (gain<8)
		{
			Temp=Temp &0x0F | gain << 4;
			ADS126xWriteRegister(MODE2, 1, &Temp);
		}
		else
			printError();
	}
}

void adc2(char cmd, char p1, char p2)
{
	switch(cmd)
	{
	case 'r':
		adc2_datarate(p1,p2);
		break;
	case 's':
		adc2_startstop(p1,0xFF);
		break;
	case 'e':
		adc2_reference(p1,p2);
		break;
	case 'p':
		adc2_pga(p1,p2);
		break;
	case 'm':
		adc2_mux(p1,p2);
		break;
	default:
		printError();
		break;
	}
}

void set_register(char addr1, char addr2, char dat1, char dat2)
{
	char addr_str[3] = {addr1, addr2, '\0'};
	uint8_t RegAddr = strtoul(addr_str, NULL, 16);

	char data_str[3] = {dat1, dat2, '\0'};
	uint8_t RegData = (uint8_t) strtoul(data_str, NULL, 16);

	//WREG Command
	ADS126xWriteRegister(RegAddr, 1, &RegData);

	strcpy(outString,"WREG to ");
	strcat(outString,ADS126xRegisterNames[RegAddr]);
	strcat(outString," = 0x");
	hex2asc(&RegData,2,2,tempString,1);
	strcat(outString,tempString);
	strcat(outString,"\r\n");
	print2Console(outString);

}

void adc2_datarate(char p1,char p2)
{
	int rate = (int) p1 - 48;

	unsigned char Temp;

	// the Vref value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(ADC2CFG, 0x01, &Temp);

	// If no data is sent, print out current value
	if(p1==NULL)
	{
			strcpy(outString,"\r\nADC2 Speed=");
			strcat(outString,scr_adc2speed_norm_strings[(Temp&0xC0)>>6]);
			print2Console(outString);
	}
	else
	{
		if (rate<4)
		{
			Temp=Temp&~0x3F | rate << 6;
			ADS126xWriteRegister(ADC2CFG, 1, &Temp);
		}
		else
			printError();
	}
}

char adc2_startstop(char p1,char p2){
	static char status = 0x00;

	if(p1=='1'&&p2==0xFF){
		ADS126xSendADC2StartCommand();
		status=1;
	}else if(p1=='0'&&p2==0xFF){
		ADS126xSendADC2StopCommand();
		status=0;
	}else if(p1==NULL&&p2==0xFF){
		strcpy(outString,"\r\nADC2 Status=");
		switch(status){
		case 1:
			strcat(outString,"Started");
			break;
		case 0:
			strcat(outString,"Stopped");
			break;
		default:
			printError();
			break;
		}
		print2Console(outString);
	}else if(p1==NULL&&p2==NULL){
		return status;
	}else{
		printError();
	}
return 0;
}

void adc2_reference(char p1,char p2){
	int ref = (int) p1 - 48;

	unsigned char Temp;

	// the Vref value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(ADC2CFG, 0x01, &Temp);

	// If no data is sent, print out current value
	if(p1==NULL){
			strcpy(outString,"\r\nADC2 Reference=");
			strcat(outString,scr_adc2ref_norm_strings[(Temp&0x38)>>3]);
			print2Console(outString);
	} else {
		if (ref<5) {
			Temp=Temp&~0x38 | ref << 3;
			ADS126xWriteRegister(ADC2CFG, 1, &Temp);
		} else {
			printError();
		}
	}
}

void adc2_pga(char p1,char p2){
	int pga = (int) p1 - 48;

	unsigned char Temp;

	// the Vref value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(ADC2CFG, 0x01, &Temp);

	// If no data is sent, print out current value
	if(p1==NULL){
			strcpy(outString,"\r\nADC2 PGA=");
			strcat(outString,scr_pga_norm_strings[(Temp&0x07)]);
			print2Console(outString);
	} else {
		if (pga<8) {
			Temp=Temp&~0x07 | pga ;
			ADS126xWriteRegister(ADC2CFG, 1, &Temp);
		} else {
			printError();
		}
	}
}

void adc2_mux(char p1,char p2){
	char temp_str[2]={p2,'\0'};
	char ref = strtoul(temp_str,NULL,16);

	unsigned char Temp;
	unsigned char muxn_val, muxp_val;

	// the Vref value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(ADC2MUX, 0x01, &Temp);
	muxp_val = (Temp & 0xF0) >> 4;
	muxn_val = Temp & 0x0F;

	// If no data is sent, print out current value
	switch (p1){
		case NULL:{
			strcpy(outString,"\r\nADC2 MUXP=");
			strcat(outString,scr_mux_norm_strings[muxp_val]);
			strcat(outString,"\r\nADC2 MUXP=");
			strcat(outString,scr_mux_norm_strings[muxn_val]);
			print2Console(outString);
			break;
		case 'p': {
			if(ref<16){
				Temp = Temp & 0xf;
				Temp = Temp | (ref<<4);
				ADS126xWriteRegister(ADC2MUX, 1, &Temp);
			}else{
				printError();
			}
			break;
		}
		case 'n': {
			if(ref<16){
				Temp=(Temp & 0xf0) | ref;
				ADS126xWriteRegister(ADC2MUX, 1, &Temp);
			}else{
				printError();
			}
			break;
		}
		default:
			printError();
			break;
		}
	}

}


void set_bias(char c)
{
	int buff = (int) c - 48;		//Convert character to a (0 through 9) number
	int mode;
	unsigned char Temp;

	// the DataRate value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(POWER, 0x01, &Temp);

	mode = Temp & VBIAS;

	// If no data is sent, print out current value
	if (c==NULL)
	{
		strcpy(outString,"VBIAS = ");
		strcat(outString,(mode)?"Enabled":"Disabled");
		strcat(outString,"\r\n");
		//strcat(outString,prompt);
		print2Console(outString);
		return;
	}
	else
	{
		if (buff==1)
		{
			Temp = Temp | VBIAS;
			ADS126xWriteRegister(POWER, 1, &Temp);
			strcpy(outString,"VBIAS = Enabled\r\n");
			print2Console(outString);
		}
		else if (buff==0)
		{
			Temp = Temp & ~VBIAS;
			ADS126xWriteRegister(POWER, 1, &Temp);
			strcpy(outString,"VBIAS = Disabled\r\n");
			print2Console(outString);
		}
		else
			printError();
	}

}

void set_chop(char c)
{
	int buff = (int) c - 48;		//Convert character to a (0 through 9) number
	int mode;
	uint8_t AdcRegByte;

	//Read MOD0
	ADS126xReadRegister(MODE0, 0x01, &AdcRegByte);
	mode = (AdcRegByte & CHOP_ON);

	// If no data is sent, print out current value
	if (c == NULL)
	{
		strcpy(outString,"CHOP = ");
		strcat(outString,(mode)?"Enabled":"Disabled");
		strcat(outString,"\r\n");
		//strcat(outString,prompt);
		print2Console(outString);
		return;
	}
	else
	{
		if(buff == 1)
		{
			AdcRegByte |= CHOP_ON;
			ADS126xWriteRegister(MODE0, 1, &AdcRegByte);
			strcpy(outString,"CHOP = Enabled\r\n");
			print2Console(outString);
		}
		else if(buff == 0)
		{
			AdcRegByte &= ~CHOP_ON;
			ADS126xWriteRegister(MODE0, 1, &AdcRegByte);
			strcpy(outString,"CHOP = Disabled\r\n");
			print2Console(outString);
		}
		else
			printError();
	}

}

void set_conv_mode(char c)
{
	int spd = (int) c - 48;		//Convert character to a (0 through 9) number
	int mode;
	unsigned char Temp;

	// the conversion mode value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(MODE0, 1, &Temp);
	mode = Temp & RUNMODE;

	// If no data is sent, print out current value
	if (c==NULL)
	{
		strcpy(outString,"Conversion Mode = ");
		strcat(outString,(mode)?"Pulse":"Continuous");
		strcat(outString,"\r\n");
		print2Console(outString);
		return;
	}
	else
	{
		if (spd == 1)
		{
			Temp = Temp | RUNMODE;
			ADS126xWriteRegister(MODE0, 1, &Temp);
			strcpy(outString,"Conversion Mode = Pulse\r\n");
			print2Console(outString);
		}
		else if (spd == 0)
		{
			Temp=Temp & ~RUNMODE;
			ADS126xWriteRegister(MODE0, 1, &Temp);
			strcpy(outString,"Conversion Mode = Continuous\r\n");
			print2Console(outString);
		}
		else
		{
			printError();
		}
	}

}

void set_gpio(char channel_char, char param1, char param2)
{
	char channel = channel_char - 48;
	unsigned char gpio_regs[3]; //[0]:GPIOCON, [1]:GPIODIR, [2]:GPIODAT

	ADS126xReadRegister(GPIOCON, 2, gpio_regs);					// Read GPIOCON & GPIODIR
																// Warning: Cannot read GPIO output values with this command! -> Stored in memory

	if(channel_char == NULL)		// User input: 'g'
	{
		for(int i=0;i<8;i++)		// Show all GPIO settings
		{
			strcpy(outString,"GPIO @ ");
			strcat(outString,scr_gpio_norm_strings[i]);
			strcat(outString,"= ");
			strcat(outString,(gpio_regs[GPIOCON-GPIOCON]&(0x01<<i))?"ENABLED,  ":"DISABLED, ");
			strcat(outString,(gpio_regs[GPIODIR-GPIOCON]&(0x01<<i))?"INPUT,  ":"OUTPUT, ");
			strcat(outString,(gpio_regs[GPIODAT-GPIOCON]&(0x01<<i))?"1":"0");
			strcat(outString,"\r\n");
			print2Console(outString);
		}
	}
	else if(channel < 8)			// User input: 'g<0..7>?'
	{
		switch(param1)
		{
		case NULL:					// User input: 'g<0..7>'
			break;						// prints output string below
		case '1':					// User input: 'g<0..7>1'
			gpio_regs[GPIODAT-GPIOCON] |= (0x01 << channel);
			ADS126xWriteRegister(GPIODAT, 1, &gpio_regs[GPIODAT-GPIOCON]);

			break;
		case '0':					// User input: 'g<0..7>0'
			gpio_regs[GPIODAT-GPIOCON] &= ~(0x01 << channel);
			ADS126xWriteRegister(GPIODAT, 1, &gpio_regs[GPIODAT-GPIOCON]);
			break;
		case 'e':					// User input: 'g<0..7>e'
			gpio_regs[GPIOCON-GPIOCON] |= (0x01 << channel);
			ADS126xWriteRegister(GPIOCON, 1, &gpio_regs[GPIOCON-GPIOCON]);
			if (param2 == 'i')		// User input: 'g<0..7>ei'
			{
				gpio_regs[GPIODIR-GPIOCON] |= (0x01 << channel);
			}
			else if (param2 == 'o')	// User input: 'g<0..7>eo'
			{
				gpio_regs[GPIODIR-GPIOCON] &= ~(0x01 << channel);
			}
			ADS126xWriteRegister(GPIODIR, 1, &gpio_regs[GPIODIR-GPIOCON]);
			break;
		case 'd':					// User input: 'g<0..7>d'
			gpio_regs[GPIOCON-GPIOCON] &= ~(0x01 << channel);
			ADS126xWriteRegister(GPIOCON, 1, &gpio_regs[GPIOCON-GPIOCON]);
			if (param2 == 'i')		// User input: 'g<0..7>di'
			{
				gpio_regs[GPIODIR-GPIOCON] |=  0x01 << channel;
			}
			else if (param2 == 'o') // User input: 'g<0..7>do'
			{
				gpio_regs[GPIODIR-GPIOCON] &=  ~(0x01 << channel);
			}
			ADS126xWriteRegister(GPIODIR, 1, &gpio_regs[GPIODIR-GPIOCON]);
			break;
		default:
			printError();
			break;
		}

		/* Build String Output */
		strcpy(outString,"GPIO @ ");
		strcat(outString,scr_gpio_norm_strings[channel]);
		strcat(outString,"= ");
		strcat(outString,(gpio_regs[GPIOCON-GPIOCON]&(0x01<<channel))?"ENABLED,  ":"DISABLED, ");
		strcat(outString,(gpio_regs[GPIODIR-GPIOCON]&(0x01<<channel))?"INPUT,  ":"OUTPUT, ");
		strcat(outString,(gpio_regs[GPIODAT-GPIOCON]&(0x01<<channel))?"1":"0");
		strcat(outString,"\r\n");
		print2Console(outString);
	}
	else
	{
		printError();
	}
}

//void data(char adc)
//{
//	bufferType_t tData;
//	//ADS126xReadDataCpp(&tData,0);
//
//	if(g_outputFormat==FORMAT_ASCII)
//		printhex(tData.data.payload.integer,1);
//	else if(g_outputFormat==FORMAT_INT)
//		cdcSendDataWaitTilDone(tData.bytes,8,0,0);
//}

void show_parms(char p1)
{
	uint8_t ADSdata[ADS126x_NUM_REG];

	ADS126xReadRegister(ID, ADS126x_NUM_REG, ADSdata);

	if(NULL == p1)
	{
		/* Displays on the console a list of current parameter settings.....
		This will need to change with regard to which parameters the ADC has and
		are available to set.....most functions assume a two state variable and uses
		a logical to determine actual printed value.  Statement ends with a CRLF */
		strcpy(outString,"\r\nVBIAS: \t");
		strcat(outString,(ADSdata[POWER]&VBIAS)?"ON":"OFF");
		print2Console(outString);

		strcpy(outString,"\r\nData Rate: ");
		strcat(outString,scr_speed_norm_strings[ADSdata[MODE2]&0x0F]);
		strcat(outString," SPS");
		print2Console(outString);

		strcpy(outString,"\r\nCHOP: \t");
		strcat(outString,(ADSdata[MODE0]&CHOP_ON)?"ON":"OFF");
		print2Console(outString);

		strcpy(outString,"\r\nGAIN: \t");
		strcat(outString,scr_pga_norm_strings[(ADSdata[MODE2]&0x70)>>4]);
		strcat(outString," V/V");
		print2Console(outString);

		strcpy(outString,"\r\nConversion Mode: ");
		strcat(outString,(ADSdata[MODE0]&RUNMODE)?"Pulse":"Continuous");
		print2Console(outString);

		strcpy(outString,"\r\nINT Reference: \t");
		strcat(outString,(ADSdata[POWER]&INTREF)?"ON":"OFF");
		strcat(outString,"\r\nREFP: \t");
		strcat(outString,scr_refp_norm_strings[(ADSdata[REFMUX]&0x38)>>3]);
		print2Console(outString);

		strcpy(outString,"\r\nREFN: \t");
		strcat(outString,scr_refn_norm_strings[(ADSdata[REFMUX]&0x07)]);
		print2Console(outString);

		strcpy(outString,"\r\nFilter: ");
		strcat(outString,scr_filter_norm_strings[(ADSdata[MODE1]&0xE0)>>5]);
		print2Console(outString);

		strcpy(outString,"\r\nMUXP: \t");
		strcat(outString,scr_mux_norm_strings[(ADSdata[INPMUX]&0xF0)>>4]);
		print2Console(outString);

		strcpy(outString,"\r\nMUXN: \t");
		strcat(outString,scr_mux_norm_strings[(ADSdata[INPMUX]&0x0F)]);
		strcat(outString,"\r\n");
		print2Console(outString);
	}

	else if('0' == p1)
	{
		strcpy(outString,"\r\n0x00	ID\t\t=\t0x");
		hex2asc(&ADSdata[ID],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x01	POWER\t\t=\t0x");
		hex2asc(&ADSdata[POWER],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x02	INTERFACE\t=\t0x");
		hex2asc(&ADSdata[INTERFACE],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x03	MODE0\t\t=\t0x");
		hex2asc(&ADSdata[MODE0],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x04	MODE1\t\t=\t0x");
		hex2asc(&ADSdata[MODE1],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x05	MODE2\t\t=\t0x");
		hex2asc(&ADSdata[MODE2],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x06	INPMUX\t\t=\t0x");
		hex2asc(&ADSdata[INPMUX],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x07	OFCAL0\t\t=\t0x");
		hex2asc(&ADSdata[OFCAL0],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x08	OFCAL1\t\t=\t0x");
		hex2asc(&ADSdata[OFCAL1],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x09	OFCAL2\t\t=\t0x");
		hex2asc(&ADSdata[OFCAL2],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x0A	FSCAL0\t\t=\t0x");
		hex2asc(&ADSdata[FSCAL0],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x0B	FSCAL1\t\t=\t0x");
		hex2asc(&ADSdata[FSCAL1],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x0C	FSCAL2\t\t=\t0x");
		hex2asc(&ADSdata[FSCAL2],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x0D	IDACMUX\t\t=\t0x");
		hex2asc(&ADSdata[IDACMUX],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x0E	IDACMAG\t\t=\t0x");
		hex2asc(&ADSdata[IDACMAG],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x0F	REFMUX\t\t=\t0x");
		hex2asc(&ADSdata[REFMUX],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x10	TDACP\t\t=\t0x");
		hex2asc(&ADSdata[TDACP],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x11	TDACN\t\t=\t0x");
		hex2asc(&ADSdata[TDACN],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x12	GPIOCON\t\t=\t0x");
		hex2asc(&ADSdata[GPIOCON],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x13	GPIODIR\t\t=\t0x");
		hex2asc(&ADSdata[GPIODIR],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x14	GPIODAT\t\t=\t0x");
		hex2asc(&ADSdata[GPIODAT],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

#ifdef ADS1263
		strcpy(outString,"\r\n0x15	ADC2CFG\t\t=\t0x");
		hex2asc(&ADSdata[ADC2CFG],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x16	ADC2MUX\t\t=\t0x");
		hex2asc(&ADSdata[ADC2MUX],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x17	ADC2OFC0\t=\t0x");
		hex2asc(&ADSdata[ADC2OFC0],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x18	ADC2OFC1\t=\t0x");
		hex2asc(&ADSdata[ADC2OFC1],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x19	ADC2FSC0\t=\t0x");
		hex2asc(&ADSdata[ADC2FSC0],2,2,tempString,1);
		strcat(outString,tempString);
		print2Console(outString);

		strcpy(outString,"\r\n0x1A	ADC2FSC1\t=\t0x");
		hex2asc(&ADSdata[ADC2FSC1],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\r\n");
		print2Console(outString);
#endif
	}

	else
	{
		//This shortened register setting string could be queried by a GUI

		strcpy(outString,"\r\nae");
		snprintf(tempString,30,"%x",(ADSdata[ADC2CFG]&0x38)>>3);
		strcat(outString,tempString);

		strcat(outString,"|amp");
		snprintf(tempString,30,"%x",(ADSdata[ADC2MUX]&0xF0)>>4);
		strcat(outString,tempString);

		strcat(outString,"|amn");
		snprintf(tempString,30,"%x",ADSdata[ADC2MUX]&0x0F);
		strcat(outString,tempString);

		strcat(outString,"|ap");
		snprintf(tempString,30,"%x",ADSdata[ADC2CFG]&0x07);
		strcat(outString,tempString);

		strcat(outString,"|ar");
		snprintf(tempString,30,"%x",(ADSdata[ADC2CFG]&0xC0)>>6);
		strcat(outString,tempString);

		strcat(outString,"|as");
		snprintf(tempString,30,"%x",adc2_startstop(NULL,NULL));
		strcat(outString,tempString);

		strcat(outString,"|b");
		snprintf(tempString,30,"%x",(ADSdata[POWER]&VBIAS)>>1);
		strcat(outString,tempString);
		strcat(outString,"|cc");
		snprintf(tempString,30,"%x",(ADSdata[MODE0]&RUNMODE)>>6);
		strcat(outString,tempString);

		strcat(outString,"|e");
		snprintf(tempString,30,"%x",ADSdata[POWER]&INTREF);
		strcat(outString,tempString);
		strcat(outString,"|ep");
		snprintf(tempString,30,"%x",(ADSdata[REFMUX]&0x38)>>3);
		strcat(outString,tempString);
		strcat(outString,"|en");
		snprintf(tempString,30,"%x",ADSdata[REFMUX]&0x07);
		strcat(outString,tempString);

		strcat(outString,"|f");
		snprintf(tempString,30,"%x",(ADSdata[MODE1]&0xE0)>>5);
		strcat(outString,tempString);

		strcat(outString,"|i1d");
		snprintf(tempString,30,"%x",ADSdata[IDACMUX]&0x0F);
		strcat(outString,tempString);
		strcat(outString,"|i1m");
		snprintf(tempString,30,"%x",ADSdata[IDACMAG]&0x0F);
		strcat(outString,tempString);

		strcat(outString,"|i2d");
		snprintf(tempString,30,"%x",(ADSdata[IDACMUX]&0xF0)>>4);
		strcat(outString,tempString);
		strcat(outString,"|i2m");
		snprintf(tempString,30,"%x",(ADSdata[IDACMAG]&0xF0)>>4);
		strcat(outString,tempString);

		strcat(outString,"|mp");
		snprintf(tempString,30,"%x",(ADSdata[INPMUX]&0xF0)>>4);
		strcat(outString,tempString);
		strcat(outString,"|mn");
		snprintf(tempString,30,"%x",(ADSdata[INPMUX]&0x0F));
		strcat(outString,tempString);

		strcat(outString,"|p");
		snprintf(tempString,30,"%x",(ADSdata[MODE2]&0x70)>>4);
		strcat(outString,tempString);

		strcat(outString,"|r");
		snprintf(tempString,30,"%x",ADSdata[MODE2]&0x0F);
		strcat(outString,tempString);

		strcat(outString,"|s");
		strcat(outString,(P1IE&GPIO_PIN2)?"1":"0");

//		strcat(outString,"|x");
//		switch(g_excitationStatus)
//		{
//		case EXC_OFF:
//			strcat(outString, "0");
//			break;
//		case EXC_POS:
//			strcat(outString, "1");
//			break;
//		case EXC_NEG:
//			strcat(outString, "2");
//			break;
//		}
		//strcat(outString,g_excitationStatus?"1":"0");

//		strcat(outString,"|xs");
//
//		if(g_samplesPerExcitation)
//		{
//			for(i=0;i<=0xf;++i)
//			{
//				if((g_samplesPerExcitation>>i)&0x01)
//					break;
//			}
//		}
//		else
//			i=0;
//		snprintf(tempString,30,"%x",i);
//		strcat(outString,tempString);
		print2Console(outString);
	}
}


void set_vref(char c, char d)
{
	int Ref_pin = (int) d - 48;			//Convert character to a (0 through 9) number
	int INTREF_bit;
	unsigned char RegPOWER,RegREF;
	unsigned char refn_val, refp_val;

	// the Vref value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(POWER, 0x01, &RegPOWER);
	ADS126xReadRegister(REFMUX, 0x01, &RegREF);

	INTREF_bit = RegPOWER & INTREF;					//Get INTREF bit value
	refn_val = RegREF & RMUXN_MASK;
	refp_val = (RegREF & RMUXP_MASK) >> 3;

	// If no data is sent, print out current value
	switch(c)
	{
		case NULL:
		{
			strcpy(outString,"Internal reference = ");
			strcat(outString,(INTREF_bit)?"ON":"OFF");
			strcat(outString,"\r\nREFP = ");
			strcat(outString,scr_refp_norm_strings[refp_val]);
			strcat(outString,"\r\nREFN = ");
			strcat(outString,scr_refn_norm_strings[refn_val]);
			strcat(outString,"\r\n");
			print2Console(outString);
			break;
		case 'p':
		{
			if((Ref_pin >= 0) && (Ref_pin < 5))
			{
				RegREF = (Ref_pin << 3) | (RegREF & 0x7);	//MUXP + MUXN Settings
				ADS126xWriteRegister(REFMUX, 1, &RegREF);
				strcpy(outString,"REFP = ");
				strcat(outString,scr_refp_norm_strings[Ref_pin]);
				strcat(outString,"\r\n");
				print2Console(outString);
			}
			else if (Ref_pin < 0)
			{
				strcpy(outString,"REFP = ");
				strcat(outString,scr_refp_norm_strings[refp_val]);
				strcat(outString,"\r\n");
				print2Console(outString);
			}
			else
			{
				printError();
			}
			break;
		}
		case 'n':
		{
			if((Ref_pin >= 0) && (Ref_pin < 5))
			{
				RegREF = (RegREF & 0x38) | Ref_pin;		//MUXP + MUXN Settings
				ADS126xWriteRegister(REFMUX, 1, &RegREF);
				strcpy(outString,"REFN = ");
				strcat(outString,scr_refn_norm_strings[Ref_pin]);
				strcat(outString,"\r\n");
				print2Console(outString);
			}
			else if (Ref_pin < 0)
			{
				strcpy(outString,"REFN = ");
				strcat(outString,scr_refp_norm_strings[refn_val]);
				strcat(outString,"\r\n");
				print2Console(outString);
			}
			else
			{
				printError();
			}
			break;
		}
		case '0':
			RegPOWER= RegPOWER & 0xFE;
			ADS126xWriteRegister(POWER, 1, &RegPOWER);
			strcpy(outString,"Internal reference = OFF\r\n");
			print2Console(outString);
			break;
		case '1':
			RegPOWER = RegPOWER | 0x01;
			ADS126xWriteRegister(POWER, 1, &RegPOWER);
			strcpy(outString,"Internal reference = ON\r\n");
			print2Console(outString);
			break;
		default:
			printError();
			break;
		}
	}
}

void set_mux(char c, char d){
	char temp_str[2]={d,'\0'};
	char ref = strtoul(temp_str,NULL,16);

	unsigned char regINPMUX;
	unsigned char muxn_val, muxp_val;

	// the Vref value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(INPMUX, 0x01, &regINPMUX);
	muxp_val = (regINPMUX & 0xF0) >> 4;
	muxn_val = regINPMUX & 0x0F;

	// If no data is sent, print out current value
	switch(c)
	{

		case NULL:
			strcpy(outString,"MUXP = ");
			strcat(outString,scr_mux_norm_strings[muxp_val]);
			strcat(outString,"\r\nMUXN = ");
			strcat(outString,scr_mux_norm_strings[muxn_val]);
			strcat(outString,"\r\n");
			print2Console(outString);
			break;

		case 'p':
			if(ref < 16)
			{
				regINPMUX = regINPMUX & 0xf;
				regINPMUX = regINPMUX | (ref<<4);
				ADS126xWriteRegister(INPMUX, 1, &regINPMUX);
				strcpy(outString,"MUXP = ");
				strcat(outString,scr_mux_norm_strings[ref]);
				strcat(outString,"\r\n");
				print2Console(outString);
			}
			else
				printError();
			break;

		case 'n':
			if(ref<16)
			{
				regINPMUX=(regINPMUX & 0xf0) | ref;
				ADS126xWriteRegister(INPMUX, 1, &regINPMUX);
				strcpy(outString,"MUXN = ");
				strcat(outString,scr_mux_norm_strings[ref]);
				strcat(outString,"\r\n");
				print2Console(outString);
			}
			else
				printError();
			break;

		default:
			printError();
			break;
	}
}

void set_filter(char c)
{
	char option = (int) c - 48; 	//Convert character "c" to a (0 through 9) integer "option"
	uint8_t AdcRegData, FilterSetting;

	// the DataRate value is only part of the register, so we have to read it back
	// and massage the new value into it
	ADS126xReadRegister(MODE1, 0x01, &AdcRegData);
	FilterSetting = (AdcRegData & FILTER_MASK) >> 5;

	// If no data is sent, print out current value
	if (NULL == c)
	{
		strcpy(outString,"Filter Mode = ");
		strcat(outString,scr_filter_norm_strings[FilterSetting]);
		strcat(outString,"\r\n");
		print2Console(outString);
		return;
	}
	else
	{
		// Change Filter
		if (option < 5)
		{
			FilterSetting = (FilterSetting & ~FILTER_MASK) | (option << 5);
			ADS126xWriteRegister(MODE1, 1, &FilterSetting);
			strcpy(outString,"Filter Mode = ");
			strcat(outString,scr_filter_norm_strings[option]);
			strcat(outString,"\r\n");
			print2Console(outString);
		}
		else
			printError();
	}
}



/*
 *  Creates a buffer and converts hex data byte to ASCII characters in the buffer string.
*/
int16_t hex2asc(void *hexNumAdr, int digs, int mode, char *outStringAdr, int LittleEndian)
{
	int i,zero;
	char dig;
	char *spos = outStringAdr;
	char *NumAdr = (char *)hexNumAdr;

	zero = 1;

	(LittleEndian) ? (NumAdr += (digs - 1) >> 1 ) : (NumAdr += (16 - digs) >> 1);

	for (i=digs-1;i>=0;--i)
	{
		if (i & 1)
		{
			dig = (*(char *)NumAdr >> 4) & 15;
		}
		else
		{
			dig = *(char *)NumAdr & 15;
			(LittleEndian) ? (--NumAdr) : (++NumAdr);
		}

		if (zero && dig)
			zero = 0;

		if (zero)
		{
			switch(mode)
			{
			case 1:
				*spos++ =' ';
				break;
			case 2:
				*spos++ ='0';
				break;
			default:
				break;
			}
		}
		else
			*spos++ = h2a(dig);
	}

	if (zero && mode == 1)
		*(spos-1)='0';
	else if (zero && mode == 0)
		*spos++ = '0';
		*spos = 0;

	return (spos - outStringAdr);
}

/*
 * ======== retInString ========
 */
// This function returns true if there's an 0x0D character in the string; and if
// so, it trims the 0x0D and anything that had followed it.
// TODO: Use strchr() from <string.h> library
uint8_t retInString (char* string)
{
    uint8_t retPos = 0,i,len;
    char tempStr[MAX_CONSOLE_STR_LEN] = "";

    strncpy(tempStr,string,strlen(string));  // Make a copy of the string
    len = strlen(tempStr);

    // Find 0x0D; if not found, retPos ends up at len
    while ((tempStr[retPos] != 0x0A) && (tempStr[retPos] != 0x0D) && (retPos++ < len));

    // If 0x0D was actually found...
    if ((retPos < len) && (tempStr[retPos] == 0x0D))
    {
        for (i = 0; i < MAX_CONSOLE_STR_LEN; i++)			// Empty the buffer
        	string[i] = 0x00;

        //...trim the input string to just before 0x0D
        strncpy(string,tempStr,retPos);

        //...and tell the calling function that we did so
        return (TRUE) ;

    // If 0x0D was actually found...
    }
    else if ((retPos < len) && (tempStr[retPos] == 0x0A))
    {
        // Empty the buffer
        for (i = 0; i < MAX_CONSOLE_STR_LEN; i++)
        	string[i] = 0x00;

        //...trim the input string to just before 0x0D
        strncpy(string,tempStr,retPos);

        //...and tell the calling function that we did so
        return (TRUE) ;
    }
	else if (tempStr[retPos] == 0x0D)
    {
        for (i = 0; i < MAX_CONSOLE_STR_LEN; i++)  // Empty the buffer
        	string[i] = 0x00;

        // ...trim the input string to just before 0x0D
        strncpy(string,tempStr,retPos);

        // ...and tell the calling function that we did so
        return (TRUE) ;
    }
	else if (retPos < len)
	{
        for (i = 0; i < MAX_CONSOLE_STR_LEN; i++)	// Empty the buffer
        	string[i] = 0x00;

        //...trim the input string to just before 0x0D
        strncpy(string,tempStr,retPos);

        //...and tell the calling function that we did so
        return (TRUE) ;
    }

    return (FALSE) ; // Otherwise, it wasn't found
}




