/* * \brief Starts slotted CSMA */ bool slotted_csma_start(bool perform_frame_retry) { PIN_CSMA_START(); /* debug pin to switch on: define ENABLE_DEBUG_PINS, * pal_config.h */ bool return_val = false; /* Assume error case */ if (check_beacon_reception()) { tal_state = TAL_SLOTTED_CSMA; csma_param_init(); if (perform_frame_retry) { number_of_tx_retries = 0; } else { /* Use the max value to indicate that no retries are * required. */ number_of_tx_retries = tal_pib.MaxFrameRetries; } calculate_transaction_duration(); /* Get a random backoff period duration. */ remaining_backoff_periods = (uint8_t)(rand() & ((1 << BE) - 1)); csma_backoff_calculation(); return_val = true; } return return_val; }
/** * @brief Starts slotted CSMA */ void slotted_csma_start(bool perform_frame_retry) { PIN_CSMA_START(); // debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h tal_state = TAL_SLOTTED_CSMA; if (check_beacon_reception() == false) { tal_csma_state = NO_BEACON_TRACKING; return; } csma_param_init(); if (perform_frame_retry) { number_of_tx_retries = 0; } else { // use the max value to indicate that no retries are required number_of_tx_retries = tal_pib_MaxFrameRetries; } calculate_transaction_duration(); /* Get a random backoff period duration. */ remaining_backoff_periods = (uint8_t)(rand() & ((1 << BE) - 1)); csma_backoff_calculation(); }
/* * \brief Requests to TAL to transmit frame * * This function is called by the MAC to deliver a frame to the TAL * to be transmitted by the transceiver. * * \param tx_frame Pointer to the frame_info_t structure updated by the MAC * layer * \param csma_mode Indicates mode of csma-ca to be performed for this frame * \param perform_frame_retry Indicates whether to retries are to be performed * for * this frame * * \return MAC_SUCCESS if the TAL has accepted the data from the MAC for frame * transmission * TAL_BUSY if the TAL is busy servicing the previous MAC request */ retval_t tal_tx_frame(frame_info_t *tx_frame, csma_mode_t csma_mode, bool perform_frame_retry) { if (tal_state != TAL_IDLE) { return TAL_BUSY; } /* * Store the pointer to the provided frame structure. * This is needed for the callback function. */ mac_frame_ptr = tx_frame; /* Set pointer to actual mpdu to be downloaded to the transceiver. */ tal_frame_to_tx = tx_frame->mpdu; last_frame_length = tal_frame_to_tx[0] - 1; /* * In case the frame is too large, return immediately indicating * invalid status. */ if (tal_frame_to_tx == NULL) { return MAC_INVALID_PARAMETER; } #ifdef BEACON_SUPPORT /* Check if beacon mode is used */ if (csma_mode == CSMA_SLOTTED) { if (!slotted_csma_start(perform_frame_retry)) { return MAC_CHANNEL_ACCESS_FAILURE; } } else { #if (MAC_INDIRECT_DATA_FFD == 1) /* * Check if frame is using indirect transmission, but do not use * the * indirect_in_transit flag. This flag is not set for null data * frames. */ if ((tal_pib.BeaconOrder < NON_BEACON_NWK) && (csma_mode == NO_CSMA_WITH_IFS) && (perform_frame_retry == false)) { /* * Check if indirect transmission can be completed * before the next * beacon transmission. */ uint32_t time_between_beacons_sym; uint32_t next_beacon_time_sym; uint32_t now_time_sym; uint32_t duration_before_beacon_sym; /* Calculate the entire transaction duration. Re-use * function of slotted CSMA. * The additional two backoff periods used for CCA are * kept as a guard time. */ calculate_transaction_duration(); /* Calculate the duration until the next beacon needs to * be transmitted. */ time_between_beacons_sym = TAL_GET_BEACON_INTERVAL_TIME( tal_pib.BeaconOrder); next_beacon_time_sym = tal_add_time_symbols( tal_pib.BeaconTxTime, time_between_beacons_sym); pal_get_current_time(&now_time_sym); now_time_sym = TAL_CONVERT_US_TO_SYMBOLS(now_time_sym); duration_before_beacon_sym = tal_sub_time_symbols( next_beacon_time_sym, now_time_sym); /* Check if transaction can be completed before next * beacon transmission. */ if ((now_time_sym >= next_beacon_time_sym) || ((transaction_duration_periods * aUnitBackoffPeriod) > duration_before_beacon_sym)) { /* * Transaction will not be completed before next * beacon transmission. * Therefore the transmission is not executed. */ return MAC_CHANNEL_ACCESS_FAILURE; } } #endif /* #if (MAC_INDIRECT_DATA_FFD == 1) */ send_frame(csma_mode, perform_frame_retry); } #else /* No BEACON_SUPPORT */ send_frame(csma_mode, perform_frame_retry); #endif /* BEACON_SUPPORT / No BEACON_SUPPORT */ return MAC_SUCCESS; }