package lejos.nxt.rcxcomm; /* * WARNING: THIS CLASS IS SHARED BETWEEN THE classes AND pccomms PROJECTS. * DO NOT EDIT THE VERSION IN pccomms AS IT WILL BE OVERWRITTEN WHEN THE PROJECT IS BUILT. */ /** * A Packet handler that guarantees reliable delivery using checksums, * acks, and a single bit sequence number. * **/ public class LLCReliableHandler extends PacketHandler { private byte [] inPacket = new byte[3]; private byte [] outPacket = new byte[3]; private byte [] inAck = new byte[2]; private byte [] outAck = new byte [2]; private int inPacketLength = 0; private boolean sequence = false, receiveSequence = false; public LLCReliableHandler(PacketHandler handler) { super(handler); } /** * Reset sequence numbers. **/ public void reset() { sequence = false; receiveSequence = false; } /** Send a packet. * @param packet the bytes to send * @param len the number of bytes to send * @return true if send successful, else false */ public boolean sendPacket(byte [] packet, int len) { byte b = (byte) (0xf0 + len); // Send byte if (sequence) b |= 8; outPacket[0] = b; int sum = b; for(int i=0; i<len; i++) { sum += packet[i]; outPacket[i+1] = packet[i]; } outPacket[len+1] = (byte) sum; for(int j=0;;j++) { int sendTime = (int)System.currentTimeMillis(); lowerHandler.sendPacket(outPacket,len+2); do { Thread.yield(); } while (!(lowerHandler.isAckAvailable()) && (int)System.currentTimeMillis() < sendTime+500); if (lowerHandler.isAckAvailable()) { int retLen = lowerHandler.receiveAck(inAck); if (retLen == 2 && inAck[0] == (byte) (b & 0xf8) && inAck[0] == inAck[1]) { sequence = !sequence; return true; } } } } /** Receive a packet. * @param buffer the buffer to receive the packet into * @return the number of bytes received */ public int receivePacket(byte [] buffer) { int temp = inPacketLength-2; for(int i=0;i<temp;i++) buffer[i] = inPacket[i+1]; inPacketLength = 0; return temp; } /** Check if a packet is available. * @return true if a packet is available, else false */ public boolean isPacketAvailable() { if (inPacketLength > 0) return true; while (lowerHandler.isPacketAvailable()) { int len = lowerHandler.receivePacket(inPacket); int sum = 0; for(int i=0; i<len-1; i++) sum += inPacket[i]; if ((byte) sum == inPacket[len-1]) { outAck[0] = (byte) (inPacket[0] & 0xf8); outAck[1] = outAck[0]; lowerHandler.sendPacket(outAck, 2); } else { continue; } // Check the sequence if ((inPacket[0] & 0x8) == (receiveSequence ? 0x8 : 0x0)) { inPacketLength = len; receiveSequence = !receiveSequence; return true; } } return false; } }