/***************************************************************************
	enet_menu.c
  	Z-World, 2002

	This program is used with RCM3000 series controllers
	with prototyping boards.
	
	The sample library, rcm3000.lib, contains a brdInit()
	function which initializes port pins. Modify this
	function to fit your application.

	An optional LCD/Keypad Module is required to run this
	program.  #define PORTA_AUX_IO at top of program to
	enable external I/O bus for LCD/Keypad operations.
	
	Description
	===========
  	This program demonstrates how to implement a menu system with using a
  	highlight bar on a graphic LCD display and to communicated to a second
  	controller via ethernet. The menu options for this sample is as follows:

 		" <<<<Main Menu>>>>",
		"1.ENET A/D voltage",
		"2.Toggle LED's",
		"3.Increment LED's",
		"4.Disable LED's",
		"5.Turn Backlight OFF",
		"6.Turn Backlight ON",
		"7.Display Date/Time",
		"8.Set Date & Time"

   Use enet_ad.c to program a second controller with Analog Inputs and
   Outputs.
   
	(Adapted from op6800_enet.c)

	Instructions
	============	
  	To select a option use the scroll keys(Scroll and/or Page UP/DOWN keys)
  	to highlight the option that you want to select and then press the ENTER
  	key.

	Once the option is selected the operation will be completed or you
	will be prompted to do additional steps to complete the option
	selected.

	Development Note:
	-----------------
	Menu options can be added/deleted and the highlight bar will automatically
	adjust to the new menu list. This will also require that you add/delete case
	statements in main() to match your menu list.
	
**************************************************************************/
#class auto

#define PORTA_AUX_IO		//required to run LCD/Keypad for this demo
#use rcm3000.lib    		//sample library used for this demo

char buffer[4096];

/***********************************
 * Configuration                   *
 * -------------                   *
 * All fields in this section must *
 * be altered to match your local  *
 * network settings.               *
 ***********************************/

/*
 * Pick the predefined TCP/IP configuration for this sample.  See
 * LIB\TCPIP\TCP_CONFIG.LIB for instructions on how to set the
 * configuration.
 */
#define TCPCONFIG 1


#memmap xmem
#use "dcrtcp.lib"

/*
 *  Remote computer to contact:
 */
#define  DEST 		"10.10.6.101"
#define  PORT 		8888

#undef  SOCK_BUF_SIZE 
#define SOCK_BUF_SIZE 	2048

/********************************
 * End of configuration section *
 ********************************/

//---------------------------------------------------------
// Bitmaps
//---------------------------------------------------------
// Bitmap : Zwbw5_bmp
// Buffer Size : 203
// Monochrome  : White Foreground, Black Background
// Mode   : Landscape
// Height : 29 pixels.
// Width  : 53 pixels.
// Init   : glXPutBitmap (leftedge,topedge,53,29,Zwbw5_bmp);

xdata Zwbw5_bmp {
'\x00','\x00','\x1F','\xF8','\x00','\x00','\x07',
'\x00','\x00','\xFF','\xFF','\x80','\x00','\x07',
'\x00','\x03','\xF3','\xF0','\xE0','\x00','\x07',
'\x00','\x0F','\xFF','\xE0','\x38','\x00','\x07',
'\x00','\x3F','\x0F','\xFC','\x0E','\x00','\x07',
'\x00','\x7E','\x1E','\x07','\x83','\x00','\x07',
'\x00','\xFC','\x38','\x01','\xE1','\x80','\x07',
'\x01','\xB8','\x30','\x00','\x38','\xC0','\x07',
'\x03','\x30','\x70','\x00','\x0C','\x60','\x07',
'\x06','\x60','\xE0','\x00','\x03','\x70','\x07',
'\x0E','\x60','\xC0','\x00','\x01','\xF0','\x07',
'\x0C','\xC1','\x80','\x00','\x00','\xE8','\x07',
'\x1F','\xFF','\xE0','\x00','\x00','\x2C','\x37',
'\x3F','\x83','\x7F','\x00','\x00','\x34','\x1F',
'\x31','\x03','\x01','\xE0','\x00','\x2A','\x3F',
'\x31','\x02','\x00','\x1C','\x00','\x26','\x67',
'\x62','\x06','\x00','\x07','\x00','\x27','\xC7',
'\x62','\x04','\x00','\x01','\x80','\x27','\x07',
'\x00','\x00','\x00','\x00','\x00','\x70','\x07',
'\x00','\x00','\x00','\x00','\x03','\x80','\x07',
'\x7C','\x21','\x0D','\xF9','\xF8','\x7C','\x07',
'\x08','\x31','\x8B','\x0F','\x84','\x63','\x07',
'\x18','\x11','\x8F','\xE1','\x14','\x61','\x07',
'\x11','\x93','\xF0','\x05','\x34','\x61','\x07',
'\x31','\xC0','\x54','\x07','\xE4','\x61','\x07',
'\x20','\x0A','\x56','\x05','\x44','\x61','\x07',
'\x40','\x0C','\x62','\x05','\x24','\x63','\x07',
'\x40','\x04','\x21','\x99','\x34','\x6E','\x07',
'\xFC','\x04','\x20','\xF1','\x17','\xF8','\x07'
};

