Example #1
0
/**
 * \brief Start CCA.
 *
 * \param parameter Unused callback parameter
 */
static void cca_start(void *parameter)
{
	tal_state = TAL_CCA;

	if (set_trx_state(CMD_PLL_ON) == PLL_ON) {
		tal_trx_status_t trx_state;
		/* No interest in receiving frames while doing CCA */
		trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE); /* disable frame
		                                           * reception
		                                           * indication */
		do {
			trx_state = set_trx_state(CMD_RX_ON);
		} while (trx_state != RX_ON);
		/* Setup interrupt handling for CCA IRQ */
		trx_irq_init((FUNC_PTR)cca_done_irq_handler);
		trx_reg_write(RG_IRQ_MASK, TRX_IRQ_CCA_ED_READY); /* enable
		                                                   * CCA
		                                                   * interrupt
		                                                   **/
		/* Start CCA */
		trx_bit_write(SR_CCA_REQUEST, CCA_START);
	} else {
		/* Channel is busy, i.e. device is receiving */
		tal_state = TAL_CSMA_CONTINUE;
	}

	/* Keep compiler happy. */
	parameter = parameter;
}
Example #2
0
/**
 * \brief Starts the timer for the backoff period and enables receiver.
 */
static void start_backoff(void)
{
	/* Start backoff timer to trigger CCA */
	uint8_t backoff_8;
	backoff_8  = (uint8_t)rand() & ((1 << BE) - 1);
	if (backoff_8 > 0) {
		uint16_t backoff_16;
		uint32_t backoff_duration_us;
		backoff_16 = backoff_8 * aUnitBackoffPeriod;
		backoff_duration_us = TAL_CONVERT_SYMBOLS_TO_US(backoff_16);
		pal_timer_start(TAL_T_BOFF, backoff_duration_us,
				TIMEOUT_RELATIVE,
				(FUNC_PTR)cca_start, NULL);
		tal_state = TAL_BACKOFF;

#ifdef RX_WHILE_BACKOFF
		/* Switch receiver on during backoff */
		if (NULL == tal_rx_buffer) {
			set_trx_state(CMD_PLL_ON);
			tal_rx_on_required = true;
		} else {
			set_trx_state(CMD_RX_AACK_ON); /* receive while backoff
			                                **/
		}

#else
		set_trx_state(CMD_PLL_ON);
#endif
	} else {
		/* Start CCA immediately - no backoff */
		cca_start(NULL);
	}
}
Example #3
0
/**
 * @brief Sets the transceiver to sleep
 *
 * This function sets the transceiver to sleep state.
 *
 * @param mode Defines sleep mode of transceiver SLEEP or PHY_TRX_OFF)
 *
 * @return   TAL_BUSY - The transceiver is busy in TX or RX
 *           MAC_SUCCESS - The transceiver is put to sleep
 *           TAL_TRX_ASLEEP - The transceiver is already asleep
 *           MAC_INVALID_PARAMETER - The specified sleep mode is not supported
 */
retval_t tal_trx_sleep(sleep_mode_t mode)
{
    tal_trx_status_t trx_status;

    /* Current transceiver only supports SLEEP_MODE_1 mode. */
    if (SLEEP_MODE_1 != mode)
    {
        return MAC_INVALID_PARAMETER;
    }

    if (tal_trx_status == TRX_SLEEP)
    {
        return TAL_TRX_ASLEEP;
    }

    /* Device can be put to sleep only when the TAL is in IDLE state. */
    if (TAL_IDLE != tal_state)
    {
        return TAL_BUSY;
    }

    tal_rx_on_required = false;

    /*
     * First set trx to TRX_OFF.
     * If trx is busy, like ACK transmission, do not interrupt it.
     */
    do
    {
        trx_status = set_trx_state(CMD_TRX_OFF);
    }
    while (trx_status != TRX_OFF);

    pal_timer_source_select(TMR_CLK_SRC_DURING_TRX_SLEEP);

    trx_status = set_trx_state(CMD_SLEEP);

#ifdef ENABLE_FTN_PLL_CALIBRATION
    /*
     * Stop the calibration timer now.
     * The timer will be restarted during wake-up.
     */
    pal_timer_stop(TAL_CALIBRATION);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */

    if (trx_status == TRX_SLEEP)
    {
#ifdef STB_ON_SAL
#if (SAL_TYPE == AT86RF2xx)
        stb_restart();
#endif
#endif
        return MAC_SUCCESS;
    }
    else
    {
        /* State could not be set due to TAL_BUSY state. */
        return TAL_BUSY;
    }
}
Example #4
0
/*
 * \brief Perform a single ED measurement
 *
 * \return ed_value Result of the measurement
 *         If the build switch TRX_REG_RAW_VALUE is defined, the transceiver's
 *         register value is returned.
 */
uint8_t tfa_ed_sample(void)
{
    uint8_t ed_value;
    tal_trx_status_t trx_status;

    /* Make sure that receiver is switched on. */
    do
    {
        trx_status = set_trx_state(CMD_RX_ON);
    }
    while (trx_status != RX_ON);

    /*
     * Disable the transceiver interrupts to prevent frame reception
     * while performing ED scan.
     */
    pal_trx_irq_dis();

    /*
     * Initiate ED operation by writing any value into transceiver register
     * PHY_ED_LEVEL.
     */
    pal_trx_reg_write(RG_PHY_ED_LEVEL, 0x00);

    /*
     * Start timer for reading ED value from the transceiver after
     * 140 microseconds.
     */
    pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(ED_SAMPLE_DURATION_SYM + 1));

    /* Read the ED Value. */
    ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL);

    /* Clear IRQ register */
    pal_trx_reg_read(RG_IRQ_STATUS);
    /* Enable reception agian */
    pal_trx_irq_flag_clr();
    pal_trx_irq_en();
    /* Switch receiver off again */
    set_trx_state(CMD_TRX_OFF);

#ifndef TRX_REG_RAW_VALUE
    /*
     * Scale ED result.
     * Clip values to 0xFF if > -35dBm
     */
    if (ed_value > CLIP_VALUE_REG)
    {
        ed_value = 0xFF;
    }
    else
    {
        ed_value = (uint8_t)(((uint16_t)ed_value * 0xFF) / CLIP_VALUE_REG);
    }
#endif

    return ed_value;
}
Example #5
0
/**
 * @brief Perform a single ED measurement
 *
 * @return ed_value Result of the measurement
 *         If the build switch TRX_REG_RAW_VALUE is defined, the transceiver's
 *         register value is returned.
 */
uint8_t tfa_ed_sample(void)
{
    trx_irq_reason_t trx_irq_cause;
    uint8_t ed_value;
    tal_trx_status_t trx_status;

    /* Make sure that receiver is switched on. */
    do
    {
        trx_status = set_trx_state(CMD_RX_ON);
    }
    while (trx_status != RX_ON);

    /*
     * Disable the transceiver interrupts to prevent frame reception
     * while performing ED scan.
     */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE);

    /* Write dummy value to start measurement. */
    pal_trx_reg_write(RG_PHY_ED_LEVEL, 0xFF);

    /* Wait for ED measurement completion. */
    pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(ED_SAMPLE_DURATION_SYM));
    do
    {
        trx_irq_cause = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS);
    }
    while ((trx_irq_cause & TRX_IRQ_CCA_ED_READY) != TRX_IRQ_CCA_ED_READY);

    /* Read the ED Value. */
    ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL);

#ifndef TRX_REG_RAW_VALUE
    /*
     * Scale ED result.
     * Clip values to 0xFF if > -35dBm
     */
    if (ed_value > CLIP_VALUE_REG)
    {
        ed_value = 0xFF;
    }
    else
    {
        ed_value = (uint8_t)(((uint16_t)ed_value * 0xFF) / CLIP_VALUE_REG);
    }
#endif

    /* Clear IRQ register */
    pal_trx_reg_read(RG_IRQ_STATUS);
    /* Enable reception agian */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
    /* Switch receiver off again */
    set_trx_state(CMD_TRX_OFF);

    return ed_value;
}
Example #6
0
/*
 * \brief Sets the transceiver to sleep
 *
 * This function sets the transceiver to sleep state.
 *
 * \param mode Defines sleep mode of transceiver SLEEP or PHY_TRX_OFF)
 *
 * \return   TAL_BUSY - The transceiver is busy in TX or RX
 *           MAC_SUCCESS - The transceiver is put to sleep
 *           TAL_TRX_ASLEEP - The transceiver is already asleep
 *           MAC_INVALID_PARAMETER - The specified sleep mode is not supported
 */
retval_t tal_trx_sleep(sleep_mode_t mode)
{
	tal_trx_status_t trx_status;

	/* Current transceiver only supports SLEEP_MODE_1 mode. */
	if (SLEEP_MODE_1 != mode) {
		return MAC_INVALID_PARAMETER;
	}

	if (tal_trx_status == TRX_SLEEP) {
		return TAL_TRX_ASLEEP;
	}

	/* Device can be put to sleep only when the TAL is in IDLE state. */
	if (TAL_IDLE != tal_state) {
		return TAL_BUSY;
	}

	tal_rx_on_required = false;

	/*
	 * First set trx to TRX_OFF.
	 * If trx is busy, like ACK transmission, do not interrupt it.
	 */
	do {
		trx_status = set_trx_state(CMD_TRX_OFF);
	} while (trx_status != TRX_OFF);

#ifndef NO_32KHZ_CRYSTAL
	/* Do not set to SLEEP to keep clock source for symbol counter alive. */
	trx_status = set_trx_state(CMD_SLEEP);
#else
	/* Pretend that trx is in SLEEP - for this function only. */
	trx_status = TRX_SLEEP;
#endif

#ifdef ENABLE_FTN_PLL_CALIBRATION

	/*
	 * Stop the calibration timer now.
	 * The timer will be restarted during wake-up.
	 */
	pal_timer_stop(TAL_CALIBRATION);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */

	if (trx_status == TRX_SLEEP) {
#ifdef STB_ON_SAL
		stb_restart();
#endif
		return MAC_SUCCESS;
	} else {
		/* State could not be set due to TAL_BUSY state. */
		return TAL_BUSY;
	}
}
Example #7
0
File: tal_ed.c Project: bswe/6.1
/*
 * \brief Starts ED Scan
 *
 * This function starts an ED Scan for the scan duration specified by the
 * MAC layer.
 *
 * \param scan_duration Specifies the ED scan duration in symbols
 *
 * \return MAC_SUCCESS - ED scan duration timer started successfully
 *         TAL_BUSY - TAL is busy servicing the previous request from MAC
 *         TAL_TRX_ASLEEP - Transceiver is currently sleeping
 *         FAILURE otherwise
 */
