コード例 #1
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);
}
コード例 #2
0
ファイル: tal_slotted_csma.c プロジェクト: InSoonPark/asf
/**
 * \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);
}
コード例 #3
0
ファイル: tal_slotted_csma.c プロジェクト: InSoonPark/asf
/**
 * \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;
}
コード例 #4
0
ファイル: tal_slotted_csma.c プロジェクト: InSoonPark/asf
/**
 * \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();
			}
		}
	}
}
コード例 #5
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;
}
コード例 #6
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;
}