//---------------------------------------------------------
// Macro's
//---------------------------------------------------------
#define MAXDISPLAYROWS	4
#define LEDOFF				0
#define TOGGLE				1
#define INCREMENT			2
#define OPERATE			3

#define ASCII				0
#define NUMBER				1

//----------------------------------------------------------
// Main_Menu options
//----------------------------------------------------------
// Can insert/delete menu options. The highlight bar is setup
// to start with the first MENU option and stop at the last
// menu option in the MENU.
//
// When adding/deleting menu options you must match up the
// case statements to the menu option number.
//  
const char *main_menu [] =
{		" <<<<Main Menu>>>>",
		"1.ENET A/D voltage",
		"2.Toggle LED's",
		"3.Increment LED's",
		"4.Disable LED's",
		"5.Turn Backlight OFF",
		"6.Turn Backlight ON",
		"7.Display Date/Time",
		"8.Set Date & Time",
		NULL
};

//----------------------------------------------------------
// Structures, arrays, variables
//----------------------------------------------------------
fontInfo fi6x8, fi8x10, fi12x16;

// Text windowframe structures
windowFrame textWindow, textWindow1, textWindow2;

typedef struct  {
	int data;
	char *ptr;
} fieldupdate;

struct tm CurTime;

char szTime[40];
char szString[20];
const char Days[] = {"SunMonTueWedThuFriSat"};
const char Months[] = {"JanFebMarAprMayJunJulAugSepOctNovDec"};


int ledCntrl;
int beeperTick, timerTick ;
int max_menu_options;
int max_cmds_options;
unsigned long ulTime;
char *keybuffer;


//------------------------------------------------------------------------
// Milli-sec delay function
//------------------------------------------------------------------------
nodebug
void msDelay(unsigned int delay)
{
	auto unsigned long done_time;
	
	done_time = MS_TIMER + delay;
   while( (long) (MS_TIMER - done_time) < 0 );
} 


//------------------------------------------------------------------------
// Process key to do number and ASCII field changes 
//------------------------------------------------------------------------
int ProcessKeyField(int mode, fieldupdate *field)
{
	static int wKey;

	keyProcess();
	msDelay(100);
	
	if((wKey = keyGet()) != 0)
	{
		switch(wKey)
		{
			// Decrement number by 10 or pointer by 3 
			case '-':
				if(mode == NUMBER)
					field->data -= 10;
				else
					field->ptr  -= 3;
				break;

			// Increment number by 10 or pointer by 3
			case '+':
				if(mode == NUMBER)
					field->data += 10;
				else
					field->ptr  += 3;				
				break;

			// Increment number or pointer by 1		
			case 'U':
				if(mode == NUMBER)	
					field->data++;
				else
					field->ptr++;	
				break;

			// Decrement number or pointer by 1
			case 'D':	// Decrement X1
				if(mode == NUMBER)	
					field->data--;
				else
					field->ptr--;
				break;

			// Done Editing field
			case 'E':
				wKey = 'E';
				break;

			default:
				wKey = -1;
		  		break;
		}
	}
	return(wKey);	
}