retval_t tal_ed_start(uint8_t scan_duration)
{
    /*
     * Check if the TAL is in idle state. Only in idle state it can
     * accept and ED request from the MAC.
     */
    if (TAL_IDLE != tal_state)
    {
        if (tal_trx_status == TRX_SLEEP)
        {
            return TAL_TRX_ASLEEP;
        }
        else
        {
            Assert("TAL is TAL_BUSY" == 0);
            return TAL_BUSY;
        }
    }

    /*
     * Disable the transceiver interrupts to prevent frame reception
     * while performing ED scan.
     */
    pal_trx_irq_dis();  /* Disable transceiver main interrupt. */
    set_trx_state(CMD_FORCE_PLL_ON);
    pal_trx_reg_read(RG_IRQ_STATUS);        /* Clear existing interrupts */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE);
    pal_trx_irq_init((FUNC_PTR)trx_ed_irq_handler_cb);
    pal_trx_bit_write(SR_IRQ_MASK, TRX_IRQ_CCA_ED_READY); /* enable interrupt */
    pal_trx_irq_en();   /* Enable main transceiver interrupt. */

    /* Make sure that receiver is switched on. */
    if (set_trx_state(CMD_RX_ON) != RX_ON)
    {
        /* Restore previous configuration */
        pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
        pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
        pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); /* enable TRX_END interrupt */
        pal_trx_irq_en();   /* Enable main transceiver interrupt. */

        return FAILURE;
    }

    // write dummy value to start measurement
    pal_trx_reg_write(RG_PHY_ED_LEVEL, 0xFF);

    /* Perform ED in TAL_ED_RUNNING state. */
    tal_state = TAL_ED_RUNNING;

    max_ed_level = 0;   // reset max value

    sampler_counter = CALCULATE_SYMBOL_TIME_SCAN_DURATION(scan_duration) / ED_SAMPLE_DURATION_SYM;

    return MAC_SUCCESS;
}
/**
 * @brief Generates a 16-bit random number used as initial seed for srand()
 *
 * This function generates a 16-bit random number by means of using the
 * Random Number Generator from the transceiver.
 * The Random Number Generator generates 2-bit random values. These 2-bit
 * random values are concatenated to the required 16-bit random seed.
 *
 * The generated random 16-bit number is feed into function srand()
 * as initial seed.
 *
 * The transceiver state is initally set to RX_ON.
 * After the completion of the random seed generation, the
 * trancseiver is set to TRX_OFF.
 *
 * As a prerequisite the preamble detector must not be disabled.
 *
 * Also in case the function is called from a different state than TRX_OFF,
 * additional trx state handling is required, such as reading the original
 * value and restoring this state after finishing the sequence.
 * Since in our case the function is called from TRX_OFF, this is not required
 * here.
 */
void tal_generate_rand_seed(void)
{
    uint16_t seed = 0;
    uint8_t cur_random_val = 0;

    /* RPC could influence the randomness; therefore disable it here. */
    uint8_t previous_RPC_value = pal_trx_reg_read(RG_TRX_RPC);
    pal_trx_reg_write(RG_TRX_RPC, 0xC1);

    /*
     * We need to disable TRX IRQs while generating random values in RX_ON,
     * we do not want to receive frames at this point of time at all.
     */
    ENTER_TRX_REGION();

    /* Ensure that PLL has locked and receive mode is reached. */
    tal_trx_status_t trx_state;
    do
    {
        trx_state = set_trx_state(CMD_RX_ON);
    }
    while (trx_state != RX_ON);

    /* Ensure that register bit RX_PDT_DIS is set to 0. */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);

    /*
     * The 16-bit random value is generated from various 2-bit random values.
     */
    for (uint8_t i = 0; i < 8; i++)
    {
        /* Now we can safely read the 2-bit random number. */
        cur_random_val = pal_trx_bit_read(SR_RND_VALUE);
        seed = seed << 2;
        seed |= cur_random_val;
        PAL_WAIT_1_US();    // wait that the random value gets updated
    }

    set_trx_state(CMD_FORCE_TRX_OFF);

    /*
     * Now we need to clear potential pending TRX IRQs and
     * enable the TRX IRQs again.
     */
    pal_trx_reg_read(RG_IRQ_STATUS);
    pal_trx_irq_flag_clr();
    LEAVE_TRX_REGION();

    /* Set the seed for the random number generator. */
    srand(seed);

    /* Restore RPC settings. */
    pal_trx_reg_write(RG_TRX_RPC, previous_RPC_value);
}
Example #9
0
/**
 * @brief Perform a CCA
 *
 * This function performs a CCA request.
 *
 * @return phy_enum_t PHY_IDLE or PHY_BUSY
 */
phy_enum_t tfa_cca_perform(void)
{
    tal_trx_status_t trx_status;
    uint8_t cca_status;
    uint8_t cca_done;

    /* Ensure that trx is not in SLEEP for register access */
    do
    {
        trx_status = set_trx_state(CMD_TRX_OFF);
    }
    while (trx_status != TRX_OFF);

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

    /* Set trx to rx mode. */
    do
    {
        trx_status = set_trx_state(CMD_RX_ON);
    }
    while (trx_status != RX_ON);

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

    /* wait until CCA is done */
    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_COMPLETED);

    set_trx_state(CMD_TRX_OFF);

    /* Check if channel was idle or busy. */
    if (pal_trx_bit_read(SR_CCA_STATUS) == CCA_CH_IDLE)
    {
        cca_status = PHY_IDLE;
    }
    else
    {
        cca_status = PHY_BUSY;
    }

    /* Enable frame reception again. */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);

    return (phy_enum_t)cca_status;
}
Example #10
0
/*
 * \brief Write all shadow PIB variables to the transceiver
 *
 * This function writes all shadow PIB variables to the transceiver.
 * It is assumed that the radio does not sleep.
 */
