Exemplo n.º 1
0
/**
 * @brief Internal TAL reset function
 *
 * @param set_default_pib Defines whether PIB values need to be set
 *                        to its default values
 *
 * @return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF and the
 *                 current device part number and version number are correct;
 *         FAILURE otherwise
 */
static retval_t internal_tal_reset(bool set_default_pib)
{
    if (trx_reset() != MAC_SUCCESS)
    {
        return FAILURE;
    }

    /*
     * Generate a seed for the random number generator in function rand().
     * This is required (for example) as seed for the CSMA-CA algorithm.
     */
    tal_generate_rand_seed();

    /* Configure the transceiver register values. */
    trx_config();

    if (set_default_pib)
    {
        /* Set the default PIB values */
        init_tal_pib(); /* implementation can be found in 'tal_pib.c' */
    }
    else
    {
        /* nothing to do - the current TAL PIB attribute values are used */
    }

    /*
     * Write all PIB values to the transceiver
     * that are needed by the transceiver itself.
     */
    write_all_tal_pib_to_trx(); /* implementation can be found in 'tal_pib.c' */

    /* Reset TAL variables. */
    tal_state = TAL_IDLE;

#ifdef BEACON_SUPPORT
    tal_csma_state = CSMA_IDLE;
#endif  /* BEACON_SUPPORT */

#if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
    tal_beacon_transmission = false;
#endif /* ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) */

    tal_rx_on_required = false;

    return MAC_SUCCESS;
}
Exemplo n.º 2
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)
    {
        /*
         * Since the wake-up procedure relies on the Awake IRQ and
         * the global interrupts may be disabled at this point of time,
         * we need to make sure that the global interrupts are enabled
         * during wake-up procedure.
         * Once the TRX is awake, the original state of the global interrupts
         * will be restored.
         */
        /* Reset wake-up interrupt flag. */
        tal_awake_end_flag = false;
        /* Set callback function for the awake interrupt. */
        pal_trx_irq_init(trx_irq_awake_handler_cb);
        /* The pending transceiver interrupts on the microcontroller are cleared. */
        pal_trx_irq_flag_clr();
        pal_trx_irq_en();     /* Enable transceiver main interrupt. */
        /* Save current state of global interrupts. */
        ENTER_CRITICAL_REGION();
        /* Force enabling of global interrupts. */
        ENABLE_GLOBAL_IRQ();
        /* Leave trx sleep mode. */
        PAL_SLP_TR_LOW();
        /* Poll wake-up interrupt flag until set within ISR. */
        while (!tal_awake_end_flag);
        /* Restore original state of global interrupts. */
        LEAVE_CRITICAL_REGION();
        /* Clear existing interrupts */
        pal_trx_reg_read(RG_IRQ_STATUS);
        /* Re-install default IRQ handler for main interrupt. */
        pal_trx_irq_init(trx_irq_handler_cb);
        /* Re-enable TRX_END interrupt */
        pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);
#if (ANTENNA_DIVERSITY == 1)
        /* Enable antenna diversity. */
        pal_trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE);
#endif

#ifdef EXT_RF_FRONT_END_CTRL
        /* Enable RF front end control */
        pal_trx_bit_write(SR_PA_EXT_EN, 1);
#endif

        tal_trx_status = TRX_OFF;
        if ((trx_cmd == CMD_TRX_OFF) || (trx_cmd == CMD_FORCE_TRX_OFF))
        {
            return TRX_OFF;
        }
    }
#ifdef ENABLE_DEEP_SLEEP
    else if (tal_trx_status == TRX_DEEP_SLEEP)
    {
        /* Leave trx sleep mode. */
        PAL_SLP_TR_LOW();
        /* Check if trx has left deep sleep. */
        tal_trx_status_t trx_state;
        do
        {
            trx_state = (tal_trx_status_t)pal_trx_reg_read(RG_TRX_STATUS);
        }
        while (trx_state != TRX_OFF);
        tal_trx_status = TRX_OFF;
        /* Using deep sleep, the transceiver's registers need to be restored. */
        trx_config();
        /*
         * Write all PIB values to the transceiver
         * that are needed by the transceiver itself.
         */
        write_all_tal_pib_to_trx(); /* implementation can be found in 'tal_pib.c' */
        if ((trx_cmd == CMD_TRX_OFF) || (trx_cmd == CMD_FORCE_TRX_OFF))
        {
            return TRX_OFF;
        }
    }