//------------------------------------------------------------------------
// Get and process the users MENU option
//------------------------------------------------------------------------
int GetKeypadOption( int *offset, int *highlight )
{
	static int wKey;

	if((wKey = keyGet()) != 0)
	{
		switch(wKey)
		{
			case '-':	// Page down
				if(*offset < ((sizeof(main_menu)/sizeof(int)) - 1))
				{
					if((*offset + MAXDISPLAYROWS) < ((sizeof(main_menu)/sizeof(int)) - 1))
						*offset += 4;
				}
				if(*offset == 0)
					*highlight = 1; 
				else
					*highlight = 0;
				wKey = -1;
				break;
				
			case '+':	// Page up
				if(*offset > 3)
					*offset -=4;
				else
					*offset = 0;
				if(*offset == 0)
					*highlight = 1;
				else
					*highlight = 0;
				wKey = -1;
				break;

			case 'U':	// Scroll-up by one line
				*highlight -= 1;
				if(*highlight < 0)
				{
					*offset -= 1;
					*highlight = 0;
				}
				if(*offset == 0 && *highlight == 0) 
					*highlight = 1;
				wKey = -1;
				break;
				
			case 'D':	// Scroll-down by one line
				if((*offset + (*highlight) + 1) < ((sizeof(main_menu)/sizeof(int)) - 1))
				{
					*highlight += 1;
					if(*highlight > 3)
					{
						*offset += 1;
						*highlight = 3;
					}
				}
				wKey = -1;
				break;
				
			case 'E':	// Select option
				wKey = *offset + *highlight;
				break;

			default:
				wKey = -1;
		  		break;
		}
	}
	return(wKey);
}

//------------------------------------------------------------------------
// Display a MENU on the LCD display and get the menu option from the user
//------------------------------------------------------------------------
int display_menu ( char **line, int initialize)
{
	static int offset, tmpoffset, i;
	static int menu_option;
	static int lasthighlight;
	static int scrolling;
	static int highlight;

	costate
	{
		if(initialize)
		{
			offset = 0;				// Initialize menu line index
			highlight = 1;			// Assumes all menus have a heading
			tmpoffset = ~offset;
		}

		menu_option = 0;			// Initially set to no option selected
		scrolling = FALSE;
	
		// Wait until you get a valid user option
		while (menu_option == 0)
		{    
			// Display menu option
			if (tmpoffset != offset)
			{
				glBlankScreen();
				for(i=0; i < 4; i++)
				{	// Display up to 4 lines of menu options
					TextGotoXY(&textWindow, 0, i);	   			
					TextPrintf(&textWindow, "%s", line[offset]); 
					if(line[offset + 1] == NULL) {	   			
			 			break;
					}
					offset++;
				}

				// Reset the offset back to the first option displayed
				offset = offset-i;
				tmpoffset = offset;
			}
			glSetBrushType(PIXXOR);
			glBlock (0, highlight*8, 122, 8);
			glSetBrushType(PIXBLACK);
			lasthighlight = highlight;
			
			// Get the user's option						
			waitfor((menu_option = GetKeypadOption(&offset, &highlight))); 		

			// Check if user selected the scrolling option
			glSetBrushType(PIXXOR);
			glBlock (0, lasthighlight*8, 122, 8);
			glSetBrushType(PIXBLACK);
			if(menu_option == -1)
			{
				// Set menu option to zero due to scrolling operation
				menu_option = 0;
				scrolling = TRUE;
			}
		}
	}
	tmpoffset = offset;
	return(menu_option);
}

//------------------------------------------------------------------------
// Format the Date and Time for the LCD display
//------------------------------------------------------------------------
void FormatDateTime ( void )
{	char Day[4], Mon[4];

	ulTime = read_rtc ();			// get the RTC value
	mktm( &CurTime, ulTime );		// convert seconds to date values

	strncpy ( Day, &Days[CurTime.tm_wday*3], 3 );
	strncpy ( Mon, &Months[(CurTime.tm_mon-1)*3], 3 );
	Day[3] = 0;
	Mon[3] = 0;

	sprintf ( szTime, "%s %s %d, %d \n%d:%02d:%02d",
		Day, Mon, CurTime.tm_mday, CurTime.tm_year+1900,
		CurTime.tm_hour, CurTime.tm_min, CurTime.tm_sec );
}

//------------------------------------------------------------------------
// Display the Date and Time on the LCD display
//------------------------------------------------------------------------
int dispDate( void )
{
	static int status;
	auto int wKey;

	costate
	{
		// Get current Date/Time
		status = 0;
		ulTime = read_rtc ();			// get the RTC value
		mktm( &CurTime, ulTime );		// convert seconds to date values
		FormatDateTime();					// convert to text
		waitfor(DelayMs(5));

		// Display Date and Time
		glBuffLock();	
		TextGotoXY(&textWindow, 0, 0);	   			
		TextPrintf(&textWindow, "%s\n", szTime);
		waitfor(DelayMs(5));

		// Display user exit message
		TextGotoXY(&textWindow, 0, 3);	   
		TextPrintf(&textWindow, "Press Key to EXIT");
		glBuffUnlock();
		waitfor(DelayMs(5));
			
		// Wait for key to be pressed to exit
		waitfor(((wKey = keyGet()) != 0) || DelayMs(100));
		if	(wKey != 0)
		{
			glBlankScreen();
			status = 1;
		}
	}
	return(status);
}

//------------------------------------------------------------------------
// LED control function 
//------------------------------------------------------------------------
void leds( int mode )
{
	static int toggle, increment;
	auto int led, mask;
	
	#GLOBAL_INIT {toggle=0;}
	#GLOBAL_INIT {increment=0;}

	if(mode != OPERATE)
	{
		ledCntrl = mode;
		toggle = 0;
		increment = 0;
		return;
	}

	if(ledCntrl == TOGGLE)
	{
		toggle = (~toggle) & 0x01;
		for(led = 0; led <= 6; led++)
		{
			//Toggle the LED's
			ledOut(led, toggle);
		}
	}
	else if(ledCntrl == INCREMENT)
	{
		mask = 0x01;
		increment++;
		for(led = 0; led <= 6; led++)
		{
			
			if(increment & mask)
				dispLedOut(led, 1);
			else
				dispLedOut(led, 0);
			mask = mask << 1;
		}
	}
	else
	{	//Turn all LED'S OFF
		for(led = 0; led <= 6; led++)
			dispLedOut(led, 0);
	}
}

//------------------------------------------------------------------------
// Date and Time prompt message routine
//------------------------------------------------------------------------
void date_prompt(char *ptr, int *col, int *row)
{
	glBlankScreen();
	TextGotoXY(&textWindow, 0, 0);	   			
	TextPrintf(&textWindow, "%s", ptr);	
	TextCursorLocation(&textWindow, col, row);
	
	TextGotoXY(&textWindow, 0, 3);
	TextPrintf(&textWindow, "ENTER to Continue...");	
}

//------------------------------------------------------------------------
// Set Date and Time
//------------------------------------------------------------------------
void SetDateTime( void )
{
	int wKey;
	int col, row;
	char buffer[256];
	fieldupdate dateTime;

	// Setup for FAST key repeat after holding down key for 12 ticks
	keyConfig (  6,'E',0, 12, 1,  1, 1 );
	keyConfig (  2,'D',0, 12, 1,  1, 1 );
	keyConfig (  5,'+',0, 12, 1,  1, 1 );
	keyConfig (  1,'U',0, 12, 1,  1, 1 );
	keyConfig (  4,'-',0, 12, 1,  1, 1 );

	glBlankScreen();
	
	date_prompt("Select \n4 digit year: ", &col, &row);
	dateTime.data = 2001;
	while(1)
	{
		sprintf(buffer, "%04d", dateTime.data);
		TextGotoXY(&textWindow, col, row);	 
		TextPrintf(&textWindow, "%s", buffer);		
		while((wKey = ProcessKeyField(NUMBER, &dateTime)) == 0);
		if(dateTime.data < 1900 || dateTime.data > 2047)
		{
			dateTime.data = 2001;
		}
		if(wKey == 'E')
		{
			if( dateTime.data  >= 1900 && dateTime.data < 2048) {
				CurTime.tm_year = dateTime.data - 1900;	// offset from 1900
				break;
			}
		}
	}
		
	date_prompt("Enter month: ", &col, &row);	
	dateTime.data = 1;
	while(1)
	{
		sprintf(buffer, "%02d", dateTime.data);
		TextGotoXY(&textWindow, col, row);	 
		TextPrintf(&textWindow, "%s", buffer);
		while((wKey = ProcessKeyField(NUMBER, &dateTime)) == 0);
		if(wKey == 'E')
		{
			if( dateTime.data >= 1 && dateTime.data < 13 )
			{
				CurTime.tm_mon = dateTime.data;				
				break;
			}
		}
		if(dateTime.data < 1 || dateTime.data > 12)
		{
			dateTime.data  = (dateTime.data < 1) ? 12 : 1;	
		}
	}

	date_prompt("Enter \nday of month: ", &col, &row);	
	dateTime.data = 1;
	while(1)
	{
		sprintf(buffer, "%02d", dateTime.data);
		TextGotoXY(&textWindow, col, row);	 
		TextPrintf(&textWindow, "%s", buffer);
		while((wKey = ProcessKeyField(NUMBER, &dateTime))== 0);
		if(wKey == 'E')
		{
			if( dateTime.data  >= 1 && dateTime.data < 32) {
				CurTime.tm_mday = dateTime.data;				
				break;
			}
		}
		if(dateTime.data < 1 || dateTime.data > 31)
		{
			dateTime.data  = (dateTime.data < 1) ? 31 : 1;	
		}
	}
   			
	date_prompt("Enter \nhour (24hr): ", &col, &row);	
	dateTime.data = 0;
	while(1)
	{
		sprintf(buffer, "%02d", dateTime.data);
		TextGotoXY(&textWindow, col, row);	 
		TextPrintf(&textWindow, "%s", buffer);
		while((wKey = ProcessKeyField(NUMBER, &dateTime)) == 0);
		if(wKey == 'E')
		{
			if(dateTime.data >= 0 && dateTime.data < 24) {
				CurTime.tm_hour = dateTime.data;
				break;
			}		
		}
		if(dateTime.data < 0 || dateTime.data > 23) 
		{
			dateTime.data  = (dateTime.data < 0) ? 23 : 0;	
		}
	}
			
	date_prompt("Enter minute: ", &col, &row);	
	dateTime.data = 0;
	while(1)
	{
		sprintf(buffer, "%02d", dateTime.data);
		TextGotoXY(&textWindow, col, row);	 
		TextPrintf(&textWindow, "%s", buffer);
		while((wKey = ProcessKeyField(NUMBER, &dateTime)) == 0);
		if(wKey == 'E')
		{
			if( dateTime.data >= 0 && dateTime.data < 60) {		
				CurTime.tm_min = dateTime.data;			
				break;
			}
			if(wKey == 'E')
			{
				break;
			}
		}
		if(dateTime.data < 0 || dateTime.data > 59) 
		{
			dateTime.data  = (dateTime.data < 0) ? 59 : 0;
		}
	}

	CurTime.tm_sec = 0;
	ulTime = mktime ( &CurTime );		// get seconds from 1/1/1980
	write_rtc ( ulTime );				// set the real time clock
	keypadDef();
	
	glBlankScreen();
	while(1)
	{
		// Get current Date/Time
		FormatDateTime();					// convert to text

		// Display Date and Time
		glBuffLock();	
		TextGotoXY(&textWindow, 0, 0);	   			
		TextPrintf(&textWindow, "%s\n", szTime);
	
		// Display user exit message
		TextGotoXY(&textWindow, 0, 3);	   
		TextPrintf(&textWindow, "Press Key to EXIT    ");
		glBuffUnlock();

		keyProcess ();
		if ((wKey = keyGet()) != 0)
		{
			glBlankScreen();
			break;
		}
	}
}

//------------------------------------------------------------------------
// Display Sign-on message 
//------------------------------------------------------------------------
void SignOnMessage(void)
{
	auto int signMesgDone, i, loop;
	auto char buffer[256];
		
	// Display Sign-on Message then wait for any key to continue
	glXPutBitmap (0,0,53,29,Zwbw5_bmp);
	msDelay(500);

	signMesgDone = FALSE;
	while (!signMesgDone)
	{
		i=0;
		sprintf(buffer, "Hello from Zworld!!!");
		strcat(buffer, "     Press any KEY to Continue...      ");
		while(buffer[i] != '\0' && !signMesgDone)
		{
			glHScroll(50, 0, LCD_XS, 16, -6);
			glPrintf (116,  4,   &fi6x8, "%c", buffer[i++]);
			for(loop=0; loop < 165; loop++)
			{
				msDelay(1);
				keyProcess ();
				if(keyGet() != 0)
				{
					signMesgDone = TRUE;
				}
			}
		}
	}
}