void write_all_tal_pib_to_trx(void)
{
	uint8_t *ptr_to_reg;

	ptr_to_reg = (uint8_t *)&tal_pib.PANId;
	for (uint8_t i = 0; i < 2; i++) {
		trx_reg_write((RG_PAN_ID_0 + i), *ptr_to_reg);
		ptr_to_reg++;
	}

	ptr_to_reg = (uint8_t *)&tal_pib.IeeeAddress;
	for (uint8_t i = 0; i < 8; i++) {
		trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg);
		ptr_to_reg++;
	}

	ptr_to_reg = (uint8_t *)&tal_pib.ShortAddress;
	for (uint8_t i = 0; i < 2; i++) {
		trx_reg_write((RG_SHORT_ADDR_0 + i), *ptr_to_reg);
		ptr_to_reg++;
	}

	/* Configure TX_ARET; CSMA and CCA */
	trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode);

#ifdef SW_CONTROLLED_CSMA

	/*
	 * If receiver is enabled during backoff periods,
	 * CSMA and frame re-transmissions are handled by software.
	 * Setup trx for immediate transmission.
	 */
	trx_bit_write(SR_MAX_FRAME_RETRIES, 0);
	trx_bit_write(SR_MAX_CSMA_RETRIES, 7);
#else
	trx_bit_write(SR_MIN_BE, tal_pib.MinBE);
	trx_bit_write(SR_MAX_BE, tal_pib.MaxBE);
#endif

	trx_bit_write(SR_AACK_I_AM_COORD, tal_pib.PrivatePanCoordinator);

	/* set phy parameter */

	apply_channel_page_configuration(tal_pib.CurrentPage);

	{
		uint8_t reg_value;

		reg_value = convert_phyTransmitPower_to_reg_value(
				tal_pib.TransmitPower);
		trx_reg_write(RG_PHY_TX_PWR, reg_value);
	}

#ifdef PROMISCUOUS_MODE
	if (tal_pib.PromiscuousMode) {
		set_trx_state(CMD_RX_ON);
	}

#endif
}
Example #11
0
/*
 * \brief Scan done
 *
 * This function updates the max_ed_level and invokes the callback function
 * tal_ed_end_cb().
 *
 * \param parameter unused callback parameter
 */
void ed_scan_done(void)
{
	trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
	trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
	trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); /* enable TRX_END
	                                              * interrupt */
	pal_trx_irq_en(); /* Enable transceiver main interrupt. */

	tal_state = TAL_IDLE; /* ed scan is done */
	set_trx_state(CMD_RX_AACK_ON);

#ifndef TRX_REG_RAW_VALUE

	/*
	 * Scale ED result.
	 * Clip values to 0xFF if > -35dBm
	 */
	if (max_ed_level > CLIP_VALUE_REG) {
		max_ed_level = 0xFF;
	} else {
		max_ed_level
			= (uint8_t)(((uint16_t)max_ed_level *
				0xFF) / CLIP_VALUE_REG);
	}
#endif
	tal_ed_end_cb(max_ed_level);
}
Example #12
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;

    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 ((tal_state == TAL_TX_AUTO) || (tal_state == TAL_TX_BASIC))
        {
            /* Switch to transceiver's default state: switch receiver on. */
            set_trx_state(CMD_RX_AACK_ON);

            handle_tx_end_irq();            // see tal_tx.c
        }
        else   /* Other tal_state than TAL_TX_... */
        {
            /* Handle rx done interrupt. */
            handle_received_frame_irq();    // see tal_rx.c
        }
    }

}/* trx_irq_handler_cb() */
Example #13
0
static void handle_received_frame_irq(void)
{
	/* Actual frame length of received frame. */
	uint8_t phy_frame_len;

	uint8_t *rx_frame_ptr = at86rfx_rx_buffer;

	/* Perform FCS check for frame validation */
	if (CRC16_NOT_VALID == pal_trx_bit_read(SR_RX_CRC_VALID)) {
		return;
	}

	/* Get frame length from transceiver. */
	pal_trx_frame_read(&phy_frame_len, LENGTH_FIELD_LEN);

	/* Check for valid frame length. */
	if (phy_frame_len > PHY_MAX_LENGTH) {
		return;
	}

	/* Frame read from transceiver buffer. */
	pal_trx_frame_read(rx_frame_ptr, LENGTH_FIELD_LEN + phy_frame_len);

	/* Set flag indicating received frame to be handled. */
	at86rfx_frame_rx = true;

	set_trx_state(CMD_RX_ON);
}
Example #14
0
/*
 * \brief Scan done
 *
 * This function updates the max_ed_level and invokes the callback function
 * tal_ed_end_cb().
 *
 * \param parameter unused callback parameter
 */
