mirror of
https://github.com/thelsing/knx.git
synced 2025-08-22 13:46:21 +02:00
initial commit of CC1310 RF driver with first working RX version
This commit is contained in:
parent
49f8c38353
commit
9692a1a317
133
examples/knx-cc1310/RFQueue.c
Normal file
133
examples/knx-cc1310/RFQueue.c
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Filename: rf_queue.c
|
||||||
|
* Revised: $ $
|
||||||
|
* Revision: $ $
|
||||||
|
*
|
||||||
|
* Description: Help functions for handling queues
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
/* Standard C Libraries */
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Application Header files */
|
||||||
|
#include "RFQueue.h"
|
||||||
|
#include <ti/devices/DeviceFamily.h>
|
||||||
|
#include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
|
||||||
|
|
||||||
|
/* Receive entry pointer to keep track of read items */
|
||||||
|
rfc_dataEntryGeneral_t* readEntry;
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
//
|
||||||
|
//! Get the current dataEntry
|
||||||
|
//!
|
||||||
|
//! \return rfc_dataEntry*
|
||||||
|
//
|
||||||
|
//*****************************************************************************
|
||||||
|
rfc_dataEntryGeneral_t*
|
||||||
|
RFQueue_getDataEntry()
|
||||||
|
{
|
||||||
|
return (readEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
//
|
||||||
|
//! Move to next dataEntry
|
||||||
|
//!
|
||||||
|
//! \return None
|
||||||
|
//
|
||||||
|
//*****************************************************************************
|
||||||
|
uint8_t
|
||||||
|
RFQueue_nextEntry()
|
||||||
|
{
|
||||||
|
/* Set status to pending */
|
||||||
|
readEntry->status = DATA_ENTRY_PENDING;
|
||||||
|
|
||||||
|
/* Move read entry pointer to next entry */
|
||||||
|
readEntry = (rfc_dataEntryGeneral_t*)readEntry->pNextEntry;
|
||||||
|
|
||||||
|
return (readEntry->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
//
|
||||||
|
//! Define a queue
|
||||||
|
//!
|
||||||
|
//! \param dataQueue is a pointer to the queue to use
|
||||||
|
//! \param buf is the prealocated byte buffer to use
|
||||||
|
//! \param buf_len is the number of preallocated bytes
|
||||||
|
//! \param numEntries are the number of dataEntries to split the buffer into
|
||||||
|
//! \param length is the length of data in every dataEntry
|
||||||
|
//!
|
||||||
|
//! \return uint8_t
|
||||||
|
//
|
||||||
|
//*****************************************************************************
|
||||||
|
uint8_t
|
||||||
|
RFQueue_defineQueue(dataQueue_t *dataQueue, uint8_t *buf, uint16_t buf_len, uint8_t numEntries, uint16_t length)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (buf_len < (numEntries * (length + RF_QUEUE_DATA_ENTRY_HEADER_SIZE + RF_QUEUE_QUEUE_ALIGN_PADDING(length))))
|
||||||
|
{
|
||||||
|
/* queue does not fit into buffer */
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Padding needed for 4-byte alignment? */
|
||||||
|
uint8_t pad = 4-((length + RF_QUEUE_DATA_ENTRY_HEADER_SIZE)%4);
|
||||||
|
|
||||||
|
/* Set the Data Entries common configuration */
|
||||||
|
uint8_t *first_entry = buf;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < numEntries; i++)
|
||||||
|
{
|
||||||
|
buf = first_entry + i * (RF_QUEUE_DATA_ENTRY_HEADER_SIZE + length + pad);
|
||||||
|
((rfc_dataEntry_t*)buf)->status = DATA_ENTRY_PENDING; // Pending - starting state
|
||||||
|
((rfc_dataEntry_t*)buf)->config.type = DATA_ENTRY_TYPE_GEN; // General Data Entry
|
||||||
|
((rfc_dataEntry_t*)buf)->config.lenSz = 0; // No length indicator byte in data
|
||||||
|
((rfc_dataEntry_t*)buf)->length = length; // Total length of data field
|
||||||
|
|
||||||
|
((rfc_dataEntryGeneral_t*)buf)->pNextEntry = &(((rfc_dataEntryGeneral_t*)buf)->data)+length+pad;
|
||||||
|
}
|
||||||
|
/* Make circular Last.Next -> First */
|
||||||
|
((rfc_dataEntry_t*)buf)->pNextEntry = first_entry;
|
||||||
|
|
||||||
|
/* Create Data Entry Queue and configure for circular buffer Data Entries */
|
||||||
|
dataQueue->pCurrEntry = first_entry;
|
||||||
|
dataQueue->pLastEntry = NULL;
|
||||||
|
|
||||||
|
/* Set read pointer to first entry */
|
||||||
|
readEntry = (rfc_dataEntryGeneral_t*)first_entry;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
79
examples/knx-cc1310/RFQueue.h
Normal file
79
examples/knx-cc1310/RFQueue.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Filename: rf_queue.h
|
||||||
|
* Revised: $ $
|
||||||
|
* Revision: $ $
|
||||||
|
*
|
||||||
|
* Description: Help functions for handling queues
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
//
|
||||||
|
//! \addtogroup rfqueue_api
|
||||||
|
//! @{
|
||||||
|
//
|
||||||
|
//*****************************************************************************
|
||||||
|
|
||||||
|
#ifndef RF_QUEUE_H
|
||||||
|
#define RF_QUEUE_H
|
||||||
|
|
||||||
|
#include <ti/devices/DeviceFamily.h>
|
||||||
|
#include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
|
||||||
|
|
||||||
|
#define RF_QUEUE_DATA_ENTRY_HEADER_SIZE 8 // Contant header size of a Generic Data Entry
|
||||||
|
|
||||||
|
#define RF_QUEUE_QUEUE_ALIGN_PADDING(length) (4-((length + RF_QUEUE_DATA_ENTRY_HEADER_SIZE)%4)) // Padding offset
|
||||||
|
|
||||||
|
#define RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(numEntries, dataSize, appendedBytes) \
|
||||||
|
(numEntries*(RF_QUEUE_DATA_ENTRY_HEADER_SIZE + dataSize + appendedBytes + RF_QUEUE_QUEUE_ALIGN_PADDING(dataSize + appendedBytes)))
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint8_t RFQueue_nextEntry();
|
||||||
|
extern rfc_dataEntryGeneral_t* RFQueue_getDataEntry();
|
||||||
|
extern uint8_t RFQueue_defineQueue(dataQueue_t *queue ,uint8_t *buf, uint16_t buf_len, uint8_t numEntries, uint16_t length);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
//
|
||||||
|
//! Close the Doxygen group.
|
||||||
|
//! @}
|
||||||
|
//
|
||||||
|
//*****************************************************************************
|
@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
#include "knx_wrapper.h"
|
#include "knx_wrapper.h"
|
||||||
|
|
||||||
KnxFacade<CC1310Platform, Bau07B0> *pKnx = nullptr;
|
KnxFacade<CC1310Platform, Bau27B0> *pKnx = nullptr;
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
pKnx = new KnxFacade<CC1310Platform, Bau07B0>;
|
pKnx = new KnxFacade<CC1310Platform, Bau27B0>;
|
||||||
KnxFacade<CC1310Platform, Bau07B0> &knx = *pKnx;
|
KnxFacade<CC1310Platform, Bau27B0> &knx = *pKnx;
|
||||||
|
|
||||||
knx.platform().init();
|
knx.platform().init();
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ void setup()
|
|||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
KnxFacade<CC1310Platform, Bau07B0> &knx = *pKnx;
|
KnxFacade<CC1310Platform, Bau27B0> &knx = *pKnx;
|
||||||
|
|
||||||
knx.loop();
|
knx.loop();
|
||||||
}
|
}
|
||||||
|
300
examples/knx-cc1310/smartrf_settings/smartrf_settings.c
Normal file
300
examples/knx-cc1310/smartrf_settings/smartrf_settings.c
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
//*********************************************************************************
|
||||||
|
// Generated by SmartRF Studio version 2.6.0 (build #8)
|
||||||
|
// Tested for SimpleLink SDK version: CC13x0 SDK 1.30.xx.xx
|
||||||
|
// Device: CC1310 Rev. 2.1
|
||||||
|
//
|
||||||
|
//*********************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
//*********************************************************************************
|
||||||
|
// Parameter summary
|
||||||
|
// Address: off
|
||||||
|
// Address0: 0xAA
|
||||||
|
// Address1: 0xBB
|
||||||
|
// Frequency: 868.29999 MHz
|
||||||
|
// Data Format: Serial mode disable
|
||||||
|
// Deviation: 50.000 kHz
|
||||||
|
// Packet Length Config: Variable
|
||||||
|
// Max Packet Length: 128
|
||||||
|
// Packet Length: 20
|
||||||
|
// RX Filter BW: 196 kHz
|
||||||
|
// Symbol Rate: 32.76825 kBaud
|
||||||
|
// Sync Word Length: 24 Bits
|
||||||
|
// TX Power: 14 dBm (requires define CCFG_FORCE_VDDR_HH = 1 in ccfg.c, see CC13xx/CC26xx Technical Reference Manual)
|
||||||
|
// Whitening: No whitening
|
||||||
|
|
||||||
|
#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_prop_cmd.h)
|
||||||
|
#include <ti/drivers/rf/RF.h>
|
||||||
|
#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_wmbus_smode.h)
|
||||||
|
#include DeviceFamily_constructPath(rf_patches/rf_patch_mce_wmbus_smode.h)
|
||||||
|
#include DeviceFamily_constructPath(rf_patches/rf_patch_rfe_wmbus_smode.h)
|
||||||
|
#include "smartrf_settings.h"
|
||||||
|
|
||||||
|
|
||||||
|
// TI-RTOS RF Mode Object
|
||||||
|
RF_Mode RF_prop =
|
||||||
|
{
|
||||||
|
.rfMode = RF_MODE_PROPRIETARY_SUB_1,
|
||||||
|
.cpePatchFxn = &rf_patch_cpe_wmbus_smode,
|
||||||
|
.mcePatchFxn = &rf_patch_mce_wmbus_smode,
|
||||||
|
.rfePatchFxn = &rf_patch_rfe_wmbus_smode,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Overrides for CMD_PROP_RADIO_DIV_SETUP
|
||||||
|
static uint32_t pOverrides[] =
|
||||||
|
{
|
||||||
|
// PHY: Run the MCE and RFE patches
|
||||||
|
MCE_RFE_OVERRIDE(1,0,0,1,0,0),
|
||||||
|
// override_synth_prop_863_930_div5.xml
|
||||||
|
// Synth: Set recommended RTRIM to 7
|
||||||
|
HW_REG_OVERRIDE(0x4038,0x0037),
|
||||||
|
// Synth: Set Fref to 4 MHz
|
||||||
|
(uint32_t)0x000684A3,
|
||||||
|
// Synth: Configure fine calibration setting
|
||||||
|
HW_REG_OVERRIDE(0x4020,0x7F00),
|
||||||
|
// Synth: Configure fine calibration setting
|
||||||
|
HW_REG_OVERRIDE(0x4064,0x0040),
|
||||||
|
// Synth: Configure fine calibration setting
|
||||||
|
(uint32_t)0xB1070503,
|
||||||
|
// Synth: Configure fine calibration setting
|
||||||
|
(uint32_t)0x05330523,
|
||||||
|
// Synth: Set loop bandwidth after lock to 20 kHz
|
||||||
|
(uint32_t)0x0A480583,
|
||||||
|
// Synth: Set loop bandwidth after lock to 20 kHz
|
||||||
|
(uint32_t)0x7AB80603,
|
||||||
|
// Synth: Configure VCO LDO (in ADI1, set VCOLDOCFG=0x9F to use voltage input reference)
|
||||||
|
ADI_REG_OVERRIDE(1,4,0x9F),
|
||||||
|
// Synth: Configure synth LDO (in ADI1, set SLDOCTL0.COMP_CAP=1)
|
||||||
|
ADI_HALFREG_OVERRIDE(1,7,0x4,0x4),
|
||||||
|
// Synth: Use 24 MHz XOSC as synth clock, enable extra PLL filtering
|
||||||
|
(uint32_t)0x02010403,
|
||||||
|
// Synth: Configure extra PLL filtering
|
||||||
|
(uint32_t)0x00108463,
|
||||||
|
// Synth: Increase synth programming timeout (0x04B0 RAT ticks = 300 us)
|
||||||
|
(uint32_t)0x04B00243,
|
||||||
|
// override_synth_disable_bias_div5.xml
|
||||||
|
// Synth: Set divider bias to disabled
|
||||||
|
HW32_ARRAY_OVERRIDE(0x405C,1),
|
||||||
|
// Synth: Set divider bias to disabled (specific for loDivider=5)
|
||||||
|
(uint32_t)0x18000200,
|
||||||
|
// override_phy_rx_aaf_bw_0xd.xml
|
||||||
|
// Rx: Set anti-aliasing filter bandwidth to 0xD (in ADI0, set IFAMPCTL3[7:4]=0xD)
|
||||||
|
ADI_HALFREG_OVERRIDE(0,61,0xF,0xD),
|
||||||
|
// override_phy_gfsk_rx.xml
|
||||||
|
// Rx: Set LNA bias current trim offset to 3
|
||||||
|
(uint32_t)0x00038883,
|
||||||
|
// Rx: Freeze RSSI on sync found event
|
||||||
|
HW_REG_OVERRIDE(0x6084,0x35F1),
|
||||||
|
// Tx: Configure PA ramping setting (0x61). Rx: Set AGC reference level to 0x1F
|
||||||
|
HW_REG_OVERRIDE(0x6088,0x611F),
|
||||||
|
// Tx: Configure PA ramping setting and setting AGC settle wait = 21 samples
|
||||||
|
HW_REG_OVERRIDE(0x608C,0x8112),
|
||||||
|
// Rx: Set RSSI offset to adjust reported RSSI by +7 dB
|
||||||
|
(uint32_t)0x00F988A3,
|
||||||
|
// TX power override
|
||||||
|
// Tx: Set PA trim to max (in ADI0, set PACTL0=0xF8)
|
||||||
|
ADI_REG_OVERRIDE(0,12,0xF8),
|
||||||
|
// Set AGC win size = 7 samples
|
||||||
|
HW_REG_OVERRIDE(0x6064,0x1306),
|
||||||
|
(uint32_t)0xFFFFFFFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMD_PROP_RADIO_DIV_SETUP
|
||||||
|
rfc_CMD_PROP_RADIO_DIV_SETUP_t RF_cmdPropRadioDivSetup =
|
||||||
|
{
|
||||||
|
.commandNo = 0x3807,
|
||||||
|
.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,
|
||||||
|
.modulation.modType = 0x0,
|
||||||
|
.modulation.deviation = 0xC8,
|
||||||
|
.symbolRate.preScale = 0xF,
|
||||||
|
.symbolRate.rateWord = 0x53E3,
|
||||||
|
.rxBw = 0x27, // S2-mode (for S1-mode, rxBw = 0x29)
|
||||||
|
.preamConf.nPreamBytes = 0x3,
|
||||||
|
.preamConf.preamMode = 0x0,
|
||||||
|
.formatConf.nSwBits = 0x18,
|
||||||
|
.formatConf.bBitReversal = 0x0,
|
||||||
|
.formatConf.bMsbFirst = 0x1,
|
||||||
|
.formatConf.fecMode = 0x0a, // manchester coding
|
||||||
|
.formatConf.whitenMode = 0x0,
|
||||||
|
.config.frontEndMode = 0x0,
|
||||||
|
.config.biasMode = 0x1,
|
||||||
|
.config.analogCfgMode = 0x0,
|
||||||
|
.config.bNoFsPowerUp = 0x0,
|
||||||
|
.txPower = 0xA73F,
|
||||||
|
.pRegOverride = pOverrides,
|
||||||
|
.centerFreq = 0x0364,
|
||||||
|
.intFreq = 0x8000,
|
||||||
|
.loDivider = 0x05,
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMD_FS
|
||||||
|
rfc_CMD_FS_t RF_cmdFs =
|
||||||
|
{
|
||||||
|
.commandNo = 0x0803,
|
||||||
|
.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,
|
||||||
|
.frequency = 0x0364,
|
||||||
|
.fractFreq = 0x4CCD,
|
||||||
|
.synthConf.bTxMode = 0x0,
|
||||||
|
.synthConf.refFreq = 0x0,
|
||||||
|
.__dummy0 = 0x00,
|
||||||
|
.__dummy1 = 0x00,
|
||||||
|
.__dummy2 = 0x00,
|
||||||
|
.__dummy3 = 0x0000,
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMD_PROP_TX
|
||||||
|
rfc_CMD_PROP_TX_t RF_cmdPropTx =
|
||||||
|
{
|
||||||
|
.commandNo = 0x3801,
|
||||||
|
.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,
|
||||||
|
.pktConf.bFsOff = 0x0,
|
||||||
|
.pktConf.bUseCrc = 0x1,
|
||||||
|
.pktConf.bVarLen = 0x1,
|
||||||
|
.pktLen = 0x14, // SET APPLICATION PAYLOAD LENGTH
|
||||||
|
.syncWord = 0x547696,
|
||||||
|
.pPkt = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMD_PROP_RX
|
||||||
|
rfc_CMD_PROP_RX_t RF_cmdPropRx =
|
||||||
|
{
|
||||||
|
.commandNo = 0x3802,
|
||||||
|
.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,
|
||||||
|
.pktConf.bFsOff = 0x0,
|
||||||
|
.pktConf.bRepeatOk = 0x0,
|
||||||
|
.pktConf.bRepeatNok = 0x0,
|
||||||
|
.pktConf.bUseCrc = 0x1,
|
||||||
|
.pktConf.bVarLen = 0x1,
|
||||||
|
.pktConf.bChkAddress = 0x0,
|
||||||
|
.pktConf.endType = 0x0,
|
||||||
|
.pktConf.filterOp = 0x0,
|
||||||
|
.rxConf.bAutoFlushIgnored = 0x0,
|
||||||
|
.rxConf.bAutoFlushCrcErr = 0x0,
|
||||||
|
.rxConf.bIncludeHdr = 0x1,
|
||||||
|
.rxConf.bIncludeCrc = 0x0,
|
||||||
|
.rxConf.bAppendRssi = 0x0,
|
||||||
|
.rxConf.bAppendTimestamp = 0x0,
|
||||||
|
.rxConf.bAppendStatus = 0x1,
|
||||||
|
.syncWord = 0x547696,
|
||||||
|
.maxPktLen = 0x80, // MAKE SURE DATA ENTRY IS LARGE ENOUGH
|
||||||
|
.address0 = 0xAA,
|
||||||
|
.address1 = 0xBB,
|
||||||
|
.endTrigger.triggerType = 0x1,
|
||||||
|
.endTrigger.bEnaCmd = 0x0,
|
||||||
|
.endTrigger.triggerNo = 0x0,
|
||||||
|
.endTrigger.pastTrig = 0x0,
|
||||||
|
.endTime = 0x00000000,
|
||||||
|
.pQueue = 0, // INSERT APPLICABLE POINTER: (dataQueue_t*)&xxx
|
||||||
|
.pOutput = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMD_PROP_RX_ADV
|
||||||
|
rfc_CMD_PROP_RX_ADV_t RF_cmdPropRxAdv =
|
||||||
|
{
|
||||||
|
.commandNo = 0x3804,
|
||||||
|
.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,
|
||||||
|
.pktConf.bFsOff = 0x0,
|
||||||
|
.pktConf.bRepeatOk = 0x0,
|
||||||
|
.pktConf.bRepeatNok = 0x0,
|
||||||
|
.pktConf.bUseCrc = 0x0,
|
||||||
|
.pktConf.bCrcIncSw = 0x0,
|
||||||
|
.pktConf.bCrcIncHdr = 0x1,
|
||||||
|
.pktConf.endType = 0x0,
|
||||||
|
.pktConf.filterOp = 0x1,
|
||||||
|
.rxConf.bAutoFlushIgnored = 0x0,
|
||||||
|
.rxConf.bAutoFlushCrcErr = 0x0,
|
||||||
|
.rxConf.bIncludeHdr = 0x1,
|
||||||
|
.rxConf.bIncludeCrc = 0x0,
|
||||||
|
.rxConf.bAppendRssi = 0x0,
|
||||||
|
.rxConf.bAppendTimestamp = 0x0,
|
||||||
|
.rxConf.bAppendStatus = 0x0,
|
||||||
|
.syncWord0 = 0x547696,
|
||||||
|
.syncWord1 = 0,
|
||||||
|
.maxPktLen = 0,
|
||||||
|
.hdrConf.numHdrBits = 8,
|
||||||
|
.hdrConf.lenPos = 0,
|
||||||
|
.hdrConf.numLenBits = 8,
|
||||||
|
.addrConf.addrType = 0,
|
||||||
|
.addrConf.addrSize = 0,
|
||||||
|
.addrConf.addrPos = 0,
|
||||||
|
.addrConf.numAddr = 1,
|
||||||
|
.lenOffset = 0,
|
||||||
|
.endTrigger.triggerType = 0x1,
|
||||||
|
.endTrigger.bEnaCmd = 0x0,
|
||||||
|
.endTrigger.triggerNo = 0x0,
|
||||||
|
.endTrigger.pastTrig = 0x0,
|
||||||
|
.endTime = 0x00000000,
|
||||||
|
.pAddr = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
|
||||||
|
.pQueue = 0, // INSERT APPLICABLE POINTER: (dataQueue_t*)&xxx
|
||||||
|
.pOutput = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
|
||||||
|
};
|
||||||
|
|
||||||
|
// CMD_TX_TEST
|
||||||
|
rfc_CMD_TX_TEST_t RF_cmdTxTest =
|
||||||
|
{
|
||||||
|
.commandNo = 0x0808,
|
||||||
|
.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,
|
||||||
|
.config.bUseCw = 0x0,
|
||||||
|
.config.bFsOff = 0x1,
|
||||||
|
.config.whitenMode = 0x2,
|
||||||
|
.__dummy0 = 0x00,
|
||||||
|
.txWord = 0xABCD,
|
||||||
|
.__dummy1 = 0x00,
|
||||||
|
.endTrigger.triggerType = 0x1,
|
||||||
|
.endTrigger.bEnaCmd = 0x0,
|
||||||
|
.endTrigger.triggerNo = 0x0,
|
||||||
|
.endTrigger.pastTrig = 0x0,
|
||||||
|
.syncWord = 0x930B51DE,
|
||||||
|
.endTime = 0x00000000,
|
||||||
|
};
|
28
examples/knx-cc1310/smartrf_settings/smartrf_settings.h
Normal file
28
examples/knx-cc1310/smartrf_settings/smartrf_settings.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _SMARTRF_SETTINGS_H_
|
||||||
|
#define _SMARTRF_SETTINGS_H_
|
||||||
|
|
||||||
|
//*********************************************************************************
|
||||||
|
// Generated by SmartRF Studio version 2.9.0 (build #168)
|
||||||
|
// Tested for SimpleLink SDK version: CC13x0 SDK 2.10.xx.xx
|
||||||
|
// Device: CC1310 Rev. 2.1
|
||||||
|
//
|
||||||
|
//*********************************************************************************
|
||||||
|
|
||||||
|
#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_prop_cmd.h)
|
||||||
|
#include <ti/drivers/rf/RF.h>
|
||||||
|
|
||||||
|
// TI-RTOS RF Mode Object
|
||||||
|
extern RF_Mode RF_prop;
|
||||||
|
|
||||||
|
// RF Core API commands
|
||||||
|
extern rfc_CMD_PROP_RADIO_DIV_SETUP_t RF_cmdPropRadioDivSetup;
|
||||||
|
extern rfc_CMD_FS_t RF_cmdFs;
|
||||||
|
extern rfc_CMD_PROP_TX_t RF_cmdPropTx;
|
||||||
|
extern rfc_CMD_PROP_RX_t RF_cmdPropRx;
|
||||||
|
extern rfc_CMD_PROP_RX_ADV_t RF_pCmdPropRxAdv;
|
||||||
|
extern rfc_CMD_TX_TEST_t RF_cmdTxTest;
|
||||||
|
|
||||||
|
#endif // _SMARTRF_SETTINGS_H_
|
364
src/knx/rf_physical_layer_cc1310.cpp
Normal file
364
src/knx/rf_physical_layer_cc1310.cpp
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright(c) 2020 - Matthias Meier */
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#ifdef USE_RF
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "rf_physical_layer.h"
|
||||||
|
#include "rf_data_link_layer.h"
|
||||||
|
|
||||||
|
#include "smartrf_settings/smartrf_settings.h"
|
||||||
|
#include <ti/drivers/rf/RF.h>
|
||||||
|
#include "RFQueue.h"
|
||||||
|
|
||||||
|
#include "cc1310_platform.h"
|
||||||
|
#include "Board.h"
|
||||||
|
|
||||||
|
#include "bits.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
static RF_Object rfObject;
|
||||||
|
RF_Handle rfHandle;
|
||||||
|
RF_CmdHandle rxCommandHandle;
|
||||||
|
uint8_t lastRssi;
|
||||||
|
|
||||||
|
#define DATA_ENTRY_HEADER_SIZE 12 /* Constant header size of a Generic Data Entry - 12 for DATA_ENTRY_TYPE_PARTIAL, 8 for DATA_ENTRY_TYPE_GEN */
|
||||||
|
#define MAX_LENGTH 255
|
||||||
|
#define LENGTH_POSITION 0
|
||||||
|
#define APPENDED_BYTES 10
|
||||||
|
|
||||||
|
static uint8_t rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + MAX_LENGTH + LENGTH_POSITION + APPENDED_BYTES] __attribute__((aligned(4)));
|
||||||
|
rfc_dataEntryPartial_t* partialReadEntry = (rfc_dataEntryPartial_t*)&rxDataEntryBuffer;
|
||||||
|
|
||||||
|
static dataQueue_t dataQueue;
|
||||||
|
static rfc_dataEntryGeneral_t* currentDataEntry;
|
||||||
|
static uint8_t packetLength;
|
||||||
|
static uint8_t* packetDataPointer;
|
||||||
|
|
||||||
|
volatile static int frags;
|
||||||
|
volatile static int rf_done, rf_err, err;
|
||||||
|
int8_t len1, len2;
|
||||||
|
|
||||||
|
rfc_propRxOutput_t rxStatistics;
|
||||||
|
static volatile uint8_t lengthWritten = false;
|
||||||
|
static volatile uint8_t rxDone = false;
|
||||||
|
int32_t packetStartTime;
|
||||||
|
|
||||||
|
#define PACKET_SIZE(lField) ((((lField - 10 /*size of first pkt*/))/16 + 2 /*CRC in first pkt */) * 2 /*to bytes*/ +lField + 1 /*size of len byte*/)
|
||||||
|
|
||||||
|
void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
|
||||||
|
{
|
||||||
|
frags++;
|
||||||
|
if (e & RF_EventNDataWritten && frags==1)
|
||||||
|
{
|
||||||
|
//uint16_t block1Crc = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + 10] << 8 | rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + 11];
|
||||||
|
if ((rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + 1] != 0x44) || (rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + 2] != 0xFF) /*|| (crc16(&rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE], 0, 10) != block1Crc)*/) {
|
||||||
|
// cancel because not a KNX package ID
|
||||||
|
RF_cancelCmd(rfHandle, rxCommandHandle, 0 /*stop gracefully*/);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t len = rxDataEntryBuffer[DATA_ENTRY_HEADER_SIZE + 0];
|
||||||
|
struct rfc_CMD_PROP_SET_LEN_s RF_cmdPropSetLen =
|
||||||
|
{
|
||||||
|
.commandNo = CMD_PROP_SET_LEN, // command identifier
|
||||||
|
.rxLen = (uint16_t)PACKET_SIZE(len)
|
||||||
|
};
|
||||||
|
|
||||||
|
len1=len; len2 = RF_cmdPropSetLen.rxLen;
|
||||||
|
//RF_cmdPropSetLen.rxLen = 40;
|
||||||
|
RF_runDirectCmd(rfHandle, (uint32_t)&RF_cmdPropSetLen);
|
||||||
|
packetStartTime = millis();
|
||||||
|
}
|
||||||
|
else if (e & (RF_EventLastCmdDone | RF_EventCmdStopped | RF_EventCmdAborted | RF_EventCmdCancelled)) {
|
||||||
|
rf_done = true;
|
||||||
|
rf_err = e & (RF_EventCmdStopped | RF_EventCmdAborted | RF_EventCmdCancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
else /* unknown reason - should not occure */
|
||||||
|
{
|
||||||
|
partialReadEntry->status = DATA_ENTRY_PENDING;
|
||||||
|
err++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RfPhysicalLayer::RfPhysicalLayer(RfDataLinkLayer& rfDataLinkLayer, Platform& platform)
|
||||||
|
: _rfDataLinkLayer(rfDataLinkLayer),
|
||||||
|
_platform(platform)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RfPhysicalLayer::setOutputPowerLevel(int8_t dBm)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* TODO: Complete if needed
|
||||||
|
* Refs:
|
||||||
|
* https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/540423?How-to-dynamically-change-tx-power-from-10dBm-to-14dBm-when-running-CC1310-application-
|
||||||
|
* https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz/f/156/t/561302?Increase-TX-power-of-cc1310-stepwise
|
||||||
|
* Power Table from Conticki:
|
||||||
|
const prop_mode_tx_power_config_t prop_mode_tx_power_779_930[] = {
|
||||||
|
{ 14, 0xa73f }, // needs CCFG_FORCE_VDDR_HH=1
|
||||||
|
{ 13, 0xa63f }, // 12.5dB
|
||||||
|
{ 12, 0xb818 },
|
||||||
|
{ 11, 0x50da },
|
||||||
|
{ 10, 0x38d3 },
|
||||||
|
{ 9, 0x2ccd },
|
||||||
|
{ 8, 0x24cb },
|
||||||
|
{ 7, 0x20c9 },
|
||||||
|
{ 6, 0x1cc7 },
|
||||||
|
{ 5, 0x18c6 },
|
||||||
|
{ 4, 0x18c5 },
|
||||||
|
{ 3, 0x14c4 },
|
||||||
|
{ 2, 0x1042 },
|
||||||
|
{ 1, 0x10c3 },
|
||||||
|
{ 0, 0x0041 },
|
||||||
|
{ -10, 0x08c0 },
|
||||||
|
{-128, 0xFFFF },
|
||||||
|
};
|
||||||
|
* code to change power to eg. 14dBm :
|
||||||
|
* RF_yield(rfHandle);
|
||||||
|
* RF_cmdPropRadioDivSetup.txPower = 0xA73F;
|
||||||
|
* RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RfPhysicalLayer::InitChip()
|
||||||
|
{
|
||||||
|
RF_Params rfParams;
|
||||||
|
RF_Params_init(&rfParams);
|
||||||
|
|
||||||
|
if( RFQueue_defineQueue(&dataQueue,
|
||||||
|
rxDataEntryBuffer,
|
||||||
|
sizeof(rxDataEntryBuffer),
|
||||||
|
1,
|
||||||
|
MAX_LENGTH + APPENDED_BYTES))
|
||||||
|
{
|
||||||
|
println("Failed to allocate space for all data entries");
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
partialReadEntry->length = 255;
|
||||||
|
partialReadEntry->config.type = DATA_ENTRY_TYPE_PARTIAL; // --> DATA_ENTRY_TYPE_PARTIAL adds a 12 Byte Header
|
||||||
|
partialReadEntry-> config.irqIntv = 12;
|
||||||
|
partialReadEntry-> config.lenSz = 0; // len field not handeld by rf core because it does not include CRC bytes
|
||||||
|
partialReadEntry->status = DATA_ENTRY_PENDING;
|
||||||
|
partialReadEntry->pNextEntry = (uint8_t*)partialReadEntry;
|
||||||
|
|
||||||
|
dataQueue.pCurrEntry = (uint8_t*)partialReadEntry;
|
||||||
|
dataQueue.pLastEntry = NULL;
|
||||||
|
|
||||||
|
/* 4.1. Modify CMD_PROP_RX command for application needs */
|
||||||
|
RF_cmdPropRx.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
|
||||||
|
RF_cmdPropRx.maxPktLen = 0; /* Unlimited length */
|
||||||
|
RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 0x0; /* Auto-flush packets with invalid CRC */
|
||||||
|
RF_cmdPropRx.pktConf.bRepeatNok = 0x0; /* Exit RX after a packet is recived */
|
||||||
|
RF_cmdPropRx.pktConf.bRepeatOk = 0x0; /* Exit RX after a packet is recived */
|
||||||
|
RF_cmdPropRx.pOutput = (uint8_t*)&rxStatistics;
|
||||||
|
|
||||||
|
/* Request access to the radio */
|
||||||
|
rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
|
||||||
|
|
||||||
|
/* Set the frequency */
|
||||||
|
RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RfPhysicalLayer::stopChip()
|
||||||
|
{
|
||||||
|
RF_cancelCmd(rfHandle, rxCommandHandle, 0 /*stop RF abort */);
|
||||||
|
RF_pendCmd(rfHandle, rxCommandHandle, 0);
|
||||||
|
RF_yield(rfHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t RfPhysicalLayer::packetSize (uint8_t lField)
|
||||||
|
{
|
||||||
|
uint16_t nrBytes;
|
||||||
|
uint8_t nrBlocks;
|
||||||
|
|
||||||
|
// The 2 first blocks contains 25 bytes when excluding CRC and the L-field
|
||||||
|
// The other blocks contains 16 bytes when excluding the CRC-fields
|
||||||
|
// Less than 26 (15 + 10)
|
||||||
|
if ( lField < 26 )
|
||||||
|
nrBlocks = 2;
|
||||||
|
else
|
||||||
|
nrBlocks = (((lField - 26) / 16) + 3);
|
||||||
|
|
||||||
|
// Add all extra fields, excluding the CRC fields
|
||||||
|
nrBytes = lField + 1;
|
||||||
|
|
||||||
|
// Add the CRC fields, each block has 2 CRC bytes
|
||||||
|
nrBytes += (2 * nrBlocks);
|
||||||
|
return nrBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RfPhysicalLayer::loop()
|
||||||
|
{
|
||||||
|
static uint8_t lastRxOk;
|
||||||
|
|
||||||
|
switch (_loopState)
|
||||||
|
{
|
||||||
|
case TX_START:
|
||||||
|
{
|
||||||
|
println("TX_START...");
|
||||||
|
_rfDataLinkLayer.loadNextTxFrame(&sendBuffer, &sendBufferLength);
|
||||||
|
pktLen = PACKET_SIZE(sendBuffer[0]);
|
||||||
|
//pktLen = packetSize(sendBuffer[0]);
|
||||||
|
if (PACKET_SIZE(sendBuffer[0]) != packetSize(sendBuffer[0]) || PACKET_SIZE(sendBuffer[0]) != sendBufferLength)
|
||||||
|
{
|
||||||
|
printf("Error: SendBuffer[0]=%d, SendBufferLength=%d PACKET_SIZE=%d, packetSize=%d\n", sendBuffer[0], sendBufferLength, PACKET_SIZE(sendBuffer[0]), packetSize(sendBuffer[0]));
|
||||||
|
}
|
||||||
|
// Calculate total number of bytes in the KNX RF packet from L-field
|
||||||
|
// Check for valid length
|
||||||
|
if ((pktLen == 0) || (pktLen > 290))
|
||||||
|
{
|
||||||
|
println("TX packet length error!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pktLen > 255)
|
||||||
|
{
|
||||||
|
println("Unhandled: TX packet > 255");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RF_cmdPropTx.pktLen = pktLen;
|
||||||
|
RF_cmdPropTx.pPkt = sendBuffer;
|
||||||
|
RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
|
||||||
|
RF_EventMask res = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
|
||||||
|
|
||||||
|
delete sendBuffer;
|
||||||
|
|
||||||
|
if (res != RF_EventLastCmdDone)
|
||||||
|
{
|
||||||
|
printf("Unexpected result command %llu\n", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
_loopState = RX_START;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RX_START:
|
||||||
|
{
|
||||||
|
//print("RX_START...\n");
|
||||||
|
frags = 0;
|
||||||
|
rf_done = rf_err = false;
|
||||||
|
err = 0;
|
||||||
|
lastRxOk = rxStatistics.nRxOk;
|
||||||
|
//RF_EventMask res = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_N_DATA_WRITTEN);
|
||||||
|
|
||||||
|
rxCommandHandle = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_N_DATA_WRITTEN);
|
||||||
|
if (rxCommandHandle == RF_ALLOC_ERROR)
|
||||||
|
{
|
||||||
|
println("Error: nRF_pendCmd() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_loopState = RX_ACTIVE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RX_ACTIVE:
|
||||||
|
{
|
||||||
|
if (!_rfDataLinkLayer.isTxQueueEmpty() && !syncStart)
|
||||||
|
{
|
||||||
|
RF_cancelCmd(rfHandle, rxCommandHandle, 1 /*stop gracefully*/);
|
||||||
|
RF_pendCmd(rfHandle, rxCommandHandle, 0);
|
||||||
|
RFQueue_nextEntry();
|
||||||
|
_loopState = TX_START;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we have an incomplete packet reception
|
||||||
|
if (!rf_done && syncStart && (millis() - packetStartTime > RX_PACKET_TIMEOUT))
|
||||||
|
{
|
||||||
|
println("RX packet timeout!");
|
||||||
|
RF_cancelCmd(rfHandle, rxCommandHandle, 1 /*stop gracefully*/);
|
||||||
|
RF_pendCmd(rfHandle, rxCommandHandle, 0);
|
||||||
|
RFQueue_nextEntry();
|
||||||
|
_loopState = RX_START;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (rf_done)
|
||||||
|
{
|
||||||
|
RF_EventMask res = RF_pendCmd(rfHandle, rxCommandHandle, 0);
|
||||||
|
/*
|
||||||
|
if (rxStatistics.nRxOk == lastRxOk)
|
||||||
|
{
|
||||||
|
println("Rx empty or invalid");
|
||||||
|
}
|
||||||
|
else if ( rxStatistics.lastRssi < -120)
|
||||||
|
{
|
||||||
|
println("\nIgnoring Rx with rssi < -120dB");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (res == RF_EventCmdCancelled || res == RF_EventCmdStopped || res == RF_EventCmdAborted)
|
||||||
|
{
|
||||||
|
println("RF terminated because of RF_flushCmd() or RF_cancelCmd()");
|
||||||
|
}
|
||||||
|
else if (res != RF_EventLastCmdDone)
|
||||||
|
{
|
||||||
|
printf("Unexpected Rx result command %llu\n", res);
|
||||||
|
}
|
||||||
|
else if (rf_err)
|
||||||
|
{
|
||||||
|
print("Rx is no KNX frame\n\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("len1=%d, len1=%d, frags=%d, err=%d\n", len1, len2, frags, err);
|
||||||
|
printf("nRxOk = %d ", rxStatistics.nRxOk); //!< Number of packets that have been received with payload, CRC OK and not ignored
|
||||||
|
printf("nRxNok = %d ", rxStatistics.nRxNok); //!< Number of packets that have been received with CRC error
|
||||||
|
printf("nRxIgnored = %d ", rxStatistics.nRxIgnored); //!< Number of packets that have been received with CRC OK and ignored due to address mismatch
|
||||||
|
printf("nRxStopped = %d ", rxStatistics.nRxStopped); //!< Number of packets not received due to illegal length or address mismatch with pktConf.filterOp = 1
|
||||||
|
printf("nRxBufFull = %d ", rxStatistics.nRxBufFull); //!< Number of packets that have been received and discarded due to lack of buffer space
|
||||||
|
printf("lastRssi = %d\n", rxStatistics.lastRssi); //!< RSSI of last received packet
|
||||||
|
|
||||||
|
currentDataEntry = RFQueue_getDataEntry();
|
||||||
|
/* Handle the packet data, located at ¤tDataEntry->data:
|
||||||
|
* For unknown reason, there is a header of 4 bytes whereas nr bytes rececived +1 is at offset [2]*/
|
||||||
|
packetLength = *(uint8_t *)(&(currentDataEntry->data)+4);
|
||||||
|
|
||||||
|
if (PACKET_SIZE(packetLength) != PACKET_SIZE(packetLength))
|
||||||
|
printf("Error RX: packetLength=%d PACKET_SIZE=%d, packetSize=%d\n", packetLength, PACKET_SIZE(packetLength), packetSize(packetLength));
|
||||||
|
|
||||||
|
packetLength = PACKET_SIZE(packetLength); // add CRC size
|
||||||
|
packetDataPointer = (uint8_t *)(&(currentDataEntry->data)+4);
|
||||||
|
|
||||||
|
if (packetLength+1 != *(uint8_t *)(&(currentDataEntry->data)+2)) {
|
||||||
|
printf("Size mismatch: %d %d\n", packetLength, *(uint8_t *)(&(currentDataEntry->data)+2));
|
||||||
|
printf("Data Start: 0x%x 0x%x 0x%x\n", packetDataPointer[0], packetDataPointer[1], packetDataPointer[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRssi = rxStatistics.lastRssi; // TODO: save rssi only if frame was addressed to this node
|
||||||
|
printHex("RX: ", packetDataPointer, packetLength);
|
||||||
|
_rfDataLinkLayer.frameBytesReceived(packetDataPointer, packetLength);
|
||||||
|
RFQueue_nextEntry();
|
||||||
|
}
|
||||||
|
_loopState = RX_START;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user