Exemplo n.º 1
0
/**
 * \brief Switches the PLL on
 * \ingroup group_tal_state_machine_231
 */
static void switch_pll_on(void)
{
	trx_irq_reason_t irq_status;
	uint8_t poll_counter = 0;

	/* 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;
	}

	pal_trx_reg_read(RG_IRQ_STATUS); /* clear PLL lock bit */
	/* Switch PLL on */
	pal_trx_reg_write(RG_TRX_STATE, CMD_PLL_ON);

	/* Check if PLL has been locked. */
	do {
		irq_status = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS);

		if (irq_status & TRX_IRQ_PLL_LOCK) {
			return; /* PLL is locked now */
		}

		/* Wait a time interval of typical value for timer TR4. */
		pal_timer_delay(TRX_OFF_TO_PLL_ON_TIME_US);

		poll_counter++;
	} while (poll_counter < PLL_LOCK_ATTEMPTS);
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
/**
 * @brief Switches the PLL on
 */
static void switch_pll_on(void)
{
    uint32_t start_time;
    uint32_t current_time;

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

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

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

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

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

    /* Clear PLL lock interrupt at trx */
    pal_trx_reg_read(RG_IRQ_STATUS);
    /* Clear MCU's interrupt flag */
    pal_trx_irq_flag_clr();
    LEAVE_TRX_REGION();    // Enable trx interrupt handling again
    /* Restore transceiver's interrupt mask. */
    pal_trx_reg_write(RG_IRQ_MASK, trx_irq_mask);
}
/**
 * @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);
}
static trx_retval_t trx_init(void)
{
	tal_trx_status_t trx_status;
	uint8_t poll_counter = 0;

	/* Ensure control lines have correct levels. */
	RST_HIGH();
	SLP_TR_LOW();

	/* Wait typical time. */
	DELAY_US(P_ON_TO_CLKM_AVAILABLE_TYP_US);

	/* Apply reset pulse */
	RST_LOW();
	DELAY_US(RST_PULSE_WIDTH_US);
	RST_HIGH();

	/* Verify that TRX_OFF can be written */
	do {
		/* Wait not more than max. value of TR1. */
		if (poll_counter == P_ON_TO_CLKM_ATTEMPTS) {
			return TRX_FAILURE;
		}
		/* Wait a short time interval. */
		DELAY_US(TRX_POLL_WAIT_TIME_US);
		poll_counter++;
		/* Check if AT86RF231 is connected; omit manufacturer id check */
	} while ((pal_trx_reg_read(RG_VERSION_NUM) != AT86RF231_VERSION_NUM) ||
			(pal_trx_reg_read(RG_PART_NUM) != AT86RF231_PART_NUM));

	/* Set trx to off mode */
	pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);

	/* Verify that the trx has reached TRX_OFF. */
	poll_counter = 0;
	do {
		/* Wait a short time interval. */
		DELAY_US(TRX_POLL_WAIT_TIME_US);

		trx_status = (tal_trx_status_t) pal_trx_bit_read(SR_TRX_STATUS);

		/* Wait not more than max attempts for state transition */
		if (poll_counter == SLEEP_TO_TRX_OFF_ATTEMPTS) {
			return TRX_FAILURE;
		}
		poll_counter++;
	} while (trx_status != TRX_OFF);

	tal_trx_status = TRX_OFF;

	return TRX_SUCCESS;
}
Exemplo n.º 7
0
/**
 * \brief Initializes the transceiver
 *
 * This function is called to initialize the transceiver.
 *
 * \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 trx_init(void)
{
    tal_trx_status_t trx_status;
    uint8_t poll_counter = 0;

    PAL_RST_HIGH();
    PAL_SLP_TR_LOW();

    pal_timer_delay(P_ON_TO_CLKM_AVAILABLE);

    /* apply reset pulse */
    PAL_RST_LOW();
    pal_timer_delay(RST_PULSE_WIDTH_US);
    PAL_RST_HIGH();

    /* Verify that TRX_OFF can be written */
    do {
        if (poll_counter == 0xFF) {
            return FAILURE;
        }

        /* Wait a short time interval. */
        pal_timer_delay(TRX_POLL_WAIT_TIME_US);
        poll_counter++;
        /* Check if AT86RF230 is connected; omit manufacturer id check
         **/
    } while ((pal_trx_reg_read(RG_VERSION_NUM) != AT86RF230_REV_B) ||
             (pal_trx_reg_read(RG_PART_NUM) != AT86RF230));

    pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);

    /* verify that trx has reached TRX_OFF */
    poll_counter = 0;
    do {
        trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);
        if (poll_counter == 0xFF) {
#if (_DEBUG_ > 0)
            Assert(
                "MAX Attempts to switch to TRX_OFF state reached" ==
                0);
#endif
            return FAILURE;
        }

        poll_counter++;
    } while (trx_status != TRX_OFF);

    tal_trx_status = TRX_OFF;

    return MAC_SUCCESS;
}
/**
 * @brief Initializes the transceiver
 *
 * This function is called to initialize the transceiver.
 *
 * @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 trx_init(void)
{
    tal_trx_status_t trx_status;
    uint8_t poll_counter = 0;

    PAL_RST_HIGH();
    PAL_SLP_TR_LOW();

    /* Wait typical time of timer TR1. */
    pal_timer_delay(P_ON_TO_CLKM_AVAILABLE_TYP_US);

    /* Apply reset pulse */
    PAL_RST_LOW();
    pal_timer_delay(RST_PULSE_WIDTH_US);
    PAL_RST_HIGH();