void ed_scan_done(void)
{
	/* Restore previous configuration */
	trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
	trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

	tal_state = TAL_IDLE; /* ed scan is done */
	set_trx_state(CMD_RX_AACK_ON);

#ifndef TRX_REG_RAW_VALUE

	/*
	 * Scale ED result.
	 * Clip values to 0xFF if > -35dBm
	 */
	if (max_ed_level > CLIP_VALUE_REG) {
		max_ed_level = 0xFF;
	} else {
		max_ed_level
			= (uint8_t)(((uint16_t)max_ed_level *
				0xFF) / CLIP_VALUE_REG);
	}

#endif
	tal_ed_end_cb(max_ed_level);
}
Example #15
0
void tal_tx_beacon(frame_info_t *tx_frame)
{
	tal_trx_status_t trx_status;

	/* Set pointer to actual mpdu to be downloaded to the transceiver. */
	uint8_t *tal_beacon_to_tx = tx_frame->mpdu;

	/* Avoid that the beacon is transmitted while other transmision is
	 * on-going. */
	if (tal_state == TAL_TX_AUTO) {
		Assert(
				"trying to transmit beacon while ongoing transmission" ==
				0);
		return;
	}

	/* Send the pre-created beacon frame to the transceiver. */
	do {
		trx_status = set_trx_state(CMD_PLL_ON);
#if (_DEBUG_ > 1)
		if (trx_status != PLL_ON) {
			Assert("PLL_ON failed for beacon transmission" == 0);
		}
#endif
	} while (trx_status != PLL_ON);

	/* \TODO wait for talbeaconTxTime */

	pal_trx_irq_dis();

	/* Toggle the SLP_TR pin triggering transmission. */
	TRX_SLP_TR_HIGH();
	PAL_WAIT_65_NS();
	TRX_SLP_TR_LOW();

	/*
	 * Send the frame to the transceiver.
	 * Note: The PhyHeader is the first byte of the frame to
	 * be sent to the transceiver and this contains the frame
	 * length.
	 * The actual length of the frame to be downloaded
	 * (parameter two of trx_frame_write)
	 * is
	 * 1 octet frame length octet
	 * + n octets frame (i.e. value of frame_tx[0])
	 * + 1 extra octet (see datasheet)
	 * - 2 octets FCS
	 */
	trx_frame_write(tal_beacon_to_tx, tal_beacon_to_tx[0]);

	tal_beacon_transmission = true;

#ifndef NON_BLOCKING_SPI
	pal_trx_irq_en();
#endif
#ifdef TX_OCTET_COUNTER
	tal_tx_octet_cnt += PHY_OVERHEAD + LENGTH_FIELD_LEN +
			tal_beacon_to_tx[0];
#endif
}
Example #16
0
/**
 * @brief Starts continuous transmission on current channel
 */
void tfa_continuous_tx_start(continuous_tx_mode_t tx_mode)
{
    uint8_t txcwdata[127];

    pal_trx_bit_write(SR_TX_AUTO_CRC_ON, TX_AUTO_CRC_DISABLE);
    pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
    pal_trx_reg_write(0x0176, 0x0F);     /*TST_CTRL_DIGI*/
    /* Here: use 2MBPS mode for PSD measurements.
     * Omit the two following lines, if 250k mode is desired for PRBS mode. */
    pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_2MBPS);
    pal_trx_reg_write(RG_RX_CTRL, 0xA7);
    if (tx_mode == CW_MODE)
    {
        txcwdata[0] = 1;    // length
        // Step 11 - frame buffer write access
        txcwdata[1] = 0x00; // f=fch-0.5 MHz; set value to 0xFF for f=fch+0.5MHz
        pal_trx_frame_write(txcwdata, 2);
    }
    else    // PRBS mode
    {
        txcwdata[0] = 127;   // = max length
        for (uint8_t i = 1; i < 128; i++)
        {
            txcwdata[i] = (uint8_t)rand();
        }
        pal_trx_frame_write(txcwdata, 128);
    }

    pal_trx_reg_write(RG_PART_NUM, 0x54);
    pal_trx_reg_write(RG_PART_NUM, 0x46);
    set_trx_state(CMD_PLL_ON);
    PAL_SLP_TR_HIGH();
    PAL_SLP_TR_LOW();
}
Example #17
0
/**
 * @brief Starts ED Scan
 *
 * This function starts an ED Scan for the scan duration specified by the
 * MAC layer.
 *
 * @param scan_duration Specifies the ED scan duration in symbols
 *
 * @return MAC_SUCCESS - ED scan duration timer started successfully
 *         TAL_BUSY - TAL is busy servicing the previous request from MAC
 *         TAL_TRX_ASLEEP - Transceiver is currently sleeping
 *         FAILURE otherwise
 */
retval_t tal_ed_start(uint8_t scan_duration)
{
    /*
     * Check if the TAL is in idle state. Only in idle state it can
     * accept and ED request from the MAC.
     */
    if (TAL_IDLE != tal_state)
    {
        if (tal_trx_status == TRX_SLEEP)
        {
            return TAL_TRX_ASLEEP;
        }
        else
        {
            ASSERT("TAL is TAL_BUSY" == 0);
            return TAL_BUSY;
        }
    }

    set_trx_state(CMD_FORCE_PLL_ON);
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_DISABLE);
    pal_trx_irq_flag_clr_cca_ed();
    pal_trx_irq_init_cca_ed((FUNC_PTR)trx_ed_irq_handler_cb);
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_CCA_ED_READY);

    /* Make sure that receiver is switched on. */
    if (set_trx_state(CMD_RX_ON) != RX_ON)
    {
        /* Restore previous configuration */
        pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);
        pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

        return FAILURE;
    }

    /* Perform ED in TAL_ED_RUNNING state. */
    tal_state = TAL_ED_RUNNING;

    max_ed_level = 0;   // reset max value

    sampler_counter = CALCULATE_SYMBOL_TIME_SCAN_DURATION(scan_duration) / ED_SAMPLE_DURATION_SYM;

    // write dummy value to start measurement
    pal_trx_reg_write(RG_PHY_ED_LEVEL, 0xFF);

    return MAC_SUCCESS;
}
Example #18
0
/**
 * @brief Generates a 16-bit random number used as initial seed for srand()
 *
 * This function generates a 16-bit random number by means of using the
 * Random Number Generator from the transceiver.
 * The Random Number Generator generates 2-bit random values. These 2-bit
 * random values are concatenated to the required 16-bit random seed.
 *
 * The generated random 16-bit number is feed into function srand()
 * as initial seed.
 *
 * The transceiver state is initally set to RX_ON.
 * After the completion of the random seed generation, the
 * trancseiver is set to TRX_OFF.
 *
 * As a prerequisite the preamble detector must not be disabled.
 *
 * Also in case the function is called from a different state than TRX_OFF,
 * additional trx state handling is required, such as reading the original
 * value and restoring this state after finishing the sequence.
 * Since in our case the function is called from TRX_OFF, this is not required
 * here.
 */
