/********************************************************************
	tcp_send.c
	Z-World, 2001
 	(Adapted from Intellicom's tcp_send.c) 	

 	This sample program is used with controller boards
 	equipped with ethernet, LCD and keypad.  A 122x32 pixel
 	display and 1x7 keypad module with LED's are assumed.

	This program and tcp_respond.c are to be executed on two different
	controller boards so that the two boards communicate with each
	other using a crossover cable.
	In the absence of a second board, pcrespond.exe can be
	used on the PC console side at the command prompt. This executable
	and source code is located in \samples\lcd_keypad\windows directory.

	When a key on the keypad is pressed, a message associated with
	that key	is sent to a specified destination address and port.
	The destination then responds to that message.  The response is
	displayed to the LCD.

	Note: Currently only LEFT and UP scroll keys are setup to
	      cause a message to be sent. 
		
********************************************************************/
#class auto		// Change default: local vars now stored on stack.
#memmap xmem  // Required to reduce root memory usage 

fontInfo fi6x8;
windowFrame wholewindow;

/***********************************
 * 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


/*
 * 	Have TCP install text error messages when trouble occurs.  If not
 * 	defined, then TcpSocket.err_msg is not used at all.
 * 	TcpSocket.err_msg == NULL if none.
 */
#define _SOCKET_MESSAGES

/*
 * 	How many seconds to wait for active connection.
 */
#define  CONNECT_TIMEOUT	10

/*
 * Also note that you will need to set up the messages in the main()
 * function.
 */
 
/********************************
 * End of configuration section *
 ********************************/
 
#memmap xmem
#use "dcrtcp.lib"

// The structure that holds a message and the destination
typedef struct {
	char *text;
	char *addr;
	word port;
} Message;

#define IGNORE 0x20


/*
 * General use 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 );
} 

/*
 * Send the message specified by the key value.  Note that the message
 * number is actually one less than the key number (since key number 0
 * cannot be used).
 * 	RETURN: 	0 = good, -1 = error.
 */
int SendMessage(unsigned key, Message messageArray[])
{
	auto tcp_Socket	tcpSock;
	auto longword		remIP;
	auto int 			numBytes;
	auto char 			buffer[500];
	auto longword 		timeout;
	auto char *			p;
	auto int 			result;

	/*  glBlankScreen() doesn't change cursor position, so must do both. */
	glBlankScreen();
	TextGotoXY(&wholewindow, 0, 0 );

	remIP = inet_addr(messageArray[key].addr);
	tcpSock.err_msg = 0;
	tcp_open(&tcpSock, 0, remIP, messageArray[key].port, NULL);

	/* Wait for connection -- 10 seconds. */
	timeout = SEC_TIMER + CONNECT_TIMEOUT;
	while( !tcp_established(&tcpSock) )
	{
		if( (long)(SEC_TIMER - timeout) >= 0 )
		{
			TextPrintf(&wholewindow, "ERROR: connect: timeout");
			return -1;
		}
		if( ! tcp_tick( (sock_type *) & tcpSock ) )
		{
			TextPrintf(&wholewindow, "ERROR: connect: %s\n", tcpSock.err_msg );
			return -1;
		}
	}

	/*  Write the message text, including the trailing NULL byte. */
	p = messageArray[key].text;
	for( numBytes = strlen(p)+1 ; numBytes > 0 ; )
	{
		result = sock_fastwrite( &tcpSock, p, numBytes );
		if( result < 0 || ! tcp_tick( (sock_type *) &tcpSock ) )
		{
			TextPrintf(&wholewindow,  "ERROR: write: %s\n", tcpSock.err_msg );
			return -1;
		}
		numBytes -= result;
		p += result;
	}


	TextPrintf(&wholewindow, "Message sent.......\nwaiting for response");

	/*  Wait for some data to appear, or an error... */
	while((numBytes = sock_fastread(&tcpSock, buffer, sizeof(buffer))) == 0)
	{
		if( ! tcp_tick( &tcpSock ) || numBytes == -1)
		{
			TextGotoXY(&wholewindow, 0, 0 );
			TextPrintf(&wholewindow, "ERROR: read: %s\n", tcpSock.err_msg );
			return -1;
		}
	}

	// Display response message
	glBlankScreen();	
	buffer[numBytes] = '\0';
	TextGotoXY(&wholewindow, 0, 0 );
	TextPrintf(&wholewindow, "%s", buffer);
	sock_close(&tcpSock);

	// Delay so that the response message can be read
	msDelay(2000);

	// Wait until the socket is closed
	while (tcp_tick(&tcpSock) != 0 );
	return 0;
}

void flashled(int led)
{
	switch (led)
	{
		case 0:  led = 0; break;
		case 1:  led = 1; break;
		case 2:  led = 2; break;
		case 3:  led = 3; break;
		default: led = 6; break;
	}
	dispLedOut(led,1);
	msDelay(400);
	dispLedOut(led,0);
	msDelay(400);
}

void initsystem(void)
{
	
	brdInit();
	dispInit();
	glXFontInit(&fi6x8, 6, 8, 32, 127, Font6x8);
	TextWindowFrame(&wholewindow, &fi6x8, 0, 0, LCD_XS, LCD_YS);
	glBackLight(1);
}

void main(void)
{
	Message messageArray[12];
	unsigned int key;
	int i;

	// Initialize the message array
	for (i = 0; i < (sizeof(messageArray)/sizeof(Message)); i++)
	{
		messageArray[i].text = NULL;
	}

	// Define messages here--note that you only need define the messages you
	// will actually use.  The IP addresses should NOT be MY_IP_ADDRESS !
	messageArray[0].text = "This is test 1.";
	messageArray[0].addr = "10.10.6.176";			/* IP or hostname of destination */
	messageArray[0].port = 4040;

	messageArray[1].text = "This is test 2.";
	messageArray[1].addr = "10.10.6.176";			/* IP or hostname of destination */
	messageArray[1].port = 4040;
		
	initsystem();
	sock_init();
	
	// Configure keys on the keypad, in order from left to right.
	for (i = 0; i < 7; i++)
	{
		// Only enable a key if there is a corresponding message
		if (messageArray[i].text != NULL)
		{
			keyConfig ( i, ('0'+ i), 0, 0, 0, 0, 0 );
		}
		else
		{
			keyConfig ( i, IGNORE, 0, 0, 0, 0, 0 );
		}
	}

	while (1)
	{
		//	Process Keypad Press/Hold/Release
		costate
		{								
			keyProcess();
			waitfor (DelayMs(10));
		}
			
		costate
		{								
			TextGotoXY(&wholewindow, 0, 0 );
			TextPrintf(&wholewindow, "Press the KEY that\ncorresponds to the\nmessage that you\nwant to send...");
			waitfor ( key = keyGet() );	//	Wait for Keypress

			// Flash LEDs to indicate that a key was pressed
			flashled(key-'0');
			
			if (key != IGNORE)
			{
				if( SendMessage((key-'0'), messageArray) < 0 )
				{
					/* If error message, display for a moment, then clear. */
					waitfor( DelayMs(3000) );
					glBlankScreen();
				}
			}
		}
	}   

}  
