diff --git a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java index 0819b616e..21ed157ce 100644 --- a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java +++ b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java @@ -44,6 +44,7 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.mote.memory.MemoryInterface; import org.contikios.cooja.motes.AbstractEmulatedMote; + import avrora.arch.avr.AVRProperties; import avrora.core.LoadableProgram; import avrora.sim.AtmelInterpreter; @@ -54,6 +55,8 @@ import avrora.sim.mcu.EEPROM; import avrora.sim.platform.MicaZ; import avrora.sim.platform.PlatformFactory; +import org.contikios.cooja.avrmote.interfaces.MicaClock; + /** * @author Joakim Eriksson, Fredrik Osterlind */ @@ -74,6 +77,10 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { private EEPROM eeprom = null; + private long executed = 0; + private long skipped = 0; + + /* Stack monitoring variables */ private boolean stopNextInstruction = false; @@ -184,6 +191,10 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { private long cyclesExecuted = 0; private long cyclesUntil = 0; public void execute(long t) { + MicaClock clock = ((MicaClock) (myMoteInterfaceHandler.getClock())); + double deviation = clock.getDeviation(); + long drift = clock.getDrift(); + /* Wait until mote boots */ if (myMoteInterfaceHandler.getClock().getTime() < 0) { scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime()); @@ -196,13 +207,22 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { } /* TODO Poll mote interfaces? */ - + + /* skip if necessary */ + if (((1-deviation) * executed) > skipped) { + skipped += 1; + scheduleNextWakeup(t + Simulation.MILLISECOND); + } + /* Execute one millisecond */ cyclesUntil += NR_CYCLES_PER_MSEC; while (cyclesExecuted < cyclesUntil) { cyclesExecuted += interpreter.step(); } + /* book keeping */ + executed += 1; + /* TODO Poll mote interfaces? */ /* Schedule wakeup every millisecond */ diff --git a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java index 468e07a73..569e08dfd 100644 --- a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java +++ b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java @@ -54,10 +54,12 @@ public class MicaClock extends Clock { private MicaZMote myMote; private long timeDrift; /* Microseconds */ + private double deviation; public MicaClock(Mote mote) { simulation = mote.getSimulation(); myMote = (MicaZMote) mote; + deviation = 1.0; } public void setTime(long newTime) { @@ -68,6 +70,15 @@ public class MicaClock extends Clock { return simulation.getSimulationTime() + timeDrift; } + public double getDeviation() { + return deviation; + } + + public void setDeviation(double deviation) { + assert (deviation>0.0) && (deviation<=1.0); + this.deviation = deviation; + } + public void setDrift(long drift) { timeDrift = drift; } @@ -75,19 +86,4 @@ public class MicaClock extends Clock { public long getDrift() { return timeDrift; } - - public JPanel getInterfaceVisualizer() { - return null; - } - - public void releaseInterfaceVisualizer(JPanel panel) { - } - - public Collection getConfigXML() { - return null; - } - - public void setConfigXML(Collection configXML, boolean visAvailable) { - } - } diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java index 403376583..b22fbc145 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java @@ -78,6 +78,8 @@ import se.sics.mspsim.util.MapEntry; import se.sics.mspsim.util.MapTable; import se.sics.mspsim.profiler.SimpleProfiler; +import org.contikios.cooja.mspmote.interfaces.MspClock; + /** * @author Fredrik Osterlind */ @@ -288,13 +290,22 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc private long lastExecute = -1; /* Last time mote executed */ private long nextExecute; + + private long executed = 0; + private long skipped = 0; + public void execute(long time) { execute(time, EXECUTE_DURATION_US); } + public void execute(long t, int duration) { + MspClock clock = ((MspClock) (myMoteInterfaceHandler.getClock())); + double deviation = clock.getDeviation(); + long drift = clock.getDrift(); + /* Wait until mote boots */ - if (!booted && myMoteInterfaceHandler.getClock().getTime() < 0) { - scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime()); + if (!booted && clock.getTime() < 0) { + scheduleNextWakeup(t - clock.getTime()); return; } booted = true; @@ -313,12 +324,17 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc throw new RuntimeException("Bad event ordering: " + lastExecute + " < " + t); } + if (((1-deviation) * executed) > skipped) { + lastExecute = lastExecute + duration; // (t+duration) - (t-lastExecute); + nextExecute = t+duration; + skipped += duration; + scheduleNextWakeup(nextExecute); + } + /* Execute MSPSim-based mote */ /* TODO Try-catch overhead */ try { - nextExecute = - t + duration + - myCpu.stepMicros(t - lastExecute, duration); + nextExecute = myCpu.stepMicros(Math.max(0, t-lastExecute), duration) + t + duration; lastExecute = t; } catch (EmulationException e) { String trace = e.getMessage() + "\n\n" + getStackTrace(); @@ -330,7 +346,9 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc if (nextExecute < t) { throw new RuntimeException(t + ": MSPSim requested early wakeup: " + nextExecute); } + /*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/ + executed += duration; scheduleNextWakeup(nextExecute); if (stopNextInstruction) { diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java index c66352e98..10aacffad 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java @@ -52,9 +52,11 @@ public class MspClock extends Clock { private Simulation simulation; private long timeDrift; /* Microseconds */ + private double deviation; public MspClock(Mote mote) { simulation = mote.getSimulation(); + deviation = 1.0; } public void setTime(long newTime) { @@ -72,20 +74,13 @@ public class MspClock extends Clock { public long getDrift() { return timeDrift; } - - public JPanel getInterfaceVisualizer() { - /* TODO Show current CPU speed */ - return null; + + public void setDeviation(double deviation) { + assert (deviation>0.0) && (deviation<=1.0); + this.deviation = deviation; } - public void releaseInterfaceVisualizer(JPanel panel) { + public double getDeviation() { + return deviation; } - - public Collection getConfigXML() { - return null; - } - - public void setConfigXML(Collection configXML, boolean visAvailable) { - } - } diff --git a/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java b/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java index 127a7a3a7..b033ef06d 100644 --- a/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java +++ b/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java @@ -114,6 +114,14 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB public long getTime() { return moteTime; } + + public void setDeviation(double deviation) { + logger.fatal("Can't change deviation");; + } + + public double getDeviation() { + return 1.0; + } public void doActionsBeforeTick() { /* Update time */ @@ -161,5 +169,4 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB public void setConfigXML(Collection configXML, boolean visAvailable) { } - } diff --git a/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java b/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java index faefaddfc..58ec05fa5 100644 --- a/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java +++ b/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java @@ -30,7 +30,19 @@ package org.contikios.cooja.interfaces; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + import org.contikios.cooja.*; +import org.jdom.Element; /** * Represents a mote's internal clock. Notice that the overall @@ -39,10 +51,10 @@ import org.contikios.cooja.*; * This observable never notifies. * * @author Fredrik Osterlind + * Andreas Löscher */ @ClassDescription("Clock") public abstract class Clock extends MoteInterface { - /** * Set mote's time to given time. * @@ -76,4 +88,88 @@ public abstract class Clock extends MoteInterface { */ public abstract long getDrift(); + + /** + * The clock deviation is a factor that represents with how much speed the + * mote progresses through the simulation in relation to the simulation speed. + * + * A value of 1.0 results in the mote being simulated with the same speed + * as the simulation. A value of 0.5 results in the mote being simulation + * at half of the simulation speed. + * + * @param deviation Deviation factor + */ + public abstract void setDeviation(double deviation); + + /** + * Get deviation factor + */ + public abstract double getDeviation(); + + @Override + public JPanel getInterfaceVisualizer() { + JPanel panel = new JPanel(); + GridLayout layout = new GridLayout(0,2); + + /* elements */ + final JLabel timeLabel = new JLabel("Time (ms)"); + final JTextField timeField = new JTextField(String.valueOf(getTime() / 1000)); + final JLabel deviationLabel = new JLabel("Deviation Factor"); + final JTextField deviationField = new JTextField(String.valueOf(getDeviation())); + final JButton readButton = new JButton("Read Clock Values"); + final JButton updateButton = new JButton("Write Clock Values"); + /* set layout */ + panel.setLayout(layout); + /* add components */ + panel.add(timeLabel); + panel.add(timeField); + panel.add(deviationLabel); + panel.add(deviationField); + panel.add(readButton); + panel.add(updateButton); + + readButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent ev) { + if (ev.getButton()==1) { + timeField.setText(String.valueOf(getTime() / 1000)); + deviationField.setText(String.valueOf(getDeviation())); + } + } + }); + + updateButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent ev) { + if (ev.getButton()==1) { + setTime(Long.parseLong(timeField.getText()) * 1000); + setDeviation(Double.parseDouble(deviationField.getText())); + } + } + }); + + return panel; + } + + @Override + public void releaseInterfaceVisualizer(JPanel panel) { + } + + @Override + public Collection getConfigXML() { + ArrayList config = new ArrayList(); + Element element = new Element("deviation"); + element.setText(String.valueOf(getDeviation())); + config.add(element); + return config; + } + + @Override + public void setConfigXML(Collection configXML, boolean visAvailable) { + for (Element element : configXML) { + if (element.getName().equals("deviation")) { + setDeviation(Double.parseDouble(element.getText())); + } + } + } }