Ejemplo n.º 1
0
/**
 * @brief Switches the PLL on
 */
static void switch_pll_on(void)
{
    uint32_t start_time;
    uint32_t current_time;

    /* Check if trx is in TRX_OFF; only from PLL_ON the following procedure is applicable */
    if (pal_trx_bit_read(SR_TRX_STATUS) != TRX_OFF)
    {
        ASSERT("Switch PLL_ON failed, because trx is not in TRX_OFF" == 0);
        return;
    }

    /* Clear all pending trx interrupts */
    pal_trx_reg_read(RG_IRQ_STATUS);
    /* Get current IRQ mask */
    uint8_t trx_irq_mask = pal_trx_reg_read(RG_IRQ_MASK);
    /* Enable transceiver's PLL lock interrupt */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_0_PLL_LOCK);
    ENTER_TRX_REGION(); // Disable trx interrupt handling

    /* Switch PLL on */
    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
    pal_get_current_time(&start_time);

    /* Wait for transceiver interrupt: check for IRQ line */
    while (PAL_TRX_IRQ_HIGH() == false)
    {
        /* Handle errata "potential long PLL settling duration". */
        pal_get_current_time(&current_time);
        if (pal_sub_time_us(current_time, start_time) > PLL_LOCK_DURATION_MAX_US)
        {
            uint8_t reg_value;

            reg_value = pal_trx_reg_read(RG_PLL_CF);
            if (reg_value & 0x01)
            {
                reg_value &= 0xFE;
            }
            else
            {
                reg_value |= 0x01;
            }
            pal_trx_reg_write(RG_PLL_CF, reg_value);
            pal_get_current_time(&start_time);
        }
        /* Wait until trx line has been raised. */
    }

    /* Clear PLL lock interrupt at trx */
    pal_trx_reg_read(RG_IRQ_STATUS);
    /* Clear MCU's interrupt flag */
    pal_trx_irq_flag_clr();
    LEAVE_TRX_REGION();    // Enable trx interrupt handling again
    /* Restore transceiver's interrupt mask. */
    pal_trx_reg_write(RG_IRQ_MASK, trx_irq_mask);
}
Ejemplo 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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
/**
 * \brief Sends the frame at the next backoff boundary
 */
static void send_frame_at_next_backoff_boundary(void)
{
	uint8_t ack_is_requested;
	uint32_t now_time_us;

	/*
	 * Locate the next backoff boundary for the frame transmissiom;
	 * this backoff boundary is the starttime for the frame fransmission.
	 * Use a blocking approach, since next backoff boundary should be close.
	 */
	do {
		pal_get_current_time(&now_time_us);
	} while (pal_add_time_us(now_time_us, PRE_TX_DURATION_US) <
			cca_starttime_us);

	/* re-programm the interrupt handler */
	pal_trx_irq_init((FUNC_PTR)ack_reception_handler_cb);
	pal_trx_irq_en();

	/* debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h */
	PIN_TX_START();

	/* Check if an acknowledgement is requested for this frame. */
	ack_is_requested = *(tal_frame_to_tx + 1) & FCF_ACK_REQUEST;

	if (ack_is_requested > 0) {
		tal_csma_state = FRAME_SENDING_WITH_ACK;
	} else {
		tal_csma_state = FRAME_SENDING_NO_ACK;
	}

	/* download and send frame, no CSMA and no frame_retry */
	send_frame(NO_CSMA_NO_IFS, false);
}
Ejemplo n.º 5
0
/**
 * @brief Switches the PLL on
 */
static void switch_pll_on(void)
{
    trx_irq_reason_t irq_status;
    uint32_t start_time, now;

    /* Check if trx is in TRX_OFF; only from PLL_ON the following procedure is applicable */
    if (pal_trx_bit_read(SR_TRX_STATUS) != TRX_OFF)
    {
        ASSERT("Switch PLL_ON failed, because trx is not in TRX_OFF" == 0);
        return;
    }

    /* use the IRQ status register checking for the actual PLL status */
    pal_trx_irq_dis();
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_PLL_LOCK);  /* allow PLL lock IRQ only*/
    pal_trx_reg_read(RG_IRQ_STATUS);    /* clear PLL lock bit */

    /* Switch PLL on */
    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);

    /* Check if PLL has been locked. */
    pal_get_current_time(&start_time);
    while (1)
    {
        irq_status = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS);
        if (irq_status & TRX_IRQ_PLL_LOCK)
        {
            break;  // PLL is locked now
        }

        /* Check if polling needs too much time. */
        pal_get_current_time(&now);
        if (pal_sub_time_us(now, start_time) > (10 * PLL_LOCK_TIME_US))
        {
            /* leave poll loop and throw assertion */
#if (DEBUG > 0)
            ASSERT("PLL switch failed" == 0);
#endif
            break;
        }
    }
    pal_trx_irq_flag_clr();
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_TRX_END); /* enable TRX_END interrupt */

    pal_trx_irq_en();
}
Ejemplo n.º 6
0
/**
 * \brief Sends the frame at the next backoff boundary
 */