void tal_generate_rand_seed(void)
{
    uint16_t seed = 0;
    uint8_t cur_random_val = 0;

    /* Ensure that PLL has locked and receive mode is reached. */
    tal_trx_status_t trx_state;
    do
    {
        trx_state = set_trx_state(CMD_RX_ON);
    }
    while (trx_state != RX_ON);

    /* Ensure that register bit RX_PDT_DIS is set to 0. */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE);

    /*
     * We need to disable TRX IRQs while generating random values in RX_ON,
     * we do not want to receive frames at this point of time at all.
     */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_NONE);

    /*
     * The 16-bit random value is generated from various 2-bit random values.
     */
    for (uint8_t i = 0; i < 8; i++)
    {
        /* Now we can safely read the 2-bit random number. */
        cur_random_val = pal_trx_bit_read(SR_RND_VALUE);
        seed = seed << 2;
        seed |= cur_random_val;
        PAL_WAIT_1_US();    // wait that the random value gets updated
    }

    set_trx_state(CMD_FORCE_TRX_OFF);

    /*
     * Now we need to clear potential pending TRX IRQs and
     * enable the TRX IRQs again.
     */
    pal_trx_reg_write(RG_IRQ_STATUS, 0xFF);
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

    /* Set the seed for the random number generator. */
    srand(seed);
}
Example #19
0
/*
 * \brief Starts continuous transmission on current channel
 *
 * \param tx_mode Mode of continuous transmission (CW or PRBS)
 * \param random_content Use random content if true
 *
 * The comment 'step #' refers to the step mentioned in the RF212's datasheet.
 */
void tfa_continuous_tx_start(continuous_tx_mode_t tx_mode, bool random_content)
{
    uint8_t txcwdata[128];
    uint8_t i;

    // step 3,6: Channel is assumed to be set before
    pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
    // step 7: Enable continuous transmission - step #1
    pal_trx_reg_write(0x36, 0x0F);
    if (tx_mode == CW_MODE)
    {
        // step 8: Register access: CW at Fc +/- 0.1 MHz
        pal_trx_reg_write(RG_TRX_CTRL_2, 0x0A);     // 400 kbit mode, step 8
        txcwdata[0] = 1;    // length
        txcwdata[1] = 0;
        // step 9: Frame buffer access
        pal_trx_frame_write(txcwdata, 2);
    }
    else    // PRBS mode
    {
        // step 8:
        /*
         * Step 8 is not explicitly written here, because the proper
         * value is set during reset or by updating the Channel Page.
         * After finishing CW/PRBS another reset is performed with
         * parameter set_default_pib set to false, which restores the
         * original value based on the current Channel Page.
         *
         * I.e., in order to use PRBS with a specific data rate,
         * the Channel Page needs to be udpated before starting PRBS.
         */

        txcwdata[0] = 127;   // = max length
        for (i = 1; i < 128; i++)
        {
            if (random_content)
            {
                txcwdata[i] = (uint8_t)rand();
            }
            else
            {
                txcwdata[i] = 0;
            }
        }
        // step 9: Frame buffer access
        pal_trx_frame_write(txcwdata, 128);
    }
    // step 10: Enable continuous transmission - step #2
    pal_trx_reg_write(RG_PART_NUM, 0x54);
    // step 11: Enable continuous transmission - step #3
    pal_trx_reg_write(RG_PART_NUM, 0x46);
    // step 12, 13: Stwitch PLL on
    set_trx_state(CMD_PLL_ON);
    // step 14: Initiate transmission using SLP_TR line
    PAL_SLP_TR_HIGH();
    PAL_SLP_TR_LOW();
}
Example #20
0
/**
 * @brief Sets the transceiver to sleep
 *
 * This function sets the transceiver to sleep state.
 *
 * @param mode Defines sleep mode of transceiver SLEEP or PHY_TRX_OFF)
 *
 * @return   TAL_BUSY - The transceiver is busy in TX or RX
 *           MAC_SUCCESS - The transceiver is put to sleep
 *           TAL_TRX_ASLEEP - The transceiver is already asleep
 *           MAC_INVALID_PARAMETER - The specified sleep mode is not supported
 */