#endif

    switch (trx_cmd)    /* requested state */
    {
        case CMD_SLEEP:
#ifdef ENABLE_DEEP_SLEEP
            /* Fall through. */
        case CMD_DEEP_SLEEP:
#endif
            pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);

#if (ANTENNA_DIVERSITY == 1)
            /*
             *  Disable antenna diversity: to reduce the power consumption or
             *  avoid leakage current of an external RF switch during SLEEP.
             */
            pal_trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_DISABLE);
#endif
#ifdef EXT_RF_FRONT_END_CTRL
            /* Disable RF front end control */
            pal_trx_bit_write(SR_PA_EXT_EN, 0);
#endif
            /* Clear existing interrupts */
            pal_trx_reg_read(RG_IRQ_STATUS);
            /*
             * Enable Awake_end interrupt.
             * This is used for save wake-up from sleep later.
             */
            pal_trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE);

#ifdef ENABLE_DEEP_SLEEP
            if (trx_cmd == CMD_DEEP_SLEEP)
            {
                pal_trx_reg_write(RG_TRX_STATE, CMD_PREP_DEEP_SLEEP);
                tal_trx_status = TRX_DEEP_SLEEP;
            }
            else
            {
                /*
                 * Enable Awake_end interrupt.
                 * This is used for save wake-up from sleep later.
                 */
                pal_trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE);
                tal_trx_status = TRX_SLEEP;
            }
#else
            /*
             * Enable Awake_end interrupt.
             * This is used for save wake-up from sleep later.
             */
            pal_trx_bit_write(SR_IRQ_MASK, TRX_IRQ_4_CCA_ED_DONE);
            tal_trx_status = TRX_SLEEP;
#endif
            PAL_WAIT_1_US();
            PAL_SLP_TR_HIGH();
            pal_timer_delay(TRX_OFF_TO_SLEEP_TIME_CLKM_CYCLES);
            /* Transceiver register cannot be read during TRX_SLEEP or DEEP_SLEEP. */
            return tal_trx_status;

        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;

                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:
            switch (tal_trx_status)
            {
                case TRX_OFF:
                    switch_pll_on();
                    break;

                case PLL_ON:
                    break;

                default:
                    pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_PLL_ON);
                    break;
            }
            break;

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

                case PLL_ON:
                case RX_AACK_ON:
                case TX_ARET_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 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 TX_ARET_ON:
                case PLL_ON:
                case RX_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 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:
                case RX_ON:
                case RX_AACK_ON:
                    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() */
Exemplo n.º 3
0
/**
 * @brief Resets TAL state machine and sets the default PIB values if requested
 *
 * @param trx_id Transceiver identifier
 * @param set_default_pib Defines whether PIB values need to be set
 *                        to its default values
 *
 * @return
 *      - @ref MAC_SUCCESS if the transceiver state is changed to TRX_OFF
 *      - @ref FAILURE otherwise
 * @ingroup apiTalApi
 */