static void send_frame_at_next_backoff_boundary(void)
{
	uint32_t now_time_us;

	/*
	 * Locate the next backoff boundary for the frame transmissiom;
	 * this backoff boundary is the starttime for the frame fransmission.
	 * Use a blocking approach, since next backoff boundary should be close.
	 */
	do {
		pal_get_current_time(&now_time_us);
	} while (pal_add_time_us(now_time_us, PRE_TX_DURATION_US) <
			cca_starttime_us);

	/* debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h */
	PIN_TX_START();

	tal_csma_state = FRAME_SENDING;

	/* download and send frame, no CSMA and no frame_retry */
	send_frame(NO_CSMA_NO_IFS, false);
}
Ejemplo n.º 7
0
/**
 * \brief Performs CCA twice
 */
static uint8_t perform_cca_twice(void)
{
	uint8_t cca_status;
	uint8_t cca_done;
	uint8_t CW = 2;
	uint32_t now_time_us;

	do {
		pal_get_current_time(&now_time_us);
	} while (pal_add_time_us(now_time_us,
			(SLEEP_TO_TRX_OFF_TYP_US +
			CCA_PREPARATION_DURATION_US)) <
			cca_starttime_us);

#if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
	if (tal_beacon_transmission) {
#if (_DEBUG_ > 0)
		Assert("Ongoing beacon transmission, slotted CSMA busy" == 0);
#endif
		return PHY_BUSY;
	}

#endif /* ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) */

	/* Ensure that trx is at least in TRX_OFF mode at this time. */
	if (tal_trx_status == TRX_SLEEP) {
		set_trx_state(CMD_TRX_OFF);
	}

	do {
		pal_get_current_time(&now_time_us);
	} while (pal_add_time_us(now_time_us,
			(TRX_OFF_TO_PLL_ON_TIME_US +
			CCA_PREPARATION_DURATION_US)) <
			cca_starttime_us);

	/*
	 * Set trx to PLL_ON.
	 * If trx is busy and trx cannot be set to PLL_ON, assess channel as
	 * busy.
	 */
	if (set_trx_state(CMD_PLL_ON) != PLL_ON) {
		return PHY_BUSY;
	}

	/* no interest in receiving frames while doing CCA */
	trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE); /* disable frame reception
	                                           * indication */

	/* do CCA twice */
	do {
		/* wait here until 16us before backoff boundary */
		/* assume TRX is in PLL_ON */
		do {
			pal_get_current_time(&now_time_us);
		} while (pal_add_time_us(now_time_us,
				CCA_PRE_START_DURATION_US) <
				cca_starttime_us);

		set_trx_state(CMD_RX_ON);

		/* debug pin to switch on: define ENABLE_DEBUG_PINS,
		 * pal_config.h */
		PIN_CCA_START();

		/* Start CCA */
		trx_bit_write(SR_CCA_REQUEST, CCA_START);

		/* wait until CCA is done and get status */
		pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(CCA_DURATION_SYM));

		do {
			/* poll until CCA is really done; */
			cca_done = trx_bit_read(SR_CCA_DONE);
		} while (cca_done != CCA_COMPLETED);

		/* between both CCA switch trx to PLL_ON to reduce power
		 * consumption */
		set_trx_state(CMD_PLL_ON);

		/* debug pin to switch on: define ENABLE_DEBUG_PINS,
		 * pal_config.h */
		PIN_CCA_END();

		/* check if channel was idle or busy */
		if (trx_bit_read(SR_CCA_STATUS) == CCA_CH_IDLE) {
			/* do next CCA at next backoff boundary */
			cca_starttime_us = pal_add_time_us(cca_starttime_us,
					TAL_CONVERT_SYMBOLS_TO_US(
					aUnitBackoffPeriod));
			CW--;
			cca_status = PHY_IDLE;
		} else { /* PHY busy */
			cca_status = PHY_BUSY;
			set_trx_state(CMD_RX_AACK_ON);
			break; /* if channel is busy do no do CCA for the second
			        * time */
		}
	} while (CW > 0);

	/*
	 * Keep trx ready for transmission if channel is idle.
	 * The transceiver is still in PLL_ON.
	 * If the channel is not idle, the trx handling is done in
	 * csma_backoff().
	 */

	/*
	 * Clear CCA interrupt flag.
	 * This is only necessary for debugging, because only in debug mode
	 * interrupt that are not handled cause an assert in the ISR.
	 */
