我用的 sdk 为 simplelink_cc13x0_sdk_2_40_00_20,在这个rfWsnNodeExtFlashOadClient-CC310_LAUNCHXL_tirtos例子上增加pa (CC1190)的功能。现场测试效果不怎么好,请帮我看一下我的代码。
修改的文件为 EasyLink.c
/*
* Copyright (c) 2015-2018, Texas Instruments Incorporated
* 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 Texas Instruments Incorporated nor the names of
* its 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.
*/
* Copyright (c) 2015-2018, Texas Instruments Incorporated
* 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 Texas Instruments Incorporated nor the names of
* its 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.
*/
/***** Includes *****/
#include "EasyLink.h"
#include "easylink_config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include "EasyLink.h"
#include "easylink_config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include <ti/drivers/PIN.h>
#ifndef USE_DMM
#include <ti/drivers/rf/RF.h>
#else
#include <dmm/dmm_rfmap.h>
#endif //USE_DMM
#include <ti/drivers/rf/RF.h>
#else
#include <dmm/dmm_rfmap.h>
#endif //USE_DMM
#include "Board.h"
/* TI Drivers */
#ifdef Board_SYSCONFIG_PREVIEW
#include <smartrf_settings/smartrf_settings.h>
#else
#include <smartrf_settings/smartrf_settings.h>
#include <smartrf_settings/smartrf_settings_predefined.h>
#endif
#ifdef Board_SYSCONFIG_PREVIEW
#include <smartrf_settings/smartrf_settings.h>
#else
#include <smartrf_settings/smartrf_settings.h>
#include <smartrf_settings/smartrf_settings_predefined.h>
#endif
/* BIOS Header files */
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
/* XDCtools Header files */
#include <xdc/runtime/Error.h>
#include <xdc/runtime/Error.h>
#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
#include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
#include DeviceFamily_constructPath(driverlib/rf_prop_cmd.h)
#include DeviceFamily_constructPath(driverlib/chipinfo.h)
#include DeviceFamily_constructPath(inc/hw_memmap.h)
#include DeviceFamily_constructPath(inc/hw_fcfg1.h)
#include DeviceFamily_constructPath(inc/hw_ccfg.h)
#include DeviceFamily_constructPath(inc/hw_ccfg_simple_struct.h)
#include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
#include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
#include DeviceFamily_constructPath(driverlib/rf_prop_cmd.h)
#include DeviceFamily_constructPath(driverlib/chipinfo.h)
#include DeviceFamily_constructPath(inc/hw_memmap.h)
#include DeviceFamily_constructPath(inc/hw_fcfg1.h)
#include DeviceFamily_constructPath(inc/hw_ccfg.h)
#include DeviceFamily_constructPath(inc/hw_ccfg_simple_struct.h)
union setupCmd_t{
#if (defined Board_CC1352P1_LAUNCHXL) || (defined Board_CC1352P_2_LAUNCHXL) || \
(defined Board_CC1352P_4_LAUNCHXL)
rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t divSetup;
#else
rfc_CMD_PROP_RADIO_DIV_SETUP_t divSetup;
#endif
rfc_CMD_PROP_RADIO_SETUP_t setup;
};
#if (defined Board_CC1352P1_LAUNCHXL) || (defined Board_CC1352P_2_LAUNCHXL) || \
(defined Board_CC1352P_4_LAUNCHXL)
rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t divSetup;
#else
rfc_CMD_PROP_RADIO_DIV_SETUP_t divSetup;
#endif
rfc_CMD_PROP_RADIO_SETUP_t setup;
};
//Primary IEEE address location
#define EASYLINK_PRIMARY_IEEE_ADDR_LOCATION (FCFG1_BASE + FCFG1_O_MAC_15_4_0)
//Secondary IEEE address location
#define EASYLINK_SECONDARY_IEEE_ADDR_LOCATION (CCFG_BASE + CCFG_O_IEEE_MAC_0)
#define EASYLINK_PRIMARY_IEEE_ADDR_LOCATION (FCFG1_BASE + FCFG1_O_MAC_15_4_0)
//Secondary IEEE address location
#define EASYLINK_SECONDARY_IEEE_ADDR_LOCATION (CCFG_BASE + CCFG_O_IEEE_MAC_0)
#define EASYLINK_RF_EVENT_MASK ( RF_EventLastCmdDone | \
RF_EventCmdAborted | RF_EventCmdStopped | RF_EventCmdCancelled | \
RF_EventCmdPreempted )
RF_EventCmdAborted | RF_EventCmdStopped | RF_EventCmdCancelled | \
RF_EventCmdPreempted )
#define EASYLINK_RF_CMD_HANDLE_INVALID -1
#define EasyLink_CmdHandle_isValid(handle) (handle >= 0)
/* EasyLink Proprietary Header Configuration */
#define EASYLINK_PROP_TRX_SYNC_WORD 0x930B51DE
#define EASYLINK_PROP_HDR_NBITS 8U
#define EASYLINK_PROP_LEN_OFFSET 0U
#define EASYLINK_PROP_TRX_SYNC_WORD 0x930B51DE
#define EASYLINK_PROP_HDR_NBITS 8U
#define EASYLINK_PROP_LEN_OFFSET 0U
/* IEEE 802.15.4g Header Configuration
* _S indicates the shift for a given bit field
* _M indicates the mask required to isolate a given bit field
*/
#define EASYLINK_IEEE_TRX_SYNC_WORD 0x0055904E
#define EASYLINK_IEEE_HDR_NBITS 16U
#define EASYLINK_IEEE_LEN_OFFSET 0xFC
* _S indicates the shift for a given bit field
* _M indicates the mask required to isolate a given bit field
*/
#define EASYLINK_IEEE_TRX_SYNC_WORD 0x0055904E
#define EASYLINK_IEEE_HDR_NBITS 16U
#define EASYLINK_IEEE_LEN_OFFSET 0xFC
#define EASYLINK_IEEE_HDR_LEN_S 0U
#define EASYLINK_IEEE_HDR_LEN_M 0x00FFU
#define EASYLINK_IEEE_HDR_CRC_S 12U
#define EASYLINK_IEEE_HDR_CRC_M 0x1000U
#define EASYLINK_IEEE_HDR_WHTNG_S 11U
#define EASYLINK_IEEE_HDR_WHTNG_M 0x0800U
#define EASYLINK_IEEE_HDR_CRC_2BYTE 1U
#define EASYLINK_IEEE_HDR_CRC_4BYTE 0U
#define EASYLINK_IEEE_HDR_WHTNG_EN 1U
#define EASYLINK_IEEE_HDR_WHTNG_DIS 0U
#define EASYLINK_IEEE_HDR_LEN_M 0x00FFU
#define EASYLINK_IEEE_HDR_CRC_S 12U
#define EASYLINK_IEEE_HDR_CRC_M 0x1000U
#define EASYLINK_IEEE_HDR_WHTNG_S 11U
#define EASYLINK_IEEE_HDR_WHTNG_M 0x0800U
#define EASYLINK_IEEE_HDR_CRC_2BYTE 1U
#define EASYLINK_IEEE_HDR_CRC_4BYTE 0U
#define EASYLINK_IEEE_HDR_WHTNG_EN 1U
#define EASYLINK_IEEE_HDR_WHTNG_DIS 0U
#define EASYLINK_IEEE_HDR_CREATE(crc, whitening, length) { \
((crc << EASYLINK_IEEE_HDR_CRC_S) | (whitening << EASYLINK_IEEE_HDR_WHTNG_S) | \
((length << EASYLINK_IEEE_HDR_LEN_S) & EASYLINK_IEEE_HDR_LEN_M)) \
}
((crc << EASYLINK_IEEE_HDR_CRC_S) | (whitening << EASYLINK_IEEE_HDR_WHTNG_S) | \
((length << EASYLINK_IEEE_HDR_LEN_S) & EASYLINK_IEEE_HDR_LEN_M)) \
}
/* Common Configuration (Prop and IEEE) */
#define EASYLINK_HDR_LEN_NBITS 8U
#define EASYLINK_HDR_LEN_NBITS 8U
/* Return the size of the header rounded up to
* the nearest integer number of bytes
*/
#define EASYLINK_HDR_SIZE_NBYTES(x) (((x) >> 3U) + (((x) & 0x03) ? 1U : 0U))
* the nearest integer number of bytes
*/
#define EASYLINK_HDR_SIZE_NBYTES(x) (((x) >> 3U) + (((x) & 0x03) ? 1U : 0U))
/***** Prototypes *****/
static EasyLink_TxDoneCb txCb;
static EasyLink_ReceiveCb rxCb;
#if (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
static EasyLink_GetRandomNumber getRN;
#endif // (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
static EasyLink_TxDoneCb txCb;
static EasyLink_ReceiveCb rxCb;
#if (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
static EasyLink_GetRandomNumber getRN;
#endif // (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
/***** Variable declarations *****/
static RF_Object rfObject;
static RF_Handle rfHandle;
static RF_Handle rfHandle;
//Rx buffer includes data entry structure, hdr (len=1byte), dst addr (max of 8 bytes) and data
//which must be aligned to 4B
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN (rxBuffer, 4);
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 4
#elif defined(__GNUC__)
__attribute__((aligned(4)))
#else
#error This compiler is not supported.
#endif
static uint8_t rxBuffer[sizeof(rfc_dataEntryGeneral_t) + 1 +
EASYLINK_MAX_ADDR_SIZE +
EASYLINK_MAX_DATA_LENGTH];
//which must be aligned to 4B
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN (rxBuffer, 4);
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 4
#elif defined(__GNUC__)
__attribute__((aligned(4)))
#else
#error This compiler is not supported.
#endif
static uint8_t rxBuffer[sizeof(rfc_dataEntryGeneral_t) + 1 +
EASYLINK_MAX_ADDR_SIZE +
EASYLINK_MAX_DATA_LENGTH];
static dataQueue_t dataQueue;
static rfc_propRxOutput_t rxStatistics;
static rfc_propRxOutput_t rxStatistics;
//Tx buffer includes hdr (len=1 or 2 bytes), dst addr (max of 8 bytes) and data
static uint8_t txBuffer[2U + EASYLINK_MAX_ADDR_SIZE + EASYLINK_MAX_DATA_LENGTH];
static uint8_t txBuffer[2U + EASYLINK_MAX_ADDR_SIZE + EASYLINK_MAX_DATA_LENGTH];
// Addr size for Filter and Tx/Rx operations
// Set default to 1 byte addr to work with SmartRF studio default settings
// NOTE that it can take on values 0, 1, 2, 4 or 8
static uint8_t addrSize = EASYLINK_ADDR_SIZE;
// Set default to 1 byte addr to work with SmartRF studio default settings
// NOTE that it can take on values 0, 1, 2, 4 or 8
static uint8_t addrSize = EASYLINK_ADDR_SIZE;
// Header Size (in bytes) for Advanced Tx operations. For IEEE 802.15.4g modes
// it is 2 bytes, 1 for the rest
static uint8_t hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
// it is 2 bytes, 1 for the rest
static uint8_t hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
//Indicating that the API is initialized
static uint8_t configured = 0;
//Indicating that the API suspended
static uint8_t suspended = 0;
//Use an IEEE header for the Tx/Rx command
static bool useIeeeHeader = 0;
static uint8_t configured = 0;
//Indicating that the API suspended
static uint8_t suspended = 0;
//Use an IEEE header for the Tx/Rx command
static bool useIeeeHeader = 0;
//RF Params allowing configuration of the inactivity timeout, which is the time
//it takes for the radio to shut down when there are no commands in the queue
static RF_Params rfParams;
static bool rfParamsConfigured = 0;
//it takes for the radio to shut down when there are no commands in the queue
static RF_Params rfParams;
static bool rfParamsConfigured = 0;
//Flag used to indicate the multi client operation is enabled
static bool rfModeMultiClient = EASYLINK_ENABLE_MULTI_CLIENT;
static bool rfModeMultiClient = EASYLINK_ENABLE_MULTI_CLIENT;
//Async Rx timeout value
static uint32_t asyncRxTimeOut = EASYLINK_ASYNC_RX_TIMEOUT;
static uint32_t asyncRxTimeOut = EASYLINK_ASYNC_RX_TIMEOUT;
//local commands, contents will be defined by modulation type
static union setupCmd_t EasyLink_cmdPropRadioSetup;
static rfc_CMD_FS_t EasyLink_cmdFs;
static RF_Mode EasyLink_RF_prop;
static rfc_CMD_PROP_TX_ADV_t EasyLink_cmdPropTxAdv;
static rfc_CMD_PROP_RX_ADV_t EasyLink_cmdPropRxAdv;
#if (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
static rfc_CMD_PROP_CS_t EasyLink_cmdPropCs;
#endif // (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
static union setupCmd_t EasyLink_cmdPropRadioSetup;
static rfc_CMD_FS_t EasyLink_cmdFs;
static RF_Mode EasyLink_RF_prop;
static rfc_CMD_PROP_TX_ADV_t EasyLink_cmdPropTxAdv;
static rfc_CMD_PROP_RX_ADV_t EasyLink_cmdPropRxAdv;
#if (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
static rfc_CMD_PROP_CS_t EasyLink_cmdPropCs;
#endif // (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
// The table for setting the Rx Address Filters
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN (addrFilterTable, 4);
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 4
#elif defined(__GNUC__)
__attribute__((aligned(4)))
#endif
static uint8_t addrFilterTable[EASYLINK_MAX_ADDR_FILTERS * EASYLINK_MAX_ADDR_SIZE] = EASYLINK_ADDR_FILTER_TABLE;
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN (addrFilterTable, 4);
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 4
#elif defined(__GNUC__)
__attribute__((aligned(4)))
#endif
static uint8_t addrFilterTable[EASYLINK_MAX_ADDR_FILTERS * EASYLINK_MAX_ADDR_SIZE] = EASYLINK_ADDR_FILTER_TABLE;
// Used as a pointer to an entry in the EasyLink_rfSettings array
static EasyLink_RfSetting *rfSetting = 0;
static EasyLink_RfSetting *rfSetting = 0;
// Default inactivity timeout of 1 ms
static uint32_t inactivityTimeout = EASYLINK_IDLE_TIMEOUT;
static uint32_t inactivityTimeout = EASYLINK_IDLE_TIMEOUT;
//Mutex for locking the RF driver resource
static Semaphore_Handle busyMutex;
static Semaphore_Handle busyMutex;
//Handle for last Async command, which is needed by EasyLink_abort
static RF_CmdHandle asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
static RF_CmdHandle asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
/* Set Default parameters structure */
static const EasyLink_Params EasyLink_defaultParams = EASYLINK_PARAM_CONFIG;
static const EasyLink_Params EasyLink_defaultParams = EASYLINK_PARAM_CONFIG;
static EasyLink_Params EasyLink_params;
static PIN_Handle paPinHandle;
static PIN_State paPinState;
static PIN_State paPinState;
PIN_Config paPinTable[] = {
Board_PALNA_HGM | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
Board_PALNA_LNA | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
Board_PALNA_PA | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_TERMINATE
};
Board_PALNA_LNA | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
Board_PALNA_PA | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_TERMINATE
};
/* Check the address size (in bytes) is either 0 or a power of 2, and less than
* the maximum allowed size
*/
static bool isAddrSizeValid(uint8_t ui8AddrSize)
{
return((ui8AddrSize == 0) || (!(ui8AddrSize & (ui8AddrSize - 1)) && \
(ui8AddrSize <= EASYLINK_MAX_ADDR_SIZE)));
}
void EasyLink_Params_init(EasyLink_Params *params)
{
*params = EasyLink_defaultParams;
}
{
*params = EasyLink_defaultParams;
}
//Create an Advanced Tx command from a Tx Command
void createTxAdvFromTx(rfc_CMD_PROP_TX_ADV_t *dst, rfc_CMD_PROP_TX_t *src)
{
memset(dst, 0 , sizeof(rfc_CMD_PROP_TX_ADV_t));
dst->commandNo = CMD_PROP_TX_ADV;
memcpy(&(dst->status), &(src->status), offsetof(rfc_CMD_PROP_TX_ADV_t, pktConf) -
offsetof(rfc_CMD_PROP_TX_ADV_t, status));
dst->pktConf.bFsOff = src->pktConf.bFsOff;
dst->pktConf.bUseCrc = src->pktConf.bUseCrc;
dst->pktLen = src->pktLen;
dst->syncWord = src->syncWord;
}
void createTxAdvFromTx(rfc_CMD_PROP_TX_ADV_t *dst, rfc_CMD_PROP_TX_t *src)
{
memset(dst, 0 , sizeof(rfc_CMD_PROP_TX_ADV_t));
dst->commandNo = CMD_PROP_TX_ADV;
memcpy(&(dst->status), &(src->status), offsetof(rfc_CMD_PROP_TX_ADV_t, pktConf) -
offsetof(rfc_CMD_PROP_TX_ADV_t, status));
dst->pktConf.bFsOff = src->pktConf.bFsOff;
dst->pktConf.bUseCrc = src->pktConf.bUseCrc;
dst->pktLen = src->pktLen;
dst->syncWord = src->syncWord;
}
//Callback for Async Tx complete
static void txDoneCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
EasyLink_Status status;
static void txDoneCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
EasyLink_Status status;
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
Semaphore_post(busyMutex);
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
if (e & RF_EventLastCmdDone)
{
status = EasyLink_Status_Success;
}
else if ( (e & RF_EventCmdAborted) || (e & RF_EventCmdCancelled) || (e & RF_EventCmdPreempted) )
{
status = EasyLink_Status_Aborted;
}
else
{
status = EasyLink_Status_Tx_Error;
}
{
status = EasyLink_Status_Success;
}
else if ( (e & RF_EventCmdAborted) || (e & RF_EventCmdCancelled) || (e & RF_EventCmdPreempted) )
{
status = EasyLink_Status_Aborted;
}
else
{
status = EasyLink_Status_Tx_Error;
}
if (txCb != NULL)
{
txCb(status);
}
}
{
txCb(status);
}
}
#if (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
//Callback for Clear Channel Assessment Done
static void ccaDoneCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
RF_ScheduleCmdParams schParams_prop;
EasyLink_Status status = EasyLink_Status_Tx_Error;
RF_Op* pCmd = RF_getCmdOp(h, ch);
bool bCcaRunAgain = false;
static uint8_t be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
static uint32_t backOffTime;
//Callback for Clear Channel Assessment Done
static void ccaDoneCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
RF_ScheduleCmdParams schParams_prop;
EasyLink_Status status = EasyLink_Status_Tx_Error;
RF_Op* pCmd = RF_getCmdOp(h, ch);
bool bCcaRunAgain = false;
static uint8_t be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
static uint32_t backOffTime;
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
if (e & RF_EventLastCmdDone)
{
if(pCmd->status == PROP_DONE_IDLE)
{
// Carrier Sense operation ended with an idle channel,
// and the next op (TX) should have already taken place
// Failure to transmit is reflected in the default status,
// EasyLink_Status_Tx_Error, being set
if(pCmd->pNextOp->status == PROP_DONE_OK)
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
status = EasyLink_Status_Success;
// Reset the number of retries
be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
}
}
else if(pCmd->status == PROP_DONE_BUSY)
{
if(be > EASYLINK_MAX_CCA_BACKOFF_WINDOW)
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
// Reset the number of retries
be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
// CCA failed max number of retries
status = EasyLink_Status_Busy_Error;
}
else
{
// The back-off time is a random number chosen from 0 to 2^be,
// where 'be' goes from EASYLINK_MIN_CCA_BACKOFF_WINDOW
// to EASYLINK_MAX_CCA_BACKOFF_WINDOW. This number is then converted
// into EASYLINK_CCA_BACKOFF_TIMEUNITS units, and subsequently used to
// schedule the next CCA sequence. The variable 'be' is incremented each
// time, up to a pre-configured maximum, the back-off algorithm is run.
backOffTime = (getRN() & ((1 << be++)-1)) *
EasyLink_us_To_RadioTime(EASYLINK_CCA_BACKOFF_TIMEUNITS);
// running CCA again
bCcaRunAgain = true;
// The random number generator function returns a value in the range
// 0 to 2^15 - 1 and we choose the 'be' most significant bits as our
// back-off time in milliseconds (converted to RAT ticks)
pCmd->startTime = RF_getCurrentTime() + backOffTime;
// post the chained CS+TX command again while checking
// for a clear channel (CCA) before sending a packet
if(rfModeMultiClient)
{
schParams_prop.priority = RF_PriorityHigh;
asyncCmdHndl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropCs,
&schParams_prop, ccaDoneCallback, EASYLINK_RF_EVENT_MASK);
}
else
{
asyncCmdHndl = RF_postCmd(h, (RF_Op*)&EasyLink_cmdPropCs,
RF_PriorityHigh, ccaDoneCallback, EASYLINK_RF_EVENT_MASK);
}
}
}
else
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
// Reset the number of retries
be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
// The CS command status should be either IDLE or BUSY,
// all other status codes can be considered errors
// Status is set to the default, EasyLink_Status_Tx_Error
}
{
if(pCmd->status == PROP_DONE_IDLE)
{
// Carrier Sense operation ended with an idle channel,
// and the next op (TX) should have already taken place
// Failure to transmit is reflected in the default status,
// EasyLink_Status_Tx_Error, being set
if(pCmd->pNextOp->status == PROP_DONE_OK)
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
status = EasyLink_Status_Success;
// Reset the number of retries
be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
}
}
else if(pCmd->status == PROP_DONE_BUSY)
{
if(be > EASYLINK_MAX_CCA_BACKOFF_WINDOW)
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
// Reset the number of retries
be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
// CCA failed max number of retries
status = EasyLink_Status_Busy_Error;
}
else
{
// The back-off time is a random number chosen from 0 to 2^be,
// where 'be' goes from EASYLINK_MIN_CCA_BACKOFF_WINDOW
// to EASYLINK_MAX_CCA_BACKOFF_WINDOW. This number is then converted
// into EASYLINK_CCA_BACKOFF_TIMEUNITS units, and subsequently used to
// schedule the next CCA sequence. The variable 'be' is incremented each
// time, up to a pre-configured maximum, the back-off algorithm is run.
backOffTime = (getRN() & ((1 << be++)-1)) *
EasyLink_us_To_RadioTime(EASYLINK_CCA_BACKOFF_TIMEUNITS);
// running CCA again
bCcaRunAgain = true;
// The random number generator function returns a value in the range
// 0 to 2^15 - 1 and we choose the 'be' most significant bits as our
// back-off time in milliseconds (converted to RAT ticks)
pCmd->startTime = RF_getCurrentTime() + backOffTime;
// post the chained CS+TX command again while checking
// for a clear channel (CCA) before sending a packet
if(rfModeMultiClient)
{
schParams_prop.priority = RF_PriorityHigh;
asyncCmdHndl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropCs,
&schParams_prop, ccaDoneCallback, EASYLINK_RF_EVENT_MASK);
}
else
{
asyncCmdHndl = RF_postCmd(h, (RF_Op*)&EasyLink_cmdPropCs,
RF_PriorityHigh, ccaDoneCallback, EASYLINK_RF_EVENT_MASK);
}
}
}
else
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
// Reset the number of retries
be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
// The CS command status should be either IDLE or BUSY,
// all other status codes can be considered errors
// Status is set to the default, EasyLink_Status_Tx_Error
}
}
else if ( (e & RF_EventCmdAborted) || (e & RF_EventCmdCancelled ) || (e & RF_EventCmdPreempted ) )
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
// Reset the number of retries
be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
status = EasyLink_Status_Aborted;
}
else
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
// Reset the number of retries
be = EASYLINK_MIN_CCA_BACKOFF_WINDOW;
// Status is set to the default, EasyLink_Status_Tx_Error
}
if ((txCb != NULL) && (!bCcaRunAgain))
{
txCb(status);
}
}
#endif // (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
{
txCb(status);
}
}
#endif // (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
//Callback for Async Rx complete
static void rxDoneCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
EasyLink_Status status = EasyLink_Status_Rx_Error;
//create rxPacket as a static so that the large payload buffer it is not
//allocated from the stack
static EasyLink_RxPacket rxPacket;
rfc_dataEntryGeneral_t *pDataEntry;
pDataEntry = (rfc_dataEntryGeneral_t*) rxBuffer;
static void rxDoneCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
EasyLink_Status status = EasyLink_Status_Rx_Error;
//create rxPacket as a static so that the large payload buffer it is not
//allocated from the stack
static EasyLink_RxPacket rxPacket;
rfc_dataEntryGeneral_t *pDataEntry;
pDataEntry = (rfc_dataEntryGeneral_t*) rxBuffer;
if (e & RF_EventLastCmdDone)
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
//Check command status
if (EasyLink_cmdPropRxAdv.status == PROP_DONE_OK)
{
//Check that data entry status indicates it is finished with
if (pDataEntry->status != DATA_ENTRY_FINISHED)
{
status = EasyLink_Status_Rx_Error;
}
else if ( (rxStatistics.nRxOk == 1) ||
//or filer disabled and ignore due to addr mistmatch
((EasyLink_cmdPropRxAdv.pktConf.filterOp == 1) &&
(rxStatistics.nRxIgnored == 1)) )
{
//copy length from pDataEntry
rxPacket.len = *(uint8_t*)(&pDataEntry->data) - addrSize;
if(useIeeeHeader)
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
}
//copy address from packet payload (as it is not in hdr)
memcpy(&rxPacket.dstAddr, (&pDataEntry->data + hdrSize), addrSize);
//copy payload
memcpy(&rxPacket.payload, (&pDataEntry->data + hdrSize + addrSize), rxPacket.len);
rxPacket.rssi = rxStatistics.lastRssi;
rxPacket.absTime = rxStatistics.timeStamp;
if (EasyLink_cmdPropRxAdv.status == PROP_DONE_OK)
{
//Check that data entry status indicates it is finished with
if (pDataEntry->status != DATA_ENTRY_FINISHED)
{
status = EasyLink_Status_Rx_Error;
}
else if ( (rxStatistics.nRxOk == 1) ||
//or filer disabled and ignore due to addr mistmatch
((EasyLink_cmdPropRxAdv.pktConf.filterOp == 1) &&
(rxStatistics.nRxIgnored == 1)) )
{
//copy length from pDataEntry
rxPacket.len = *(uint8_t*)(&pDataEntry->data) - addrSize;
if(useIeeeHeader)
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
}
//copy address from packet payload (as it is not in hdr)
memcpy(&rxPacket.dstAddr, (&pDataEntry->data + hdrSize), addrSize);
//copy payload
memcpy(&rxPacket.payload, (&pDataEntry->data + hdrSize + addrSize), rxPacket.len);
rxPacket.rssi = rxStatistics.lastRssi;
rxPacket.absTime = rxStatistics.timeStamp;
status = EasyLink_Status_Success;
}
else if ( rxStatistics.nRxBufFull == 1)
{
status = EasyLink_Status_Rx_Buffer_Error;
}
else if ( rxStatistics.nRxStopped == 1)
{
status = EasyLink_Status_Aborted;
}
else
{
status = EasyLink_Status_Rx_Error;
}
}
else if ( EasyLink_cmdPropRxAdv.status == PROP_DONE_RXTIMEOUT)
{
status = EasyLink_Status_Rx_Timeout;
}
else
{
status = EasyLink_Status_Rx_Error;
}
}
else if (e & (RF_EventCmdCancelled | RF_EventCmdAborted | RF_EventCmdPreempted | RF_EventCmdStopped))
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
status = EasyLink_Status_Aborted;
}
}
else if ( rxStatistics.nRxBufFull == 1)
{
status = EasyLink_Status_Rx_Buffer_Error;
}
else if ( rxStatistics.nRxStopped == 1)
{
status = EasyLink_Status_Aborted;
}
else
{
status = EasyLink_Status_Rx_Error;
}
}
else if ( EasyLink_cmdPropRxAdv.status == PROP_DONE_RXTIMEOUT)
{
status = EasyLink_Status_Rx_Timeout;
}
else
{
status = EasyLink_Status_Rx_Error;
}
}
else if (e & (RF_EventCmdCancelled | RF_EventCmdAborted | RF_EventCmdPreempted | RF_EventCmdStopped))
{
//Release now so user callback can call EasyLink API's
Semaphore_post(busyMutex);
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
status = EasyLink_Status_Aborted;
}
if (rxCb != NULL)
{
PIN_setOutputValue(paPinHandle, Board_PALNA_PA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
{
PIN_setOutputValue(paPinHandle, Board_PALNA_PA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
rxCb(&rxPacket, status);
}
}
}
}
//Callback for Async TX Test mode
static void asyncCmdCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
Semaphore_post(busyMutex);
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
}
static void asyncCmdCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
Semaphore_post(busyMutex);
asyncCmdHndl = EASYLINK_RF_CMD_HANDLE_INVALID;
}
static EasyLink_Status enableTestMode(EasyLink_CtrlOption mode)
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
//This needs to be static as it is used by the RF driver and Modem after
//this function exits
static rfc_CMD_TX_TEST_t txTestCmd = {0};
static rfc_CMD_RX_TEST_t rxTestCmd = {0};
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
//This needs to be static as it is used by the RF driver and Modem after
//this function exits
static rfc_CMD_TX_TEST_t txTestCmd = {0};
static rfc_CMD_RX_TEST_t rxTestCmd = {0};
if((!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
if((mode != EasyLink_Ctrl_Test_Tone) &&
(mode != EasyLink_Ctrl_Test_Signal) &&
(mode != EasyLink_Ctrl_Rx_Test_Tone))
{
return EasyLink_Status_Param_Error;
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Busy_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
{
return EasyLink_Status_Config_Error;
}
if((mode != EasyLink_Ctrl_Test_Tone) &&
(mode != EasyLink_Ctrl_Test_Signal) &&
(mode != EasyLink_Ctrl_Rx_Test_Tone))
{
return EasyLink_Status_Param_Error;
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Busy_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
if((mode == EasyLink_Ctrl_Test_Tone) || (mode == EasyLink_Ctrl_Test_Signal))
{
txTestCmd.commandNo = CMD_TX_TEST;
txTestCmd.startTrigger.triggerType = TRIG_NOW;
txTestCmd.startTrigger.pastTrig = 1;
txTestCmd.startTime = 0;
{
txTestCmd.commandNo = CMD_TX_TEST;
txTestCmd.startTrigger.triggerType = TRIG_NOW;
txTestCmd.startTrigger.pastTrig = 1;
txTestCmd.startTime = 0;
txTestCmd.config.bFsOff = 1;
txTestCmd.syncWord = EasyLink_cmdPropTxAdv.syncWord;
txTestCmd.syncWord = EasyLink_cmdPropTxAdv.syncWord;
/* WhitenMode
* 0: No whitening
* 1: Default whitening
* 2: PRBS-15
* 3: PRBS-32
*/
txTestCmd.config.whitenMode = EASYLINK_WHITENING_MODE;
* 0: No whitening
* 1: Default whitening
* 2: PRBS-15
* 3: PRBS-32
*/
txTestCmd.config.whitenMode = EASYLINK_WHITENING_MODE;
//set tone (unmodulated) or signal (modulated)
if (mode == EasyLink_Ctrl_Test_Tone)
{
txTestCmd.txWord = 0xFFFF;
txTestCmd.config.bUseCw = 1;
}
else
{
txTestCmd.txWord = 0xAAAA;
txTestCmd.config.bUseCw = 0;
}
if (mode == EasyLink_Ctrl_Test_Tone)
{
txTestCmd.txWord = 0xFFFF;
txTestCmd.config.bUseCw = 1;
}
else
{
txTestCmd.txWord = 0xAAAA;
txTestCmd.config.bUseCw = 0;
}
//generate continuous test signal
txTestCmd.endTrigger.triggerType = TRIG_NEVER;
txTestCmd.endTrigger.triggerType = TRIG_NEVER;
/* Post command and store Cmd Handle for future abort */
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&txTestCmd,
RF_PriorityNormal, asyncCmdCallback,
EASYLINK_RF_EVENT_MASK);
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&txTestCmd,
RF_PriorityNormal, asyncCmdCallback,
EASYLINK_RF_EVENT_MASK);
/* Has command completed? */
uint16_t count = 0;
while (txTestCmd.status != ACTIVE)
{
//The command did not complete as fast as expected, sleep for 10ms
Task_sleep(10000 / Clock_tickPeriod);
uint16_t count = 0;
while (txTestCmd.status != ACTIVE)
{
//The command did not complete as fast as expected, sleep for 10ms
Task_sleep(10000 / Clock_tickPeriod);
if (count++ > 500)
{
//Should not get here, if we did Something went wrong with the
//the RF Driver, get out of here and return an error.
//The next command will likely lock up.
break;
}
}
{
//Should not get here, if we did Something went wrong with the
//the RF Driver, get out of here and return an error.
//The next command will likely lock up.
break;
}
}
if (txTestCmd.status == ACTIVE)
{
status = EasyLink_Status_Success;
}
}
else // mode is EasyLink_Ctrl_Rx_Test_Tone
{
rxTestCmd.commandNo = CMD_RX_TEST;
rxTestCmd.startTrigger.triggerType = TRIG_NOW;
rxTestCmd.startTrigger.pastTrig = 1;
rxTestCmd.startTime = 0;
{
status = EasyLink_Status_Success;
}
}
else // mode is EasyLink_Ctrl_Rx_Test_Tone
{
rxTestCmd.commandNo = CMD_RX_TEST;
rxTestCmd.startTrigger.triggerType = TRIG_NOW;
rxTestCmd.startTrigger.pastTrig = 1;
rxTestCmd.startTime = 0;
rxTestCmd.config.bFsOff = 1;
// Correlation threshold set to max to prevent sync, as RSSI values
// are locked after sync
rxTestCmd.config.bNoSync = 1;
rxTestCmd.syncWord = EasyLink_cmdPropRxAdv.syncWord0;
// Correlation threshold set to max to prevent sync, as RSSI values
// are locked after sync
rxTestCmd.config.bNoSync = 1;
rxTestCmd.syncWord = EasyLink_cmdPropRxAdv.syncWord0;
//detect test signal continuously
rxTestCmd.endTrigger.triggerType = TRIG_NEVER;
rxTestCmd.endTrigger.triggerType = TRIG_NEVER;
/* Post command and store Cmd Handle for future abort */
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&rxTestCmd,
RF_PriorityNormal, asyncCmdCallback,
EASYLINK_RF_EVENT_MASK);
if(EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
status = EasyLink_Status_Success;
}
else
{
status = EasyLink_Status_Cmd_Error;
}
}
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&rxTestCmd,
RF_PriorityNormal, asyncCmdCallback,
EASYLINK_RF_EVENT_MASK);
if(EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
status = EasyLink_Status_Success;
}
else
{
status = EasyLink_Status_Cmd_Error;
}
}
return status;
}
}
EasyLink_Status EasyLink_init(EasyLink_Params *params)
{
/* Open pa pins */
paPinHandle = PIN_open(&paPinState, paPinTable);
if (!paPinHandle)
{
// System_abort("Error initializing board 3.3V domain pins\n");
}
{
/* Open pa pins */
paPinHandle = PIN_open(&paPinState, paPinTable);
if (!paPinHandle)
{
// System_abort("Error initializing board 3.3V domain pins\n");
}
if (params == NULL)
{
EasyLink_Params_init(&EasyLink_params);
} else
{
memcpy(&EasyLink_params, params, sizeof(EasyLink_params));
}
{
EasyLink_Params_init(&EasyLink_params);
} else
{
memcpy(&EasyLink_params, params, sizeof(EasyLink_params));
}
if (configured)
{
//Already configure, check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
{
//Already configure, check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
RF_close(rfHandle);
}
}
if (!rfParamsConfigured)
{
RF_Params_init(&rfParams);
//set default InactivityTimeout to 1000us
rfParams.nInactivityTimeout = inactivityTimeout;
//configure event callback
if(EasyLink_params.pClientEventCb != NULL && EasyLink_params.nClientEventMask != 0){
rfParams.pClientEventCb = EasyLink_params.pClientEventCb;
rfParams.nClientEventMask = EasyLink_params.nClientEventMask;
}
{
RF_Params_init(&rfParams);
//set default InactivityTimeout to 1000us
rfParams.nInactivityTimeout = inactivityTimeout;
//configure event callback
if(EasyLink_params.pClientEventCb != NULL && EasyLink_params.nClientEventMask != 0){
rfParams.pClientEventCb = EasyLink_params.pClientEventCb;
rfParams.nClientEventMask = EasyLink_params.nClientEventMask;
}
rfParamsConfigured = 1;
}
}
#if (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
// Assign the random number generator function pointer to the global
// handle, if it is NULL any function that employs it will return a
// configuration error
getRN = EasyLink_params.pGrnFxn;
// Assign the random number generator function pointer to the global
// handle, if it is NULL any function that employs it will return a
// configuration error
getRN = EasyLink_params.pGrnFxn;
// Configure the EasyLink Carrier Sense Command
memset(&EasyLink_cmdPropCs, 0, sizeof(rfc_CMD_PROP_CS_t));
EasyLink_cmdPropCs.commandNo = CMD_PROP_CS;
EasyLink_cmdPropCs.rssiThr = EASYLINK_CS_RSSI_THRESHOLD_DBM;
EasyLink_cmdPropCs.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropCs.condition.rule = COND_STOP_ON_TRUE; // Stop next command if this command returned TRUE,
// End causes for the CMD_PROP_CS command:
// Observed channel state Busy with csConf.busyOp = 1: PROP_DONE_BUSY TRUE
// 0bserved channel state Idle with csConf.idleOp = 1: PROP_DONE_IDLE FALSE
// Timeout trigger observed with channel state Busy: PROP_DONE_BUSY TRUE
// Timeout trigger observed with channel state Idle: PROP_DONE_IDLE FALSE
// Timeout trigger observed with channel state Invalid and csConf.timeoutRes = 0: PROP_DONE_BUSYTIMEOUT TRUE
// Timeout trigger observed with channel state Invalid and csConf.timeoutRes = 1: PROP_DONE_IDLETIMEOUT FALSE
// Received CMD_STOP after command started: PROP_DONE_STOPPED FALSE
EasyLink_cmdPropCs.csConf.bEnaRssi = 0x1; // Enable RSSI as a criterion
EasyLink_cmdPropCs.csConf.busyOp = 0x1; // End carrier sense on channel Busy
EasyLink_cmdPropCs.csConf.idleOp = 0x0; // Continue carrier sense on channel Idle
EasyLink_cmdPropCs.csEndTrigger.triggerType = TRIG_REL_START; // Ends at a time relative to the command started
EasyLink_cmdPropCs.csEndTime = EasyLink_us_To_RadioTime(EASYLINK_CHANNEL_IDLE_TIME_US);
#endif //(defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
memset(&EasyLink_cmdPropCs, 0, sizeof(rfc_CMD_PROP_CS_t));
EasyLink_cmdPropCs.commandNo = CMD_PROP_CS;
EasyLink_cmdPropCs.rssiThr = EASYLINK_CS_RSSI_THRESHOLD_DBM;
EasyLink_cmdPropCs.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropCs.condition.rule = COND_STOP_ON_TRUE; // Stop next command if this command returned TRUE,
// End causes for the CMD_PROP_CS command:
// Observed channel state Busy with csConf.busyOp = 1: PROP_DONE_BUSY TRUE
// 0bserved channel state Idle with csConf.idleOp = 1: PROP_DONE_IDLE FALSE
// Timeout trigger observed with channel state Busy: PROP_DONE_BUSY TRUE
// Timeout trigger observed with channel state Idle: PROP_DONE_IDLE FALSE
// Timeout trigger observed with channel state Invalid and csConf.timeoutRes = 0: PROP_DONE_BUSYTIMEOUT TRUE
// Timeout trigger observed with channel state Invalid and csConf.timeoutRes = 1: PROP_DONE_IDLETIMEOUT FALSE
// Received CMD_STOP after command started: PROP_DONE_STOPPED FALSE
EasyLink_cmdPropCs.csConf.bEnaRssi = 0x1; // Enable RSSI as a criterion
EasyLink_cmdPropCs.csConf.busyOp = 0x1; // End carrier sense on channel Busy
EasyLink_cmdPropCs.csConf.idleOp = 0x0; // Continue carrier sense on channel Idle
EasyLink_cmdPropCs.csEndTrigger.triggerType = TRIG_REL_START; // Ends at a time relative to the command started
EasyLink_cmdPropCs.csEndTime = EasyLink_us_To_RadioTime(EASYLINK_CHANNEL_IDLE_TIME_US);
#endif //(defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
#if (defined(FEATURE_OAD_ONCHIP))
EasyLink_params.ui32ModType = EasyLink_Phy_Custom;
#endif
EasyLink_params.ui32ModType = EasyLink_Phy_Custom;
#endif
bool useDivRadioSetup = true;
bool rfConfigOk = false;
bool createCmdTxAdvFromTx = true;
useIeeeHeader = false;
bool rfConfigOk = false;
bool createCmdTxAdvFromTx = true;
useIeeeHeader = false;
// Check if the PHY setting is compatible with the current device
switch(EasyLink_params.ui32ModType)
{
case EasyLink_Phy_Custom:
if((ChipInfo_ChipFamilyIs_CC26x0()) || (ChipInfo_ChipFamilyIs_CC26x0R2()))
{
useDivRadioSetup= false;
}
rfConfigOk = true;
break;
switch(EasyLink_params.ui32ModType)
{
case EasyLink_Phy_Custom:
if((ChipInfo_ChipFamilyIs_CC26x0()) || (ChipInfo_ChipFamilyIs_CC26x0R2()))
{
useDivRadioSetup= false;
}
rfConfigOk = true;
break;
case EasyLink_Phy_50kbps2gfsk:
if(!(ChipInfo_ChipFamilyIs_CC26x0()) && !(ChipInfo_ChipFamilyIs_CC26x0R2()))
{
useDivRadioSetup= true;
rfConfigOk = true;
}
break;
if(!(ChipInfo_ChipFamilyIs_CC26x0()) && !(ChipInfo_ChipFamilyIs_CC26x0R2()))
{
useDivRadioSetup= true;
rfConfigOk = true;
}
break;
case EasyLink_Phy_625bpsLrm:
if(!(ChipInfo_ChipFamilyIs_CC26x0()) && !(ChipInfo_ChipFamilyIs_CC26x0R2())
&& !(ChipInfo_ChipFamilyIs_CC13x2_CC26x2()))
{
useDivRadioSetup= true;
rfConfigOk = true;
}
break;
if(!(ChipInfo_ChipFamilyIs_CC26x0()) && !(ChipInfo_ChipFamilyIs_CC26x0R2())
&& !(ChipInfo_ChipFamilyIs_CC13x2_CC26x2()))
{
useDivRadioSetup= true;
rfConfigOk = true;
}
break;
case EasyLink_Phy_2_4_100kbps2gfsk:
if((ChipInfo_GetChipType() == CHIP_TYPE_CC2640R2))
{
useDivRadioSetup= false;
rfConfigOk = true;
}
break;
if((ChipInfo_GetChipType() == CHIP_TYPE_CC2640R2))
{
useDivRadioSetup= false;
rfConfigOk = true;
}
break;
case EasyLink_Phy_2_4_200kbps2gfsk:
if((ChipInfo_GetChipType() == CHIP_TYPE_CC2650))
{
useDivRadioSetup= false;
rfConfigOk = true;
}
break;
if((ChipInfo_GetChipType() == CHIP_TYPE_CC2650))
{
useDivRadioSetup= false;
rfConfigOk = true;
}
break;
case EasyLink_Phy_2_4_250kbps2gfsk:
if((ChipInfo_GetChipType() == CHIP_TYPE_CC2640R2))
{
useDivRadioSetup= false;
rfConfigOk = true;
}
break;
if((ChipInfo_GetChipType() == CHIP_TYPE_CC2640R2))
{
useDivRadioSetup= false;
rfConfigOk = true;
}
break;
case EasyLink_Phy_5kbpsSlLr:
if(!(ChipInfo_ChipFamilyIs_CC26x0()) && !(ChipInfo_ChipFamilyIs_CC26x0R2()))
{
useDivRadioSetup= true;
rfConfigOk = true;
#if (defined Board_CC1352P_4_LAUNCHXL)
// CC1352P-4 SLR operates at 433.92 MHz
EasyLink_cmdFs.frequency = 0x01B1;
EasyLink_cmdFs.fractFreq = 0xEB9A;
#endif
}
break;
if(!(ChipInfo_ChipFamilyIs_CC26x0()) && !(ChipInfo_ChipFamilyIs_CC26x0R2()))
{
useDivRadioSetup= true;
rfConfigOk = true;
#if (defined Board_CC1352P_4_LAUNCHXL)
// CC1352P-4 SLR operates at 433.92 MHz
EasyLink_cmdFs.frequency = 0x01B1;
EasyLink_cmdFs.fractFreq = 0xEB9A;
#endif
}
break;
case EasyLink_Phy_200kbps2gfsk:
if((ChipInfo_GetChipType() == CHIP_TYPE_CC1312) || (ChipInfo_GetChipType() == CHIP_TYPE_CC1352) ||
(ChipInfo_GetChipType() == CHIP_TYPE_CC1352P))
{
#if !defined(Board_CC1352P_4_LAUNCHXL)
// This mode is not supported in the 433 MHz band
useDivRadioSetup= true;
rfConfigOk = true;
createCmdTxAdvFromTx = false;
useIeeeHeader = true;
#endif
}
break;
if((ChipInfo_GetChipType() == CHIP_TYPE_CC1312) || (ChipInfo_GetChipType() == CHIP_TYPE_CC1352) ||
(ChipInfo_GetChipType() == CHIP_TYPE_CC1352P))
{
#if !defined(Board_CC1352P_4_LAUNCHXL)
// This mode is not supported in the 433 MHz band
useDivRadioSetup= true;
rfConfigOk = true;
createCmdTxAdvFromTx = false;
useIeeeHeader = true;
#endif
}
break;
default: // Invalid PHY setting
rfConfigOk = false;
break;
}
// Return an error if the PHY setting is incompatible with the current device
if(!rfConfigOk)
{
if (busyMutex != NULL)
{
Semaphore_post(busyMutex);
}
return EasyLink_Status_Param_Error;
}
if(!rfConfigOk)
{
if (busyMutex != NULL)
{
Semaphore_post(busyMutex);
}
return EasyLink_Status_Param_Error;
}
// Loop through the EasyLink_supportedPhys array looking for the PHY
uint8_t i = 0;
while(i < EasyLink_numSupportedPhys)
{
if(EasyLink_supportedPhys[i].EasyLink_phyType == EasyLink_params.ui32ModType)
{
rfSetting = &EasyLink_supportedPhys[i];
break;
}
i++;
}
uint8_t i = 0;
while(i < EasyLink_numSupportedPhys)
{
if(EasyLink_supportedPhys[i].EasyLink_phyType == EasyLink_params.ui32ModType)
{
rfSetting = &EasyLink_supportedPhys[i];
break;
}
i++;
}
// Return an error if the PHY isn't in the supported settings list
if(rfSetting == 0)
{
if (busyMutex != NULL)
{
Semaphore_post(busyMutex);
}
return EasyLink_Status_Param_Error;
}
if(rfSetting == 0)
{
if (busyMutex != NULL)
{
Semaphore_post(busyMutex);
}
return EasyLink_Status_Param_Error;
}
// Copy the PHY settings to the EasyLink PHY variable
if(useDivRadioSetup)
{
#if (defined Board_CC1352P1_LAUNCHXL) || (defined Board_CC1352P_2_LAUNCHXL) || \
(defined Board_CC1352P_4_LAUNCHXL)
memcpy(&EasyLink_cmdPropRadioSetup.divSetup, (rfSetting->RF_uCmdPropRadio.RF_pCmdPropRadioDivSetup), sizeof(rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t));
#else
memcpy(&EasyLink_cmdPropRadioSetup.divSetup, (rfSetting->RF_uCmdPropRadio.RF_pCmdPropRadioDivSetup), sizeof(rfc_CMD_PROP_RADIO_DIV_SETUP_t));
#endif
}
else
{
memcpy(&EasyLink_cmdPropRadioSetup.setup, (rfSetting->RF_uCmdPropRadio.RF_pCmdPropRadioSetup), sizeof(rfc_CMD_PROP_RADIO_SETUP_t));
}
memcpy(&EasyLink_cmdFs, (rfSetting->RF_pCmdFs), sizeof(rfc_CMD_FS_t));
memcpy(&EasyLink_RF_prop, (rfSetting->RF_pProp), sizeof(RF_Mode));
memcpy(&EasyLink_cmdPropRxAdv,(rfSetting->RF_pCmdPropRxAdv), sizeof(rfc_CMD_PROP_RX_ADV_t));
if(createCmdTxAdvFromTx)
{
createTxAdvFromTx(&EasyLink_cmdPropTxAdv, (rfSetting->RF_pCmdPropTx));
}
else
{
memcpy(&EasyLink_cmdPropTxAdv, (rfSetting->RF_pCmdPropTxAdv), sizeof(rfc_CMD_PROP_TX_ADV_t));
}
if(useDivRadioSetup)
{
#if (defined Board_CC1352P1_LAUNCHXL) || (defined Board_CC1352P_2_LAUNCHXL) || \
(defined Board_CC1352P_4_LAUNCHXL)
memcpy(&EasyLink_cmdPropRadioSetup.divSetup, (rfSetting->RF_uCmdPropRadio.RF_pCmdPropRadioDivSetup), sizeof(rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t));
#else
memcpy(&EasyLink_cmdPropRadioSetup.divSetup, (rfSetting->RF_uCmdPropRadio.RF_pCmdPropRadioDivSetup), sizeof(rfc_CMD_PROP_RADIO_DIV_SETUP_t));
#endif
}
else
{
memcpy(&EasyLink_cmdPropRadioSetup.setup, (rfSetting->RF_uCmdPropRadio.RF_pCmdPropRadioSetup), sizeof(rfc_CMD_PROP_RADIO_SETUP_t));
}
memcpy(&EasyLink_cmdFs, (rfSetting->RF_pCmdFs), sizeof(rfc_CMD_FS_t));
memcpy(&EasyLink_RF_prop, (rfSetting->RF_pProp), sizeof(RF_Mode));
memcpy(&EasyLink_cmdPropRxAdv,(rfSetting->RF_pCmdPropRxAdv), sizeof(rfc_CMD_PROP_RX_ADV_t));
if(createCmdTxAdvFromTx)
{
createTxAdvFromTx(&EasyLink_cmdPropTxAdv, (rfSetting->RF_pCmdPropTx));
}
else
{
memcpy(&EasyLink_cmdPropTxAdv, (rfSetting->RF_pCmdPropTxAdv), sizeof(rfc_CMD_PROP_TX_ADV_t));
}
#if !(defined(DeviceFamily_CC26X0R2))
if (rfModeMultiClient)
{
EasyLink_RF_prop.rfMode = RF_MODE_MULTIPLE;
}
#endif //defined(DeviceFamily_CC26X0R2)
if (rfModeMultiClient)
{
EasyLink_RF_prop.rfMode = RF_MODE_MULTIPLE;
}
#endif //defined(DeviceFamily_CC26X0R2)
/* Request access to the radio */
rfHandle = RF_open(&rfObject, &EasyLink_RF_prop,
(RF_RadioSetup*)&EasyLink_cmdPropRadioSetup.setup, &rfParams);
rfHandle = RF_open(&rfObject, &EasyLink_RF_prop,
(RF_RadioSetup*)&EasyLink_cmdPropRadioSetup.setup, &rfParams);
// Setup the Proprietary Rx Advanced Command
EasyLink_cmdPropRxAdv.status = 0x0000;
EasyLink_cmdPropRxAdv.pNextOp = 0;
EasyLink_cmdPropRxAdv.startTime = 0x00000000;
EasyLink_cmdPropRxAdv.startTrigger.triggerType = 0x0;
EasyLink_cmdPropRxAdv.startTrigger.bEnaCmd = 0x0;
EasyLink_cmdPropRxAdv.startTrigger.triggerNo = 0x0;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 0x0;
EasyLink_cmdPropRxAdv.condition.rule = 0x1;
EasyLink_cmdPropRxAdv.condition.nSkip = 0x0;
EasyLink_cmdPropRxAdv.pktConf.bFsOff = 0x0;
EasyLink_cmdPropRxAdv.pktConf.bRepeatOk = 0x0;
EasyLink_cmdPropRxAdv.pktConf.bRepeatNok = 0x0;
EasyLink_cmdPropRxAdv.pktConf.bUseCrc = 0x1;
EasyLink_cmdPropRxAdv.pktConf.bCrcIncSw = 0x0;
EasyLink_cmdPropRxAdv.pktConf.endType = 0x0;
EasyLink_cmdPropRxAdv.pktConf.filterOp = !(EASYLINK_ENABLE_ADDR_FILTERING);
EasyLink_cmdPropRxAdv.rxConf.bAutoFlushIgnored = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bAutoFlushCrcErr = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bIncludeHdr = 0x1;
EasyLink_cmdPropRxAdv.rxConf.bIncludeCrc = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bAppendRssi = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bAppendTimestamp = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bAppendStatus = 0x0;
EasyLink_cmdPropRxAdv.syncWord1 = 0;
EasyLink_cmdPropRxAdv.maxPktLen = EASYLINK_MAX_DATA_LENGTH +
EASYLINK_MAX_ADDR_SIZE;
if(useIeeeHeader)
{
EasyLink_cmdPropRxAdv.syncWord0 = EASYLINK_IEEE_TRX_SYNC_WORD;
EasyLink_cmdPropRxAdv.hdrConf.numHdrBits = EASYLINK_IEEE_HDR_NBITS;
EasyLink_cmdPropRxAdv.lenOffset = EASYLINK_IEEE_LEN_OFFSET;
// Exclude the header from the CRC calculation
EasyLink_cmdPropRxAdv.pktConf.bCrcIncHdr = 0U;
}
else
{
EasyLink_cmdPropRxAdv.syncWord0 = EASYLINK_PROP_TRX_SYNC_WORD;
EasyLink_cmdPropRxAdv.hdrConf.numHdrBits = EASYLINK_PROP_HDR_NBITS;
EasyLink_cmdPropRxAdv.lenOffset = EASYLINK_PROP_LEN_OFFSET;
// Include the header in the CRC calculation - The header (length
// byte) is considered to be the first byte of the payload
EasyLink_cmdPropRxAdv.pktConf.bCrcIncHdr = 1U;
}
EasyLink_cmdPropRxAdv.hdrConf.numLenBits = EASYLINK_HDR_LEN_NBITS;
EasyLink_cmdPropRxAdv.hdrConf.lenPos = 0;
EasyLink_cmdPropRxAdv.addrConf.addrType = 0;
EasyLink_cmdPropRxAdv.addrConf.addrSize = addrSize;
EasyLink_cmdPropRxAdv.addrConf.addrPos = 0;
EasyLink_cmdPropRxAdv.addrConf.numAddr = EASYLINK_NUM_ADDR_FILTER;
EasyLink_cmdPropRxAdv.endTrigger.triggerType = 0x1;
EasyLink_cmdPropRxAdv.endTrigger.bEnaCmd = 0x0;
EasyLink_cmdPropRxAdv.endTrigger.triggerNo = 0x0;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 0x0;
EasyLink_cmdPropRxAdv.endTime = 0x00000000;
EasyLink_cmdPropRxAdv.pAddr = addrFilterTable;
EasyLink_cmdPropRxAdv.pQueue = &dataQueue;
EasyLink_cmdPropRxAdv.pOutput = (uint8_t*)&rxStatistics;
EasyLink_cmdPropRxAdv.status = 0x0000;
EasyLink_cmdPropRxAdv.pNextOp = 0;
EasyLink_cmdPropRxAdv.startTime = 0x00000000;
EasyLink_cmdPropRxAdv.startTrigger.triggerType = 0x0;
EasyLink_cmdPropRxAdv.startTrigger.bEnaCmd = 0x0;
EasyLink_cmdPropRxAdv.startTrigger.triggerNo = 0x0;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 0x0;
EasyLink_cmdPropRxAdv.condition.rule = 0x1;
EasyLink_cmdPropRxAdv.condition.nSkip = 0x0;
EasyLink_cmdPropRxAdv.pktConf.bFsOff = 0x0;
EasyLink_cmdPropRxAdv.pktConf.bRepeatOk = 0x0;
EasyLink_cmdPropRxAdv.pktConf.bRepeatNok = 0x0;
EasyLink_cmdPropRxAdv.pktConf.bUseCrc = 0x1;
EasyLink_cmdPropRxAdv.pktConf.bCrcIncSw = 0x0;
EasyLink_cmdPropRxAdv.pktConf.endType = 0x0;
EasyLink_cmdPropRxAdv.pktConf.filterOp = !(EASYLINK_ENABLE_ADDR_FILTERING);
EasyLink_cmdPropRxAdv.rxConf.bAutoFlushIgnored = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bAutoFlushCrcErr = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bIncludeHdr = 0x1;
EasyLink_cmdPropRxAdv.rxConf.bIncludeCrc = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bAppendRssi = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bAppendTimestamp = 0x0;
EasyLink_cmdPropRxAdv.rxConf.bAppendStatus = 0x0;
EasyLink_cmdPropRxAdv.syncWord1 = 0;
EasyLink_cmdPropRxAdv.maxPktLen = EASYLINK_MAX_DATA_LENGTH +
EASYLINK_MAX_ADDR_SIZE;
if(useIeeeHeader)
{
EasyLink_cmdPropRxAdv.syncWord0 = EASYLINK_IEEE_TRX_SYNC_WORD;
EasyLink_cmdPropRxAdv.hdrConf.numHdrBits = EASYLINK_IEEE_HDR_NBITS;
EasyLink_cmdPropRxAdv.lenOffset = EASYLINK_IEEE_LEN_OFFSET;
// Exclude the header from the CRC calculation
EasyLink_cmdPropRxAdv.pktConf.bCrcIncHdr = 0U;
}
else
{
EasyLink_cmdPropRxAdv.syncWord0 = EASYLINK_PROP_TRX_SYNC_WORD;
EasyLink_cmdPropRxAdv.hdrConf.numHdrBits = EASYLINK_PROP_HDR_NBITS;
EasyLink_cmdPropRxAdv.lenOffset = EASYLINK_PROP_LEN_OFFSET;
// Include the header in the CRC calculation - The header (length
// byte) is considered to be the first byte of the payload
EasyLink_cmdPropRxAdv.pktConf.bCrcIncHdr = 1U;
}
EasyLink_cmdPropRxAdv.hdrConf.numLenBits = EASYLINK_HDR_LEN_NBITS;
EasyLink_cmdPropRxAdv.hdrConf.lenPos = 0;
EasyLink_cmdPropRxAdv.addrConf.addrType = 0;
EasyLink_cmdPropRxAdv.addrConf.addrSize = addrSize;
EasyLink_cmdPropRxAdv.addrConf.addrPos = 0;
EasyLink_cmdPropRxAdv.addrConf.numAddr = EASYLINK_NUM_ADDR_FILTER;
EasyLink_cmdPropRxAdv.endTrigger.triggerType = 0x1;
EasyLink_cmdPropRxAdv.endTrigger.bEnaCmd = 0x0;
EasyLink_cmdPropRxAdv.endTrigger.triggerNo = 0x0;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 0x0;
EasyLink_cmdPropRxAdv.endTime = 0x00000000;
EasyLink_cmdPropRxAdv.pAddr = addrFilterTable;
EasyLink_cmdPropRxAdv.pQueue = &dataQueue;
EasyLink_cmdPropRxAdv.pOutput = (uint8_t*)&rxStatistics;
//Set the frequency
RF_runCmd(rfHandle, (RF_Op*)&EasyLink_cmdFs, RF_PriorityNormal, 0, //asyncCmdCallback,
EASYLINK_RF_EVENT_MASK);
RF_runCmd(rfHandle, (RF_Op*)&EasyLink_cmdFs, RF_PriorityNormal, 0, //asyncCmdCallback,
EASYLINK_RF_EVENT_MASK);
//Create a semaphore for blocking commands
Semaphore_Params semParams;
Error_Block eb;
Semaphore_Params semParams;
Error_Block eb;
// init params
Semaphore_Params_init(&semParams);
Error_init(&eb);
Semaphore_Params_init(&semParams);
Error_init(&eb);
// create semaphore instance if not already created
if (busyMutex == NULL)
{
busyMutex = Semaphore_create(0, &semParams, &eb);
if (busyMutex == NULL)
{
return EasyLink_Status_Mem_Error;
}
if (busyMutex == NULL)
{
busyMutex = Semaphore_create(0, &semParams, &eb);
if (busyMutex == NULL)
{
return EasyLink_Status_Mem_Error;
}
Semaphore_post(busyMutex);
}
else
{
//already configured and taken busyMutex, so release it
Semaphore_post(busyMutex);
}
}
else
{
//already configured and taken busyMutex, so release it
Semaphore_post(busyMutex);
}
configured = 1;
return EasyLink_Status_Success;
}
EasyLink_Status EasyLink_setFrequency(uint32_t ui32Frequency)
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
uint16_t centerFreq, fractFreq;
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
uint16_t centerFreq, fractFreq;
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
{
return EasyLink_Status_Config_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
/* Set the frequency */
centerFreq = (uint16_t)(ui32Frequency / 1000000);
fractFreq = (uint16_t) (((uint64_t)ui32Frequency -
((uint64_t)centerFreq * 1000000)) *
65536 / 1000000);
EasyLink_cmdFs.frequency = centerFreq;
EasyLink_cmdFs.fractFreq = fractFreq;
centerFreq = (uint16_t)(ui32Frequency / 1000000);
fractFreq = (uint16_t) (((uint64_t)ui32Frequency -
((uint64_t)centerFreq * 1000000)) *
65536 / 1000000);
EasyLink_cmdFs.frequency = centerFreq;
EasyLink_cmdFs.fractFreq = fractFreq;
#if (!defined(DeviceFamily_CC26X0R2) && !defined(DeviceFamily_CC26X0))
/* If the command type is CMD_PROP_RADIO_DIV_SETUP then set the center frequency
* to the same band as the FS command
*/
if((EasyLink_cmdPropRadioSetup.divSetup.commandNo == CMD_PROP_RADIO_DIV_SETUP) &&
(EasyLink_cmdPropRadioSetup.divSetup.centerFreq != centerFreq))
{
EasyLink_cmdPropRadioSetup.divSetup.centerFreq = centerFreq;
/* Run the Setup Command */
(void)RF_runCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRadioSetup,
RF_PriorityNormal, 0, EASYLINK_RF_EVENT_MASK);
}
#endif
/* If the command type is CMD_PROP_RADIO_DIV_SETUP then set the center frequency
* to the same band as the FS command
*/
if((EasyLink_cmdPropRadioSetup.divSetup.commandNo == CMD_PROP_RADIO_DIV_SETUP) &&
(EasyLink_cmdPropRadioSetup.divSetup.centerFreq != centerFreq))
{
EasyLink_cmdPropRadioSetup.divSetup.centerFreq = centerFreq;
/* Run the Setup Command */
(void)RF_runCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRadioSetup,
RF_PriorityNormal, 0, EASYLINK_RF_EVENT_MASK);
}
#endif
/* Run command */
RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&EasyLink_cmdFs,
RF_PriorityNormal, 0, EASYLINK_RF_EVENT_MASK);
RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&EasyLink_cmdFs,
RF_PriorityNormal, 0, EASYLINK_RF_EVENT_MASK);
if((result & RF_EventLastCmdDone) && (EasyLink_cmdFs.status == DONE_OK))
{
status = EasyLink_Status_Success;
}
{
status = EasyLink_Status_Success;
}
Semaphore_post(busyMutex);
return status;
}
}
uint32_t EasyLink_getFrequency(void)
{
uint32_t freq_khz;
{
uint32_t freq_khz;
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
{
return EasyLink_Status_Config_Error;
}
freq_khz = EasyLink_cmdFs.frequency * 1000000;
freq_khz += ((((uint64_t)EasyLink_cmdFs.fractFreq * 1000000)) / 65536);
freq_khz += ((((uint64_t)EasyLink_cmdFs.fractFreq * 1000000)) / 65536);
return freq_khz;
}
}
EasyLink_Status EasyLink_setRfPower(int8_t i8TxPowerDbm)
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
{
return EasyLink_Status_Config_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
#if (defined Board_CC1310_LAUNCHXL) || (defined Board_CC1350_LAUNCHXL) || \
(defined Board_CC1350STK) || (defined Board_CC1350_LAUNCHXL_433) || \
(defined Board_CC1312R1_LAUNCHXL) || (defined Board_CC1352R1_LAUNCHXL) || \
(defined Board_CC1352P1_LAUNCHXL) || (defined Board_CC1352P_2_LAUNCHXL) || \
(defined Board_CC1352P_4_LAUNCHXL) || (defined Board_CC2640R2_LAUNCHXL)
(defined Board_CC1350STK) || (defined Board_CC1350_LAUNCHXL_433) || \
(defined Board_CC1312R1_LAUNCHXL) || (defined Board_CC1352R1_LAUNCHXL) || \
(defined Board_CC1352P1_LAUNCHXL) || (defined Board_CC1352P_2_LAUNCHXL) || \
(defined Board_CC1352P_4_LAUNCHXL) || (defined Board_CC2640R2_LAUNCHXL)
RF_TxPowerTable_Entry *rfPowerTable = NULL;
RF_TxPowerTable_Value newValue;
uint8_t rfPowerTableSize = 0;
RF_TxPowerTable_Value newValue;
uint8_t rfPowerTableSize = 0;
newValue = RF_TxPowerTable_findValue((RF_TxPowerTable_Entry *)rfSetting->RF_pTxPowerTable, i8TxPowerDbm);
if(newValue.rawValue != RF_TxPowerTable_INVALID_VALUE)
{
// Found a valid entry
rfPowerTable = (RF_TxPowerTable_Entry *)rfSetting->RF_pTxPowerTable;
rfPowerTableSize = rfSetting->RF_txPowerTableSize;
}
else
{
//Release the busyMutex
Semaphore_post(busyMutex);
// Desired power is too low to be supported on this device
return EasyLink_Status_Config_Error;
}
if(newValue.rawValue != RF_TxPowerTable_INVALID_VALUE)
{
// Found a valid entry
rfPowerTable = (RF_TxPowerTable_Entry *)rfSetting->RF_pTxPowerTable;
rfPowerTableSize = rfSetting->RF_txPowerTableSize;
}
else
{
//Release the busyMutex
Semaphore_post(busyMutex);
// Desired power is too low to be supported on this device
return EasyLink_Status_Config_Error;
}
//if max power is requested then the CCFG_FORCE_VDDR_HH must be set in
//the ccfg; this does not apply to 2.4GHz proprietary modes either
#if (CCFG_FORCE_VDDR_HH != 0x1)
if((newValue.paType == RF_TxPowerTable_DefaultPA) &&
(i8TxPowerDbm == rfPowerTable[rfPowerTableSize-2].power))
{
#if !(defined Board_CC2640R2_LAUNCHXL)
//Release the busyMutex
Semaphore_post(busyMutex);
// The desired power level is set to the maximum supported under the
// default PA settings, but the boost mode (CCFG_FORCE_VDDR_HH) is not
// turned on
return EasyLink_Status_Config_Error;
#endif
}
#else
// dummy read to avoid build warnings
if(rfPowerTable[rfPowerTableSize-2].power){}
#endif
//the ccfg; this does not apply to 2.4GHz proprietary modes either
#if (CCFG_FORCE_VDDR_HH != 0x1)
if((newValue.paType == RF_TxPowerTable_DefaultPA) &&
(i8TxPowerDbm == rfPowerTable[rfPowerTableSize-2].power))
{
#if !(defined Board_CC2640R2_LAUNCHXL)
//Release the busyMutex
Semaphore_post(busyMutex);
// The desired power level is set to the maximum supported under the
// default PA settings, but the boost mode (CCFG_FORCE_VDDR_HH) is not
// turned on
return EasyLink_Status_Config_Error;
#endif
}
#else
// dummy read to avoid build warnings
if(rfPowerTable[rfPowerTableSize-2].power){}
#endif
RF_Stat rfStatus = RF_setTxPower(rfHandle, newValue);
if(rfStatus == RF_StatSuccess)
{
status = EasyLink_Status_Success;
}
else
{
status = EasyLink_Status_Config_Error;
}
#else
rfc_CMD_SCH_IMM_t immOpCmd = {0};
rfc_CMD_SET_TX_POWER_t cmdSetPower = {0};
uint8_t txPowerIdx;
rfc_CMD_SET_TX_POWER_t cmdSetPower = {0};
uint8_t txPowerIdx;
immOpCmd.commandNo = CMD_SCH_IMM;
immOpCmd.startTrigger.triggerType = TRIG_NOW;
immOpCmd.startTrigger.pastTrig = 1;
immOpCmd.startTime = 0;
immOpCmd.startTrigger.triggerType = TRIG_NOW;
immOpCmd.startTrigger.pastTrig = 1;
immOpCmd.startTime = 0;
cmdSetPower.commandNo = CMD_SET_TX_POWER;
if (i8TxPowerDbm < rfPowerTable[0].dbm)
{
i8TxPowerDbm = rfPowerTable[0].dbm;
}
else if (i8TxPowerDbm > rfPowerTable[rfPowerTableSize-1].dbm )
{
i8TxPowerDbm = rfPowerTable[rfPowerTableSize-1].dbm;
}
{
i8TxPowerDbm = rfPowerTable[0].dbm;
}
else if (i8TxPowerDbm > rfPowerTable[rfPowerTableSize-1].dbm )
{
i8TxPowerDbm = rfPowerTable[rfPowerTableSize-1].dbm;
}
//if max power is requested then the CCFG_FORCE_VDDR_HH must be set in
//the ccfg
#if (CCFG_FORCE_VDDR_HH != 0x1)
if (i8TxPowerDbm == rfPowerTable[rfPowerTableSize-1].dbm)
{
//Release the busyMutex
Semaphore_post(busyMutex);
return EasyLink_Status_Config_Error;
}
#endif
//the ccfg
#if (CCFG_FORCE_VDDR_HH != 0x1)
if (i8TxPowerDbm == rfPowerTable[rfPowerTableSize-1].dbm)
{
//Release the busyMutex
Semaphore_post(busyMutex);
return EasyLink_Status_Config_Error;
}
#endif
for (txPowerIdx = 0; txPowerIdx < rfPowerTableSize; txPowerIdx++)
{
if (i8TxPowerDbm >= rfPowerTable[txPowerIdx].dbm)
{
cmdSetPower.txPower = rfPowerTable[txPowerIdx].txPower;
EasyLink_cmdPropRadioSetup.setup.txPower = rfPowerTable[txPowerIdx].txPower;
}
}
{
if (i8TxPowerDbm >= rfPowerTable[txPowerIdx].dbm)
{
cmdSetPower.txPower = rfPowerTable[txPowerIdx].txPower;
EasyLink_cmdPropRadioSetup.setup.txPower = rfPowerTable[txPowerIdx].txPower;
}
}
//point the Operational Command to the immediate set power command
immOpCmd.cmdrVal = (uint32_t) &cmdSetPower;
immOpCmd.cmdrVal = (uint32_t) &cmdSetPower;
// Send command
RF_CmdHandle cmd = RF_postCmd(rfHandle, (RF_Op*)&immOpCmd,
RF_PriorityNormal, 0, EASYLINK_RF_EVENT_MASK);
RF_CmdHandle cmd = RF_postCmd(rfHandle, (RF_Op*)&immOpCmd,
RF_PriorityNormal, 0, EASYLINK_RF_EVENT_MASK);
RF_EventMask result = RF_pendCmd(rfHandle, cmd, RF_EventLastCmdDone);
if (result & RF_EventLastCmdDone)
{
status = EasyLink_Status_Success;
}
#endif
{
status = EasyLink_Status_Success;
}
#endif
//Release the busyMutex
Semaphore_post(busyMutex);
Semaphore_post(busyMutex);
return status;
}
}
EasyLink_Status EasyLink_getRfPower(int8_t *pi8TxPowerDbm)
{
int8_t txPowerDbm = 0xff;
{
int8_t txPowerDbm = 0xff;
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
{
return EasyLink_Status_Config_Error;
}
#if (defined Board_CC1310_LAUNCHXL) || (defined Board_CC1350_LAUNCHXL) || \
(defined Board_CC1350STK) || (defined Board_CC1350_LAUNCHXL_433) || \
(defined Board_CC1312R1_LAUNCHXL) || (defined Board_CC1352R1_LAUNCHXL) || \
(defined Board_CC1352P1_LAUNCHXL) || (defined Board_CC1352P_2_LAUNCHXL) || \
(defined Board_CC1352P_4_LAUNCHXL) || (defined Board_CC2640R2_LAUNCHXL)
(defined Board_CC1350STK) || (defined Board_CC1350_LAUNCHXL_433) || \
(defined Board_CC1312R1_LAUNCHXL) || (defined Board_CC1352R1_LAUNCHXL) || \
(defined Board_CC1352P1_LAUNCHXL) || (defined Board_CC1352P_2_LAUNCHXL) || \
(defined Board_CC1352P_4_LAUNCHXL) || (defined Board_CC2640R2_LAUNCHXL)
uint8_t rfPowerTableSize = 0;
RF_TxPowerTable_Entry *rfPowerTable = NULL;
RF_TxPowerTable_Value currValue = RF_getTxPower(rfHandle);
RF_TxPowerTable_Entry *rfPowerTable = NULL;
RF_TxPowerTable_Value currValue = RF_getTxPower(rfHandle);
if(currValue.rawValue == RF_TxPowerTable_INVALID_VALUE)
{
// Value not valid
return EasyLink_Status_Config_Error;
}
else
{
rfPowerTable = (RF_TxPowerTable_Entry *)rfSetting->RF_pTxPowerTable;
rfPowerTableSize = rfSetting->RF_txPowerTableSize;
txPowerDbm = RF_TxPowerTable_findPowerLevel(rfPowerTable, currValue);
{
// Value not valid
return EasyLink_Status_Config_Error;
}
else
{
rfPowerTable = (RF_TxPowerTable_Entry *)rfSetting->RF_pTxPowerTable;
rfPowerTableSize = rfSetting->RF_txPowerTableSize;
txPowerDbm = RF_TxPowerTable_findPowerLevel(rfPowerTable, currValue);
//if CCFG_FORCE_VDDR_HH is not set max power cannot be achieved; this
//does not apply to 2.4GHz proprietary modes either
#if (CCFG_FORCE_VDDR_HH != 0x1)
if((currValue.paType == RF_TxPowerTable_DefaultPA) &&
(txPowerDbm == rfPowerTable[rfPowerTableSize-2].power))
{
#if !(defined Board_CC2640R2_LAUNCHXL)
txPowerDbm = rfPowerTable[rfPowerTableSize-3].power;
#endif
}
#else
// dummy read to avoid build warnings
if(rfPowerTable[rfPowerTableSize-2].power){}
#endif
}
#else
uint8_t txPowerIdx;
for (txPowerIdx = 0; txPowerIdx < rfPowerTableSize; txPowerIdx++)
{
if (rfPowerTable[txPowerIdx].txPower == EasyLink_cmdPropRadioSetup.setup.txPower)
{
txPowerDbm = rfPowerTable[txPowerIdx].dbm;
continue;
}
}
//does not apply to 2.4GHz proprietary modes either
#if (CCFG_FORCE_VDDR_HH != 0x1)
if((currValue.paType == RF_TxPowerTable_DefaultPA) &&
(txPowerDbm == rfPowerTable[rfPowerTableSize-2].power))
{
#if !(defined Board_CC2640R2_LAUNCHXL)
txPowerDbm = rfPowerTable[rfPowerTableSize-3].power;
#endif
}
#else
// dummy read to avoid build warnings
if(rfPowerTable[rfPowerTableSize-2].power){}
#endif
}
#else
uint8_t txPowerIdx;
for (txPowerIdx = 0; txPowerIdx < rfPowerTableSize; txPowerIdx++)
{
if (rfPowerTable[txPowerIdx].txPower == EasyLink_cmdPropRadioSetup.setup.txPower)
{
txPowerDbm = rfPowerTable[txPowerIdx].dbm;
continue;
}
}
//if CCFG_FORCE_VDDR_HH is not set max power cannot be achieved
#if (CCFG_FORCE_VDDR_HH != 0x1)
if (txPowerDbm == rfPowerTable[rfPowerTableSize-1].dbm)
{
txPowerDbm = rfPowerTable[rfPowerTableSize-2].dbm;
}
#endif
#endif
#if (CCFG_FORCE_VDDR_HH != 0x1)
if (txPowerDbm == rfPowerTable[rfPowerTableSize-1].dbm)
{
txPowerDbm = rfPowerTable[rfPowerTableSize-2].dbm;
}
#endif
#endif
*pi8TxPowerDbm = txPowerDbm;
return EasyLink_Status_Success;
}
}
EasyLink_Status EasyLink_getRssi(int8_t *pi8Rssi)
{
if((!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
{
if((!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
*pi8Rssi = RF_getRssi(rfHandle);
return EasyLink_Status_Success;
}
}
EasyLink_Status EasyLink_getAbsTime(uint32_t *pui32AbsTime)
{
if((!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
{
if((!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
*pui32AbsTime = RF_getCurrentTime();
return EasyLink_Status_Success;
}
}
EasyLink_Status EasyLink_transmit(EasyLink_TxPacket *txPacket)
{
EasyLink_Status status = EasyLink_Status_Tx_Error;
RF_ScheduleCmdParams schParams_prop;
RF_CmdHandle cmdHdl;
uint32_t cmdTime;
{
EasyLink_Status status = EasyLink_Status_Tx_Error;
RF_ScheduleCmdParams schParams_prop;
RF_CmdHandle cmdHdl;
uint32_t cmdTime;
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
if (txPacket->len > EASYLINK_MAX_DATA_LENGTH)
{
return EasyLink_Status_Param_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
{
return EasyLink_Status_Config_Error;
}
if (txPacket->len > EASYLINK_MAX_DATA_LENGTH)
{
return EasyLink_Status_Param_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
if(useIeeeHeader)
{
uint16_t ieeeHdr = EASYLINK_IEEE_HDR_CREATE(EASYLINK_IEEE_HDR_CRC_2BYTE, EASYLINK_IEEE_HDR_WHTNG_EN, (txPacket->len + addrSize + sizeof(ieeeHdr)));
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
txBuffer[0] = (uint8_t)(ieeeHdr & 0x00FF);
txBuffer[1] = (uint8_t)((ieeeHdr & 0xFF00) >> 8);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
txBuffer[0] = txPacket->len + addrSize;
}
memcpy(&txBuffer[hdrSize], txPacket->dstAddr, addrSize);
memcpy(&txBuffer[addrSize + hdrSize], txPacket->payload, txPacket->len);
//packet length to Tx includes address and length field
EasyLink_cmdPropTxAdv.pktLen = txPacket->len + addrSize + hdrSize;
EasyLink_cmdPropTxAdv.pPkt = txBuffer;
EasyLink_cmdPropTxAdv.pktLen = txPacket->len + addrSize + hdrSize;
EasyLink_cmdPropTxAdv.pPkt = txBuffer;
if(EasyLink_params.ui32ModType == EasyLink_Phy_5kbpsSlLr)
{
/* calculate the command time:
* (len + preamble + phy len + address) * 8bits / 5kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 5;
}
else //assume 50kbps
{
/* calculate the command time:
* (len + preamble + syncword + len + address) * 8bits / 50kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 50;
}
{
/* calculate the command time:
* (len + preamble + phy len + address) * 8bits / 5kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 5;
}
else //assume 50kbps
{
/* calculate the command time:
* (len + preamble + syncword + len + address) * 8bits / 50kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 50;
}
if (txPacket->absTime != 0)
{
EasyLink_cmdPropTxAdv.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropTxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropTxAdv.startTime = txPacket->absTime;
schParams_prop.endTime = EasyLink_cmdPropTxAdv.startTime + EasyLink_ms_To_RadioTime(cmdTime);
}
else
{
EasyLink_cmdPropTxAdv.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropTxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropTxAdv.startTime = 0;
schParams_prop.endTime = RF_getCurrentTime() + EasyLink_ms_To_RadioTime(cmdTime);
}
{
EasyLink_cmdPropTxAdv.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropTxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropTxAdv.startTime = txPacket->absTime;
schParams_prop.endTime = EasyLink_cmdPropTxAdv.startTime + EasyLink_ms_To_RadioTime(cmdTime);
}
else
{
EasyLink_cmdPropTxAdv.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropTxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropTxAdv.startTime = 0;
schParams_prop.endTime = RF_getCurrentTime() + EasyLink_ms_To_RadioTime(cmdTime);
}
PIN_setOutputValue(paPinHandle, Board_PALNA_PA, 1);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
// Send packet
if(rfModeMultiClient)
{
schParams_prop.priority = RF_PriorityHigh;
cmdHdl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropTxAdv,
&schParams_prop, 0, EASYLINK_RF_EVENT_MASK);
}
else
{
cmdHdl = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropTxAdv,
RF_PriorityHigh, 0, EASYLINK_RF_EVENT_MASK);
}
if(rfModeMultiClient)
{
schParams_prop.priority = RF_PriorityHigh;
cmdHdl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropTxAdv,
&schParams_prop, 0, EASYLINK_RF_EVENT_MASK);
}
else
{
cmdHdl = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropTxAdv,
RF_PriorityHigh, 0, EASYLINK_RF_EVENT_MASK);
}
// Wait for Command to complete
RF_EventMask result = RF_pendCmd(rfHandle, cmdHdl, EASYLINK_RF_EVENT_MASK);
RF_EventMask result = RF_pendCmd(rfHandle, cmdHdl, EASYLINK_RF_EVENT_MASK);
if (result & RF_EventLastCmdDone)
{
status = EasyLink_Status_Success;
}
{
status = EasyLink_Status_Success;
}
PIN_setOutputValue(paPinHandle, Board_PALNA_PA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
//Release the busyMutex
Semaphore_post(busyMutex);
Semaphore_post(busyMutex);
return status;
}
}
EasyLink_Status EasyLink_transmitAsync(EasyLink_TxPacket *txPacket, EasyLink_TxDoneCb cb)
{
EasyLink_Status status = EasyLink_Status_Tx_Error;
RF_ScheduleCmdParams schParams_prop;
uint32_t cmdTime;
{
EasyLink_Status status = EasyLink_Status_Tx_Error;
RF_ScheduleCmdParams schParams_prop;
uint32_t cmdTime;
//Check if not configure or already an Async command being performed
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Busy_Error;
}
if (txPacket->len > EASYLINK_MAX_DATA_LENGTH)
{
return EasyLink_Status_Param_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Busy_Error;
}
if (txPacket->len > EASYLINK_MAX_DATA_LENGTH)
{
return EasyLink_Status_Param_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
//store application callback
txCb = cb;
txCb = cb;
if(useIeeeHeader)
{
uint16_t ieeeHdr = EASYLINK_IEEE_HDR_CREATE(EASYLINK_IEEE_HDR_CRC_2BYTE, EASYLINK_IEEE_HDR_WHTNG_EN, (txPacket->len + addrSize + sizeof(ieeeHdr)));
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
txBuffer[0] = (uint8_t)(ieeeHdr & 0x00FF);
txBuffer[1] = (uint8_t)((ieeeHdr & 0xFF00) >> 8);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
txBuffer[0] = txPacket->len + addrSize;
}
memcpy(&txBuffer[hdrSize], txPacket->dstAddr, addrSize);
memcpy(&txBuffer[addrSize + hdrSize], txPacket->payload, txPacket->len);
{
uint16_t ieeeHdr = EASYLINK_IEEE_HDR_CREATE(EASYLINK_IEEE_HDR_CRC_2BYTE, EASYLINK_IEEE_HDR_WHTNG_EN, (txPacket->len + addrSize + sizeof(ieeeHdr)));
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
txBuffer[0] = (uint8_t)(ieeeHdr & 0x00FF);
txBuffer[1] = (uint8_t)((ieeeHdr & 0xFF00) >> 8);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
txBuffer[0] = txPacket->len + addrSize;
}
memcpy(&txBuffer[hdrSize], txPacket->dstAddr, addrSize);
memcpy(&txBuffer[addrSize + hdrSize], txPacket->payload, txPacket->len);
//packet length to Tx includes address and length field
EasyLink_cmdPropTxAdv.pktLen = txPacket->len + addrSize + hdrSize;
EasyLink_cmdPropTxAdv.pPkt = txBuffer;
EasyLink_cmdPropTxAdv.pktLen = txPacket->len + addrSize + hdrSize;
EasyLink_cmdPropTxAdv.pPkt = txBuffer;
if(EasyLink_params.ui32ModType == EasyLink_Phy_5kbpsSlLr)
{
/* calculate the command time:
* (len + preamble + phy len + address) * 8bits / 5kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 5;
}
else //assume 50kbps
{
/* calculate the command time:
* (len + preamble + syncword + len + address) * 8bits / 50kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 50;
}
{
/* calculate the command time:
* (len + preamble + phy len + address) * 8bits / 5kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 5;
}
else //assume 50kbps
{
/* calculate the command time:
* (len + preamble + syncword + len + address) * 8bits / 50kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 50;
}
if (txPacket->absTime != 0)
{
EasyLink_cmdPropTxAdv.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropTxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropTxAdv.startTime = txPacket->absTime;
schParams_prop.endTime = EasyLink_cmdPropTxAdv.startTime + EasyLink_ms_To_RadioTime(cmdTime);
}
else
{
EasyLink_cmdPropTxAdv.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropTxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropTxAdv.startTime = 0;
schParams_prop.endTime = RF_getCurrentTime() + EasyLink_ms_To_RadioTime(cmdTime);
}
{
EasyLink_cmdPropTxAdv.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropTxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropTxAdv.startTime = txPacket->absTime;
schParams_prop.endTime = EasyLink_cmdPropTxAdv.startTime + EasyLink_ms_To_RadioTime(cmdTime);
}
else
{
EasyLink_cmdPropTxAdv.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropTxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropTxAdv.startTime = 0;
schParams_prop.endTime = RF_getCurrentTime() + EasyLink_ms_To_RadioTime(cmdTime);
}
// Send packet
if(rfModeMultiClient)
{
schParams_prop.priority = RF_PriorityHigh;
asyncCmdHndl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropTxAdv,
&schParams_prop, txDoneCallback, EASYLINK_RF_EVENT_MASK);
}
else
{
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropTxAdv,
RF_PriorityHigh, txDoneCallback, EASYLINK_RF_EVENT_MASK);
}
if(rfModeMultiClient)
{
schParams_prop.priority = RF_PriorityHigh;
asyncCmdHndl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropTxAdv,
&schParams_prop, txDoneCallback, EASYLINK_RF_EVENT_MASK);
}
else
{
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropTxAdv,
RF_PriorityHigh, txDoneCallback, EASYLINK_RF_EVENT_MASK);
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
status = EasyLink_Status_Success;
}
{
status = EasyLink_Status_Success;
}
//busyMutex will be released by the callback
return status;
}
}
#if (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
EasyLink_Status EasyLink_transmitCcaAsync(EasyLink_TxPacket *txPacket, EasyLink_TxDoneCb cb)
{
EasyLink_Status status = EasyLink_Status_Tx_Error;
RF_ScheduleCmdParams schParams_prop;
uint32_t cmdTime;
EasyLink_Status EasyLink_transmitCcaAsync(EasyLink_TxPacket *txPacket, EasyLink_TxDoneCb cb)
{
EasyLink_Status status = EasyLink_Status_Tx_Error;
RF_ScheduleCmdParams schParams_prop;
uint32_t cmdTime;
//Check if not configure or already an Async command being performed, or
//if a random number generator function is not provided
if ( (!configured) || suspended || (!getRN))
{
return EasyLink_Status_Config_Error;
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Busy_Error;
}
if (txPacket->len > EASYLINK_MAX_DATA_LENGTH)
{
return EasyLink_Status_Param_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
//if a random number generator function is not provided
if ( (!configured) || suspended || (!getRN))
{
return EasyLink_Status_Config_Error;
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Busy_Error;
}
if (txPacket->len > EASYLINK_MAX_DATA_LENGTH)
{
return EasyLink_Status_Param_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
//store application callback
txCb = cb;
txCb = cb;
if(useIeeeHeader)
{
uint16_t ieeeHdr = EASYLINK_IEEE_HDR_CREATE(EASYLINK_IEEE_HDR_CRC_2BYTE, EASYLINK_IEEE_HDR_WHTNG_EN, (txPacket->len + addrSize + sizeof(ieeeHdr)));
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
txBuffer[0] = (uint8_t)(ieeeHdr & 0x00FF);
txBuffer[1] = (uint8_t)((ieeeHdr & 0xFF00) >> 8);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
txBuffer[0] = txPacket->len + addrSize;
}
memcpy(&txBuffer[hdrSize], txPacket->dstAddr, addrSize);
memcpy(&txBuffer[addrSize + hdrSize], txPacket->payload, txPacket->len);
{
uint16_t ieeeHdr = EASYLINK_IEEE_HDR_CREATE(EASYLINK_IEEE_HDR_CRC_2BYTE, EASYLINK_IEEE_HDR_WHTNG_EN, (txPacket->len + addrSize + sizeof(ieeeHdr)));
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
txBuffer[0] = (uint8_t)(ieeeHdr & 0x00FF);
txBuffer[1] = (uint8_t)((ieeeHdr & 0xFF00) >> 8);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
txBuffer[0] = txPacket->len + addrSize;
}
memcpy(&txBuffer[hdrSize], txPacket->dstAddr, addrSize);
memcpy(&txBuffer[addrSize + hdrSize], txPacket->payload, txPacket->len);
// Set the Carrier Sense command attributes
// Chain the TX command to run after the CS command
EasyLink_cmdPropCs.pNextOp = (rfc_radioOp_t *)&EasyLink_cmdPropTxAdv;
// Chain the TX command to run after the CS command
EasyLink_cmdPropCs.pNextOp = (rfc_radioOp_t *)&EasyLink_cmdPropTxAdv;
//packet length to Tx includes address and length field
EasyLink_cmdPropTxAdv.pktLen = txPacket->len + addrSize + hdrSize;
EasyLink_cmdPropTxAdv.pPkt = txBuffer;
EasyLink_cmdPropTxAdv.pktLen = txPacket->len + addrSize + hdrSize;
EasyLink_cmdPropTxAdv.pPkt = txBuffer;
if(EasyLink_params.ui32ModType == EasyLink_Phy_5kbpsSlLr)
{
/* calculate the command time:
* (len + preamble + phy len + address) * 8bits / 5kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 5;
}
else //assume 50kbps
{
/* calculate the command time:
* (len + preamble + syncword + len + address) * 8bits / 50kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 50;
}
{
/* calculate the command time:
* (len + preamble + phy len + address) * 8bits / 5kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 5;
}
else //assume 50kbps
{
/* calculate the command time:
* (len + preamble + syncword + len + address) * 8bits / 50kbps */
cmdTime = ((EasyLink_cmdPropTxAdv.pktLen + 10 + addrSize) * 8) / 50;
}
if (txPacket->absTime != 0)
{
EasyLink_cmdPropCs.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropCs.startTrigger.pastTrig = 1;
EasyLink_cmdPropCs.startTime = txPacket->absTime;
schParams_prop.endTime = EasyLink_cmdPropCs.startTime + EasyLink_ms_To_RadioTime(cmdTime);
}
else
{
EasyLink_cmdPropCs.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropCs.startTrigger.pastTrig = 1;
EasyLink_cmdPropCs.startTime = 0;
schParams_prop.endTime = RF_getCurrentTime() + EasyLink_ms_To_RadioTime(cmdTime);
}
{
EasyLink_cmdPropCs.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropCs.startTrigger.pastTrig = 1;
EasyLink_cmdPropCs.startTime = txPacket->absTime;
schParams_prop.endTime = EasyLink_cmdPropCs.startTime + EasyLink_ms_To_RadioTime(cmdTime);
}
else
{
EasyLink_cmdPropCs.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropCs.startTrigger.pastTrig = 1;
EasyLink_cmdPropCs.startTime = 0;
schParams_prop.endTime = RF_getCurrentTime() + EasyLink_ms_To_RadioTime(cmdTime);
}
// Check for a clear channel (CCA) before sending a packet
if(rfModeMultiClient)
{
schParams_prop.priority = RF_PriorityHigh;
asyncCmdHndl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropCs,
&schParams_prop, ccaDoneCallback, EASYLINK_RF_EVENT_MASK);
}
else
{
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropCs,
RF_PriorityHigh, ccaDoneCallback, EASYLINK_RF_EVENT_MASK);
}
if(rfModeMultiClient)
{
schParams_prop.priority = RF_PriorityHigh;
asyncCmdHndl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropCs,
&schParams_prop, ccaDoneCallback, EASYLINK_RF_EVENT_MASK);
}
else
{
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropCs,
RF_PriorityHigh, ccaDoneCallback, EASYLINK_RF_EVENT_MASK);
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
status = EasyLink_Status_Success;
}
{
status = EasyLink_Status_Success;
}
//busyMutex will be released by the callback
return status;
}
#endif // (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
}
#endif // (defined(DeviceFamily_CC13X0) || defined(DeviceFamily_CC13X2))
EasyLink_Status EasyLink_receive(EasyLink_RxPacket *rxPacket)
{
EasyLink_Status status = EasyLink_Status_Rx_Error;
RF_EventMask result;
rfc_dataEntryGeneral_t *pDataEntry;
RF_CmdHandle rx_cmd;
RF_ScheduleCmdParams schParams_prop;
{
EasyLink_Status status = EasyLink_Status_Rx_Error;
RF_EventMask result;
rfc_dataEntryGeneral_t *pDataEntry;
RF_CmdHandle rx_cmd;
RF_ScheduleCmdParams schParams_prop;
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
{
return EasyLink_Status_Config_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
pDataEntry = (rfc_dataEntryGeneral_t*) rxBuffer;
//data entry rx buffer includes hdr (len-1Byte), addr (max 8Bytes) and data
pDataEntry->length = 1 + EASYLINK_MAX_ADDR_SIZE + EASYLINK_MAX_DATA_LENGTH;
pDataEntry->status = 0;
dataQueue.pCurrEntry = (uint8_t*)pDataEntry;
dataQueue.pLastEntry = NULL;
EasyLink_cmdPropRxAdv.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
EasyLink_cmdPropRxAdv.pOutput = (uint8_t*)&rxStatistics;
//data entry rx buffer includes hdr (len-1Byte), addr (max 8Bytes) and data
pDataEntry->length = 1 + EASYLINK_MAX_ADDR_SIZE + EASYLINK_MAX_DATA_LENGTH;
pDataEntry->status = 0;
dataQueue.pCurrEntry = (uint8_t*)pDataEntry;
dataQueue.pLastEntry = NULL;
EasyLink_cmdPropRxAdv.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
EasyLink_cmdPropRxAdv.pOutput = (uint8_t*)&rxStatistics;
if (rxPacket->absTime != 0)
{
EasyLink_cmdPropRxAdv.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.startTime = rxPacket->absTime;
}
else
{
EasyLink_cmdPropRxAdv.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.startTime = 0;
}
{
EasyLink_cmdPropRxAdv.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.startTime = rxPacket->absTime;
}
else
{
EasyLink_cmdPropRxAdv.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.startTime = 0;
}
if (rxPacket->rxTimeout != 0)
{
EasyLink_cmdPropRxAdv.endTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.endTime = RF_getCurrentTime() + rxPacket->rxTimeout;
}
else
{
EasyLink_cmdPropRxAdv.endTrigger.triggerType = TRIG_NEVER;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.endTime = 0;
}
{
EasyLink_cmdPropRxAdv.endTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.endTime = RF_getCurrentTime() + rxPacket->rxTimeout;
}
else
{
EasyLink_cmdPropRxAdv.endTrigger.triggerType = TRIG_NEVER;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.endTime = 0;
}
//Clear the Rx statistics structure
memset(&rxStatistics, 0, sizeof(rfc_propRxOutput_t));
memset(&rxStatistics, 0, sizeof(rfc_propRxOutput_t));
if(rfModeMultiClient)
{
/* assume high priority */
schParams_prop.priority = RF_PriorityHigh;
schParams_prop.endTime = EasyLink_cmdPropRxAdv.endTime;
{
/* assume high priority */
schParams_prop.priority = RF_PriorityHigh;
schParams_prop.endTime = EasyLink_cmdPropRxAdv.endTime;
rx_cmd = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRxAdv,
&schParams_prop, 0, EASYLINK_RF_EVENT_MASK);
}
else
{
rx_cmd = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRxAdv,
RF_PriorityHigh, 0, EASYLINK_RF_EVENT_MASK);
}
&schParams_prop, 0, EASYLINK_RF_EVENT_MASK);
}
else
{
rx_cmd = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRxAdv,
RF_PriorityHigh, 0, EASYLINK_RF_EVENT_MASK);
}
/* Wait for Command to complete */
result = RF_pendCmd(rfHandle, rx_cmd, RF_EventLastCmdDone);
result = RF_pendCmd(rfHandle, rx_cmd, RF_EventLastCmdDone);
if (result & RF_EventLastCmdDone)
{
//Check command status
if (EasyLink_cmdPropRxAdv.status == PROP_DONE_OK)
{
//Check that data entry status indicates it is finished with
if (pDataEntry->status != DATA_ENTRY_FINISHED)
{
status = EasyLink_Status_Rx_Error;
}
//check Rx Statistics
else if ( (rxStatistics.nRxOk == 1) ||
//or filer disabled and ignore due to addr mistmatch
((EasyLink_cmdPropRxAdv.pktConf.filterOp == 1) &&
(rxStatistics.nRxIgnored == 1)) )
{
//copy length from pDataEntry (- addrSize)
rxPacket->len = *(uint8_t*)(&pDataEntry->data) - addrSize;
if(useIeeeHeader)
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
}
//copy address
memcpy(rxPacket->dstAddr, (&pDataEntry->data + hdrSize), addrSize);
//copy payload
memcpy(&rxPacket->payload, (&pDataEntry->data + hdrSize + addrSize), (rxPacket->len));
rxPacket->rssi = rxStatistics.lastRssi;
{
//Check command status
if (EasyLink_cmdPropRxAdv.status == PROP_DONE_OK)
{
//Check that data entry status indicates it is finished with
if (pDataEntry->status != DATA_ENTRY_FINISHED)
{
status = EasyLink_Status_Rx_Error;
}
//check Rx Statistics
else if ( (rxStatistics.nRxOk == 1) ||
//or filer disabled and ignore due to addr mistmatch
((EasyLink_cmdPropRxAdv.pktConf.filterOp == 1) &&
(rxStatistics.nRxIgnored == 1)) )
{
//copy length from pDataEntry (- addrSize)
rxPacket->len = *(uint8_t*)(&pDataEntry->data) - addrSize;
if(useIeeeHeader)
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_IEEE_HDR_NBITS);
}
else
{
hdrSize = EASYLINK_HDR_SIZE_NBYTES(EASYLINK_PROP_HDR_NBITS);
}
//copy address
memcpy(rxPacket->dstAddr, (&pDataEntry->data + hdrSize), addrSize);
//copy payload
memcpy(&rxPacket->payload, (&pDataEntry->data + hdrSize + addrSize), (rxPacket->len));
rxPacket->rssi = rxStatistics.lastRssi;
status = EasyLink_Status_Success;
rxPacket->absTime = rxStatistics.timeStamp;
}
else if ( rxStatistics.nRxBufFull == 1)
{
status = EasyLink_Status_Rx_Buffer_Error;
}
else if ( rxStatistics.nRxStopped == 1)
{
status = EasyLink_Status_Aborted;
}
else
{
status = EasyLink_Status_Rx_Error;
}
}
else if ( EasyLink_cmdPropRxAdv.status == PROP_DONE_RXTIMEOUT)
{
status = EasyLink_Status_Rx_Timeout;
}
else
{
status = EasyLink_Status_Rx_Error;
}
}
rxPacket->absTime = rxStatistics.timeStamp;
}
else if ( rxStatistics.nRxBufFull == 1)
{
status = EasyLink_Status_Rx_Buffer_Error;
}
else if ( rxStatistics.nRxStopped == 1)
{
status = EasyLink_Status_Aborted;
}
else
{
status = EasyLink_Status_Rx_Error;
}
}
else if ( EasyLink_cmdPropRxAdv.status == PROP_DONE_RXTIMEOUT)
{
status = EasyLink_Status_Rx_Timeout;
}
else
{
status = EasyLink_Status_Rx_Error;
}
}
//Release the busyMutex
Semaphore_post(busyMutex);
Semaphore_post(busyMutex);
return status;
}
}
EasyLink_Status EasyLink_receiveAsync(EasyLink_ReceiveCb cb, uint32_t absTime)
{
EasyLink_Status status = EasyLink_Status_Rx_Error;
rfc_dataEntryGeneral_t *pDataEntry;
RF_ScheduleCmdParams schParams_prop;
{
EasyLink_Status status = EasyLink_Status_Rx_Error;
rfc_dataEntryGeneral_t *pDataEntry;
RF_ScheduleCmdParams schParams_prop;
//Check if not configure of already an Async command being performed
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Busy_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Busy_Error;
}
//Check and take the busyMutex
if (Semaphore_pend(busyMutex, 0) == false)
{
return EasyLink_Status_Busy_Error;
}
rxCb = cb;
pDataEntry = (rfc_dataEntryGeneral_t*) rxBuffer;
//data entry rx buffer includes hdr (len-1Byte), addr (max 8Bytes) and data
pDataEntry->length = 1 + EASYLINK_MAX_ADDR_SIZE + EASYLINK_MAX_DATA_LENGTH;
pDataEntry->status = 0;
dataQueue.pCurrEntry = (uint8_t*)pDataEntry;
dataQueue.pLastEntry = NULL;
EasyLink_cmdPropRxAdv.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
EasyLink_cmdPropRxAdv.pOutput = (uint8_t*)&rxStatistics;
//data entry rx buffer includes hdr (len-1Byte), addr (max 8Bytes) and data
pDataEntry->length = 1 + EASYLINK_MAX_ADDR_SIZE + EASYLINK_MAX_DATA_LENGTH;
pDataEntry->status = 0;
dataQueue.pCurrEntry = (uint8_t*)pDataEntry;
dataQueue.pLastEntry = NULL;
EasyLink_cmdPropRxAdv.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
EasyLink_cmdPropRxAdv.pOutput = (uint8_t*)&rxStatistics;
if (absTime != 0)
{
EasyLink_cmdPropRxAdv.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.startTime = absTime;
}
else
{
EasyLink_cmdPropRxAdv.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.startTime = 0;
}
{
EasyLink_cmdPropRxAdv.startTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.startTime = absTime;
}
else
{
EasyLink_cmdPropRxAdv.startTrigger.triggerType = TRIG_NOW;
EasyLink_cmdPropRxAdv.startTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.startTime = 0;
}
if (asyncRxTimeOut != 0)
{
EasyLink_cmdPropRxAdv.endTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.endTime = RF_getCurrentTime() + asyncRxTimeOut;
}
else
{
EasyLink_cmdPropRxAdv.endTrigger.triggerType = TRIG_NEVER;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.endTime = 0;
}
{
EasyLink_cmdPropRxAdv.endTrigger.triggerType = TRIG_ABSTIME;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.endTime = RF_getCurrentTime() + asyncRxTimeOut;
}
else
{
EasyLink_cmdPropRxAdv.endTrigger.triggerType = TRIG_NEVER;
EasyLink_cmdPropRxAdv.endTrigger.pastTrig = 1;
EasyLink_cmdPropRxAdv.endTime = 0;
}
//Clear the Rx statistics structure
memset(&rxStatistics, 0, sizeof(rfc_propRxOutput_t));
memset(&rxStatistics, 0, sizeof(rfc_propRxOutput_t));
PIN_setOutputValue(paPinHandle, Board_PALNA_PA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
if(rfModeMultiClient)
{
/* assume high priority */
schParams_prop.priority = RF_PriorityHigh;
schParams_prop.endTime = EasyLink_cmdPropRxAdv.endTime;
{
/* assume high priority */
schParams_prop.priority = RF_PriorityHigh;
schParams_prop.endTime = EasyLink_cmdPropRxAdv.endTime;
asyncCmdHndl = RF_scheduleCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRxAdv,
&schParams_prop, rxDoneCallback, EASYLINK_RF_EVENT_MASK);
}
else
{
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRxAdv,
RF_PriorityHigh, rxDoneCallback, EASYLINK_RF_EVENT_MASK);
}
&schParams_prop, rxDoneCallback, EASYLINK_RF_EVENT_MASK);
}
else
{
asyncCmdHndl = RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRxAdv,
RF_PriorityHigh, rxDoneCallback, EASYLINK_RF_EVENT_MASK);
}
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
status = EasyLink_Status_Success;
}
else
{
PIN_setOutputValue(paPinHandle, Board_PALNA_PA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
{
status = EasyLink_Status_Success;
}
else
{
PIN_setOutputValue(paPinHandle, Board_PALNA_PA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 0);
PIN_setOutputValue(paPinHandle, Board_PALNA_LNA, 1);
//Callback will not be called, release the busyMutex
Semaphore_post(busyMutex);
Semaphore_post(busyMutex);
}
//busyMutex will be released in callback
return status;
}
}
EasyLink_Status EasyLink_abort(void)
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
//check an Async command is running, if not return success
if (!EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Aborted;
}
{
return EasyLink_Status_Config_Error;
}
//check an Async command is running, if not return success
if (!EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
return EasyLink_Status_Aborted;
}
//force abort (gracefull param set to 0)
if (RF_cancelCmd(rfHandle, asyncCmdHndl, 0) == RF_StatSuccess)
{
/* If command is cancelled immediately, callback may have set the cmd handle to invalid.
* In that case, no need to pend.
*/
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
/* Wait for Command to complete */
RF_EventMask result = RF_pendCmd(rfHandle, asyncCmdHndl, (RF_EventLastCmdDone |
RF_EventCmdAborted | RF_EventCmdCancelled | RF_EventCmdStopped));
if (result & RF_EventLastCmdDone)
{
status = EasyLink_Status_Success;
}
}
else
{
/* Command already cancelled */
status = EasyLink_Status_Success;
}
}
else
{
status = EasyLink_Status_Cmd_Error;
}
if (RF_cancelCmd(rfHandle, asyncCmdHndl, 0) == RF_StatSuccess)
{
/* If command is cancelled immediately, callback may have set the cmd handle to invalid.
* In that case, no need to pend.
*/
if (EasyLink_CmdHandle_isValid(asyncCmdHndl))
{
/* Wait for Command to complete */
RF_EventMask result = RF_pendCmd(rfHandle, asyncCmdHndl, (RF_EventLastCmdDone |
RF_EventCmdAborted | RF_EventCmdCancelled | RF_EventCmdStopped));
if (result & RF_EventLastCmdDone)
{
status = EasyLink_Status_Success;
}
}
else
{
/* Command already cancelled */
status = EasyLink_Status_Success;
}
}
else
{
status = EasyLink_Status_Cmd_Error;
}
return status;
}
}
EasyLink_Status EasyLink_enableRxAddrFilter(uint8_t* pui8AddrFilterTable, uint8_t ui8AddrSize, uint8_t ui8NumAddrs)
{
EasyLink_Status status = EasyLink_Status_Param_Error;
{
EasyLink_Status status = EasyLink_Status_Param_Error;
if ( (!configured) || suspended)
{
return EasyLink_Status_Config_Error;
}
if (isAddrSizeValid(ui8AddrSize) == false)
{
return EasyLink_Status_Param_Error;
}
if ( Semaphore_pend(busyMutex, 0) == false )
{
return EasyLink_Status_Busy_Error;
}
{
return EasyLink_Status_Config_Error;
}
if (isAddrSizeValid(ui8AddrSize) == false)
{
return EasyLink_Status_Param_Error;
}
if ( Semaphore_pend(busyMutex, 0) == false )
{
return EasyLink_Status_Busy_Error;
}
if ( (pui8AddrFilterTable != NULL) &&
(ui8AddrSize != 0) && (ui8NumAddrs != 0) &&
(ui8AddrSize == addrSize) &&
(ui8NumAddrs <= EASYLINK_MAX_ADDR_FILTERS) )
{
memcpy(addrFilterTable, pui8AddrFilterTable, ui8AddrSize * ui8NumAddrs);
EasyLink_cmdPropRxAdv.addrConf.addrSize = ui8AddrSize;
EasyLink_cmdPropRxAdv.addrConf.numAddr = ui8NumAddrs;
EasyLink_cmdPropRxAdv.pktConf.filterOp = 0;
(ui8AddrSize != 0) && (ui8NumAddrs != 0) &&
(ui8AddrSize == addrSize) &&
(ui8NumAddrs <= EASYLINK_MAX_ADDR_FILTERS) )
{
memcpy(addrFilterTable, pui8AddrFilterTable, ui8AddrSize * ui8NumAddrs);
EasyLink_cmdPropRxAdv.addrConf.addrSize = ui8AddrSize;
EasyLink_cmdPropRxAdv.addrConf.numAddr = ui8NumAddrs;
EasyLink_cmdPropRxAdv.pktConf.filterOp = 0;
status = EasyLink_Status_Success;
}
else if (pui8AddrFilterTable == NULL)
{
//disable filter
EasyLink_cmdPropRxAdv.pktConf.filterOp = 1;
}
else if (pui8AddrFilterTable == NULL)
{
//disable filter
EasyLink_cmdPropRxAdv.pktConf.filterOp = 1;
status = EasyLink_Status_Success;
}
}
//Release the busyMutex
Semaphore_post(busyMutex);
Semaphore_post(busyMutex);
return status;
}
}
EasyLink_Status EasyLink_setCtrl(EasyLink_CtrlOption Ctrl, uint32_t ui32Value)
{
EasyLink_Status status = EasyLink_Status_Param_Error;
switch(Ctrl)
{
case EasyLink_Ctrl_AddSize:
if (isAddrSizeValid(ui32Value))
{
addrSize = (uint8_t) ui32Value;
EasyLink_cmdPropRxAdv.addrConf.addrSize = addrSize;
status = EasyLink_Status_Success;
}
break;
case EasyLink_Ctrl_Idle_TimeOut:
if(configured)
{
// Client has already been configured, need to modify
// the client configuration directly
RF_control(rfHandle, RF_CTRL_SET_INACTIVITY_TIMEOUT, &ui32Value);
}
else
{
// RF_open() in EasyLink_init() has not been called yet so it
// is safe to alter the rfParams
inactivityTimeout = ui32Value;
}
{
EasyLink_Status status = EasyLink_Status_Param_Error;
switch(Ctrl)
{
case EasyLink_Ctrl_AddSize:
if (isAddrSizeValid(ui32Value))
{
addrSize = (uint8_t) ui32Value;
EasyLink_cmdPropRxAdv.addrConf.addrSize = addrSize;
status = EasyLink_Status_Success;
}
break;
case EasyLink_Ctrl_Idle_TimeOut:
if(configured)
{
// Client has already been configured, need to modify
// the client configuration directly
RF_control(rfHandle, RF_CTRL_SET_INACTIVITY_TIMEOUT, &ui32Value);
}
else
{
// RF_open() in EasyLink_init() has not been called yet so it
// is safe to alter the rfParams
inactivityTimeout = ui32Value;
}
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_MultiClient_Mode:
rfModeMultiClient = (bool) ui32Value;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_AsyncRx_TimeOut:
asyncRxTimeOut = ui32Value;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_Test_Tone:
status = enableTestMode(EasyLink_Ctrl_Test_Tone);
break;
case EasyLink_Ctrl_Test_Signal:
status = enableTestMode(EasyLink_Ctrl_Test_Signal);
break;
case EasyLink_Ctrl_Rx_Test_Tone:
status = enableTestMode(EasyLink_Ctrl_Rx_Test_Tone);
break;
}
break;
case EasyLink_Ctrl_MultiClient_Mode:
rfModeMultiClient = (bool) ui32Value;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_AsyncRx_TimeOut:
asyncRxTimeOut = ui32Value;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_Test_Tone:
status = enableTestMode(EasyLink_Ctrl_Test_Tone);
break;
case EasyLink_Ctrl_Test_Signal:
status = enableTestMode(EasyLink_Ctrl_Test_Signal);
break;
case EasyLink_Ctrl_Rx_Test_Tone:
status = enableTestMode(EasyLink_Ctrl_Rx_Test_Tone);
break;
}
return status;
}
}
EasyLink_Status EasyLink_getCtrl(EasyLink_CtrlOption Ctrl, uint32_t* pui32Value)
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
{
EasyLink_Status status = EasyLink_Status_Cmd_Error;
switch(Ctrl)
{
case EasyLink_Ctrl_AddSize:
*pui32Value = addrSize;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_Idle_TimeOut:
*pui32Value = rfParams.nInactivityTimeout;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_MultiClient_Mode:
*pui32Value = (uint32_t) rfModeMultiClient;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_AsyncRx_TimeOut:
*pui32Value = asyncRxTimeOut;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_Test_Tone:
case EasyLink_Ctrl_Test_Signal:
case EasyLink_Ctrl_Rx_Test_Tone:
*pui32Value = 0;
status = EasyLink_Status_Success;
break;
}
{
case EasyLink_Ctrl_AddSize:
*pui32Value = addrSize;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_Idle_TimeOut:
*pui32Value = rfParams.nInactivityTimeout;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_MultiClient_Mode:
*pui32Value = (uint32_t) rfModeMultiClient;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_AsyncRx_TimeOut:
*pui32Value = asyncRxTimeOut;
status = EasyLink_Status_Success;
break;
case EasyLink_Ctrl_Test_Tone:
case EasyLink_Ctrl_Test_Signal:
case EasyLink_Ctrl_Rx_Test_Tone:
*pui32Value = 0;
status = EasyLink_Status_Success;
break;
}
return status;
}
}
EasyLink_Status EasyLink_getIeeeAddr(uint8_t *ieeeAddr)
{
EasyLink_Status status = EasyLink_Status_Param_Error;
{
EasyLink_Status status = EasyLink_Status_Param_Error;
if (ieeeAddr != NULL)
{
int i;
{
int i;
//Reading from primary IEEE location...
uint8_t *location = (uint8_t *)EASYLINK_PRIMARY_IEEE_ADDR_LOCATION;
uint8_t *location = (uint8_t *)EASYLINK_PRIMARY_IEEE_ADDR_LOCATION;
/*
* ...unless we can find a byte != 0xFF in secondary
*
* Intentionally checking all 8 bytes here instead of len, because we
* are checking validity of the entire IEEE address irrespective of the
* actual number of bytes the caller wants to copy over.
*/
for (i = 0; i < 8; i++) {
if (((uint8_t *)EASYLINK_SECONDARY_IEEE_ADDR_LOCATION)[i] != 0xFF) {
//A byte in the secondary location is not 0xFF. Use the
//secondary
location = (uint8_t *)EASYLINK_SECONDARY_IEEE_ADDR_LOCATION;
break;
}
}
* ...unless we can find a byte != 0xFF in secondary
*
* Intentionally checking all 8 bytes here instead of len, because we
* are checking validity of the entire IEEE address irrespective of the
* actual number of bytes the caller wants to copy over.
*/
for (i = 0; i < 8; i++) {
if (((uint8_t *)EASYLINK_SECONDARY_IEEE_ADDR_LOCATION)[i] != 0xFF) {
//A byte in the secondary location is not 0xFF. Use the
//secondary
location = (uint8_t *)EASYLINK_SECONDARY_IEEE_ADDR_LOCATION;
break;
}
}
//inverting byte order
for (i = 0; i < 8; i++) {
ieeeAddr[i] = location[8 - 1 - i];
}
for (i = 0; i < 8; i++) {
ieeeAddr[i] = location[8 - 1 - i];
}
status = EasyLink_Status_Success;
}
}
return status;
}
}