new radio driver (allows for transmissions longer than one tick)

This commit is contained in:
fros4943 2006-10-02 15:18:55 +00:00
parent c69f9298a4
commit 2ae5b09f30

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: ContikiRadio.java,v 1.2 2006/09/26 13:08:05 fros4943 Exp $ * $Id: ContikiRadio.java,v 1.3 2006/10/02 15:18:55 fros4943 Exp $
*/ */
package se.sics.cooja.contikimote.interfaces; package se.sics.cooja.contikimote.interfaces;
@ -41,21 +41,27 @@ import se.sics.cooja.contikimote.ContikiMoteInterface;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
/** /**
* This class represents a radio transciever. * This class represents a radio transciever. In order to simulate different
* transmission rates, the underlying Contiki system can be locked in either
* transmission or reception states (using multi-threading). When a transmission
* is initiated, it will automatically lock the Contiki system. When a packet is
* received by this radio the Contiki system, the entitiy transfering the packet may explicitly
* lock the radio in receiving mode. After some time it should then deliver the
* packet.
* *
* It needs read/write access to the following core variables: * It needs read/write access to the following core variables:
* <ul> * <ul>
* <li>char simSentPacket (1=mote has new outgoing data, else no new outgoing * <li>char simTransmitting (1=mote radio is transmitting)
* data) * <li>char simReceiving (1=mote radio is receiving)
* <li>char simReceivedPacket (1=mote has new incoming data, else no new * <p>
* incoming data) * <li>int simInSize (size of received data packet)
* <li>char simEtherBusy (1=ether is busy, MAC may try to resend later, else * <li>byte[] simInDataBuffer (data of received data packet)
* not busy) * <p>
* <li>int simReceivedPacketSize (size of new received data packet) * <li>int simOutSize (size of transmitted data packet)
* <li>int simSentPacketSize (size of new sent data packet) * <li>byte[] simOutDataBuffer (data of transmitted data packet)
* <li>byte[] simSentPacketData (data of new sent data packet) * <p>
* <li>byte[] simReceivedPacketData (data of new received data packet)
* <li>char simRadioHWOn (radio hardware status (on/off)) * <li>char simRadioHWOn (radio hardware status (on/off))
* <li>int simSignalStrength (heard radio signal strength)
* </ul> * </ul>
* <p> * <p>
* Dependency core interfaces are: * Dependency core interfaces are:
@ -63,13 +69,6 @@ import se.sics.cooja.interfaces.Radio;
* <li>radio_interface * <li>radio_interface
* </ul> * </ul>
* <p> * <p>
* This observable is changed and notifies observers whenever either the send
* status or listen status is changed. If current listen status is HEARS_PACKET
* just before a mote tick, the current packet data is transferred to the core.
* Otherwise no data will be transferred. If core has sent a packet, current
* sent status will be set to SENT_SOMETHING when returning from the mote tick
* that sent the packet. This status will be reset to SENT_NOTHING just before
* next tick.
* *
* @author Fredrik Osterlind * @author Fredrik Osterlind
*/ */
@ -86,17 +85,23 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
private final boolean RAISES_EXTERNAL_INTERRUPT; private final boolean RAISES_EXTERNAL_INTERRUPT;
private double energyActiveRadioPerTick = -1; private double energyListeningRadioPerTick = -1;
private int mySendState = SENT_NOTHING;
private int myListenState = HEARS_NOTHING;
private byte[] packetToMote = null; private byte[] packetToMote = null;
private byte[] packetFromMote = null; private byte[] packetFromMote = null;
private boolean radioOn = true; private boolean radioOn = true;
private double myEnergyConsumption=0.0; private double myEnergyConsumption = 0.0;
private boolean transmitting = false;
private int transmissionEndTime = 0;
private int receptionEndTime = 0;
private RadioEvent lastEvent = RadioEvent.UNKNOWN;
private int lastEventTime = 0;
/** /**
* Creates an interface to the radio at mote. * Creates an interface to the radio at mote.
@ -108,21 +113,27 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
*/ */
public ContikiRadio(Mote mote) { public ContikiRadio(Mote mote) {
// Read class configurations of this mote type // Read class configurations of this mote type
ENERGY_CONSUMPTION_RADIO_mA = mote.getType().getConfig().getDoubleValue(ContikiRadio.class, "ACTIVE_CONSUMPTION_mA"); ENERGY_CONSUMPTION_RADIO_mA = mote.getType().getConfig().getDoubleValue(
RAISES_EXTERNAL_INTERRUPT = mote.getType().getConfig().getBooleanValue(ContikiRadio.class, "EXTERNAL_INTERRUPT_bool"); ContikiRadio.class, "ACTIVE_CONSUMPTION_mA");
RAISES_EXTERNAL_INTERRUPT = mote.getType().getConfig().getBooleanValue(
ContikiRadio.class, "EXTERNAL_INTERRUPT_bool");
this.myMote = mote; this.myMote = mote;
this.myMoteMemory = (SectionMoteMemory) mote.getMemory(); this.myMoteMemory = (SectionMoteMemory) mote.getMemory();
if (energyActiveRadioPerTick < 0) // Calculate energy consumption of a listening radio
energyActiveRadioPerTick = ENERGY_CONSUMPTION_RADIO_mA * mote.getSimulation().getTickTimeInSeconds(); if (energyListeningRadioPerTick < 0)
energyListeningRadioPerTick = ENERGY_CONSUMPTION_RADIO_mA
* mote.getSimulation().getTickTimeInSeconds();
radioOn = myMoteMemory.getByteValueOf("simRadioHWOn") == 1;
} }
public static String[] getCoreInterfaceDependencies() { public static String[] getCoreInterfaceDependencies() {
return new String[] { "radio_interface" }; return new String[] { "radio_interface" };
} }
public byte[] getLastPacketSent() { public byte[] getLastPacketTransmitted() {
return packetFromMote; return packetFromMote;
} }
@ -130,109 +141,179 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
return packetToMote; return packetToMote;
} }
public void receivePacket(byte[] data) { public boolean isTransmitting() {
return transmitting;
}
public int getTransmissionEndTime() {
return transmissionEndTime;
}
public boolean isReceiving() {
if (isLockedAtReceiving())
return true;
return myMoteMemory.getIntValueOf("simInSize") != 0;
}
public RadioEvent getLastEvent() {
return lastEvent;
}
/**
* @return True if locked at transmitting
*/
private boolean isLockedAtTransmitting() {
return myMoteMemory.getByteValueOf("simTransmitting") == 1;
}
/**
* @return True if locked at receiving
*/
private boolean isLockedAtReceiving() {
return myMoteMemory.getByteValueOf("simReceiving") == 1;
}
/**
* Locks underlying Contiki system in receiving mode. This may, but does not
* have to, be used during a simulated data transfer that takes longer than
* one tick to complete. The system is unlocked by delivering the received
* data to the mote.
*
* @see #receivePacket(byte[])
*/
private void lockInReceivingMode() {
// If mote is inactive, try to wake it up
if (myMote.getState() != Mote.State.ACTIVE) {
if (RAISES_EXTERNAL_INTERRUPT)
myMote.setState(Mote.State.ACTIVE);
if (myMote.getState() != Mote.State.ACTIVE)
return;
}
// Lock core radio in receiving loop
myMoteMemory.setByteValueOf("simReceiving", (byte) 1);
lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.RECEPTION_STARTED;
this.setChanged();
this.notifyObservers();
}
public void receivePacket(byte[] data, int endTime) {
lockInReceivingMode();
receptionEndTime = endTime;
packetToMote = data; packetToMote = data;
} }
public int getSendState() { private void deliverPacket() {
return mySendState; // If mote is inactive, try to wake it up
} if (myMote.getState() != Mote.State.ACTIVE) {
if (RAISES_EXTERNAL_INTERRUPT)
public int getListenState() { myMote.setState(Mote.State.ACTIVE);
return myListenState; if (myMote.getState() != Mote.State.ACTIVE)
} return;
public void setListenState(int newStatus) {
if (newStatus != myListenState) {
myListenState = newStatus;
this.setChanged();
this.notifyObservers(myMote.getInterfaces().getPosition());
} }
// If mote is inactive, wake it up // Unlock (if locked)
if (RAISES_EXTERNAL_INTERRUPT) myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
myMote.setState(Mote.State.ACTIVE);
// Set data
myMoteMemory.setIntValueOf("simInSize", packetToMote.length);
myMoteMemory.setByteArray("simInDataBuffer", packetToMote);
lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.RECEPTION_FINISHED;
this.setChanged();
this.notifyObservers();
} }
public void advanceListenState() {
if (myListenState == HEARS_NOTHING) { /**
setListenState(HEARS_PACKET); * Resets receive status. If a packet, or part of a packet, has been received
} else * but not yet taken care of in the Contiki system, this will be removed.
setListenState(HEARS_NOISE); */
public void interferReception() {
// Unlock (if locked)
myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
// Reset data
myMoteMemory.setIntValueOf("simInSize", 0);
lastEvent = RadioEvent.RECEPTION_INTERFERED;
lastEventTime = myMote.getSimulation().getSimulationTime();
this.setChanged();
this.notifyObservers();
}
public double getCurrentSignalStrength() {
return myMoteMemory.getIntValueOf("simSignalStrength");
}
public void setCurrentSignalStrength(double signalStrength) {
myMoteMemory.setIntValueOf("simSignalStrength", (int) signalStrength);
} }
public void doActionsBeforeTick() { public void doActionsBeforeTick() {
// If radio hardware is turned off, we don't need to do anything.. // Do nothing
if (isLockedAtReceiving() && myMote.getSimulation().getSimulationTime() >= receptionEndTime)
deliverPacket();
}
public void doActionsAfterTick() {
// Check if radio hardware status changed
if (radioOn != (myMoteMemory.getByteValueOf("simRadioHWOn") == 1)) {
// Radio changed
radioOn = !radioOn;
if (!radioOn) {
// Reset status
myMoteMemory.setByteValueOf("simReceiving", (byte) 0);
myMoteMemory.setIntValueOf("simInSize", 0);
myMoteMemory.setByteValueOf("simTransmitting", (byte) 0);
myMoteMemory.setIntValueOf("simOutSize", 0);
transmitting = false;
lastEvent = RadioEvent.HW_OFF;
} else
lastEvent = RadioEvent.HW_ON;
lastEventTime = myMote.getSimulation().getSimulationTime();
this.setChanged();
this.notifyObservers();
}
if (!radioOn) { if (!radioOn) {
myEnergyConsumption = 0.0; myEnergyConsumption = 0.0;
return; return;
} }
myEnergyConsumption = energyActiveRadioPerTick; myEnergyConsumption = energyListeningRadioPerTick;
// Set ether status // Are we transmitting but should stop?
if (getListenState() == HEARS_PACKET || if (transmitting && myMote.getSimulation().getSimulationTime() >= transmissionEndTime) {
getListenState() == HEARS_NOISE || myMoteMemory.setByteValueOf("simTransmitting", (byte) 0);
getSendState() == SENT_SOMETHING) { myMoteMemory.setIntValueOf("simOutSize", 0);
myMoteMemory.setByteValueOf("simEtherBusy", (byte) 1); transmitting = false;
} else {
myMoteMemory.setByteValueOf("simEtherBusy", (byte) 0);
}
if (getListenState() == HEARS_NOTHING) { lastEventTime = myMote.getSimulation().getSimulationTime();
// Haven't heard anything, nothing to do lastEvent = RadioEvent.TRANSMISSION_FINISHED;
} else if (getListenState() == HEARS_PACKET) { // TODO Memory consumption of transmitted packet?
// Heard only one packet, transfer to mote ok
myMoteMemory.setByteValueOf("simReceivedPacket", (byte) 1);
myMoteMemory.setIntValueOf("simReceivedPacketSize", packetToMote.length);
myMoteMemory.setByteArray("simReceivedPacketData", packetToMote);
} else if (getListenState() == HEARS_NOISE) {
// Heard several packets or noise, transfer failed
}
// Reset send flag
setSendStatus(SENT_NOTHING);
}
public void doActionsAfterTick() {
// Check new radio hardware status
if (myMoteMemory.getByteValueOf("simRadioHWOn") == 1) {
radioOn = true;
} else {
radioOn = false;
return;
}
// Reset listen flag
setListenState(HEARS_NOTHING);
if (fetchPacketFromCore()) {
setSendStatus(SENT_SOMETHING);
}
}
private void setSendStatus(int newStatus) {
if (newStatus != mySendState) {
mySendState = newStatus;
this.setChanged(); this.setChanged();
this.notifyObservers(myMote.getInterfaces().getPosition()); this.notifyObservers();
} }
}
private boolean fetchPacketFromCore() { // Check if a new transmission should be started
if (myMoteMemory.getByteValueOf("simSentPacket") == 1) { if (!transmitting && myMoteMemory.getByteValueOf("simTransmitting") == 1) {
// TODO Increase energy consumption, we are sending a packet... transmitting = true;
int size = myMoteMemory.getIntValueOf("simOutSize");
packetFromMote = myMoteMemory.getByteArray("simOutDataBuffer", size);
transmissionEndTime = myMote.getSimulation().getSimulationTime() + 100; // TODO What's the duration?
myMoteMemory.setByteValueOf("simSentPacket", (byte) 0); lastEventTime = myMote.getSimulation().getSimulationTime();
lastEvent = RadioEvent.TRANSMISSION_STARTED;
int size = myMoteMemory.getIntValueOf("simSentPacketSize"); this.setChanged();
this.notifyObservers();
packetFromMote = myMoteMemory.getByteArray("simSentPacketData", size);
myMoteMemory.setIntValueOf("simSentPacketSize", 0);
return true;
} }
return false;
} }
public JPanel getInterfaceVisualizer() { public JPanel getInterfaceVisualizer() {
@ -240,41 +321,30 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface {
JPanel panel = new JPanel(); JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final JLabel listenLabel = new JLabel(); final JLabel statusLabel = new JLabel("");
final JLabel sendLabel = new JLabel(); final JLabel lastEventLabel = new JLabel("");
if (getListenState() == HEARS_NOISE) panel.add(statusLabel);
listenLabel.setText("Current listen status: hears noise"); panel.add(lastEventLabel);
else if (getListenState() == HEARS_NOTHING)
listenLabel.setText("Current listen status: hears nothing");
else if (getListenState() == HEARS_PACKET)
listenLabel.setText("Current listen status: hears a packet");
if (getSendState() == SENT_NOTHING)
sendLabel.setText("Current sending status: sent nothing");
else if (getSendState() == SENT_SOMETHING)
sendLabel.setText("Current sending status: sent a packet");
panel.add(listenLabel);
panel.add(sendLabel);
Observer observer; Observer observer;
this.addObserver(observer = new Observer() { this.addObserver(observer = new Observer() {
public void update(Observable obs, Object obj) { public void update(Observable obs, Object obj) {
if (getListenState() == HEARS_NOISE) if (isTransmitting())
listenLabel.setText("Current listen status: hears noise"); statusLabel.setText("Transmitting packet now!");
else if (getListenState() == HEARS_NOTHING) else if (isReceiving())
listenLabel.setText("Current listen status: hears nothing"); statusLabel.setText("Receiving packet now!");
else if (getListenState() == HEARS_PACKET) else if (radioOn)
listenLabel.setText("Current listen status: hears a packet"); statusLabel.setText("Listening...");
else
statusLabel.setText("HW turned off");
if (getSendState() == SENT_NOTHING) lastEventLabel.setText("Last event (time=" + lastEventTime + "): " + lastEvent);
sendLabel.setText("Current sending status: sent nothing");
else if (getSendState() == SENT_SOMETHING)
sendLabel.setText("Current sending status: sent a packet");
} }
}); });
observer.update(null, null);
// Saving observer reference for releaseInterfaceVisualizer // Saving observer reference for releaseInterfaceVisualizer
panel.putClientProperty("intf_obs", observer); panel.putClientProperty("intf_obs", observer);