#if (_DEBUG_ > 0)
	trx_reg_read(RG_IRQ_STATUS);
#endif

	/*
	 * Since we are not interested in any frames that might be received
	 * during CCA, reject any information that indicates a previous frame
	 * reception.
	 */
	trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); /* enable frame reception
	                                          * indication */

	return cca_status;
}
Ejemplo n.º 8
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();
			}
		}
	}
}
Ejemplo n.º 9
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() */
Ejemplo n.º 11
0
/**
 * @brief Transceiver interrupt handler
 *
 * This function handles the transceiver interrupt. It reads all IRQs from the
 * transceivers and stores them to a variable. If a transceiver is currently
 * sleeping, then the IRQs are not handled.
 * The actual processing of the IRQs is triggered from tal_task().
 */
void trx_irq_handler_cb(void)
{
#ifdef IRQ_DEBUGGING
	uint32_t now;
	pal_get_current_time(&now);
#endif

	/* Get all IRQS values */
	uint8_t irqs_array[4];

	trx_read(RG_RF09_IRQS, irqs_array, 4);

	/* Handle BB IRQS */
	for (uint8_t trx_id = 0; trx_id < NUM_TRX; trx_id++) {
		if (tal_state[trx_id] == TAL_SLEEP) {
			continue;
		}

		bb_irq_t irqs = (bb_irq_t)irqs_array[trx_id + 2];

		if (irqs != BB_IRQ_NO_IRQ) {
			if (irqs & BB_IRQ_RXEM) {
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_RXEM)); /*
				                                              * avoid
				                                              * Pa091 */
			}

			if (irqs & BB_IRQ_RXAM) {
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_RXAM)); /*
				                                              * avoid
				                                              * Pa091 */
			}

			if (irqs & BB_IRQ_AGCR) {
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_AGCR)); /*
				                                              * avoid
				                                              * Pa091 */
#ifdef IRQ_DEBUGGING
				per[trx_id].agcr++;
				printf("AGCR %" PRIu32 "\n", now);
#endif
#if (defined RF215V1) && (!defined BASIC_MODE)
				/* Workaround for errata reference #4830 */
				if ((irqs & BB_IRQ_RXFE) == 0) {
					uint16_t reg_offset
						= RF_BASE_ADDR_OFFSET *
							trx_id;
					trx_bit_write(
							reg_offset + SR_BBC0_AMCS_AACK,
							0);
					trx_bit_write(
							reg_offset + SR_BBC0_AMCS_AACK,
							1);
				}

#endif
			}

			if (irqs & BB_IRQ_AGCH) {
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_AGCH)); /*
				                                              * avoid
				                                              * Pa091 */
#ifdef IRQ_DEBUGGING
				per[trx_id].agch++;
				printf("AGCH %" PRIu32 "\n", now);
#endif
			}

			if (irqs & BB_IRQ_RXFS) {
#ifdef ENABLE_TSTAMP
				pal_get_current_time(&fs_tstamp[trx_id]);
#endif
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_RXFS)); /*
				                                              * avoid
				                                              * Pa091 */
#ifdef IRQ_DEBUGGING
				per[trx_id].rxfs++;
				printf("RXFS %" PRIu32 "\n", now);
#endif
			}

			if (irqs & BB_IRQ_RXFE) {
				pal_get_current_time(&rxe_txe_tstamp[trx_id]);
#ifdef IRQ_DEBUGGING
				per[trx_id].rxfe++;
				printf("RXFE %" PRIu32 "\n", now);
#endif
			}

			if (irqs & BB_IRQ_TXFE) {
				/* used for IFS and for MEASURE_ON_AIR_DURATION
				 **/
				pal_get_current_time(&rxe_txe_tstamp[trx_id]);
				/* tal_rx_enable(trx_id, PHY_RX_ON);//abi */
			}

			/*
			 * Store remaining flags to global TAL variable and
			 * handle them within tal_task()
			 */
			tal_bb_irqs[trx_id] |= irqs;
		}
	}

	/* Handle RF IRQS */
	for (uint8_t trx_id = 0; trx_id < NUM_TRX; trx_id++) {
		if (tal_state[trx_id] == TAL_SLEEP) {
			continue;
		}

		rf_irq_t irqs = (rf_irq_t)irqs_array[trx_id];

		if (irqs != RF_IRQ_NO_IRQ) {
			if (irqs & RF_IRQ_TRXRDY) {
				irqs &= (uint8_t)(~((uint32_t)RF_IRQ_TRXRDY)); /*
				                                                * avoid
				                                                * Pa091 */
			}

			if (irqs & RF_IRQ_TRXERR) {
			}

			if (irqs & RF_IRQ_BATLOW) {
			}

			if (irqs & RF_IRQ_WAKEUP) {
			}

			if (irqs & RF_IRQ_IQIFSF) {
			}

			if (irqs & RF_IRQ_EDC) {
			}

			tal_rf_irqs[trx_id] |= irqs;
		}
	}
} /* trx_irq_handler_cb() */
Ejemplo n.º 12
0
void bb_irq_handler_cb(void)
{
#ifdef IRQ_DEBUGGING
	uint32_t now;
	pal_get_current_time(&now);
#endif

	/* Get all IRQS values */
	uint8_t irqs_array[4];

	pal_trx_read(RF215_BB, RG_RF09_IRQS, irqs_array, 4);

	/* Handle BB IRQS */
	for (uint8_t trx_id = 0; trx_id < NUM_TRX; trx_id++) {
		if (tal_state[trx_id] == TAL_SLEEP) {
			continue;
		}

		uint8_t irqs = irqs_array[trx_id + 2];

		if (irqs != BB_IRQ_NO_IRQ) {
			if (irqs & BB_IRQ_RXEM) {
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_RXEM)); /*
				                                              * avoid
				                                              * Pa091 */
			}

			if (irqs & BB_IRQ_RXAM) {
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_RXAM)); /*
				                                              * avoid
				                                              * Pa091 */
			}

			if (irqs & BB_IRQ_AGCR) {
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_AGCR)); /*
				                                              * avoid
				                                              * Pa091 */
				uint16_t reg_offset = RF_BASE_ADDR_OFFSET *
						trx_id;
				/* Release AGC */
				pal_trx_bit_write(RF215_RF,
						reg_offset + SR_RF09_AGCC_FRZC,
						0);
#ifdef IRQ_DEBUGGING
				per[trx_id].agcr++;
				printf("AGCR %" PRIu32 "\n", now);
#endif
#if (defined RF215V1) && (!defined BASIC_MODE)
				/* Workaround for errata reference #4830 */
				if ((irqs & BB_IRQ_RXFE) == 0) {
					uint16_t reg_offset
						= RF_BASE_ADDR_OFFSET *
							trx_id;
					trx_bit_write(
							reg_offset + SR_BBC0_AMCS_AACK,
							0);
					trx_bit_write(
							reg_offset + SR_BBC0_AMCS_AACK,
							1);
				}

#endif
			}

			if (irqs & BB_IRQ_AGCH) {
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_AGCH)); /*
				                                              * avoid
				                                              * Pa091 */
				/* Hold AGC */
				uint16_t reg_offset = RF_BASE_ADDR_OFFSET *
						trx_id;
				pal_trx_bit_write(RF215_RF,
						reg_offset + SR_RF09_AGCC_FRZC,
						1);
#ifdef IRQ_DEBUGGING
				per[trx_id].agch++;
				printf("AGCH %" PRIu32 "\n", now);