static int cursor_location;
//***************************************************************************
//	Function to display a graph bar a voltage indicator 
//***************************************************************************
void update_bar( float value )
{
	static int barGraph, pixel;

	if(value > 11.00)
	{
		value = 10.99;
	}
	if(value < 0)
	{
		value = 0;
	}

	pixel = ((int) ((value * .12) * 100)) + 1;
	if(pixel > 121) pixel = 121;			

	barGraph = 0;
	if(pixel > cursor_location)
	{
		glSetBrushType(PIXBLACK);
		while(cursor_location+barGraph < pixel)
		{
			barGraph++;
		}
		glBlock(cursor_location, 29, barGraph,  2);
		cursor_location += barGraph;
	}
	else if(pixel < cursor_location)
	{
		glSetBrushType(PIXWHITE);
		while(cursor_location-barGraph > pixel)
		{
			barGraph++;
		}
		glBlock(cursor_location-barGraph, 29, barGraph,  2);
		cursor_location -= barGraph;
	}
	glSetBrushType(PIXBLACK);
}

static int old_channel;

void displayAnalog(int channel, float value, int *row, int *col)
{	
	glSetBrushType(PIXBLACK);
	if(channel != old_channel)
	{
		glBuffLock();
		glPlotPolygon(4, 0,0,  121,0,  121,15,  0,15);
		glPlotPolygon(4, 0+2,0+2,  121-2,0+2,  121-2,15-2,  0+2,15-2);
		// Display A/D channel information
		TextGotoXY(&textWindow1, 0, 0);
		TextPrintf(&textWindow1, "A/D Ch%d = ", channel);

		// For 2 digit channels the location of the A/D volage will change
		TextCursorLocation(&textWindow1, col, row);
		TextPrintf(&textWindow1, "%5.2f", value);
		
		glPrintf(0,17, &fi6x8, "0");
		glPrintf(22,17, &fi6x8, "2");
		glPrintf(45,17, &fi6x8, "4");
		glPrintf(70,17, &fi6x8, "6");
		glPrintf(94,17, &fi6x8, "8");
		glPrintf(111,17, &fi6x8, "10");

		glPlotLine(0,   25,  0,  28);
		glPlotLine(24,  25, 24,  28);
		glPlotLine(48,  25, 48,  28);
		glPlotLine(72,  25, 72,  28);
		glPlotLine(96,  25, 96,  28);
		glPlotLine(121, 25, 121, 28);
				
		glPlotPolygon(4, 0,28,  121,28,  121,31,  0,31);
		glBuffUnlock();
			
		update_bar(value);
		old_channel = channel;
	}
	else
	{
		TextGotoXY(&textWindow1, *col, *row);
		TextPrintf(&textWindow1, "%5.2f", value);
		update_bar(value);
	}	
}

static int connected;
int analog_menu( int *state )
{
	static int row, col;
	static float value;
	static int status;
	int display_analog;
	int channel;
	longword  destIP;
	static int counter;
	char *ptr;
	int numbytes;
	
	int tcp_status;
	int len, key;
				
	tcp_Socket socket;

	#GLOBAL_INIT {connected=FALSE;}

	tcp_tick(NULL);
	switch(*state)
	{
		case 0:
			status = 0;
			value = 0;
			channel = 0;
			old_channel = -1;
			cursor_location = 0;
			display_analog = TRUE;
			glBlankScreen();
			displayAnalog(channel, value, &row, &col);
			*state = 1;
			counter = 0;
			break;
						
		case 1:
			if(!connected)
			{
				destIP = resolve(DEST);
				tcp_open(&socket,0,destIP,PORT,NULL);
				sock_mode(&socket,TCP_MODE_BINARY);
				*state = 2;
			}
			else
			{
				*state = 3;
			}
			break;
		
		case 2:	
			if(sock_established(&socket))
			{	
				connected = TRUE;
				*state = 3;
			}			
			break;

		case 3:
			sock_fastwrite(&socket,"Send Analog ch1\n", sizeof("Send Analog ch1\n"));
			tcp_tick(&socket);
			*state = 4;
			break;

		case 4:
			if(sock_bytesready(&socket)> 0)
			{
				len = sock_fastread(&socket,buffer,sizeof(buffer));
				buffer[len] = '\0';
				value = atof(buffer);
				displayAnalog(channel, value, &row, &col);
				*state = 3;
			}
			
			keyProcess ();
			if(keyGet() != 0)
			{
				display_analog = FALSE;
				old_channel = -1;
				*state = 5;
			}
			break;
			
		case 5:
			// Dump data before closing the socket 
			if(sock_rbused(&socket) > 0)
			{
				sock_fastread(&socket,buffer,sizeof(buffer));
			}
			else
			{
	   		//sock_close(&socket);
	   		sock_abort(&socket);
				*state = 6;
			}
			break;

		case 6:
			// Dump data before closing the socket 
			if(sock_rbused(&socket) > 0)
			{
				sock_fastread(&socket,buffer,sizeof(buffer));
			}
			if(sock_tbused(&socket) > 0)
			{
				sock_flush(&socket);
			}	
			if(tcp_tick(&socket) == 0)
			{
				*state = -1;
				connected = FALSE;
			}
			break;
	}
	return(*state);
}

