(main)
1. Introduction
2. The Protocol
	Initialization
	Usage
	Shutdown
	Message Formats
3. Class vNet
4. Class vPacket
5. Conclusion
	Code Sample: demoApplet.java
	Code Sample: demo.a96 

 

The vNet Protocol

Developer’s Guide

 

Copyright 1997

Anurag Sharma

Ted Bonkenburg

    

Introduction

 

Presented in this document is an in-depth discussion of user level details of the vNet protocol which runs over TCP/IP. The vNet protocol is implemented in the vNet Java class, which is public domain (freeware) for developers. Using the vNet class, developers can write Java applets or applications that can interact with assembly programs that support vNet (see Visual Asm Environment for 80C196KB Developer’s Guide) over the internet. The vNet protocol consists of a limited number of message types and a few simple routines which provide the basic functionality for any Java application or applet (note that anything that can be done with an applet can be done with an application, so we will simply use the term "applet" from now on). This document should provide all the information necessary for a developer to create an applet that makes use of the vNet protocol to communicate with a micro-controller.

 

The Protocol

 

Initialization: To use vNet, the two class files "vNet" and "vPacket" must be included in the Java project. To initialize a connection with the proxy server, the applet must use the Connect() function provided in the vNet class.

 

Usage: There are two available methods for communication. These consist of SendMsg() and RecvMsg(). Both functions use the vPacket class to handle messages. The standard communication procedure is to create a new vPacket object that contains the message to be sent and another vPacket object in which the message from the proxy server is received. The convention for communicating with the proxy server is strict in that for every message sent (which is basically a request), the client must wait and receive a reply (which is some form of acknowledgment, usually with extended information). Appropriate actions, including error handling, should be done based on the proxy server’s reply for each request.

 

Shutdown: A good applet should gracefully shut down the connection by calling the Close() method of the vNet class before it terminates. Note that the proxy server is fault tolerant, in that it will recover from a lost connection, but this is not good practice in general.

 

Message Formats: Every message must adhere to a standard format. All messages have a standard message id and an optional message buffer (depending on the particular message). The following is a list of all message formats currently supported:

Message ID Description

 

NET_ERROR				General purpose error reply by proxy server
						Buffer: null
 
ASSEMBLE_CODE				Assemble code directive to server.
						Buffer: the code to be assembled
 
ASSEMBLY_COMPLETE_SUCCESS		Assembly completion reply from server
						Buffer: output from assembler
 
ASSEMBLY_COMPLETE_ERROR			Assembly completion reply from server
						Buffer: output from assembler
 
EXECUTE_CODE				Execution directive to server
						Buffer: null
EXECUTE_CODE_SUCCESS			Execution reply from server
						Buffer: null
 
EXECUTE_CODE_ERROR			Execution reply from server
						Buffer: null
 
QUERY_REGISTER				Request for vRegister contents to server
						Buffer[0] = register id number 0..15
 
QUERY_REGISTER_REPLY			Contents of requested register from server
						Buffer[0] = high byte
						Buffer[1] = low byte
 
 
HALT_CODE					Directive to server to halt code execution
						Buffer: null
 
HALT_CODE_SUCCESS			Halt of code execution reply from server
						Buffer: null
 
HALT_CODE_ERROR				Halt of code execution reply from server
						Buffer: null
 
RESUME_CODE				Directive to server to resume code execution
						The return messages from server are
						HALT_CODE_SUCCESS
or HALT_CODE_ERROR
						Buffer: null
 
MODIFY_REGISTER				Directive to server to modify register contents
						Buffer[0] = register id number
						Buffer[1] = low byte
						Buffer[2] = high byte
 
MODIFY_REGISTER_REPLY 			Reply from server for register modification
						Buffer: null

 

 

Class vNet

 

class vNet	{
 
	//Message id's
	public static final byte NET_ERROR;
	public static final byte ASSEMBLE_CODE;
	public static final byte ASSEMBLY_COMPLETE_SUCCESS;
	public static final byte ASSEMBLY_COMPLETE_ERROR;
	public static final byte EXECUTE_CODE;
	public static final byte EXECUTE_CODE_SUCCESS;
	public static final byte EXECUTE_CODE_ERROR;
	public static final byte QUERY_REGISTER;
	public static final byte QUERY_REGISTER_REPLY;
	public static final byte HALT_CODE;
	public static final byte HALT_CODE_SUCCESS;
	public static final byte HALT_CODE_ERROR;
	public static final byte RESUME_CODE;
	public static final byte MODIFY_REGISTER;
	public static final byte MODIFY_REGISTER_REPLY;
	
	//Methods
	/** Connect : connects to given IP address (TCP)*/
	public static boolean Connect(String ipAddr);
	
	/** Close : shuts down socket if connected */
	public static void Close();
 
	/** SendMsg : sends the given packet */
	synchronized public static boolean SendMsg(vPacket sendPacket);
 
	/** RecvMsg : returns a received packet or a NET_ERROR packet */
	synchronized public static vPacket RecvMsg();
 
} /* end class vNet */

 

 

Class vPacket

 
class vPacket {
 
	/** Constructor */
	vPacket(byte id, int size, byte[] buffer);
 
	/** Constructor */
	vPacket(byte id);
 
	public byte bId;
	public int iSize;
	public byte[] buff;
 
} /* end class vPacket */
 
 
	Constructors: 
 
	vPacket.vPacket
 
	/** Constructor */
	vPacket(byte id, int size, byte[] buffer);
	
	Creates a new packet with the provided id and the given buffer. The size 			
	parameter is used to specify the length of the given buffer, but may be less
	than the actual size of the buffer. 
 
	Parameters:
	id - one of the message id members of class vNet
	size - the size of the data in the buffer
	buffer - a byte array (may be bigger than size)
 

	/** Constructor */
	vPacket(byte id);
 
	Creates a new packet with the provided id and a null buffer. The size is set to zero.
 
	Parameters:
	id - one of the message id members of class vNet

 

 

 

Conclusion


This completes the description of the vNet protocol. In order to ease the transition into using vNet, the following is code for a sample applet provided by the development team. It simply adds two number using four vRegisters. The assembly code was created and tested using the Visual Asm Environment for 80C196KB.

 

demoApplet.java: Demonstration applet using the vNet protocol.

 

/* demoApplet.java */
 
import vNet;
import java.awt.*;
import java.applet.*;
 
public class demoApplet extends Applet
{
 
	//Class vars
	TextField	op1;
	TextField	op2;
	Button		addButt;
	TextField	result;
	String		strHost = null;	
 
	/** init() */
	public void init()
	{
		strHost = getParameter("Host");
		if(strHost == null)	{
			return;
		}
		vNet.Connect(strHost);
		//Init vars
		op1 = new TextField(10);
		op2 = new TextField(10);
		addButt = new Button("Add!");
		result = new TextField(15);
		result.setEditable(false);
		
		//Set the layout
		setLayout(new FlowLayout());
		add(op1);
		add(op2);
		add(addButt);
		add(result);
 
		resize(320, 320);
 
	} /* end init */
 
	/** action */
	public boolean action(Event evt, Object whatAction)
	{	
		/** BUTTON */
		if(evt.target instanceof Button) {
			String buttonLabel = (String) whatAction;
 
			/**Add!*/
			if(buttonLabel.equals("Add!")) {
 
				int iOp1;
				int iOp2;
				int	answer;
				try {
					iOp1 = (Integer.valueOf(op1.getText())).intValue();
					iOp2 = (Integer.valueOf(op2.getText())).intValue();
					//process
					addButt.disable();
					answer = ProcessOperands(iOp1, iOp2);
					addButt.enable();
					if(answer == -1) {
						result.setText("Sorry- Try again.");
					}
					else {
						result.setText(answer + " ");
					}
				}
				catch(NumberFormatException nfe) {					
					result.setText("Bad operand(s)!");
				}
 
			} /* end if Add!*/
		}
		return true;
	} /* end action() */
	
	/** Called when unloading applet */
	public void destroy()
	{
		vNet.Close();
	} /* end destroy() */
	
	/** ProcessOperands : does the adding work */
	public int	ProcessOperands(int a, int b)	{
		//send operands
		byte[]	buff = new byte[3];
		vPacket	outPacket = null;
		vPacket	inPacket = null;
 
		//modify vR1 with "a"
		buff[0] = (byte) 1;
		buff[1] = (byte) (a & 0xff);		//low byte
		buff[2] = (byte) ((a >> 8) & 0xff);	//high byte
		outPacket = new vPacket(vNet.MODIFY_REGISTER, 3, buff);
		vNet.SendMsg(outPacket);
		inPacket = vNet.RecvMsg();
		if(inPacket.bId != vNet.MODIFY_REGISTER_REPLY)	{
			//post error
			return -1;
		}
 
		//modify vR2 with "b"
		outPacket.buff[0] = (byte) 2;
		outPacket.buff[1] = (byte) (b & 0xff);		//low byte
		outPacket.buff[2] = (byte) ((b >> 8) & 0xff);	//high byte
		vNet.SendMsg(outPacket);
		inPacket = vNet.RecvMsg();
		if(inPacket.bId != vNet.MODIFY_REGISTER_REPLY)	{
			//post error
			return -1;
		}
		
		//set flag vR0
		outPacket.buff[0] = (byte) 0;
		outPacket.buff[1] = (byte) 1;	//set it to one
		outPacket.buff[2] = (byte) 0;
		vNet.SendMsg(outPacket);
		inPacket = vNet.RecvMsg();
		if(inPacket.bId != vNet.MODIFY_REGISTER_REPLY)	{
			//post error
			return -1;
		}
		
		//get result in vR3
		buff = new byte[1];
		buff[0] = 3;
		outPacket = new vPacket(vNet.QUERY_REGISTER, 1, buff);
		vNet.SendMsg(outPacket);
		inPacket = vNet.RecvMsg();
		if(inPacket.bId != vNet.QUERY_REGISTER_REPLY)	{
			//post error
			return -1;
		}
		return ((inPacket.buff[0] << 8) & 0xff00) | (inPacket.buff[1] & 0xff);
	} /* end ProcessOperands() */
	
} /* end class demoApplet */
	
 

demo.a96: Assembly code (for the Intel 80C196KB micro-controller) for use with the demoApplet.java code.


; demo.a96 (demo assembly file for Intel 80C196KB micro-controller)
;	 developed using Visual Asm Environment for 80C196KB
 
$EP PL(79) PW(115) NOSB DB
$include(vSetup.inc)
 
 
	rseg at 60H
 
; no need to declare any registers use the vR's
 
	cseg at 3000H
 
start:	ld	sp, #100H	; init stack pointer
	clr	vR0		; clear flag
loop:	bbc	vR0, 0, $		; wait for flag to be toggled
	add	vR3, vR2, vR1	; add the inputs and put them in result register
	clr	vR0		; reset flag
	br	loop		; wait for next toggle
 
;;;Default Interrupt Routines
	cseg at 7FE2H
int00:	br	$
int01:	br	$
int02:	br	$
int03:	br	$
int04:	br	$
int05:	br	$
int06:	br	$
int07:	br	$
int10:	br	$
int11:	br	$
int12:	br	$
int13:	br	$
int14:	br	$
 
end