retval_t tal_reset(trx_id_t trx_id, bool set_default_pib)
{
	rf_cmd_state_t previous_trx_state[NUM_TRX];

	previous_trx_state[RF09] = trx_state[RF09];
	previous_trx_state[RF24] = trx_state[RF24];

	/* Reset the actual device or part of the device */
	if (trx_reset(trx_id) != MAC_SUCCESS) {
		return FAILURE;
	}

	/* Init Trx if necessary, e.g. trx was in deep sleep */
	if (((previous_trx_state[RF09] == RF_SLEEP) &&
			(previous_trx_state[RF24] == RF_SLEEP)) ||
			(trx_id == RFBOTH)) {
		trx_init(); /* Initialize generic trx functionality */
	}

	if (trx_id == RFBOTH) {
		for (uint8_t i = 0; i < NUM_TRX; i++) {
			/* Clean TAL and removed any pending tasks */
			cleanup_tal((trx_id_t)i);

			/* Configure the transceiver register values. */
			trx_config((trx_id_t)i);

			if (set_default_pib) {
				/* Set the default PIB values */
				init_tal_pib((trx_id_t)i); /* see 'tal_pib.c' */
				calculate_pib_values(trx_id);
			} else {
				/* nothing to do - the current TAL PIB attribute
				 *values are used */
			}

			write_all_tal_pib_to_trx((trx_id_t)i); /* see
			                                        *'tal_pib.c' */
			config_phy((trx_id_t)i);

			/* Reset TAL variables. */
			tal_state[(trx_id_t)i] = TAL_IDLE;
			tx_state[(trx_id_t)i] = TX_IDLE;
#ifdef ENABLE_FTN_PLL_CALIBRATION
			/* Stop FTN timer */
			stop_ftn_timer((trx_id_t)i);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
		}
	} else {
		/* Maintain other trx */
		trx_id_t other_trx_id;
		if (trx_id == RF09) {
			other_trx_id = RF24;
		} else {
			other_trx_id = RF09;
		}

		if (tal_state[other_trx_id] == TAL_SLEEP) {
			/* Switch other trx back to sleep again */
			uint16_t reg_offset = RF_BASE_ADDR_OFFSET *
					other_trx_id;
#ifdef IQ_RADIO
			pal_dev_reg_write(RF215_BB, reg_offset + RG_RF09_CMD,
					RF_SLEEP);
			pal_dev_reg_write(RF215_RF, reg_offset + RG_RF09_CMD,
					RF_SLEEP);
#else
			trx_reg_write(reg_offset + RG_RF09_CMD, RF_SLEEP);
#endif
			TAL_RF_IRQ_CLR_ALL(trx_id);
		}

		/* Clean TAL and removed any pending tasks */
		cleanup_tal(trx_id);

		/* Configure the transceiver register values. */
		trx_config(trx_id);

		if (set_default_pib) {
			/* Set the default PIB values */
			init_tal_pib(trx_id); /* see 'tal_pib.c' */
			calculate_pib_values(trx_id);
		} else {
			/* nothing to do - the current TAL PIB attribute values
			 *are used */
		}

		write_all_tal_pib_to_trx(trx_id); /* see 'tal_pib.c' */
		config_phy(trx_id);

		/* Reset TAL variables. */
		tal_state[trx_id] = TAL_IDLE;
		tx_state[trx_id] = TX_IDLE;
#ifdef ENABLE_FTN_PLL_CALIBRATION
		/* Stop FTN timer */
		stop_ftn_timer(trx_id);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
	}

	/*
	 * Configure interrupt handling.
	 * Install a handler for the transceiver interrupt.
	 */
#ifdef IQ_RADIO
	trx_irq_init(RF215_BB, bb_irq_handler_cb);
	trx_irq_init(RF215_RF, rf_irq_handler_cb);
	pal_trx_irq_en(RF215_BB); /* Enable transceiver main interrupt. */
	pal_trx_irq_en(RF215_RF); /* Enable transceiver main interrupt. */
#else
	trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
	pal_trx_irq_en(); /* Enable transceiver main interrupt. */
#endif

	return MAC_SUCCESS;
}
Exemplo n.º 4
0
/**
 * @brief Initializes the TAL
 *
 * This function is called to initialize the TAL. The transceiver is
 * initialized, the TAL PIBs are set to their default values, and the TAL state
 * machine is set to TAL_IDLE state.
 *
 * @return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF and the
 *                 current device part number and version number are correct;
 *         FAILURE otherwise
 */