#if !(defined FPGA_EMULATION)
    do
    {
        /* Wait not more than max. value of TR1. */
        if (poll_counter == P_ON_TO_CLKM_ATTEMPTS)
        {
            return FAILURE;
        }
        /* Wait a short time interval. */
        pal_timer_delay(TRX_POLL_WAIT_TIME_US);
        poll_counter++;
        /* Check if AT86RF233 is connected; omit manufacturer id check */
    }
    while (pal_trx_reg_read(RG_PART_NUM) != PART_NUM_AT86RF233);
#endif  /* !defined FPGA_EMULATION */

    /* Verify that TRX_OFF can be written */
    pal_trx_reg_write(RG_TRX_STATE, CMD_TRX_OFF);

    /* Verify that the trx has reached TRX_OFF. */
    poll_counter = 0;
    do
    {
        /* Wait a short time interval. */
        pal_timer_delay(TRX_POLL_WAIT_TIME_US);

        trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);

        /* Wait not more than max. value of TR15. */
        if (poll_counter == P_ON_TO_TRX_OFF_ATTEMPTS)
        {
#if (DEBUG > 0)
            pal_alert();
#endif
            return FAILURE;
        }
        poll_counter++;
    }
    while (trx_status != TRX_OFF);

    tal_trx_status = TRX_OFF;

    return MAC_SUCCESS;
}
Exemplo n.º 9
0
/**
 * @brief ED Scan Interrupt
 *
 * This function handles an ED done interrupt from the transceiver.
 */
static void trx_ed_irq_handler_cb(void)
{
    uint8_t ed_value;

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

    /*
     * Update the peak ED value received, if greater than the previously
     * read ED value.
     */
    if (ed_value > max_ed_level)
    {
        max_ed_level = ed_value;
    }

    /* Start next ED sampling */
    sampler_counter--;
    if (sampler_counter > 0)
    {
        // write dummy value to start measurement
        pal_trx_reg_write(RG_PHY_ED_LEVEL, 0xFF);
    }
    else
    {
        tal_state = TAL_ED_DONE;
    }
}
Exemplo n.º 10
0
/**
 * \brief Callback function for CCA completion.
 */
static void cca_done_irq_handler(void)
{
	/* Clear CCA interrupt. */
	pal_trx_reg_read(RG_IRQ_STATUS);

	tal_state = TAL_CCA_DONE;
}
/**
 * Function initializing the Timestamp IRQ to get synchronized
 * as required for ranging.
 */
void rtb_tstamp_irq_init(void)
{	
    pal_trx_irq_dis();

    pal_trx_reg_read(RG_IRQ_STATUS);
    pal_trx_bit_write(SR_ARET_TX_TS_EN, 0x01);
    pal_trx_bit_write(SR_IRQ_2_EXT_EN, 0x01); //Enable Timestamping over DIG2 on the at86rf233

    PORTC.INTFLAGS = PORT_INT1IF_bm;

    TCC1_CTRLB &= ~TC1_CCAEN_bm;

    TIMER_SRC_DURING_TRX_AWAKE();

    PORTC.INT1MASK = PIN1_bm; //DIG2 over PortC 1

    /* Reset register, until time out is triggered is 65535 ms */
    TCC1_CNT = 0;

    PORTC.PIN1CTRL = PORT_ISC1_bm;

    TCC1_INTFLAGS = TC1_CCAIF_bm;

    TCC1_INTCTRLB = TC_CCAINTLVL_HI_gc;

    TCC1_CTRLB |= TC1_CCAEN_bm;	
}
Exemplo n.º 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() */
Exemplo n.º 13
0
/**
 * @brief Switches the PLL on
 */
static void switch_pll_on(void)
{
    trx_irq_reason_t irq_status;
    uint32_t start_time, now;

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

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

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

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

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

    pal_trx_irq_en();
}
Exemplo n.º 14
0
static void switch_rf_to_txprep(trx_id_t trx_id)
{
	uint16_t reg_offset = RF_BASE_ADDR_OFFSET * trx_id;
	pal_trx_reg_write(RF215_RF, reg_offset + RG_RF09_CMD, RF_TXPREP);
	/* Wait for TXPREP */
	rf_cmd_state_t state;
	do {
		state = (rf_cmd_state_t)pal_trx_reg_read(RF215_RF,
				reg_offset +
				RG_RF09_STATE);
	} while (state != RF_TXPREP);
	/* Clear TRXRDY interrupt */
	uint8_t irqs = pal_trx_reg_read(RF215_RF, trx_id + RG_RF09_IRQS);
	tal_rf_irqs[trx_id] |= irqs & ((uint8_t)(~((uint32_t)RF_IRQ_TRXRDY))); /*
	                                                                        * avoid
	                                                                        * Pa091 */
	pal_trx_irq_flag_clr(RF215_RF);
}
Exemplo n.º 15
0
/**
 * @brief Subregister read
 *
 * @param addr Offset of the register
 * @param mask Bit mask of the subregister
 * @param pos  Bit position of the subregister
 *
 * @return  value of the read bit(s)
 */
uint8_t pal_trx_bit_read(uint8_t addr, uint8_t mask, uint8_t pos)
{
    uint8_t ret;

    ret = pal_trx_reg_read(addr);
    ret &= mask;
    ret >>= pos;

    return ret;
}
Exemplo n.º 16
0
Arquivo: tal_ed.c Projeto: 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;
}
Exemplo n.º 17
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 (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
#if (DISABLE_TSTAMP_IRQ == 1)
    if (trx_irq_cause & TRX_IRQ_2_RX_START)
    {
        /*
         * Get timestamp.
         *
         * In case Antenna diversity is used or the utilization of
         * the Timestamp IRQ is disabled, the timestamp needs to be read now
         * the "old-fashioned" way.
         *
         * The timestamping is generally only done for
         * beaconing networks or if timestamping is explicitly enabled.
         */
        pal_trx_read_timestamp(&tal_timestamp);
    }
#endif  /* #if (DISABLE_TSTAMP_IRQ == 1) */
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

    if (trx_irq_cause & TRX_IRQ_3_TRX_END)
    {
        /*
         * TRX_END reason depends on if the trx is currently used for
         * transmission or reception.
         */
#if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
        if ((tal_state == TAL_TX_AUTO) || tal_beacon_transmission)
#else
        if (tal_state == TAL_TX_AUTO)
#endif
        {
            /* Get the result and push it to the queue. */
            if (trx_irq_cause & TRX_IRQ_6_TRX_UR)
            {
                handle_tx_end_irq(true);            // see tal_tx.c
            }
            else
            {
                handle_tx_end_irq(false);            // see tal_tx.c
            }
        }
        else   /* Other tal_state than TAL_TX_... */
        {
            /* Handle rx interrupt. */
            handle_received_frame_irq();    // see tal_rx.c
        }
    }
}/* trx_irq_handler_cb() */
Exemplo n.º 18
0
/**
 * \brief Test the read and write of register on AT86RFx module
 *
 * This function will test the read and write functionalities of register
 * It will first write a known value (state) to register and reads the
 * register to confirm the same value.
 *
 * \param test Current test case.
 */
static void run_at86rfx_reg_access_test(const struct test_case *test)
{
	bool status;
	trx_cmd_t value;

	pal_trx_reg_write(RG_TRX_STATE, CMD_RX_ON);

	value = (trx_cmd_t) pal_trx_reg_read(RG_TRX_STATE);
	status = (CMD_RX_ON == value) ? true : false;
	test_assert_true(test, status == true,
			"Error Read/write AT86RFx register access failed");
}
Exemplo n.º 19
0
/**
 * @brief Subregister write
 *
 * @param[in] reg_addr Offset of the register
 * @param[in] mask Bit mask of the subregister
 * @param[in] pos Bit position of the subregister
 * @param[out] new_value Data, which is muxed into the register
 */
void pal_trx_bit_write(uint8_t reg_addr, uint8_t mask, uint8_t pos, uint8_t new_value)
{
    uint8_t current_reg_value;

    current_reg_value = pal_trx_reg_read(reg_addr);
    current_reg_value &= (uint8_t)~(uint32_t)mask;  // Implicit casting required to avoid IAR Pa091.
    new_value <<= pos;
    new_value &= mask;
    new_value |= current_reg_value;

    pal_trx_reg_write(reg_addr, new_value);
}
Exemplo n.º 20
0
Arquivo: tal_ed.c Projeto: bswe/6.1
/**
 * \brief ED Scan Interrupt
 * This function handles an ED done interrupt from the transceiver.
 *
 */
static void trx_ed_irq_handler_cb(void)
{
    uint8_t ed_value;
    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_CCA_ED_READY)
    {
        /* Read the ED Value. */
        ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL);

        /*
         * Update the peak ED value received, if greater than the previously
         * read ED value.
         */
        if (ed_value > max_ed_level)
        {
            max_ed_level = ed_value;
        }

        sampler_counter--;
        if (sampler_counter > 0)
        {
            // write dummy value to start measurement
            pal_trx_reg_write(RG_PHY_ED_LEVEL, 0xFF);
        }
        else
        {
            tal_state = TAL_ED_DONE;
        }
    }

#if (_DEBUG_ > 0)
    if (trx_irq_cause & (~(TRX_IRQ_PLL_LOCK | TRX_IRQ_CCA_ED_READY)))
    {
        Assert("Unexpected interrupt" == 0);
    }
#endif
}
Exemplo n.º 21
0
/**
 * \brief Finalizes the CSMA procedure
 *
 * \param status Result of the slotted transmission
 */
static void tx_done(retval_t status)
{
#if (_DEBUG_ > 0)
	switch (tal_state) {
	case TAL_SLOTTED_CSMA:
	case TAL_TX_BASIC:
		break;

#if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
	case TAL_TX_BEACON:
		Assert("unexpected tal_state TAL_TX_BEACON" == 0);
		return;

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

	default:
		Assert("unexpected tal_state" == 0);
		break;
	}
#endif
#if (_DEBUG_ > 0)
	if (pal_is_timer_running(TAL_CSMA_BEACON_LOSS_TIMER)) {
		Assert("beacon lost timer is still running" == 0);
	}

#endif

	tal_state = TAL_IDLE;
	tal_csma_state = CSMA_IDLE;

	/*
	 * Restore the interrupt handler.
	 * Install a handler for the transceiver interrupt.
	 */
	pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
	pal_trx_reg_read(RG_IRQ_STATUS);

	/* Check if a receive buffer is available. */
	if (NULL != tal_rx_buffer) {
		pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
	} else {
		tal_rx_on_required = true;
	}

	pal_trx_irq_en();

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

	tal_tx_frame_done_cb(status, mac_frame_ptr);
}
/**
 * Function disabling the Timestamp IRQ as utilized for ranging.
 */
void rtb_tstamp_irq_exit(void)
{
    TCC1_INTCTRLB = TC_CCAINTLVL_OFF_gc;

    TCC1_CTRLB &= ~TC1_CCAEN_bm;

    /* Clear status register. */
    pal_trx_reg_read(RG_IRQ_STATUS);

    /* Enable main Trx IRQ. */
    pal_trx_irq_en();

    /* Re-enable all interrupts. */
    pal_global_irq_enable();
}
Exemplo n.º 23
0
/**
 * @brief Initializes the transceiver
 *
 * This function is called to initialize the transceiver.
 *
 * @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 trx_init(void)
{
    tal_trx_status_t trx_status;
    uint8_t poll_counter = 0;

    /* Ensure control lines have correct levels. */
    PAL_RST_HIGH();
    PAL_SLP_TR_LOW();

    pal_timer_delay(P_ON_TO_CLKM_AVAILABLE_TYP_US);

    /* Apply reset pulse */
    PAL_RST_LOW();
    pal_timer_delay(RST_PULSE_WIDTH_US);
    PAL_RST_HIGH();

    /* Verify that the trx has reached TRX_OFF. */
    poll_counter = 0;
    do
    {
        /* Wait a short time interval. */
        pal_timer_delay(TRX_POLL_WAIT_TIME_US);

        trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);

        /* Wait not more than max. value of TR2. */
        if (poll_counter == RESET_TO_TRX_OFF_ATTEMPTS)
        {
#if (DEBUG > 0)
            pal_alert();
#endif
            return FAILURE;
        }
        poll_counter++;
    }
    while (trx_status != TRX_OFF);

    tal_trx_status = TRX_OFF;

#if !defined(FPGA_EMULATION)
    /* Check if actually running on an ATmegaRFR2 device. */
    if (ATMEGARFR2_PART_NUM != pal_trx_reg_read(RG_PART_NUM))
    {
        return FAILURE;
    }
#endif
    return MAC_SUCCESS;
}
Exemplo n.º 24
0
/**
 * \brief Initializes the transceiver
 *
 * This function is called to initialize the transceiver.
 *
 * \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 trx_init(void)
{
	tal_trx_status_t trx_status;
	uint8_t poll_counter = 0;

	sysclk_enable_peripheral_clock(&TRX_CTRL_0);
	PAL_RST_HIGH();
	PAL_SLP_TR_LOW();

	pal_timer_delay(P_ON_TO_CLKM_AVAILABLE_TYP_US);

	/* Apply reset pulse */
	PAL_RST_LOW();
	pal_timer_delay(RST_PULSE_WIDTH_US);
	PAL_RST_HIGH();

	/* Verify that the trx has reached TRX_OFF. */
	poll_counter = 0;
	do {
		/* Wait a short time interval. */
		pal_timer_delay(TRX_POLL_WAIT_TIME_US);

		trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);

		/* Wait not more than max. value of TR2. */
		if (poll_counter == RESET_TO_TRX_OFF_ATTEMPTS) {
#if (_DEBUG_ > 0)
			Assert(
					"MAX Attempts to switch to TRX_OFF state reached" ==
					0);
#endif
			return FAILURE;
		}

		poll_counter++;
	} while (trx_status != TRX_OFF);

	tal_trx_status = TRX_OFF;

#if !defined(FPGA_EMULATION)
	/* Check if actually running on an ATmegaRFR2 device. */
	if (ATMEGARFR2_PART_NUM != pal_trx_reg_read(RG_PART_NUM)) {
		return FAILURE;
	}

#endif
	return MAC_SUCCESS;
}
Exemplo n.º 25
0
/*
 * \brief Transceiver interrupt handler for awake end IRQ
 *
 * This function handles the transceiver awake end interrupt.
 */
void trx_irq_awake_handler_cb(void)
{
	trx_irq_reason_t trx_irq_cause = (trx_irq_reason_t)pal_trx_reg_read(
			RG_IRQ_STATUS);

	if (trx_irq_cause & TRX_IRQ_4_CCA_ED_DONE) {
		/* Set the wake-up flag. */
		tal_awake_end_flag = true;
	}

#if (_DEBUG_ > 0)
	if (trx_irq_cause & (~(TRX_IRQ_0_PLL_LOCK | TRX_IRQ_4_CCA_ED_DONE))) {
		Assert("Unexpected interrupt" == 0);
	}

#endif
}
Exemplo n.º 26
0
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) {
			handle_tx_end_irq();
		} else {	/* Other tal_state than TAL_TX_... */
			/* Handle rx interrupt. */
			handle_received_frame_irq();
		}
	}
}
Exemplo n.º 27
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);
}
Exemplo n.º 28
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.º 29
0
/**
 * @brief Get the transceiver's supply voltage
 *
 * @return mv Milli Volt; 0 if below threshold, 0xFFFF if above threshold
 */
uint16_t tfa_get_batmon_voltage(void)
{
    tal_trx_status_t previous_trx_status;
    uint8_t vth_val;
    uint8_t i;
    uint16_t mv = 1;    // 1 used as indicator flag
    bool range;

    previous_trx_status = tal_trx_status;
    if (tal_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_TRX_OFF);
    }

    /*
     * Disable all trx interrupts.
     * This needs to be done AFTER the transceiver has been woken up.
     */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_NONE);

    /* Check if supply voltage is within lower range */
    pal_trx_bit_write(SR_BATMON_HR, BATMON_LOW_RANGE);
    pal_trx_bit_write(SR_BATMON_VTH, 0x0F);
    pal_timer_delay(5); /* Wait until Batmon has been settled. */
    if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES)
    {
        /* Lower range */
        /* Check if supply voltage is below lower limit */
        pal_trx_bit_write(SR_BATMON_VTH, 0);
        pal_timer_delay(2); /* Wait until Batmon has been settled. */
        if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES)
        {
            /* below lower limit */
            mv = SUPPLY_VOLTAGE_BELOW_LOWER_LIMIT;
        }
        range = LOW;
    }
    else
    {
        /* Higher range */
        pal_trx_bit_write(SR_BATMON_HR, BATMON_HIGH_RANGE);
        /* Check if supply voltage is above upper limit */
        pal_trx_bit_write(SR_BATMON_VTH, 0x0F);
        pal_timer_delay(5); /* Wait until Batmon has been settled. */
        if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_ABOVE_THRES)
        {
            /* above upper limit */
            mv = SUPPLY_VOLTAGE_ABOVE_UPPER_LIMIT;
        }
        range = HIGH;
    }

    /* Scan through the current range for the matching threshold. */
    if (mv == 1)
    {
        vth_val = 0x0F;
        for (i = 0; i < 16; i++)
        {
            pal_trx_bit_write(SR_BATMON_VTH, i);
            pal_timer_delay(2); /* Wait until Batmon has been settled. */
            if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_BELOW_THRES)
            {
                if (i > 0)
                {
                    vth_val = i - 1;
                }
                else
                {
                    vth_val = i;
                }
                break;
            }
        }

        if (range == HIGH)
        {
            mv = 2550 + (75 * vth_val);
        }
        else
        {
            mv = 1700 + (50 * vth_val);
        }
    }

    pal_trx_reg_read(RG_IRQ_STATUS);

    /* Clear all pending interrupts. */
    pal_trx_irq_flag_clr_rx_end();
    pal_trx_irq_flag_clr_tx_end();
    pal_trx_irq_flag_clr_tstamp();

    /*
     * Enable all trx interrupts.
     * This needs to be done BEFORE putting the transceiver back to slee.
     */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

    if (previous_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_SLEEP);
    }

    return mv;
}
Exemplo n.º 30
0
/*
 * \brief Handle received frame interrupt
 *
 * This function handles transceiver interrupts for received frames and
 * uploads the frames from the trx.
 */
