+ int8_t dummy;
+ bool ccaFailure = FALSE;
+ error_t result = FAIL;
+ ieee154_txframe_t *frame = NULL;
+ ieee154_csma_t *csma = NULL;
+
+ atomic {
+ /* The CC2420 needs to be in an Rx mode for STXONCCA strobe */
+ /* Note: the receive logic of the CC2420 driver is not yet */
+ /* started, i.e. we cannot (yet) receive any packets */
+ call CC2420Power.rxOn();
+ m_state = S_TX_ACTIVE_SLOTTED_CSMA;
+
+ /* wait for CC2420 Rx to calibrate + CCA valid time */
+ while (call CC2420Power.rssi(&dummy) != SUCCESS)
+ ;
+
+ /* perform CCA on slot boundary (i.e. 8 symbols after backoff bounday); */
+ /* this platform-specific command is supposed to return just in time, so */
+ /* that the frame will be transmitted exactly on the next backoff boundary */
+ if (call ReliableWait.ccaOnBackoffBoundary(&m_t0.native)) {
+ /* first CCA succeeded */
+ if (call CC2420Tx.send(TRUE) == SUCCESS) {
+ /* frame is being sent now, do we need Rx logic ready for an ACK? */
+ checkEnableRxForACK();
+ return;
+ } else
+ ccaFailure = TRUE; /* second CCA failed */
+ } else
+ ccaFailure = TRUE; /* first CCA failed */
+
+ /* did not transmit the frame */
+ call CC2420Power.rfOff();
+ call CC2420Power.flushRxFifo(); /* we might have (accidentally) caught something */
+ m_state = S_LOAD_TXFIFO_SLOTTED;
+ if (ccaFailure) {
+ m_csma->NB += 1;
+ if (m_csma->NB > m_csma->macMaxCsmaBackoffs) {
+ /* CSMA-CA failure, we're done. The MAC may decide to retransmit. */
+ frame = m_txframe;
+ csma = m_csma;
+ result = FAIL;
+ } else {
+ /* next iteration of slotted CSMA-CA */
+ m_csma->BE += 1;
+ if (m_csma->BE > m_csma->macMaxBE)
+ m_csma->BE = m_csma->macMaxBE;
+ nextIterationSlottedCsma();
+ }
+ } else {
+ /* frame didn't fit into remaining CAP, this can only happen */
+ /* if the runtime overhead was too high. this should actually not happen. */
+ /* (in principle the frame should have fitted, because we checked before) */
+ frame = m_txframe;
+ csma = m_csma;
+ result = ERETRY;
+ }
+ }
+ if (frame != NULL) {
+ call CC2420Tx.unlockChipSpi();
+ call TxControl.stop();
+ call SpiResource.release();
+ m_state = S_RADIO_OFF;
+ signal SlottedCsmaCa.transmitDone(frame, csma, FALSE, 0, result);
+ }