//------------------------------------------------------------------------
// Sample program to demonstrate the LCD and keypad
//------------------------------------------------------------------------
void main (	void	)		
{
	auto int option, initialize;
	static int state;
	
	//------------------------------------------------------------------------
	// Initialize the controller
	//------------------------------------------------------------------------	
	brdInit();			// Initialize for this demo
	
	dispInit();			// Start-up the keypad driver, Initialize the graphic driver

	keypadDef();		// Use the default keypad ASCII return values

	glBackLight(1);	// Turn-on the backlight
	glXFontInit(&fi6x8, 6, 8, 32, 127, Font6x8);			//	Initialize 6x8 font
	glXFontInit(&fi8x10, 8, 10, 32, 127, Font8x10);		//	Initialize 10x16 font
	glXFontInit(&fi12x16, 12, 16, 32, 127, Font12x16);	//	Initialize 12x16 font
	
	// Setup and center text window to be the entire display
	TextWindowFrame(&textWindow, &fi6x8, 1, 0, 121, 32);

	//------------------------------------------------------------------------
	// Text window initialization for analog menu
	//------------------------------------------------------------------------
	// Setup the widow frame to be the entire LCD to display information
	TextWindowFrame(&textWindow1, &fi6x8, 14, 4, 122-14, 8);
	TextWindowFrame(&textWindow2, &fi6x8, 0, 17, 122, 8);

	// Set variables to known states 
	initialize = TRUE; 	// Set flag for MENU options to be displayed
	ledCntrl = LEDOFF;	// Initially disable the LED's

	//------------------------------------------------------------------------
	// Display Sign-on message and wait for keypress
	//------------------------------------------------------------------------
	SignOnMessage();

	sock_init();
	
	//------------------------------------------------------------------------
	// Main program loop for the MENU system 
	//------------------------------------------------------------------------
	for (;;)
	{
		costate
		{
			keyProcess ();
			waitfor(DelayMs(10));
		}
		
		costate
		{
			leds(OPERATE);
			waitfor(DelayMs(100));
		}
		costate
		{
			// Display the MAIN MENU
			waitfor((option = display_menu(main_menu, initialize)) > 0);

			// Get menu option from the user
			switch(option)
			{  
				// Turn Backlight OFF
				case 1:	state = 0;
							waitfor(analog_menu(&state) == -1);
							initialize = TRUE;
							break;	
			
				// Enable Toggle leds option	
				case 2:	leds(TOGGLE);
							initialize = FALSE;
							break;	

				// Enable Increment leds option	
				case 3:	leds(INCREMENT);
							initialize = FALSE;
							break;	

				// Disable LED's
				case 4:	leds(LEDOFF);
							initialize = FALSE;
							break;	

				// Turn Backlight OFF
				case 5:
							glBackLight(0);
							initialize = FALSE;
							break;	

				// Turn Backlight ON
				case 6:	
							glBackLight(1);
							initialize = FALSE;
							break; 	

				// Display current Date/Time
				case 7:	
							glBlankScreen();
							waitfor(dispDate());
							initialize = TRUE;
							break;	
							
				// Change Date/Time
				case 8:	
							SetDateTime();						
							initialize = TRUE;
							break; 			
							
				// User made invalid selection
				default:												
					break;
			}
		}
	}
}