retval_t tal_init(void)
{
	/* Init the PAL and by this means also the transceiver interface */
	if (pal_init() != MAC_SUCCESS) {
		return FAILURE;
	}

	/* Reset trx */
	if (trx_reset(RFBOTH) != MAC_SUCCESS) {
		return FAILURE;
	}

	/* Check if RF215 is connected */
	if ((trx_reg_read( RG_RF_PN) != 0x34) ||
			(trx_reg_read( RG_RF_VN) != 0x01)) {
		return FAILURE;
	}

	/* Initialize trx */
	trx_init();

	if (tal_timer_init() != MAC_SUCCESS) {
		return FAILURE;
	}

	/* Initialize the buffer management */
	bmm_buffer_init();

	/* Configure both trx and set default PIB values */
	for (uint8_t trx_id = 0; trx_id < NUM_TRX; trx_id++) {
		/* Configure transceiver */
		trx_config((trx_id_t)trx_id);
#ifdef RF215V1
		/* Calibrate LO */
		calibrate_LO((trx_id_t)trx_id);
#endif

		/* Set the default PIB values */
		init_tal_pib((trx_id_t)trx_id); /* see 'tal_pib.c' */
		calculate_pib_values((trx_id_t)trx_id);

		/*
		 * Write all PIB values to the transceiver
		 * that are needed by the transceiver itself.
		 */
		write_all_tal_pib_to_trx((trx_id_t)trx_id); /* see 'tal_pib.c'
		                                             **/
		config_phy((trx_id_t)trx_id);

		tal_rx_buffer[trx_id] = bmm_buffer_alloc(LARGE_BUFFER_SIZE);
		if (tal_rx_buffer[trx_id] == NULL) {
			return FAILURE;
		}

		/* Init incoming frame queue */
		qmm_queue_init(&tal_incoming_frame_queue[trx_id]);

		tal_state[trx_id] = TAL_IDLE;
		tx_state[trx_id] = TX_IDLE;
	}

	/* Init seed of rand() */
	tal_generate_rand_seed();

#ifndef DISABLE_IEEE_ADDR_CHECK
	for (uint8_t trx_id = 0; trx_id < 2; trx_id++) {
		/* Check if a valid IEEE address is available. */

		/*
		 * This while loop is on purpose, since just in the
		 * rare case that such an address is randomly
		 * generated again, we must repeat this.
		 */
		while ((tal_pib[trx_id].IeeeAddress == 0x0000000000000000) ||
				(tal_pib[trx_id].IeeeAddress ==
				((uint64_t)-1))) {
			/*
			 * In case no valid IEEE address is available, a random
			 * IEEE address will be generated to be able to run the
			 * applications for demonstration purposes.
			 * In production code this can be omitted.
			 */

			/*
			 * The proper seed for function rand() has already been
			 *generated
			 * in function tal_generate_rand_seed().
			 */
			uint8_t *ptr_pib
				= (uint8_t *)&tal_pib[trx_id].IeeeAddress;

			for (uint8_t i = 0; i < 8; i++) {
				*ptr_pib++ = (uint8_t)rand();

				/*
				 * Note:
				 * Even if casting the 16 bit rand value back to
				 *8 bit,
				 * and running the loop 8 timers (instead of
				 *only 4 times)
				 * may look cumbersome, it turns out that the
				 *code gets
				 * smaller using 8-bit here.
				 * And timing is not an issue at this place...
				 */
			}
		}
	}
#endif

#ifdef IQ_RADIO
	/* Init BB IRQ handler */
	pal_trx_irq_flag_clr(RF215_BB);
	trx_irq_init(RF215_BB, bb_irq_handler_cb);
	pal_trx_irq_en(RF215_BB);

	/* Init RF IRQ handler */
	pal_trx_irq_flag_clr(RF215_RF);
	trx_irq_init(RF215_RF, rf_irq_handler_cb);
	pal_trx_irq_en(RF215_RF);
#else

	/*
	 * Configure interrupt handling.
	 * Install a handler for the radio and the baseband interrupt.
	 */
	pal_trx_irq_flag_clr();
	trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
	pal_trx_irq_en(); /* Enable transceiver main interrupt. */
#endif

#if ((defined SUPPORT_FSK) && (defined SUPPORT_MODE_SWITCH))
	init_mode_switch();
#endif

	return MAC_SUCCESS;
} /* tal_init() */