/**
 * @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);
}
/**
 * @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);
}
Exemple #3
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);
}
Exemple #4
0
/**
 * @brief Sets transceiver state
 *
 * @param trx_cmd needs to be one of the trx commands
 *
 * @return current trx state
 */
tal_trx_status_t set_trx_state(trx_cmd_t trx_cmd)
{
    if (tal_trx_status == TRX_SLEEP)
    {
        uint8_t bit_status;

        PAL_SLP_TR_LOW();
        do
        {
            bit_status = pal_trx_bit_read(SR_TRX_STATUS);
        } while (bit_status != TRX_OFF);

        if ((trx_cmd == CMD_TRX_OFF) || (trx_cmd == CMD_FORCE_TRX_OFF))
        {
            tal_trx_status = TRX_OFF;
            return TRX_OFF;
        }
    }

    tal_trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);

    switch (trx_cmd)    /* new state */
    {
        case CMD_TRX_SLEEP:
            pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);

            {
                uint16_t rand_value;

                /*
                 * Init the SEED value of the CSMA backoff algorithm.
                 */
                rand_value = (uint16_t)rand();
                pal_trx_reg_write(RG_CSMA_SEED_0, (uint8_t)rand_value);
                pal_trx_bit_write(SR_CSMA_SEED_1, (uint8_t)(rand_value >> 8));
            }

            PAL_WAIT_1_US();
            PAL_SLP_TR_HIGH();
            pal_timer_delay(TRX_OFF_TO_SLEEP_TIME);
            tal_trx_status = TRX_SLEEP;
            return TRX_SLEEP;   /* transceiver register cannot be read during TRX_SLEEP */
            //break; // do not use break, since it is unreachable

        case CMD_TRX_OFF:
            switch (tal_trx_status)
            {
                case TRX_OFF:
                    break;

                default:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);
                    PAL_WAIT_1_US();
                    break;
            }
            break;

        case CMD_FORCE_TRX_OFF:
            switch (tal_trx_status)
            {
                case TRX_OFF:
                    break;

                case TX_ARET_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
                    PAL_SLP_TR_HIGH();
                    pal_timer_delay(2);
                    PAL_SLP_TR_LOW();
                    break;

                default:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
                    PAL_WAIT_1_US();
                    break;
            }
            break;

        case CMD_PLL_ON:
            switch (tal_trx_status)
            {
                case PLL_ON:
                    break;

                case TRX_OFF:
                    switch_pll_on();
                    break;

                case RX_ON:
                case RX_AACK_ON:
                case TX_ARET_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
                    PAL_WAIT_1_US();
                    break;

                case BUSY_RX:
                case BUSY_TX:
                case BUSY_RX_AACK:
                case BUSY_TX_ARET:
                    /* do nothing if trx is busy */
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        case CMD_FORCE_PLL_ON:  /* software state */
            switch (tal_trx_status)
            {
                case RX_ON:
                case BUSY_RX:
                case RX_AACK_ON:
                case BUSY_RX_AACK:
                    ENTER_TRX_REGION();
                    pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
                    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
                    // clear trx irq in case a frame is received meanwhile
                    pal_trx_reg_read(RG_IRQ_STATUS);
                    pal_trx_irq_flag_clr();
                    LEAVE_TRX_REGION();
                    PAL_WAIT_1_US();
                    break;

                case BUSY_TX:
                    ENTER_TRX_REGION();
                    pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
                    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
                    LEAVE_TRX_REGION();
                    PAL_WAIT_1_US();
                    break;

                case BUSY_TX_ARET:
                    ENTER_TRX_REGION();
                    pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
                    PAL_SLP_TR_LOW();
                    pal_timer_delay(SLP_TR_TOGGLE_US);
                    PAL_SLP_TR_HIGH();
                    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
                    LEAVE_TRX_REGION();
                    PAL_WAIT_1_US();
                    break;

                case TRX_OFF:
                    switch_pll_on();
                    break;

                case PLL_ON:
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        case CMD_RX_ON:
            switch (tal_trx_status)
            {
                case RX_ON:
                    break;

                case PLL_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_ON);
                    PAL_WAIT_1_US();
                    break;

                case TRX_OFF:
                    switch_pll_on();
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_ON);
                    PAL_WAIT_1_US();
                    break;

                case RX_AACK_ON:
                case TX_ARET_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
                    PAL_WAIT_1_US();
                    // check if state change could be applied
                    tal_trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);
                    if (tal_trx_status != PLL_ON)
                    {
                        return tal_trx_status;
                    }
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_ON);
                    PAL_WAIT_1_US();
                    break;

                case BUSY_RX:
                case BUSY_TX:
                case BUSY_RX_AACK:
                case BUSY_TX_ARET:
                    /* do nothing if trx is busy */
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        case CMD_RX_AACK_ON:
            switch (tal_trx_status)
            {
                case RX_AACK_ON:
                    break;

                case PLL_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
                    PAL_WAIT_1_US();
                    break;

                case TRX_OFF:
                    switch_pll_on();// state change from TRX_OFF to RX_AACK_ON can be done directly, too
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
                    PAL_WAIT_1_US();
                    break;

                case TX_ARET_ON:
                case RX_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
                    PAL_WAIT_1_US();
                    // check if state change could be applied
                    tal_trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);
                    if (tal_trx_status != PLL_ON)
                    {
                        return tal_trx_status;
                    }
                    pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
                    PAL_WAIT_1_US();
                    break;

                case BUSY_RX:
                case BUSY_TX:
                case BUSY_RX_AACK:
                case BUSY_TX_ARET:
                    /* do nothing if trx is busy */
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        case CMD_TX_ARET_ON:
            switch (tal_trx_status)
            {
                case TX_ARET_ON:
                    break;

                case PLL_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_TX_ARET_ON);
                    PAL_WAIT_1_US();
                    break;

                case RX_ON:
                case RX_AACK_ON:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);
                    PAL_WAIT_1_US();
                    // check if state change could be applied
                    tal_trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);
                    if (tal_trx_status != PLL_ON)
                    {
                        return tal_trx_status;
                    }
                    pal_trx_reg_write(RG_TRX_STATE, CMD_TX_ARET_ON);
                    PAL_WAIT_1_US();
                    break;

                case TRX_OFF:
                    switch_pll_on();// state change from TRX_OFF to TX_ARET_ON can be done directly, too
                    pal_trx_reg_write(RG_TRX_STATE, CMD_TX_ARET_ON);
                    PAL_WAIT_1_US();
                    break;

                case BUSY_RX:
                case BUSY_TX:
                case BUSY_RX_AACK:
                case BUSY_TX_ARET:
                    /* do nothing if trx is busy */
                    break;

                default:
                    ASSERT("state transition not handled" == 0);
                    break;
            }
            break;

        default:
            /* CMD_NOP, CMD_TX_START */
            ASSERT("trx command not handled" == 0);
            break;
    }

    do
    {
        tal_trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);
    } while (tal_trx_status == STATE_TRANSITION_IN_PROGRESS);

    return tal_trx_status;
} /* set_trx_state() */
Exemple #5
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;
}
Exemple #6
-1
/*
 * \brief Generates a 16-bit random number used as initial seed for srand()
 *
 */
static void rf_generate_random_seed(void)
{
	uint16_t seed = 0;
	uint8_t cur_random_val = 0;

	/*
	 * 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();

	do
	{
		trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_TRX_OFF);
		
	} while (TRXCMD_TRX_OFF != rf233_status());

	do
	{
		/* Ensure that PLL has locked and receive mode is reached. */
		trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_PLL_ON);
		
	} while (TRXCMD_PLL_ON != rf233_status());
	do
	{
		trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_RX_ON);
		
	} while (TRXCMD_RX_ON != rf233_status());

	/* Ensure that register bit RX_PDT_DIS is set to 0. */
	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 = trx_bit_read(SR_RND_VALUE);
		seed = seed << 2;
		seed |= cur_random_val;
		delay_us(1); /* wait that the random value gets updated */
	}

	do
	{
		/* Ensure that PLL has locked and receive mode is reached. */
		trx_reg_write(RF233_REG_TRX_STATE, TRXCMD_TRX_OFF);		
	} while (TRXCMD_TRX_OFF != rf233_status());
	/*
	 * Now we need to clear potential pending TRX IRQs and
	 * enable the TRX IRQs again.
	 */
	trx_reg_read(RF233_REG_IRQ_STATUS);
	trx_irq_flag_clr();
	LEAVE_TRX_REGION();

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