#endif
			}

			if (irqs & BB_IRQ_RXFS) {
#ifdef ENABLE_TSTAMP
				pal_get_current_time(&fs_tstamp[trx_id]);
#endif
				irqs &= (uint8_t)(~((uint32_t)BB_IRQ_RXFS)); /*
				                                              * avoid
				                                              * Pa091 */
#ifdef IRQ_DEBUGGING
				per[trx_id].rxfs++;
				printf("RXFS %" PRIu32 "\n", now);
#endif
			}

			if (irqs & BB_IRQ_RXFE) {
#ifdef IRQ_DEBUGGING
				per[trx_id].rxfe++;
				printf("RXFE %" PRIu32 "\n", now);
#endif
				pal_get_current_time(&rxe_txe_tstamp[trx_id]);
				/* Wait for TXPREP and clear TRXRDY IRQ */
				switch_rf_to_txprep((trx_id_t)trx_id);
			}

			if (irqs & BB_IRQ_TXFE) {
				/* used for IFS and for MEASURE_ON_AIR_DURATION
				 **/
				pal_get_current_time(&rxe_txe_tstamp[trx_id]);
				/* BB interrupt handles further processing */
			}

			/*
			 * Store remaining flags to global TAL variable and
			 * handle them within tal_task()
			 */
			tal_bb_irqs[trx_id] |= irqs;
		}
	}

	/* Handle RF IRQS */
	for (uint8_t trx_id = 0; trx_id < NUM_TRX; trx_id++) {
		if (tal_state[trx_id] == TAL_SLEEP) {
			continue;
		}

		uint8_t irqs = irqs_array[trx_id];

		if (irqs != RF_IRQ_NO_IRQ) {
			if (irqs & RF_IRQ_TRXRDY) {
				irqs &= (uint8_t)(~((uint32_t)RF_IRQ_TRXRDY)); /*
				                                                * avoid
				                                                * Pa091 */
			}

			if (irqs & RF_IRQ_TRXERR) {
#if (BOARD_TYPE == EVAL215_FPGA)
				printf("BB - RF_IRQ_TRXERR\n");
#endif
			}

			if (irqs & RF_IRQ_BATLOW) {
				irqs &= (uint8_t)(~((uint32_t)RF_IRQ_BATLOW)); /*
				                                                * avoid
				                                                * Pa091 */
#if (BOARD_TYPE == EVAL215_FPGA)
				printf("BB - RF_IRQ_BATLOW\n");
#endif
			}

			if (irqs & RF_IRQ_WAKEUP) {
				irqs &= (uint8_t)(~((uint32_t)RF_IRQ_WAKEUP)); /*
				                                                * avoid
				                                                * Pa091 */
#if (BOARD_TYPE == EVAL215_FPGA)
				printf("BB - RF_IRQ_WAKEUP\n");
#endif
			}

			if (irqs & RF_IRQ_IQIFSF) {
#if (BOARD_TYPE == EVAL215_FPGA)
#ifdef IRQ_DEBUGGING
				printf("BB - RF_IRQ_IQIFSF %" PRIu32 "\n", now);
#endif
#endif
			}

			if (irqs & RF_IRQ_EDC) {
				irqs &= (uint8_t)(~((uint32_t)RF_IRQ_EDC)); /*
				                                             * avoid
				                                             * Pa091 */
			}

			if (irqs != 0) {
			}

			tal_rf_irqs[trx_id] |= irqs;
		}
	}
} /* bb_irq_handler_cb() */
Ejemplo n.º 13
0
/**
 * @brief Performs CCA twice
 */
static uint8_t perform_cca_twice(void)
{
    uint8_t cca_status;
    uint8_t cca_done;
    uint8_t CW = 2;
    uint32_t now_time_us;

    do
    {
        pal_get_current_time(&now_time_us);
    } while (pal_add_time_us(now_time_us, (SLEEP_TO_TRX_OFF_US + CCA_PREPARATION_DURATION_US)) <
             cca_starttime_us);

#ifndef RFD
    if (tal_beacon_transmission)
    {
#if (DEBUG > 0)
        ASSERT("Ongoing beacon transmission, slotted CSMA busy" == 0);
#endif
        return PHY_BUSY;
    }
#endif

    // Ensure that trx is at least in TRX_OFF mode at this time.
    if (tal_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_TRX_OFF);
    }

    do
    {
        pal_get_current_time(&now_time_us);
    } while (pal_add_time_us(now_time_us, (PLL_LOCK_TIME_US + CCA_PREPARATION_DURATION_US)) <
             cca_starttime_us);

    /*
     * Set trx to PLL_ON.
     * If trx is busy and trx cannot be set to PLL_ON, assess channel as busy.
     */
    if (set_trx_state(CMD_PLL_ON) != PLL_ON)
    {
        return PHY_BUSY;
    }

    // no interest in receiving frames while doing CCA
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE); // disable frame reception indication

    // do CCA twice
    do
    {
        // wait here until 16us before backoff boundary
        // assume TRX is in PLL_ON
        do
        {
            pal_get_current_time(&now_time_us);
        } while (pal_add_time_us(now_time_us, CCA_PRE_START_DURATION_US) <
                 cca_starttime_us);

        pal_trx_reg_write(RG_TRX_STATE, CMD_RX_ON);

        // debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h
        PIN_CCA_START();

        /* Start CCA */
        pal_trx_bit_write(SR_CCA_REQUEST, CCA_START);

        // wait until CCA is done and get status
        pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(CCA_DURATION_SYM));

        do
        {
          // poll until CCA is really done;
          cca_done = pal_trx_bit_read(SR_CCA_DONE);
        } while (cca_done != CCA_DETECTION_DONE);

        // between both CCA switch trx to PLL_ON to reduce power consumption
        pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);

        // debug pin to switch on: define ENABLE_DEBUG_PINS, pal_config.h
        PIN_CCA_END();

        // check if channel was idle or busy
        if (pal_trx_bit_read(SR_CCA_STATUS) == CCA_STATUS_CHANNEL_IS_IDLE)
        {
            // do next CCA at next backoff boundary
            cca_starttime_us = pal_add_time_us(cca_starttime_us,
                                               TAL_CONVERT_SYMBOLS_TO_US(aUnitBackoffPeriod));
            CW--;
            cca_status = PHY_IDLE;
        }
        else    // PHY busy
        {
            cca_status = PHY_BUSY;
            break;  // if channel is busy do no do CCA for the second time
        }
    }
    while (CW > 0);

    /*
     * Keep trx ready for transmission if channel is idle.
     * The transceiver is still in PLL_ON.
     * If the channel is not idle, the trx handling is done in csma_backoff().
     */

    /*
     * Clear CCA interrupt flag.
     * This is only necessary for debugging, because only in debug mode
     * interrupt that are not handled cause an assert in the ISR.
     */
