⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radio.c

📁 Contiki是一个开源
💻 C
📖 第 1 页 / 共 4 页
字号:
/*   Copyright (c) 2008, Swedish Institute of Computer Science *  All rights reserved. * *  Additional fixes for AVR contributed by: *      Colin O'Flynn coflynn@newae.com *      Eric Gnoske egnoske@gmail.com *      Blake Leverett bleverett@gmail.com *      Mike Vidales mavida404@gmail.com *      Kevin Brown kbrown3@uccs.edu *      Nate Bohlmann nate@elfwerks.com * *   All rights reserved. * *   Redistribution and use in source and binary forms, with or without *   modification, are permitted provided that the following conditions are met: * *   * Redistributions of source code must retain the above copyright *     notice, this list of conditions and the following disclaimer. *   * Redistributions in binary form must reproduce the above copyright *     notice, this list of conditions and the following disclaimer in *     the documentation and/or other materials provided with the *     distribution. *   * Neither the name of the copyright holders nor the names of *     contributors may be used to endorse or promote products derived *     from this software without specific prior written permission. * *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *  POSSIBILITY OF SUCH DAMAGE. * * $Id: radio.c,v 1.2 2008/10/14 18:37:28 c_oflynn Exp $*//** *  \brief This module contains the radio driver code for the Atmel *  AT86RF230, '231, and '212 chips. * *  \author Blake Leverett <bleverett@gmail.com> *          Mike Vidales <mavida404@gmail.com> *          Eric Gnoske <egnoske@gmail.com> **//**  \addtogroup wireless * @{ *//** *  \defgroup radiorf230 RF230 interface * @{ *//** *  \file *  This file contains radio driver code. * *//*============================ INCLUDE =======================================*/#include <stdlib.h>#include <util/delay.h>#include "radio.h"#include "hal.h"#include "process.h"#include "sicslowmac.h"#include "frame.h"/*============================ MACROS ========================================*/#define RADIO_CCA_DONE_MASK     (1 << 7) /**<  Mask used to check the CCA_DONE bit. */#define RADIO_CCA_IDLE_MASK     (1 << 6) /**<  Mask used to check the CCA_STATUS bit. */#define RADIO_START_CCA (1) /**<  Value in the CCA_REQUEST subregister that initiate a cca. */#define RADIO_TRANSMISSION_SUCCESS  (0)#define RADIO_BUSY_CHANNEL          (3)#define RADIO_MIN_IEEE_FRAME_LENGTH (5)/*============================ TYPEDEFS ======================================*//** \brief  This enumeration defines the necessary timing information for the *          AT86RF230 radio transceiver. All times are in microseconds. * *          These constants are extracted from the datasheet. */typedef enum{    TIME_TO_ENTER_P_ON               = 510, /**<  Transition time from VCC is applied to P_ON. */    TIME_P_ON_TO_TRX_OFF             = 510, /**<  Transition time from P_ON to TRX_OFF. */    TIME_SLEEP_TO_TRX_OFF            = 880, /**<  Transition time from SLEEP to TRX_OFF. */    TIME_RESET                       = 6,   /**<  Time to hold the RST pin low during reset */    TIME_ED_MEASUREMENT              = 140, /**<  Time it takes to do a ED measurement. */    TIME_CCA                         = 140, /**<  Time it takes to do a CCA. */    TIME_PLL_LOCK                    = 150, /**<  Maximum time it should take for the PLL to lock. */    TIME_FTN_TUNING                  = 25,  /**<  Maximum time it should take to do the filter tuning. */    TIME_NOCLK_TO_WAKE               = 6,   /**<  Transition time from *_NOCLK to being awake. */    TIME_CMD_FORCE_TRX_OFF           = 1,    /**<  Time it takes to execute the FORCE_TRX_OFF command. */    TIME_TRX_OFF_TO_PLL_ACTIVE       = 180, /**<  Transition time from TRX_OFF to: RX_ON, PLL_ON, TX_ARET_ON and RX_AACK_ON. */    TIME_STATE_TRANSITION_PLL_ACTIVE = 1, /**<  Transition time from PLL active state to another. */}radio_trx_timing_t;/*============================ VARIABLES =====================================*/static hal_rx_start_isr_event_handler_t user_rx_event;static hal_trx_end_isr_event_handler_t user_trx_end_event;static radio_rx_callback rx_frame_callback;static uint8_t rssi_val;static uint8_t rx_mode;uint8_t rxMode = RX_AACK_ON;static hal_rx_frame_t rx_frame;static parsed_frame_t parsed_frame;/*============================ PROTOTYPES ====================================*/bool radio_is_sleeping(void);static void radio_rx_start_event(uint32_t const isr_timestamp, uint8_t const frame_length);static void radio_trx_end_event(uint32_t const isr_timestamp);/** \brief  Initialize the Transceiver Access Toolbox and lower layers. * *          If the initialization is successful the radio transceiver will be in *          TRX_OFF state. * *  \note  This function must be called prior to any of the other functions in *         this file! Can be called from any transceiver state. * *  \param cal_rc_osc If true, the radio's accurate clock is used to calibrate the *                    CPU's internal RC oscillator. * *  \param rx_event Optional pointer to a user-defined function to be called on an *                  RX_START interrupt.  Use NULL for no handler. * *  \param trx_end_event Optional pointer to a user-defined function to be called on an *                  TRX_END interrupt.  Use NULL for no handler. * *  \param rx_callback Optional pointer to a user-defined function that receives *         a frame from the radio one byte at a time.  If the index parameter to *         this callback is 0xff, then the function should reset its state and prepare *         for a frame from the radio, with one call per byte. * *  \retval RADIO_SUCCESS     The radio transceiver was successfully initialized *                          and put into the TRX_OFF state. *  \retval RADIO_UNSUPPORTED_DEVICE  The connected device is not an Atmel *                                  AT86RF230 radio transceiver. *  \retval RADIO_TIMED_OUT   The radio transceiver was not able to initialize and *                          enter TRX_OFF state within the specified time. */radio_status_tradio_init(bool cal_rc_osc,           hal_rx_start_isr_event_handler_t rx_event,           hal_trx_end_isr_event_handler_t trx_end_event,           radio_rx_callback rx_callback){    radio_status_t init_status = RADIO_SUCCESS;    delay_us(TIME_TO_ENTER_P_ON);    /*  calibrate oscillator */    if (cal_rc_osc){        calibrate_rc_osc_32k();    }    /* Initialize Hardware Abstraction Layer. */    hal_init();    radio_reset_trx(); /* Do HW reset of radio transeiver. */    /* Force transition to TRX_OFF. */    hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);    delay_us(TIME_P_ON_TO_TRX_OFF); /* Wait for the transition to be complete. */    if (radio_get_trx_state() != TRX_OFF){        init_status = RADIO_TIMED_OUT;    } else {        /* Read Version Number */        uint8_t version_number = hal_register_read(RG_VERSION_NUM);        if ((version_number != RF230_REVA) && (version_number != RF230_REVB))            init_status = RADIO_UNSUPPORTED_DEVICE;        else {            if (hal_register_read(RG_MAN_ID_0) != SUPPORTED_MANUFACTURER_ID)                init_status = RADIO_UNSUPPORTED_DEVICE;    else        hal_register_write(RG_IRQ_MASK, RF230_SUPPORTED_INTERRUPT_MASK);        }    }    /*  set callbacks for events.  Save user's rx_event, which we will */    /*  call from radio_rx_start_event().  Same with trx_end */    user_rx_event = rx_event;    user_trx_end_event = trx_end_event;    hal_set_rx_start_event_handler(radio_rx_start_event);    hal_set_trx_end_event_handler(radio_trx_end_event);    rx_frame_callback = rx_callback;    return init_status;}/*---------------------------------------------------------------------------*/uint8_t *radio_frame_data(void){        return rx_frame.data;}uint8_tradio_frame_length(void){        return rx_frame.length;}/*---------------------------------------------------------------------------*/static voidradio_rx_start_event(uint32_t const isr_timestamp, uint8_t const frame_length){    /*  save away RSSI */    rssi_val =  hal_subregister_read( SR_RSSI );    /*  call user's rx_start event handler */    if (user_rx_event)        user_rx_event(isr_timestamp, frame_length);}/*---------------------------------------------------------------------------*/uint8_tradio_get_saved_rssi_value(void){    return rssi_val;}/*---------------------------------------------------------------------------*/static voidradio_trx_end_event(uint32_t const isr_timestamp){    volatile uint8_t status;    /*  call user's trx_end event handler */    if (user_trx_end_event){        user_trx_end_event(isr_timestamp);        return;    }    if (rx_mode){        /* radio has received frame, store it away */        parsed_frame.time = isr_timestamp;        parsed_frame.rssi = rssi_val;                hal_frame_read(&rx_frame, NULL);        rx_frame_parse(&rx_frame, &parsed_frame);        }    if (!rx_mode){        /*  Put radio back into receive mode. */        radio_set_trx_state(TRX_OFF);        radio_set_trx_state(rxMode);        /*  transmit mode, put end-of-transmit event in queue */        event_object_t event;        event.event = 0;        event.data = 0;        status = hal_subregister_read(SR_TRAC_STATUS);        switch(status){        case TRAC_SUCCESS:        case TRAC_SUCCESS_DATA_PENDING:            event.event = MAC_EVENT_ACK;            break;        case TRAC_NO_ACK:        case TRAC_CHANNEL_ACCESS_FAILURE:            event.event = MAC_EVENT_NACK;            break;        case TRAC_SUCCESS_WAIT_FOR_ACK:            /*  should only happen in RX mode */        case TRAC_INVALID:            /*  should never happen here */        default:            break;        }        if (event.event)            mac_put_event(&event);        process_post(&mac_process, event.event, event.data);    }}/*----------------------------------------------------------------------------*//** \brief  This function will return the channel used by the radio transceiver. * *  \return Current channel, 11 to 26. */uint8_tradio_get_operating_channel(void){    return hal_subregister_read(SR_CHANNEL);}/*----------------------------------------------------------------------------*//** \brief This function will change the operating channel. * *  \param  channel New channel to operate on. Must be between 11 and 26. * *  \retval RADIO_SUCCESS New channel set. *  \retval RADIO_WRONG_STATE Transceiver is in a state where the channel cannot *                          be changed (SLEEP). *  \retval RADIO_INVALID_ARGUMENT Channel argument is out of bounds. *  \retval RADIO_TIMED_OUT The PLL did not lock within the specified time. */radio_status_tradio_set_operating_channel(uint8_t channel){    /*Do function parameter and state check.*/    if ((channel < RF230_MIN_CHANNEL) ||        (channel > RF230_MAX_CHANNEL)){        return RADIO_INVALID_ARGUMENT;    }    if (radio_is_sleeping() == true){        return RADIO_WRONG_STATE;    }    if (radio_get_operating_channel() == channel){        return RADIO_SUCCESS;    }    /*Set new operating channel.*/    hal_subregister_write(SR_CHANNEL, channel);    /* Read current state and wait for the PLL_LOCK interrupt if the */    /* radio transceiver is in either RX_ON or PLL_ON. */    uint8_t trx_state = radio_get_trx_state();    if ((trx_state == RX_ON) ||        (trx_state == PLL_ON)){        delay_us(TIME_PLL_LOCK);    }    radio_status_t channel_set_status = RADIO_TIMED_OUT;    /* Check that the channel was set properly. */    if (radio_get_operating_channel() == channel){        channel_set_status = RADIO_SUCCESS;    }    return channel_set_status;}/*----------------------------------------------------------------------------*//** \brief This function will read and return the output power level.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -