📄 mrfi_radio.c
字号:
/**************************************************************************************************
Revised: $Date: 2009-01-13 12:04:00 -0700 (Wed, 13 Jan 2009) $
Revision: $Revision: 18768 $
Copyright 2007-2009 Texas Instruments Incorporated. All rights reserved.
IMPORTANT: Your use of this Software is limited to those specific rights granted under
the terms of a software license agreement between the user who downloaded the software,
his/her employer (which must be your employer) and Texas Instruments Incorporated (the
"License"). You may not use this Software unless you agree to abide by the terms of the
License. The License limits your use, and you acknowledge, that the Software may not be
modified, copied or distributed unless embedded on a Texas Instruments microcontroller
or used solely and exclusively in conjunction with a Texas Instruments radio frequency
transceiver, which is integrated into your product. Other than for the foregoing purpose,
you may not use, reproduce, copy, prepare derivative works of, modify, distribute,
perform, display or sell this Software and/or its documentation for any purpose.
YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE PROVIDED WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY
WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE
THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY
INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST
DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY
THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
Should you have any questions regarding your right to use this Software,
contact Texas Instruments Incorporated at www.TI.com.
**************************************************************************************************/
/* ~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=
* MRFI (Minimal RF Interface)
* Radios: CC2500, CC1100, CC1101
* Primary code file for supported radios.
* ~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=
*/
/* ------------------------------------------------------------------------------------------------
* Includes
* ------------------------------------------------------------------------------------------------
*/
#include "App.h"
#include <string.h>
#include "mrfi.h"
//#include "bsp.h"
//#include "bsp_macros.h"
//#include "bsp_external/mrfi_board_defs.h"
#include "app.h"
#include "mrfi_defs.h"
#include "mrfi_spi.h"
//#include "../common/mrfi_f1f2.h"
#include "mrfi_f1f2.h"
#include "smartrf_CC2500.h"
#include "mrfi_spi.h"
/* ------------------------------------------------------------------------------------------------
* Defines
* ------------------------------------------------------------------------------------------------
*/
#if (defined MRFI_CC2500)
#define MRFI_RSSI_OFFSET 72 /* no units */
/* Worst case wait period in RX state before RSSI becomes valid.
* These numbers are from Design Note DN505 with added safety margin.
*/
#define MRFI_RSSI_VALID_DELAY_US 1000
#elif (defined MRFI_CC1100)
#define MRFI_RSSI_OFFSET 79 /* no units */
/* Worst case wait period in RX state before RSSI becomes valid.
* These numbers are from Design Note DN505 with added safety margin.
*/
#define MRFI_RSSI_VALID_DELAY_US 1300
#elif (defined MRFI_CC1101) || (defined MRFI_CC1100E_470) || (defined MRFI_CC1100E_950)
#define MRFI_RSSI_OFFSET 74 /* no units */
/* Worst case wait period in RX state before RSSI becomes valid.
* These numbers are from Design Note DN505 with added safety margin.
*/
#define MRFI_RSSI_VALID_DELAY_US 1300
#else
#error "ERROR: RSSI offset value not defined for this radio"
#endif
#define MRFI_LENGTH_FIELD_OFS __mrfi_LENGTH_FIELD_OFS__
#define MRFI_LENGTH_FIELD_SIZE __mrfi_LENGTH_FIELD_SIZE__
#define MRFI_HEADER_SIZE __mrfi_HEADER_SIZE__
#define MRFI_FRAME_BODY_OFS __mrfi_DST_ADDR_OFS__
#define MRFI_BACKOFF_PERIOD_USECS __mrfi_BACKOFF_PERIOD_USECS__
#define MRFI_RANDOM_OFFSET 67
#define MRFI_RANDOM_MULTIPLIER 109
#define MRFI_MIN_SMPL_FRAME_SIZE (MRFI_HEADER_SIZE + NWK_HDR_SIZE)
/* rx metrics definitions, known as appended "packet status bytes" in datasheet parlance */
#define MRFI_RX_METRICS_CRC_OK_MASK __mrfi_RX_METRICS_CRC_OK_MASK__
#define MRFI_RX_METRICS_LQI_MASK __mrfi_RX_METRICS_LQI_MASK__
/* GDO functionality */
#define MRFI_GDO_SYNC 6
#define MRFI_GDO_CCA 9
#define MRFI_GDO_PA_PD 27 /* low when transmit is active, low during sleep */
#define MRFI_GDO_LNA_PD 28 /* low when receive is active, low during sleep */
/* ---------- Radio Abstraction ---------- */
#if (defined MRFI_CC1100)
#define MRFI_RADIO_PARTNUM 0x00
#define MRFI_RADIO_MIN_VERSION 3
#elif (defined MRFI_CC1101)
#define MRFI_RADIO_PARTNUM 0x00
#define MRFI_RADIO_MIN_VERSION 4
#elif (defined MRFI_CC1100E_470)
#define MRFI_RADIO_PARTNUM 0x00
#define MRFI_RADIO_MIN_VERSION 5
#elif (defined MRFI_CC1100E_950)
#define MRFI_RADIO_PARTNUM 0x00
#define MRFI_RADIO_MIN_VERSION 5
#elif (defined MRFI_CC2500)
#define MRFI_RADIO_PARTNUM 0x80
#define MRFI_RADIO_MIN_VERSION 3
#else
#error "ERROR: Missing or unrecognized radio."
#endif
/* GDO0 output pin configuration */
#define MRFI_SETTING_IOCFG0 MRFI_GDO_SYNC
/* GDO2 output pin configuration */
#define MRFI_SETTING_IOCFG2 MRFI_GDO_PA_PD
/* Main Radio Control State Machine control configuration:
* Auto Calibrate - when going from IDLE to RX/TX
* PO_TIMEOUT is extracted from SmartRF setting.
* XOSC is OFF in Sleep state.
*/
#define MRFI_SETTING_MCSM0 (0x10 | (SMARTRF_SETTING_MCSM0 & (BV(2)|BV(3))))
/* Main Radio Control State Machine control configuration:
* - Remain RX state after RX
* - Go to IDLE after TX
* - RSSI below threshold and NOT receiving.
*/
#define MRFI_SETTING_MCSM1 0x3C
/*
* Packet Length - Setting for maximum allowed packet length.
* The PKTLEN setting does not include the length field but maximum frame size does.
* Subtract length field size from maximum frame size to get value for PKTLEN.
*/
#define MRFI_SETTING_PKTLEN (MRFI_MAX_FRAME_SIZE - MRFI_LENGTH_FIELD_SIZE)
/* Packet automation control - Original value except WHITE_DATA is extracted from SmartRF setting. */
#define MRFI_SETTING_PKTCTRL0 (0x05 | (SMARTRF_SETTING_PKTCTRL0 & BV(6)))
/* FIFO threshold - this register has fields that need to be configured for the CC1101 */
#define MRFI_SETTING_FIFOTHR (0x07 | (SMARTRF_SETTING_FIFOTHR & (BV(4)|BV(5)|BV(6))))
/* Max time we can be in a critical section within the delay function.
* This could be fine-tuned by observing the overhead is calling the bsp delay
* function. The overhead should be very small compared to this value.
* Note that the max value for this must be less than 19 usec with the
* default CLKCON.TICKSPD and CLKCON.CLOCKSPD settings and external 26 MHz
* crystal as a clock source (which we use).
*
* Be careful of direct calls to Mrfi_DelayUsec().
*/
#define MRFI_MAX_DELAY_US 16 /* usec */
#define MRFI_PKTSTATUS_CCA BV(4)
#define MRFI_PKTSTATUS_CS BV(6)
/* The SW timer is calibrated by adjusting the call to the microsecond delay
* routine. This allows maximum calibration control with repects to the longer
* times requested by applicationsd and decouples internal from external calls
* to the microsecond routine which can be calibrated independently.
*/
#if defined(SW_TIMER)
#define APP_USEC_VALUE 496
#else
#define APP_USEC_VALUE 1000
#endif
/* ------------------------------------------------------------------------------------------------
* Macros
* ------------------------------------------------------------------------------------------------
*/
//#define MRFI_SYNC_PIN_IS_HIGH() MRFI_GDO0_PIN_IS_HIGH()
//#define MRFI_ENABLE_SYNC_PIN_INT() MRFI_ENABLE_GDO0_INT()
//#define MRFI_DISABLE_SYNC_PIN_INT() MRFI_DISABLE_GDO0_INT()
//#define MRFI_SYNC_PIN_INT_IS_ENABLED() MRFI_GDO0_INT_IS_ENABLED()
//#define MRFI_CLEAR_SYNC_PIN_INT_FLAG() MRFI_CLEAR_GDO0_INT_FLAG()
//#define MRFI_SYNC_PIN_INT_FLAG_IS_SET() MRFI_GDO0_INT_FLAG_IS_SET()
//#define MRFI_CONFIG_SYNC_PIN_FALLING_EDGE_INT() MRFI_CONFIG_GDO0_FALLING_EDGE_INT()
#define MRFI_SYNC_PIN_IS_HIGH() (GPIO_ReadInput(CGDOPort) & CGDO0)
#define MRFI_ENABLE_SYNC_PIN_INT() (LPC_GPIO2->IE |= CGDO0)
#define MRFI_DISABLE_SYNC_PIN_INT() (LPC_GPIO2->IE &= ~(CGDO0))
#define MRFI_SYNC_PIN_INT_IS_ENABLED()
#define MRFI_CLEAR_SYNC_PIN_INT_FLAG() (LPC_GPIO2->IC |= CGDO0)
#define MRFI_SYNC_PIN_INT_FLAG_IS_SET() (LPC_GPIO2->MIS & CGDO0)
#define MRFI_CONFIG_SYNC_PIN_EDGE_INT() (LPC_GPIO2->IS &= ~CGDO0)
#define MRFI_CONFIG_SYNC_PIN_RISING_EDGE_INT() (LPC_GPIO2->IEV |= CGDO0)
#define MRFI_CONFIG_SYNC_PIN_FALLING_EDGE_INT() (LPC_GPIO2->IEV &= ~(CGDO0))
//#define MRFI_PAPD_PIN_IS_HIGH() MRFI_SYNC_PIN_IS_HIGH()
//#define MRFI_CLEAR_PAPD_PIN_INT_FLAG() MRFI_CLEAR_SYNC_PIN_INT_FLAG()
//#define MRFI_PAPD_INT_FLAG_IS_SET() MRFI_SYNC_PIN_INT_FLAG_IS_SET()
//#define MRFI_CONFIG_PAPD_FALLING_EDGE_INT() MRFI_CONFIG_SYNC_PIN_FALLING_EDGE_INT()
#define MRFI_PAPD_PIN_IS_HIGH() GPIO_ReadInput(CGDOPort) & CGDO2
#define MRFI_CLEAR_PAPD_PIN_INT_FLAG() (LPC_GPIO2->IC |= CGDO2)
#define MRFI_PAPD_INT_FLAG_IS_SET() (LPC_GPIO2->MIS & CGDO2)
#define MRFI_CONFIG_PAPD_RISING_EDGE_INT() (GPIOINT->IO2IntEnR |= CGDO2)
#define MRFI_CONFIG_PAPD_FALLING_EDGE_INT() (GPIOINT->IO2IntEnF |= CGDO2)
#define MRFI_CONFIG_GDO0_AS_PAPD_SIGNAL() mrfiSpiWriteReg(IOCFG0, MRFI_GDO_PA_PD)
#define MRFI_CONFIG_GDO0_AS_SYNC_SIGNAL() mrfiSpiWriteReg(IOCFG0, MRFI_GDO_SYNC)
/* There is no bit in h/w to tell if RSSI in the register is valid or not.
* The hardware needs to be in RX state for a certain amount of time before
* a valid RSSI value is calculated and placed in the register. This min
* wait time is defined by MRFI_BOARD_RSSI_VALID_DELAY_US. We don't need to
* add such delay every time RSSI value is needed. If the Carier Sense signal
* is high or CCA signal is high, we know that the RSSI value must be valid.
* We use that knowledge to reduce our wait time. We break down the delay loop
* in multiple chunks and during each iteration, check for the CS and CCA
* signal. If either of these signals is high, we return immediately. Else,
* we wait for the max delay specified.
*/
static void Mrfi_DelayUsec(uint16_t howLong);
void MRFI_RSSI_VALID_WAIT( void )
{
int16_t delay = MRFI_RSSI_VALID_DELAY_US;
do
{
if(mrfiSpiReadReg(PKTSTATUS) & (MRFI_PKTSTATUS_CCA | MRFI_PKTSTATUS_CS))
{
break;
}
Mrfi_DelayUsec(64); /* sleep */
delay -= 64;
}while(delay > 0);
}
#define MRFI_STROBE_IDLE_AND_WAIT() \
{ \
mrfiSpiCmdStrobe( SIDLE ); \
while (mrfiSpiCmdStrobe( SNOP ) & 0xF0) ; \
}
/* ------------------------------------------------------------------------------------------------
* Local Constants
* ------------------------------------------------------------------------------------------------
*/
static const uint8_t mrfiRadioCfg[][2] =
{
/* internal radio configuration */
{ IOCFG0, MRFI_SETTING_IOCFG0 },
/* { IOCFG2, MRFI_SETTING_IOCFG2 },*/
{ MCSM1, MRFI_SETTING_MCSM1 }, /* CCA mode, RX_OFF_MODE and TX_OFF_MODE */
{ MCSM0, MRFI_SETTING_MCSM0 }, /* AUTO_CAL and XOSC state in sleep */
{ PKTLEN, MRFI_SETTING_PKTLEN },
{ PKTCTRL0, MRFI_SETTING_PKTCTRL0 },
#ifdef MRFI_CC1101
{ FIFOTHR, MRFI_SETTING_FIFOTHR },
#endif
/* imported SmartRF radio configuration */
{ FSCTRL1, SMARTRF_SETTING_FSCTRL1 },
{ FSCTRL0, SMARTRF_SETTING_FSCTRL0 },
{ FREQ2, SMARTRF_SETTING_FREQ2 },
{ FREQ1, SMARTRF_SETTING_FREQ1 },
{ FREQ0, SMARTRF_SETTING_FREQ0 },
{ MDMCFG4, SMARTRF_SETTING_MDMCFG4 },
{ MDMCFG3, SMARTRF_SETTING_MDMCFG3 },
{ MDMCFG2, SMARTRF_SETTING_MDMCFG2 },
{ MDMCFG1, SMARTRF_SETTING_MDMCFG1 },
{ MDMCFG0, SMARTRF_SETTING_MDMCFG0 },
{ DEVIATN, SMARTRF_SETTING_DEVIATN },
{ FOCCFG, SMARTRF_SETTING_FOCCFG },
{ BSCFG, SMARTRF_SETTING_BSCFG },
{ AGCCTRL2, SMARTRF_SETTING_AGCCTRL2 },
{ AGCCTRL1, SMARTRF_SETTING_AGCCTRL1 },
{ AGCCTRL0, SMARTRF_SETTING_AGCCTRL0 },
{ FREND1, SMARTRF_SETTING_FREND1 },
{ FREND0, SMARTRF_SETTING_FREND0 },
{ FSCAL3, SMARTRF_SETTING_FSCAL3 },
{ FSCAL2, SMARTRF_SETTING_FSCAL2 },
{ FSCAL1, SMARTRF_SETTING_FSCAL1 },
{ FSCAL0, SMARTRF_SETTING_FSCAL0 },
{ TEST2, SMARTRF_SETTING_TEST2 },
{ TEST1, SMARTRF_SETTING_TEST1 },
{ TEST0, SMARTRF_SETTING_TEST0 },
};
/* ------------------------------------------------------------------------------------------------
* Local Prototypes
* ------------------------------------------------------------------------------------------------
*/
void MRFI_GpioIsr(void); /* this called from mrfi_board.c */
//static void Mrfi_SyncPinRxIsr(void);
void Mrfi_SyncPinRxIsr(void);
void Mrfi_RxModeOn(void);
//static void Mrfi_RandomBackoffDelay(void);
//static void Mrfi_RxModeOff(void);
void Mrfi_RxModeOff(void);
//static void Mrfi_DelayUsec(uint16_t howLong);
static void Mrfi_DelayUsecSem(uint16_t howLong);
static int8_t Mrfi_CalculateRssi(uint8_t rawValue);
/* ------------------------------------------------------------------------------------------------
* Local Variables
* ------------------------------------------------------------------------------------------------
*/
//static uint8_t mrfiRadioState = MRFI_RADIO_STATE_UNKNOWN;
uint8_t mrfiRadioState = MRFI_RADIO_STATE_UNKNOWN;
static mrfiPacket_t mrfiIncomingPacket;
static uint8_t mrfiRndSeed = 0;
/* reply delay support */
static volatile uint8_t sKillSem = 0;
static volatile uint8_t sReplyDelayContext = 0;
static uint16_t sReplyDelayScalar = 0;
static uint16_t sBackoffHelper = 0;
/**************************************************************************************************
* @fn MRFI_Init
*
* @brief Initialize MRFI.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void MRFI_Init(void)
{
int iTemp;//,i;
EVENT_InitTypeDef Event_InitStruct;
/* ------------------------------------------------------------------
* Initialization
* -----------------
*/
memset(&mrfiIncomingPacket, 0x0, sizeof(mrfiIncomingPacket));
/* initialize GPIO pins */
//MRFI_CONFIG_GDO0_PIN_AS_INPUT();
GPIO_SetDir(CGDOPort, CGDO0, 0);
GPIO_SetDir(CGDOPort, CGDO2, 0);
/* initialize SPI */
SPI_GPIO_Configuration();
GPIO_SetBits(SCLKPort, CSPISCLK);
GPIO_ResetBits(CSPIPort, CSPISI);
/* ------------------------------------------------------------------
* Radio power-up reset
* ----------------------
*/
GPIO_SetBits(CSPort, CSPICSN);
MRFI_DELAY(10);
/* pulse CSn low then high */
GPIO_ResetBits(CSPort, CSPICSN);
MRFI_DELAY(10);
GPIO_SetBits(CSPort, CSPICSN);
/* hold CSn high for at least 40 microseconds */
MRFI_DELAY(20000);
/* pull CSn low and wait for SO to go low */
GPIO_ResetBits(CSPort, CSPICSN);
while( GPIO_ReadInput(CSPIPort) & CSPISO );
/* directly send strobe command - cannot use function as it affects CSn pin */
while ( (LPC_SSP0->SR & (SSP_SR_TNF|SSP_SR_BSY)) != SSP_SR_TNF );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -