コード例 #1
0
ファイル: tal_slotted_csma.c プロジェクト: nandojve/embedded
/**
 * @brief Performs CCA twice
 */
static uint8_t perform_cca_twice(void)
{
    uint8_t cca_status;
    uint8_t cca_done;
    uint8_t CW = 2;
    uint32_t now_time_us;

    do
    {
        pal_get_current_time(&now_time_us);
    }
    while (pal_add_time_us(now_time_us, (SLEEP_TO_TRX_OFF_TYP_US + CCA_PREPARATION_DURATION_US)) <
           cca_starttime_us);

#if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
    if (tal_beacon_transmission)
    {
#if (DEBUG > 0)
        ASSERT("Ongoing beacon transmission, slotted CSMA busy" == 0);
#endif
        return PHY_BUSY;
    }
#endif /* ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) */

    /* Ensure that trx is at least in TRX_OFF mode at this time. */
    if (tal_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_TRX_OFF);
    }

    do
    {
        pal_get_current_time(&now_time_us);
    }
    while (pal_add_time_us(now_time_us, (TRX_OFF_TO_PLL_ON_TIME_US + CCA_PREPARATION_DURATION_US)) <
           cca_starttime_us);

    /*
     * Set trx to PLL_ON.
     * If trx is busy and trx cannot be set to PLL_ON, assess channel as busy.
     */
    if (set_trx_state(CMD_PLL_ON) != PLL_ON)
    {
        return PHY_BUSY;
    }

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

    /* do CCA twice */
    do
    {
        /* wait here until 16us before backoff boundary */
        /* assume TRX is in PLL_ON */
        do
        {
            pal_get_current_time(&now_time_us);
        }
        while (pal_add_time_us(now_time_us, CCA_PRE_START_DURATION_US) <
               cca_starttime_us);

        set_trx_state(CMD_RX_ON);

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

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

        /* wait until CCA is done and get status */
        pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US(CCA_DURATION_SYM));

        do
        {
            /* poll until CCA is really done; */
            cca_done = pal_trx_bit_read(SR_CCA_DONE);
        }
        while (cca_done != CCA_COMPLETED);

        /* between both CCA switch trx to PLL_ON to reduce power consumption */
        set_trx_state(CMD_PLL_ON);

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

        /* check if channel was idle or busy */
        if (pal_trx_bit_read(SR_CCA_STATUS) == CCA_CH_IDLE)
        {
            /* do next CCA at next backoff boundary */
            cca_starttime_us = pal_add_time_us(cca_starttime_us,
                                               TAL_CONVERT_SYMBOLS_TO_US(aUnitBackoffPeriod));
            CW--;
            cca_status = PHY_IDLE;
        }
        else    // PHY busy
        {
            cca_status = PHY_BUSY;
            set_trx_state(CMD_RX_AACK_ON);
            break;  // if channel is busy do no do CCA for the second time
        }
    }
    while (CW > 0);

    /*
     * Keep trx ready for transmission if channel is idle.
     * The transceiver is still in PLL_ON.
     * If the channel is not idle, the trx handling is done in csma_backoff().
     */

    /*
     * Clear CCA interrupt flag.
     * This is only necessary for debugging, because only in debug mode
     * interrupt that are not handled cause an assert in the ISR.
     */
#if (DEBUG > 0)
    pal_trx_reg_read(RG_IRQ_STATUS);
#endif

    /*
     * Since we are not interested in any frames that might be received
     * during CCA, reject any information that indicates a previous frame
     * reception.
     */
    pal_trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); // enable frame reception indication

    return cca_status;
}
コード例 #2
0
ファイル: tal.c プロジェクト: mknapik/avr-MAC
/**
 * @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;
        uint8_t cnt;
      tryagain:
        cnt = 100;

        PAL_SLP_TR_LOW();
        /* poll status register until TRX_OFF is reached */
        do
        {
            bit_status = pal_trx_bit_read(SR_TRX_STATUS);
            if (bit_status != TRX_OFF)
            {
                if (--cnt == 0)
                {
                    /* Work around for trx being "half awake". */
                    PAL_SLP_TR_HIGH();
                    goto tryagain;
                }
                PAL_WAIT_1_US();
            }
        } while (bit_status != TRX_OFF);

#if (DEBUG > 0)
        pal_trx_reg_read(RG_IRQ_STATUS);    /* clear Wake irq, dummy read */
#endif

#ifdef ANTENNA_DIVERSITY
        /* Enable antenna diversity. */
        pal_trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_SWITCH_ENABLE);
#endif

        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)    /* requested state */
    {
        case CMD_SLEEP:
            pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
#ifdef ANTENNA_DIVERSITY
            /* Disable antenna diversity: sets pulls */
            pal_trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_SWITCH_DISABLE);
#endif
            {
                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 */

        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:
                    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 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() */
コード例 #3
0
ファイル: tal_init.c プロジェクト: bswe/6.1
/**
 * \brief Reset transceiver
 *
 * \return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF
 *         FAILURE otherwise
 */
static retval_t trx_reset(void)
{
    tal_trx_status_t trx_status;
    uint8_t poll_counter = 0;
#if (EXTERN_EEPROM_AVAILABLE == 1)
    uint8_t xtal_trim_value;
#endif

    /* Get trim value for 16 MHz xtal; needs to be done before reset */
#if (EXTERN_EEPROM_AVAILABLE == 1)
    pal_ps_get(EXTERN_EEPROM, EE_XTAL_TRIM_ADDR, 1, &xtal_trim_value);
#endif

    /* trx might sleep, so wake it up */
    PAL_SLP_TR_LOW();
    pal_timer_delay(SLEEP_TO_TRX_OFF_TYP_US);

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

    /* verify that trx has reached TRX_OFF */
    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 == SLEEP_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;

    // Write 16MHz xtal trim value to trx.
    // It's only necessary if it differs from the reset value.
#if (EXTERN_EEPROM_AVAILABLE == 1)
    if (xtal_trim_value != 0x00)
    {
        pal_trx_bit_write(SR_XTAL_TRIM, xtal_trim_value);
    }
#endif

#ifdef STB_ON_SAL
#if (SAL_TYPE == AT86RF2xx)
    stb_restart();
#endif
#endif

    return MAC_SUCCESS;
}
コード例 #4
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 */
        CONF_REG_WRITE();
        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 */
        CONF_REG_WRITE();
        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)
    {
        /* 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 */

        CONF_REG_WRITE();
    }

    /*
     * 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();
}
コード例 #5
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_irq_dis();

    /* Check if supply voltage is within lower range */
    pal_trx_bit_write(SR_BATMON_HR, BATMON_HR_LOW);
    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_NOT_VALID)
    {
        /* Lower range */
        /* Check if supply voltage is below lower limit */
        pal_trx_bit_write(SR_BATMON_VTH, 0);
        if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_NOT_VALID)
        {
            /* below lower limit */
            mv = SUPPLY_VOLTAGE_BELOW_LOWER_LIMIT;
        }
        range = LOW;
    }
    else
    {
        /* Higher range */
        pal_trx_bit_write(SR_BATMON_HR, BATMON_HR_HIGH);
        /* 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_VALID)
        {
            /* 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_NOT_VALID)
            {
                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);

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

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

    return mv;
}
コード例 #6
0
ファイル: tal_init.c プロジェクト: bswe/6.1
/**
 * \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();

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

    /* 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 FAILURE;
        }
        /* Wait a short time interval. */
        pal_timer_delay(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));

    /* 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 TR2. */
        if (poll_counter == SLEEP_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;

    return MAC_SUCCESS;
}
コード例 #7
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. */
		if(CMD_SLEEP == trx_cmd)
		{
			return TRX_SLEEP;
		}
		tal_awake_end_flag = false;
		/* Set callback function for the awake interrupt. */
		pal_trx_irq_init_awake((FUNC_PTR)trx_awake_handler_cb);
		/* 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_write(RG_IRQ_STATUS, 0xFF);
		/* 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

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

	switch (trx_cmd) { /* requested state */
	case CMD_SLEEP:
		pal_trx_reg_write(RG_TRX_STATE, CMD_FORCE_TRX_OFF);
#if (ANTENNA_DIVERSITY == 1)
		/* Disable antenna diversity: sets pulls */
		pal_trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_DISABLE);
#endif
		{
			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));
		}

		/*
		 * Clear existing interrupts to have clear interrupt flags
		 * during wake-up.
		 */
		pal_trx_reg_write(RG_IRQ_STATUS, 0xFF);

		/*
		 * Enable Awake_end interrupt.
		 * This is used for save wake-up from sleep later.
		 */
		pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_AWAKE_ONLY);

		PAL_WAIT_1_US();
		PAL_SLP_TR_HIGH();
		pal_timer_delay(TRX_OFF_TO_SLEEP_TIME_CLKM_CYCLES);
		tal_trx_status = TRX_SLEEP;
		return TRX_SLEEP; /* transceiver register cannot be read during
		                   *TRX_SLEEP */

	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:
			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 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() */
コード例 #8
0
/**
 * \brief Interrupt handler for ACK reception
 *
 * \param parameter Unused callback parameter
 */
static void ack_reception_handler_cb(void *parameter)
{
	trx_irq_reason_t trx_irq_cause;

	if (tal_csma_state == TX_DONE_NO_ACK) {
		return; /* ack expiration timer has already been fired */
	}

	trx_irq_cause = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS);

	if (trx_irq_cause & TRX_IRQ_TRX_END) {
		retval_t timer_status;

		switch (tal_csma_state) {
		case FRAME_SENDING_WITH_ACK:
			set_trx_state(CMD_RX_ON);

			timer_status
				= pal_timer_start(TAL_ACK_WAIT_TIMER,
					TAL_CONVERT_SYMBOLS_TO_US(
					TAL_ACK_WAIT_DURATION_DEFAULT),
					TIMEOUT_RELATIVE,
					(FUNC_PTR)ack_timer_expiry_handler_cb,
					NULL);

			if (timer_status == MAC_SUCCESS) {
				tal_csma_state = WAITING_FOR_ACK;
			} else if (timer_status == PAL_TMR_ALREADY_RUNNING) {
				tal_csma_state = WAITING_FOR_ACK;
			} else {
				tal_csma_state = TX_DONE_NO_ACK;
				Assert("timer start failed" == 0);
			}

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

		case WAITING_FOR_ACK:
		{
			uint8_t ack_frame[ACK_FRAME_LEN + LENGTH_FIELD_LEN];

			/*
			 * Read the frame buffer, identify if this is an ACK
			 *frame,
			 * and get the sequence number.
			 * Üpload the frame from the transceiver.
			 */
			pal_trx_frame_read(ack_frame,
					(ACK_FRAME_LEN +
					LENGTH_FIELD_LEN));

			/* Check if the uploaded frame is an ACK frame */
			if ((ack_frame[1] & ACK_FRAME) != ACK_FRAME) {
				/* The received frame is not an ACK frame */
				return;
			}

			/* check CRC */
			if (pal_trx_bit_read(SR_RX_CRC_VALID) != CRC16_VALID) {
				return;
			}

			/* check the sequence number */
			if (ack_frame[3] == tal_frame_to_tx[SEQ_NUMBER_POS]) {
				/*
				 * If we are here, the ACK is valid and matches
				 * the transmitted sequence number.
				 */
				pal_timer_stop(TAL_ACK_WAIT_TIMER);
#if (_DEBUG_ > 0)
				if (pal_is_timer_running(TAL_ACK_WAIT_TIMER)) {
					Assert("Ack timer running" == 0);
				}

#endif
				/* restore the interrupt handler */
				pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb);
				pal_trx_irq_en();

				if (NULL != tal_rx_buffer) {
					pal_trx_reg_write(RG_TRX_STATE,
							CMD_RX_AACK_ON);
				} else {
					tal_rx_on_required = true;
				}

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

				if (ack_frame[1] & FCF_FRAME_PENDING) {
					tal_csma_state = TX_DONE_FRAME_PENDING;
				} else {
					tal_csma_state = TX_DONE_SUCCESS;
				}

				/* debug pin to switch on: define
				 *ENABLE_DEBUG_PINS, pal_config.h */
				PIN_ACK_OK_END();
				PIN_ACK_WAITING_END();
			}
		}
		break;

		case FRAME_SENDING_NO_ACK:
			/* Tx is done */
			/* debug pin to switch on: define ENABLE_DEBUG_PINS,
			 *pal_config.h */
			PIN_TX_END();
			tal_csma_state = TX_DONE_SUCCESS;
			break;

		default:
			Assert("unknown tal_csma_state" == 0);
			break;
		}
	} else { /* other interrupt than TRX_END */
		/* no interest in any other interrupt */
		return;
	}

	parameter = parameter; /* Keep compiler happy. */
}
コード例 #9
0
/*
 * \brief Handles interrupts issued due to end of transmission
 *
 * \param underrun_occured  true if under-run has occurred
 */
void handle_tx_end_irq(bool underrun_occured)
{
#if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
	if (tal_beacon_transmission) {
		tal_beacon_transmission = false;

		if (tal_csma_state == BACKOFF_WAITING_FOR_BEACON) {
			/* Slotted CSMA has been waiting for a beacon, now it
			 * can continue. */
			tal_csma_state = CSMA_HANDLE_BEACON;
		}
	} else
#endif /* ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) */
	{
#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)

		/*
		 * Store tx timestamp to frame_info_t structure.
		 * The timestamping is only required for beaconing networks
		 * or if timestamping is explicitly enabled.
		 */
		pal_trx_read_timestamp(&mac_frame_ptr->time_stamp);
#endif  /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

		/* Read trac status before enabling RX_AACK_ON. */
		if (underrun_occured) {
			trx_trac_status = TRAC_INVALID;
		} else {
			trx_trac_status = (trx_trac_status_t)pal_trx_bit_read(
					SR_TRAC_STATUS);
		}

#ifdef BEACON_SUPPORT
		if (tal_csma_state == FRAME_SENDING) { /* Transmission was
		                                        * issued by slotted CSMA */
			PIN_TX_END();
			tal_state = TAL_SLOTTED_CSMA;

			/* Map status message of transceiver to TAL constants.
			 **/
			switch (trx_trac_status) {
			case TRAC_SUCCESS_DATA_PENDING:
				PIN_ACK_OK_START();
				tal_csma_state = TX_DONE_FRAME_PENDING;
				break;

			case TRAC_SUCCESS:
				PIN_ACK_OK_START();
				tal_csma_state = TX_DONE_SUCCESS;
				break;

			case TRAC_CHANNEL_ACCESS_FAILURE:
				PIN_NO_ACK_START();
				tal_csma_state = CSMA_ACCESS_FAILURE;
				break;

			case TRAC_NO_ACK:
				PIN_NO_ACK_START();
				tal_csma_state = TX_DONE_NO_ACK;
				break;

			case TRAC_INVALID: /* Handle this in the same way as
				            *default. */
			default:
				Assert("not handled trac status" == 0);
				tal_csma_state = CSMA_ACCESS_FAILURE;
				break;
			}
			PIN_ACK_OK_END();
			PIN_ACK_WAITING_END();
		} else
#endif  /* BEACON_SUPPORT */
		/* Trx has handled the entire transmission incl. CSMA */
		{
			tal_state = TAL_TX_DONE; /* Further handling is done by
			                          * tx_done_handling() */
		}
	}

	/*
	 * After transmission has finished, switch receiver on again.
	 * Check if receive buffer is available.
	 */
	if (NULL == tal_rx_buffer) {
		set_trx_state(CMD_PLL_ON);
		tal_rx_on_required = true;
	} else {
		set_trx_state(CMD_RX_AACK_ON);
	}
}
コード例 #10
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)
{
    volatile tal_trx_status_t test_status;
    uint8_t poll_counter = 0;
    /* Wait typical time of timer TR1. */
    pal_timer_delay(P_ON_TO_CLKM_AVAILABLE_TYP_US);

    /* make sure SPI is working properly */
    //    while ((tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS) != P_ON);

    /* Apply reset pulse. Ensure control lines have correct levels (SEL is
     * already set in TRX_INIT().
     */
    PAL_RST_LOW();
    PAL_SLP_TR_LOW();
    pal_timer_delay(RST_PULSE_WIDTH_US);
    PAL_RST_HIGH();

    /* Wait typical time of timer TR13. */
    pal_timer_delay(30);

    test_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);

    /* Dummy assignment, to avoid compiler warning */
    test_status = test_status;

#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 AT86RF212B is connected; omit manufacturer id check */
    }
    while (pal_trx_reg_read(RG_PART_NUM) != PART_NUM_AT86RF212B);

#endif  /* !defined FPGA_EMULATION */

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

    /* \todo remove this line?! */
    while ((tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS) != TRX_OFF);


#if (_DEBUG_ > 0)
    tal_trx_status_t trx_status;
    trx_status = (tal_trx_status_t)pal_trx_bit_read(SR_TRX_STATUS);
    if (trx_status != TRX_OFF)
    {
        return FAILURE;
    }
#endif

    pal_trx_reg_write(RG_IRQ_MASK, TRX_NO_IRQ);
    tal_trx_status = TRX_OFF;

    return MAC_SUCCESS;
}
コード例 #11
0
ファイル: tal_rx.c プロジェクト: nandojve/embedded
/**
 * @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 (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
    uint32_t timestamp_us;
#endif  /*if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

    if (tal_rx_buffer == NULL)
    {
        ASSERT("no tal_rx_buffer available" == 0);
        return;
    }

#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
    /*
     * The timestamping is only required for beaconing networks
     * or if timestamping is explicitly enabled.
     */
    pal_trx_read_timestamp(&timestamp_us);
#endif  /*if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */

    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. */
    pal_trx_frame_read(&phy_frame_len, LENGTH_FIELD_LEN);

    /* 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 = phy_frame_len + LENGTH_FIELD_LEN + 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 single chip
     * transceivers, since reading the frame via SPI contains the length field
     * in the first octet.
     */
    pal_trx_frame_read(frame_ptr, LENGTH_FIELD_LEN + phy_frame_len + LQI_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 = timestamp_us;
#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.
         */
        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);
    }
}
コード例 #12
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;

    pal_trx_irq_dis();

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

    /* 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);
    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);
        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);
        if (pal_trx_bit_read(SR_BATMON_OK) == BATMON_ABOVE_THRES)
        {
            /* above upper limit */
            mv = SUPPLY_VOLTAGE_ABOVE_UPPER_LIMIT;
        }
        range = HIGH;
    }

    if (mv == 1)
    {
        vth_val = 0x0F;
        for (i = 0; i < 16; i++)
        {
            pal_trx_bit_write(SR_BATMON_VTH, i);
            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);
    if (previous_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_TRX_SLEEP);
    }

    pal_trx_irq_en();

    return mv;
}
コード例 #13
0
static tal_trx_status_t set_trx_state(trx_cmd_t trx_cmd)
{
	tal_trx_status = (tal_trx_status_t) pal_trx_bit_read(SR_TRX_STATUS);

	/*
	 * State transition is handled among TRX_OFF, RX_ON and PLL_ON.
	 * These are the essential states required for a basic transmission
	 * and reception.
	 */
	switch (trx_cmd) {	/* requested state */
	case CMD_TRX_OFF:
		/* Handling TRX_OFF state */
		switch (tal_trx_status) {
		case TRX_OFF:
			/* Do nothing - maintain the previous state */
			break;

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

	case CMD_PLL_ON:
		/* Handling PLL_ON state */
		switch (tal_trx_status) {
		case PLL_ON:
			/* Do nothing - maintain the previous state */
			break;

		case TRX_OFF:
			switch_pll_on();
			break;

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

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

	case CMD_RX_ON:
		/* Handling the RX_ON state */
		switch (tal_trx_status) {
		case RX_ON:
			/* Do nothing - maintain the previous state */
			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;

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

	default:
		Assert("trx command not handled" == 0);
		break;
	}

	/* Hold till the state transition is complete */
	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;
}
コード例 #14
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)
{
	/* 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. Reading anything from
		 *the
		 * frame resets the buffer protection mode.
		 */
		uint8_t dummy;
		pal_trx_frame_read(&dummy, 1);
		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

#if (defined ENABLE_TRX_SRAM) || defined(ENABLE_TRX_SRAM_READ)
	/* Use SRAM read to keep rx safe mode armed. */
	pal_trx_sram_read(0x00, &phy_frame_len, LENGTH_FIELD_LEN); /* 0x00: SRAM
	                                                            * offset
	                                                            * address */
#else
	/* Get frame length from transceiver. */
	pal_trx_frame_read(&phy_frame_len, LENGTH_FIELD_LEN);
#endif

	/* 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 = phy_frame_len + LENGTH_FIELD_LEN + 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 single chip
	 * transceivers, since reading the frame via SPI contains the length
	 *field
	 * in the first octet. RF233's frame buffer includes ED value too.
	 */
	pal_trx_frame_read(frame_ptr,
			LENGTH_FIELD_LEN + phy_frame_len + LQI_LEN +
			ED_VAL_LEN);
	receive_frame->mpdu = frame_ptr;

#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_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.
		 */
		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); */
	}
}
コード例 #15
0
ファイル: tfa.c プロジェクト: mknapik/avr-MAC
/**
 * @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;

    /* Disable all trx interrupts */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_NONE);

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

    /* Check if supply voltage is within lower range */
    pal_trx_bit_write(SR_BATMON_HR, HIGH_RANGE_DISABLED);
    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_NOT_VALID)
    {
        /* 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_NOT_VALID)
        {
            /* below lower limit */
            mv = 0x0000;
        }
        range = LOW;
    }
    else
    {
        /* Higher range */
        pal_trx_bit_write(SR_BATMON_HR, HIGH_RANGE_ENABLED);
        /* 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_VALID)
        {
            /* above upper limit */
            mv = 0xFFFF;
        }
        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_NOT_VALID)
            {
                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);
    if (previous_trx_status == TRX_SLEEP)
    {
        set_trx_state(CMD_SLEEP);
    }

    /* 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 */
    pal_trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT);

    return mv;
}