rflib
Data Structures | Macros | Typedefs
rf_hid_cmd.h File Reference

Detailed Description

RF HID command interface for CC13x2, CC26x2.


To use the CMD_HID_TX and CMD_HID_RX commands, make sure that the following override list is being used:

#define TURNAROUND_TIME 64 // 64 µs turnaround time
uint32_t pOverridesCommon[] =
{
// DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0x3 (DITHER_EN=0 and IPEAK=3).
(uint32_t)0x00F388D3,
// Set pilot tone length to 4 us (enable phase error discard as early as possible)
HW_REG_OVERRIDE(0x6024,0x0020),
// Bluetooth 5: Default to no CTE.
HW_REG_OVERRIDE(0x5328,0x0000),
// Synth: Increase mid code calibration time to 5 us
(uint32_t)0x00058683,
// Synth: Increase mid code calibration time to 5 us
// Synth: Increase mid code calibration time to 5 us
(uint32_t)0x38183C30,
// HID: Reduce turnaround times:
(uint32_t)((TURNAROUND_TIME*4)<<16)|0x0263, // modify tx to rx turnaround time
(uint32_t)((TURNAROUND_TIME*4)<<16)|0x0283, // modify rx to tx turnaround time
// Of of override list
(uint32_t)0xFFFFFFFF
};

Overview

The HID commands are designed to be compatible with CC254x devices, using the same protocol as the CC254x. The packet are defined as: 8 bit preamble, 32 bit sync word, optional 8 bit address, 8 or 9 bit header, [0-n] byte payload and 16 bit CRC at 2 Mbps. The HID commands uses the same automode functionality as found in the CC254x devices, see CC254x user guide.

The CMD_HID_TX utlizes a TX queue to evaluate if the subsequent packet should be sent, given that the device is not retranmitting the previous packet. On submission of the CMD_HID_TX, the radio will check if there are TX entries in the queue. If TX entires are present, the radio will start sending the packets as defined by the startTrigger. If no packets are present, the radio will enter a wait-state, waiting on CMD_TRIGGER_HID_TX. Once CMD_TRIGGER_HID_TX is submitted, the radio will re-evaluate the TX queue, and if packets are present , the radio will start sending the TX packets as defined by the startTrigger. If no entries in the TX queue has been submitted, or CMD_STOP/CMD_ABORT was submitted, the CMD_HID_TX will end and the radio is ready for another command.


Usage

This documentation provides basic rf_hid_settings.c, rf_hid_settings.h and a set of examples in the form of commented code fragments. Detailed descriptions of the APIs are provided in subsequent sections.

RF HID settings

// Filename: rf_hid_settings.c
// Import the settings header file
#include "rf_hid_settings.h"
// Import the RF driver definitions
// Import the needed radio files
#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
#include DeviceFamily_constructPath(driverlib/rf_hid_cmd.h)
#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_multi_protocol_hid.h)
#include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
#include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
// TI-RTOS RF Mode Object
RF_Mode RF_hid =
{
.cpePatchFxn = &rf_patch_cpe_multi_protocol_hid,
.mcePatchFxn = 0,
.rfePatchFxn = 0
};
// TX and RX queue declarations
uint8_t txEntry1[BUFFER_LEN];
uint8_t txEntry2[BUFFER_LEN];
uint8_t rxEntry1[BUFFER_LEN];
uint8_t rxEntry2[BUFFER_LEN];
dataQueue_t txQ = {
.pCurrEntry = NULL,
.pLastEntry = NULL,
};
dataQueue_t rxQ = {
.pCurrEntry = NULL,
.pLastEntry = NULL,
};
// Statistics
rfc_hidRxTxOutput_t rxTxStatistics;
// Override list. 64 us turnaround compatible with fastest setting
// for CC254x devices
#define TURNAROUND_TIME 64 // Turnaround time in usec
uint32_t pOverridesCommon[] =
{
// DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0x3 (DITHER_EN=0 and IPEAK=3).
(uint32_t)0x00F388D3,
// Set pilot tone length to 4 us (enable phase error discard as early as possible)
HW_REG_OVERRIDE(0x6024,0x0020),
// Bluetooth 5: Default to no CTE.
HW_REG_OVERRIDE(0x5328,0x0000),
// Synth: Increase mid code calibration time to 5 us
(uint32_t)0x00058683,
// Synth: Increase mid code calibration time to 5 us
// Synth: Increase mid code calibration time to 5 us
(uint32_t)0x38183C30,
// HID: Reduce turnaround times:
(uint32_t)((TURNAROUND_TIME*4)<<16)|0x0263, // modify tx to rx turnaround time
(uint32_t)((TURNAROUND_TIME*4)<<16)|0x0283, // modify rx to tx turnaround time
// Of of override list
(uint32_t)0xFFFFFFFF
};
// CMD_RADIO_SETUP
// Radio setup for HID command
rfc_CMD_RADIO_SETUP_t RF_cmdRadioSetup =
{
.status = 0x0000,
.pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
.startTime = 0x00000000,
.startTrigger.triggerType = 0x0,
.startTrigger.bEnaCmd = 0x0,
.startTrigger.triggerNo = 0x0,
.startTrigger.pastTrig = 0x0,
.condition.rule = 0x1,
.condition.nSkip = 0x0,
.mode = 0x2, // HID mode
.loDivider = 0x00,
.config.frontEndMode = 0x0,
.config.biasMode = 0x0,
.config.analogCfgMode = 0x0,
.config.bNoFsPowerUp = 0x0,
.txPower = 0x7217,
.pRegOverride = pOverridesCommon,
};
// CMD_FS
// Frequency Synthesizer Programming Command
rfc_CMD_FS_t RF_cmdFs =
{
.commandNo = 0x0803,
.status = 0x0000,
.pNextOp = 0,
.startTime = 0x00000000,
.startTrigger.triggerType = 0x0,
.startTrigger.bEnaCmd = 0x0,
.startTrigger.triggerNo = 0x0,
.startTrigger.pastTrig = 0x1,
.condition.rule = 0x1,
.condition.nSkip = 0x0,
.frequency = 2440,
.fractFreq = 0x0000,
.synthConf.bTxMode = 0x0,
.synthConf.refFreq = 0x0,
.__dummy0 = 0x00,
.__dummy1 = 0x00,
.__dummy2 = 0x00,
.__dummy3 = 0x0000
};
// CMD_HID_TX
// HID TX command
rfc_CMD_HID_TX_t RF_cmdTxHID =
{
.status = 0x0000,
.pNextOp = 0x00000000,
.startTime = 0x00000000,
.startTrigger.triggerType = 0x0,
.startTrigger.bEnaCmd = 0x0,
.startTrigger.triggerNo = 0x0,
.startTrigger.pastTrig = 0x0,
.condition.rule = COND_NEVER,
.condition.nSkip = 0x0,
.pktConf.bFsOff = 0x0, // Keep synth on
.pktConf.bAutoRetransmit = 0x1, // Listen for ack and retransmit
.pktConf.bVarLen = 0x1, // Variable length mode
.pktConf.hdrMode = 0x0, // 9 bit mode
.pktConf.bIncludeAddr = 0x1, // Include address after sync word
.pktConf.hdrConf = 0x0, // Automatically generate header
.pktConf.bFixedTxLen = 0x0, // Calculate length when sending packet
.rxConf.bAutoFlushIgnored = 0x0, // Do not flush ignored packets
.rxConf.bAutoFlushCrcErr = 0x1, // Flush packets with CRC error
.rxConf.bIncludeAddr = 0x0, // Do not include address in queue
.rxConf.bIncludeHdr = 0x1, // Include header in queue
.rxConf.bIncludeCrc = 0x0, // Do not include CRC in queue
.rxConf.bAppendStatus = 0x0, // Do not append status byte in queue
.rxConf.bAppendTimestamp = 0x0, // Do not append time stamp of received packet in queue
.syncWord = 0x29417671,
.address = 0xEF,
.seqNo = 0x00,
.maxAckLen = 0x1E, // Maximum length of ack
.pktLen = 32, // Packet is 32 bytes
.maxRetrans = 3, // Maximum three retransmissions
.noAckMode.noAckVal = 0, // Set automatic NO_ACK value to inverse of bAutoRetransmit
.noAckMode.bAlwaysAutoRetransmit = 1, // Never disable auto retransmit
.retransDelay = 0x1E, // Number of RAT ticks from start of transmission of a packet to retransmission
.pPkt = 0,
.pRxQueue = 0,
.pOutput = 0,
};
// CMD_HID_RX
// HID RX command
rfc_CMD_HID_RX_t RF_cmdRxHID =
{
.status = 0x0000,
.pNextOp = 0x00000000,
.startTime = 0x00000000,
.startTrigger.triggerType = 0x0,
.startTrigger.bEnaCmd = 0x0,
.startTrigger.triggerNo = 0x0,
.startTrigger.pastTrig = 0x0,
.condition.rule = COND_NEVER,
.condition.nSkip = 0x0,
.pktConf.bFsOff = 0x0, // Keep synth on
.pktConf.bRepeatOk = 1, // If packet was received OK, then end
.pktConf.bRepeatNok = 1, // If packer was NOK, then go back to sync search
.pktConf.hdrMode = 0x0, // 9 bit mode
.pktConf.bIncludeAddr = 0x1, // Include address after sync word
.pktConf.hdrConf = 0x0, // Automatically generate header
.rxConf.bAutoFlushIgnored = 0x0, // Do not flush ignored packets
.rxConf.bAutoFlushCrcErr = 0x0, // Do not flush packets with CRC error
.rxConf.bIncludeAddr = 0x0, // Do not include address in queue
.rxConf.bIncludeHdr = 0x0, // Do not include header in queue
.rxConf.bIncludeCrc = 0x0, // Do not include CRC in queue
.rxConf.bAppendRssi = 0x0, // Do not append RSSI in queue
.rxConf.bAppendStatus = 0x0, // Do not append status byte in queue
.rxConf.bAppendTimestamp = 0x0, // Do not append time stamp of received packet in queue
.syncWord0 = 0x29417671,
.syncWord1 = 0x0,
.numAddr = 1, // Number of address entries in pAddrEntry
.__dummy0 = 0,
.__dummy1 = 0,
.endTrigger.triggerType = 1, // Trig never
.endTrigger.bEnaCmd = 0,
.endTrigger.triggerNo = 0,
.endTrigger.pastTrig = 0,
.endTime = 0,
.pAddrEntry = 0, //pointer to array of address entries
.pRxQueue = 0,
.pOutput = 0,
};
// Struct used for the address entry
rfc_hidAddrEntry_t addrEntry =
{
.addrConfig.ena0 = 1, // Enable entry for sync word 0
.addrConfig.ena1 = 0, // Disable entry for sync word 0
.addrConfig.autoAckMode = 2, // Always enable auto-acknowledgement for the entry
.addrConfig.bVarLen = 1, // Use variable length in receiver when receiving packets
.addrConfig.bFixedTxLen = 0, // Use actual length in header when sending ACK
.maxPktLen = 100,
.address = 0xEF, // Address of packet
.pTxQueue = 0, // Pointer to transmit queue for acknowledgements in use for the address
.crcVal = 0,
};

// Filename: rf_hid_settings.h
#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
#include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
#include DeviceFamily_constructPath(driverlib/rf_hid_cmd.h)
#include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
extern RF_Mode RF_hid;
#define BUFFER_LEN 20 // Set the appropriate length here
// RF Core API commands
extern rfc_CMD_RADIO_SETUP_t RF_cmdRadioSetup;
extern rfc_CMD_FS_t RF_cmdFs;
extern rfc_CMD_HID_TX_t RF_cmdTxHID;
extern rfc_CMD_HID_RX_t RF_cmdRxHID;
extern rfc_hidAddrEntry_t addrEntry;
// RF HID queue and statistics
extern dataQueue_t txQ;
extern dataQueue_t rxQ;
extern uint8_t txEntry1[BUFFER_LEN];
extern uint8_t rxEntry1[BUFFER_LEN];
extern uint8_t txEntry2[BUFFER_LEN];
extern uint8_t rxEntry2[BUFFER_LEN];
extern rfc_hidRxTxOutput_t rxTxStatistics;

Examples

The following code example opens the RF driver, setup the radio for CMD_HID_TX, initiates the TX/RX queues so that the packet is being transmitted as fast as possible once the CMD_HID_TX is submitted.

Using the RF CMD_HID_TX without trigger

The example below does not use the CMD_HID_TRIGGER_TX, since the queues are committed to the command before the RF_cmdTxHID is submitted. The radio will evaluate the TX queue as containing data and proceed to start the transmission. The radio will continue to send packets and receive ACK's as long as there are enough space in the queues to allow reception of ACK's, TX queue is filled and retramission count is below the threshold, and no other error has occured. The command will terminate if the RX queue ran out of free entries, or the maximum number of retransmissions (RF_cmdTxHID.maxRetrans) was done, or the CMD_STOP/CMD_ABORT command was submitted, or any error occured. If the TX queue runs out of valid entires, the radio will enter the same wait state as if command is submitted without committed TX queues.