retval_t tal_trx_sleep(sleep_mode_t mode)
{
    tal_trx_status_t trx_status;

    /* Current transceiver only supports SLEEP_MODE_1 mode. */
    if (SLEEP_MODE_1 != mode)
    {
        return MAC_INVALID_PARAMETER;
    }

    if (tal_trx_status == TRX_SLEEP)
    {
        return TAL_TRX_ASLEEP;
    }

    /* Device can be put to sleep only when the TAL is in IDLE state. */
    if (TAL_IDLE != tal_state)
    {
        return TAL_BUSY;
    }

    /*
     * First set trx to TRX_OFF.
     * If trx is busy, like ACK transmission, do not interrupt it.
     */
    do
    {
        trx_status = set_trx_state(CMD_TRX_OFF);
    } while (trx_status != TRX_OFF);

    pal_timer_source_select(TMR_CLK_SRC_DURING_TRX_SLEEP);

    trx_status = set_trx_state(CMD_TRX_SLEEP);

    if (trx_status == TRX_SLEEP)
    {
        return MAC_SUCCESS;
    }
    else
    {
        /* State could not be set due to TAL_BUSY state. */
        return TAL_BUSY;
    }
}
Example #21
0
static void handle_tx_end_irq(void)
{
	// Trx has handled the entire transmission incl. CSMA
	tal_state = TAL_TX_END;	// Further handling is done by tx_end_handling()

	/*
	 * After transmission has finished, switch receiver on again.
	 */
	set_trx_state(CMD_RX_ON);
}
Example #22
0
void tal_tx_beacon(frame_info_t *tx_frame)
{
	tal_trx_status_t trx_status;

	/* Set pointer to actual mpdu to be downloaded to the transceiver. */
	uint8_t *tal_beacon_to_tx = tx_frame->mpdu;

	/* Avoid that the beacon is transmitted while other transmision is
	 *on-going. */
	if (tal_state == TAL_TX_AUTO) {
		Assert(
				"trying to transmit beacon while ongoing transmission" ==
				0);
		return;
	}

	/* Send the pre-created beacon frame to the transceiver. */
	do {
		trx_status = set_trx_state(CMD_PLL_ON);
#if (_DEBUG_ > 1)
		if (trx_status != PLL_ON) {
			Assert("PLL_ON failed for beacon transmission" == 0);
		}

#endif
	} while (trx_status != PLL_ON);

	/* \TODO wait for talbeaconTxTime */

	ENTER_CRITICAL_REGION(); /* prevent from buffer underrun */

	/* Toggle the SLP_TR pin triggering transmission. */
	TRX_SLP_TR_HIGH();
	PAL_WAIT_65_NS();
	TRX_SLP_TR_LOW();

	/*
	 * Send the frame to the transceiver.
	 * Note: The PhyHeader is the first byte of the frame to
	 * be sent to the transceiver and this contains the frame
	 * length.
	 * The actual length of the frame to be downloaded
	 * (parameter two of trx_frame_write)
	 * is
	 * 1 octet frame length octet
	 * + n octets frame (i.e. value of frame_tx[0])
	 * - 2 octets FCS
	 */
	trx_frame_write(tal_beacon_to_tx, tal_beacon_to_tx[0] - 1);

	tal_beacon_transmission = true;

	LEAVE_CRITICAL_REGION();
}
Example #23
0
/**
 * @brief Write all shadow PIB variables to the transceiver
 *
 * This function writes all shadow PIB variables to the transceiver.
 * It is assumed that the radio does not sleep.
 */
