--- /dev/null
+/*
+ * 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$ $Date$
+ * @author Jan Hauer <hauer@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@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);
+}
+
--- /dev/null
+/*
+ * 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@archrock.com>
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de> (added some commands)
+ * @version $Revision$ $Date$
+ */
+
+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);
+
+}
--- /dev/null
+/*
+ * 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@archrock.com>
+ * @author David Moss
+ * @author Urs Hunkeler (ReadRssi implementation)
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de> (support for promiscuous mode)
+ * @version $Revision$ $Date$
+ */
+
+#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 ) );
+ }
+}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+/**
+ * This configuration combines CC2420ControlC and CC2420TransmitC
+ * and uses only one instance of CC2420SpiC.
+ *
+ * @author Jonathan Hui <jhui@archrock.com>
+ * @author Jan-Hinrich Hauer
+ * @version $Revision$ $Date$
+ */
+
+#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;
+}
+
--- /dev/null
+/*
+ * 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@archrock.com>
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+
+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);
+}
--- /dev/null
+/*
+ * 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@archrock.com>
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+
+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 );
+
+}
+
--- /dev/null
+/*
+ * 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@archrock.com>
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+
+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;
+
+}
--- /dev/null
+/*
+ * 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@archrock.com>
+ * @author David Moss
+ * @author Jung Il Choi
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+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;
+ }
+
+}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author: Jan Hauer <hauer@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);
+
+}
+
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author: Jan Hauer <hauer@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;
+}
+
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author: Jan Hauer <hauer@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){}
+}
+
--- /dev/null
+/*
+ * 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@archrock.com>
+ * @author David Moss
+ * @author Jung Il Choi Initial SACK implementation
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * @version $Revision$ $Date$
+ */
+
+#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 ) {*/
+/* }*/
+
+}
+
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author: Jan Hauer <hauer@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 );
+
+}
+
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@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);
+}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@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);
+}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@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();
+}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author: Jan Hauer <hauer@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
+
--- /dev/null
+/*
+ * 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$ $Date$
+ * @author Jan Hauer <hauer@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);
+}