/*
* $Log: RemoteControlSensor.java,v $
* Revision 1.2 2002/11/01 16:03:35 mpscholz
* support of LEGO F7 protocol
*
* Revision 1.1 2002/09/28 10:32:28 mpscholz
* initial version of the remotecontrol package
*
*/
package josx.platform.rcx.remotecontrol;
import java.io.*;
import java.util.*;
import josx.platform.rcx.*;
/////////////////////////////////////////////////////////
/**
*
* This class is a sensor for remote control messages.
*
It listens for remote control messages and triggers the registered listener
* methods.
*
F7 LEGO firmware opcodes are supported also which means that the sender could use RCXF7Port
*
instead of the LEGO remote control
*
The sensor uses the built-in lejos SerialListener thread
*
* @author Matthias Paul Scholz (mp.scholz@t-online.de)
* @version 1.1 (16/10/2002)
*/
public class RemoteControlSensor implements SerialListener,Opcode {
////////////////////////////////////////////
// constants
////////////////////////////////////////////
/**
* the F7 LEGO firmware F7 opcode byte
*/
private static final byte F7_OPCODE = (byte)0xF7;
////////////////////////////////////////////
// fields
////////////////////////////////////////////
/**
* the F7 LEGO firmware F7 acknowledge packet
*/
private byte [] fF7AckPacket = { F7_OPCODE,0x00 };
/**
* the F7 buffer
*/
private byte[] fF7Buffer = { 0x00,0x00 };
/**
* the F7 packet counter
*/
private int fF7Counter = 0;
/**
* the remote control listeners
*/
private Vector fListeners = null;
////////////////////////////////////////////
// constructors
////////////////////////////////////////////
////////////////////////////////////////////
/**
* creates a new instance of RemoteControlSensor
*/
public RemoteControlSensor() {
// instantiate listeners vector
fListeners = new Vector(2,2);
// add a SerialListener to Serial
Serial.addSerialListener(this);
} // RemoteControl()
////////////////////////////////////////////
// public methods
////////////////////////////////////////////
////////////////////////////////////////////
/**
adds a remote control listener
@param aListener a remote control listener
@see RemoteControlListener
*/
public void addRemoteControlListener(RemoteControlListener aListener) {
fListeners.addElement(aListener);
} // addRemoteControlListener()
////////////////////////////////////////////
/**
* removes a remote control listener
* @param aListener a remote control listener
* @see RemoteControlListener
*/
public void removeRemoteControlListener(RemoteControlListener aListener) {
fListeners.removeElement(aListener);
} // removeRemoteControlListener()
////////////////////////////////////////////
/**
* implements the SerialListener interface
*
listens for incoming packets on the IR port
* and notifies the registered listeners.
* @param byte[] the packet data received
* @param int the length of the packet
*/
public void packetAvailable(byte[] aPacket, int aLength) {
// length must be 3 at least
if(aLength<3)
return;
// opcode
int opcode = 0;
// check protocol
byte protocol = aPacket[0];
// we support F7 LEGO firmware protocol also
if(protocol==F7_OPCODE) {
// put first opcode byte into F7 buffer
fF7Buffer[fF7Counter] = aPacket[1];
// send an ack
if(!acknowledgeF7(aPacket)) {
// acknowledgement failed
Sound.buzz();
return;
} // if
// increment F7 counter
fF7Counter++;
// complete F7 message?
if(fF7Counter<2) {
// wait for next F7 byte
return;
} else {
// reset F7 counter
fF7Counter = 0;
// inspect F7 message
opcode = (fF7Buffer[0]&255)*256+(fF7Buffer[1]&255);
} // if
} // if
// if no F7, we check for the standard LEGO remote control protocol
else if((protocol&255)==(OPCODE_REMOTE_COMMAND&255)) {
opcode = (aPacket[1]&255)*256+(aPacket[2]&255);
} else
return;
// now inspect packet opcode
inspect(opcode);
} // packetAvailable()
////////////////////////////////////////////
// private methods
////////////////////////////////////////////
////////////////////////////////////////////
/**
* sends acknowledge data for F7 LEGO firmware messages
* @param byte[] the incoming packet to acknowlegde
* @return true if the acknowledge data was successfully sent, else false
*/
private boolean acknowledgeF7(byte[] anIncomingPacket) {
synchronized (this) {
// build acknowledge data
byte incoming = anIncomingPacket[1];
fF7AckPacket[1] = (byte) ~incoming;
// wait if Serial is sending at the moment
while(Serial.isSending())
Thread.yield();
// send data
return Serial.sendPacket(fF7AckPacket,0,2);
} // synchronized
} // acknowledge()
////////////////////////////////////////////
/**
* inspects the opcode sent.
* @param anOpcode the opcode
*/
private void inspect(int anOpcode) {
// check codes & trigger assigned handler
// a bit wordy due to the lacking of the switch-statement
// "message 1" pressed
if (anOpcode==0x01)
// notify listeners
for(int i=0;i