#if (DEBUG > 0)
    pal_trx_reg_read(RG_IRQ_STATUS);
#endif

    /*
     * Since we are not interested in any frames that might be received
     * during CCA, reject any information that indicates a previous frame
     * reception.
     */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); // enable frame reception indication

    return cca_status;
}
Ejemplo n.º 14
0
/**
 * \brief Performs CCA twice
 */
static uint8_t perform_cca_twice(void)
{
	tal_trx_status_t trx_status;
	uint8_t cca_status;
	uint8_t CW = 2;
	uint32_t now_time_us;

	do {
		pal_get_current_time(&now_time_us);
	} while (pal_add_time_us(now_time_us,
			(SLEEP_TO_TRX_OFF_US + CCA_PREPARATION_DURATION_US)) <
			cca_starttime_us);

	/* Ensure that trx is at least in TRX_OFF mode at this time. */
	if (tal_trx_status == TRX_SLEEP) {
		set_trx_state(CMD_TRX_OFF);
	}

	do {
		pal_get_current_time(&now_time_us);
	} while (pal_add_time_us(now_time_us,
			(PLL_LOCK_TIME_US + CCA_PREPARATION_DURATION_US)) <
			cca_starttime_us);

	/*
	 * Set trx to PLL_ON.
	 * If trx is busy and trx cannot be set to PLL_ON, assess channel as
	 *busy.
	 */
	if (set_trx_state(CMD_PLL_ON) != PLL_ON) {
		return PHY_BUSY;
	}

	/* no interest in trx interrupts while doing CCA */
	pal_trx_irq_dis();

	/* do CCA twice */
	do {
		/* wait here until 16us before backoff boundary */
		/* assume TRX is in PLL_ON */
		do {
			pal_get_current_time(&now_time_us);
		} while (pal_add_time_us(now_time_us,
				CCA_PRE_START_DURATION_US) <
				cca_starttime_us);

		set_trx_state(CMD_RX_ON);

		/* debug pin to switch on: define ENABLE_DEBUG_PINS,
		 *pal_config.h */
		PIN_CCA_START();

		/* Start CCA by writing any dummy value to this register */
		pal_trx_bit_write(SR_CCA_REQUEST, 1);

		/* wait until CCA is done and get status */
		pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(CCA_DURATION_SYM));

		do {
			/* poll until CCA is really done; */
			trx_status = (tal_trx_status_t)pal_trx_reg_read(
					RG_TRX_STATUS);
		} while ((trx_status & CCA_DONE_BIT) != CCA_DONE_BIT);

		/* between both CCA switch trx to PLL_ON to reduce power
		 *consumption */
		set_trx_state(CMD_PLL_ON);

		/* debug pin to switch on: define ENABLE_DEBUG_PINS,
		 *pal_config.h */
		PIN_CCA_END();

		/* check if channel was idle or busy */
		if (trx_status & CCA_STATUS_BIT) {
			/* do next CCA at next backoff boundary */
			cca_starttime_us = pal_add_time_us(cca_starttime_us,
					TAL_CONVERT_SYMBOLS_TO_US(
					aUnitBackoffPeriod));
			CW--;
			cca_status = PHY_IDLE;
		} else { /* PHY busy */
			cca_status = PHY_BUSY;
			set_trx_state(CMD_RX_AACK_ON);
			break; /* if channel is busy do no do CCA for the second
			        * time */
		}
	} while (CW > 0);

	/*
	 * Keep trx ready for transmission if channel is idle.
	 * The transceiver is still in PLL_ON.
	 * If the channel is not idle, the trx handling is done in
	 *csma_backoff().
	 */

	/*
	 * Since we are not interested in any frames that might be received
	 * during CCA, reject any information that indicates a previous frame
	 * reception.
	 */
	pal_trx_reg_read(RG_IRQ_STATUS);
	pal_trx_irq_flag_clr();
	pal_trx_irq_en();

	return cca_status;
}
Ejemplo n.º 15
0
/**
 * @brief Transceiver interrupt handler
 *
 * This function handles the transceiver generated interrupts.
 */
