Exemplo n.º 1
0
/**
 * @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;
}
Exemplo n.º 2
0
/**
 * \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;
}
Exemplo n.º 3
0
/**
 * \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();
			}
		}
	}
}
Exemplo n.º 4
0
/*
 * \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() */
Exemplo n.º 5
0
/*
 * \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() */
Exemplo n.º 7
0
/**
 * @brief Conversion of microseconds to symbols
 */
uint32_t tal_convert_us_to_symbols_def(uint32_t time)
{
	return (TAL_CONVERT_US_TO_SYMBOLS(time));
}
Exemplo n.º 8
0
/**
 * @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 {