void write_all_tal_pib_to_trx(void)
{
    uint8_t *ptr_to_reg;

    ptr_to_reg = (uint8_t *)&tal_pib.PANId;
    for (uint8_t i = 0; i < 2; i++)
    {
        pal_trx_reg_write((RG_PAN_ID_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    ptr_to_reg = (uint8_t *)&tal_pib.IeeeAddress;
    for (uint8_t i = 0; i < 8; i++)
    {
        pal_trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    ptr_to_reg = (uint8_t *)&tal_pib.ShortAddress;
    for (uint8_t i = 0; i < 2; i++)
    {
        pal_trx_reg_write((RG_SHORT_ADDR_0 + i), *ptr_to_reg);
        ptr_to_reg++;
    }

    /* configure TX_ARET; CSMA and CCA */
    pal_trx_bit_write(SR_CCA_MODE, tal_pib.CCAMode);
    pal_trx_bit_write(SR_MIN_BE, tal_pib.MinBE);

    pal_trx_bit_write(SR_AACK_I_AM_COORD, tal_pib.PrivatePanCoordinator);

    /* set phy parameter */
    pal_trx_bit_write(SR_MAX_BE, tal_pib.MaxBE);

#ifdef HIGH_DATA_RATE_SUPPORT
    apply_channel_page_configuration(tal_pib.CurrentPage);
#endif

    pal_trx_bit_write(SR_CHANNEL, tal_pib.CurrentChannel);
    {
        uint8_t reg_value;

        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib.TransmitPower);
        pal_trx_bit_write(SR_TX_PWR, reg_value);
    }

#ifdef PROMISCUOUS_MODE
    if (tal_pib.PromiscuousMode)
    {
        set_trx_state(CMD_RX_ON);
    }
#endif
}
Example #24
0
/**
 * @brief Wakes up the transceiver from sleep
 *
 * This function awakes the transceiver from sleep state.
 *
 * @return   TAL_TRX_AWAKE - The transceiver is already awake
 *           MAC_SUCCESS - The transceiver is woken up from sleep
 *           FAILURE - The transceiver did not wake-up from sleep
 */
retval_t tal_trx_wakeup(void)
{
    tal_trx_status_t trx_status;

    if (tal_trx_status != TRX_SLEEP)
    {
        return TAL_TRX_AWAKE;
    }

#ifdef ENABLE_FTN_PLL_CALIBRATION
    {
        retval_t timer_status;

        /*
         * Calibration timer has been stopped when going to sleep,
         * so it needs to be restarted.
         * All other state changes except via sleep that are ensuring
         * implicit filter tuning and pll calibration are ignored.
         * Therefore the calibration timer needs to be restarted for
         * to those cases.
         * This is handled in file tal.c.
         */

        /* Start periodic calibration timer.*/
        timer_status = pal_timer_start(TAL_CALIBRATION,
                                       TAL_CALIBRATION_TIMEOUT_US,
                                       TIMEOUT_RELATIVE,
                                       (FUNC_PTR)calibration_timer_handler_cb,
                                       NULL);

        if (timer_status != MAC_SUCCESS)
        {
            ASSERT("PLL calibration timer start problem" == 0);
        }
    }
#endif  /* ENABLE_FTN_PLL_CALIBRATION */

    trx_status = set_trx_state(CMD_TRX_OFF);

    if (trx_status == TRX_OFF)
    {
        pal_timer_source_select(TMR_CLK_SRC_DURING_TRX_AWAKE);
        return MAC_SUCCESS;
    }
    else
    {
        return FAILURE;
    }
}
Example #25
0
static void generate_rand_seed(void)
{
	uint16_t seed = 0;
	uint8_t cur_random_val = 0;

	set_trx_state(CMD_RX_ON);

	/*
	 * We need to disable TRX IRQs while generating random values in RX_ON,
	 * we do not want to receive frames at this point of time at all.
	 */
	ENTER_TRX_REGION();

	/*
	 * The 16-bit random value is generated from various 2-bit random values.
	 */
	for (uint8_t i = 0; i < 8; i++) {
		/* Now we can safely read the 2-bit random number. */
		cur_random_val = pal_trx_bit_read(SR_RND_VALUE);
		seed = seed << 2;
		seed |= cur_random_val;
	}

	set_trx_state(CMD_FORCE_TRX_OFF);

	/*
	 * Now we need to clear potential pending TRX IRQs and
	 * enable the TRX IRQs again.
	 */
	pal_trx_reg_read(RG_IRQ_STATUS);
	CLEAR_TRX_IRQ();
	LEAVE_TRX_REGION();

	/* Set the seed for the random number generator. */
	srand(seed);
}
Example #26
0
/**
 * \brief This function is called to initiate the RX_ON test 
 * The transceiver is put into the RX_ON mode and no requests are handled until 
 * this mode is stopped.
 * On the receptor ,the mode is stopped only on reception of the RX_ON_STOP 
 * command which is sent without ack_req
 * \param start_stop_param Indicates whether the request is to 
 * Start or Stop the mode
 */
void rx_on_test(bool start_stop_param)
{


	if(start_stop_param)
	{
		if(node_info.main_state != PER_TEST_RECEPTOR)
		{
			
			set_trx_state(CMD_RX_ON);
			curr_trx_config_params.trx_state = RX_ON ;
		}
    /* For receptor the mode is switched on successful transmission of 
	 * the confirmation message*/
		rx_on_mode = true;
	}
	else
	{
		set_trx_state(CMD_RX_AACK_ON);
		curr_trx_config_params.trx_state = RX_AACK_ON ;
		rx_on_mode = false;
	}
	usr_rx_on_confirm(MAC_SUCCESS,start_stop_param);
}
Example #27
0
void tx_frame_config(void)
{
	tal_trx_status_t trx_status;

	/* Set trx to PLL_ON state to initiate transmission procedure */
	do {
		trx_status = set_trx_state(CMD_PLL_ON);
	} while (trx_status != PLL_ON);

	tal_state = TAL_TX_AUTO;

	/* Toggle the SLP_TR pin triggering transmission. */
	SLP_TR_HIGH();
	WAIT_65_NS();
	SLP_TR_LOW();
}
Example #28
0
/*
 * \brief handling of CCA result.
 */
void cca_done_handling(void)
{
	set_trx_state(CMD_PLL_ON); /* leave RX_ON */
	/* Restore IRQ handling */
	trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
	trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);
	trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); /* Enable frame reception.
	                                         **/

	/* Check if channel was idle or busy */
	if (trx_bit_read(SR_CCA_STATUS) == CCA_STATUS_CHANNEL_IS_IDLE) {
		tx_frame();
	} else {
		tal_state = TAL_CSMA_CONTINUE;
	}
}
Example #29
0
/*
 * \brief Continues CSMA; handles next CSMA retry.
 */
void csma_continue(void)
{
	NB++;
	if (NB > tal_pib.MaxCSMABackoffs) {
		trx_trac_status = TRAC_CHANNEL_ACCESS_FAILURE;
		tal_state = TAL_TX_DONE;
		set_trx_state(CMD_RX_AACK_ON);
	} else {
		BE++;
		if (BE > tal_pib.MaxBE) {
			BE = tal_pib.MaxBE;
		}

		/* Start backoff timer to trigger CCA */
		start_backoff();
	}
}
Example #30
0
/**
 * \brief Transmits the frame over-the-air
 */
static void tx_frame(void)
{
    tal_trx_status_t trx_status;

    /*
     * Trigger transmission
     * In case of an ongoing reception,
     * the incoming frame is handled first within ISR.
     */
    do
    {
        trx_status = set_trx_state(CMD_TX_ARET_ON);
    }
    while (trx_status != TX_ARET_ON);

    pal_trx_irq_dis();

    /* Toggle the SLP_TR pin triggering transmission. */
    PAL_SLP_TR_HIGH();
    PAL_WAIT_65_NS();
    PAL_SLP_TR_LOW();

    /*
     * Send the frame to the transceiver.
     * Note: The PhyHeader is the first byte of the frame to
     * be sent to the transceiver and this contains the frame
     * length.
     * The actual length of the frame to be downloaded
     * (parameter two of pal_trx_frame_write)
     * is
     * 1 octet frame length octet
     * + n octets frame (i.e. value of frame_tx[0])
     * + 1 extra octet (see datasheet)
     * - 2 octets FCS
     */
    pal_trx_frame_write(tal_frame_to_tx, tal_frame_to_tx[0]);

    tal_state = TAL_TX_AUTO;

#ifndef NON_BLOCKING_SPI
    pal_trx_irq_en();
#endif
#ifdef TX_OCTET_COUNTER
    tal_tx_octet_cnt += PHY_OVERHEAD + LENGTH_FIELD_LEN + tal_frame_to_tx[0];
#endif
}