package lego.explorer;
import util.Timer;
import lego.lib.Buttons;
import lego.lib.DigitalInputs;
import lego.lib.Leds;
/** common I/O for explorer bots */
public class BotInterface {
public static final int LED_STATUS_OFF = 0, LED_STATUS_BLINK = 1, LED_STATUS_ON = 2;
/** time **/
public static class TimeStamp {
public int secs;
public int usecs;
public void sync(TimeStamp ts) {
ts.secs = secs;
ts.usecs = usecs;
}
// FIXME: inefficient
public int msDiff(TimeStamp ts) {
int msdiff = (secs - ts.secs) * 1000;
msdiff += (usecs - ts.usecs) / 1000;
return msdiff;
}
}
public TimeStamp time = new TimeStamp();
private boolean timeInit = false;
private int usecBase = 0;
/* Board elements */
/** IR Sensor */
public IRSensor irSensor;
/** Drive */
public Drive drive;
/** Digitial sensors */
public boolean[] digitals = new boolean[3];
/** LEDs */
public int[] ledStatus = new int[Leds.LED_COUNT];
/** Buttons */
private boolean[] buttons = new boolean[4];
public boolean[] buttonEdge = new boolean[4];
public BotInterface(int irSensorId, int motorLeft, int motorRight) {
this.irSensor = new IRSensor(irSensorId);
this.drive = new Drive(motorLeft, motorRight);
}
/** For simplicity, this is for now a single write/read loop.
* This is a little unrealistic, though.
* Needs to be update at least every 20ms.
*
* FIXME: I didn't use JOPs Timer implementation, because it is unclear how to get a synchronized
* usec / sec pair. The subtraction trick is from there.
*/
public void update() {
int currentUS = Timer.us(); // relative us
if(! timeInit) {
time.secs = 0;
time.usecs = 0;
usecBase = currentUS;
timeInit = true;
} else {
int diff = currentUS - usecBase;
time.usecs += diff;
if(time.usecs >= 1000000) {
time.usecs -= 1000000;
time.secs++;
}
usecBase = currentUS;
}
// write
drive.write();
for(int i = 0; i < Leds.LED_COUNT; i++) {
if(ledStatus[i] == LED_STATUS_OFF) Leds.setLed(i, false);
else if(ledStatus[i] == LED_STATUS_ON) Leds.setLed(i, true);
else Leds.blinkUpdate(i);
}
// read
drive.read();
irSensor.updateSensor();
int buttonVal = Buttons.getButtons();
for(int ix = 0; ix < 4; ix++) {
boolean btnDown = ((buttonVal >> ix) & 1) != 0;
if(btnDown && ! buttons[ix]) buttonEdge[ix] = true;
else buttonEdge[ix] = false;
buttons[ix] = btnDown;
}
int digitalVal = DigitalInputs.getDigitalInputs();
for(int ix = 0; ix < 3; ix++) {
boolean digitalOn = ((digitalVal >> ix) & 1) != 1;
digitals[ix] = digitalOn;
}
}
public void dump() {
System.out.print("Interface State at time ");
System.out.print(time.secs);
System.out.print(".");
System.out.println(time.usecs);
irSensor.dump();
System.out.print("Buttons ");
for(int i = 0; i < 4; i ++) {
System.out.print(i);
System.out.print(" = ");
System.out.print(buttons[i]);
System.out.print(" | ");
}
System.out.print("\nDigitals ");
for(int i = 0; i < 3; i ++) {
System.out.print(i);
System.out.print(" = ");
System.out.print(digitals[i]);
System.out.print(" | ");
}
System.out.println("");
drive.dump();
}
}