// Initialize the radio
RF_Params rfParams;
RF_Params_init(&rfParams);
// Open the radio and submit setup command
RF_Handle rfHandle = RF_open(pObj, &RF_hid, (RF_RadioSetup *)&RF_cmdRadioSetup, NULL);
RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
// Initialize the queues
txEntry->pNextEntry = txEntry2;
txEntry->config.irqIntv = 0;
txEntry->config.lenSz = 0;
txEntry->config.type = 0;
txEntry->length = 10; // Set the appropriate length here
txEntry = (rfc_dataEntryGeneral_t *)txEntry2;
txEntry->pNextEntry = txEntry1;
txEntry->config.irqIntv = 0;
txEntry->config.lenSz = 0;
txEntry->config.type = 0;
txEntry->length = 10; // Set the appropriate length here
txQ.pCurrEntry = txEntry1;
txQ.pLastEntry = NULL;
rxEntry->pNextEntry = rxEntry2;
rxEntry->config.lenSz = 1;
rxEntry->length = BUFFER_LEN-8;
rxEntry = (rfc_dataEntryGeneral_t*)rxEntry2;
rxEntry->pNextEntry = rxEntry1;
rxEntry->config.lenSz = 1;
rxEntry->length = BUFFER_LEN-8;
rxQ.pCurrEntry = rxEntry1;
rxQ.pLastEntry = NULL;
// Commit the queues and statistics to the TX command
RF_cmdTxHID.pPkt = (uint8_t*)&txQ;
RF_cmdTxHID.pRxQueue = &rxQ;
RF_cmdTxHID.pOutput = &rxTxStatistics;
// Submit the command and handle the queue fill/empty in the hidTxCb callback
RF_runCmd(rfHandle,
(RF_Op*)&RF_cmdTxHID,
&hidTxCb,

Using the RF CMD_HID_TX with trigger

The example below is using the CMD_HID_TRIGGER_TX to trigger the transmission of the TX packet and ACK reception. The setup for the command is the same as for the example without the trigger, with the only difference being that the queues are commited to the command after it has been submitted. This is a way to enable faster TX start up, compared to regular command submission.

The example below is using the same data as the above. The transmission is then triggered 500 usec after CMD_HID_TX command submission. The delta between RF_runCmd(..., RF_cmdTxHID, ...) and TX start without trigger is greater than delta between RF_runDirectCmd(rfHandle, CMD_TRIGGER_HID_TX) and TX start, but will consume more power.

// Initialize the radio
RF_Params rfParams;
RF_Params_init(&rfParams);
// Open the radio and submit setup command
RF_Handle rfHandle = RF_open(pObj, &RF_hid, (RF_RadioSetup *)&RF_cmdRadioSetup, NULL);
RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
// Initialize the queues
txEntry->pNextEntry = txEntry2;
txEntry->config.irqIntv = 0;
txEntry->config.lenSz = 0;
txEntry->config.type = 0;
txEntry->length = 10; // Set the appropriate length here
txEntry = (rfc_dataEntryGeneral_t *)txEntry2;
txEntry->pNextEntry = txEntry1;
txEntry->config.irqIntv = 0;
txEntry->config.lenSz = 0;
txEntry->config.type = 0;
txEntry->length = 10; // Set the appropriate length here
txQ.pCurrEntry = txEntry1;
txQ.pLastEntry = NULL;
rxEntry->pNextEntry = rxEntry2;
rxEntry->config.lenSz = 1;
rxEntry->length = BUFFER_LEN-8;
rxEntry = (rfc_dataEntryGeneral_t*)rxEntry2;
rxEntry->pNextEntry = rxEntry1;
rxEntry->config.lenSz = 1;
rxEntry->length = BUFFER_LEN-8;
rxQ.pCurrEntry = rxEntry1;
rxQ.pLastEntry = NULL;
RF_cmdTxHID.pRxQueue = &rxQ;
RF_cmdTxHID.pOutput = &rxTxStatistics;
// Submit the command and handle the queue fill/empty in the hidTxCb callback
RF_CmdHandle ch = RF_postCmd(rfHandle,
(RF_Op*)&RF_cmdTxHID,
&hidTxCb,
// Wait 500 usec
usleep(500);
// Commit the queues and statistics to the TX command
RF_cmdTxHID.pPkt = (uint8_t*)&txQ;
// Submit the trigger
RF_runDirectCmd(rfHandle, CMD_TRIGGER_HID_TX);
// Pend on the command end.
RF_pendCmd(rfHandle, ch, RF_EventCmdDone);

Using the RF CMD_HID_RX command

The CMD_HID_RX is not using the trigger as done with the CMD_HID_TX, instead the reception is handled by the startTrigger.

The TX queues are used for sending the ACK's, and the TX queue to use is decided by the address entry, meaning that it's possible to have different TX queues for different received addresses, allowing for different ACK's for different addresses.

If pktConf.bIncludeAddr is zero, meaning that no address is sent, the address entry used will be the first entry that matches the received sync word with the sync word ID in the address entry.

The command will terminate if the RX queue is full, CMD_STOP/CMD_ABORT is being sent or if any error occured.

An example of the CMD_HID_RX is shown below.

// Initialize the radio
RF_Params rfParams;
RF_Params_init(&rfParams);
// Open the radio and submit setup command
RF_Handle rfHandle = RF_open(pObj, &RF_hid, (RF_RadioSetup *)&RF_cmdRadioSetup, NULL);
RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
// Initialize the queues
txEntry->pNextEntry = txEntry2;
txEntry->config.irqIntv = 0;
txEntry->config.lenSz = 0;
txEntry->config.type = 0;
txEntry->length = 10; // Set the appropriate length here
txEntry = (rfc_dataEntryGeneral_t *)txEntry2;
txEntry->pNextEntry = txEntry1;
txEntry->config.irqIntv = 0;
txEntry->config.lenSz = 0;
txEntry->config.type = 0;
txEntry->length = 10; // Set the appropriate length here
rxEntry->pNextEntry = rxEntry2;
rxEntry->config.lenSz = 1;
rxEntry->length = BUFFER_LEN-8;
rxEntry = (rfc_dataEntryGeneral_t*)rxEntry2;
rxEntry->pNextEntry = rxEntry1;
rxEntry->config.lenSz = 1;
rxEntry->length = BUFFER_LEN-8;
rxQ.pCurrEntry = rxEntry1;
rxQ.pLastEntry = NULL;
// Attach the TX queue to the address entry. Used for ACK's
addrEntry.pTxQueue = &txQ;
RF_cmdRxHID.pAddrEntry = &addrEntry;
RF_cmdRxHID.pRxQueue = &rxQ;
RF_cmdRxHID.pOutput = &rxTxStatistics;
// Submit the command and handle the queue fill/empty in the hidRxCb callback
RF_runCmd(rfHandle,
(RF_Op*)&RF_cmdRxHID,
&hidRxCb,


#include <stdint.h>
#include "rf_mailbox.h"
#include "rf_common_cmd.h"
Include dependency graph for rf_hid_cmd.h:

Go to the source code of this file.

Data Structures

struct  rfc_CMD_HID_TX_s
 HID Transmit Command with Auto Retransmission. More...
 
struct  rfc_CMD_HID_RX_s
 HID Recieve Command with Auto Ack. More...
 
struct  rfc_hidAddrEntry_s
 
struct  rfc_hidRxTxOutput_s
 
struct  rfc_hidRxStatus_s
 

Macros

#define __RFC_STRUCT
 
#define __RFC_STRUCT_ATTR
 
#define CMD_HID_TX   0x5801
 
#define CMD_HID_RX   0x5802
 

Typedefs

typedef struct rfc_CMD_HID_TX_s rfc_CMD_HID_TX_t
 
typedef struct rfc_CMD_HID_RX_s rfc_CMD_HID_RX_t
 
typedef struct rfc_hidAddrEntry_s rfc_hidAddrEntry_t
 
typedef struct rfc_hidRxTxOutput_s rfc_hidRxTxOutput_t
 
typedef struct rfc_hidRxStatus_s rfc_hidRxStatus_t
 

Macro Definition Documentation

§ __RFC_STRUCT

#define __RFC_STRUCT

§ __RFC_STRUCT_ATTR

#define __RFC_STRUCT_ATTR
© Copyright 1995-2021, Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale