(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
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.
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 {
//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 {
/** 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
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