void trx_irq_handler_cb(void)
{
    trx_irq_reason_t trx_irq_cause;

#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
#ifdef DISABLE_TSTAMP_IRQ
    /*
     * Get timestamp.
     *
     * In case Antenna diversity is used or the utilization of
     * the Timestamp IRQ is disabled, the timestamp needs to be read now
     * the "old-fashioned" way.
     *
     * The timestamping is generally only done for
     * beaconing networks or if timestamping is explicitly enabled.
     */
    pal_get_current_time(&tal_rx_timestamp);
#endif  /* DISABLE_TSTAMP_IRQ */
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

    trx_irq_cause = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS);

    if (trx_irq_cause & TRX_IRQ_TRX_END)
    {
        /*
         * TRX_END reason depends on if the trx is currently used for
         * transmission or reception.
         */
#if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
        if ((tal_state == TAL_TX_AUTO) || tal_beacon_transmission)
#else
        if (tal_state == TAL_TX_AUTO)
#endif
        {
            /* Get the result and push it to the queue. */
            if (trx_irq_cause & TRX_IRQ_TRX_UR)
            {
                handle_tx_end_irq(true);            // see tal_tx.c
            }
            else
            {
                handle_tx_end_irq(false);            // see tal_tx.c
            }
        }
        else   /* Other tal_state than TAL_TX_... */
        {
            /* Handle rx interrupt. */
            handle_received_frame_irq();    // see tal_rx.c
        }
    }

#if (DEBUG > 0)
    /* Other IRQ than TRX_END */
    if (trx_irq_cause != TRX_IRQ_TRX_END)
    {
        /* PLL_LOCK interrupt migth be set, because poll mode is enabled. */
        /*
        if (trx_irq_cause & TRX_IRQ_PLL_LOCK)
        {
            ASSERT("unexpected IRQ: TRX_IRQ_PLL_LOCK" == 0);
        }
        */
        if (trx_irq_cause & TRX_IRQ_PLL_UNLOCK)
        {
            ASSERT("unexpected IRQ: TRX_IRQ_PLL_UNLOCK" == 0);
        }
        /* RX_START interrupt migth be set, because poll mode is enabled. */
        /*
        if (trx_irq_cause & TRX_IRQ_RX_START)
        {
            ASSERT("unexpected IRQ: TRX_IRQ_RX_START" == 0);
        }
        */
        if (trx_irq_cause & TRX_IRQ_CCA_ED_READY)
        {
            ASSERT("unexpected IRQ: TRX_IRQ_CCA_ED_READY" == 0);
        }
        /* AMI interrupt might set, because poll mode is enabled. */
        /*
        if (trx_irq_cause & TRX_IRQ_AMI)
        {
            ASSERT("unexpected IRQ: TRX_IRQ_AMI" == 0);
        }
        */
        if (trx_irq_cause & TRX_IRQ_TRX_UR)
        {
            ASSERT("unexpected IRQ: TRX_IRQ_TRX_UR" == 0);
        }
        if (trx_irq_cause & TRX_IRQ_BAT_LOW)
        {
            ASSERT("unexpected IRQ: TRX_IRQ_BAT_LOW" == 0);
        }
    }
#endif

}/* trx_irq_handler_cb() */
Ejemplo n.º 16
0
/**
 * @brief Resets transceiver(s)
 *
 * @param trx_id Transceiver identifier
 *
 * @return MAC_SUCCESS  if the transceiver returns TRX_OFF
 *         FAILURE otherwise
 */
