/** * @brief Checks if node is receiving beacons * * @return true: beacons are received otherwise false */ static bool check_beacon_reception(void) { uint32_t time_between_beacons_sym; uint32_t next_beacon_time_sym; //uint8_t number_of_lost_beacon = 0; uint32_t now_time; 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); now_time = TAL_CONVERT_US_TO_SYMBOLS(now_time); /* If the last beacon was not received, calculate/estimate the next beacon time */ while (next_beacon_time_sym < now_time) { tal_pib_BeaconTxTime = next_beacon_time_sym; next_beacon_time_sym = tal_add_time_symbols(tal_pib_BeaconTxTime, time_between_beacons_sym); /* * The following lines are excluded until, * the node is able to sync before transmission. */ /* number_of_lost_beacon++; if (number_of_lost_beacon == aMaxLostBeacons) // sync loss { return false; } */ } return true; }
/** * \brief Checks if node is receiving beacons * * \return true: beacons are received otherwise false */ static bool check_beacon_reception(void) { uint32_t time_between_beacons_sym; uint32_t next_beacon_time_sym; uint8_t number_of_lost_beacon = 0; uint32_t now_time; 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); now_time = TAL_CONVERT_US_TO_SYMBOLS(now_time); /* If the last beacon was not received, calculate/estimate the next * beacon time */ while (next_beacon_time_sym < now_time) { tal_pib.BeaconTxTime = next_beacon_time_sym; next_beacon_time_sym = tal_add_time_symbols( tal_pib.BeaconTxTime, time_between_beacons_sym); number_of_lost_beacon++; if (number_of_lost_beacon == aMaxLostBeacons) { /* sync loss */ return false; } } return true; }
/** * \brief Calculates backoff duration and handles the start of the CCA */ static void csma_backoff_calculation(void) { uint32_t current_CAP_duration_sym; uint32_t current_CAP_end_sym; uint32_t next_backoff_boundary_us; uint32_t now_time_sym; uint32_t guard_time_before_next_beacon; /* \TODO consider CFP and BLE mode */ current_CAP_duration_sym = TAL_GET_SUPERFRAME_DURATION_TIME( tal_pib.SuperFrameOrder); current_CAP_end_sym = tal_add_time_symbols(tal_pib.BeaconTxTime, current_CAP_duration_sym); /* * Add some guard time to ensure that the transaction is completed * before * the timer fires that is going to track the next beacon. */ guard_time_before_next_beacon = TAL_RADIO_WAKEUP_TIME_SYM << (tal_pib.BeaconOrder + 2); guard_time_before_next_beacon += TAL_CONVERT_US_TO_SYMBOLS( PRE_BEACON_GUARD_TIME_US); current_CAP_end_sym = tal_sub_time_symbols(current_CAP_end_sym, guard_time_before_next_beacon); /* Calculate next backoff period boundary. */ { uint32_t time_since_last_beacon_sym; uint32_t next_backoff_boundary_period; pal_get_current_time(&now_time_sym); now_time_sym = TAL_CONVERT_US_TO_SYMBOLS(now_time_sym); time_since_last_beacon_sym = tal_sub_time_symbols(now_time_sym, tal_pib.BeaconTxTime); next_backoff_boundary_period = time_since_last_beacon_sym / aUnitBackoffPeriod; if ((time_since_last_beacon_sym % aUnitBackoffPeriod) > 0) { next_backoff_boundary_period++; } next_backoff_boundary_us = TAL_CONVERT_SYMBOLS_TO_US( pal_add_time_us(tal_pib.BeaconTxTime, (next_backoff_boundary_period * aUnitBackoffPeriod))); } /* Check if we are still within the CAP. */ if (next_backoff_boundary_us >= TAL_CONVERT_SYMBOLS_TO_US(current_CAP_end_sym)) { /* current CAP is over, wait for next CAP */ tal_csma_state = BACKOFF_WAITING_FOR_BEACON; start_beacon_loss_timer(); } else { /* next backoff boundary is within current CAP */ uint32_t remaining_periods_in_CAP; /* \TODO check if variable * size can be reduced */ /* Check if the remaining backoff time will expire in current * CAP. */ remaining_periods_in_CAP = tal_sub_time_symbols( current_CAP_end_sym, now_time_sym) / aUnitBackoffPeriod; if (remaining_backoff_periods > remaining_periods_in_CAP) { /* * Reduce the backoff peridos by the remaining duration * in * the current CAP and continue in next CAP. */ remaining_backoff_periods -= remaining_periods_in_CAP; tal_csma_state = BACKOFF_WAITING_FOR_BEACON; start_beacon_loss_timer(); } else { /* there are enough backoff periods in current CAP */ uint32_t time_after_transaction_sym; /* \TODO check if * variable size * can be reduced **/ uint32_t transaction_duration_sym; /* \TODO check if * variable size can * be reduced */ /* Add some guard time to wakeup the transceiver. */ transaction_duration_sym = (transaction_duration_periods * aUnitBackoffPeriod) + TAL_CONVERT_US_TO_SYMBOLS( SLEEP_TO_TRX_OFF_TYP_US + CCA_GUARD_DURATION_US); time_after_transaction_sym = tal_add_time_symbols(TAL_CONVERT_US_TO_SYMBOLS( next_backoff_boundary_us), transaction_duration_sym); /* Check if the entire transaction fits into the current * CAP. */ if (time_after_transaction_sym < current_CAP_end_sym) { retval_t timer_status; uint32_t callback_start_time; /* Calculate the time needed to backoff. */ cca_starttime_us = pal_add_time_us( next_backoff_boundary_us, TAL_CONVERT_SYMBOLS_TO_US( remaining_backoff_periods * aUnitBackoffPeriod)); /* * Ensure that wakeup time is available before * CCA. * The required duration depends on the current * trx status. * Assume here the worst case: trx is in SLEEP. */ /* * \TODO depending on the duration that we need * to backoff, * set trx to SLEEP, TRX_OFF or PLL_ON * meanwhile. */ while (pal_sub_time_us(cca_starttime_us, TAL_CONVERT_SYMBOLS_TO_US( now_time_sym)) < (SLEEP_TO_TRX_OFF_TYP_US + CCA_GUARD_DURATION_US)) { cca_starttime_us = pal_add_time_us( cca_starttime_us, TAL_CONVERT_SYMBOLS_TO_US( aUnitBackoffPeriod)); } /* * Start the CCA timer. * Add some time to locate the next backoff * boundary * once CCA timer fires. */ callback_start_time = pal_sub_time_us(cca_starttime_us, (SLEEP_TO_TRX_OFF_TYP_US + CCA_PREPARATION_DURATION_US)); timer_status = pal_timer_start(TAL_CSMA_CCA, callback_start_time, TIMEOUT_ABSOLUTE, (FUNC_PTR)cca_timer_handler_cb, NULL); if (timer_status == MAC_SUCCESS) { tal_csma_state = BACKOFF_WAITING_FOR_CCA_TIMER; } else if (timer_status == PAL_TMR_INVALID_TIMEOUT) { /* Start the CCA immediately. */ cca_timer_handler_cb(NULL); } else { tal_csma_state = CSMA_ACCESS_FAILURE; Assert("CCA timer start problem" == 0); } /* debug pin to switch on: define * ENABLE_DEBUG_PINS, pal_config.h */ PIN_BACKOFF_START(); } else { /* Restart again after next beacon. */ NB = 0; remaining_backoff_periods = (uint8_t)(rand() & ((1 << BE) - 1)); tal_csma_state = BACKOFF_WAITING_FOR_BEACON; start_beacon_loss_timer(); } } } }
/* * \brief Parses received frame and create the frame_info_t structure * * This function parses the received frame and creates the frame_info_t * structure to be sent to the MAC as a parameter of tal_rx_frame_cb(). * * \param buf Pointer to the buffer containing the received frame */ void process_incoming_frame(buffer_t *buf_ptr) { #ifndef TRX_REG_RAW_VALUE uint8_t frame_len; uint8_t *frame_ptr; uint8_t ed_level; uint8_t lqi; #endif frame_info_t *receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr); /* The frame is present towards the end of the buffer. */ #ifndef TRX_REG_RAW_VALUE /* * Store the last frame length for IFS handling. * Substract LQI and length fields. */ frame_len = last_frame_length = receive_frame->mpdu[0]; #else last_frame_length = receive_frame->mpdu[0]; #endif #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { #ifndef TRX_REG_RAW_VALUE frame_ptr = &(receive_frame->mpdu[frame_len + LQI_LEN]); /* * The LQI is stored after the FCS. * The ED value is stored after the LQI. */ lqi = *frame_ptr++; ed_level = *frame_ptr; /* * The LQI normalization is done using the ED level measured during * the frame reception. */ #ifdef RSSI_TO_LQI_MAPPING lqi = normalize_lqi(ed_level); #else lqi = normalize_lqi(lqi, ed_level); #endif /* Store normalized LQI value again. */ frame_ptr--; *frame_ptr = lqi; #endif /* #ifndef TRX_REG_RAW_VALUE */ receive_frame->buffer_header = buf_ptr; /* The callback function implemented by MAC is invoked. */ tal_rx_frame_cb(receive_frame); return; } #endif /* #ifdef PROMISCUOUS_MODE */ #ifdef BEACON_SUPPORT /* * Are we waiting for a beacon for slotted CSMA? * Check if received frame is a beacon. */ if ((receive_frame->mpdu[PL_POS_FCF_1] & FCF_FRAMETYPE_MASK) == FCF_FRAMETYPE_BEACON) { /* Debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h */ PIN_BEACON_START(); if (tal_csma_state == BACKOFF_WAITING_FOR_BEACON) { /* Debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h */ PIN_WAITING_FOR_BEACON_END(); tal_pib.BeaconTxTime = TAL_CONVERT_US_TO_SYMBOLS(receive_frame->time_stamp); tal_csma_state = CSMA_HANDLE_BEACON; } /* Debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h */ PIN_BEACON_END(); } #endif /* BEACON_SUPPORT */ #ifndef TRX_REG_RAW_VALUE /* * The LQI is stored after the FCS. * The ED value is stored after the LQI. */ frame_ptr = &(receive_frame->mpdu[frame_len + LQI_LEN]); lqi = *frame_ptr++; ed_level = *frame_ptr; /* * The LQI normalization is done using the ED level measured during * the frame reception. */ #ifdef RSSI_TO_LQI_MAPPING lqi = normalize_lqi(ed_level); #else lqi = normalize_lqi(lqi, ed_level); #endif /* Store normalized LQI value again. */ frame_ptr--; *frame_ptr = lqi; #endif /* #ifndef TRX_REG_RAW_VALUE */ receive_frame->buffer_header = buf_ptr; #ifdef ENABLE_RTB /* The callback function implemented by RTB is invoked. */ rtb_rx_frame_cb(receive_frame); #else /* The callback function implemented by MAC is invoked. */ tal_rx_frame_cb(receive_frame); #endif } /* process_incoming_frame() */
/* * \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; }
/** * @brief Implement the MLME-RX-ENABLE.request primitive. * * The MLME-RX-ENABLE.request primitive is generated by the next * higher layer and issued to MAC to enable the receiver for a * fixed duration, at a time relative to the start of the current or * next superframe on a beacon-enabled PAN or immediately on a * nonbeacon-enabled PAN. The receiver is enabled exactly once per * primitive request. * * @param m Pointer to the MLME-RX-ENABLE.request message */ void mlme_rx_enable_request(uint8_t *m) { mlme_rx_enable_req_t *rxe; rxe = (mlme_rx_enable_req_t *)BMM_BUFFER_POINTER((buffer_t *)m); /* If RxOnDuration is zero, the receiver shall be disabled */ if (0 == rxe->RxOnDuration) { /* * Turn the radio off. This is doney by calling the * same function as for the expiration of the Rx on timer. */ mac_t_rx_off_cb(NULL); /* Send the confirm immediately. */ gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_SUCCESS); return; } /* * Reject the request when the MAC is currently in any of the * polling states or scanning. */ if ((MAC_POLL_IDLE != mac_poll_state) || (MAC_SCAN_IDLE != mac_scan_state) ) { /* Send the confirm immediately. */ gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_TX_ACTIVE); return; } #ifdef BEACON_SUPPORT if (NON_BEACON_NWK == tal_pib.BeaconOrder) { handle_rx_on(rxe->RxOnDuration, m); } else { /* We have a beacon-enabled network. */ uint32_t curr_beacon_int_time_symbols = TAL_GET_BEACON_INTERVAL_TIME(tal_pib.BeaconOrder); uint32_t now_time_symbols; uint32_t symbols_since_beacon; uint32_t rx_on_time_symbols; retval_t timer_status; /* * Determine if (RxOnTime + RxOnDuration) is less than the beacon * interval. * According to 7.1.10.1.3: * On a beacon-enabled PAN, the MLME first determines whether * (RxOnTime + RxOnDuration) is less than the beacon interval, defined * by macBeaconOrder. If it is not less, the MLME issues the * MLME-RX-ENABLE.confirm primitive with a status of MAC_INVALID_PARAMETER. */ rx_off_time_symbols = rxe->RxOnTime + rxe->RxOnDuration; if (rx_off_time_symbols >= curr_beacon_int_time_symbols) { /* Send the confirm immediately. */ gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_INVALID_PARAMETER); return; } pal_get_current_time(&now_time_symbols); now_time_symbols = TAL_CONVERT_US_TO_SYMBOLS(now_time_symbols); symbols_since_beacon = tal_sub_time_symbols(now_time_symbols, tal_pib.BeaconTxTime); /* * Actually, MLME-RX-ENABLE.request in a beacon enabled PAN does * only make sense if the MAC is currently tracking beacons, so * that macBeaconTxTime is up to date. If it appears that * the last known macBeaconTxTime does not relate to the * current superframe, reject the request. */ if (symbols_since_beacon > curr_beacon_int_time_symbols) { /* Send the confirm immediately. */ gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_INVALID_PARAMETER); return; } rx_on_time_symbols = tal_add_time_symbols(tal_pib.BeaconTxTime, rxe->RxOnTime); /* Check whether RxOnTime can still be handled in current CAP. */ pal_get_current_time(&now_time_symbols); now_time_symbols = TAL_CONVERT_US_TO_SYMBOLS(now_time_symbols); if (tal_add_time_symbols(rx_on_time_symbols, TAL_CONVERT_US_TO_SYMBOLS(MIN_TIMEOUT)) < now_time_symbols) { /* RxOnTime not possible within this CAP, see whether deferred * handling is allowed or not.. */ if (!(rxe->DeferPermit)) { gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_PAST_TIME); return; } else { /* * The MAC defers until the next superframe and attempts to enable * the receiver in that superframe. */ rx_on_time_symbols = tal_add_time_symbols(rx_on_time_symbols, curr_beacon_int_time_symbols); } } /* * Since the Rx-Enable timer could already be running, * it is stopped first, before it will be started (again). */ pal_timer_stop(T_Rx_Enable); do { /* * Start a timer to turn Rx ON at the time "rxe->RxOnTime" from the start * of the next superframe. * Return value to be checked, because Rx on time could be too short * or in the past already. */ timer_status = pal_timer_start(T_Rx_Enable, TAL_CONVERT_SYMBOLS_TO_US(rx_on_time_symbols), TIMEOUT_ABSOLUTE, (FUNC_PTR())mac_t_rx_on_cb, (void *)m); if (MAC_SUCCESS != timer_status) { rx_on_time_symbols = tal_add_time_symbols(rx_on_time_symbols, curr_beacon_int_time_symbols); } } while (MAC_SUCCESS != timer_status); /* Remember the time to turn off the receiver. */ rx_off_time_symbols = tal_add_time_symbols(rx_on_time_symbols, rxe->RxOnDuration); /* The remaining stuff will be done once the Rx On Timer expires. */ } #else /* No BEACON_SUPPORT */ handle_rx_on(rxe->RxOnDuration, m); #endif /* BEACON_SUPPORT / No BEACON_SUPPORT */ } /* mlme_rx_enable_request() */
/** * @brief Conversion of microseconds to symbols */ uint32_t tal_convert_us_to_symbols_def(uint32_t time) { return (TAL_CONVERT_US_TO_SYMBOLS(time)); }
/** * @brief Continues processing a data indication from the TAL for * non-polling and non-scanning states of the MAC * (mac_poll_state == MAC_POLL_IDLE, mac_scan_state == MAC_SCAN_IDLE). * * @param b_ptr Pointer to the buffer header. * @param f_ptr Pointer to the frame_info_t structure. * * @return bool True if frame has been processed, or false otherwise. */ static bool process_data_ind_not_transient(buffer_t *b_ptr, frame_info_t *f_ptr) { bool processed_in_not_transient = false; /* * We are in MAC_POLL_IDLE and MAC_SCAN_IDLE now, * so continue with the real MAC states. */ switch (mac_state) { #if (MAC_START_REQUEST_CONFIRM == 1) case MAC_PAN_COORD_STARTED: { switch (mac_parse_data.frame_type) { case FCF_FRAMETYPE_MAC_CMD: { switch (mac_parse_data.mac_command) { #if (MAC_ASSOCIATION_INDICATION_RESPONSE == 1) case ASSOCIATIONREQUEST: mac_process_associate_request(b_ptr); processed_in_not_transient = true; break; #endif /* (MAC_ASSOCIATION_INDICATION_RESPONSE == 1) */ #if (MAC_DISASSOCIATION_BASIC_SUPPORT == 1) case DISASSOCIATIONNOTIFICATION: mac_process_disassociate_notification(b_ptr); processed_in_not_transient = true; break; #endif /* (MAC_DISASSOCIATION_BASIC_SUPPORT == 1) */ #if (MAC_INDIRECT_DATA_FFD == 1) case DATAREQUEST: if (indirect_data_q.size > 0) { mac_process_data_request(b_ptr); processed_in_not_transient = true; } else { mac_handle_tx_null_data_frame(); } break; #endif /* (MAC_INDIRECT_DATA_FFD == 1) */ #if (MAC_ORPHAN_INDICATION_RESPONSE == 1) case ORPHANNOTIFICATION: mac_process_orphan_notification(b_ptr); processed_in_not_transient = true; break; #endif /* (MAC_ORPHAN_INDICATION_RESPONSE == 1) */ case BEACONREQUEST: mac_process_beacon_request(b_ptr); processed_in_not_transient = true; break; #if (MAC_PAN_ID_CONFLICT_AS_PC == 1) case PANIDCONFLICTNOTIFICAION: mac_sync_loss(MAC_PAN_ID_CONFLICT); break; #endif /* (MAC_PAN_ID_CONFLICT_AS_PC == 1) */ #ifdef GTS_SUPPORT case GTSREQUEST: mac_process_gts_request(b_ptr); processed_in_not_transient = true; #endif /* GTS_SUPPORT */ default: break; } } break; case FCF_FRAMETYPE_DATA: mac_process_data_frame(b_ptr); processed_in_not_transient = true; break; #if (MAC_PAN_ID_CONFLICT_AS_PC == 1) case FCF_FRAMETYPE_BEACON: /* PAN-Id conflict detection as PAN-Coordinator. */ /* Node is not scanning. */ check_for_pan_id_conflict_as_pc(false); break; #endif /* (MAC_PAN_ID_CONFLICT_AS_PC == 1) */ default: break; } } break; /* MAC_PAN_COORD_STARTED */ #endif /* (MAC_START_REQUEST_CONFIRM == 1) */ case MAC_IDLE: #if (MAC_ASSOCIATION_REQUEST_CONFIRM == 1) case MAC_ASSOCIATED: #endif /* (MAC_ASSOCIATION_REQUEST_CONFIRM == 1) */ #if (MAC_START_REQUEST_CONFIRM == 1) case MAC_COORDINATOR: #endif /* (MAC_START_REQUEST_CONFIRM == 1) */ { /* Is it a Beacon from our parent? */ switch (mac_parse_data.frame_type) { #if (MAC_SYNC_REQUEST == 1) case FCF_FRAMETYPE_BEACON: { uint32_t beacon_tx_time_symb; /* Check for PAN-Id conflict being NOT a PAN * Corodinator. */ #if (MAC_PAN_ID_CONFLICT_NON_PC == 1) if (mac_pib.mac_AssociatedPANCoord && (MAC_IDLE != mac_state)) { check_for_pan_id_conflict_non_pc(false); } #endif /* (MAC_PAN_ID_CONFLICT_NON_PC == 1) */ /* Check if the beacon is received from my * parent. */ if ((mac_parse_data.src_panid == tal_pib.PANId) && (((mac_parse_data.src_addr_mode == FCF_SHORT_ADDR) && (mac_parse_data.src_addr. short_address == mac_pib.mac_CoordShortAddress)) || ((mac_parse_data.src_addr_mode == FCF_LONG_ADDR) && (mac_parse_data.src_addr. long_address == mac_pib.mac_CoordExtendedAddress)))) { beacon_tx_time_symb = TAL_CONVERT_US_TO_SYMBOLS( f_ptr->time_stamp); #if (_DEBUG_ > 0) retval_t set_status = #endif set_tal_pib_internal(macBeaconTxTime, (void *)&beacon_tx_time_symb); #if (_DEBUG_ > 0) Assert(MAC_SUCCESS == set_status); #endif if ((MAC_SYNC_TRACKING_BEACON == mac_sync_state) || (MAC_SYNC_BEFORE_ASSOC == mac_sync_state) ) { uint32_t nxt_bcn_tm; uint32_t beacon_int_symb; /* Process a received beacon. */ mac_process_beacon_frame(b_ptr); /* Initialize beacon tracking * timer. */ { retval_t tmr_start_res = FAILURE; #ifdef BEACON_SUPPORT if (tal_pib.BeaconOrder < NON_BEACON_NWK) { beacon_int_symb = TAL_GET_BEACON_INTERVAL_TIME( tal_pib.BeaconOrder); } else #endif /* BEACON_SUPPORT */ { beacon_int_symb = TAL_GET_BEACON_INTERVAL_TIME( BO_USED_FOR_MAC_PERS_TIME); } pal_timer_stop( T_Beacon_Tracking_Period); #if (_DEBUG_ > 0) if (pal_is_timer_running( T_Beacon_Tracking_Period)) { Assert( "Bcn tmr running" == 0); } #endif do { /* * Calculate the * time for next * beacon * transmission */ beacon_tx_time_symb = tal_add_time_symbols( beacon_tx_time_symb, beacon_int_symb); /* * Take into * account the * time taken by * the radio to * wakeup from * sleep state */ nxt_bcn_tm = tal_sub_time_symbols( beacon_tx_time_symb, TAL_RADIO_WAKEUP_TIME_SYM << ( tal_pib . BeaconOrder + 2)); tmr_start_res = pal_timer_start( T_Beacon_Tracking_Period, TAL_CONVERT_SYMBOLS_TO_US( nxt_bcn_tm), TIMEOUT_ABSOLUTE, ( FUNC_PTR)mac_t_tracking_beacons_cb, NULL); } while (MAC_SUCCESS != tmr_start_res); #ifdef GTS_DEBUG port_pin_toggle_output_level( DEBUG_PIN1); port_pin_set_output_level( DEBUG_PIN2, 0); #endif } /* * Initialize superframe timer * if required only * for devices because * Superframe timer is already * running for * coordinator. */ /* TODO */ if (MAC_ASSOCIATED == mac_state) { mac_superframe_state = MAC_ACTIVE_CAP; /* Check whether the * radio needs to be * woken up. */ mac_trx_wakeup(); /* Set transceiver in rx * mode, otherwise it * may stay in * TRX_OFF). */ tal_rx_enable(PHY_RX_ON); if (tal_pib. SuperFrameOrder < tal_pib . BeaconOrder) { pal_timer_start( T_Superframe, TAL_CONVERT_SYMBOLS_TO_US( TAL_GET_SUPERFRAME_DURATION_TIME( tal_pib . SuperFrameOrder)), TIMEOUT_RELATIVE, ( FUNC_PTR)mac_t_start_inactive_device_cb, NULL); #ifdef GTS_DEBUG port_pin_set_output_level( DEBUG_PIN2, 1); #endif } #ifdef GTS_SUPPORT if (mac_final_cap_slot < FINAL_CAP_SLOT_DEFAULT) { uint32_t gts_tx_time = ( TAL_CONVERT_SYMBOLS_TO_US( TAL_GET_SUPERFRAME_DURATION_TIME( tal_pib . SuperFrameOrder)) >> 4) * ( mac_final_cap_slot + 1); pal_timer_start( T_CAP, gts_tx_time, TIMEOUT_RELATIVE, ( FUNC_PTR)mac_t_gts_cb, NULL); #ifdef GTS_DEBUG port_pin_set_output_level( DEBUG_PIN3, 1); #endif } #endif /* GTS_SUPPORT */ } /* Initialize missed beacon * timer. */ mac_start_missed_beacon_timer(); /* A device that is neither * scanning nor polling shall go * to sleep now. */ if ( (MAC_COORDINATOR != mac_state) && (MAC_SCAN_IDLE == mac_scan_state) && (MAC_POLL_IDLE == mac_poll_state) ) { /* * If the last received * beacon frame from our * parent * has indicated pending * broadbast data, we * need to * stay awake, until the * broadcast data has * been received. */ if (! mac_bc_data_indicated) { /* Set radio to * sleep if * allowed */ mac_sleep_trans(); } } } else if (MAC_SYNC_ONCE == mac_sync_state) { mac_process_beacon_frame(b_ptr); /* Do this after processing the * beacon. */ mac_sync_state = MAC_SYNC_NEVER; /* A device that is neither * scanning nor polling shall go * to sleep now. */ if ( (MAC_COORDINATOR != mac_state) && (MAC_SCAN_IDLE == mac_scan_state) && (MAC_POLL_IDLE == mac_poll_state) ) { /* * If the last received * beacon frame from our * parent * has indicated pending * broadbast data, we * need to * stay awake, until the * broadcast data has * been received. */ if (! mac_bc_data_indicated) { /* Set radio to * sleep if * allowed */ mac_sleep_trans(); } } } else { /* Process the beacon frame */ bmm_buffer_free(b_ptr); } processed_in_not_transient = true; } else {