knx
ETS configurable knx-stack
rf_physical_layer_cc1310.cpp
Go to the documentation of this file.
1 #ifdef DeviceFamily_CC13X0
2 
3 #include "config.h"
4 #ifdef USE_RF
5 
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 
11 #include "rf_data_link_layer.h"
12 
13 #include <ti/devices/DeviceFamily.h>
14 #include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
15 #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
16 #include <ti/drivers/rf/RF.h>
17 #include "smartrf_settings/smartrf_settings.h"
18 
19 #include "cc1310_platform.h"
20 #include "Board.h"
21 
22 #include "bits.h"
23 #include "platform.h"
24 
25 #define RX_MAX_BUFFER_LENGTH 256
26 #define RF_TERMINATION_EVENT_MASK (RF_EventLastCmdDone | RF_EventLastFGCmdDone | RF_EventCmdAborted | RF_EventCmdStopped | RF_EventCmdCancelled)
27 
28 #define DEBUG_DUMP_PACKETS
29 
30 static RF_Object rfObject;
31 static RF_Handle rfHandle;
32 static RF_CmdHandle rxCommandHandle;
33 
34 static uint8_t rxBuffer[sizeof(rfc_dataEntryPartial_t) + RX_MAX_BUFFER_LENGTH] __attribute__((aligned(4)));
35 static rfc_dataEntryPartial_t* pDataEntry = (rfc_dataEntryPartial_t*)& rxBuffer;
36 static dataQueue_t dataQueue;
37 
38 static uint8_t addrFilterTable[2] = {0x44, 0xFF}; // Do not modify the size without changing RF_cmdPropRxAdv.addrConf.addrSize!
39 
40 static rfc_propRxOutput_t rxStatistics;
41 
42 static uint8_t packetLength;
43 static uint8_t* packetDataPointer;
44 static int32_t packetStartTime = 0;
45 
46 static volatile bool rfDone = false;
47 static volatile int rfErr = 0;
48 static volatile int err;
49 
50 static void RxCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
51 {
52  /*
53  static uint32_t count = 0;
54 
55  print("count: ");println(count++);
56  print("nextIndex: ");println(pDataEntry->nextIndex);
57  //print("pktStatus.numElements: ");println(pDataEntry->pktStatus.numElements);
58  print("RF_cmdPropRxAdv.status: ");println(RF_cmdPropRxAdv.status, HEX);
59  print("pktStatus.bEntryOpen: ");println(pDataEntry->pktStatus.bEntryOpen, HEX);
60  print("RF_EventMask: ");println(e, HEX);
61  */
62 
63  if (e & RF_EventNDataWritten)
64  {
65  // Make sure sure we are at the beginning of the packet
66  if (packetStartTime == 0)
67  {
68  packetStartTime = millis();
69 
70  // pDataEntry->rxData contains the first byte of the received packet.
71  // Just get the address to get the start address of the receive buffer
72  uint8_t* pData = &pDataEntry->rxData;
73 
74  // Make sure we have a valid first block
75  if (((pData[1] != addrFilterTable[0]) || (pData[2] != addrFilterTable[1])) ||
76  (crc16Dnp(pData, 10) != ((pData[10] << 8) | pData[11])))
77  {
78  // cancel early because it does not seem to be KNX RF packet
79  RF_cancelCmd(rfHandle, rxCommandHandle, 0 /* force abort RF */);
80  return;
81  }
82 
83  // First block is valid, so the length is valid
84  uint8_t len = pDataEntry->rxData;
85  struct rfc_CMD_PROP_SET_LEN_s RF_cmdPropSetLen =
86  {
87  .commandNo = CMD_PROP_SET_LEN, // command identifier
88  .rxLen = (uint16_t)PACKET_SIZE(len) // packet length to set
89  };
90 
91  //RF_runImmediateCmd(rfHandle, (uint32_t*)&RF_cmdPropSetLen); // for length > 255
92  RF_Stat status = RF_runDirectCmd(rfHandle, (uint32_t)&RF_cmdPropSetLen);
93 
94  if (status != RF_StatCmdDoneSuccess)
95  {
96  println("RF CMD_PROP_SET_LEN failed!");
97  }
98  }
99  }
100  else if (e & RF_TERMINATION_EVENT_MASK)
101  {
102  if (e & RF_EventCmdAborted)
103  {
104  println("RX ABORT");
105  }
106 
107  rfDone = true;
108  rfErr = e & (RF_EventCmdStopped | RF_EventCmdAborted | RF_EventCmdCancelled);
109  }
110  else /* unknown reason - should not occur */
111  {
112  pDataEntry->status = DATA_ENTRY_PENDING;
113  err++;
114  }
115 }
116 
118  : RfPhysicalLayer(rfDataLinkLayer, platform)
119 {
120 }
121 
123 {
124  RF_TxPowerTable_Entry* rfPowerTable = NULL;
125  RF_TxPowerTable_Value newValue;
126  uint8_t rfPowerTableSize = 0;
127 
128  // Search the default PA power table for the desired power level
129  newValue = RF_TxPowerTable_findValue((RF_TxPowerTable_Entry*)PROP_RF_txPowerTable, dBm);
130 
131  if (newValue.rawValue != RF_TxPowerTable_INVALID_VALUE)
132  {
133  // Found a valid entry
134  rfPowerTable = (RF_TxPowerTable_Entry*)PROP_RF_txPowerTable;
135  rfPowerTableSize = PROP_RF_txPowerTableSize;
136  }
137 
138  // if max power is requested then the CCFG_FORCE_VDDR_HH must be set in
139  // the ccfg
140 #if (CCFG_FORCE_VDDR_HH != 0x1)
141 
142  if ((newValue.paType == RF_TxPowerTable_DefaultPA) &&
143  (dBm == rfPowerTable[rfPowerTableSize - 2].power))
144  {
145  // The desired power level is set to the maximum supported under the
146  // default PA settings, but the boost mode (CCFG_FORCE_VDDR_HH) is not
147  // turned on
148  return;
149  }
150 
151 #endif
152 
153  RF_Stat rfStatus = RF_setTxPower(rfHandle, newValue);
154 
155  if (rfStatus == RF_StatSuccess)
156  {
157  print("Successfully set TX output power to: ");
158  println(newValue.rawValue);
159  }
160  else
161  {
162  print("Could not set TX output power to: ");
163  println(newValue.rawValue);
164  }
165 }
166 
167 
169 {
170  RF_Params rfParams;
171  RF_Params_init(&rfParams);
172 
173  pDataEntry->length = 255;
174  pDataEntry->config.type = DATA_ENTRY_TYPE_PARTIAL; // --> DATA_ENTRY_TYPE_PARTIAL adds a 12 Byte Header
175  pDataEntry-> config.irqIntv = 12; // KNX-RF first block consists of 12 bytes (one length byte, 0x44, 0xFF, one RFinfo byte, six Serial/DoA bytes, two CRC bytes)
176  pDataEntry-> config.lenSz = 0; // no length indicator at beginning of data entry
177  pDataEntry->status = DATA_ENTRY_PENDING;
178  pDataEntry->pNextEntry = (uint8_t*)pDataEntry;
179 
180  dataQueue.pCurrEntry = (uint8_t*)pDataEntry;
181  dataQueue.pLastEntry = NULL;
182 
183  // Set buffer with address. We use the two fixed bytes 0x44 and 0xFF as our address to let the
184  // packet engine do more filtering on itself
185  RF_cmdPropRxAdv.pAddr = (uint8_t*)&addrFilterTable;
186  // Set the Data Entity queue for received data
187  RF_cmdPropRxAdv.pQueue = &dataQueue;
188  // Set the output buffer for RX packet statistics
189  RF_cmdPropRxAdv.pOutput = (uint8_t*)&rxStatistics;
190 
191  // Request access to the radio
192  rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
193 
194  /* Set the frequency */
195  RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
196  return true;
197 }
198 
200 {
201  RF_cancelCmd(rfHandle, rxCommandHandle, 0 /* do not stop gracefully, instead hard abort RF */);
202  RF_pendCmd(rfHandle, rxCommandHandle, RF_TERMINATION_EVENT_MASK);
203  RF_yield(rfHandle);
204  RF_close(rfHandle);
205 }
206 
208 {
209  switch (_loopState)
210  {
211  case TX_START:
212  {
213  uint8_t* sendBuffer {nullptr};
214  uint16_t sendBufferLength {0};
215 
216  //println("TX_START...");
217  _rfDataLinkLayer.loadNextTxFrame(&sendBuffer, &sendBufferLength);
218  uint16_t pktLen = PACKET_SIZE(sendBuffer[0]);
219 
220  if (pktLen != sendBufferLength)
221  {
222  print("Error TX: SendBuffer[0]=");
223  println(sendBuffer[0]);
224  print("Error TX: SendBufferLength=");
225  println(sendBufferLength);
226  print("Error TX: PACKET_SIZE=");
227  println(PACKET_SIZE(sendBuffer[0]));
228  }
229 
230  // Calculate total number of bytes in the KNX RF packet from L-field
231  // Check for valid length
232  if ((pktLen == 0) || (pktLen > 290))
233  {
234  println("TX packet length error!");
235  break;
236  }
237 
238  if (pktLen > 255)
239  {
240  println("Unhandled: TX packet > 255");
241  break;
242  }
243 
244  RF_cmdPropTx.pktLen = pktLen;
245  RF_cmdPropTx.pPkt = sendBuffer;
246  RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
247  RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, RF_TERMINATION_EVENT_MASK);
248  //print("TX: RF_EventMask: ");println(result, HEX);
249 
250 #if defined(DEBUG_DUMP_PACKETS)
251  printHex("TX: ", sendBuffer, pktLen);
252 #endif
253  delete sendBuffer;
254 
255  if (result != RF_EventLastCmdDone)
256  {
257  print("Unexpected result command: ");
258  println(result, HEX);
259  }
260 
261  //println("Restart RX...");
262  _loopState = RX_START;
263  }
264  break;
265 
266  case RX_START:
267  {
268  packetStartTime = 0;
269  rfDone = false;
270  rfErr = 0;
271  err = 0;
272  pDataEntry->status = DATA_ENTRY_PENDING;
273 
274  rxCommandHandle = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRxAdv, RF_PriorityNormal, &RxCallback, RF_EventNDataWritten | RF_EventRxAborted);
275 
276  if (rxCommandHandle == RF_ALLOC_ERROR)
277  {
278  println("Error: nRF_pendCmd() failed");
279  return;
280  }
281 
282  _loopState = RX_ACTIVE;
283  }
284  break;
285 
286  case RX_ACTIVE:
287  {
288  if (!_rfDataLinkLayer.isTxQueueEmpty())
289  {
290  RF_cancelCmd(rfHandle, rxCommandHandle, RF_ABORT_GRACEFULLY);
291  RF_pendCmd(rfHandle, rxCommandHandle, RF_TERMINATION_EVENT_MASK);
292 
293  if (RF_cmdPropTx.status != PROP_DONE_OK)
294  {
295  print("Unexpected RF_cmdPropTx.status after stopping RX: ");
296  println(RF_cmdPropTx.status, HEX);
297  }
298 
299  _loopState = TX_START;
300  break;
301  }
302 
303  // Check if we have an incomplete packet reception
304  if (!rfDone && ((packetStartTime > 0) && (millis() - packetStartTime > RX_PACKET_TIMEOUT)))
305  {
306  println("RX packet timeout!");
307  RF_cancelCmd(rfHandle, rxCommandHandle, RF_ABORT_GRACEFULLY);
308  RF_pendCmd(rfHandle, rxCommandHandle, RF_TERMINATION_EVENT_MASK);
309  /*
310  print("nRxOk = ");println(rxStatistics.nRxOk); // Number of packets that have been received with payload, CRC OK and not ignored
311  print("nRxNok = ");println(rxStatistics.nRxNok); // Number of packets that have been received with CRC error
312  print("nRxIgnored = ");println(rxStatistics.nRxIgnored); // Number of packets that have been received with CRC OK and ignored due to address mismatch
313  print("nRxStopped = ");println(rxStatistics.nRxStopped); // Number of packets not received due to illegal length or address mismatch with pktConf.filterOp = 1
314  print("nRxBufFull = ");println(rxStatistics.nRxBufFull); // Number of packets that have been received and discarded due to lack of buffer space
315  */
316  _loopState = RX_START;
317  break;
318  }
319  else if (rfDone)
320  {
321  RF_EventMask result = RF_pendCmd(rfHandle, rxCommandHandle, RF_TERMINATION_EVENT_MASK);
322 
323  if ((result & RF_EventCmdCancelled) || (result & RF_EventCmdStopped) || (result & RF_EventCmdAborted))
324  {
325  println("RF terminated because of RF_flushCmd() or RF_cancelCmd()");
326  }
327  else if ((result & RF_EventLastCmdDone) != RF_EventLastCmdDone)
328  {
329  print("Unexpected Rx result command: ");
330  println(result, HEX);
331  }
332  else if (rfErr)
333  {
334  println("Rx is no KNX frame");
335  }
336  else if ((result & RF_EventLastCmdDone) == RF_EventLastCmdDone)
337  {
338  // add CRC sizes for received blocks, but do not add the length of the L-field (1 byte) itself
339  packetLength = PACKET_SIZE(pDataEntry->rxData);
340  packetDataPointer = (uint8_t*) &pDataEntry->rxData;
341 
342  // Sanity check: the partial data entry index points to the next free location in the partial RX buffer
343  if (packetLength != (pDataEntry->nextIndex - 1))
344  {
345  println("Mismatch between packetLength and pDataEntry->nextIndex: ");
346  print("packetLength = ");
347  print(packetLength);
348  print(", pDataEntry->nextIndex = ");
349  println(pDataEntry->nextIndex);
350  }
351 
352  /*
353  print("nRxOk = ");println(rxStatistics.nRxOk); // Number of packets that have been received with payload, CRC OK and not ignored
354  print("nRxNok = ");println(rxStatistics.nRxNok); // Number of packets that have been received with CRC error
355  print("nRxIgnored = ");println(rxStatistics.nRxIgnored); // Number of packets that have been received with CRC OK and ignored due to address mismatch
356  print("nRxStopped = ");println(rxStatistics.nRxStopped); // Number of packets not received due to illegal length or address mismatch with pktConf.filterOp = 1
357  print("nRxBufFull = ");println(rxStatistics.nRxBufFull); // Number of packets that have been received and discarded due to lack of buffer space
358  */
359 
360 #if defined(DEBUG_DUMP_PACKETS)
361  printHex("RX: ", packetDataPointer, packetLength, false);
362  print ("- RSSI: ");
363  println(rxStatistics.lastRssi);
364 #endif
365  _rfDataLinkLayer.frameBytesReceived(packetDataPointer, packetLength);
366  }
367 
368  _loopState = RX_START;
369  }
370  }
371  break;
372  }
373 }
374 
375 #endif // USE_RF
376 
377 #endif // DeviceFamily_CC13X0
void print(const char *s)
void println(const char *s)
uint16_t crc16Dnp(uint8_t *input, uint16_t length)
Definition: bits.cpp:153
void printHex(const char *suffix, const uint8_t *data, size_t length, bool newline)
Definition: bits.cpp:12
uint32_t millis()
RfPhysicalLayerCC1310(RfDataLinkLayer &rfDataLinkLayer, Platform &platform)
RfDataLinkLayer & _rfDataLinkLayer
volatile uint8_t __attribute__((aligned(uartDmaBufferSize))) uartDmaBuffer[uartDmaBufferSize]