retval_t trx_reset(trx_id_t trx_id)
{
	ENTER_TRX_REGION();

	uint32_t start_time;
	uint32_t current_time;
	pal_get_current_time(&start_time);

	if (trx_id == RFBOTH) {
		TAL_RF_IRQ_CLR_ALL(RF09);
		TAL_RF_IRQ_CLR_ALL(RF24);
		tal_state[RF09] = TAL_RESET;
		tal_state[RF24] = TAL_RESET;

		/* Apply reset pulse; low active */
#ifdef IQ_RADIO
		RST_LOW();
		PAL_WAIT_1_US();
		PAL_WAIT_1_US();
		RST_HIGH();
#if (BOARD_TYPE == EVAL215_FPGA)
		pal_timer_delay(10000);
#endif
		RST_LOW();
		PAL_WAIT_1_US();
		RST_HIGH();
#else
		RST_LOW();
		PAL_WAIT_1_US();
		RST_HIGH();
#endif

		/* Wait for IRQ line */
		while (1) {
			/*
			 * @ToDo: Use a different macro for IRQ line; the
			 *polarity might be
			 * different after reset
			 */
#ifdef IQ_RADIO
			if ((PAL_DEV_IRQ_GET(RF215_BB) == HIGH) &&
					(PAL_DEV_IRQ_GET(RF215_RF) == HIGH)) {
				break;
			}

#else
			if (TRX_IRQ_GET() == HIGH) {
				break;
			}

#endif

			/* Handle timeout */
			pal_get_current_time(&current_time);
			/* @ToDo: Remove magic number */
			if (pal_sub_time_us(current_time, start_time) > 1000) {
				return FAILURE;
			}
		}
#ifdef IQ_RADIO
		trx_state[RF09] = (rf_cmd_state_t)pal_dev_reg_read(RF215_RF,
				RG_RF09_STATE);
		trx_state[RF24] = (rf_cmd_state_t)pal_dev_reg_read(RF215_RF,
				RG_RF24_STATE);
		rf_cmd_state_t bb_trx_state[NUM_TRX];
		bb_trx_state[RF09] = (rf_cmd_state_t)pal_dev_reg_read(RF215_BB,
				RG_RF09_STATE);
		bb_trx_state[RF24] = (rf_cmd_state_t)pal_dev_reg_read(RF215_BB,
				RG_RF24_STATE);
		if ((bb_trx_state[RF09] != RF_TRXOFF) ||
				(bb_trx_state[RF24] != RF_TRXOFF)) {
			return FAILURE;
		}

#else
		trx_state[RF09] = trx_reg_read(RG_RF09_STATE);
		trx_state[RF24] = trx_reg_read(RG_RF24_STATE);
#endif
		if ((trx_state[RF09] != RF_TRXOFF) ||
				(trx_state[RF24] != RF_TRXOFF)) {
			return FAILURE;
		}

		/* Get all IRQ status information */
#ifdef IQ_RADIO
		bb_irq_handler_cb();
		rf_irq_handler_cb();
#else
		trx_irq_handler_cb();
#endif
		TAL_RF_IRQ_CLR(RF09, RF_IRQ_WAKEUP);
		TAL_RF_IRQ_CLR(RF24, RF_IRQ_WAKEUP);
	} else {
		TAL_RF_IRQ_CLR_ALL(trx_id);
		tal_state[trx_id] = TAL_RESET;

		/* Trigger reset of device */
		uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id;

#ifdef IQ_RADIO
		pal_trx_reg_write(RF215_RF, reg_offset + RG_RF09_CMD, RF_RESET);
		pal_trx_reg_write(RF215_BB, reg_offset + RG_RF09_CMD, RF_RESET);
#else
		trx_reg_write(reg_offset + RG_RF09_CMD, RF_RESET);
#endif

		/* Wait for IRQ line */
		while (1) {
#ifdef IQ_RADIO
			if ((PAL_DEV_IRQ_GET(RF215_BB) == HIGH) &&
					(PAL_DEV_IRQ_GET(RF215_RF) == HIGH)) {
				break;
			}

#else
			if (TRX_IRQ_GET() == HIGH) {
				break;
			}

#endif

			/* Handle timeout */
			pal_get_current_time(&current_time);
			/* @ToDo: Remove magic number */
			if (pal_sub_time_us(current_time, start_time) > 1000) {
				return FAILURE;
			}
		}
		trx_state[trx_id] = RF_TRXOFF;
		/* Get all IRQ status information */
#ifdef IQ_RADIO
		bb_irq_handler_cb();
		rf_irq_handler_cb();
#else
		trx_irq_handler_cb();
#endif
		TAL_RF_IRQ_CLR(trx_id, RF_IRQ_WAKEUP);
	}

#ifdef IQ_RADIO
	pal_trx_irq_flag_clr(RF215_BB);
	pal_trx_irq_flag_clr(RF215_RF);
#else
	pal_trx_irq_flag_clr();
#endif
	LEAVE_TRX_REGION();

	return MAC_SUCCESS;
}