📄 cc2420transmitp.nc
字号:
/* * Copyright (c) 2005-2006 Arch Rock Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * - Neither the name of the Arch Rock Corporation nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE *//** * @author Jonathan Hui <jhui@archrock.com> * @author David Moss * @author Jung Il Choi Initial SACK implementation * @version $Revision: 1.4 $ $Date: 2008/06/04 05:36:21 $ */#include "CC2420.h"#include "crc.h"#include "message.h"module CC2420TransmitP { provides interface Init; provides interface StdControl; provides interface CC2420Transmit as Send; provides interface RadioBackoff; provides interface RadioTimeStamping as TimeStamp; provides interface ReceiveIndicator as EnergyIndicator; provides interface ReceiveIndicator as ByteIndicator; uses interface Alarm<T32khz,uint32_t> as BackoffTimer; 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 CC2420Register as MDMCTRL1; 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 * ONE_NOK m_msg; norace bool m_cca; norace uint8_t m_tx_power; 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 */ 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 send( message_t * ONE p_msg, bool cca ); error_t resend( bool cca ); void loadTXFIFO(); void attemptSend(); void congestionBackoff(); error_t acquireSpiResource(); error_t releaseSpiResource(); void signalDone( error_t err ); /***************** Init Commands *****************/ command error_t Init.init() { call CCA.makeInput(); call CSN.makeOutput(); call SFD.makeInput(); return SUCCESS; } /***************** StdControl Commands ****************/ command error_t StdControl.start() { atomic { call CaptureSFD.captureRisingEdge(); m_state = S_STARTED; m_receiving = FALSE; abortSpiRelease = FALSE; m_tx_power = 0; } return SUCCESS; } command error_t StdControl.stop() { atomic { m_state = S_STOPPED; call BackoffTimer.stop(); call CaptureSFD.disable(); call SpiResource.release(); // REMOVE call CSN.set(); } return SUCCESS; } /**************** Send Commands ****************/ async command error_t Send.send( message_t* ONE p_msg, bool useCca ) { return send( p_msg, useCca ); } async command error_t Send.resend(bool useCca) { return resend( useCca ); } async command error_t Send.cancel() { atomic { switch( m_state ) { case S_LOAD: case S_SAMPLE_CCA: case S_BEGIN_TRANSMIT: m_state = S_CANCEL; break; default: // cancel not allowed while radio is busy transmitting return FAIL; } } return SUCCESS; } async command error_t Send.modify( uint8_t offset, uint8_t* buf, uint8_t len ) { call CSN.clr(); call TXFIFO_RAM.write( offset, buf, len ); call CSN.set(); return SUCCESS; } /***************** 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 ) { atomic { switch( m_state ) { case S_SFD: m_state = S_EFD; sfdHigh = TRUE; call CaptureSFD.captureFallingEdge(); signal TimeStamp.transmittedSFD( time, m_msg ); if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) { // This is an ack packet, don't release the chip's SPI bus lock. abortSpiRelease = TRUE; } releaseSpiResource(); call BackoffTimer.stop(); 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 ) ) { m_state = S_ACK_WAIT; call BackoffTimer.start( CC2420_ACK_WAIT_DELAY ); } else { signalDone(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 CC2420Receive.sfd( time ); 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 ) { 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* ack_msg ) { cc2420_header_t* ack_header; cc2420_header_t* msg_header; cc2420_metadata_t* msg_metadata; uint8_t* ack_buf; uint8_t length; if ( type == IEEE154_TYPE_ACK ) { ack_header = call CC2420PacketBody.getHeader( ack_msg ); msg_header = call CC2420PacketBody.getHeader( m_msg );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -