📄 cc2420transmitp.nc
字号:
if ( m_state == S_ACK_WAIT && msg_header->dsn == ack_header->dsn ) { call BackoffTimer.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(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: call CSN.clr(); call SFLUSHTX.strobe(); call CSN.set(); releaseSpiResource(); atomic { m_state = S_STARTED; } signal Send.sendDone( m_msg, ECANCEL ); 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 ( m_state == S_CANCEL ) { atomic { call CSN.clr(); call SFLUSHTX.strobe(); call CSN.set(); } releaseSpiResource(); m_state = S_STARTED; signal Send.sendDone( m_msg, ECANCEL ); } else if ( !m_cca ) { atomic { m_state = S_BEGIN_TRANSMIT; } attemptSend(); } else { releaseSpiResource(); atomic { m_state = S_SAMPLE_CCA; } signal RadioBackoff.requestInitialBackoff(m_msg); call BackoffTimer.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 BackoffTimer.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 BackoffTimer.start( CC2420_TIME_ACK_TURNAROUND ); } else { congestionBackoff(); } break; case S_BEGIN_TRANSMIT: case S_CANCEL: if ( acquireSpiResource() == SUCCESS ) { attemptSend(); } break; case S_ACK_WAIT: signalDone( SUCCESS ); break; case S_SFD: // We didn't receive an SFD interrupt within CC2420_ABORT_PERIOD // jiffies. Assume something is wrong. call SFLUSHTX.strobe(); call CaptureSFD.captureRisingEdge(); releaseSpiResource(); signalDone( ERETRY ); 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 send( message_t* ONE p_msg, bool cca ) { atomic { if (m_state == S_CANCEL) { return ECANCEL; } if ( m_state != S_STARTED ) { return FAIL; } m_state = S_LOAD; m_cca = cca; m_msg = p_msg; 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_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 BackoffTimer.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() { uint8_t status; bool congestion = TRUE; atomic { if (m_state == S_CANCEL) { call SFLUSHTX.strobe(); releaseSpiResource(); call CSN.set(); m_state = S_STARTED; signal Send.sendDone( m_msg, ECANCEL ); return; } call CSN.clr(); status = m_cca ? call STXONCCA.strobe() : call STXON.strobe(); if ( !( status & CC2420_STATUS_TX_ACTIVE ) ) { status = call SNOP.strobe(); if ( status & CC2420_STATUS_TX_ACTIVE ) { congestion = FALSE; } } m_state = congestion ? S_SAMPLE_CCA : S_SFD; call CSN.set(); } if ( congestion ) { totalCcaChecks = 0; releaseSpiResource(); congestionBackoff(); } else { call BackoffTimer.start(CC2420_ABORT_PERIOD); } } /** * Congestion Backoff */ void congestionBackoff() { atomic { signal RadioBackoff.requestCongestionBackoff(m_msg); call BackoffTimer.start(myCongestionBackoff); } } error_t acquireSpiResource() { 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; if ( !tx_power ) { tx_power = CC2420_DEF_RFPOWER; } call CSN.clr(); if ( m_tx_power != tx_power ) { call TXCTRL.write( ( 2 << CC2420_TXCTRL_TXMIXBUF_CUR ) | ( 3 << CC2420_TXCTRL_PA_CURRENT ) | ( 1 << CC2420_TXCTRL_RESERVED ) | ( (tx_power & 0x1F) << CC2420_TXCTRL_PA_LEVEL ) ); } m_tx_power = tx_power; { uint8_t tmpLen __DEPUTY_UNUSED__ = header->length - 1; call TXFIFO.write(TCAST(uint8_t * COUNT(tmpLen), header), header->length - 1); } } void signalDone( error_t err ) { atomic m_state = S_STARTED; abortSpiRelease = FALSE; 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 ) { }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -