[Tinyos-2-commits] CVS: tinyos-2.x/tos/chips/cc2420_tkn154 CC2420AsyncSplitControl.nc, NONE, 1.1 CC2420Config.nc, NONE, 1.1 CC2420ControlP.nc, NONE, 1.1 CC2420ControlTransmitC.nc, NONE, 1.1 CC2420Power.nc, NONE, 1.1 CC2420Receive.nc, NONE, 1.1 CC2420ReceiveC.nc, NONE, 1.1 CC2420ReceiveP.nc, NONE, 1.1 CC2420Rx.nc, NONE, 1.1 CC2420TKN154C.nc, NONE, 1.1 CC2420TKN154P.nc, NONE, 1.1 CC2420TransmitP.nc, NONE, 1.1 CC2420Tx.nc, NONE, 1.1 CaptureTime.nc, NONE, 1.1 ReferenceTime.nc, NONE, 1.1 ReliableWait.nc, NONE, 1.1 TKN154_PHY.h, NONE, 1.1 Timestamp.nc, NONE, 1.1
Jan-Hinrich Hauer
janhauer at users.sourceforge.net
Mon Jun 16 11:02:42 PDT 2008
Update of /cvsroot/tinyos/tinyos-2.x/tos/chips/cc2420_tkn154
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv31609/tos/chips/cc2420_tkn154
Added Files:
CC2420AsyncSplitControl.nc CC2420Config.nc CC2420ControlP.nc
CC2420ControlTransmitC.nc CC2420Power.nc CC2420Receive.nc
CC2420ReceiveC.nc CC2420ReceiveP.nc CC2420Rx.nc
CC2420TKN154C.nc CC2420TKN154P.nc CC2420TransmitP.nc
CC2420Tx.nc CaptureTime.nc ReferenceTime.nc ReliableWait.nc
TKN154_PHY.h Timestamp.nc
Log Message:
Initial version of a CC2420 driver for TKN15.4 (see tinyos-2.x/tos/lib/mac/tkn154/README.txt)
--- NEW FILE: CC2420AsyncSplitControl.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. - Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. - Neither the name of the
* Technische Universitaet Berlin nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
/*
* "Copyright (c) 2005 Washington University in St. Louis.
* 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 WASHINGTON UNIVERSITY IN ST. LOUIS 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 WASHINGTON
* UNIVERSITY IN ST. LOUIS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* WASHINGTON UNIVERSITY IN ST. LOUIS 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 WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
* MODIFICATIONS."
*/
/*
* "Copyright (c) 2000-2005 The Regents of the University of California.
* 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 UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA 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 UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*/
/**
* An async version of the SplitControl interface.
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
*/
interface CC2420AsyncSplitControl
{
/**
* Start this component and all of its subcomponents. Return
* values of SUCCESS will always result in a <code>startDone()</code>
* event being signalled.
*
* @return SUCCESS if the device is already in the process of
* starting or the device was off and the device is now ready to turn
* on. After receiving this return value, you should expect a
* <code>startDone</code> event in the near future.<br>
* EBUSY if the component is in the middle of powering down
* i.e. a <code>stop()</code> command has been called,
* and a <code>stopDone()</code> event is pending<br>
* EALREADY if the device is already on <br>
* FAIL Otherwise
*/
async command error_t start();
/**
* Notify caller that the component has been started and is ready to
* receive other commands.
*
* @param <b>error</b> -- SUCCESS if the component was successfully
* turned on, FAIL otherwise
*/
async event void startDone(error_t error);
/**
* Start this component and all of its subcomponents. Return
* values of SUCCESS will always result in a <code>startDone()</code>
* event being signalled.
*
* @return SUCCESS if the device is already in the process of
* stopping or the device was on and the device is now ready to turn
* off. After receiving this return value, you should expect a
* <code>stopDone</code> event in the near future.<br>
* EBUSY if the component is in the middle of powering up
* i.e. a <code>start()</code> command has been called,
* and a <code>startDone()</code> event is pending<br>
* EALREADY if the device is already off <br>
* FAIL Otherwise
*/
async command error_t stop();
/**
* Notify caller that the component has been stopped.
*
* @param <b>error</b> -- SUCCESS if the component was successfully
* turned off, FAIL otherwise
*/
async event void stopDone(error_t error);
}
--- NEW FILE: CC2420Config.nc ---
/*
* Copyright (c) 2005-2006 Arch Rock Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the Arch Rock Corporation nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE
*/
/**
* An HAL abstraction of the ChipCon CC2420 radio. This abstraction
* deals specifically with radio configurations. All get() and set()
* commands are single-phase. After setting some values, a call to
* sync() is required for the changes to propagate to the cc2420
* hardware chip. This interface allows setting multiple parameters
* before calling sync().
*
* @author Jonathan Hui <jhui at archrock.com>
* @author Jan Hauer <hauer at tkn.tu-berlin.de> (added some commands)
* @version $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
*/
interface CC2420Config {
/**
* Sync configuration changes with the radio hardware. This only
* applies to set commands below.
*
* @return SUCCESS if the request was accepted, FAIL otherwise.
*/
async command error_t sync();
/**
* Whether changes have been made that should be sync-ed.
*
* @return TRUE if changes have been made, FALSE otherwise.
*/
async command bool needsSync();
/**
* Change the channel of the radio, between 11 and 26
*/
command uint8_t getChannel();
command void setChannel( uint8_t channel );
/**
* Change the short address of the radio.
*/
async command uint16_t getShortAddr();
command void setShortAddr( uint16_t address );
/**
* Change the PAN address of the radio.
*/
async command uint16_t getPanAddr();
command void setPanAddr( uint16_t address );
/**
* Change the PAN address of the radio.
*/
async command bool getPanCoordinator();
command void setPanCoordinator( bool pcoord );
/**
* Change to promiscuous mode.
*/
command void setPromiscuousMode(bool on);
async command bool isPromiscuousModeEnabled();
/**
* Change the CCA mode.
*/
async command uint8_t getCCAMode();
command void setCCAMode(uint8_t mode);
/**
* Change the transmission power.
*/
async command uint8_t getTxPower();
command void setTxPower(uint8_t txPower);
}
--- NEW FILE: CC2420ControlP.nc ---
/*
* Copyright (c) 2005-2006 Arch Rock Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the Arch Rock Corporation nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE
*/
/**
* @author Jonathan Hui <jhui at archrock.com>
* @author David Moss
* @author Urs Hunkeler (ReadRssi implementation)
* @author Jan Hauer <hauer at tkn.tu-berlin.de> (support for promiscuous mode)
* @version $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
*/
#include "Timer.h"
#include "AM.h"
#include "TKN154_PIB.h"
module CC2420ControlP {
provides interface Init;
provides interface Resource;
provides interface CC2420Config;
provides interface CC2420Power;
uses interface Alarm<T62500hz,uint32_t> as StartupAlarm;
uses interface GeneralIO as CSN;
uses interface GeneralIO as RSTN;
uses interface GeneralIO as VREN;
uses interface GpioInterrupt as InterruptCCA;
uses interface CC2420Ram as IEEEADR;
uses interface CC2420Register as FSCTRL;
uses interface CC2420Register as IOCFG0;
uses interface CC2420Register as IOCFG1;
uses interface CC2420Register as MDMCTRL0;
uses interface CC2420Register as MDMCTRL1;
uses interface CC2420Register as RXCTRL1;
uses interface CC2420Register as RSSI;
uses interface CC2420Strobe as SRXON;
uses interface CC2420Strobe as SRFOFF;
uses interface CC2420Strobe as SXOSCOFF;
uses interface CC2420Strobe as SXOSCON;
uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
uses interface CC2420Register as TXCTRL;
uses interface AMPacket;
uses interface Resource as SpiResource;
uses interface Leds;
uses interface FrameUtility;
}
implementation {
typedef enum {
S_VREG_STOPPED,
S_VREG_STARTING,
S_VREG_STARTED,
S_XOSC_STARTING,
S_XOSC_STARTED,
} cc2420_control_state_t;
uint8_t m_channel;
uint16_t m_pan;
uint16_t m_short_addr;
bool autoAckEnabled;
bool hwAutoAckDefault;
bool addressRecognition;
bool acceptReservedFrames;
bool m_isPanCoord;
uint8_t m_CCAMode;
uint8_t m_txPower;
bool m_needsSync;
norace cc2420_control_state_t m_state = S_VREG_STOPPED;
/***************** Prototypes ****************/
void writeFsctrl();
void writeMdmctrl0();
void writeId();
void writeTxPower();
/***************** Init Commands ****************/
command error_t Init.init() {
call CSN.makeOutput();
call RSTN.makeOutput();
call VREN.makeOutput();
autoAckEnabled = TRUE;
hwAutoAckDefault = TRUE;
addressRecognition = TRUE;
acceptReservedFrames = FALSE;
m_needsSync = FALSE;
return SUCCESS;
}
/***************** Resource Commands ****************/
async command error_t Resource.immediateRequest() {
error_t error = call SpiResource.immediateRequest();
if ( error == SUCCESS ) {
/* call CSN.clr();*/
}
return error;
}
async command error_t Resource.request() {
return call SpiResource.request();
}
async command uint8_t Resource.isOwner() {
return call SpiResource.isOwner();
}
async command error_t Resource.release() {
atomic {
/* call CSN.set();*/
return call SpiResource.release();
}
}
void switchToUnbufferedMode()
{
uint16_t mdmctrol1;
call CSN.set();
call CSN.clr();
call MDMCTRL1.read(&mdmctrol1);
call CSN.set();
mdmctrol1 &= ~0x0003;
mdmctrol1 |= 0x0000;
call CSN.clr();
call MDMCTRL1.write(mdmctrol1);
call CSN.set();
}
void switchToBufferedMode()
{
uint16_t mdmctrol1;
call CSN.set();
call CSN.clr();
call MDMCTRL1.read(&mdmctrol1);
mdmctrol1 &= ~0x03;
call MDMCTRL1.write(mdmctrol1);
call CSN.set();
}
/***************** CC2420Power Commands ****************/
async command error_t CC2420Power.startVReg() {
atomic {
if ( m_state != S_VREG_STOPPED ) {
return FAIL;
}
m_state = S_VREG_STARTING;
}
call VREN.set();
call StartupAlarm.start( CC2420_TIME_VREN * 2 ); // JH: a 15.4 symbol is about two 32khz ticks
return SUCCESS;
}
async command error_t CC2420Power.stopVReg() {
m_state = S_VREG_STOPPED;
call RSTN.clr();
call VREN.clr();
call RSTN.set();
return SUCCESS;
}
async command error_t CC2420Power.startOscillator() {
atomic {
if ( m_state != S_VREG_STARTED ) {
return FAIL;
}
m_state = S_XOSC_STARTING;
call CSN.set();
call CSN.clr();
call IOCFG1.write( CC2420_SFDMUX_XOSC16M_STABLE <<
CC2420_IOCFG1_CCAMUX );
call InterruptCCA.enableRisingEdge();
call SXOSCON.strobe();
call IOCFG0.write( ( 1 << CC2420_IOCFG0_FIFOP_POLARITY ) |
( 127 << CC2420_IOCFG0_FIFOP_THR ) );
writeFsctrl();
writeMdmctrl0();
call RXCTRL1.write( ( 1 << CC2420_RXCTRL1_RXBPF_LOCUR ) |
( 1 << CC2420_RXCTRL1_LOW_LOWGAIN ) |
( 1 << CC2420_RXCTRL1_HIGH_HGM ) |
( 1 << CC2420_RXCTRL1_LNA_CAP_ARRAY ) |
( 1 << CC2420_RXCTRL1_RXMIX_TAIL ) |
( 1 << CC2420_RXCTRL1_RXMIX_VCM ) |
( 2 << CC2420_RXCTRL1_RXMIX_CURRENT ) );
call CSN.set();
}
return SUCCESS;
}
async command error_t CC2420Power.stopOscillator() {
atomic {
if ( m_state != S_XOSC_STARTED ) {
return FAIL;
}
m_state = S_VREG_STARTED;
call CSN.set();
call CSN.clr();
call SXOSCOFF.strobe();
call CSN.set();
}
return SUCCESS;
}
async command error_t CC2420Power.rxOn() {
atomic {
if ( m_state != S_XOSC_STARTED ) {
return FAIL;
}
call CSN.set();
call CSN.clr();
call SRXON.strobe();
call SACKPEND.strobe(); // JH: ACKs have the pending bit set
call CSN.set();
}
return SUCCESS;
}
async command error_t CC2420Power.rfOff() {
atomic {
if ( m_state != S_XOSC_STARTED ) {
return FAIL;
}
call CSN.set();
call CSN.clr();
call SACKPEND.strobe(); // JH: ACKs have the pending bit set
call SRFOFF.strobe();
call CSN.set();
}
return SUCCESS;
}
/***************** CC2420Config Commands ****************/
command uint8_t CC2420Config.getChannel() {
atomic return m_channel;
}
command void CC2420Config.setChannel( uint8_t channel ) {
atomic {
m_needsSync = TRUE;
m_channel = channel;
}
}
async command uint16_t CC2420Config.getShortAddr() {
atomic return m_short_addr;
}
command void CC2420Config.setShortAddr( uint16_t addr ) {
atomic {
m_needsSync = TRUE;
m_short_addr = addr;
}
}
async command uint16_t CC2420Config.getPanAddr() {
atomic return m_pan;
}
command void CC2420Config.setPanAddr( uint16_t pan ) {
atomic {
m_needsSync = TRUE;
m_pan = pan;
}
}
async command bool CC2420Config.getPanCoordinator() {
atomic return m_isPanCoord;
}
command void CC2420Config.setPanCoordinator( bool pCoord ) {
atomic {
m_needsSync = TRUE;
m_isPanCoord = pCoord;
}
}
command void CC2420Config.setPromiscuousMode(bool on)
{
atomic {
m_needsSync = TRUE;
if (on){
addressRecognition = FALSE;
acceptReservedFrames = TRUE;
autoAckEnabled = FALSE;
} else {
addressRecognition = TRUE;
acceptReservedFrames = FALSE;
autoAckEnabled = TRUE;
}
}
}
async command bool CC2420Config.isPromiscuousModeEnabled()
{
return acceptReservedFrames;
}
async command uint8_t CC2420Config.getCCAMode()
{
atomic return m_CCAMode;
}
command void CC2420Config.setCCAMode(uint8_t mode)
{
atomic {
m_needsSync = TRUE;
m_CCAMode = mode;
}
}
async command uint8_t CC2420Config.getTxPower()
{
atomic return m_txPower;
}
command void CC2420Config.setTxPower(uint8_t txPower)
{
atomic {
m_needsSync = TRUE;
m_txPower = txPower;
}
}
async command bool CC2420Config.needsSync(){
atomic return m_needsSync;
}
/**
* Sync must be called to commit software parameters configured on
* the microcontroller (through the CC2420Config interface) to the
* CC2420 radio chip.
* ASSUMPTION: caller owns the SPI, radio will be switched off !
*/
async command error_t CC2420Config.sync() {
atomic {
if ( m_state != S_XOSC_STARTED ) {
return FAIL;
}
if (m_needsSync){
call CSN.set();
call CSN.clr();
call SRFOFF.strobe();
call CSN.set();
call CSN.clr();
writeFsctrl();
writeMdmctrl0();
writeTxPower();
call CSN.set();
call CSN.clr();
writeId();
call CSN.set();
m_needsSync = FALSE;
}
}
return SUCCESS;
}
/***************** ReadRssi Commands ****************/
async command error_t CC2420Power.rssi(int8_t *rssi) {
// we are owner of the Spi !
uint16_t data;
cc2420_status_t status;
call CSN.clr();
status = call RSSI.read(&data);
call CSN.set();
if ((status & 0x02)){
*rssi = (data & 0x00FF);
return SUCCESS;
} else
return FAIL;
}
event void SpiResource.granted() {
/* call CSN.clr();*/
signal Resource.granted();
}
/***************** StartupAlarm Events ****************/
async event void StartupAlarm.fired() {
if ( m_state == S_VREG_STARTING ) {
m_state = S_VREG_STARTED;
call RSTN.clr();
call RSTN.set();
signal CC2420Power.startVRegDone();
}
}
/***************** InterruptCCA Events ****************/
async event void InterruptCCA.fired() {
m_state = S_XOSC_STARTED;
call InterruptCCA.disable();
call CSN.set();
call CSN.clr();
call IOCFG1.write( 0 );
writeId();
call CSN.set();
signal CC2420Power.startOscillatorDone();
}
/***************** Functions ****************/
/**
* Write teh FSCTRL register
*/
void writeFsctrl() {
uint8_t channel;
atomic {
channel = m_channel;
}
call FSCTRL.write( ( 1 << CC2420_FSCTRL_LOCK_THR ) |
( ( (channel - 11)*5+357 ) << CC2420_FSCTRL_FREQ ) );
}
/**
* Write the MDMCTRL0 register
*/
void writeMdmctrl0() {
atomic {
uint8_t _acceptReservedFrames = (acceptReservedFrames ? 1: 0);
uint8_t _panCoord = (m_isPanCoord ? 1: 0);
uint8_t _addressRecognition = (addressRecognition ? 1: 0);
uint8_t _autoAck = ((autoAckEnabled && hwAutoAckDefault) ? 1 : 0);
call MDMCTRL0.write( ( _acceptReservedFrames << CC2420_MDMCTRL0_RESERVED_FRAME_MODE ) |
( _panCoord << CC2420_MDMCTRL0_PAN_COORDINATOR ) |
( _addressRecognition << CC2420_MDMCTRL0_ADR_DECODE ) |
( 2 << CC2420_MDMCTRL0_CCA_HYST ) |
( m_CCAMode << CC2420_MDMCTRL0_CCA_MOD ) |
( 1 << CC2420_MDMCTRL0_AUTOCRC ) |
( _autoAck << CC2420_MDMCTRL0_AUTOACK ) |
( 2 << CC2420_MDMCTRL0_PREAMBLE_LENGTH ) );
}
// Jon Green:
// MDMCTRL1.CORR_THR is defaulted to 20 instead of 0 like the datasheet says
// If we add in changes to MDMCTRL1, be sure to include this fix.
}
/**
* Write the IEEEADR register
*/
void writeId() {
uint16_t bcnAccept = 0;
nxle_uint16_t id[ 6 ];
atomic {
call FrameUtility.copyLocalExtendedAddressLE((uint8_t*) &id);
id[ 4 ] = m_pan;
id[ 5 ] = m_short_addr;
}
if (m_pan == 0xFFFF)
bcnAccept = 1;
call IOCFG0.write( (bcnAccept << CC2420_IOCFG0_BCN_ACCEPT) |
( 1 << CC2420_IOCFG0_FIFOP_POLARITY ) |
( 127 << CC2420_IOCFG0_FIFOP_THR ) );
// ext.adr, PANID and short adr are located at consecutive addresses in RAM
call IEEEADR.write(0, (uint8_t*)&id, sizeof(id));
}
void writeTxPower(){
call TXCTRL.write(
( 2 << CC2420_TXCTRL_TXMIXBUF_CUR ) |
( 3 << CC2420_TXCTRL_PA_CURRENT ) |
( 1 << CC2420_TXCTRL_RESERVED ) |
( (m_txPower & 0x1F) << CC2420_TXCTRL_PA_LEVEL ) );
}
}
--- NEW FILE: CC2420ControlTransmitC.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
/**
* This configuration combines CC2420ControlC and CC2420TransmitC
* and uses only one instance of CC2420SpiC.
*
* @author Jonathan Hui <jhui at archrock.com>
* @author Jan-Hinrich Hauer
* @version $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
*/
#include "CC2420.h"
configuration CC2420ControlTransmitC {
provides {
// CC2420ControlC
interface Resource;
interface CC2420Config;
interface CC2420Power;
// CC2420TransmitC
interface AsyncStdControl as TxControl;
interface CC2420Tx;
} uses {
// CC2420ControlC
interface Alarm<T62500hz,uint32_t> as StartupAlarm;
interface FrameUtility;
// CC2420TransmitC
interface Alarm<T62500hz,uint32_t> as AckAlarm;
interface CaptureTime;
interface ReferenceTime;
interface Leds;
}
}
implementation {
// CC2420ControlC
components CC2420ControlP;
Resource = CC2420ControlP;
CC2420Config = CC2420ControlP;
CC2420Power = CC2420ControlP;
FrameUtility = CC2420ControlP;
CC2420ControlP.Leds = Leds;
components MainC;
MainC.SoftwareInit -> CC2420ControlP;
CC2420ControlP.StartupAlarm = StartupAlarm;
components HplCC2420PinsC as Pins;
CC2420ControlP.CSN -> Pins.CSN;
CC2420ControlP.RSTN -> Pins.RSTN;
CC2420ControlP.VREN -> Pins.VREN;
components HplCC2420InterruptsC as Interrupts;
CC2420ControlP.InterruptCCA -> Interrupts.InterruptCCA;
components new CC2420SpiC() as Spi;
CC2420ControlP.SpiResource -> Spi;
CC2420ControlP.SRXON -> Spi.SRXON;
CC2420ControlP.SACKPEND -> Spi.SACKPEND;
CC2420ControlP.SRFOFF -> Spi.SRFOFF;
CC2420ControlP.SXOSCON -> Spi.SXOSCON;
CC2420ControlP.SXOSCOFF -> Spi.SXOSCOFF;
CC2420ControlP.FSCTRL -> Spi.FSCTRL;
CC2420ControlP.IOCFG0 -> Spi.IOCFG0;
CC2420ControlP.IOCFG1 -> Spi.IOCFG1;
CC2420ControlP.MDMCTRL0 -> Spi.MDMCTRL0;
CC2420ControlP.MDMCTRL1 -> Spi.MDMCTRL1;
/* CC2420ControlP.PANID -> Spi.PANID;*/
CC2420ControlP.TXCTRL -> Spi.TXCTRL;
CC2420ControlP.IEEEADR -> Spi.IEEEADR;
CC2420ControlP.RXCTRL1 -> Spi.RXCTRL1;
CC2420ControlP.RSSI -> Spi.RSSI;
// CC2420TransmitC
components CC2420TransmitP;
TxControl = CC2420TransmitP;
CC2420Tx = CC2420TransmitP;
AckAlarm = CC2420TransmitP;
CaptureTime = CC2420TransmitP;
ReferenceTime = CC2420TransmitP;
CC2420TransmitP.Leds = Leds;
MainC.SoftwareInit -> CC2420TransmitP;
CC2420TransmitP.CCA -> Pins.CCA;
CC2420TransmitP.CSN -> Pins.CSN;
CC2420TransmitP.SFD -> Pins.SFD;
CC2420TransmitP.CaptureSFD -> Interrupts.CaptureSFD;
CC2420TransmitP.ChipSpiResource -> Spi;
CC2420TransmitP.SNOP -> Spi.SNOP;
CC2420TransmitP.STXON -> Spi.STXON;
CC2420TransmitP.STXONCCA -> Spi.STXONCCA;
CC2420TransmitP.SFLUSHTX -> Spi.SFLUSHTX;
CC2420TransmitP.TXCTRL -> Spi.TXCTRL;
CC2420TransmitP.TXFIFO -> Spi.TXFIFO;
CC2420TransmitP.TXFIFO_RAM -> Spi.TXFIFO_RAM;
CC2420TransmitP.MDMCTRL1 -> Spi.MDMCTRL1;
CC2420TransmitP.SRXON -> Spi.SRXON;
CC2420TransmitP.SRFOFF -> Spi.SRFOFF;
CC2420TransmitP.SFLUSHRX-> Spi.SFLUSHRX;
CC2420TransmitP.SACKPEND -> Spi.SACKPEND;
components CC2420ReceiveC;
CC2420TransmitP.CC2420Receive -> CC2420ReceiveC;
components CC2420PacketC;
CC2420TransmitP.CC2420Packet -> CC2420PacketC;
CC2420TransmitP.CC2420PacketBody -> CC2420PacketC;
}
--- NEW FILE: CC2420Power.nc ---
/*
* Copyright (c) 2005-2006 Arch Rock Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the Arch Rock Corporation nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE
*/
/**
* An HAL abstraction of the ChipCon CC2420 radio. This abstraction
* deals specifically with radio power operations (e.g. voltage
* regulator, oscillator, etc). However, it does not include
* transmission power, see the CC2420Config interface.
*
* @author Jonathan Hui <jhui at archrock.com>
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* @version $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
*/
interface CC2420Power {
/**
* Start the voltage regulator on the CC2420. On SUCCESS,
* <code>startVReg()</code> will be signalled when the voltage
* regulator is fully on.
*
* @return SUCCESS if the request was accepted, FAIL otherwise.
*/
async command error_t startVReg();
/**
* Signals that the voltage regulator has been started.
*/
async event void startVRegDone();
/**
* Stop the voltage regulator immediately.
*
* @return SUCCESS always
*/
async command error_t stopVReg();
/**
* Start the oscillator. On SUCCESS, <code>startOscillator</code>
* will be signalled when the oscillator has been started.
*
* @return SUCCESS if the request was accepted, FAIL otherwise.
*/
async command error_t startOscillator();
/**
* Signals that the oscillator has been started.
*/
async event void startOscillatorDone();
/**
* Stop the oscillator.
*
* @return SUCCESS if the oscillator was stopped, FAIL otherwise.
*/
async command error_t stopOscillator();
/**
* Enable RX.
*
* @return SUCCESS if receive mode has been enabled, FAIL otherwise.
*/
async command error_t rxOn();
/**
* Disable RX.
*
* @return SUCCESS if receive mode has been disabled, FAIL otherwise.
*/
async command error_t rfOff();
/**
* Read RSSI from the radio.
* @return SUCCESS if RSSI was read successfulyy, FAIL otherwise.
*/
async command error_t rssi(int8_t *rssi);
}
--- NEW FILE: CC2420Receive.nc ---
/*
* Copyright (c) 2005-2006 Arch Rock Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the Arch Rock Corporation nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE
*/
/**
* Low-level abstraction of the receive path implementation for the
* ChipCon CC2420 radio.
*
* @author Jonathan Hui <jhui at archrock.com>
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* @version $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
*/
interface CC2420Receive {
/**
* Notification that an SFD capture has occured.
*
* @param time at which the capture happened.
*/
async command void sfd( ieee154_reftime_t *time );
/**
* Notification that the packet has been dropped by the radio
* (e.g. due to address rejection).
*/
async command void sfd_dropped();
/**
* Signals that a message has been received.
*
* @param type of the message received.
* @param message pointer to message received.
*/
async event void receive( uint8_t type, message_t* message );
}
--- NEW FILE: CC2420ReceiveC.nc ---
/*
* Copyright (c) 2005-2006 Arch Rock Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the Arch Rock Corporation nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE
*/
/**
* Implementation of the receive path for the ChipCon CC2420 radio.
*
* @author Jonathan Hui <jhui at archrock.com>
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* @version $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
*/
configuration CC2420ReceiveC {
provides interface CC2420AsyncSplitControl;
provides interface CC2420Receive; // to CC2420TransmitP for ACK
provides interface CC2420Rx; // to the driver
uses interface ReferenceTime;
uses interface Leds;
uses interface FrameUtility;
uses interface CC2420Config;
}
implementation {
components MainC;
components CC2420ReceiveP;
components new CC2420SpiC() as Spi;
components HplCC2420PinsC as Pins;
components HplCC2420InterruptsC as InterruptsC;
CC2420ReceiveP.Leds = Leds;
CC2420AsyncSplitControl = CC2420ReceiveP;
CC2420Receive = CC2420ReceiveP;
CC2420Rx = CC2420ReceiveP;
ReferenceTime = CC2420ReceiveP;
FrameUtility = CC2420ReceiveP;
CC2420Config = CC2420ReceiveP;
MainC.SoftwareInit -> CC2420ReceiveP;
CC2420ReceiveP.CSN -> Pins.CSN;
CC2420ReceiveP.FIFO -> Pins.FIFO;
CC2420ReceiveP.FIFOP -> Pins.FIFOP;
CC2420ReceiveP.InterruptFIFOP -> InterruptsC.InterruptFIFOP;
CC2420ReceiveP.SpiResource -> Spi;
CC2420ReceiveP.RXFIFO -> Spi.RXFIFO;
CC2420ReceiveP.SFLUSHRX -> Spi.SFLUSHRX;
CC2420ReceiveP.SACK -> Spi.SACK;
CC2420ReceiveP.SACKPEND -> Spi.SACKPEND;
CC2420ReceiveP.SRXON -> Spi.SRXON;
CC2420ReceiveP.MDMCTRL1 -> Spi.MDMCTRL1;
}
--- NEW FILE: CC2420ReceiveP.nc ---
/*
* Copyright (c) 2005-2006 Arch Rock Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the Arch Rock Corporation nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE
*/
/**
* @author Jonathan Hui <jhui at archrock.com>
* @author David Moss
* @author Jung Il Choi
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* @version $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
*/
module CC2420ReceiveP {
provides interface Init;
provides interface CC2420AsyncSplitControl as AsyncSplitControl;
provides interface CC2420Receive;
provides interface CC2420Rx;
/* provides interface ReceiveIndicator as PacketIndicator;*/
uses interface GeneralIO as CSN;
uses interface GeneralIO as FIFO;
uses interface GeneralIO as FIFOP;
uses interface GpioInterrupt as InterruptFIFOP;
uses interface Resource as SpiResource;
uses interface CC2420Fifo as RXFIFO;
uses interface CC2420Strobe as SACK;
uses interface CC2420Strobe as SFLUSHRX;
uses interface CC2420Strobe as SRXON;
uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
uses interface CC2420Register as MDMCTRL1;
uses interface ReferenceTime;
uses interface FrameUtility;
uses interface CC2420Config;
/* uses interface CC2420Packet;*/
/* uses interface CC2420PacketBody;*/
uses interface Leds;
}
implementation {
typedef enum {
S_STOPPED,
S_STARTING,
S_STARTING_FLUSHRX,
S_STARTED,
S_RX_LENGTH,
S_RX_FCF,
S_RX_HEADER,
S_RX_PAYLOAD,
} cc2420_receive_state_t;
enum {
RXFIFO_SIZE = 128,
TIMESTAMP_QUEUE_SIZE = 8,
//SACK_HEADER_LENGTH = 7,
SACK_HEADER_LENGTH = 3,
};
ieee154_reftime_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ];
ieee154_reftime_t m_timestamp;
norace bool m_timestampValid;
uint8_t m_timestamp_head;
uint8_t m_timestamp_size;
/** Number of packets we missed because we were doing something else */
uint8_t m_missed_packets;
/** TRUE if we are receiving a valid packet into the stack */
norace bool receivingPacket;
/** The length of the frame we're currently receiving */
norace uint8_t rxFrameLength;
norace uint8_t m_bytes_left;
// norace message_t* m_p_rx_buf;
// message_t m_rx_buf;
cc2420_receive_state_t m_state;
// new packet format:
message_t m_frame;
norace message_t *m_rxFramePtr;
norace uint8_t m_mhrLen;
uint8_t m_dummy;
norace bool m_stop;
/***************** Prototypes ****************/
void reset_state();
void beginReceive();
void receive();
void waitForNextPacket();
void flush();
void switchToUnbufferedMode();
void switchToBufferedMode();
void startingSpiReserved();
void continueStart();
void continueStop();
task void stopContinueTask();
task void receiveDone_task();
/***************** Init Commands ****************/
command error_t Init.init() {
m_rxFramePtr = &m_frame;
atomic m_state = S_STOPPED;
return SUCCESS;
}
/***************** AsyncSplitControl ****************
* IMPORTANT: when AsyncSplitControl.start is called,
* the radio MUST be off !
*/
async command error_t AsyncSplitControl.start()
{
atomic {
if (m_state != S_STOPPED){
call Leds.led0On();
return FAIL;
} else {
m_state = S_STARTING;
if (call SpiResource.isOwner()){
call Leds.led0On(); // internal error (debug) !
startingSpiReserved();
}
if (call SpiResource.immediateRequest() == SUCCESS)
startingSpiReserved();
else
call SpiResource.request();
}
}
return SUCCESS;
}
void startingSpiReserved()
{
atomic {
if (!call FIFOP.get() || call FIFO.get()){ // FIFOP is inverted
// there is something in RXFIFO: flush it out
// the datasheet says at least one byte should
// be read before flushing
m_state = S_STARTING_FLUSHRX;
call CSN.set();
call CSN.clr();
call RXFIFO.beginRead( &m_dummy, 1 ); // will continue in continueFlushStart()
return;
}
}
continueStart();
}
void continueFlushStart()
{
atomic {
call CSN.set();
call CSN.clr();
call SFLUSHRX.strobe();
call SFLUSHRX.strobe();
call CSN.set();
}
continueStart();
}
void continueStart()
{
// RXFIFO is empty
if (!call FIFOP.get() || call FIFO.get()){
call Leds.led0On();
}
atomic {
reset_state();
m_state = S_STARTED;
}
call SpiResource.release();
call InterruptFIFOP.enableFallingEdge();
signal AsyncSplitControl.startDone(SUCCESS);
}
/***************** AsyncSplitControl ****************
* IMPORTANT: when AsyncSplitControl.stop is called,
* the radio MUST NOT be off !
*/
async command error_t AsyncSplitControl.stop()
{
atomic {
if (m_state == S_STOPPED)
return EALREADY;
else {
m_stop = TRUE;
call InterruptFIFOP.disable();
if (!receivingPacket)
continueStop();
// else stopContinueTask will be posted after
// current Rx operation is finished, because m_stop is set
}
}
return SUCCESS;
}
void continueStop()
{
atomic {
m_stop = FALSE;
m_state = S_STOPPED;
}
post stopContinueTask();
}
task void stopContinueTask()
{
if (receivingPacket){
call Leds.led0On();
}
call SpiResource.release(); // may fail
atomic m_state = S_STOPPED;
signal AsyncSplitControl.stopDone(SUCCESS);
}
void switchToUnbufferedMode()
{
uint16_t mdmctrol1;
call CSN.set();
call CSN.clr();
call MDMCTRL1.read(&mdmctrol1);
mdmctrol1 &= ~0x03;
mdmctrol1 |= 0x01;
call MDMCTRL1.write(mdmctrol1);
call CSN.set();
}
void switchToBufferedMode()
{
uint16_t mdmctrol1;
call CSN.set();
call CSN.clr();
call MDMCTRL1.read(&mdmctrol1);
mdmctrol1 &= ~0x03;
call MDMCTRL1.write(mdmctrol1);
call CSN.set();
}
/***************** CC2420Receive Commands ****************/
/**
* Start frame delimiter signifies the beginning/end of a packet
* See the CC2420 datasheet for details.
*/
async command void CC2420Receive.sfd( ieee154_reftime_t *time ) {
if (m_state == S_STOPPED)
return;
if ( m_timestamp_size < TIMESTAMP_QUEUE_SIZE ) {
uint8_t tail = ( ( m_timestamp_head + m_timestamp_size ) %
TIMESTAMP_QUEUE_SIZE );
memcpy(&m_timestamp_queue[ tail ], time, sizeof(ieee154_reftime_t) );
m_timestamp_size++;
}
}
async command void CC2420Receive.sfd_dropped() {
if (m_state == S_STOPPED)
return;
if ( m_timestamp_size ) {
m_timestamp_size--;
}
}
/***************** InterruptFIFOP Events ****************/
async event void InterruptFIFOP.fired() {
atomic {
if ( m_state == S_STARTED ) {
beginReceive();
} else {
m_missed_packets++;
}
}
}
/***************** SpiResource Events ****************/
event void SpiResource.granted() {
atomic {
switch (m_state)
{
case S_STARTING: startingSpiReserved(); break;
case S_STARTING_FLUSHRX: // fall through
case S_STOPPED: call Leds.led0On();
call SpiResource.release(); break;
default: receive();
}
}
}
uint8_t mhrLength(uint8_t *fcf)
{
uint8_t idCompression;
uint8_t len = MHR_INDEX_ADDRESS;
if (fcf[MHR_INDEX_FC1] & FC1_SECURITY_ENABLED)
return 0xFF; // not supported
idCompression = (fcf[0] & FC1_PAN_ID_COMPRESSION);
if (fcf[MHR_INDEX_FC2] & 0x08){ // short or ext. address
len += 4; // pan id + short address
if (fcf[MHR_INDEX_FC2] & 0x04) // ext. address
len += 6; // diff to short address
}
if (fcf[MHR_INDEX_FC2] & 0x80){ // short or ext. address
len += 2;
if (!idCompression)
len += 2;
if (fcf[MHR_INDEX_FC2] & 0x40) // ext. address
len += 6; // diff to short address
}
return len;
}
/***************** RXFIFO Events ****************/
/**
* We received some bytes from the SPI bus. Process them in the context
* of the state we're in. Remember the length byte is not part of the length
*/
async event void RXFIFO.readDone( uint8_t* rx_buf, uint8_t rx_len,
error_t error ) {
uint8_t* buf;
atomic {
buf = (uint8_t*) &((ieee154_header_t*) m_rxFramePtr->header)->length;
rxFrameLength = ((ieee154_header_t*) m_rxFramePtr->header)->length;
switch( m_state ) {
case S_RX_LENGTH:
m_state = S_RX_FCF;
if ( rxFrameLength + 1 > m_bytes_left ) {
// Length of this packet is bigger than the RXFIFO, flush it out.
flush();
} else {
if ( !call FIFO.get() && !call FIFOP.get() ) {
//m_bytes_left -= rxFrameLength + 1;
flush();
}
//if(rxFrameLength <= MAC_PACKET_SIZE) {
if(rxFrameLength <= (sizeof(ieee154_header_t) - 1 + TOSH_DATA_LENGTH + 2)){
if(rxFrameLength > 0) {
if(rxFrameLength > SACK_HEADER_LENGTH) {
// This packet has an FCF byte plus at least one more byte to read
call RXFIFO.continueRead(buf + 1, SACK_HEADER_LENGTH);
} else {
// This is really a bad packet, skip FCF and get it out of here.
flush();
//m_state = S_RX_PAYLOAD;
//call RXFIFO.continueRead(buf + 1, rxFrameLength);
}
} else {
// Length == 0; start reading the next packet
flush();
/* atomic receivingPacket = FALSE;*/
/* call CSN.set();*/
/* call SpiResource.release();*/
/* waitForNextPacket();*/
}
} else {
// Length is too large; we have to flush the entire Rx FIFO
flush();
}
}
break;
case S_RX_FCF:
if (call FrameUtility.getMHRLength(buf[1], buf[2], &m_mhrLen) != SUCCESS ||
m_mhrLen > rxFrameLength - 2) {
// header size incorrect
flush();
break;
} else if (m_mhrLen > SACK_HEADER_LENGTH) {
m_state = S_RX_HEADER;
call RXFIFO.continueRead(buf + 1 + SACK_HEADER_LENGTH,
m_mhrLen - SACK_HEADER_LENGTH);
break;
} else {
// complete header has been read: fall through
}
// fall through
case S_RX_HEADER:
// JH: we are either using HW ACKs (normal receive mode) or don't ACK any
// packets (promiscuous mode)
// Didn't flip CSn, we're ok to continue reading.
if ((rxFrameLength - m_mhrLen - 2) > TOSH_DATA_LENGTH) // 2 for CRC
flush();
else {
m_state = S_RX_PAYLOAD;
call RXFIFO.continueRead((uint8_t*) m_rxFramePtr->data, rxFrameLength - m_mhrLen);
}
break;
case S_RX_PAYLOAD:
call CSN.set();
if(!m_missed_packets) {
// Release the SPI only if there are no more frames to download
call SpiResource.release();
}
if ( m_timestamp_size ) {
if ( rxFrameLength > 10 ) {
//((ieee154_metadata_t*) m_rxFramePtr->metadata)->timestamp = m_timestamp_queue[ m_timestamp_head ];
memcpy(&m_timestamp, &m_timestamp_queue[ m_timestamp_head ], sizeof(ieee154_reftime_t) );
m_timestampValid = TRUE;
m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE;
m_timestamp_size--;
}
} else {
/* metadata->time = 0xffff;*/
m_timestampValid = FALSE;
//((ieee154_metadata_t*) m_rxFramePtr->metadata)->timestamp = IEEE154_INVALID_TIMESTAMP;
}
// We may have received an ack that should be processed by Transmit
// buf[rxFrameLength] >> 7 checks the CRC
if ( ( m_rxFramePtr->data[ rxFrameLength - m_mhrLen - 1 ] >> 7 ) && rx_buf ) {
uint8_t type = ((ieee154_header_t*) m_rxFramePtr->header)->mhr[0] & 0x07;
/* signal CC2420Receive.receive( type, m_p_rx_buf );*/
signal CC2420Receive.receive( type, m_rxFramePtr );
/* if ( type == IEEE154_TYPE_DATA ) {*/
if ( (type != IEEE154_TYPE_ACK || call CC2420Config.isPromiscuousModeEnabled())
&& !m_stop) {
post receiveDone_task();
return;
}
}
waitForNextPacket();
break;
case S_STARTING_FLUSHRX: continueFlushStart(); break;
default:
atomic receivingPacket = FALSE;
call CSN.set();
call SpiResource.release();
if (m_stop){
continueStop();
return;
}
break;
}
}
}
async event void RXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len, error_t error ) {
}
/***************** Tasks *****************/
/**
* Fill in metadata details, pass the packet up the stack, and
* get the next packet.
*/
task void receiveDone_task() {
uint8_t payloadLen = ((ieee154_header_t*) m_rxFramePtr->header)->length - m_mhrLen - 2;
ieee154_metadata_t *metadata = (ieee154_metadata_t*) m_rxFramePtr->metadata;
atomic {
if (m_state == S_STOPPED){
call Leds.led0On();
return;
}
}
((ieee154_header_t*) m_rxFramePtr->header)->length = m_rxFramePtr->data[payloadLen+1] & 0x7f; // temp. LQI
metadata->rssi = m_rxFramePtr->data[payloadLen];
metadata->linkQuality = ((ieee154_header_t*) m_rxFramePtr->header)->length; // copy back
((ieee154_header_t*) m_rxFramePtr->header)->length = payloadLen;
if (m_timestampValid)
metadata->timestamp = call ReferenceTime.toLocalTime(&m_timestamp);
else
metadata->timestamp = IEEE154_INVALID_TIMESTAMP;
m_rxFramePtr = signal CC2420Rx.received(m_rxFramePtr, &m_timestamp);
/* cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( m_p_rx_buf );*/
/* uint8_t* buf = (uint8_t*) call CC2420PacketBody.getHeader( m_p_rx_buf );;*/
/* */
/* metadata->crc = buf[ rxFrameLength ] >> 7;*/
/* metadata->rssi = buf[ rxFrameLength - 1 ];*/
/* metadata->lqi = buf[ rxFrameLength ] & 0x7f;*/
// async event message_t* receiveDone( message_t *data );
/* m_p_rx_buf = signal Receive.receive( m_rxFramePtrm_p_rx_buf, m_p_rx_buf->data, */
/* rxFrameLength );*/
atomic receivingPacket = FALSE;
waitForNextPacket();
}
/****************** Functions ****************/
/**
* Attempt to acquire the SPI bus to receive a packet.
*/
void beginReceive() {
atomic {
if ( m_state == S_STOPPED){
call Leds.led0On();
return;
}
m_state = S_RX_LENGTH;
receivingPacket = TRUE;
if(call SpiResource.isOwner()) {
receive();
} else if (call SpiResource.immediateRequest() == SUCCESS) {
receive();
} else {
call SpiResource.request();
}
}
}
/**
* Flush out the Rx FIFO
*/
void flush() {
reset_state();
call CSN.set();
call CSN.clr();
call SFLUSHRX.strobe();
call SFLUSHRX.strobe();
call CSN.set();
call SpiResource.release();
waitForNextPacket();
}
/**
* The first byte of each packet is the length byte. Read in that single
* byte, and then read in the rest of the packet. The CC2420 could contain
* multiple packets that have been buffered up, so if something goes wrong,
* we necessarily want to flush out the FIFO unless we have to.
*/
void receive() {
call CSN.set();
call CSN.clr();
//call RXFIFO.beginRead( (uint8_t*)(call CC2420PacketBody.getHeader( m_p_rx_buf )), 1 );
call RXFIFO.beginRead( &((ieee154_header_t*) m_rxFramePtr->header)->length, 1 );
}
/**
* Determine if there's a packet ready to go, or if we should do nothing
* until the next packet arrives
*/
void waitForNextPacket() {
atomic {
receivingPacket = FALSE;
if ( m_state == S_STOPPED) {
call SpiResource.release();
return;
}
if (m_stop){
continueStop();
return;
}
if ( ( m_missed_packets && call FIFO.get() ) || !call FIFOP.get() ) {
// A new packet is buffered up and ready to go
if ( m_missed_packets ) {
m_missed_packets--;
}
beginReceive();
} else {
// Wait for the next packet to arrive
m_state = S_STARTED;
m_missed_packets = 0;
call SpiResource.release();
}
}
}
/**
* Reset this component
*/
void reset_state() {
m_bytes_left = RXFIFO_SIZE;
atomic receivingPacket = FALSE;
m_timestamp_head = 0;
m_timestamp_size = 0;
m_missed_packets = 0;
}
}
--- NEW FILE: CC2420Rx.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
#include "TKN154_platform.h"
interface CC2420Rx {
/**
* Receive a packet buffer, returning a buffer for the signaling
* component to use for the next reception.
*/
event message_t* received(message_t *data, ieee154_reftime_t *timestamp);
}
--- NEW FILE: CC2420TKN154C.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "Timer62500hz.h"
configuration CC2420TKN154C
{
provides
{
interface SplitControl;
interface RadioRx;
interface RadioTx;
interface EnergyDetection;
interface RadioOff;
interface Set<bool> as RadioPromiscuousMode;
interface Timestamp;
} uses {
interface Notify<const void*> as PIBUpdate[uint8_t attributeID];
interface LocalTime<T62500hz>;
interface Alarm<T62500hz,uint32_t> as Alarm1;
interface Alarm<T62500hz,uint32_t> as Alarm2;
interface FrameUtility;
interface CaptureTime;
interface ReferenceTime;
interface ReliableWait;
interface TimeCalc;
interface Leds;
interface Random;
}
} implementation {
components MainC, CC2420TKN154P as PHY;
SplitControl = PHY;
RadioRx = PHY;
RadioTx = PHY;
RadioOff = PHY;
EnergyDetection = PHY;
PIBUpdate = PHY;
RadioPromiscuousMode = PHY;
Timestamp = PHY;
LocalTime = PHY;
ReliableWait = PHY;
ReferenceTime = PHY;
TimeCalc = PHY;
PHY.Random = Random;
Leds = PHY.Leds;
components CC2420ControlTransmitC;
PHY.SpiResource -> CC2420ControlTransmitC;
PHY.CC2420Power -> CC2420ControlTransmitC;
PHY.CC2420Config -> CC2420ControlTransmitC;
CC2420ControlTransmitC.StartupAlarm = Alarm2;
FrameUtility = CC2420ControlTransmitC;
Leds = CC2420ControlTransmitC;
PHY.TxControl -> CC2420ControlTransmitC;
PHY.CC2420Tx -> CC2420ControlTransmitC;
CC2420ControlTransmitC.AckAlarm = Alarm1;
CC2420ControlTransmitC.CaptureTime = CaptureTime;
CC2420ControlTransmitC.ReferenceTime = ReferenceTime;
components CC2420ReceiveC;
PHY.RxControl -> CC2420ReceiveC;
PHY.CC2420Rx -> CC2420ReceiveC.CC2420Rx;
ReferenceTime = CC2420ReceiveC;
Leds = CC2420ReceiveC;
FrameUtility = CC2420ReceiveC;
CC2420ReceiveC.CC2420Config -> CC2420ControlTransmitC;
}
--- NEW FILE: CC2420TKN154P.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
#include "TKN154_PHY.h"
#include <CC2420.h>
#include "Timer62500hz.h"
module CC2420TKN154P
{
provides {
interface SplitControl;
interface RadioRx;
interface RadioTx;
interface RadioOff;
interface EnergyDetection;
interface Set<bool> as RadioPromiscuousMode;
interface Timestamp;
} uses {
interface Notify<const void*> as PIBUpdate[uint8_t attributeID];
interface LocalTime<T62500hz> as LocalTime;
interface Resource as SpiResource;
interface AsyncStdControl as TxControl;
interface CC2420AsyncSplitControl as RxControl;
interface CC2420Power;
interface CC2420Config;
interface CC2420Rx;
interface CC2420Tx;
interface Random;
interface Leds;
interface ReliableWait;
interface ReferenceTime;
interface TimeCalc;
}
} implementation {
typedef enum {
S_STOPPED,
S_STOPPING,
S_STARTING,
S_RADIO_OFF,
S_ED,
S_RESERVE_RX_SPI,
S_RX_PREPARED,
S_RECEIVING,
S_OFF_PENDING,
S_LOAD_TXFIFO,
S_TX_LOADED,
S_TX_ACTIVE,
S_TX_CANCEL,
S_TX_DONE,
} m_state_t;
norace m_state_t m_state = S_STOPPED;
norace ieee154_txframe_t *m_txdata;
norace error_t m_txError;
norace ieee154_reftime_t m_txReferenceTime;
norace bool m_ackFramePending;
uint32_t m_edDuration;
bool m_pibUpdated;
uint8_t m_numCCA;
ieee154_reftime_t *m_t0Tx;
uint32_t m_dtTx;
norace uint8_t m_txLockOnCCAFail;
norace bool m_rxAfterTx = FALSE;
norace bool m_stop = FALSE;
task void startDoneTask();
task void rxControlStopDoneTask();
task void stopTask();
uint8_t dBmToPA_LEVEL(int dbm);
void txDoneRxControlStopped();
void rxSpiReserved();
void txSpiReserved();
void txDoneSpiReserved();
void signalTxDone();
void finishTx();
void stopContinue();
void offSpiReserved();
void offStopRxDone();
void continueTxPrepare();
/******************************/
/* StdControl Operations */
/******************************/
/****************************************/
/* TelosB Pin connection (debug) */
/* */
/* R1 = P6.6 = ADC6, R2 = P6.7 = ADC7 */
/* S1 = P2.3 = GIO2, S2 = P2.6 = GIO3 */
/* R1 is at 6pin-expansion pin 1, */
/* R2 is at 6pin-expansion pin 2, */
/****************************************/
command error_t SplitControl.start()
{
// debug
//P6SEL &= ~0xC0; // debug PIN: 6.6, 6.7, set to I/O function
//P6DIR |= 0xC0; // output
//P6OUT &= ~0xC0; // low
atomic {
if (m_state == S_RADIO_OFF)
return EALREADY;
else {
if (m_state != S_STOPPED)
return FAIL;
m_state = S_STARTING;
}
}
return call SpiResource.request();
}
void startReserved()
{
call CC2420Power.startVReg();
}
async event void CC2420Power.startVRegDone()
{
call CC2420Power.startOscillator();
}
async event void CC2420Power.startOscillatorDone()
{
// default configuration (addresses, etc) has been written
call CC2420Power.rfOff();
call CC2420Tx.unlockChipSpi();
post startDoneTask();
}
task void startDoneTask()
{
call CC2420Config.setChannel(IEEE154_DEFAULT_CURRENTCHANNEL);
call CC2420Config.setShortAddr(IEEE154_DEFAULT_SHORTADDRESS);
call CC2420Config.setPanAddr(IEEE154_DEFAULT_PANID);
call CC2420Config.setPanCoordinator(FALSE);
call CC2420Config.setPromiscuousMode(FALSE);
call CC2420Config.setCCAMode(IEEE154_DEFAULT_CCAMODE);
call CC2420Config.setTxPower(dBmToPA_LEVEL(IEEE154_DEFAULT_TRANSMITPOWER_dBm));
call CC2420Config.sync();
call SpiResource.release();
m_stop = FALSE;
m_state = S_RADIO_OFF;
signal SplitControl.startDone(SUCCESS);
}
command error_t SplitControl.stop()
{
atomic {
if (m_state == S_STOPPED)
return EALREADY;
}
post stopTask();
return SUCCESS;
}
task void stopTask()
{
atomic {
if (m_state == S_RADIO_OFF)
m_state = S_STOPPING;
}
if (m_state != S_STOPPING)
post stopTask(); // this will not happen, because the caller has switched radio off
else
if (call RxControl.stop() == EALREADY)
stopContinue();
}
void stopContinue()
{
call SpiResource.request();
}
void stopReserved()
{
// we own the SPI bus
atomic {
call CC2420Power.rfOff();
call CC2420Tx.unlockChipSpi();
call TxControl.stop();
call CC2420Power.stopOscillator();
call CC2420Power.stopVReg();
call SpiResource.release();
m_state = S_STOPPED;
signal SplitControl.stopDone(SUCCESS);
}
}
/*********************************/
/* PIB Updates */
/*********************************/
// input: power in dBm, output: PA_LEVEL parameter for cc2420 TXCTRL register
uint8_t dBmToPA_LEVEL(int dBm)
{
uint8_t result;
// the cc2420 has 8 discrete (documented) values - we take the closest
if (dBm >= 0)
result = 31;
else if (dBm > -2)
result = 27;
else if (dBm > -4)
result = 23;
else if (dBm > -6)
result = 19;
else if (dBm > -9)
result = 15;
else if (dBm > -13)
result = 11;
else if (dBm > -20)
result = 7;
else
result = 3;
return result;
}
event void PIBUpdate.notify[uint8_t PIBAttribute](const void* PIBAttributeValue)
{
uint8_t txpower;
switch (PIBAttribute)
{
case IEEE154_macShortAddress:
call CC2420Config.setShortAddr(*((ieee154_macShortAddress_t*) PIBAttributeValue));
break;
case IEEE154_macPANId:
call CC2420Config.setPanAddr(*((ieee154_macPANId_t*) PIBAttributeValue));
break;
case IEEE154_phyCurrentChannel:
call CC2420Config.setChannel(*((ieee154_phyCurrentChannel_t*) PIBAttributeValue));
break;
case IEEE154_macPanCoordinator:
call CC2420Config.setPanCoordinator(*((ieee154_macPanCoordinator_t*) PIBAttributeValue));
break;
case IEEE154_phyTransmitPower:
// lower 6 bits are twos-complement in dBm (range -32..+31 dBm)
txpower = (*((ieee154_phyTransmitPower_t*) PIBAttributeValue)) & 0x3F;
if (txpower & 0x20)
txpower |= 0xC0; // make it negative, to be interpreted as int8_t
call CC2420Config.setTxPower(dBmToPA_LEVEL((int8_t) txpower));
break;
case IEEE154_phyCCAMode:
call CC2420Config.setCCAMode(*((ieee154_phyCCAMode_t*) PIBAttributeValue));
break;
}
}
command void RadioPromiscuousMode.set( bool val )
{
call CC2420Config.setPromiscuousMode(val);
}
/*********************************/
/* Energy Detection */
/*********************************/
command error_t EnergyDetection.start(uint32_t duration)
{
error_t status = FAIL;
atomic {
if (m_state == S_RADIO_OFF){
m_state = S_ED;
m_edDuration = duration;
status = SUCCESS;
}
}
if (status == SUCCESS)
call SpiResource.request(); // we will not give up the SPI until we're done
return status;
}
void edReserved()
{
int8_t value, maxEnergy = -128;
uint32_t start = call LocalTime.get();
call CC2420Config.sync(); // put PIB changes into operation (if any)
call CC2420Power.rxOn();
// reading an RSSI value over SPI will usually almost
// take as much time as 8 symbols, i.e. there's
// no point using an Alarm here (but maybe a BusyWait?)
while (!call TimeCalc.hasExpired(start, m_edDuration)){
if (call CC2420Power.rssi(&value) != SUCCESS)
continue;
if (value > maxEnergy)
maxEnergy = value;
}
// P = RSSI_VAL + RSSI_OFFSET [dBm]
// RSSI_OFFSET is approximately -45.
if (maxEnergy > -128)
maxEnergy -= 45;
call CC2420Power.rfOff();
m_state = S_RADIO_OFF;
call SpiResource.release();
signal EnergyDetection.done(SUCCESS, maxEnergy);
}
/****************************************/
/* Transceiver Off */
/****************************************/
async command error_t RadioOff.off()
{
atomic {
if (m_state == S_RADIO_OFF)
return EALREADY;
else if (m_state != S_RECEIVING && m_state != S_TX_LOADED && m_state != S_RX_PREPARED)
return FAIL;
m_state = S_OFF_PENDING;
}
call SpiResource.release(); // may fail
if (call RxControl.stop() == EALREADY) // will trigger offStopRxDone()
offStopRxDone();
return SUCCESS;
}
void offStopRxDone()
{
if (call SpiResource.immediateRequest() == SUCCESS)
offSpiReserved();
else
call SpiResource.request(); // will trigger offSpiReserved()
}
void offSpiReserved()
{
call TxControl.stop();
call CC2420Power.rfOff();
call CC2420Config.sync(); // put any PIB updates into operation
call CC2420Tx.unlockChipSpi();
call SpiResource.release();
m_state = S_RADIO_OFF;
signal RadioOff.offDone();
}
async command bool RadioOff.isOff()
{
return m_state == S_RADIO_OFF;
}
/****************************************/
/* Receive Operations */
/****************************************/
async command error_t RadioRx.prepare()
{
atomic {
if (call RadioRx.isPrepared())
return EALREADY;
else if (m_state != S_RADIO_OFF)
return FAIL;
m_state = S_RESERVE_RX_SPI;
}
if (call RxControl.start() != SUCCESS){ // will trigger rxStartRxDone()
m_state = S_RADIO_OFF;
call Leds.led0On();
return FAIL;
}
return SUCCESS;
}
void rxStartRxDone()
{
if (call SpiResource.immediateRequest() == SUCCESS) // will trigger rxSpiReserved()
rxSpiReserved();
else
call SpiResource.request();
}
void rxSpiReserved()
{
call CC2420Config.sync(); // put PIB changes into operation
call TxControl.start(); // for timestamping
m_state = S_RX_PREPARED;
signal RadioRx.prepareDone(); // keep owning the SPI
}
async command bool RadioRx.isPrepared()
{
return m_state == S_RX_PREPARED;
}
async command error_t RadioRx.receive(ieee154_reftime_t *t0, uint32_t dt)
{
atomic {
if (m_state != S_RX_PREPARED){
call Leds.led0On();
return FAIL;
}
if (t0 != NULL && dt)
call ReliableWait.waitRx(t0, dt);
else
signal ReliableWait.waitRxDone();
}
return SUCCESS;
}
async event void ReliableWait.waitRxDone()
{
atomic {
if (call CC2420Power.rxOn() != SUCCESS)
call Leds.led0On();
m_state = S_RECEIVING;
}
call CC2420Tx.lockChipSpi();
call SpiResource.release();
}
event message_t* CC2420Rx.received(message_t *data, ieee154_reftime_t *timestamp)
{
if (m_state == S_RECEIVING)
return signal RadioRx.received(data, timestamp);
else
return data;
}
async command bool RadioRx.isReceiving()
{
return m_state == S_RECEIVING;
}
/******************************/
/* Transmit Operations */
/******************************/
async command error_t RadioTx.load(ieee154_txframe_t *frame)
{
bool startRxControl;
atomic {
if (m_state != S_RADIO_OFF && m_state != S_TX_LOADED)
return FAIL;
startRxControl = (m_state == S_RADIO_OFF);
m_txdata = frame;
m_state = S_LOAD_TXFIFO;
}
if (!startRxControl)
continueTxPrepare();
else if (call RxControl.start() != SUCCESS) // will trigger continueTxPrepare()
call Leds.led0On();
return SUCCESS;
}
void continueTxPrepare()
{
if (call SpiResource.immediateRequest() == SUCCESS)
txSpiReserved();
else
call SpiResource.request(); // will trigger txSpiReserved()
}
void txSpiReserved()
{
call CC2420Config.sync();
call TxControl.start();
if (call CC2420Tx.loadTXFIFO(m_txdata) != SUCCESS)
call Leds.led0On();
}
async event void CC2420Tx.loadTXFIFODone(ieee154_txframe_t *data, error_t error)
{
if (m_state != S_LOAD_TXFIFO || error != SUCCESS)
call Leds.led0On();
m_state = S_TX_LOADED;
signal RadioTx.loadDone(); // we keep owning the SPI
}
async command ieee154_txframe_t* RadioTx.getLoadedFrame()
{
if (m_state == S_TX_LOADED)
return m_txdata;
else
return NULL;
}
async command error_t RadioTx.transmit(ieee154_reftime_t *t0, uint32_t dt, uint8_t numCCA, bool ackRequest)
{
atomic {
if (m_state != S_TX_LOADED)
return FAIL;
m_numCCA = numCCA;
m_t0Tx = t0;
m_dtTx = dt;
if (numCCA){
// for CCA we need to be in Rx mode
call CC2420Power.rxOn();
call ReliableWait.busyWait(20); // turnaround + CCA valid time
if (numCCA == 2){
// first CCA is done in software (8 symbols after backoff boundary)
if (t0 != NULL){
call ReliableWait.waitCCA(t0, dt-IEEE154_aUnitBackoffPeriod-12);
return SUCCESS;
}
}
}
signal ReliableWait.waitCCADone();
}
return SUCCESS;
}
async event void ReliableWait.waitCCADone()
{
bool cca = call CC2420Tx.cca();
if (m_numCCA == 2 && !cca){
// channel is busy
ieee154_reftime_t now;
call ReferenceTime.getNow(&now, IEEE154_aUnitBackoffPeriod+12);
memcpy(&m_txReferenceTime, &now, sizeof(ieee154_reftime_t));
m_ackFramePending = FALSE;
m_txError = EBUSY;
signalTxDone();
return;
} else {
// the second CCA (or first CCA if there's only one) is done in hardware...
uint16_t offset = 0;
if (m_numCCA)
offset = 12;
if (m_t0Tx)
call ReliableWait.waitTx(m_t0Tx, m_dtTx-offset);
else
signal ReliableWait.waitTxDone();
}
}
async event void ReliableWait.waitTxDone()
{
m_state = S_TX_ACTIVE;
call CC2420Tx.send(m_numCCA>0); // go (with or without CCA) !
}
async event void CC2420Tx.transmissionStarted( ieee154_txframe_t *data )
{
uint8_t frameType = data->header->mhr[0] & FC1_FRAMETYPE_MASK;
uint8_t token = data->headerLen;
signal Timestamp.transmissionStarted(frameType, data->handle, data->payload, token);
}
async event void CC2420Tx.transmittedSFD(uint32_t time, ieee154_txframe_t *data)
{
uint8_t frameType = data->header->mhr[0] & FC1_FRAMETYPE_MASK;
uint8_t token = data->headerLen;
signal Timestamp.transmittedSFD(time, frameType, data->handle, data->payload, token);
// ATTENTION: here we release the SPI, so we can receive a possible ACK
call SpiResource.release();
}
async command void Timestamp.modifyMACPayload(uint8_t token, uint8_t offset, uint8_t* buf, uint8_t len )
{
if (m_state == S_TX_ACTIVE)
call CC2420Tx.modify(offset+1+token, buf, len);
}
async event void CC2420Tx.sendDone(ieee154_txframe_t *frame, ieee154_reftime_t *referenceTime,
bool ackPendingFlag, error_t error)
{
memcpy(&m_txReferenceTime, referenceTime, sizeof(ieee154_reftime_t));
m_ackFramePending = ackPendingFlag;
m_txError = error;
if (error == EBUSY) // CCA failure, i.e. didn't transmit
signalTxDone();
else
// reset radio
if (call RxControl.stop() != SUCCESS) // will trigger txDoneRxControlStopped()
call Leds.led0On();
}
void txDoneRxControlStopped()
{
// get SPI to switch radio off
if (call SpiResource.isOwner() || call SpiResource.immediateRequest() == SUCCESS)
txDoneSpiReserved();
else
call SpiResource.request(); // will trigger txDoneSpiReserved()
}
void txDoneSpiReserved()
{
// switch radio off
call CC2420Power.rfOff();
call TxControl.stop();
call SpiResource.release(); // for RxControl.start to succeed
if (m_txError == SUCCESS)
signalTxDone();
else {
call TxControl.start();
call RxControl.start(); // will trigger txDoneRxControlStarted()
}
}
void txDoneRxControlStarted()
{
m_state = S_TX_DONE;
call SpiResource.request(); // will trigger signalTxDone()
}
void signalTxDone()
{
// radio is off, Rx component is started, radio is loaded, we own the SPI
if (m_txError == SUCCESS)
m_state = S_RADIO_OFF;
else
m_state = S_TX_LOADED;
signal RadioTx.transmitDone(m_txdata, &m_txReferenceTime, m_ackFramePending, m_txError);
}
/*************/
/* RxControl */
/*************/
async event void RxControl.stopDone(error_t error)
{
post rxControlStopDoneTask();
}
task void rxControlStopDoneTask()
{
if (m_stop && m_state != S_STOPPING)
return;
switch (m_state)
{
case S_OFF_PENDING: offStopRxDone(); break;
case S_RX_PREPARED: rxStartRxDone(); break;
case S_TX_ACTIVE: txDoneRxControlStopped(); break;
case S_STOPPING: stopContinue(); break;
default: // huh ?
call Leds.led0On(); break;
}
}
async event void RxControl.startDone(error_t error)
{
switch (m_state)
{
case S_RESERVE_RX_SPI: rxStartRxDone(); break;
case S_LOAD_TXFIFO: continueTxPrepare(); break;
case S_TX_ACTIVE: txDoneRxControlStarted(); break;
default: // huh ?
call Leds.led0On(); break;
}
}
/***********************/
/* SPI Bus Arbitration */
/***********************/
event void SpiResource.granted()
{
switch (m_state)
{
case S_STARTING: startReserved(); break;
case S_ED: edReserved(); break;
case S_RESERVE_RX_SPI: rxSpiReserved(); break;
case S_LOAD_TXFIFO: txSpiReserved(); break;
case S_TX_ACTIVE: txDoneSpiReserved(); break;
case S_STOPPING: stopReserved(); break;
case S_TX_DONE: signalTxDone(); break;
case S_OFF_PENDING: offSpiReserved(); break;
default: // huh ?
call Leds.led0On(); break;
}
}
default event void SplitControl.startDone(error_t error){}
default event void SplitControl.stopDone(error_t error){}
default async event void Timestamp.transmissionStarted(uint8_t frameType, uint8_t msduHandle, uint8_t *msdu, uint8_t token){}
default async event void Timestamp.transmittedSFD(uint32_t time, uint8_t frameType, uint8_t msduHandle, uint8_t *msdu, uint8_t token){}
}
--- NEW FILE: CC2420TransmitP.nc ---
/*
* Copyright (c) 2005-2006 Arch Rock Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the Arch Rock Corporation nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE
*/
/**
* @author Jonathan Hui <jhui at archrock.com>
* @author David Moss
* @author Jung Il Choi Initial SACK implementation
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* @version $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
*/
#include "CC2420.h"
#include "crc.h"
#include "message.h"
module CC2420TransmitP {
provides interface Init;
provides interface AsyncStdControl;
/* interface CC2420Transmit;*/
provides interface CC2420Tx;
/* provides interface RadioBackoff;*/
/* provides interface RadioTimeStamping as TimeStamp;*/
provides interface ReceiveIndicator as EnergyIndicator;
provides interface ReceiveIndicator as ByteIndicator;
/* uses interface Alarm<T32khz,uint32_t> as BackoffAlarm;*/
uses interface Alarm<T62500hz,uint32_t> as BackoffAlarm;
uses interface CC2420Packet;
uses interface CC2420PacketBody;
uses interface GpioCapture as CaptureSFD;
uses interface GeneralIO as CCA;
uses interface GeneralIO as CSN;
uses interface GeneralIO as SFD;
/* uses interface Resource as SpiResource;*/
uses interface ChipSpiResource;
uses interface CC2420Fifo as TXFIFO;
uses interface CC2420Ram as TXFIFO_RAM;
uses interface CC2420Register as TXCTRL;
uses interface CC2420Strobe as SNOP;
uses interface CC2420Strobe as STXON;
uses interface CC2420Strobe as STXONCCA;
uses interface CC2420Strobe as SFLUSHTX;
uses interface CC2420Strobe as SRXON;
uses interface CC2420Strobe as SRFOFF;
uses interface CC2420Strobe as SFLUSHRX;
uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
uses interface CC2420Register as MDMCTRL1;
uses interface CaptureTime;
uses interface ReferenceTime;
uses interface CC2420Receive;
uses interface Leds;
}
implementation {
typedef enum {
S_STOPPED,
S_STARTED,
S_LOAD,
S_SAMPLE_CCA,
S_BEGIN_TRANSMIT,
S_SFD,
S_EFD,
S_ACK_WAIT,
S_CANCEL,
} cc2420_transmit_state_t;
// This specifies how many jiffies the stack should wait after a
// TXACTIVE to receive an SFD interrupt before assuming something is
// wrong and aborting the send. There seems to be a condition
// on the micaZ where the SFD interrupt is never handled.
enum {
CC2420_ABORT_PERIOD = 320
};
/* norace message_t *m_msg;*/
norace ieee154_txframe_t *m_data;
norace uint8_t m_txFrameLen;
ieee154_reftime_t m_timestamp;
cc2420_transmit_state_t m_state = S_STOPPED;
bool m_receiving = FALSE;
uint16_t m_prev_time;
/** Byte reception/transmission indicator */
bool sfdHigh;
/** Let the CC2420 driver keep a lock on the SPI while waiting for an ack */
norace bool abortSpiRelease;
/** Total CCA checks that showed no activity before the NoAck LPL send */
norace int8_t totalCcaChecks;
/** The initial backoff period */
norace uint16_t myInitialBackoff;
/** The congestion backoff period */
norace uint16_t myCongestionBackoff;
/***************** Prototypes ****************/
error_t load( ieee154_txframe_t *data );
error_t resend( bool cca );
void loadTXFIFO();
void attemptSend(bool cca);
void congestionBackoff();
error_t acquireSpiResource();
error_t releaseSpiResource();
/* void signalDone( error_t err );*/
void signalDone( bool ackFramePending, error_t err );
/* void cancelTx();*/
/***************** Init Commands *****************/
command error_t Init.init() {
call CCA.makeInput();
call CSN.makeOutput();
call SFD.makeInput();
return SUCCESS;
}
/***************** AsyncStdControl Commands ****************/
async command error_t AsyncStdControl.start() {
atomic {
if (m_state == S_STARTED)
return EALREADY;
call CaptureSFD.captureRisingEdge();
m_state = S_STARTED;
m_receiving = FALSE;
}
return SUCCESS;
}
async command error_t AsyncStdControl.stop() {
atomic {
m_state = S_STOPPED;
call BackoffAlarm.stop();
call CaptureSFD.disable();
/* call SpiResource.release(); // REMOVE*/
call CSN.set();
}
return SUCCESS;
}
/**************** Send Commands ****************/
/* async command error_t Send.send( message_t* p_msg, bool useCca ) {*/
async command error_t CC2420Tx.loadTXFIFO(ieee154_txframe_t *data) {
return load( data);
}
async command void CC2420Tx.send(bool cca)
{
attemptSend(cca);
}
async command bool CC2420Tx.cca()
{
return call CCA.get();
}
async command error_t CC2420Tx.modify( uint8_t offset, uint8_t* buf,
uint8_t len ) {
call CSN.set();
call CSN.clr();
call TXFIFO_RAM.write( offset, buf, len );
call CSN.set();
return SUCCESS;
}
async command void CC2420Tx.lockChipSpi()
{
abortSpiRelease = TRUE;
}
async command void CC2420Tx.unlockChipSpi()
{
abortSpiRelease = FALSE;
}
/***************** Indicator Commands ****************/
command bool EnergyIndicator.isReceiving() {
return !(call CCA.get());
}
command bool ByteIndicator.isReceiving() {
bool high;
atomic high = sfdHigh;
return high;
}
/***************** RadioBackoff Commands ****************/
/**
* Must be called within a requestInitialBackoff event
* @param backoffTime the amount of time in some unspecified units to backoff
*/
/* async command void RadioBackoff.setInitialBackoff(uint16_t backoffTime) {*/
/* myInitialBackoff = backoffTime + 1;*/
/* }*/
/**
* Must be called within a requestCongestionBackoff event
* @param backoffTime the amount of time in some unspecified units to backoff
*/
/* async command void RadioBackoff.setCongestionBackoff(uint16_t backoffTime) {*/
/* myCongestionBackoff = backoffTime + 1;*/
/* }*/
/* async command void RadioBackoff.setCca(bool useCca) {*/
/* }*/
/**
* The CaptureSFD event is actually an interrupt from the capture pin
* which is connected to timing circuitry and timer modules. This
* type of interrupt allows us to see what time (being some relative value)
* the event occurred, and lets us accurately timestamp our packets. This
* allows higher levels in our system to synchronize with other nodes.
*
* Because the SFD events can occur so quickly, and the interrupts go
* in both directions, we set up the interrupt but check the SFD pin to
* determine if that interrupt condition has already been met - meaning,
* we should fall through and continue executing code where that interrupt
* would have picked up and executed had our microcontroller been fast enough.
*/
async event void CaptureSFD.captured( uint16_t time ) {
// "time" is from TimerB capture, which is sourced by SMCLK (1MHz)
//P2OUT &= ~0x40; // debug: P2.6 low
uint32_t localTime;
atomic {
switch( m_state ) {
case S_SFD:
m_state = S_EFD;
sfdHigh = TRUE;
call CaptureTime.convert(time, &m_timestamp, -8); // -8 for the preamble
call CaptureSFD.captureFallingEdge();
/* signal TimeStamp.transmittedSFD( time, m_msg );*/
localTime = call ReferenceTime.toLocalTime(&m_timestamp);
signal CC2420Tx.transmittedSFD(localTime, m_data );
//if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
//if ( (m_data->header)[0] & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
// This is an ack packet, don't release the chip's SPI bus lock.
//}
releaseSpiResource();
call BackoffAlarm.stop();
m_data->metadata->timestamp = localTime;
/* if ( ( ( (call CC2420PacketBody.getHeader( m_msg ))->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7 ) == IEEE154_TYPE_DATA ) {*/
/* (call CC2420PacketBody.getMetadata( m_msg ))->time = time;*/
/* }*/
if ( call SFD.get() ) {
break;
}
/** Fall Through because the next interrupt was already received */
case S_EFD:
sfdHigh = FALSE;
call CaptureSFD.captureRisingEdge();
/* if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {*/
if ( (m_data->header->mhr)[0] & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
m_state = S_ACK_WAIT;
call BackoffAlarm.start( 200 ); // we need to have *completely* received the ACK
} else {
signalDone(FALSE, SUCCESS);
}
if ( !call SFD.get() ) {
break;
}
/** Fall Through because the next interrupt was already received */
default:
if ( !m_receiving ) {
sfdHigh = TRUE;
call CaptureSFD.captureFallingEdge();
/* signal TimeStamp.receivedSFD( time );*/
call CaptureTime.convert(time, &m_timestamp, -8);
call CC2420Receive.sfd( &m_timestamp );
m_receiving = TRUE;
m_prev_time = time;
if ( call SFD.get() ) {
// wait for the next interrupt before moving on
return;
}
}
sfdHigh = FALSE;
call CaptureSFD.captureRisingEdge();
m_receiving = FALSE;
/* if ( time - m_prev_time < 10 ) {*/
#ifdef PIERCEBOARD_ENABLED
if ( time - m_prev_time < 10*30 ) {
#else
if ( time - m_prev_time < 10 ) {
#endif
call CC2420Receive.sfd_dropped();
}
break;
}
}
}
/***************** ChipSpiResource Events ****************/
async event void ChipSpiResource.releasing() {
if(abortSpiRelease) {
call ChipSpiResource.abortRelease();
}
}
/***************** CC2420Receive Events ****************/
/**
* If the packet we just received was an ack that we were expecting,
* our send is complete.
*/
async event void CC2420Receive.receive( uint8_t type, message_t *ackFrame ){
/* async event void CC2420Receive.receive( uint8_t type, message_t* ack_msg ) {*/
/* cc2420_header_t* ack_header;*/
/* cc2420_header_t* msg_header;*/
/* cc2420_metadata_t* msg_metadata;*/
/* uint8_t* ack_buf;*/
/* uint8_t length;*/
atomic {
if ( type == IEEE154_TYPE_ACK ) {
/* ack_header = call CC2420PacketBody.getHeader( ack_msg );*/
/* msg_header = call CC2420PacketBody.getHeader( m_msg );*/
/* if ( m_state == S_ACK_WAIT && msg_header->dsn == ack_header->dsn ) {*/
if ( m_state == S_ACK_WAIT &&
m_data->header->mhr[2] == ((ieee154_header_t*) ackFrame->header)->mhr[2] ) { // compare seqno
call BackoffAlarm.stop();
/* msg_metadata = call CC2420PacketBody.getMetadata( m_msg );*/
/* ack_buf = (uint8_t *) ack_header;*/
/* length = ack_header->length;*/
/* */
/* msg_metadata->ack = TRUE;*/
/* msg_metadata->rssi = ack_buf[ length - 1 ];*/
/* msg_metadata->lqi = ack_buf[ length ] & 0x7f;*/
signalDone(( ((ieee154_header_t*) ackFrame->header)->mhr[0] & 0x10) ? TRUE: FALSE, SUCCESS);
}
}
}
}
/***************** SpiResource Events ****************/
/*
event void SpiResource.granted() {
uint8_t cur_state;
atomic {
cur_state = m_state;
}
switch( cur_state ) {
case S_LOAD:
loadTXFIFO();
break;
case S_BEGIN_TRANSMIT:
attemptSend();
break;
case S_CANCEL:
cancelTx();
break;
default:
releaseSpiResource();
break;
}
}
*/
/***************** TXFIFO Events ****************/
/**
* The TXFIFO is used to load packets into the transmit buffer on the
* chip
*/
async event void TXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len,
error_t error ) {
call CSN.set();
if (tx_buf == &m_txFrameLen){
// until here: 1.65 ms
call CSN.clr();
call TXFIFO.write( m_data->header->mhr, m_data->headerLen );
return;
} else if (tx_buf == m_data->header->mhr) {
// until here: 2.2 ms
call CSN.clr();
call TXFIFO.write( m_data->payload, m_data->payloadLen );
return;
}
// until here: 4.6 ms (no DMA on USART0)
// until here: 3.3 ms (with DMA on USART0)
// P2OUT &= ~0x40; // P2.1 low
/* if ( m_state == S_CANCEL ) {*/
/* atomic {*/
/* call CSN.clr();*/
/* call SFLUSHTX.strobe();*/
/* call CSN.set();*/
/* }*/
/* releaseSpiResource();*/
/* m_state = S_STARTED;*/
/* } else if ( !m_cca ) {*/
/* } else {*/
m_state = S_BEGIN_TRANSMIT;
releaseSpiResource();
signal CC2420Tx.loadTXFIFODone(m_data, error);
/* attemptSend();*/
/* }*/
/* } else {*/
/* releaseSpiResource();*/
/* atomic {*/
/* if (m_state == S_LOAD_CANCEL) {*/
/* m_state = S_CCA_CANCEL;*/
/* } else {*/
/* m_state = S_SAMPLE_CCA;*/
/* }*/
/* }*/
/* signal CC2420Tx.loadTXFIFODone(m_data, error);*/
/* signal RadioBackoff.requestInitialBackoff(m_msg);*/
/* call BackoffAlarm.start(myInitialBackoff);*/
/* }*/
}
async event void TXFIFO.readDone( uint8_t* tx_buf, uint8_t tx_len,
error_t error ) {
}
/***************** Timer Events ****************/
/**
* The backoff timer is mainly used to wait for a moment before trying
* to send a packet again. But we also use it to timeout the wait for
* an acknowledgement, and timeout the wait for an SFD interrupt when
* we should have gotten one.
*/
async event void BackoffAlarm.fired() {
atomic {
switch( m_state ) {
case S_SAMPLE_CCA :
// sample CCA and wait a little longer if free, just in case we
// sampled during the ack turn-around window
if ( call CCA.get() ) {
m_state = S_BEGIN_TRANSMIT;
call BackoffAlarm.start( CC2420_TIME_ACK_TURNAROUND );
} else {
congestionBackoff();
}
break;
case S_BEGIN_TRANSMIT:
case S_CANCEL:
// should never happen
call Leds.led0On();
/* if ( acquireSpiResource() == SUCCESS ) {*/
/* attemptSend();*/
/* }*/
break;
case S_ACK_WAIT:
/* signalDone( SUCCESS );*/
signalDone( FALSE, FAIL );
break;
case S_SFD:
// We didn't receive an SFD interrupt within CC2420_ABORT_PERIOD
// jiffies. Assume something is wrong.
atomic {
call CSN.set();
call CSN.clr();
call SFLUSHTX.strobe();
call CSN.set();
}
signalDone( FALSE, ERETRY );
releaseSpiResource();
//call CaptureSFD.captureRisingEdge();
break;
default:
break;
}
}
}
/***************** Functions ****************/
/**
* Set up a message to be sent. First load it into the outbound tx buffer
* on the chip, then attempt to send it.
* @param *p_msg Pointer to the message that needs to be sent
* @param cca TRUE if this transmit should use clear channel assessment
*/
error_t load( ieee154_txframe_t *data) {
atomic {
if (m_state == S_CANCEL) {
return ECANCEL;
}
if ( m_state != S_STARTED ) {
return FAIL;
}
m_state = S_LOAD;
/* m_msg = p_msg;*/
m_data = data;
totalCcaChecks = 0;
}
if ( acquireSpiResource() == SUCCESS ) {
loadTXFIFO();
}
return SUCCESS;
}
/**
* Resend a packet that already exists in the outbound tx buffer on the
* chip
* @param cca TRUE if this transmit should use clear channel assessment
*/
/* error_t resend( bool cca ) {*/
/* atomic {*/
/* if (m_state == S_LOAD_CANCEL*/
/* || m_state == S_CCA_CANCEL*/
/* || m_state == S_TX_CANCEL) {*/
/* return ECANCEL;*/
/* }*/
/* */
/* if ( m_state != S_STARTED ) {*/
/* return FAIL;*/
/* }*/
/* */
/* m_cca = cca;*/
/* m_state = cca ? S_SAMPLE_CCA : S_BEGIN_TRANSMIT;*/
/* totalCcaChecks = 0;*/
/* }*/
/* */
/* if(m_cca) {*/
/* signal RadioBackoff.requestInitialBackoff(m_msg);*/
/* call BackoffAlarm.start( myInitialBackoff );*/
/* */
/* } else if ( acquireSpiResource() == SUCCESS ) {*/
/* attemptSend();*/
/* }*/
/* */
/* return SUCCESS;*/
/* }*/
/**
* Attempt to send the packet we have loaded into the tx buffer on
* the radio chip. The STXONCCA will send the packet immediately if
* the channel is clear. If we're not concerned about whether or not
* the channel is clear (i.e. m_cca == FALSE), then STXON will send the
* packet without checking for a clear channel.
*
* If the packet didn't get sent, then congestion == TRUE. In that case,
* we reset the backoff timer and try again in a moment.
*
* If the packet got sent, we should expect an SFD interrupt to take
* over, signifying the packet is getting sent.
*/
void attemptSend(bool cca) {
uint8_t status;
bool congestion = TRUE;
atomic {
call CSN.set();
call CSN.clr();
// STXONCCA costs about ? symbols, i.e. attemptSend should be called
// ? symbols, before the actual CCA
//P2OUT |= 0x40; // P2.6 high
status = cca ? call STXONCCA.strobe() : call STXON.strobe();
//status = call STXON.strobe();
//U0TXBUF = 0x04; // strobe STXON
//while (!(IFG1 & URXIFG0));
//status = U0RXBUF;
//call CSN.set();
if ( !( status & CC2420_STATUS_TX_ACTIVE ) ) {
status = call SNOP.strobe();
if ( status & CC2420_STATUS_TX_ACTIVE ) {
congestion = FALSE;
}
}
call CSN.set();
// debug: on telosb SFD is connected to Pin P4.1
if (!congestion) {while (!(P4IN & 0x02)) ; P6OUT &= ~0x80;}
if (congestion){
call ReferenceTime.getNow(&m_timestamp, 0);
m_state = S_BEGIN_TRANSMIT; // don't use a state S_SAMPLE_CCA
releaseSpiResource();
signal CC2420Tx.sendDone(m_data, &m_timestamp, FALSE, EBUSY); // waiting for the next send()
} else {
m_state = S_SFD; // wait for an ACK
signal CC2420Tx.transmissionStarted(m_data);
call BackoffAlarm.start(CC2420_ABORT_PERIOD*3);
}
return; // we still own the SPI, either we wait for an ACK or resend is going to be called soon
}
/* if ( congestion ) {*/
/* totalCcaChecks = 0;*/
/* releaseSpiResource();*/
/* congestionBackoff();*/
/* } else {*/
/* call BackoffAlarm.start(CC2420_ABORT_PERIOD);*/
/* }*/
}
/**
* Congestion Backoff
*/
void congestionBackoff() {
atomic {
/* signal RadioBackoff.requestCongestionBackoff(m_msg);*/
call BackoffAlarm.start(myCongestionBackoff);
}
}
error_t acquireSpiResource() {
return SUCCESS;
/*
error_t error = call SpiResource.immediateRequest();
if ( error != SUCCESS ) {
call SpiResource.request();
}
return error;
*/
}
error_t releaseSpiResource() {
//call SpiResource.release();
return SUCCESS;
}
/**
* Setup the packet transmission power and load the tx fifo buffer on
* the chip with our outbound packet.
*
* Warning: the tx_power metadata might not be initialized and
* could be a value other than 0 on boot. Verification is needed here
* to make sure the value won't overstep its bounds in the TXCTRL register
* and is transmitting at max power by default.
*
* It should be possible to manually calculate the packet's CRC here and
* tack it onto the end of the header + payload when loading into the TXFIFO,
* so the continuous modulation low power listening strategy will continually
* deliver valid packets. This would increase receive reliability for
* mobile nodes and lossy connections. The crcByte() function should use
* the same CRC polynomial as the CC2420's AUTOCRC functionality.
*/
void loadTXFIFO() {
/* cc2420_header_t* header = call CC2420PacketBody.getHeader( m_msg );*/
/* uint8_t tx_power = (call CC2420PacketBody.getMetadata( m_msg ))->tx_power;*/
m_txFrameLen = m_data->headerLen + m_data->payloadLen + 2;
/* if ( !tx_power ) {*/
/* tx_power = CC2420_DEF_RFPOWER;*/
/* }*/
call CSN.set();
call CSN.clr();
call SFLUSHTX.strobe(); // flush out anything that was in there
call CSN.set();
call CSN.clr();
/* call TXFIFO.write( (uint8_t*)header, header->length - 1);*/
call TXFIFO.write( &m_txFrameLen, 1 );
}
void signalDone( bool ackFramePending, error_t err ) {
atomic m_state = S_STARTED;
signal CC2420Tx.sendDone( m_data, &m_timestamp, ackFramePending, err );
call ChipSpiResource.attemptRelease();
/* signal Send.sendDone( m_msg, err );*/
}
/***************** Tasks ****************/
/***************** Defaults ****************/
/* default async event void TimeStamp.transmittedSFD( uint16_t time, message_t* p_msg ) {*/
/* }*/
/* default async event void TimeStamp.receivedSFD( uint16_t time ) {*/
/* }*/
}
--- NEW FILE: CC2420Tx.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "TKN154_MAC.h"
#include "TKN154_PHY.h"
interface CC2420Tx {
async command error_t loadTXFIFO(ieee154_txframe_t *data);
async event void loadTXFIFODone(ieee154_txframe_t *data, error_t error );
async command void send(bool cca);
async event void sendDone(ieee154_txframe_t *frame, ieee154_reftime_t *referenceTime,
bool ackPendingFlag, error_t error);
async command bool cca();
async command void lockChipSpi();
async command void unlockChipSpi();
async event void transmissionStarted ( ieee154_txframe_t *data );
async event void transmittedSFD ( uint32_t time, ieee154_txframe_t *data );
/**
* Modify the contents of a packet. This command can only be used
* when an SFD capture event for the sending packet is signalled.
*
* @param offset in the message to start modifying.
* @param buf to data to write
* @param len of bytes to write
* @return SUCCESS if the request was accepted, FAIL otherwise.
*/
async command error_t modify( uint8_t offset, uint8_t* buf, uint8_t len );
}
--- NEW FILE: CaptureTime.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. - Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. - Neither the name of the
* Technische Universitaet Berlin nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
interface CaptureTime
{
/**
* Convert a capture time (+ symbol offset) to local time.
*
* @param time capture time
* @param localTime capture time converted to local time + offset symbols
* @param offset time in symbols (16 us) to add to capture time
*/
async command void convert(uint16_t time, ieee154_reftime_t *localTime, int16_t offset);
}
--- NEW FILE: ReferenceTime.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. - Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. - Neither the name of the
* Technische Universitaet Berlin nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
interface ReferenceTime
{
/**
* Gets current reference time plus dt symbols.
*/
async command void getNow(ieee154_reftime_t* reftime, uint16_t dt);
/**
* Converts reference time to local time.
*/
async command uint32_t toLocalTime(ieee154_reftime_t* refTime);
}
--- NEW FILE: ReliableWait.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. - Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. - Neither the name of the
* Technische Universitaet Berlin nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
interface ReliableWait
{
async command void busyWait(uint16_t dt);
/*
* The following command/event pairs are platform-specific
* busy-waits.
*/
async command void waitRx(ieee154_reftime_t *t0, uint16_t dt);
async event void waitRxDone();
async command void waitCCA(ieee154_reftime_t *t0, uint16_t dt);
async event void waitCCADone();
async command void waitTx(ieee154_reftime_t *t0, uint16_t dt);
async event void waitTxDone();
}
--- NEW FILE: TKN154_PHY.h ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the Technische Universitaet Berlin nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $
* $Date: 2008/06/16 18:02:40 $
* @author: Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
// PHY constants for the CC2420
#ifndef __TKN154_PHY_H
#define __TKN154_PHY_H
#include "TKN154_MAC.h"
enum {
IEEE154_SUPPORTED_CHANNELS = 0x07FFF800,
IEEE154_SYMBOLS_PER_OCTET = 2,
IEEE154_TXPOWER_TOLERANCE = 0x80,
IEEE154_SHR_DURATION = (5 * IEEE154_SYMBOLS_PER_OCTET),
IEEE154_MAX_FRAME_DURATION = (IEEE154_SHR_DURATION + ((IEEE154_aMaxPHYPacketSize + 1) * IEEE154_SYMBOLS_PER_OCTET)),
IEEE154_PREAMBLE_LENGTH = (4*IEEE154_SYMBOLS_PER_OCTET),
IEEE154_SYNC_SYMBOL_OFFSET = (1 * IEEE154_SYMBOLS_PER_OCTET),
IEEE154_MIN_LIFS_PERIOD = 40,
IEEE154_MIN_SIFS_PERIOD = 12,
IEEE154_ACK_WAIT_DURATION = (20 + 12 + IEEE154_SHR_DURATION + 6 * IEEE154_SYMBOLS_PER_OCTET),
// TODO: check BATT_LIFE_EXT
IEEE154_BATT_LIFE_EXT_PERIODS = 1,
IEEE154_BATT_LIFE_EXT_PERIOD_TERM3 = 1,
IEEE154_TIMESTAMP_SUPPORTED = TRUE,
};
#include "Timer62500hz.h"
#define TSymbolIEEE802154 T62500hz
#endif
--- NEW FILE: Timestamp.nc ---
/*
* Copyright (c) 2008, Technische Universitaet Berlin All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. - Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. - Neither the name of the
* Technische Universitaet Berlin nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* - Revision -------------------------------------------------------------
* $Revision: 1.1 $ $Date: 2008/06/16 18:02:40 $
* @author Jan Hauer <hauer at tkn.tu-berlin.de>
* ========================================================================
*/
#include "IEEE802154.h"
interface Timestamp
{
/**
* The transmission of a packet has started (the PHY preamble is being
* transmitted).
* Within the event handler the <code>modifyPayload()<\code> command can
* be called to modify the contents of the frame's payload.
*
* @param frameType the type of frame (BEACON=0, DATA=1, ACK=2, COMMAND=3)
* @param msduHandle for DATA frames the handle associated with the MSDU,
* otherwise undefined
* @param payload the MAC payload (e.g. in a DATA frame this is the msdu,
* in a BEACON frame this is the first byte of the SFSpec)
* @param token a token to be used as parameter for the
* <code>modifyPayload()<\code> command
*/
async event void transmissionStarted(uint8_t frameType, uint8_t msduHandle, uint8_t *payload, uint8_t token);
/**
* The Start-of-Frame Delimiter of an outgoing frame has been transmitted.
* Within the event handler the <code>modifyPayload()<\code> command may
* be called to modify the contents of the frame's payload.
*
* @param time the time when the SFD was transmitted, expressed
* in 15.4 symbols as determined by a call to a T62500hz
* Alarm/Timer.getNow()
* @param frameType the type of frame (BEACON=0, DATA=1, ACK=2, COMMAND=3)
* @param msduHandle for DATA frames the handle associated with the MSDU,
* otherwise undefined
* @param payload the MAC payload (e.g. in a DATA frame this is the msdu,
* in a BEACON frame this is the first byte of the SFSpec)
* @param token a token to be used as parameter for the
* <code>modifyPayload()<\code> command
*/
async event void transmittedSFD(uint32_t time, uint8_t frameType, uint8_t msduHandle, uint8_t *payload, uint8_t token);
/**
* Modify (overwrite) the contents of the MAC payload. This command must
* only be called in the context of a <code>transmittedSFD()<\code> event and it
* should return fast. Note: the smaller offset is the faster
* <code>transmittedSFD()<\code> must be finished (offset of zero might not work).
*
* @param token the token signalled by <code>transmittedSFD()<\code>
* @param offset the offset in the frame's payload to start modifying;
* an offset of zero means the first byte of the MAC payload field
* @param buf data to write
* @param len number of bytes to write
*/
async command void modifyMACPayload(uint8_t token, uint8_t offset, uint8_t* buf, uint8_t len);
}
More information about the Tinyos-2-commits
mailing list