void handle_received_frame_irq(void)
{
    uint8_t ed_value;
    /* Actual frame length of received frame. */
    uint8_t phy_frame_len;
    /* Extended frame length appended by LQI and ED. */
    uint8_t ext_frame_length;
    frame_info_t *receive_frame;
    uint8_t *frame_ptr;

    if (tal_rx_buffer == NULL)
    {
        Assert("no tal_rx_buffer available" == 0);
        /*
         * Although the buffer protection mode is enabled and the receiver has
         * been switched to PLL_ON, the next incoming frame was faster.
         * It cannot be handled and is discarded.
         */
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE);  /* Disable buffer protection mode */
        pal_timer_delay(2); // Allow pin change to get effective
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE);  /* Enable buffer protection mode */
        return;
    }

    receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(tal_rx_buffer);

#ifdef PROMISCUOUS_MODE
    if (tal_pib.PromiscuousMode)
    {
        /* Check for valid FCS */
        if (pal_trx_bit_read(SR_RX_CRC_VALID) == CRC16_NOT_VALID)
        {
            return;
        }
    }
#endif

    /* Get ED value; needed to normalize LQI. */
    ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL);

    /* Get frame length from transceiver. */
    phy_frame_len = ext_frame_length = pal_trx_reg_read(RG_TST_RX_LENGTH);

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

    /*
     * The PHY header is also included in the frame (length field), hence the frame length
     * is incremented.
     * In addition to that, the LQI and ED value are uploaded, too.
     */
    ext_frame_length += LQI_LEN + ED_VAL_LEN;

    /* Update payload pointer to store received frame. */
    frame_ptr = (uint8_t *)receive_frame + LARGE_BUFFER_SIZE - ext_frame_length;

    /*
     * Note: The following code is different from other non-single chip
     * transceivers, where reading the frame via SPI contains the length field
     * in the first octet.
     */
    pal_trx_frame_read(frame_ptr, phy_frame_len + LQI_LEN);
    frame_ptr--;
    *frame_ptr = phy_frame_len;
    receive_frame->mpdu = frame_ptr;
    /* Add ED value at the end of the frame buffer. */
    receive_frame->mpdu[phy_frame_len + LQI_LEN + ED_VAL_LEN] = ed_value;


#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
    /*
     * Store the timestamp.
     * The timestamping is only required for beaconing networks
     * or if timestamping is explicitly enabled.
     */
    receive_frame->time_stamp = tal_rx_timestamp;
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

    /* Append received frame to incoming_frame_queue and get new rx buffer. */
    qmm_queue_append(&tal_incoming_frame_queue, tal_rx_buffer);

    /* The previous buffer is eaten up and a new buffer is not assigned yet. */
    tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE);

    /* Check if receive buffer is available */
    if (NULL == tal_rx_buffer)
    {
        /*
         * Turn off the receiver until a buffer is available again.
         * tal_task() will take care of eventually reactivating it.
         * Due to ongoing ACK transmission do not force to switch it off.
         */

        /* Do not change the state since buffer protection mode is not re-enabled yet.
         * Buffer protection will be re-enabled after buffer becomes available
         */
        //set_trx_state(CMD_PLL_ON);
        tal_rx_on_required = true;
    }
    else
    {
        /*
         * Trx returns to RX_AACK_ON automatically, if this was its previous state.
         * Keep the following as a reminder, if receiver is used with RX_ON instead.
         */
        //pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON);
        /*
         * Release the protected buffer and set it again for further protection since
         * the buffer is available
         */
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE);  /* Disable buffer protection mode */
        pal_timer_delay(2); // Allow pin change to get effective
        pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE);  /* Enable buffer protection mode */
    }

    /*
     * Clear pending TX_END IRQ: The TX_END IRQ is envoked for the transmission
     * end of an automatically sent ACK frame. This implementation does not use
     * this feature.
     */
    pal_trx_irq_flag_clr_tx_end();
}