[Tinyos-2-commits] CVS: tinyos-2.x/tos/chips/rf230 RF2xx.h, NONE, 1.1 RF2xxActiveMessageC.nc, NONE, 1.1 RF2xxActiveMessageP.nc, NONE, 1.1 RF2xxDriverConfig.nc, NONE, 1.1 RF2xxDriverLayerC.nc, NONE, 1.1 RF2xxDriverLayerP.nc, NONE, 1.1 RF2xxPacket.h, NONE, 1.1 RF2xxPacketC.nc, NONE, 1.1 RF2xxPacketP.nc, NONE, 1.1 RF2xxTimeSyncMessageC.nc, NONE, 1.1 RF2xxTimeSyncMessageP.nc, NONE, 1.1 RF230.h, 1.1, NONE RF230ActiveMessageC.nc, 1.8, NONE RF230ActiveMessageP.nc, 1.3, NONE RF230Config.nc, 1.4, NONE RF230LayerC.nc, 1.9, NONE RF230LayerP.nc, 1.25, NONE RF230Packet.h, 1.4, NONE RF230PacketC.nc, 1.4, NONE RF230PacketP.nc, 1.6, NONE RF230TimeSyncMessageC.nc, 1.3, NONE RF230TimeSyncMessageP.nc, 1.3, NONE
Miklos Maroti
mmaroti at users.sourceforge.net
Sun Mar 8 16:22:44 PDT 2009
- Previous message: [Tinyos-2-commits] CVS: tinyos-2.x/tos/platforms/iris/chips/rf230 RadioAlarm.h, NONE, 1.1 HplRF230.h, 1.6, 1.7 HplRF230C.nc, 1.7, 1.8 HplRF230P.nc, 1.2, 1.3
- Next message: [Tinyos-2-commits] CVS: tinyos-2.x/tos/platforms/iris/chips/rf230 HplRF2xx.h, NONE, 1.1 HplRF2xxC.nc, NONE, 1.1 HplRF2xxP.nc, NONE, 1.1 RadioAlarm.h, 1.1, 1.2 HplRF230.h, 1.7, NONE HplRF230C.nc, 1.8, NONE HplRF230P.nc, 1.3, NONE
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/tinyos/tinyos-2.x/tos/chips/rf230
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv16126
Added Files:
RF2xx.h RF2xxActiveMessageC.nc RF2xxActiveMessageP.nc
RF2xxDriverConfig.nc RF2xxDriverLayerC.nc RF2xxDriverLayerP.nc
RF2xxPacket.h RF2xxPacketC.nc RF2xxPacketP.nc
RF2xxTimeSyncMessageC.nc RF2xxTimeSyncMessageP.nc
Removed Files:
RF230.h RF230ActiveMessageC.nc RF230ActiveMessageP.nc
RF230Config.nc RF230LayerC.nc RF230LayerP.nc RF230Packet.h
RF230PacketC.nc RF230PacketP.nc RF230TimeSyncMessageC.nc
RF230TimeSyncMessageP.nc
Log Message:
rename everything to support the RF212
--- NEW FILE: RF2xx.h ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
#ifndef __RF2XX_H__
#define __RF2XX_H__
enum rf2xx_chipsets_enum
{
RF230_CHIPSET = 0,
RF212_CHIPSET = 1,
};
enum rf2xx_registers_enum
{
RF2XX_TRX_STATUS = 0x01,
RF2XX_TRX_STATE = 0x02,
RF2XX_TRX_CTRL_0 = 0x03,
RF2XX_PHY_TX_PWR = 0x05,
RF2XX_PHY_RSSI = 0x06,
RF2XX_PHY_ED_LEVEL = 0x07,
RF2XX_PHY_CC_CCA = 0x08,
RF2XX_CCA_THRES = 0x09,
RF2XX_IRQ_MASK = 0x0E,
RF2XX_IRQ_STATUS = 0x0F,
RF2XX_VREG_CTRL = 0x10,
RF2XX_BATMON = 0x11,
RF2XX_XOSC_CTRL = 0x12,
RF2XX_PLL_CF = 0x1A,
RF2XX_PLL_DCU = 0x1B,
RF2XX_PART_NUM = 0x1C,
RF2XX_VERSION_NUM = 0x1D,
RF2XX_MAN_ID_0 = 0x1E,
RF2XX_MAN_ID_1 = 0x1F,
RF2XX_SHORT_ADDR_0 = 0x20,
RF2XX_SHORT_ADDR_1 = 0x21,
RF2XX_PAN_ID_0 = 0x22,
RF2XX_PAN_ID_1 = 0x23,
RF2XX_IEEE_ADDR_0 = 0x24,
RF2XX_IEEE_ADDR_1 = 0x25,
RF2XX_IEEE_ADDR_2 = 0x26,
RF2XX_IEEE_ADDR_3 = 0x27,
RF2XX_IEEE_ADDR_4 = 0x28,
RF2XX_IEEE_ADDR_5 = 0x29,
RF2XX_IEEE_ADDR_6 = 0x2A,
RF2XX_IEEE_ADDR_7 = 0x2B,
RF2XX_XAH_CTRL = 0x2C,
RF2XX_CSMA_SEED_0 = 0x2D,
RF2XX_CSMA_SEED_1 = 0x2E,
};
enum rf2xx_trx_register_enums
{
RF2XX_CCA_DONE = 1 << 7,
RF2XX_CCA_STATUS = 1 << 6,
RF2XX_TRX_STATUS_MASK = 0x1F,
RF2XX_P_ON = 0,
RF2XX_BUSY_RX = 1,
RF2XX_BUSY_TX = 2,
RF2XX_RX_ON = 6,
RF2XX_TRX_OFF = 8,
RF2XX_PLL_ON = 9,
RF2XX_SLEEP = 15,
RF2XX_BUSY_RX_AACK = 16,
RF2XX_BUSR_TX_ARET = 17,
RF2XX_RX_AACK_ON = 22,
RF2XX_TX_ARET_ON = 25,
RF2XX_RX_ON_NOCLK = 28,
RF2XX_AACK_ON_NOCLK = 29,
RF2XX_BUSY_RX_AACK_NOCLK = 30,
RF2XX_STATE_TRANSITION_IN_PROGRESS = 31,
RF2XX_TRAC_STATUS_MASK = 0xE0,
RF2XX_TRAC_SUCCESS = 0,
RF2XX_TRAC_CHANNEL_ACCESS_FAILURE = 3 << 5,
RF2XX_TRAC_NO_ACK = 5 << 5,
RF2XX_TRX_CMD_MASK = 0x1F,
RF2XX_NOP = 0,
RF2XX_TX_START = 2,
RF2XX_FORCE_TRX_OFF = 3,
};
enum rf2xx_phy_register_enums
{
RF2XX_TX_AUTO_CRC_ON = 1 << 7,
RF2XX_TX_PWR_MASK = 0x0F,
RF2XX_TX_PWR_DEFAULT = 0,
RF2XX_RSSI_MASK = 0x1F,
RF2XX_CCA_REQUEST = 1 << 7,
RF2XX_CCA_MODE_0 = 0 << 5,
RF2XX_CCA_MODE_1 = 1 << 5,
RF2XX_CCA_MODE_2 = 2 << 5,
RF2XX_CCA_MODE_3 = 3 << 5,
RF2XX_CHANNEL_DEFAULT = 11,
RF2XX_CHANNEL_MASK = 0x1F,
RF2XX_CCA_CS_THRES_SHIFT = 4,
RF2XX_CCA_ED_THRES_SHIFT = 0,
};
enum rf2xx_irq_register_enums
{
RF2XX_IRQ_BAT_LOW = 1 << 7,
RF2XX_IRQ_TRX_UR = 1 << 6,
RF2XX_IRQ_TRX_END = 1 << 3,
RF2XX_IRQ_RX_START = 1 << 2,
RF2XX_IRQ_PLL_UNLOCK = 1 << 1,
RF2XX_IRQ_PLL_LOCK = 1 << 0,
};
enum rf2xx_control_register_enums
{
RF2XX_AVREG_EXT = 1 << 7,
RF2XX_AVDD_OK = 1 << 6,
RF2XX_DVREG_EXT = 1 << 3,
RF2XX_DVDD_OK = 1 << 2,
RF2XX_BATMON_OK = 1 << 5,
RF2XX_BATMON_VHR = 1 << 4,
RF2XX_BATMON_VTH_MASK = 0x0F,
RF2XX_XTAL_MODE_OFF = 0 << 4,
RF2XX_XTAL_MODE_EXTERNAL = 4 << 4,
RF2XX_XTAL_MODE_INTERNAL = 15 << 4,
};
enum rf2xx_pll_register_enums
{
RF2XX_PLL_CF_START = 1 << 7,
RF2XX_PLL_DCU_START = 1 << 7,
};
enum rf2xx_spi_command_enums
{
RF2XX_CMD_REGISTER_READ = 0x80,
RF2XX_CMD_REGISTER_WRITE = 0xC0,
RF2XX_CMD_REGISTER_MASK = 0x3F,
RF2XX_CMD_FRAME_READ = 0x20,
RF2XX_CMD_FRAME_WRITE = 0x60,
RF2XX_CMD_SRAM_READ = 0x00,
RF2XX_CMD_SRAM_WRITE = 0x40,
};
#endif//__RF2XX_H__
--- NEW FILE: RF2xxActiveMessageC.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
#include <RadioAlarm.h>
configuration RF2xxActiveMessageC
{
provides
{
interface SplitControl;
interface AMSend[am_id_t id];
interface Receive[am_id_t id];
interface Receive as Snoop[am_id_t id];
interface Packet;
interface AMPacket;
interface PacketAcknowledgements;
interface LowPowerListening;
interface RadioChannel;
interface PacketField<uint8_t> as PacketLinkQuality;
interface PacketField<uint8_t> as PacketTransmitPower;
interface PacketField<uint8_t> as PacketRSSI;
interface PacketTimeStamp<TRadio, uint32_t> as PacketTimeStampRadio;
interface PacketTimeStamp<TMilli, uint32_t> as PacketTimeStampMilli;
}
}
implementation
{
components RF2xxActiveMessageP, RF2xxPacketC, IEEE154PacketC, RadioAlarmC;
#ifdef RF2XX_DEBUG
components AssertC;
#endif
RF2xxActiveMessageP.IEEE154Packet -> IEEE154PacketC;
RF2xxActiveMessageP.Packet -> RF2xxPacketC;
RF2xxActiveMessageP.RadioAlarm -> RadioAlarmC.RadioAlarm[unique("RadioAlarm")];
Packet = RF2xxPacketC;
AMPacket = RF2xxPacketC;
PacketAcknowledgements = RF2xxPacketC;
PacketLinkQuality = RF2xxPacketC.PacketLinkQuality;
PacketTransmitPower = RF2xxPacketC.PacketTransmitPower;
PacketRSSI = RF2xxPacketC.PacketRSSI;
PacketTimeStampRadio = RF2xxPacketC;
PacketTimeStampMilli = RF2xxPacketC;
LowPowerListening = LowPowerListeningLayerC;
RadioChannel = MessageBufferLayerC;
components ActiveMessageLayerC;
#ifdef TFRAMES_ENABLED
components new DummyLayerC() as IEEE154NetworkLayerC;
#else
components IEEE154NetworkLayerC;
#endif
#ifdef LOW_POWER_LISTENING
components LowPowerListeningLayerC;
#else
components new DummyLayerC() as LowPowerListeningLayerC;
#endif
components MessageBufferLayerC;
components UniqueLayerC;
components TrafficMonitorLayerC;
#ifdef RF2XX_SLOTTED_MAC
components SlottedCollisionLayerC as CollisionAvoidanceLayerC;
#else
components RandomCollisionLayerC as CollisionAvoidanceLayerC;
#endif
components SoftwareAckLayerC;
components new DummyLayerC() as CsmaLayerC;
components RF2xxDriverLayerC;
SplitControl = LowPowerListeningLayerC;
AMSend = ActiveMessageLayerC;
Receive = ActiveMessageLayerC.Receive;
Snoop = ActiveMessageLayerC.Snoop;
ActiveMessageLayerC.Config -> RF2xxActiveMessageP;
ActiveMessageLayerC.AMPacket -> IEEE154PacketC;
ActiveMessageLayerC.SubSend -> IEEE154NetworkLayerC;
ActiveMessageLayerC.SubReceive -> IEEE154NetworkLayerC;
IEEE154NetworkLayerC.SubSend -> UniqueLayerC;
IEEE154NetworkLayerC.SubReceive -> LowPowerListeningLayerC;
// the UniqueLayer is wired at two points
UniqueLayerC.Config -> RF2xxActiveMessageP;
UniqueLayerC.SubSend -> LowPowerListeningLayerC;
LowPowerListeningLayerC.SubControl -> MessageBufferLayerC;
LowPowerListeningLayerC.SubSend -> MessageBufferLayerC;
LowPowerListeningLayerC.SubReceive -> MessageBufferLayerC;
#ifdef LOW_POWER_LISTENING
LowPowerListeningLayerC.PacketSleepInterval -> RF2xxPacketC;
LowPowerListeningLayerC.IEEE154Packet -> IEEE154PacketC;
LowPowerListeningLayerC.PacketAcknowledgements -> RF2xxPacketC;
#endif
MessageBufferLayerC.Packet -> RF2xxPacketC;
MessageBufferLayerC.RadioSend -> TrafficMonitorLayerC;
MessageBufferLayerC.RadioReceive -> UniqueLayerC;
MessageBufferLayerC.RadioState -> TrafficMonitorLayerC;
UniqueLayerC.SubReceive -> TrafficMonitorLayerC;
TrafficMonitorLayerC.Config -> RF2xxActiveMessageP;
TrafficMonitorLayerC.SubSend -> CollisionAvoidanceLayerC;
TrafficMonitorLayerC.SubReceive -> CollisionAvoidanceLayerC;
TrafficMonitorLayerC.SubState -> RF2xxDriverLayerC;
CollisionAvoidanceLayerC.Config -> RF2xxActiveMessageP;
CollisionAvoidanceLayerC.SubSend -> SoftwareAckLayerC;
CollisionAvoidanceLayerC.SubReceive -> SoftwareAckLayerC;
SoftwareAckLayerC.Config -> RF2xxActiveMessageP;
SoftwareAckLayerC.SubSend -> CsmaLayerC;
SoftwareAckLayerC.SubReceive -> RF2xxDriverLayerC;
CsmaLayerC.Config -> RF2xxActiveMessageP;
CsmaLayerC -> RF2xxDriverLayerC.RadioSend;
CsmaLayerC -> RF2xxDriverLayerC.RadioCCA;
RF2xxDriverLayerC.RF2xxDriverConfig -> RF2xxActiveMessageP;
}
--- NEW FILE: RF2xxActiveMessageP.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
#include <RF2xxPacket.h>
#include <RadioAlarm.h>
#include <Tasklet.h>
#include <HplRF2xx.h>
module RF2xxActiveMessageP
{
provides
{
interface RF2xxDriverConfig;
interface SoftwareAckConfig;
interface UniqueConfig;
interface CsmaConfig;
interface TrafficMonitorConfig;
interface RandomCollisionConfig;
interface SlottedCollisionConfig;
interface ActiveMessageConfig;
interface DummyConfig;
}
uses
{
interface IEEE154Packet;
interface Packet;
interface RadioAlarm;
}
}
implementation
{
/*----------------- RF2xxDriverConfig -----------------*/
async command uint8_t RF2xxDriverConfig.getLength(message_t* msg)
{
return call IEEE154Packet.getLength(msg);
}
async command void RF2xxDriverConfig.setLength(message_t* msg, uint8_t len)
{
call IEEE154Packet.setLength(msg, len);
}
async command uint8_t* RF2xxDriverConfig.getPayload(message_t* msg)
{
return ((uint8_t*)(call IEEE154Packet.getHeader(msg))) + 1;
}
inline rf2xxpacket_metadata_t* getMeta(message_t* msg)
{
return (rf2xxpacket_metadata_t*)(msg->metadata);
}
async command uint8_t RF2xxDriverConfig.getHeaderLength()
{
// we need the fcf, dsn, destpan and dest
return 7;
}
async command uint8_t RF2xxDriverConfig.getMaxLength()
{
// note, that the ieee154_footer_t is not stored, but we should include it here
return sizeof(rf2xxpacket_header_t) - 1 + TOSH_DATA_LENGTH + sizeof(ieee154_footer_t);
}
async command uint8_t RF2xxDriverConfig.getDefaultChannel()
{
return RF2XX_DEF_CHANNEL;
}
async command bool RF2xxDriverConfig.requiresRssiCca(message_t* msg)
{
return call IEEE154Packet.isDataFrame(msg);
}
/*----------------- SoftwareAckConfig -----------------*/
async command bool SoftwareAckConfig.requiresAckWait(message_t* msg)
{
return call IEEE154Packet.requiresAckWait(msg);
}
async command bool SoftwareAckConfig.isAckPacket(message_t* msg)
{
return call IEEE154Packet.isAckFrame(msg);
}
async command bool SoftwareAckConfig.verifyAckPacket(message_t* data, message_t* ack)
{
return call IEEE154Packet.verifyAckReply(data, ack);
}
async command bool SoftwareAckConfig.requiresAckReply(message_t* msg)
{
return call IEEE154Packet.requiresAckReply(msg);
}
async command void SoftwareAckConfig.createAckPacket(message_t* data, message_t* ack)
{
call IEEE154Packet.createAckReply(data, ack);
}
async command void SoftwareAckConfig.setAckReceived(message_t* msg, bool acked)
{
if( acked )
getMeta(msg)->flags |= RF2XXPACKET_WAS_ACKED;
else
getMeta(msg)->flags &= ~RF2XXPACKET_WAS_ACKED;
}
async command uint16_t SoftwareAckConfig.getAckTimeout()
{
return (uint16_t)(800 * RADIO_ALARM_MICROSEC);
}
tasklet_async command void SoftwareAckConfig.reportChannelError()
{
signal TrafficMonitorConfig.channelError();
}
/*----------------- UniqueConfig -----------------*/
async command uint8_t UniqueConfig.getSequenceNumber(message_t* msg)
{
return call IEEE154Packet.getDSN(msg);
}
async command void UniqueConfig.setSequenceNumber(message_t* msg, uint8_t dsn)
{
call IEEE154Packet.setDSN(msg, dsn);
}
async command am_addr_t UniqueConfig.getSender(message_t* msg)
{
return call IEEE154Packet.getSrcAddr(msg);
}
tasklet_async command void UniqueConfig.reportChannelError()
{
signal TrafficMonitorConfig.channelError();
}
/*----------------- ActiveMessageConfig -----------------*/
command error_t ActiveMessageConfig.checkPacket(message_t* msg)
{
// the user forgot to call clear, we should return EINVAL
if( ! call IEEE154Packet.isDataFrame(msg) )
call Packet.clear(msg);
return SUCCESS;
}
/*----------------- CsmaConfig -----------------*/
async command bool CsmaConfig.requiresSoftwareCCA(message_t* msg)
{
return call IEEE154Packet.isDataFrame(msg);
}
/*----------------- TrafficMonitorConfig -----------------*/
enum
{
TRAFFIC_UPDATE_PERIOD = 100, // in milliseconds
TRAFFIC_MAX_BYTES = (uint16_t)(TRAFFIC_UPDATE_PERIOD * 1000UL / 32), // 3125
};
async command uint16_t TrafficMonitorConfig.getUpdatePeriod()
{
return TRAFFIC_UPDATE_PERIOD;
}
async command uint16_t TrafficMonitorConfig.getChannelTime(message_t* msg)
{
/* We count in bytes, one byte is 32 microsecond. We are conservative here.
*
* pure airtime: preable (4 bytes), SFD (1 byte), length (1 byte), payload + CRC (len bytes)
* frame separation: 5-10 bytes
* ack required: 8-16 byte separation, 11 bytes airtime, 5-10 bytes separation
*/
uint8_t len = call IEEE154Packet.getLength(msg);
return call IEEE154Packet.getAckRequired(msg) ? len + 6 + 16 + 11 + 10 : len + 6 + 10;
}
async command am_addr_t TrafficMonitorConfig.getSender(message_t* msg)
{
return call IEEE154Packet.getSrcAddr(msg);
}
tasklet_async command void TrafficMonitorConfig.timerTick()
{
signal SlottedCollisionConfig.timerTick();
}
/*----------------- RandomCollisionConfig -----------------*/
/*
* We try to use the same values as in CC2420
*
* CC2420_MIN_BACKOFF = 10 jiffies = 320 microsec
* CC2420_BACKOFF_PERIOD = 10 jiffies
* initial backoff = 0x1F * CC2420_BACKOFF_PERIOD = 310 jiffies = 9920 microsec
* congestion backoff = 0x7 * CC2420_BACKOFF_PERIOD = 70 jiffies = 2240 microsec
*/
async command uint16_t RandomCollisionConfig.getMinimumBackoff()
{
return (uint16_t)(320 * RADIO_ALARM_MICROSEC);
}
async command uint16_t RandomCollisionConfig.getInitialBackoff(message_t* msg)
{
return (uint16_t)(9920 * RADIO_ALARM_MICROSEC);
}
async command uint16_t RandomCollisionConfig.getCongestionBackoff(message_t* msg)
{
return (uint16_t)(2240 * RADIO_ALARM_MICROSEC);
}
async command uint16_t RandomCollisionConfig.getTransmitBarrier(message_t* msg)
{
uint16_t time;
// TODO: maybe we should use the embedded timestamp of the message
time = call RadioAlarm.getNow();
// estimated response time (download the message, etc) is 5-8 bytes
if( call IEEE154Packet.requiresAckReply(msg) )
time += (uint16_t)(32 * (-5 + 16 + 11 + 5) * RADIO_ALARM_MICROSEC);
else
time += (uint16_t)(32 * (-5 + 5) * RADIO_ALARM_MICROSEC);
return time;
}
tasklet_async event void RadioAlarm.fired() { }
/*----------------- SlottedCollisionConfig -----------------*/
async command uint16_t SlottedCollisionConfig.getInitialDelay()
{
return 300;
}
async command uint8_t SlottedCollisionConfig.getScheduleExponent()
{
return 11;
}
async command uint16_t SlottedCollisionConfig.getTransmitTime(message_t* msg)
{
// TODO: check if the timestamp is correct
return getMeta(msg)->timestamp;
}
async command uint16_t SlottedCollisionConfig.getCollisionWindowStart(message_t* msg)
{
// the preamble (4 bytes), SFD (1 byte), plus two extra for safety
return getMeta(msg)->timestamp - (uint16_t)(7 * 32 * RADIO_ALARM_MICROSEC);
}
async command uint16_t SlottedCollisionConfig.getCollisionWindowLength(message_t* msg)
{
return (uint16_t)(2 * 7 * 32 * RADIO_ALARM_MICROSEC);
}
default tasklet_async event void SlottedCollisionConfig.timerTick() { }
/*----------------- Dummy -----------------*/
async command void DummyConfig.nothing()
{
}
}
--- NEW FILE: RF2xxDriverConfig.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
/**
* This interface needs to be implemented by the MAC to control the behaviour
* of the RF2xxDriverLayerC component.
*/
interface RF2xxDriverConfig
{
/**
* Returns the length of the PHY payload (including the FCF field).
* This value must be in the range [3, 127].
*/
async command uint8_t getLength(message_t* msg);
/**
* Sets the length of the PHY payload.
*/
async command void setLength(message_t* msg, uint8_t len);
/**
* Returns a pointer to the start of the PHY payload that contains
* getLength()-2 number of bytes. The FCF field (CRC-16) is not stored,
* but automatically appended / verified.
*/
async command uint8_t* getPayload(message_t* msg);
/**
* Gets the number of bytes we should read before the RadioReceive.header
* event is fired. If the length of the packet is less than this amount,
* then that event is fired earlier. The header length must be at least one.
*/
async command uint8_t getHeaderLength();
/**
* Returns the maximum PHY length that can be set via the setLength command
*/
async command uint8_t getMaxLength();
/**
* This command is used at power up to set the default channel.
* The default CC2420 channel is 26.
*/
async command uint8_t getDefaultChannel();
/**
* Returns TRUE if before sending this message we should make sure that
* the channel is clear via a very basic (and quick) RSSI check.
*/
async command bool requiresRssiCca(message_t* msg);
}
--- NEW FILE: RF2xxDriverLayerC.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
configuration RF2xxDriverLayerC
{
provides
{
interface RadioState;
interface RadioSend;
interface RadioReceive;
interface RadioCCA;
}
uses interface RF2xxDriverConfig;
}
implementation
{
components RF2xxDriverLayerP, HplRF2xxC, BusyWaitMicroC, TaskletC, MainC, RadioAlarmC, RF2xxPacketC, LocalTimeMicroC as LocalTimeRadioC;
RadioState = RF2xxDriverLayerP;
RadioSend = RF2xxDriverLayerP;
RadioReceive = RF2xxDriverLayerP;
RadioCCA = RF2xxDriverLayerP;
RF2xxDriverConfig = RF2xxDriverLayerP;
RF2xxDriverLayerP.PacketLinkQuality -> RF2xxPacketC.PacketLinkQuality;
RF2xxDriverLayerP.PacketTransmitPower -> RF2xxPacketC.PacketTransmitPower;
RF2xxDriverLayerP.PacketRSSI -> RF2xxPacketC.PacketRSSI;
RF2xxDriverLayerP.PacketTimeSyncOffset -> RF2xxPacketC.PacketTimeSyncOffset;
RF2xxDriverLayerP.PacketTimeStamp -> RF2xxPacketC;
RF2xxDriverLayerP.LocalTime -> LocalTimeRadioC;
RF2xxDriverLayerP.RadioAlarm -> RadioAlarmC.RadioAlarm[unique("RadioAlarm")];
RadioAlarmC.Alarm -> HplRF2xxC.Alarm;
RF2xxDriverLayerP.SELN -> HplRF2xxC.SELN;
RF2xxDriverLayerP.SpiResource -> HplRF2xxC.SpiResource;
RF2xxDriverLayerP.FastSpiByte -> HplRF2xxC;
RF2xxDriverLayerP.SLP_TR -> HplRF2xxC.SLP_TR;
RF2xxDriverLayerP.RSTN -> HplRF2xxC.RSTN;
RF2xxDriverLayerP.IRQ -> HplRF2xxC.IRQ;
RF2xxDriverLayerP.Tasklet -> TaskletC;
RF2xxDriverLayerP.BusyWait -> BusyWaitMicroC;
#ifdef RF2XX_DEBUG
components DiagMsgC;
RF2xxDriverLayerP.DiagMsg -> DiagMsgC;
#endif
MainC.SoftwareInit -> RF2xxDriverLayerP.SoftwareInit;
components RealMainP;
RealMainP.PlatformInit -> RF2xxDriverLayerP.PlatformInit;
}
--- NEW FILE: RF2xxDriverLayerP.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
#include <RF2xx.h>
#include <HplRF2xx.h>
#include <Tasklet.h>
#include <RadioAssert.h>
#include <TimeSyncMessage.h>
#include <RadioAlarm.h>
module RF2xxDriverLayerP
{
provides
{
interface Init as PlatformInit @exactlyonce();
interface Init as SoftwareInit @exactlyonce();
interface RadioState;
interface RadioSend;
interface RadioReceive;
interface RadioCCA;
}
uses
{
interface GeneralIO as SELN;
interface Resource as SpiResource;
interface FastSpiByte;
interface GeneralIO as SLP_TR;
interface GeneralIO as RSTN;
interface GpioCapture as IRQ;
interface BusyWait<TMicro, uint16_t>;
interface PacketField<uint8_t> as PacketLinkQuality;
interface PacketField<uint8_t> as PacketTransmitPower;
interface PacketField<uint8_t> as PacketRSSI;
interface PacketField<uint8_t> as PacketTimeSyncOffset;
interface PacketTimeStamp<TRadio, uint32_t>;
interface LocalTime<TRadio>;
interface RF2xxDriverConfig;
interface Tasklet;
interface RadioAlarm;
#ifdef RF2XX_DEBUG
interface DiagMsg;
#endif
}
}
implementation
{
/*----------------- STATE -----------------*/
tasklet_norace uint8_t state;
enum
{
STATE_P_ON = 0,
STATE_SLEEP = 1,
STATE_SLEEP_2_TRX_OFF = 2,
STATE_TRX_OFF = 3,
STATE_TRX_OFF_2_RX_ON = 4,
STATE_RX_ON = 5,
STATE_BUSY_TX_2_RX_ON = 6,
STATE_PLL_ON_2_RX_ON = 7,
};
tasklet_norace uint8_t cmd;
enum
{
CMD_NONE = 0, // the state machine has stopped
CMD_TURNOFF = 1, // goto SLEEP state
CMD_STANDBY = 2, // goto TRX_OFF state
CMD_TURNON = 3, // goto RX_ON state
CMD_TRANSMIT = 4, // currently transmitting a message
CMD_RECEIVE = 5, // currently receiving a message
CMD_CCA = 6, // performing clear chanel assesment
CMD_CHANNEL = 7, // changing the channel
CMD_SIGNAL_DONE = 8, // signal the end of the state transition
CMD_DOWNLOAD = 9, // download the received message
};
norace bool radioIrq;
tasklet_norace uint8_t txPower;
tasklet_norace uint8_t channel;
tasklet_norace message_t* rxMsg;
message_t rxMsgBuffer;
uint16_t capturedTime; // the current time when the last interrupt has occured
tasklet_norace uint8_t rssiClear;
tasklet_norace uint8_t rssiBusy;
/*----------------- REGISTER -----------------*/
inline void writeRegister(uint8_t reg, uint8_t value)
{
ASSERT( call SpiResource.isOwner() );
ASSERT( reg == (reg & RF2XX_CMD_REGISTER_MASK) );
call SELN.clr();
call FastSpiByte.splitWrite(RF2XX_CMD_REGISTER_WRITE | reg);
call FastSpiByte.splitReadWrite(value);
call FastSpiByte.splitRead();
call SELN.set();
}
inline uint8_t readRegister(uint8_t reg)
{
ASSERT( call SpiResource.isOwner() );
ASSERT( reg == (reg & RF2XX_CMD_REGISTER_MASK) );
call SELN.clr();
call FastSpiByte.splitWrite(RF2XX_CMD_REGISTER_READ | reg);
call FastSpiByte.splitReadWrite(0);
reg = call FastSpiByte.splitRead();
call SELN.set();
return reg;
}
/*----------------- ALARM -----------------*/
enum
{
SLEEP_WAKEUP_TIME = (uint16_t)(880 * RADIO_ALARM_MICROSEC),
CCA_REQUEST_TIME = (uint16_t)(140 * RADIO_ALARM_MICROSEC),
TX_SFD_DELAY = (uint16_t)(176 * RADIO_ALARM_MICROSEC),
RX_SFD_DELAY = (uint16_t)(8 * RADIO_ALARM_MICROSEC),
};
tasklet_async event void RadioAlarm.fired()
{
if( state == STATE_SLEEP_2_TRX_OFF )
state = STATE_TRX_OFF;
else if( cmd == CMD_CCA )
{
uint8_t cca;
ASSERT( state == STATE_RX_ON );
cmd = CMD_NONE;
cca = readRegister(RF2XX_TRX_STATUS);
ASSERT( (cca & RF2XX_TRX_STATUS_MASK) == RF2XX_RX_ON );
signal RadioCCA.done( (cca & RF2XX_CCA_DONE) ? ((cca & RF2XX_CCA_STATUS) ? SUCCESS : EBUSY) : FAIL );
}
else
ASSERT(FALSE);
// make sure the rest of the command processing is called
call Tasklet.schedule();
}
/*----------------- INIT -----------------*/
command error_t PlatformInit.init()
{
call SELN.makeOutput();
call SELN.set();
call SLP_TR.makeOutput();
call SLP_TR.clr();
call RSTN.makeOutput();
call RSTN.set();
rxMsg = &rxMsgBuffer;
// these are just good approximates
rssiClear = 0;
rssiBusy = 90;
return SUCCESS;
}
command error_t SoftwareInit.init()
{
// for powering up the radio
return call SpiResource.request();
}
void initRadio()
{
call BusyWait.wait(510);
call RSTN.clr();
call SLP_TR.clr();
call BusyWait.wait(6);
call RSTN.set();
writeRegister(RF2XX_TRX_CTRL_0, RF2XX_TRX_CTRL_0_VALUE);
writeRegister(RF2XX_TRX_STATE, RF2XX_TRX_OFF);
call BusyWait.wait(510);
writeRegister(RF2XX_IRQ_MASK, RF2XX_IRQ_TRX_UR | RF2XX_IRQ_PLL_LOCK | RF2XX_IRQ_TRX_END | RF2XX_IRQ_RX_START);
writeRegister(RF2XX_CCA_THRES, RF2XX_CCA_THRES_VALUE);
writeRegister(RF2XX_PHY_TX_PWR, RF2XX_TX_AUTO_CRC_ON | RF2XX_TX_PWR_DEFAULT);
txPower = RF2XX_TX_PWR_DEFAULT;
channel = call RF2xxDriverConfig.getDefaultChannel() & RF2XX_CHANNEL_MASK;
writeRegister(RF2XX_PHY_CC_CCA, RF2XX_CCA_MODE_VALUE | channel);
call SLP_TR.set();
state = STATE_SLEEP;
}
/*----------------- SPI -----------------*/
event void SpiResource.granted()
{
call SELN.makeOutput();
call SELN.set();
if( state == STATE_P_ON )
{
initRadio();
call SpiResource.release();
}
else
call Tasklet.schedule();
}
bool isSpiAcquired()
{
if( call SpiResource.isOwner() )
return TRUE;
if( call SpiResource.immediateRequest() == SUCCESS )
{
call SELN.makeOutput();
call SELN.set();
return TRUE;
}
call SpiResource.request();
return FALSE;
}
/*----------------- CHANNEL -----------------*/
tasklet_async command uint8_t RadioState.getChannel()
{
return channel;
}
tasklet_async command error_t RadioState.setChannel(uint8_t c)
{
c &= RF2XX_CHANNEL_MASK;
if( cmd != CMD_NONE )
return EBUSY;
else if( channel == c )
return EALREADY;
channel = c;
cmd = CMD_CHANNEL;
call Tasklet.schedule();
return SUCCESS;
}
inline void changeChannel()
{
ASSERT( cmd == CMD_CHANNEL );
ASSERT( state == STATE_SLEEP || state == STATE_TRX_OFF || state == STATE_RX_ON );
if( isSpiAcquired() )
{
writeRegister(RF2XX_PHY_CC_CCA, RF2XX_CCA_MODE_VALUE | channel);
if( state == STATE_RX_ON )
state = STATE_TRX_OFF_2_RX_ON;
else
cmd = CMD_SIGNAL_DONE;
}
}
/*----------------- TURN ON/OFF -----------------*/
inline void changeState()
{
if( (cmd == CMD_STANDBY || cmd == CMD_TURNON)
&& state == STATE_SLEEP && call RadioAlarm.isFree() )
{
call SLP_TR.clr();
call RadioAlarm.wait(SLEEP_WAKEUP_TIME);
state = STATE_SLEEP_2_TRX_OFF;
}
else if( cmd == CMD_TURNON && state == STATE_TRX_OFF && isSpiAcquired() )
{
ASSERT( ! radioIrq );
readRegister(RF2XX_IRQ_STATUS); // clear the interrupt register
call IRQ.captureRisingEdge();
// setChannel was ignored in SLEEP because the SPI was not working, so do it here
writeRegister(RF2XX_PHY_CC_CCA, RF2XX_CCA_MODE_VALUE | channel);
writeRegister(RF2XX_TRX_STATE, RF2XX_RX_ON);
state = STATE_TRX_OFF_2_RX_ON;
}
else if( (cmd == CMD_TURNOFF || cmd == CMD_STANDBY)
&& state == STATE_RX_ON && isSpiAcquired() )
{
writeRegister(RF2XX_TRX_STATE, RF2XX_FORCE_TRX_OFF);
call IRQ.disable();
radioIrq = FALSE;
state = STATE_TRX_OFF;
}
if( cmd == CMD_TURNOFF && state == STATE_TRX_OFF )
{
call SLP_TR.set();
state = STATE_SLEEP;
cmd = CMD_SIGNAL_DONE;
}
else if( cmd == CMD_STANDBY && state == STATE_TRX_OFF )
cmd = CMD_SIGNAL_DONE;
}
tasklet_async command error_t RadioState.turnOff()
{
if( cmd != CMD_NONE )
return EBUSY;
else if( state == STATE_SLEEP )
return EALREADY;
cmd = CMD_TURNOFF;
call Tasklet.schedule();
return SUCCESS;
}
tasklet_async command error_t RadioState.standby()
{
if( cmd != CMD_NONE || (state == STATE_SLEEP && ! call RadioAlarm.isFree()) )
return EBUSY;
else if( state == STATE_TRX_OFF )
return EALREADY;
cmd = CMD_STANDBY;
call Tasklet.schedule();
return SUCCESS;
}
tasklet_async command error_t RadioState.turnOn()
{
if( cmd != CMD_NONE || (state == STATE_SLEEP && ! call RadioAlarm.isFree()) )
return EBUSY;
else if( state == STATE_RX_ON )
return EALREADY;
cmd = CMD_TURNON;
call Tasklet.schedule();
return SUCCESS;
}
default tasklet_async event void RadioState.done() { }
/*----------------- TRANSMIT -----------------*/
tasklet_async command error_t RadioSend.send(message_t* msg)
{
uint16_t time;
uint8_t length;
uint8_t* data;
uint8_t header;
uint32_t time32;
void* timesync;
if( cmd != CMD_NONE || state != STATE_RX_ON || ! isSpiAcquired() || radioIrq )
return EBUSY;
length = (call PacketTransmitPower.isSet(msg) ?
call PacketTransmitPower.get(msg) : RF2XX_DEF_RFPOWER) & RF2XX_TX_PWR_MASK;
if( length != txPower )
{
txPower = length;
writeRegister(RF2XX_PHY_TX_PWR, RF2XX_TX_AUTO_CRC_ON | txPower);
}
if( call RF2xxDriverConfig.requiresRssiCca(msg)
&& (readRegister(RF2XX_PHY_RSSI) & RF2XX_RSSI_MASK) > ((rssiClear + rssiBusy) >> 3) )
return EBUSY;
writeRegister(RF2XX_TRX_STATE, RF2XX_PLL_ON);
// do something useful, just to wait a little
time32 = call LocalTime.get();
timesync = call PacketTimeSyncOffset.isSet(msg) ? msg->data + call PacketTimeSyncOffset.get(msg) : 0;
// we have missed an incoming message in this short amount of time
if( (readRegister(RF2XX_TRX_STATUS) & RF2XX_TRX_STATUS_MASK) != RF2XX_PLL_ON )
{
ASSERT( (readRegister(RF2XX_TRX_STATUS) & RF2XX_TRX_STATUS_MASK) == RF2XX_BUSY_RX );
state = STATE_PLL_ON_2_RX_ON;
return EBUSY;
}
atomic
{
call SLP_TR.set();
time = call RadioAlarm.getNow() + TX_SFD_DELAY;
}
call SLP_TR.clr();
ASSERT( ! radioIrq );
call SELN.clr();
call FastSpiByte.splitWrite(RF2XX_CMD_FRAME_WRITE);
length = call RF2xxDriverConfig.getLength(msg);
data = call RF2xxDriverConfig.getPayload(msg);
// length | data[0] ... data[length-3] | automatically generated FCS
call FastSpiByte.splitReadWrite(length);
// the FCS is atomatically generated (2 bytes)
length -= 2;
header = call RF2xxDriverConfig.getHeaderLength();
if( header > length )
header = length;
length -= header;
// first upload the header to gain some time
do {
call FastSpiByte.splitReadWrite(*(data++));
}
while( --header != 0 );
time32 += (int16_t)(time) - (int16_t)(time32);
if( timesync != 0 )
*(timesync_relative_t*)timesync = (*(timesync_absolute_t*)timesync) - time32;
do {
call FastSpiByte.splitReadWrite(*(data++));
}
while( --length != 0 );
// wait for the SPI transfer to finish
call FastSpiByte.splitRead();
call SELN.set();
/*
* There is a very small window (~1 microsecond) when the RF2xx went
* into PLL_ON state but was somehow not properly initialized because
* of an incoming message and could not go into BUSY_TX. I think the
* radio can even receive a message, and generate a TRX_UR interrupt
* because of concurrent access, but that message probably cannot be
* recovered.
*
* TODO: this needs to be verified, and make sure that the chip is
* not locked up in this case.
*/
// go back to RX_ON state when finished
writeRegister(RF2XX_TRX_STATE, RF2XX_RX_ON);
#ifdef RF2XX_DEBUG_MESSAGES
if( call DiagMsg.record() )
{
length = call RF2xxDriverConfig.getLength(msg);
call DiagMsg.str("tx");
call DiagMsg.uint16(time);
call DiagMsg.uint8(length);
call DiagMsg.hex8s(data, length - 2);
call DiagMsg.send();
}
#endif
if( timesync != 0 )
*(timesync_absolute_t*)timesync = (*(timesync_relative_t*)timesync) + time32;
call PacketTimeStamp.set(msg, time32);
// wait for the TRX_END interrupt
state = STATE_BUSY_TX_2_RX_ON;
cmd = CMD_TRANSMIT;
return SUCCESS;
}
default tasklet_async event void RadioSend.sendDone(error_t error) { }
default tasklet_async event void RadioSend.ready() { }
/*----------------- CCA -----------------*/
tasklet_async command error_t RadioCCA.request()
{
if( cmd != CMD_NONE || state != STATE_RX_ON || ! isSpiAcquired() || ! call RadioAlarm.isFree() )
return EBUSY;
// see Errata B7 of the datasheet
// writeRegister(RF2XX_TRX_STATE, RF2XX_PLL_ON);
// writeRegister(RF2XX_TRX_STATE, RF2XX_RX_ON);
writeRegister(RF2XX_PHY_CC_CCA, RF2XX_CCA_REQUEST | RF2XX_CCA_MODE_VALUE | channel);
call RadioAlarm.wait(CCA_REQUEST_TIME);
cmd = CMD_CCA;
return SUCCESS;
}
default tasklet_async event void RadioCCA.done(error_t error) { }
/*----------------- RECEIVE -----------------*/
inline void downloadMessage()
{
uint8_t length;
uint16_t crc;
call SELN.clr();
call FastSpiByte.write(RF2XX_CMD_FRAME_READ);
// read the length byte
length = call FastSpiByte.write(0);
// if correct length
if( length >= 3 && length <= call RF2xxDriverConfig.getMaxLength() )
{
uint8_t read;
uint8_t* data;
// initiate the reading
call FastSpiByte.splitWrite(0);
call RF2xxDriverConfig.setLength(rxMsg, length);
data = call RF2xxDriverConfig.getPayload(rxMsg);
crc = 0;
// we do not store the CRC field
length -= 2;
read = call RF2xxDriverConfig.getHeaderLength();
if( length < read )
read = length;
length -= read;
do {
crc = RF2XX_CRCBYTE_COMMAND(crc, *(data++) = call FastSpiByte.splitReadWrite(0));
}
while( --read != 0 );
if( signal RadioReceive.header(rxMsg) )
{
while( length-- != 0 )
crc = RF2XX_CRCBYTE_COMMAND(crc, *(data++) = call FastSpiByte.splitReadWrite(0));
crc = RF2XX_CRCBYTE_COMMAND(crc, call FastSpiByte.splitReadWrite(0));
crc = RF2XX_CRCBYTE_COMMAND(crc, call FastSpiByte.splitReadWrite(0));
call PacketLinkQuality.set(rxMsg, call FastSpiByte.splitRead());
}
else
crc = 1;
}
else
crc = 1;
call SELN.set();
state = STATE_RX_ON;
#ifdef RF2XX_DEBUG_MESSAGES
if( call DiagMsg.record() )
{
length = call RF2xxDriverConfig.getLength(rxMsg);
call DiagMsg.str("rx");
call DiagMsg.uint32(call PacketTimeStamp.isValid(rxMsg) ? call PacketTimeStamp.timestamp(rxMsg) : 0);
call DiagMsg.uint16(call RadioAlarm.getNow());
call DiagMsg.uint8(crc != 0);
call DiagMsg.uint8(length);
call DiagMsg.hex8s(call RF2xxDriverConfig.getPayload(rxMsg), length - 2);
call DiagMsg.send();
}
#endif
cmd = CMD_NONE;
// signal only if it has passed the CRC check
if( crc == 0 )
rxMsg = signal RadioReceive.receive(rxMsg);
}
/*----------------- IRQ -----------------*/
async event void IRQ.captured(uint16_t time)
{
ASSERT( ! radioIrq );
atomic
{
capturedTime = time;
radioIrq = TRUE;
}
call Tasklet.schedule();
}
void serviceRadio()
{
if( isSpiAcquired() )
{
uint16_t time;
uint32_t time32;
uint8_t irq;
uint8_t temp;
atomic time = capturedTime;
radioIrq = FALSE;
irq = readRegister(RF2XX_IRQ_STATUS);
#ifdef RF2XX_DEBUG
// TODO: handle this interrupt
if( irq & RF2XX_IRQ_TRX_UR )
{
if( call DiagMsg.record() )
{
call DiagMsg.str("assert ur");
call DiagMsg.uint16(call RadioAlarm.getNow());
call DiagMsg.hex8(readRegister(RF2XX_TRX_STATUS));
call DiagMsg.hex8(readRegister(RF2XX_TRX_STATE));
call DiagMsg.hex8(irq);
call DiagMsg.uint8(state);
call DiagMsg.uint8(cmd);
call DiagMsg.send();
}
}
#endif
if( irq & RF2XX_IRQ_PLL_LOCK )
{
if( cmd == CMD_TURNON || cmd == CMD_CHANNEL )
{
ASSERT( state == STATE_TRX_OFF_2_RX_ON );
state = STATE_RX_ON;
cmd = CMD_SIGNAL_DONE;
}
else if( cmd == CMD_TRANSMIT )
{
ASSERT( state == STATE_BUSY_TX_2_RX_ON );
}
else
ASSERT(FALSE);
}
if( irq & RF2XX_IRQ_RX_START )
{
if( cmd == CMD_CCA )
{
signal RadioCCA.done(FAIL);
cmd = CMD_NONE;
}
if( cmd == CMD_NONE )
{
ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON );
// the most likely place for busy channel, with no TRX_END interrupt
if( irq == RF2XX_IRQ_RX_START )
{
temp = readRegister(RF2XX_PHY_RSSI) & RF2XX_RSSI_MASK;
rssiBusy += temp - (rssiBusy >> 2);
#ifndef RF2XX_RSSI_ENERGY
call PacketRSSI.set(rxMsg, temp);
}
else
{
call PacketRSSI.clear(rxMsg);
#endif
}
/*
* The timestamp corresponds to the first event which could not
* have been a PLL_LOCK because then cmd != CMD_NONE, so we must
* have received a message (and could also have received the
* TRX_END interrupt in the mean time, but that is fine. Also,
* we could not be after a transmission, because then cmd =
* CMD_TRANSMIT.
*/
if( irq == RF2XX_IRQ_RX_START ) // just to be cautious
{
time32 = call LocalTime.get();
time32 += (int16_t)(time - RX_SFD_DELAY) - (int16_t)(time32);
call PacketTimeStamp.set(rxMsg, time32);
}
else
call PacketTimeStamp.clear(rxMsg);
cmd = CMD_RECEIVE;
}
else
ASSERT( cmd == CMD_TURNOFF );
}
if( irq & RF2XX_IRQ_TRX_END )
{
if( cmd == CMD_TRANSMIT )
{
ASSERT( state == STATE_BUSY_TX_2_RX_ON );
state = STATE_RX_ON;
cmd = CMD_NONE;
signal RadioSend.sendDone(SUCCESS);
// TODO: we could have missed a received message
ASSERT( ! (irq & RF2XX_IRQ_RX_START) );
}
else if( cmd == CMD_RECEIVE )
{
ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON );
#ifdef RF2XX_RSSI_ENERGY
if( irq == RF2XX_IRQ_TRX_END )
call PacketRSSI.set(rxMsg, readRegister(RF2XX_PHY_ED_LEVEL));
else
call PacketRSSI.clear(rxMsg);
#endif
if( state == STATE_PLL_ON_2_RX_ON )
{
ASSERT( (readRegister(RF2XX_TRX_STATUS) & RF2XX_TRX_STATUS_MASK) == RF2XX_PLL_ON );
writeRegister(RF2XX_TRX_STATE, RF2XX_RX_ON);
state = STATE_RX_ON;
}
else
{
// the most likely place for clear channel (hope to avoid acks)
rssiClear += (readRegister(RF2XX_PHY_RSSI) & RF2XX_RSSI_MASK) - (rssiClear >> 2);
}
cmd = CMD_DOWNLOAD;
}
else
ASSERT(FALSE);
}
}
}
default tasklet_async event bool RadioReceive.header(message_t* msg)
{
return TRUE;
}
default tasklet_async event message_t* RadioReceive.receive(message_t* msg)
{
return msg;
}
/*----------------- TASKLET -----------------*/
tasklet_async event void Tasklet.run()
{
if( radioIrq )
serviceRadio();
if( cmd != CMD_NONE )
{
if( cmd == CMD_DOWNLOAD )
downloadMessage();
else if( CMD_TURNOFF <= cmd && cmd <= CMD_TURNON )
changeState();
else if( cmd == CMD_CHANNEL )
changeChannel();
if( cmd == CMD_SIGNAL_DONE )
{
cmd = CMD_NONE;
signal RadioState.done();
}
}
if( cmd == CMD_NONE && state == STATE_RX_ON && ! radioIrq )
signal RadioSend.ready();
if( cmd == CMD_NONE )
call SpiResource.release();
}
}
--- NEW FILE: RF2xxPacket.h ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
#ifndef __RF2XXPACKET_H__
#define __RF2XXPACKET_H__
#include <IEEE154Packet.h>
typedef ieee154_header_t rf2xxpacket_header_t;
typedef nx_struct rf2xxpacket_footer_t
{
// the time stamp is not recorded here, time stamped messaged cannot have max length
} rf2xxpacket_footer_t;
typedef struct rf2xxpacket_metadata_t
{
uint8_t flags;
uint8_t lqi;
uint8_t power; // shared between TXPOWER and RSSI
#ifdef LOW_POWER_LISTENING
uint16_t lpl_sleepint;
#endif
uint32_t timestamp;
} rf2xxpacket_metadata_t;
enum rf2xxpacket_metadata_flags
{
RF2XXPACKET_WAS_ACKED = 0x01, // PacketAcknowledgements
RF2XXPACKET_TIMESTAMP = 0x02, // PacketTimeStamp
RF2XXPACKET_TXPOWER = 0x04, // PacketTransmitPower
RF2XXPACKET_RSSI = 0x08, // PacketRSSI
RF2XXPACKET_TIMESYNC = 0x10, // PacketTimeSync (update timesync_footer)
RF2XXPACKET_LPL_SLEEPINT = 0x20, // LowPowerListening
RF2XXPACKET_CLEAR_METADATA = 0x00,
};
#endif//__RF2XXPACKET_H__
--- NEW FILE: RF2xxPacketC.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
configuration RF2xxPacketC
{
provides
{
interface Packet;
interface AMPacket;
interface PacketAcknowledgements;
interface PacketField<uint8_t> as PacketLinkQuality;
interface PacketField<uint8_t> as PacketTransmitPower;
interface PacketField<uint8_t> as PacketRSSI;
interface PacketField<uint16_t> as PacketSleepInterval;
interface PacketField<uint8_t> as PacketTimeSyncOffset;
interface PacketTimeStamp<TRadio, uint32_t> as PacketTimeStampRadio;
interface PacketTimeStamp<TMilli, uint32_t> as PacketTimeStampMilli;
}
}
implementation
{
components RF2xxPacketP, IEEE154PacketC, LocalTimeMicroC, LocalTimeMilliC;
RF2xxPacketP.IEEE154Packet -> IEEE154PacketC;
RF2xxPacketP.LocalTimeRadio -> LocalTimeMicroC;
RF2xxPacketP.LocalTimeMilli -> LocalTimeMilliC;
Packet = RF2xxPacketP;
AMPacket = IEEE154PacketC;
PacketAcknowledgements = RF2xxPacketP;
PacketLinkQuality = RF2xxPacketP.PacketLinkQuality;
PacketTransmitPower = RF2xxPacketP.PacketTransmitPower;
PacketRSSI = RF2xxPacketP.PacketRSSI;
PacketSleepInterval = RF2xxPacketP.PacketSleepInterval;
PacketTimeSyncOffset = RF2xxPacketP.PacketTimeSyncOffset;
PacketTimeStampRadio = RF2xxPacketP;
PacketTimeStampMilli = RF2xxPacketP;
}
--- NEW FILE: RF2xxPacketP.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
#include <RF2xxPacket.h>
#include <TimeSyncMessage.h>
module RF2xxPacketP
{
provides
{
interface PacketAcknowledgements;
interface Packet;
interface PacketField<uint8_t> as PacketLinkQuality;
interface PacketField<uint8_t> as PacketTransmitPower;
interface PacketField<uint8_t> as PacketRSSI;
interface PacketField<uint16_t> as PacketSleepInterval;
interface PacketField<uint8_t> as PacketTimeSyncOffset;
interface PacketTimeStamp<TRadio, uint32_t> as PacketTimeStampRadio;
interface PacketTimeStamp<TMilli, uint32_t> as PacketTimeStampMilli;
}
uses
{
interface IEEE154Packet;
interface LocalTime<TRadio> as LocalTimeRadio;
interface LocalTime<TMilli> as LocalTimeMilli;
}
}
implementation
{
enum
{
PACKET_LENGTH_INCREASE =
sizeof(rf2xxpacket_header_t) - 1 // the 8-bit length field is not counted
+ sizeof(ieee154_footer_t), // the CRC is not stored in memory
};
inline rf2xxpacket_metadata_t* getMeta(message_t* msg)
{
return (rf2xxpacket_metadata_t*)(msg->metadata);
}
/*----------------- Packet -----------------*/
command void Packet.clear(message_t* msg)
{
call IEEE154Packet.createDataFrame(msg);
getMeta(msg)->flags = RF2XXPACKET_CLEAR_METADATA;
}
inline command void Packet.setPayloadLength(message_t* msg, uint8_t len)
{
call IEEE154Packet.setLength(msg, len + PACKET_LENGTH_INCREASE);
}
inline command uint8_t Packet.payloadLength(message_t* msg)
{
return call IEEE154Packet.getLength(msg) - PACKET_LENGTH_INCREASE;
}
inline command uint8_t Packet.maxPayloadLength()
{
return TOSH_DATA_LENGTH;
}
command void* Packet.getPayload(message_t* msg, uint8_t len)
{
if( len > TOSH_DATA_LENGTH )
return NULL;
return msg->data;
}
/*----------------- PacketAcknowledgements -----------------*/
async command error_t PacketAcknowledgements.requestAck(message_t* msg)
{
call IEEE154Packet.setAckRequired(msg, TRUE);
return SUCCESS;
}
async command error_t PacketAcknowledgements.noAck(message_t* msg)
{
call IEEE154Packet.setAckRequired(msg, FALSE);
return SUCCESS;
}
async command bool PacketAcknowledgements.wasAcked(message_t* msg)
{
return getMeta(msg)->flags & RF2XXPACKET_WAS_ACKED;
}
/*----------------- PacketLinkQuality -----------------*/
async command bool PacketLinkQuality.isSet(message_t* msg)
{
return TRUE;
}
async command uint8_t PacketLinkQuality.get(message_t* msg)
{
return getMeta(msg)->lqi;
}
async command void PacketLinkQuality.clear(message_t* msg)
{
}
async command void PacketLinkQuality.set(message_t* msg, uint8_t value)
{
getMeta(msg)->lqi = value;
}
/*----------------- PacketTimeStampRadio -----------------*/
async command bool PacketTimeStampRadio.isValid(message_t* msg)
{
return getMeta(msg)->flags & RF2XXPACKET_TIMESTAMP;
}
async command uint32_t PacketTimeStampRadio.timestamp(message_t* msg)
{
return getMeta(msg)->timestamp;
}
async command void PacketTimeStampRadio.clear(message_t* msg)
{
getMeta(msg)->flags &= ~RF2XXPACKET_TIMESTAMP;
}
async command void PacketTimeStampRadio.set(message_t* msg, uint32_t value)
{
getMeta(msg)->flags |= RF2XXPACKET_TIMESTAMP;
getMeta(msg)->timestamp = value;
}
/*----------------- PacketTimeStampMilli -----------------*/
async command bool PacketTimeStampMilli.isValid(message_t* msg)
{
return call PacketTimeStampRadio.isValid(msg);
}
async command uint32_t PacketTimeStampMilli.timestamp(message_t* msg)
{
int32_t offset = call PacketTimeStampRadio.timestamp(msg) - call LocalTimeRadio.get();
// TODO: Make the shift constant configurable
return (offset >> 10) + call LocalTimeMilli.get();
}
async command void PacketTimeStampMilli.clear(message_t* msg)
{
call PacketTimeStampRadio.clear(msg);
}
async command void PacketTimeStampMilli.set(message_t* msg, uint32_t value)
{
// TODO: Make the shift constant configurable
int32_t offset = (value - call LocalTimeMilli.get()) << 10;
call PacketTimeStampRadio.set(msg, offset + call LocalTimeRadio.get());
}
/*----------------- PacketTransmitPower -----------------*/
async command bool PacketTransmitPower.isSet(message_t* msg)
{
return getMeta(msg)->flags & RF2XXPACKET_TXPOWER;
}
async command uint8_t PacketTransmitPower.get(message_t* msg)
{
return getMeta(msg)->power;
}
async command void PacketTransmitPower.clear(message_t* msg)
{
getMeta(msg)->flags &= ~RF2XXPACKET_TXPOWER;
}
async command void PacketTransmitPower.set(message_t* msg, uint8_t value)
{
getMeta(msg)->flags &= ~RF2XXPACKET_RSSI;
getMeta(msg)->flags |= RF2XXPACKET_TXPOWER;
getMeta(msg)->power = value;
}
/*----------------- PacketRSSI -----------------*/
async command bool PacketRSSI.isSet(message_t* msg)
{
return getMeta(msg)->flags & RF2XXPACKET_RSSI;
}
async command uint8_t PacketRSSI.get(message_t* msg)
{
return getMeta(msg)->power;
}
async command void PacketRSSI.clear(message_t* msg)
{
getMeta(msg)->flags &= ~RF2XXPACKET_RSSI;
}
async command void PacketRSSI.set(message_t* msg, uint8_t value)
{
getMeta(msg)->flags &= ~RF2XXPACKET_TXPOWER;
getMeta(msg)->flags |= RF2XXPACKET_RSSI;
getMeta(msg)->power = value;
}
/*----------------- PacketTimeSyncOffset -----------------*/
async command bool PacketTimeSyncOffset.isSet(message_t* msg)
{
return getMeta(msg)->flags & RF2XXPACKET_TIMESYNC;
}
async command uint8_t PacketTimeSyncOffset.get(message_t* msg)
{
return call IEEE154Packet.getLength(msg) - PACKET_LENGTH_INCREASE - sizeof(timesync_absolute_t);
}
async command void PacketTimeSyncOffset.clear(message_t* msg)
{
getMeta(msg)->flags &= ~RF2XXPACKET_TIMESYNC;
}
async command void PacketTimeSyncOffset.set(message_t* msg, uint8_t value)
{
// the value is ignored, the offset always points to the timesync footer at the end of the payload
getMeta(msg)->flags |= RF2XXPACKET_TIMESYNC;
}
/*----------------- PacketSleepInterval -----------------*/
async command bool PacketSleepInterval.isSet(message_t* msg)
{
return getMeta(msg)->flags & RF2XXPACKET_LPL_SLEEPINT;
}
async command uint16_t PacketSleepInterval.get(message_t* msg)
{
#ifdef LOW_POWER_LISTENING
return getMeta(msg)->lpl_sleepint;
#else
return 0;
#endif
}
async command void PacketSleepInterval.clear(message_t* msg)
{
getMeta(msg)->flags &= ~RF2XXPACKET_LPL_SLEEPINT;
}
async command void PacketSleepInterval.set(message_t* msg, uint16_t value)
{
getMeta(msg)->flags |= RF2XXPACKET_LPL_SLEEPINT;
#ifdef LOW_POWER_LISTENING
getMeta(msg)->lpl_sleepint = value;
#endif
}
}
--- NEW FILE: RF2xxTimeSyncMessageC.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
#include <Timer.h>
#include <AM.h>
#include <RadioAlarm.h>
configuration RF2xxTimeSyncMessageC
{
provides
{
interface SplitControl;
interface Receive[uint8_t id];
interface Receive as Snoop[am_id_t id];
interface Packet;
interface AMPacket;
interface TimeSyncAMSend<TRadio, uint32_t> as TimeSyncAMSendRadio[am_id_t id];
interface TimeSyncPacket<TRadio, uint32_t> as TimeSyncPacketRadio;
interface TimeSyncAMSend<TMilli, uint32_t> as TimeSyncAMSendMilli[am_id_t id];
interface TimeSyncPacket<TMilli, uint32_t> as TimeSyncPacketMilli;
}
}
implementation
{
components RF2xxTimeSyncMessageP, RF2xxActiveMessageC, LocalTimeMilliC, LocalTimeMicroC as LocalTimeRadioC, RF2xxPacketC;
TimeSyncAMSendRadio = RF2xxTimeSyncMessageP;
TimeSyncPacketRadio = RF2xxTimeSyncMessageP;
TimeSyncAMSendMilli = RF2xxTimeSyncMessageP;
TimeSyncPacketMilli = RF2xxTimeSyncMessageP;
Packet = RF2xxTimeSyncMessageP;
RF2xxTimeSyncMessageP.SubSend -> RF2xxActiveMessageC.AMSend;
RF2xxTimeSyncMessageP.SubPacket -> RF2xxActiveMessageC.Packet;
RF2xxTimeSyncMessageP.PacketTimeStampRadio -> RF2xxActiveMessageC;
RF2xxTimeSyncMessageP.PacketTimeStampMilli -> RF2xxActiveMessageC;
RF2xxTimeSyncMessageP.LocalTimeRadio -> LocalTimeRadioC;
RF2xxTimeSyncMessageP.LocalTimeMilli -> LocalTimeMilliC;
RF2xxTimeSyncMessageP.PacketTimeSyncOffset -> RF2xxPacketC.PacketTimeSyncOffset;
SplitControl = RF2xxActiveMessageC;
Receive = RF2xxActiveMessageC.Receive;
Snoop = RF2xxActiveMessageC.Snoop;
AMPacket = RF2xxActiveMessageC;
}
--- NEW FILE: RF2xxTimeSyncMessageP.nc ---
/*
* Copyright (c) 2007, Vanderbilt University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE VANDERBILT UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE VANDERBILT
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE VANDERBILT UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE VANDERBILT UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Author: Miklos Maroti
*/
#include <TimeSyncMessage.h>
#include <RadioAlarm.h>
module RF2xxTimeSyncMessageP
{
provides
{
interface TimeSyncAMSend<TRadio, uint32_t> as TimeSyncAMSendRadio[uint8_t id];
interface TimeSyncAMSend<TMilli, uint32_t> as TimeSyncAMSendMilli[uint8_t id];
interface Packet;
interface TimeSyncPacket<TRadio, uint32_t> as TimeSyncPacketRadio;
interface TimeSyncPacket<TMilli, uint32_t> as TimeSyncPacketMilli;
}
uses
{
interface AMSend as SubSend[uint8_t id];
interface Packet as SubPacket;
interface PacketTimeStamp<TRadio, uint32_t> as PacketTimeStampRadio;
interface PacketTimeStamp<TMilli, uint32_t> as PacketTimeStampMilli;
interface LocalTime<TRadio> as LocalTimeRadio;
interface LocalTime<TMilli> as LocalTimeMilli;
interface PacketField<uint8_t> as PacketTimeSyncOffset;
}
}
implementation
{
inline void* getFooter(message_t* msg)
{
// we use the payload length that we export (the smaller one)
return msg->data + call Packet.payloadLength(msg);
}
/*----------------- Packet -----------------*/
command void Packet.clear(message_t* msg)
{
call SubPacket.clear(msg);
}
command void Packet.setPayloadLength(message_t* msg, uint8_t len)
{
call SubPacket.setPayloadLength(msg, len + sizeof(timesync_relative_t));
}
command uint8_t Packet.payloadLength(message_t* msg)
{
return call SubPacket.payloadLength(msg) - sizeof(timesync_relative_t);
}
command uint8_t Packet.maxPayloadLength()
{
return call SubPacket.maxPayloadLength() - sizeof(timesync_relative_t);
}
command void* Packet.getPayload(message_t* msg, uint8_t len)
{
return call SubPacket.getPayload(msg, len + sizeof(timesync_relative_t));
}
/*----------------- TimeSyncAMSendRadio -----------------*/
command error_t TimeSyncAMSendRadio.send[am_id_t id](am_addr_t addr, message_t* msg, uint8_t len, uint32_t event_time)
{
*(timesync_absolute_t*)(msg->data + len) = event_time;
call PacketTimeSyncOffset.set(msg, len);
return call SubSend.send[id](addr, msg, len + sizeof(timesync_relative_t));
}
command error_t TimeSyncAMSendRadio.cancel[am_id_t id](message_t* msg)
{
return call SubSend.cancel[id](msg);
}
default event void TimeSyncAMSendRadio.sendDone[am_id_t id](message_t* msg, error_t error)
{
}
command uint8_t TimeSyncAMSendRadio.maxPayloadLength[am_id_t id]()
{
return call SubSend.maxPayloadLength[id]() - sizeof(timesync_relative_t);
}
command void* TimeSyncAMSendRadio.getPayload[am_id_t id](message_t* msg, uint8_t len)
{
return call SubSend.getPayload[id](msg, len + sizeof(timesync_relative_t));
}
/*----------------- TimeSyncAMSendMilli -----------------*/
command error_t TimeSyncAMSendMilli.send[am_id_t id](am_addr_t addr, message_t* msg, uint8_t len, uint32_t event_time)
{
// compute elapsed time in millisecond
event_time = ((int32_t)(event_time - call LocalTimeMilli.get()) << 10) + call LocalTimeRadio.get();
return call TimeSyncAMSendRadio.send[id](addr, msg, len, event_time);
}
command error_t TimeSyncAMSendMilli.cancel[am_id_t id](message_t* msg)
{
return call TimeSyncAMSendRadio.cancel[id](msg);
}
default event void TimeSyncAMSendMilli.sendDone[am_id_t id](message_t* msg, error_t error)
{
}
command uint8_t TimeSyncAMSendMilli.maxPayloadLength[am_id_t id]()
{
return call TimeSyncAMSendRadio.maxPayloadLength[id]();
}
command void* TimeSyncAMSendMilli.getPayload[am_id_t id](message_t* msg, uint8_t len)
{
return call TimeSyncAMSendRadio.getPayload[id](msg, len);
}
/*----------------- SubSend.sendDone -------------------*/
event void SubSend.sendDone[am_id_t id](message_t* msg, error_t error)
{
signal TimeSyncAMSendRadio.sendDone[id](msg, error);
signal TimeSyncAMSendMilli.sendDone[id](msg, error);
}
/*----------------- TimeSyncPacketRadio -----------------*/
command bool TimeSyncPacketRadio.isValid(message_t* msg)
{
timesync_relative_t* timesync = getFooter(msg);
return call PacketTimeStampRadio.isValid(msg) && *timesync != 0x80000000L;
}
command uint32_t TimeSyncPacketRadio.eventTime(message_t* msg)
{
timesync_relative_t* timesync = getFooter(msg);
return (*timesync) + call PacketTimeStampRadio.timestamp(msg);
}
/*----------------- TimeSyncPacketMilli -----------------*/
command bool TimeSyncPacketMilli.isValid(message_t* msg)
{
timesync_relative_t* timesync = getFooter(msg);
return call PacketTimeStampMilli.isValid(msg) && *timesync != 0x80000000L;
}
command uint32_t TimeSyncPacketMilli.eventTime(message_t* msg)
{
timesync_relative_t* timesync = getFooter(msg);
return ((int32_t)(*timesync) >> 10) + call PacketTimeStampMilli.timestamp(msg);
}
}
--- RF230.h DELETED ---
--- RF230ActiveMessageC.nc DELETED ---
--- RF230ActiveMessageP.nc DELETED ---
--- RF230Config.nc DELETED ---
--- RF230LayerC.nc DELETED ---
--- RF230LayerP.nc DELETED ---
--- RF230Packet.h DELETED ---
--- RF230PacketC.nc DELETED ---
--- RF230PacketP.nc DELETED ---
--- RF230TimeSyncMessageC.nc DELETED ---
--- RF230TimeSyncMessageP.nc DELETED ---
- Previous message: [Tinyos-2-commits] CVS: tinyos-2.x/tos/platforms/iris/chips/rf230 RadioAlarm.h, NONE, 1.1 HplRF230.h, 1.6, 1.7 HplRF230C.nc, 1.7, 1.8 HplRF230P.nc, 1.2, 1.3
- Next message: [Tinyos-2-commits] CVS: tinyos-2.x/tos/platforms/iris/chips/rf230 HplRF2xx.h, NONE, 1.1 HplRF2xxC.nc, NONE, 1.1 HplRF2xxP.nc, NONE, 1.1 RadioAlarm.h, 1.1, 1.2 HplRF230.h, 1.7, NONE HplRF230C.nc, 1.8, NONE HplRF230P.nc, 1.3, NONE
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Tinyos-2-commits
mailing list