From 951aef87fc91f346a3a2ab34791211f22ba88736 Mon Sep 17 00:00:00 2001 From: janhauer Date: Mon, 16 Jun 2008 18:02:40 +0000 Subject: [PATCH] Initial version of a CC2420 driver for TKN15.4 (see tinyos-2.x/tos/lib/mac/tkn154/README.txt) --- .../cc2420_tkn154/CC2420AsyncSplitControl.nc | 133 ++++ tos/chips/cc2420_tkn154/CC2420Config.nc | 104 +++ tos/chips/cc2420_tkn154/CC2420ControlP.nc | 509 ++++++++++++ .../cc2420_tkn154/CC2420ControlTransmitC.nc | 147 ++++ tos/chips/cc2420_tkn154/CC2420Power.nc | 105 +++ tos/chips/cc2420_tkn154/CC2420Receive.nc | 65 ++ tos/chips/cc2420_tkn154/CC2420ReceiveC.nc | 81 ++ tos/chips/cc2420_tkn154/CC2420ReceiveP.nc | 632 +++++++++++++++ tos/chips/cc2420_tkn154/CC2420Rx.nc | 48 ++ tos/chips/cc2420_tkn154/CC2420TKN154C.nc | 103 +++ tos/chips/cc2420_tkn154/CC2420TKN154P.nc | 709 +++++++++++++++++ tos/chips/cc2420_tkn154/CC2420TransmitP.nc | 744 ++++++++++++++++++ tos/chips/cc2420_tkn154/CC2420Tx.nc | 66 ++ tos/chips/cc2420_tkn154/CaptureTime.nc | 43 + tos/chips/cc2420_tkn154/ReferenceTime.nc | 44 ++ tos/chips/cc2420_tkn154/ReliableWait.nc | 49 ++ tos/chips/cc2420_tkn154/TKN154_PHY.h | 65 ++ tos/chips/cc2420_tkn154/Timestamp.nc | 82 ++ 18 files changed, 3729 insertions(+) create mode 100644 tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420Config.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420ControlP.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420Power.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420Receive.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420ReceiveC.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420ReceiveP.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420Rx.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420TKN154C.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420TKN154P.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420TransmitP.nc create mode 100644 tos/chips/cc2420_tkn154/CC2420Tx.nc create mode 100644 tos/chips/cc2420_tkn154/CaptureTime.nc create mode 100644 tos/chips/cc2420_tkn154/ReferenceTime.nc create mode 100644 tos/chips/cc2420_tkn154/ReliableWait.nc create mode 100644 tos/chips/cc2420_tkn154/TKN154_PHY.h create mode 100644 tos/chips/cc2420_tkn154/Timestamp.nc diff --git a/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc b/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc new file mode 100644 index 00000000..7688a55e --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc @@ -0,0 +1,133 @@ +/* + * 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 + * ======================================================================== + */ +/* + * "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 + */ + +interface CC2420AsyncSplitControl +{ + /** + * Start this component and all of its subcomponents. Return + * values of SUCCESS will always result in a startDone() + * 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 + * startDone event in the near future.
+ * EBUSY if the component is in the middle of powering down + * i.e. a stop() command has been called, + * and a stopDone() event is pending
+ * EALREADY if the device is already on
+ * FAIL Otherwise + */ + async command error_t start(); + + /** + * Notify caller that the component has been started and is ready to + * receive other commands. + * + * @param error -- 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 startDone() + * 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 + * stopDone event in the near future.
+ * EBUSY if the component is in the middle of powering up + * i.e. a start() command has been called, + * and a startDone() event is pending
+ * EALREADY if the device is already off
+ * FAIL Otherwise + */ + async command error_t stop(); + + /** + * Notify caller that the component has been stopped. + * + * @param error -- SUCCESS if the component was successfully + * turned off, FAIL otherwise + */ + async event void stopDone(error_t error); +} + diff --git a/tos/chips/cc2420_tkn154/CC2420Config.nc b/tos/chips/cc2420_tkn154/CC2420Config.nc new file mode 100644 index 00000000..c1e07de1 --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420Config.nc @@ -0,0 +1,104 @@ +/* + * 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 + * @author Jan Hauer (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); + +} diff --git a/tos/chips/cc2420_tkn154/CC2420ControlP.nc b/tos/chips/cc2420_tkn154/CC2420ControlP.nc new file mode 100644 index 00000000..64e4adf8 --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420ControlP.nc @@ -0,0 +1,509 @@ +/* + * 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 + * @author David Moss + * @author Urs Hunkeler (ReadRssi implementation) + * @author Jan Hauer (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 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 ) ); + } +} diff --git a/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc b/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc new file mode 100644 index 00000000..97637d87 --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc @@ -0,0 +1,147 @@ +/* + * 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 + * ======================================================================== + */ + +/** + * This configuration combines CC2420ControlC and CC2420TransmitC + * and uses only one instance of CC2420SpiC. + * + * @author Jonathan Hui + * @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 as StartupAlarm; + interface FrameUtility; + + // CC2420TransmitC + interface Alarm 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; +} + diff --git a/tos/chips/cc2420_tkn154/CC2420Power.nc b/tos/chips/cc2420_tkn154/CC2420Power.nc new file mode 100644 index 00000000..a213f31d --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420Power.nc @@ -0,0 +1,105 @@ +/* + * 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 + * @author Jan Hauer + * @version $Revision$ $Date$ + */ + +interface CC2420Power { + + /** + * Start the voltage regulator on the CC2420. On SUCCESS, + * startVReg() 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, startOscillator + * 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); +} diff --git a/tos/chips/cc2420_tkn154/CC2420Receive.nc b/tos/chips/cc2420_tkn154/CC2420Receive.nc new file mode 100644 index 00000000..1ba224ed --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420Receive.nc @@ -0,0 +1,65 @@ +/* + * 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 + * @author Jan Hauer + * @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 ); + +} + diff --git a/tos/chips/cc2420_tkn154/CC2420ReceiveC.nc b/tos/chips/cc2420_tkn154/CC2420ReceiveC.nc new file mode 100644 index 00000000..f8381822 --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420ReceiveC.nc @@ -0,0 +1,81 @@ +/* + * 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 + * @author Jan Hauer + * @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; + +} diff --git a/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc b/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc new file mode 100644 index 00000000..04860924 --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc @@ -0,0 +1,632 @@ +/* + * 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 + * @author David Moss + * @author Jung Il Choi + * @author Jan Hauer + * @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; + } + +} diff --git a/tos/chips/cc2420_tkn154/CC2420Rx.nc b/tos/chips/cc2420_tkn154/CC2420Rx.nc new file mode 100644 index 00000000..1f1abf2e --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420Rx.nc @@ -0,0 +1,48 @@ +/* + * 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 + * ======================================================================== + */ + +#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); + +} + diff --git a/tos/chips/cc2420_tkn154/CC2420TKN154C.nc b/tos/chips/cc2420_tkn154/CC2420TKN154C.nc new file mode 100644 index 00000000..18da878a --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420TKN154C.nc @@ -0,0 +1,103 @@ +/* + * 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 + * ======================================================================== + */ + +#include "Timer62500hz.h" +configuration CC2420TKN154C +{ + provides + { + interface SplitControl; + interface RadioRx; + interface RadioTx; + interface EnergyDetection; + interface RadioOff; + interface Set as RadioPromiscuousMode; + interface Timestamp; + } uses { + interface Notify as PIBUpdate[uint8_t attributeID]; + interface LocalTime; + interface Alarm as Alarm1; + interface Alarm 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; +} + diff --git a/tos/chips/cc2420_tkn154/CC2420TKN154P.nc b/tos/chips/cc2420_tkn154/CC2420TKN154P.nc new file mode 100644 index 00000000..2546253e --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420TKN154P.nc @@ -0,0 +1,709 @@ +/* + * 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 + * ======================================================================== + */ + +#include "TKN154_MAC.h" +#include "TKN154_PHY.h" +#include +#include "Timer62500hz.h" + +module CC2420TKN154P +{ + + provides { + interface SplitControl; + interface RadioRx; + interface RadioTx; + interface RadioOff; + interface EnergyDetection; + interface Set as RadioPromiscuousMode; + interface Timestamp; + } uses { + interface Notify as PIBUpdate[uint8_t attributeID]; + interface LocalTime 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){} +} + diff --git a/tos/chips/cc2420_tkn154/CC2420TransmitP.nc b/tos/chips/cc2420_tkn154/CC2420TransmitP.nc new file mode 100644 index 00000000..b839a99c --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420TransmitP.nc @@ -0,0 +1,744 @@ +/* + * 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 + * @author David Moss + * @author Jung Il Choi Initial SACK implementation + * @author Jan Hauer + * @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 as BackoffAlarm;*/ + uses interface Alarm 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 ) {*/ +/* }*/ + +} + diff --git a/tos/chips/cc2420_tkn154/CC2420Tx.nc b/tos/chips/cc2420_tkn154/CC2420Tx.nc new file mode 100644 index 00000000..53e1fc9f --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420Tx.nc @@ -0,0 +1,66 @@ +/* + * 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 + * ======================================================================== + */ + +#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 ); + +} + diff --git a/tos/chips/cc2420_tkn154/CaptureTime.nc b/tos/chips/cc2420_tkn154/CaptureTime.nc new file mode 100644 index 00000000..45e7300e --- /dev/null +++ b/tos/chips/cc2420_tkn154/CaptureTime.nc @@ -0,0 +1,43 @@ +/* + * 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 + * ======================================================================== + */ +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); +} diff --git a/tos/chips/cc2420_tkn154/ReferenceTime.nc b/tos/chips/cc2420_tkn154/ReferenceTime.nc new file mode 100644 index 00000000..e91e0e6b --- /dev/null +++ b/tos/chips/cc2420_tkn154/ReferenceTime.nc @@ -0,0 +1,44 @@ +/* + * 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 + * ======================================================================== + */ +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); +} diff --git a/tos/chips/cc2420_tkn154/ReliableWait.nc b/tos/chips/cc2420_tkn154/ReliableWait.nc new file mode 100644 index 00000000..02140b11 --- /dev/null +++ b/tos/chips/cc2420_tkn154/ReliableWait.nc @@ -0,0 +1,49 @@ +/* + * 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 + * ======================================================================== + */ +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(); +} diff --git a/tos/chips/cc2420_tkn154/TKN154_PHY.h b/tos/chips/cc2420_tkn154/TKN154_PHY.h new file mode 100644 index 00000000..12b69f05 --- /dev/null +++ b/tos/chips/cc2420_tkn154/TKN154_PHY.h @@ -0,0 +1,65 @@ +/* + * 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 + * ======================================================================== + */ + +// 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 + diff --git a/tos/chips/cc2420_tkn154/Timestamp.nc b/tos/chips/cc2420_tkn154/Timestamp.nc new file mode 100644 index 00000000..0f041631 --- /dev/null +++ b/tos/chips/cc2420_tkn154/Timestamp.nc @@ -0,0 +1,82 @@ +/* + * 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 + * ======================================================================== + */ +#include "IEEE802154.h" +interface Timestamp +{ + /** + * The transmission of a packet has started (the PHY preamble is being + * transmitted). + * Within the event handler the 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 + * 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 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 + * 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 transmittedSFD()<\code> event and it + * should return fast. Note: the smaller offset is the faster + * transmittedSFD()<\code> must be finished (offset of zero might not work). + * + * @param token the token signalled by 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); +} -- 2.39.2