/*---------------------------------------------------------------------------*/ static int cc2420_prepare(const void *payload, unsigned short payload_len) { uint8_t total_len; #if CC2420_CONF_CHECKSUM uint16_t checksum; #endif /* CC2420_CONF_CHECKSUM */ GET_LOCK(); PRINTF("cc2420: sending %d bytes\n", payload_len); RIMESTATS_ADD(lltx); /* Wait for any previous transmission to finish. */ /* while(status() & BV(CC2420_TX_ACTIVE));*/ /* Write packet to TX FIFO. */ strobe(CC2420_SFLUSHTX); #if CC2420_CONF_CHECKSUM checksum = crc16_data(payload, payload_len, 0); #endif /* CC2420_CONF_CHECKSUM */ total_len = payload_len + AUX_LEN; FASTSPI_WRITE_FIFO(&total_len, 1); FASTSPI_WRITE_FIFO(payload, payload_len); #if CC2420_CONF_CHECKSUM FASTSPI_WRITE_FIFO(&checksum, CHECKSUM_LEN); #endif /* CC2420_CONF_CHECKSUM */ RELEASE_LOCK(); return 0; }
int cc2420_send(struct hdr_802_15 *hdr, u8_t hdr_len, const u8_t *payload, u8_t payload_len) { u8_t spiStatusByte; int s; /* struct hdr_802_15::len shall *not* be counted, thus the -1. * 2 == sizeof(footer). */ if (((hdr_len - 1) + payload_len + 2) > MAX_PACKET_LEN) return -1; /* This code uses the CC2420 CCA (Clear Channel Assessment) to * implement Carrier Sense Multiple Access with Collision Avoidance * (CSMA-CA) and requires the receiver to be enabled and ready. */ if (!receive_on) return -2; /* Wait for previous transmission to finish and RSSI. */ do { spiStatusByte = cc2420_status(); if (!(spiStatusByte & BV(CC2420_RSSI_VALID))) /* RSSI needed by CCA */ continue; } while (spiStatusByte & BV(CC2420_TX_ACTIVE)); hdr->dst_pan = pan_id; /* Not at fixed position! xxx/bg */ last_dst = hdr->dst; /* Not dst either. */ last_used_seq++; hdr->seq = last_used_seq; cc2420_ack_received = 0; /* Write packet to TX FIFO, appending FCS if AUTOCRC is enabled. */ cc2420_strobe(CC2420_SFLUSHTX); /* Cancel send that never started. */ s = splhigh(); FASTSPI_WRITE_FIFO(hdr, hdr_len); FASTSPI_WRITE_FIFO(payload, payload_len); splx(s); /* Send stuff from FIFO now! */ process_post_synch(&cc2420_retransmit_process, PROCESS_EVENT_MSG, NULL); return UIP_FW_OK; }
/*---------------------------------------------------------------------------*/ void cc2420_ugly_hack_send_only_one_symbol(void) { uint8_t len; GET_LOCK(); /* Write packet to TX FIFO. */ strobe(CC2420_SFLUSHTX); len = 1; FASTSPI_WRITE_FIFO(&len, 1); FASTSPI_WRITE_FIFO(&len, 1); strobe(CC2420_STXON); while(!SFD_IS_1); /* Turn radio off immediately after sending the first symbol. */ strobe(CC2420_SRFOFF); RELEASE_LOCK(); return; }
//------------------------------------------------------------------------------------------------------- // BYTE rf_tx_packet(RF_TX_INFO *pRTI) // // DESCRIPTION: // Transmits a packet using the IEEE 802.15.4 MAC data packet format with short addresses. CCA is // measured only once before backet transmission (not compliant with 802.15.4 CSMA-CA). // The function returns: // - When pRTI->ackRequest is FALSE: After the transmission has begun (SFD gone high) // - When pRTI->ackRequest is TRUE: After the acknowledgment has been received/declared missing. // The acknowledgment is received through the FIFOP interrupt. // // ARGUMENTS: // RF_TX_INFO *pRTI // The transmission structure, which contains all relevant info about the packet. // // RETURN VALUE: // uint8_t // Successful transmission (acknowledgment received) //------------------------------------------------------------------------------------------------------- uint8_t rf_tx_packet(RF_TX_INFO *pRTI) { uint16_t frameControlField; uint8_t packetLength, length; uint8_t success; uint8_t spiStatusByte; uint8_t checksum,i; #ifdef RADIO_PRIORITY_CEILING nrk_sem_pend(radio_sem); #endif #ifdef CC2420_OSC_OPT FASTSPI_STROBE(CC2420_SXOSCON); nrk_spin_wait_us(OSC_STARTUP_DELAY); #endif if(security_enable) FASTSPI_STROBE(CC2420_STXENC); checksum=0; for(i=0; i<pRTI->length; i++ ) { // lets do our own payload checksum because we don't trust the CRC checksum+=pRTI->pPayload[i]; } // Write the packet to the TX FIFO (the FCS is appended automatically when AUTOCRC is enabled) // These are only the MAC AGNOSTIC parameters... // Slots for example are at a slighly higher later since they assume TDMA packetLength = pRTI->length + RF_PACKET_OVERHEAD_SIZE + CHECKSUM_OVERHEAD; if(security_enable) packetLength+=4; // for CTR counter // XXX 2 below are hacks... FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); // Wait until the transceiver is idle while (FIFOP_IS_1 || SFD_IS_1); // Turn off global interrupts to avoid interference on the SPI interface DISABLE_GLOBAL_INT(); // Flush the TX FIFO just in case... FASTSPI_STROBE(CC2420_SFLUSHTX); FASTSPI_STROBE(CC2420_SFLUSHTX); /* // Turn on RX if necessary if (!rfSettings.receiveOn) { FASTSPI_STROBE(CC2420_SRXON); } // Wait for the RSSI value to become valid do { FASTSPI_UPD_STATUS(spiStatusByte); } while (!(spiStatusByte & BM(CC2420_RSSI_VALID))); // TX begins after the CCA check has passed do { FASTSPI_STROBE(CC2420_STXONCCA); FASTSPI_UPD_STATUS(spiStatusByte); halWait(100); } while (!(spiStatusByte & BM(CC2420_TX_ACTIVE))); */ FASTSPI_WRITE_FIFO((uint8_t*)&packetLength, 1); // Packet length frameControlField = RF_FCF_NOACK; // default if(auto_ack_enable) frameControlField |= RF_ACK_BM; if(security_enable) frameControlField |= RF_SEC_BM; FASTSPI_WRITE_FIFO((uint8_t*) &frameControlField, 2); // Frame control field FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.txSeqNumber, 1); // Sequence number FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.panId, 2); // Dest. PAN ID FASTSPI_WRITE_FIFO((uint8_t*) &pRTI->destAddr, 2); // Dest. address FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.myAddr, 2); // Source address if(security_enable) FASTSPI_WRITE_FIFO((uint8_t*) &tx_ctr, 4); // CTR counter FASTSPI_WRITE_FIFO((uint8_t*) pRTI->pPayload, pRTI->length); // Payload FASTSPI_WRITE_FIFO((uint8_t*) &checksum, 1); // Checksum if (pRTI->cca == TRUE) { uint8_t cnt; if (!rfSettings.receiveOn) { FASTSPI_STROBE (CC2420_SRXON); } // Wait for the RSSI value to become valid do { FASTSPI_UPD_STATUS (spiStatusByte); } while (!(spiStatusByte & BM (CC2420_RSSI_VALID))); // TX begins after the CCA check has passed cnt = 0; do { FASTSPI_STROBE (CC2420_STXONCCA); FASTSPI_UPD_STATUS (spiStatusByte); cnt++; if (cnt > 100) { ENABLE_GLOBAL_INT (); nrk_sem_post(radio_sem); return FALSE; } halWait (100); } while (!(spiStatusByte & BM (CC2420_TX_ACTIVE))); } else FASTSPI_STROBE (CC2420_STXON); ENABLE_GLOBAL_INT(); // Wait for the transmission to begin before exiting (makes sure that this function cannot be called // a second time, and thereby cancelling the first transmission (observe the FIFOP + SFD test above). while (!SFD_IS_1); success = TRUE; // Turn interrupts back on // ENABLE_GLOBAL_INT(); while (SFD_IS_1); // wait for packet to finish // Wait for the acknowledge to be received, if any if (auto_ack_enable) { // rfSettings.ackReceived = FALSE; // Wait for the SFD to go low again // while (SFD_IS_1); // We'll enter RX automatically, so just wait until we can be sure that the // ack reception should have finished // The timeout consists of a 12-symbol turnaround time, the ack packet duration, // and a small margin halWait((12 * RF_SYMBOL_DURATION) + (RF_ACK_DURATION) + (2 * RF_SYMBOL_DURATION) + 100); if(FIFO_IS_1) { FASTSPI_READ_FIFO_BYTE(length); length &= RF_LENGTH_MASK; // Ignore MSB success = TRUE; } else { FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); success = FALSE; } } // Turn off the receiver if it should not continue to be enabled DISABLE_GLOBAL_INT(); //FASTSPI_STROBE(CC2420_SFLUSHRX); //FASTSPI_STROBE(CC2420_SFLUSHRX); //FASTSPI_STROBE(CC2420_SFLUSHTX); //FASTSPI_STROBE(CC2420_SFLUSHTX); #ifdef CC2420_OSC_OPT FASTSPI_STROBE(CC2420_SXOSCOFF); #endif FASTSPI_STROBE(CC2420_SRFOFF); // shut off radio ENABLE_GLOBAL_INT(); // agr XXX hack to test time issue //rf_rx_on(); // Increment the sequence number, and return the result rfSettings.txSeqNumber++; // while (SFD_IS_1); #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return success; }
/************************************************************************** This function is the same as normal TX, only it waits until the last second to send the duty out with the high speed timer. And by duty, I mean the packet BIATCH... **************************************************************************/ uint8_t rf_tx_tdma_packet(RF_TX_INFO *pRTI, uint16_t slot_start_time, uint16_t tx_guard_time) { uint16_t frameControlField; uint8_t packetLength; uint8_t success; uint8_t spiStatusByte; uint8_t checksum,i; uint8_t timestamp; #ifdef RADIO_PRIORITY_CEILING nrk_sem_pend (radio_sem); #endif timestamp=_nrk_os_timer_get(); // XXX 2 below are hacks... #ifdef CC2420_OSC_OPT FASTSPI_STROBE(CC2420_SXOSCON); nrk_spin_wait_us(OSC_STARTUP_DELAY); #endif FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); // Wait until the transceiver is idle while (FIFOP_IS_1 || SFD_IS_1); // Turn off global interrupts to avoid interference on the SPI interface DISABLE_GLOBAL_INT(); // Flush the TX FIFO just in case... FASTSPI_STROBE(CC2420_SFLUSHTX); FASTSPI_STROBE(CC2420_SFLUSHTX); checksum=0; for(i=0; i<pRTI->length; i++ ) { // lets do our own payload checksum because we don't trust the CRC checksum+=pRTI->pPayload[i]; } packetLength = pRTI->length + RF_PACKET_OVERHEAD_SIZE + CHECKSUM_OVERHEAD; //nrk_set_led(3); //do { } while(_nrk_get_high_speed_timer()<(tx_guard_time)); // Write the packet to the TX FIFO (the FCS is appended automatically when AUTOCRC is enabled) // These are only the MAC AGNOSTIC parameters... // Slots for example are at a higher layer since they assume TDMA FASTSPI_WRITE_FIFO((uint8_t*)&packetLength, 1); // Packet length frameControlField = pRTI->ackRequest ? RF_FCF_ACK : RF_FCF_NOACK; FASTSPI_WRITE_FIFO((uint8_t*) &frameControlField, 2); // Frame control field FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.txSeqNumber, 1); // Sequence number FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.panId, 2); // Dest. PAN ID FASTSPI_WRITE_FIFO((uint8_t*) &pRTI->destAddr, 2); // Dest. address FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.myAddr, 2); // Source address nrk_high_speed_timer_wait(slot_start_time,tx_guard_time); //nrk_clr_led(3); /* DISABLE_GLOBAL_INT(); nrk_set_led(3); last=0; do { if(last==_nrk_get_high_speed_timer()) { //while(1) //printf( "TX ERROR %d vs %d\r\n",_nrk_get_high_speed_timer(),tx_guard_time ); break; } last=_nrk_get_high_speed_timer(); } while((volatile)last<(tx_guard_time)); ENABLE_GLOBAL_INT(); nrk_clr_led(3); */ /* // Turn on RX if necessary if (!rfSettings.receiveOn) { FASTSPI_STROBE(CC2420_SRXON); } // Wait for the RSSI value to become valid do { FASTSPI_UPD_STATUS(spiStatusByte); } while (!(spiStatusByte & BM(CC2420_RSSI_VALID))); // TX begins after the CCA check has passed do { FASTSPI_STROBE(CC2420_STXONCCA); FASTSPI_UPD_STATUS(spiStatusByte); halWait(100); } while (!(spiStatusByte & BM(CC2420_TX_ACTIVE))); */ if (pRTI->cca == TRUE) { uint8_t cnt; if (!rfSettings.receiveOn) { FASTSPI_STROBE (CC2420_SRXON); } // Wait for the RSSI value to become valid do { FASTSPI_UPD_STATUS (spiStatusByte); } while (!(spiStatusByte & BM (CC2420_RSSI_VALID))); // TX begins after the CCA check has passed cnt = 0; do { FASTSPI_STROBE (CC2420_STXONCCA); FASTSPI_UPD_STATUS (spiStatusByte); cnt++; if (cnt > 100) { ENABLE_GLOBAL_INT (); nrk_sem_post(radio_sem); return FALSE; } halWait (100); } while (!(spiStatusByte & BM (CC2420_TX_ACTIVE))); } else FASTSPI_STROBE (CC2420_STXON); //nrk_gpio_set(DEBUG_0); // Fill in the rest of the packet now FASTSPI_WRITE_FIFO((uint8_t*) pRTI->pPayload, pRTI->length); // Payload FASTSPI_WRITE_FIFO((uint8_t*) &checksum, 1); // Checksum //nrk_spin_wait_us(200); // FASTSPI_STROBE(CC2420_STXON); // Wait for the transmission to begin before exiting (makes sure that this function cannot be called // a second time, and thereby cancelling the first transmission (observe the FIFOP + SFD test above). while (!SFD_IS_1); success = TRUE; // Turn interrupts back on // ENABLE_GLOBAL_INT(); // Wait for the acknowledge to be received, if any /*if (pRTI->ackRequest) { rfSettings.ackReceived = FALSE; // Wait for the SFD to go low again while (SFD_IS_1); // We'll enter RX automatically, so just wait until we can be sure that the ack reception should have finished // The timeout consists of a 12-symbol turnaround time, the ack packet duration, and a small margin halWait((12 * RF_SYMBOL_DURATION) + (RF_ACK_DURATION) + (2 * RF_SYMBOL_DURATION) + 100); // If an acknowledgment has been received (by the FIFOP interrupt), the ackReceived flag should be set success = rfSettings.ackReceived; }*/ // Turn off the receiver if it should not continue to be enabled DISABLE_GLOBAL_INT(); // XXX hack, temp out //if (!rfSettings.receiveOn) { while (SFD_IS_1); /*FASTSPI_STROBE(CC2420_SRFOFF);*/ } // while (SFD_IS_1); while (SFD_IS_1); // wait for packet to finish FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHTX); FASTSPI_STROBE(CC2420_SFLUSHTX); #ifdef CC2420_OSC_OPT FASTSPI_STROBE(CC2420_SXOSCOFF); #endif FASTSPI_STROBE(CC2420_SRFOFF); // shut off radio ENABLE_GLOBAL_INT(); // Increment the sequence number, and return the result rfSettings.txSeqNumber++; // while (SFD_IS_1); #ifdef RADIO_PRIORITY_CEILING nrk_sem_post(radio_sem); #endif return success; }
/*---------------------------------------------------------------------------*/ int cc2420_send(const void *payload, unsigned short payload_len) { int i; uint8_t total_len; struct timestamp timestamp; uint16_t checksum; GET_LOCK(); PRINTF("cc2420: sending %d bytes\n", payload_len); RIMESTATS_ADD(lltx); /* Wait for any previous transmission to finish. */ while(status() & BV(CC2420_TX_ACTIVE)); /* Write packet to TX FIFO. */ strobe(CC2420_SFLUSHTX); checksum = crc16_data(payload, payload_len, 0); total_len = payload_len + AUX_LEN; FASTSPI_WRITE_FIFO(&total_len, 1); FASTSPI_WRITE_FIFO(payload, payload_len); FASTSPI_WRITE_FIFO(&checksum, CHECKSUM_LEN); #if CC2420_CONF_TIMESTAMPS timestamp.authority_level = timesynch_authority_level(); timestamp.time = timesynch_time(); FASTSPI_WRITE_FIFO(×tamp, TIMESTAMP_LEN); #endif /* CC2420_CONF_TIMESTAMPS */ /* The TX FIFO can only hold one packet. Make sure to not overrun * FIFO by waiting for transmission to start here and synchronizing * with the CC2420_TX_ACTIVE check in cc2420_send. * * Note that we may have to wait up to 320 us (20 symbols) before * transmission starts. */ #ifdef TMOTE_SKY #define LOOP_20_SYMBOLS 100 /* 326us (msp430 @ 2.4576MHz) */ #elif __AVR__ #define LOOP_20_SYMBOLS 500 /* XXX */ #endif #if WITH_SEND_CCA strobe(CC2420_SRXON); while(!(status() & BV(CC2420_RSSI_VALID))); strobe(CC2420_STXONCCA); #else /* WITH_SEND_CCA */ strobe(CC2420_STXON); #endif /* WITH_SEND_CCA */ for(i = LOOP_20_SYMBOLS; i > 0; i--) { if(SFD_IS_1) { #if CC2420_CONF_TIMESTAMPS rtimer_clock_t txtime = timesynch_time(); #endif /* CC2420_CONF_TIMESTAMPS */ if(receive_on) { ENERGEST_OFF(ENERGEST_TYPE_LISTEN); } ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); /* We wait until transmission has ended so that we get an accurate measurement of the transmission time.*/ while(status() & BV(CC2420_TX_ACTIVE)); #if CC2420_CONF_TIMESTAMPS setup_time_for_transmission = txtime - timestamp.time; if(num_transmissions < 10000) { total_time_for_transmission += timesynch_time() - txtime; total_transmission_len += total_len; num_transmissions++; } #endif /* CC2420_CONF_TIMESTAMPS */ #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower()); #endif ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); if(receive_on) { ENERGEST_ON(ENERGEST_TYPE_LISTEN); } RELEASE_LOCK(); return 0; } } /* If we are using WITH_SEND_CCA, we get here if the packet wasn't transmitted because of other channel activity. */ RIMESTATS_ADD(contentiondrop); PRINTF("cc2420: do_send() transmission never started\n"); RELEASE_LOCK(); return -3; /* Transmission never started! */ }