From 07753fb01f6bd0ebad0984282e4f34760a1bf871 Mon Sep 17 00:00:00 2001 From: fros4943 Date: Tue, 9 Mar 2010 08:11:05 +0000 Subject: [PATCH] updated radio driver, simplified code --- platform/cooja/dev/cooja-radio.c | 345 +++++++++--------- platform/cooja/dev/cooja-radio.h | 69 +--- .../contikimote/interfaces/ContikiRadio.java | 126 +++---- 3 files changed, 217 insertions(+), 323 deletions(-) diff --git a/platform/cooja/dev/cooja-radio.c b/platform/cooja/dev/cooja-radio.c index 0ab9554bd..0d1c6a42f 100644 --- a/platform/cooja/dev/cooja-radio.c +++ b/platform/cooja/dev/cooja-radio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2010, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,247 +26,236 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cooja-radio.c,v 1.10 2009/04/16 14:38:41 fros4943 Exp $ + * $Id: cooja-radio.c,v 1.11 2010/03/09 08:11:05 fros4943 Exp $ */ +#include #include + #include "contiki.h" +#include "sys/cooja_mt.h" +#include "lib/simEnvChange.h" + +#include "net/rime/packetbuf.h" +#include "net/rime/rimestats.h" +#include "net/netstack.h" + #include "dev/radio.h" #include "dev/cooja-radio.h" -#include "lib/simEnvChange.h" -#include "sys/cooja_mt.h" -#define USING_CCA 1 -#define USING_CCA_BUSYWAIT 1 -#define CCA_BUSYWAIT_MS 100 +#define COOJA_RADIO_BUFSIZE PACKETBUF_SIZE + #define CCA_SS_THRESHOLD -95 -#define SS_NOTHING -100 - const struct simInterface radio_interface; -// COOJA variables -char simTransmitting = 0; +/* COOJA */ char simReceiving = 0; - char simInDataBuffer[COOJA_RADIO_BUFSIZE]; int simInSize = 0; -char simInPolled = 0; char simOutDataBuffer[COOJA_RADIO_BUFSIZE]; int simOutSize = 0; - char simRadioHWOn = 1; -int simSignalStrength = SS_NOTHING; -int simLastSignalStrength = SS_NOTHING; +int simSignalStrength = -100; +int simLastSignalStrength = -100; char simPower = 100; int simRadioChannel = 26; -int inSendFunction = 0; -static void (* receiver_callback)(const struct radio_driver *); +static const void *pending_data; -const struct radio_driver cooja_radio = - { - radio_send, - radio_read, - radio_set_receiver, - radio_on, - radio_off, - }; +PROCESS(cooja_radio_process, "cooja radio process"); -/*-----------------------------------------------------------------------------------*/ -void -radio_set_receiver(void (* recv)(const struct radio_driver *)) -{ - receiver_callback = recv; -} -/*-----------------------------------------------------------------------------------*/ -int -radio_on(void) -{ - simRadioHWOn = 1; - return 1; -} -/*-----------------------------------------------------------------------------------*/ -int -radio_off(void) -{ - simRadioHWOn = 0; - return 1; -} /*---------------------------------------------------------------------------*/ void radio_set_channel(int channel) { simRadioChannel = channel; } -/*-----------------------------------------------------------------------------------*/ -int -radio_sstrength(void) -{ - return simLastSignalStrength; -} -/*-----------------------------------------------------------------------------------*/ -int -radio_current_sstrength(void) -{ - return simSignalStrength; -} -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ void radio_set_txpower(unsigned char power) { /* 1 - 100: Number indicating output power */ simPower = power; } -/*-----------------------------------------------------------------------------------*/ -static void -doInterfaceActionsBeforeTick(void) +/*---------------------------------------------------------------------------*/ +int +radio_signal_strength_last(void) { - // If radio is turned off, do nothing - if (!simRadioHWOn) { - simInSize = 0; - simInPolled = 0; - return; - } - - // Don't fall asleep while receiving (in main file) - if (simReceiving) { - simLastSignalStrength = simSignalStrength; - simDontFallAsleep = 1; - return; - } - - // If no incoming radio data, do nothing - if (simInSize == 0) { - simInPolled = 0; - return; - } - - // Check size of received packet - if (simInSize > COOJA_RADIO_BUFSIZE) { - // Drop packet by not delivering - return; - } - - // ** Good place to add explicit manchester/gcr-encoding - - if(receiver_callback != NULL && !simInPolled) { - simDoReceiverCallback = 1; - simInPolled = 1; - } else { - simInPolled = 0; - simDontFallAsleep = 1; - } + return simLastSignalStrength; } /*---------------------------------------------------------------------------*/ int -radio_read(void *buf, unsigned short bufsize) +radio_signal_strength_current(void) { - int tmpInSize = simInSize; - - if( bufsize < simInSize ) { - return 0; - } - - if(simInSize > 0) { - memcpy(buf, simInDataBuffer, simInSize); - simInSize = 0; - return tmpInSize; - } - return 0; + return simSignalStrength; } -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +static int +radio_on(void) +{ + simRadioHWOn = 1; + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +radio_off(void) +{ + simRadioHWOn = 0; + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +doInterfaceActionsBeforeTick(void) +{ + if (!simRadioHWOn) { + simInSize = 0; + return; + } + if (simReceiving) { + simLastSignalStrength = simSignalStrength; + return; + } + + if (simInSize > 0) { + process_poll(&cooja_radio_process); + } +} +/*---------------------------------------------------------------------------*/ static void doInterfaceActionsAfterTick(void) { - // Make sure we are awake during radio activity - if (simReceiving || simTransmitting) { - simDontFallAsleep = 1; - return; - } } -/*-----------------------------------------------------------------------------------*/ -int +/*---------------------------------------------------------------------------*/ +static int +radio_read(void *buf, unsigned short bufsize) +{ + int tmp = simInSize; + + if (simInSize == 0) { + return 0; + } + if(bufsize < simInSize) { + simInSize = 0; /* rx flush */ + RIMESTATS_ADD(toolong); + return 0; + } + + memcpy(buf, simInDataBuffer, simInSize); + simInSize = 0; + return tmp; +} +/*---------------------------------------------------------------------------*/ +static int radio_send(const void *payload, unsigned short payload_len) { - /* If radio already actively transmitting, drop packet*/ - if(inSendFunction) { - return COOJA_RADIO_DROPPED; - } - - inSendFunction = 1; - - /* If radio is turned off, do nothing */ if(!simRadioHWOn) { - inSendFunction = 0; - return COOJA_RADIO_DROPPED; + /* TODO Turn on radio temporarily during tx */ + return RADIO_TX_ERR; } - - /* Drop packet if data size too large */ if(payload_len > COOJA_RADIO_BUFSIZE) { - inSendFunction = 0; - return COOJA_RADIO_TOOLARGE; + return RADIO_TX_ERR; } - - /* Drop packet if no data length */ - if(payload_len <= 0) { - inSendFunction = 0; - return COOJA_RADIO_ZEROLEN; + if(payload_len == 0) { + return RADIO_TX_ERR; + } + if(simOutSize > 0) { + return RADIO_TX_ERR; } /* Copy packet data to temporary storage */ memcpy(simOutDataBuffer, payload, payload_len); simOutSize = payload_len; -#if USING_CCA_BUSYWAIT - /* Busy-wait until both radio HW and ether is ready */ - { - int retries = 0; - while(retries < CCA_BUSYWAIT_MS && !simNoYield && - (simSignalStrength > CCA_SS_THRESHOLD || simReceiving)) { - retries++; - cooja_mt_yield(); - if(!(simSignalStrength > CCA_SS_THRESHOLD || simReceiving)) { - /* Wait one extra tick before transmission starts */ - cooja_mt_yield(); - } - } - } -#endif /* USING_CCA_BUSYWAIT */ - -#if USING_CCA - if(simSignalStrength > CCA_SS_THRESHOLD || simReceiving) { - inSendFunction = 0; - return COOJA_RADIO_DROPPED; - } -#endif /* USING_CCA */ - - if(simOutSize <= 0) { - inSendFunction = 0; - return COOJA_RADIO_DROPPED; - } - - // - Initiate transmission - - simTransmitting = 1; - - // Busy-wait while transmitting - while(simTransmitting && !simNoYield) { + /* Transmit */ + while(simOutSize > 0) { cooja_mt_yield(); } - if (simTransmitting) { - simDontFallAsleep = 1; + + return RADIO_TX_OK; +} +/*---------------------------------------------------------------------------*/ +static int +prepare_packet(const void *data, unsigned short len) +{ + pending_data = data; + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +transmit_packet(unsigned short len) +{ + int ret = RADIO_TX_ERR; + if(pending_data != NULL) { + ret = radio_send(pending_data, len); + pending_data = NULL; + } + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +receiving_packet(void) +{ + return simReceiving; +} +/*---------------------------------------------------------------------------*/ +static int +pending_packet(void) +{ + return !simReceiving && simInSize > 0; +} +/*---------------------------------------------------------------------------*/ +static int +cca(void) +{ + if(simSignalStrength > CCA_SS_THRESHOLD) { + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cooja_radio_process, ev, data) +{ + int len; + + PROCESS_BEGIN(); + + while(1) { + PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); + + packetbuf_clear(); + len = radio_read(packetbuf_dataptr(), PACKETBUF_SIZE); + if(len > 0) { + packetbuf_set_datalen(len); + NETSTACK_RDC.input(); + } } - inSendFunction = 0; - return COOJA_RADIO_OK; + PROCESS_END(); } -/*-----------------------------------------------------------------------------------*/ -void radio_call_receiver() +/*---------------------------------------------------------------------------*/ +static int +init(void) { - receiver_callback(&cooja_radio); + process_start(&cooja_radio_process, NULL); + return 1; } -/*-----------------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +const struct radio_driver cooja_radio_driver = +{ + init, + prepare_packet, + transmit_packet, + radio_send, + radio_read, + cca, + receiving_packet, + pending_packet, + radio_on, + radio_off, +}; +/*---------------------------------------------------------------------------*/ SIM_INTERFACE(radio_interface, doInterfaceActionsBeforeTick, doInterfaceActionsAfterTick); diff --git a/platform/cooja/dev/cooja-radio.h b/platform/cooja/dev/cooja-radio.h index ddaec2688..413e21e7e 100644 --- a/platform/cooja/dev/cooja-radio.h +++ b/platform/cooja/dev/cooja-radio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2010, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,45 +28,16 @@ * * This file is part of the Contiki operating system. * - * $Id: cooja-radio.h,v 1.5 2009/04/01 13:44:34 fros4943 Exp $ + * $Id: cooja-radio.h,v 1.6 2010/03/09 08:11:05 fros4943 Exp $ */ #ifndef __COOJA_RADIO_H__ #define __COOJA_RADIO_H__ #include "contiki.h" -#include "contiki-conf.h" - #include "dev/radio.h" -#include "net/uip.h" -#include "net/uip-fw.h" - -#define COOJA_RADIO_BUFSIZE UIP_BUFSIZE -#define COOJA_RADIO_DROPPED UIP_FW_DROPPED -#define COOJA_RADIO_TOOLARGE UIP_FW_TOOLARGE -#define COOJA_RADIO_ZEROLEN UIP_FW_ZEROLEN -#define COOJA_RADIO_OK UIP_FW_OK - -extern const struct radio_driver cooja_radio; - -/** - * Turn radio hardware on. - */ -int -radio_on(void); - -/** - * Turn radio hardware off. - */ -int -radio_off(void); - -/** - * Set radio receiver. - */ -void -radio_set_receiver(void (* recv)(const struct radio_driver *)); +extern const struct radio_driver cooja_radio_driver; /** * Set radio channel. @@ -77,45 +48,21 @@ radio_set_channel(int channel); /** * Set transmission power of transceiver. * - * \param p The power of the tranceiver, between 1 (lowest) and 100 - * (highest). + * \param p The power of the transceiver, between 1 and 100. */ void radio_set_txpower(unsigned char p); /** - * Send a packet from the given buffer with the given length. + * The signal strength of the last received packet */ int -radio_send(const void *payload, unsigned short payload_len); +radio_signal_strength_last(void); /** - * Check if an incoming packet has been received. - * - * This function checks the receive buffer to see if an entire packet - * has been received. - * - * \return The length of the received packet, or 0 if no packet has - * been received. + * This current signal strength. */ int -radio_read(void *buf, unsigned short bufsize); - -/** - * This function returns the signal strength of the last - * received packet. This function typically is called when a packet - * has been received. - */ -int radio_sstrength(void); - -/** - * This function measures and returns the signal strength. - */ -int radio_current_sstrength(void); - -/** - * Internal COOJA function, calls the current receiver function. - */ -void radio_call_receiver(void); +radio_signal_strength_current(void); #endif /* __COOJA_RADIO_H__ */ diff --git a/tools/cooja/java/se/sics/cooja/contikimote/interfaces/ContikiRadio.java b/tools/cooja/java/se/sics/cooja/contikimote/interfaces/ContikiRadio.java index 64070149b..ca756bec7 100644 --- a/tools/cooja/java/se/sics/cooja/contikimote/interfaces/ContikiRadio.java +++ b/tools/cooja/java/se/sics/cooja/contikimote/interfaces/ContikiRadio.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ContikiRadio.java,v 1.31 2010/02/05 09:07:13 fros4943 Exp $ + * $Id: ContikiRadio.java,v 1.32 2010/03/09 08:11:05 fros4943 Exp $ */ package se.sics.cooja.contikimote.interfaces; @@ -66,7 +66,6 @@ import se.sics.cooja.radiomediums.UDGM; * * Contiki variables: *
    - *
  • char simTransmitting (1=mote radio is transmitting) *
  • char simReceiving (1=mote radio is receiving) *
  • char simInPolled *

    @@ -174,7 +173,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA } public boolean isReceiving() { - return isLockedAtReceiving(); + return myMoteMemory.getByteValueOf("simReceiving") == 1; } public boolean isInterfered() { @@ -191,45 +190,31 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA interfereAnyReception(); return; } - lockInReceivingMode(); + + myMoteMemory.setByteValueOf("simReceiving", (byte) 1); + mote.requestImmediateWakeup(); lastEventTime = mote.getSimulation().getSimulationTime(); lastEvent = RadioEvent.RECEPTION_STARTED; + this.setChanged(); this.notifyObservers(); } public void signalReceptionEnd() { - if (isInterfered() || packetToMote == null) { - // Reset interfered flag + if (isInterfered || packetToMote == null) { isInterfered = false; - - // Reset data packetToMote = null; myMoteMemory.setIntValueOf("simInSize", 0); - - // Unlock (if locked) - myMoteMemory.setByteValueOf("simReceiving", (byte) 0); - - mote.requestImmediateWakeup(); - - lastEventTime = mote.getSimulation().getSimulationTime(); - lastEvent = RadioEvent.RECEPTION_FINISHED; - this.setChanged(); - this.notifyObservers(); - return; + } else { + myMoteMemory.setIntValueOf("simInSize", packetToMote.getPacketData().length); + myMoteMemory.setByteArray("simInDataBuffer", packetToMote.getPacketData()); } - // Unlock (if locked) myMoteMemory.setByteValueOf("simReceiving", (byte) 0); - - // Set data - myMoteMemory.setIntValueOf("simInSize", packetToMote.getPacketData().length); - myMoteMemory.setByteArray("simInDataBuffer", packetToMote.getPacketData()); - + mote.requestImmediateWakeup(); lastEventTime = mote.getSimulation().getSimulationTime(); lastEvent = RadioEvent.RECEPTION_FINISHED; - mote.requestImmediateWakeup(); this.setChanged(); this.notifyObservers(); } @@ -239,18 +224,20 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA } public void interfereAnyReception() { - if (!isInterfered()) { - isInterfered = true; - - lastEvent = RadioEvent.RECEPTION_INTERFERED; - lastEventTime = mote.getSimulation().getSimulationTime(); - this.setChanged(); - this.notifyObservers(); + if (isInterfered()) { + return; } + + isInterfered = true; + + lastEvent = RadioEvent.RECEPTION_INTERFERED; + lastEventTime = mote.getSimulation().getSimulationTime(); + this.setChanged(); + this.notifyObservers(); } public double getCurrentOutputPower() { - // TODO Implement method + /* TODO Implement method */ logger.warn("Not implemented, always returning 0 dBm"); return 0; } @@ -275,43 +262,16 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA return mote.getInterfaces().getPosition(); } - /** - * @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. - */ - private void lockInReceivingMode() { - mote.requestImmediateWakeup(); - - // Lock core radio in receiving loop - myMoteMemory.setByteValueOf("simReceiving", (byte) 1); - } - public void doActionsAfterTick() { + long now = mote.getSimulation().getSimulationTime(); + /* Check if radio hardware status changed */ if (radioOn != (myMoteMemory.getByteValueOf("simRadioHWOn") == 1)) { radioOn = !radioOn; if (!radioOn) { - // Reset status myMoteMemory.setByteValueOf("simReceiving", (byte) 0); myMoteMemory.setIntValueOf("simInSize", 0); - myMoteMemory.setByteValueOf("simTransmitting", (byte) 0); myMoteMemory.setIntValueOf("simOutSize", 0); isTransmitting = false; lastEvent = RadioEvent.HW_OFF; @@ -319,7 +279,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA lastEvent = RadioEvent.HW_ON; } - lastEventTime = mote.getSimulation().getSimulationTime(); + lastEventTime = now; this.setChanged(); this.notifyObservers(); } @@ -327,7 +287,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA return; } - // Check if radio output power changed + /* Check if radio output power changed */ if (myMoteMemory.getByteValueOf("simPower") != oldOutputPowerIndicator) { oldOutputPowerIndicator = myMoteMemory.getByteValueOf("simPower"); lastEvent = RadioEvent.UNKNOWN; @@ -335,34 +295,28 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA this.notifyObservers(); } - /* Are we transmitting but should stop? */ - /* TODO Use time events */ - if (isTransmitting - && mote.getSimulation().getSimulationTime() >= transmissionEndTime) { - myMoteMemory.setByteValueOf("simTransmitting", (byte) 0); + /* Ongoing transmission */ + if (isTransmitting && now >= transmissionEndTime) { myMoteMemory.setIntValueOf("simOutSize", 0); isTransmitting = false; + mote.requestImmediateWakeup(); - lastEventTime = mote.getSimulation().getSimulationTime(); + lastEventTime = now; lastEvent = RadioEvent.TRANSMISSION_FINISHED; - // TODO Energy consumption of transmitted packet? this.setChanged(); this.notifyObservers(); - //logger.debug("----- CONTIKI TRANSMISSION ENDED -----"); + /*logger.debug("----- CONTIKI TRANSMISSION ENDED -----");*/ } - // Check if a new transmission should be started - if (!isTransmitting && myMoteMemory.getByteValueOf("simTransmitting") == 1) { - int size = myMoteMemory.getIntValueOf("simOutSize"); - if (size <= 0) { - logger.warn("Skipping zero sized Contiki packet (no size)"); - myMoteMemory.setByteValueOf("simTransmitting", (byte) 0); - return; - } + /* New transmission */ + int size = myMoteMemory.getIntValueOf("simOutSize"); + if (!isTransmitting && size > 0) { packetFromMote = new COOJARadioPacket(myMoteMemory.getByteArray("simOutDataBuffer", size)); + if (packetFromMote.getPacketData() == null || packetFromMote.getPacketData().length == 0) { logger.warn("Skipping zero sized Contiki packet (no buffer)"); - myMoteMemory.setByteValueOf("simTransmitting", (byte) 0); + myMoteMemory.setIntValueOf("simOutSize", 0); + mote.requestImmediateWakeup(); return; } @@ -371,9 +325,9 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA /* Calculate transmission duration (us) */ /* XXX Currently floored due to millisecond scheduling! */ long duration = (int) (Simulation.MILLISECOND*((8 * size /*bits*/) / RADIO_TRANSMISSION_RATE_kbps)); - transmissionEndTime = mote.getSimulation().getSimulationTime() + Math.max(1, duration); - lastEventTime = mote.getSimulation().getSimulationTime(); + transmissionEndTime = now + Math.max(1, duration); + lastEventTime = now; lastEvent = RadioEvent.TRANSMISSION_STARTED; this.setChanged(); this.notifyObservers(); @@ -385,6 +339,10 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA this.notifyObservers(); //logger.debug("----- CONTIKI PACKET DELIVERED -----"); } + + if (isTransmitting && transmissionEndTime > now) { + mote.scheduleNextWakeup(transmissionEndTime); + } } public JPanel getInterfaceVisualizer() {