Contiki 3.x
ieee-mode.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /*---------------------------------------------------------------------------*/
31 /**
32  * \addtogroup rf-core
33  * @{
34  *
35  * \defgroup rf-core-ieee CC13xx/CC26xx IEEE mode driver
36  *
37  * @{
38  *
39  * \file
40  * Implementation of the CC13xx/CC26xx IEEE mode NETSTACK_RADIO driver
41  */
42 /*---------------------------------------------------------------------------*/
43 #include "contiki.h"
44 #include "dev/radio.h"
45 #include "dev/cc26xx-uart.h"
46 #include "dev/oscillators.h"
47 #include "net/packetbuf.h"
48 #include "net/rime/rimestats.h"
49 #include "net/linkaddr.h"
50 #include "net/netstack.h"
51 #include "sys/energest.h"
52 #include "sys/clock.h"
53 #include "sys/rtimer.h"
54 #include "sys/cc.h"
55 #include "lpm.h"
56 #include "ti-lib.h"
57 #include "rf-core/rf-core.h"
58 #include "rf-core/rf-ble.h"
59 /*---------------------------------------------------------------------------*/
60 /* RF core and RF HAL API */
61 #include "hw_rfc_dbell.h"
62 #include "hw_rfc_pwr.h"
63 /*---------------------------------------------------------------------------*/
64 /* RF Core Mailbox API */
65 #include "rf-core/api/mailbox.h"
66 #include "rf-core/api/common_cmd.h"
67 #include "rf-core/api/ieee_cmd.h"
68 #include "rf-core/api/data_entry.h"
69 #include "rf-core/api/ieee_mailbox.h"
70 /*---------------------------------------------------------------------------*/
71 #include "smartrf-settings.h"
72 /*---------------------------------------------------------------------------*/
73 #include <stdint.h>
74 #include <string.h>
75 #include <stdio.h>
76 #include <stdbool.h>
77 /*---------------------------------------------------------------------------*/
78 #define DEBUG 0
79 #if DEBUG
80 #define PRINTF(...) printf(__VA_ARGS__)
81 #else
82 #define PRINTF(...)
83 #endif
84 
85 /* Configuration to enable/disable auto ACKs in IEEE mode */
86 #ifdef IEEE_MODE_CONF_AUTOACK
87 #define IEEE_MODE_AUTOACK IEEE_MODE_CONF_AUTOACK
88 #else
89 #define IEEE_MODE_AUTOACK 1
90 #endif /* IEEE_MODE_CONF_AUTOACK */
91 
92 /* Configuration to enable/disable frame filtering in IEEE mode */
93 #ifdef IEEE_MODE_CONF_PROMISCOUS
94 #define IEEE_MODE_PROMISCOUS IEEE_MODE_CONF_PROMISCOUS
95 #else
96 #define IEEE_MODE_PROMISCOUS 0
97 #endif /* IEEE_MODE_CONF_PROMISCOUS */
98 
99 #ifdef IEEE_MODE_CONF_RSSI_THRESHOLD
100 #define IEEE_MODE_RSSI_THRESHOLD IEEE_MODE_CONF_RSSI_THRESHOLD
101 #else
102 #define IEEE_MODE_RSSI_THRESHOLD 0xA6
103 #endif /* IEEE_MODE_CONF_RSSI_THRESHOLD */
104 /*---------------------------------------------------------------------------*/
105 /* Data entry status field constants */
106 #define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */
107 #define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */
108 #define DATA_ENTRY_STATUS_BUSY 0x02 /* Ongoing r/w */
109 #define DATA_ENTRY_STATUS_FINISHED 0x03 /* Free to use and to free */
110 #define DATA_ENTRY_STATUS_UNFINISHED 0x04 /* Partial RX entry */
111 /*---------------------------------------------------------------------------*/
112 /* RF stats data structure */
113 static uint8_t rf_stats[16] = { 0 };
114 /*---------------------------------------------------------------------------*/
115 /* The size of the RF commands buffer */
116 #define RF_CMD_BUFFER_SIZE 128
117 /*---------------------------------------------------------------------------*/
118 /**
119  * \brief Returns the current status of a running Radio Op command
120  * \param a A pointer with the buffer used to initiate the command
121  * \return The value of the Radio Op buffer's status field
122  *
123  * This macro can be used to e.g. return the status of a previously
124  * initiated background operation, or of an immediate command
125  */
126 #define RF_RADIO_OP_GET_STATUS(a) (((rfc_radioOp_t *)a)->status)
127 /*---------------------------------------------------------------------------*/
128 /* Special value returned by CMD_IEEE_CCA_REQ when an RSSI is not available */
129 #define RF_CMD_CCA_REQ_RSSI_UNKNOWN -128
130 
131 /* Used for the return value of channel_clear */
132 #define RF_CCA_CLEAR 1
133 #define RF_CCA_BUSY 0
134 
135 /* Used as an error return value for get_cca_info */
136 #define RF_GET_CCA_INFO_ERROR 0xFF
137 
138 /*
139  * Values of the individual bits of the ccaInfo field in CMD_IEEE_CCA_REQ's
140  * status struct
141  */
142 #define RF_CMD_CCA_REQ_CCA_STATE_IDLE 0 /* 00 */
143 #define RF_CMD_CCA_REQ_CCA_STATE_BUSY 1 /* 01 */
144 #define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 /* 10 */
145 /*---------------------------------------------------------------------------*/
146 #define IEEE_MODE_CHANNEL_MIN 11
147 #define IEEE_MODE_CHANNEL_MAX 26
148 /*---------------------------------------------------------------------------*/
149 /* How long to wait for an ongoing ACK TX to finish before starting frame TX */
150 #define TX_WAIT_TIMEOUT (RTIMER_SECOND >> 11)
151 
152 /* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */
153 #define ENTER_RX_WAIT_TIMEOUT (RTIMER_SECOND >> 10)
154 /*---------------------------------------------------------------------------*/
155 /* TX Power dBm lookup table - values from SmartRF Studio */
156 typedef struct output_config {
157  radio_value_t dbm;
158  uint8_t register_ib;
159  uint8_t register_gc;
160  uint8_t temp_coeff;
161 } output_config_t;
162 
163 static const output_config_t output_power[] = {
164  { 5, 0x30, 0x00, 0x93 },
165  { 4, 0x24, 0x00, 0x93 },
166  { 3, 0x1c, 0x00, 0x5a },
167  { 2, 0x18, 0x00, 0x4e },
168  { 1, 0x14, 0x00, 0x42 },
169  { 0, 0x21, 0x01, 0x31 },
170  { -3, 0x18, 0x01, 0x25 },
171  { -6, 0x11, 0x01, 0x1d },
172  { -9, 0x0e, 0x01, 0x19 },
173  {-12, 0x0b, 0x01, 0x14 },
174  {-15, 0x0b, 0x03, 0x0c },
175  {-18, 0x09, 0x03, 0x0c },
176  {-21, 0x07, 0x03, 0x0c },
177 };
178 
179 #define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t))
180 
181 /* Max and Min Output Power in dBm */
182 #define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].dbm)
183 #define OUTPUT_POWER_MAX (output_power[0].dbm)
184 #define OUTPUT_POWER_UNKNOWN 0xFFFF
185 
186 /* Default TX Power - position in output_power[] */
187 const output_config_t *tx_power_current = &output_power[0];
188 /*---------------------------------------------------------------------------*/
189 /*
190  * Buffers used to send commands to the RF core (generic and IEEE commands).
191  * Some of those buffers are re-usable, some are not.
192  *
193  * If you are uncertain, declare a new buffer.
194  */
195 /*
196  * A buffer to send a CMD_IEEE_RX and to subsequently monitor its status
197  * Do not use this buffer for any commands other than CMD_IEEE_RX
198  */
199 static uint8_t cmd_ieee_rx_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN(4);
200 /*---------------------------------------------------------------------------*/
201 #define DATA_ENTRY_LENSZ_NONE 0
202 #define DATA_ENTRY_LENSZ_BYTE 1
203 #define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
204 
205 #define RX_BUF_SIZE 140
206 /* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */
207 static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN(4);
208 static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4);
209 static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN(4);
210 static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN(4);
211 
212 /* The RX Data Queue */
213 static dataQueue_t rx_data_queue = { 0 };
214 
215 /* Receive entry pointer to keep track of read items */
216 volatile static uint8_t *rx_read_entry;
217 /*---------------------------------------------------------------------------*/
218 /* The outgoing frame buffer */
219 #define TX_BUF_PAYLOAD_LEN 180
220 #define TX_BUF_HDR_LEN 2
221 
222 static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4);
223 /*---------------------------------------------------------------------------*/
224 /* Overrides for IEEE 802.15.4, differential mode */
225 static uint32_t ieee_overrides[] = {
226  0x00354038, /* Synth: Set RTRIM (POTAILRESTRIM) to 5 */
227  0x4001402D, /* Synth: Correct CKVD latency setting (address) */
228  0x00608402, /* Synth: Correct CKVD latency setting (value) */
229 // 0x4001405D, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (address) */
230 // 0x1801F800, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (value) */
231  0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */
232  0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */
233  0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */
234  0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */
235  0x002B50DC, /* Adjust AGC DC filter */
236  0x05000243, /* Increase synth programming timeout */
237  0x002082C3, /* Increase synth programming timeout */
238  0xFFFFFFFF, /* End of override list */
239 };
240 /*---------------------------------------------------------------------------*/
241 static int on(void);
242 static int off(void);
243 /*---------------------------------------------------------------------------*/
244 /**
245  * \brief Checks whether the RFC domain is accessible and the RFC is in IEEE RX
246  * \return 1: RFC in RX mode (and therefore accessible too). 0 otherwise
247  */
248 static uint8_t
249 rf_is_on(void)
250 {
251  if(!rf_core_is_accessible()) {
252  return 0;
253  }
254 
255  return RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_CORE_RADIO_OP_STATUS_ACTIVE;
256 }
257 /*---------------------------------------------------------------------------*/
258 /**
259  * \brief Check the RF's TX status
260  * \return 1 RF is transmitting
261  * \return 0 RF is not transmitting
262  *
263  * TX mode may be triggered either by a CMD_IEEE_TX or by the automatic
264  * transmission of an ACK frame.
265  */
266 static uint8_t
268 {
269  uint32_t cmd_status;
270  rfc_CMD_IEEE_CCA_REQ_t cmd;
271 
272  /* If we are off, we are not in TX */
273  if(!rf_core_is_accessible()) {
274  return 0;
275  }
276 
277  memset(&cmd, 0x00, sizeof(cmd));
278 
279  cmd.commandNo = CMD_IEEE_CCA_REQ;
280 
281  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
282  PRINTF("transmitting: CMDSTA=0x%08lx\n", cmd_status);
283  return 0;
284  }
285 
286  if((cmd.currentRssi == RF_CMD_CCA_REQ_RSSI_UNKNOWN) &&
287  (cmd.ccaInfo.ccaEnergy == RF_CMD_CCA_REQ_CCA_STATE_BUSY)) {
288  return 1;
289  }
290 
291  return 0;
292 }
293 /*---------------------------------------------------------------------------*/
294 /**
295  * \brief Returns CCA information
296  * \return RF_GET_CCA_INFO_ERROR if the RF was not on
297  * \return On success, the return value is formatted as per the ccaInfo field
298  * of CMD_IEEE_CCA_REQ
299  *
300  * It is the caller's responsibility to make sure the RF is on. This function
301  * will return RF_GET_CCA_INFO_ERROR if the RF is off
302  *
303  * This function will in fact wait for a valid RSSI signal
304  */
305 static uint8_t
307 {
308  uint32_t cmd_status;
309  int8_t rssi;
310  rfc_CMD_IEEE_CCA_REQ_t cmd;
311 
312  if(!rf_is_on()) {
313  PRINTF("get_cca_info: Not on\n");
314  return RF_GET_CCA_INFO_ERROR;
315  }
316 
317  rssi = RF_CMD_CCA_REQ_RSSI_UNKNOWN;
318 
319  while(rssi == RF_CMD_CCA_REQ_RSSI_UNKNOWN || rssi == 0) {
320  memset(&cmd, 0x00, sizeof(cmd));
321  cmd.commandNo = CMD_IEEE_CCA_REQ;
322 
323  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
324  PRINTF("get_cca_info: CMDSTA=0x%08lx\n", cmd_status);
325 
326  return RF_GET_CCA_INFO_ERROR;
327  }
328 
329  rssi = cmd.currentRssi;
330  }
331 
332  /* We have a valid RSSI signal. Return the CCA Info */
333  return *((uint8_t *)&cmd.ccaInfo);
334 }
335 /*---------------------------------------------------------------------------*/
336 /**
337  * \brief Reads the current signal strength (RSSI)
338  * \return The current RSSI in dBm or CMD_GET_RSSI_UNKNOWN
339  *
340  * This function reads the current RSSI on the currently configured
341  * channel.
342  */
343 static radio_value_t
344 get_rssi(void)
345 {
346  uint32_t cmd_status;
347  int8_t rssi;
348  uint8_t was_off = 0;
349  rfc_CMD_GET_RSSI_t cmd;
350 
351  /* If we are off, turn on first */
352  if(!rf_is_on()) {
353  was_off = 1;
354  if(on() != RF_CORE_CMD_OK) {
355  PRINTF("get_rssi: on() failed\n");
356  return RF_CMD_CCA_REQ_RSSI_UNKNOWN;
357  }
358  }
359 
360  memset(&cmd, 0x00, sizeof(cmd));
361  cmd.commandNo = CMD_GET_RSSI;
362 
363  rssi = RF_CMD_CCA_REQ_RSSI_UNKNOWN;
364 
365  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_OK) {
366  /* Current RSSI in bits 23:16 of cmd_status */
367  rssi = (cmd_status >> 16) & 0xFF;
368  }
369 
370  /* If we were off, turn back off */
371  if(was_off) {
372  off();
373  }
374 
375  return rssi;
376 }
377 /*---------------------------------------------------------------------------*/
378 /* Returns the current TX power in dBm */
379 static radio_value_t
380 get_tx_power(void)
381 {
382  return tx_power_current->dbm;
383 }
384 /*---------------------------------------------------------------------------*/
385 /*
386  * Set TX power to 'at least' power dBm
387  * This works with a lookup table. If the value of 'power' does not exist in
388  * the lookup table, TXPOWER will be set to the immediately higher available
389  * value
390  */
391 static void
392 set_tx_power(radio_value_t power)
393 {
394  uint32_t cmd_status;
395  int i;
396  rfc_CMD_SET_TX_POWER_t cmd;
397 
398  /* First, find the correct setting and save it */
399  for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) {
400  if(power <= output_power[i].dbm) {
401  tx_power_current = &output_power[i];
402  break;
403  }
404  }
405 
406  /*
407  * If the core is not accessible, the new setting will be applied next
408  * time we send CMD_RADIO_SETUP, so we don't need to do anything further.
409  * If the core is accessible, we can apply the new setting immediately with
410  * CMD_SET_TX_POWER
411  */
412  if(rf_core_is_accessible() == RF_CORE_NOT_ACCESSIBLE) {
413  return;
414  }
415 
416  memset(&cmd, 0x00, sizeof(cmd));
417  cmd.commandNo = CMD_SET_TX_POWER;
418  cmd.txPower.IB = output_power[i].register_ib;
419  cmd.txPower.GC = output_power[i].register_gc;
420  cmd.txPower.tempCoeff = output_power[i].temp_coeff;
421 
422  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
423  PRINTF("set_tx_power: CMDSTA=0x%08lx\n", cmd_status);
424  }
425 }
426 /*---------------------------------------------------------------------------*/
427 static uint8_t
428 rf_radio_setup()
429 {
430  uint32_t cmd_status;
431  rfc_CMD_RADIO_SETUP_t cmd;
432 
433  /* Create radio setup command */
434  rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_RADIO_SETUP);
435 
436  cmd.txPower.IB = tx_power_current->register_ib;
437  cmd.txPower.GC = tx_power_current->register_gc;
438  cmd.txPower.tempCoeff = tx_power_current->temp_coeff;
439  cmd.pRegOverride = ieee_overrides;
440  cmd.mode = 1;
441 
442  /* Send Radio setup to RF Core */
443  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) != RF_CORE_CMD_OK) {
444  PRINTF("rf_radio_setup: CMD_RADIO_SETUP, CMDSTA=0x%08lx, status=0x%04x\n",
445  cmd_status, cmd.status);
446  return RF_CORE_CMD_ERROR;
447  }
448 
449  /* Wait until radio setup is done */
450  if(rf_core_wait_cmd_done(&cmd) != RF_CORE_CMD_OK) {
451  PRINTF("rf_radio_setup: CMD_RADIO_SETUP wait, CMDSTA=0x%08lx, status=0x%04x\n",
452  cmd_status, cmd.status);
453  return RF_CORE_CMD_ERROR;
454  }
455 
456  return RF_CORE_CMD_OK;
457 }
458 /*---------------------------------------------------------------------------*/
459 /**
460  * \brief Set up radio in IEEE802.15.4 RX mode
461  *
462  * \return RF_CORE_CMD_OK Succeeded
463  * \return RF_CORE_CMD_ERROR Failed
464  *
465  * This function assumes that cmd_ieee_rx_buf has been previously populated
466  * with correct values. This can be done through init_rf_params (sets defaults)
467  * or through Contiki's extended RF API (set_value, set_object)
468  */
469 static uint8_t
471 {
472  uint32_t cmd_status;
473  rtimer_clock_t t0;
474  int ret;
475 
476  ret = rf_core_send_cmd((uint32_t)cmd_ieee_rx_buf, &cmd_status);
477 
478  if(ret != RF_CORE_CMD_OK) {
479  PRINTF("rf_cmd_ieee_rx: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
480  ret, cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
481  return RF_CORE_CMD_ERROR;
482  }
483 
484  t0 = RTIMER_NOW();
485 
486  while(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE &&
487  (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ENTER_RX_WAIT_TIMEOUT)));
488 
489  /* Wait to enter RX */
490  if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE) {
491  PRINTF("rf_cmd_ieee_rx: CMDSTA=0x%08lx, status=0x%04x\n",
492  cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
493  return RF_CORE_CMD_ERROR;
494  }
495 
496  return ret;
497 }
498 /*---------------------------------------------------------------------------*/
499 static void
500 init_rx_buffers(void)
501 {
502  rfc_dataEntry_t *entry;
503 
504  entry = (rfc_dataEntry_t *)rx_buf_0;
505  entry->pNextEntry = rx_buf_1;
506  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
507  entry->length = sizeof(rx_buf_0) - 8;
508 
509  entry = (rfc_dataEntry_t *)rx_buf_1;
510  entry->pNextEntry = rx_buf_2;
511  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
512  entry->length = sizeof(rx_buf_0) - 8;
513 
514  entry = (rfc_dataEntry_t *)rx_buf_2;
515  entry->pNextEntry = rx_buf_3;
516  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
517  entry->length = sizeof(rx_buf_0) - 8;
518 
519  entry = (rfc_dataEntry_t *)rx_buf_3;
520  entry->pNextEntry = rx_buf_0;
521  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
522  entry->length = sizeof(rx_buf_0) - 8;
523 }
524 /*---------------------------------------------------------------------------*/
525 static void
526 init_rf_params(void)
527 {
528  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
529 
530  memset(cmd_ieee_rx_buf, 0x00, RF_CMD_BUFFER_SIZE);
531 
532  cmd->commandNo = CMD_IEEE_RX;
533  cmd->status = RF_CORE_RADIO_OP_STATUS_IDLE;
534  cmd->pNextOp = NULL;
535  cmd->startTime = 0x00000000;
536  cmd->startTrigger.triggerType = TRIG_NOW;
537  cmd->condition.rule = COND_NEVER;
538  cmd->channel = RF_CORE_CHANNEL;
539 
540  cmd->rxConfig.bAutoFlushCrc = 1;
541  cmd->rxConfig.bAutoFlushIgn = 0;
542  cmd->rxConfig.bIncludePhyHdr = 0;
543  cmd->rxConfig.bIncludeCrc = 1;
544  cmd->rxConfig.bAppendRssi = 1;
545  cmd->rxConfig.bAppendCorrCrc = 1;
546  cmd->rxConfig.bAppendSrcInd = 0;
547  cmd->rxConfig.bAppendTimestamp = 0;
548 
549  cmd->pRxQ = &rx_data_queue;
550  cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats;
551 
552 #if IEEE_MODE_PROMISCOUS
553  cmd->frameFiltOpt.frameFiltEn = 0;
554 #else
555  cmd->frameFiltOpt.frameFiltEn = 1;
556 #endif
557 
558  cmd->frameFiltOpt.frameFiltStop = 1;
559 
560 #if IEEE_MODE_AUTOACK
561  cmd->frameFiltOpt.autoAckEn = 1;
562 #else
563  cmd->frameFiltOpt.autoAckEn = 0;
564 #endif
565 
566  cmd->frameFiltOpt.slottedAckEn = 0;
567  cmd->frameFiltOpt.autoPendEn = 0;
568  cmd->frameFiltOpt.defaultPend = 0;
569  cmd->frameFiltOpt.bPendDataReqOnly = 0;
570  cmd->frameFiltOpt.bPanCoord = 0;
571  cmd->frameFiltOpt.maxFrameVersion = 1;
572  cmd->frameFiltOpt.bStrictLenFilter = 0;
573 
574  /* Receive all frame types */
575  cmd->frameTypes.bAcceptFt0Beacon = 1;
576  cmd->frameTypes.bAcceptFt1Data = 1;
577  cmd->frameTypes.bAcceptFt2Ack = 1;
578  cmd->frameTypes.bAcceptFt3MacCmd = 1;
579  cmd->frameTypes.bAcceptFt4Reserved = 1;
580  cmd->frameTypes.bAcceptFt5Reserved = 1;
581  cmd->frameTypes.bAcceptFt6Reserved = 1;
582  cmd->frameTypes.bAcceptFt7Reserved = 1;
583 
584  /* Configure CCA settings */
585  cmd->ccaOpt.ccaEnEnergy = 1;
586  cmd->ccaOpt.ccaEnCorr = 1;
587  cmd->ccaOpt.ccaEnSync = 0;
588  cmd->ccaOpt.ccaCorrOp = 1;
589  cmd->ccaOpt.ccaSyncOp = 1;
590  cmd->ccaOpt.ccaCorrThr = 3;
591 
592  cmd->ccaRssiThr = IEEE_MODE_RSSI_THRESHOLD;
593 
594  cmd->numExtEntries = 0x00;
595  cmd->numShortEntries = 0x00;
596  cmd->pExtEntryList = 0;
597  cmd->pShortEntryList = 0;
598 
599  cmd->endTrigger.triggerType = TRIG_NEVER;
600  cmd->endTime = 0x00000000;
601 }
602 /*---------------------------------------------------------------------------*/
603 static int
604 rx_on(void)
605 {
606  int ret;
607 
608  /* Get status of running IEEE_RX (if any) */
609  if(rf_is_on()) {
610  PRINTF("rx_on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
611  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
612  return RF_CORE_CMD_OK;
613  }
614 
615  /* Put CPE in RX using the currently configured parameters */
616  ret = rf_cmd_ieee_rx();
617 
618  if(ret) {
619  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
620  }
621 
622  return ret;
623 }
624 /*---------------------------------------------------------------------------*/
625 static int
626 rx_off(void)
627 {
628  uint32_t cmd_status;
629  int ret;
630 
631  /* If we are off, do nothing */
632  if(!rf_is_on()) {
633  return RF_CORE_CMD_OK;
634  }
635 
636  /* Wait for ongoing ACK TX to finish */
637  while(transmitting());
638 
639  /* Send a CMD_ABORT command to RF Core */
640  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
641  PRINTF("RX off: CMD_ABORT status=0x%08lx\n", cmd_status);
642  /* Continue nonetheless */
643  }
644 
645  while(rf_is_on());
646 
647  if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED ||
648  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) {
649  /* Stopped gracefully */
650  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
651  ret = RF_CORE_CMD_OK;
652  } else {
653  PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
654  ret = RF_CORE_CMD_ERROR;
655  }
656 
657  return ret;
658 }
659 /*---------------------------------------------------------------------------*/
660 static uint8_t
661 request(void)
662 {
663  /*
664  * We rely on the RDC layer to turn us on and off. Thus, if we are on we
665  * will only allow sleep, standby otherwise
666  */
667  if(rf_is_on()) {
668  return LPM_MODE_SLEEP;
669  }
670 
671  return LPM_MODE_MAX_SUPPORTED;
672 }
673 /*---------------------------------------------------------------------------*/
674 LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
675 /*---------------------------------------------------------------------------*/
676 static void
677 soft_off(void)
678 {
679  uint32_t cmd_status;
680  volatile rfc_radioOp_t *cmd = rf_core_get_last_radio_op();
681 
682  if(!rf_core_is_accessible()) {
683  return;
684  }
685 
686  PRINTF("soft_off: Aborting 0x%04x, Status=0x%04x\n", cmd->commandNo,
687  cmd->status);
688 
689  /* Send a CMD_ABORT command to RF Core */
690  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
691  PRINTF("soft_off: CMD_ABORT status=0x%08lx\n", cmd_status);
692  return;
693  }
694 
695  while((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) ==
696  RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING);
697 }
698 /*---------------------------------------------------------------------------*/
699 static uint8_t
700 soft_on(void)
701 {
702  if(rf_radio_setup() != RF_CORE_CMD_OK) {
703  PRINTF("on: radio_setup() failed\n");
704  return RF_CORE_CMD_ERROR;
705  }
706 
707  return rx_on();
708 }
709 /*---------------------------------------------------------------------------*/
710 static const rf_core_primary_mode_t mode_ieee = {
711  soft_off,
712  soft_on,
713 };
714 /*---------------------------------------------------------------------------*/
715 static int
716 init(void)
717 {
718  lpm_register_module(&cc26xx_rf_lpm_module);
719 
721 
722  /* Initialise RX buffers */
723  memset(rx_buf_0, 0, RX_BUF_SIZE);
724  memset(rx_buf_1, 0, RX_BUF_SIZE);
725  memset(rx_buf_2, 0, RX_BUF_SIZE);
726  memset(rx_buf_3, 0, RX_BUF_SIZE);
727 
728  /* Set of RF Core data queue. Circular buffer, no last entry */
729  rx_data_queue.pCurrEntry = rx_buf_0;
730 
731  rx_data_queue.pLastEntry = NULL;
732 
733  /* Initialize current read pointer to first element (used in ISR) */
734  rx_read_entry = rx_buf_0;
735 
736  /* Populate the RF parameters data structure with default values */
737  init_rf_params();
738 
739  if(on() != RF_CORE_CMD_OK) {
740  PRINTF("init: on() failed\n");
741  return RF_CORE_CMD_ERROR;
742  }
743 
744  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
745 
746  rf_core_primary_mode_register(&mode_ieee);
747 
748  process_start(&rf_core_process, NULL);
749  return 1;
750 }
751 /*---------------------------------------------------------------------------*/
752 static int
753 prepare(const void *payload, unsigned short payload_len)
754 {
755  int len = MIN(payload_len, TX_BUF_PAYLOAD_LEN);
756 
757  memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, len);
758  return RF_CORE_CMD_OK;
759 }
760 /*---------------------------------------------------------------------------*/
761 static int
762 transmit(unsigned short transmit_len)
763 {
764  int ret;
765  uint8_t was_off = 0;
766  uint32_t cmd_status;
767  uint16_t stat;
768  uint8_t tx_active = 0;
769  rtimer_clock_t t0;
770  volatile rfc_CMD_IEEE_TX_t cmd;
771 
772  if(!rf_is_on()) {
773  was_off = 1;
774  if(on() != RF_CORE_CMD_OK) {
775  PRINTF("transmit: on() failed\n");
776  return RADIO_TX_ERR;
777  }
778  }
779 
780  /*
781  * We are certainly not TXing a frame as a result of CMD_IEEE_TX, but we may
782  * be in the process of TXing an ACK. In that case, wait for the TX to finish
783  * or return after approx TX_WAIT_TIMEOUT
784  */
785  t0 = RTIMER_NOW();
786 
787  do {
788  tx_active = transmitting();
789  } while(tx_active == 1 &&
790  (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TX_WAIT_TIMEOUT)));
791 
792  if(tx_active) {
793  PRINTF("transmit: Already TXing and wait timed out\n");
794 
795  if(was_off) {
796  off();
797  }
798 
799  return RADIO_TX_COLLISION;
800  }
801 
802  /* Send the CMD_IEEE_TX command */
803  rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_IEEE_TX);
804 
805  cmd.payloadLen = transmit_len;
806  cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN];
807 
808  /* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */
809  rf_core_cmd_done_en(true);
810 
811  ret = rf_core_send_cmd((uint32_t)&cmd, &cmd_status);
812 
813  if(ret) {
814  /* If we enter here, TX actually started */
815  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
816  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
817 
818  /* Idle away while the command is running */
819  while((cmd.status & RF_CORE_RADIO_OP_MASKED_STATUS)
820  == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
821  lpm_sleep();
822  }
823 
824  stat = cmd.status;
825 
826  if(stat == RF_CORE_RADIO_OP_STATUS_IEEE_DONE_OK) {
827  /* Sent OK */
828  RIMESTATS_ADD(lltx);
829  ret = RADIO_TX_OK;
830  } else {
831  /* Operation completed, but frame was not sent */
832  PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", ret,
833  cmd_status, stat);
834  ret = RADIO_TX_ERR;
835  }
836  } else {
837  /* Failure sending the CMD_IEEE_TX command */
838  PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
839  ret, cmd_status, cmd.status);
840 
841  ret = RADIO_TX_ERR;
842  }
843 
844  /*
845  * Update ENERGEST state here, before a potential call to off(), which
846  * will correctly update it if required.
847  */
848  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
849  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
850 
851  /*
852  * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
853  * except when we are transmitting
854  */
856 
857 
858  if(was_off) {
859  off();
860  }
861 
862  return ret;
863 }
864 /*---------------------------------------------------------------------------*/
865 static int
866 send(const void *payload, unsigned short payload_len)
867 {
868  prepare(payload, payload_len);
869  return transmit(payload_len);
870 }
871 /*---------------------------------------------------------------------------*/
872 static void
873 release_data_entry(void)
874 {
875  rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
876 
877  /* Clear the length byte */
878  rx_read_entry[8] = 0;
879 
880  /* Set status to 0 "Pending" in element */
881  entry->status = DATA_ENTRY_STATUS_PENDING;
882  rx_read_entry = entry->pNextEntry;
883 }/*---------------------------------------------------------------------------*/
884 static int
885 read_frame(void *buf, unsigned short buf_len)
886 {
887  int8_t rssi;
888  int len = 0;
889  rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
890 
891  if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
892  /* No available data */
893  return 0;
894  }
895 
896  if(rx_read_entry[8] < 4) {
897  PRINTF("RF: too short\n");
898  RIMESTATS_ADD(tooshort);
899 
900  release_data_entry();
901  return 0;
902  }
903 
904  len = rx_read_entry[8] - 4;
905 
906  if(len > buf_len) {
907  PRINTF("RF: too long\n");
908  RIMESTATS_ADD(toolong);
909 
910  release_data_entry();
911  return 0;
912  }
913 
914  memcpy(buf, (char *)&rx_read_entry[9], len);
915 
916  rssi = (int8_t)rx_read_entry[9 + len + 2];
917 
918  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
919  RIMESTATS_ADD(llrx);
920 
921  release_data_entry();
922 
923  return len;
924 }
925 /*---------------------------------------------------------------------------*/
926 static int
927 channel_clear(void)
928 {
929  uint8_t was_off = 0;
930  uint8_t cca_info;
931  int ret = RF_CCA_CLEAR;
932 
933  /*
934  * If we are in the middle of a BLE operation, we got called by ContikiMAC
935  * from within an interrupt context. Indicate a clear channel
936  */
937  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
938  PRINTF("channel_clear: Interrupt context but BLE in progress\n");
939  return RF_CCA_CLEAR;
940  }
941 
942  if(rf_is_on()) {
943  /*
944  * Wait for potential leftover ACK still being sent.
945  * Strictly speaking, if we are TXing an ACK then the channel is not clear.
946  * However, channel_clear is only ever called to determine whether there is
947  * someone else's packet in the air, not ours.
948  *
949  * We could probably even simply return that the channel is clear
950  */
951  while(transmitting());
952  } else {
953  was_off = 1;
954  if(on() != RF_CORE_CMD_OK) {
955  PRINTF("channel_clear: on() failed\n");
956  if(was_off) {
957  off();
958  }
959  return RF_CCA_CLEAR;
960  }
961  }
962 
963  cca_info = get_cca_info();
964 
965  if(cca_info == RF_GET_CCA_INFO_ERROR) {
966  PRINTF("channel_clear: CCA error\n");
967  ret = RF_CCA_CLEAR;
968  } else {
969  /*
970  * cca_info bits 1:0 - ccaStatus
971  * Return 1 (clear) if idle or invalid.
972  */
973  ret = (cca_info & 0x03) != RF_CMD_CCA_REQ_CCA_STATE_BUSY;
974  }
975 
976  if(was_off) {
977  off();
978  }
979 
980  return ret;
981 }
982 /*---------------------------------------------------------------------------*/
983 static int
984 receiving_packet(void)
985 {
986  int ret = 0;
987  uint8_t cca_info;
988  uint8_t was_off = 0;
989 
990  /*
991  * If we are in the middle of a BLE operation, we got called by ContikiMAC
992  * from within an interrupt context. We are not receiving
993  */
994  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
995  PRINTF("receiving_packet: Interrupt context but BLE in progress\n");
996  return 0;
997  }
998 
999  /* If we are off, we are not receiving */
1000  if(!rf_is_on()) {
1001  PRINTF("receiving_packet: We were off\n");
1002  return 0;
1003  }
1004 
1005  /* If we are transmitting (can only be an ACK here), we are not receiving */
1006  if(transmitting()) {
1007  PRINTF("receiving_packet: We were TXing\n");
1008  return 0;
1009  }
1010 
1011  cca_info = get_cca_info();
1012 
1013  if(cca_info == RF_GET_CCA_INFO_ERROR) {
1014  /* If we can't read CCA info, return "not receiving" */
1015  ret = 0;
1016  } else {
1017  /* Return 1 (receiving) if ccaState is busy */
1018  ret = (cca_info & 0x03) == RF_CMD_CCA_REQ_CCA_STATE_BUSY;
1019  }
1020 
1021  if(was_off) {
1022  off();
1023  }
1024 
1025  return ret;
1026 }
1027 /*---------------------------------------------------------------------------*/
1028 static int
1029 pending_packet(void)
1030 {
1031  volatile rfc_dataEntry_t *entry = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
1032  int rv = 0;
1033 
1034  /* Go through all RX buffers and check their status */
1035  do {
1036  if(entry->status == DATA_ENTRY_STATUS_FINISHED) {
1037  rv = 1;
1038  process_poll(&rf_core_process);
1039  }
1040 
1041  entry = (rfc_dataEntry_t *)entry->pNextEntry;
1042  } while(entry != (rfc_dataEntry_t *)rx_data_queue.pCurrEntry);
1043 
1044  /* If we didn't find an entry at status finished, no frames are pending */
1045  return rv;
1046 }
1047 /*---------------------------------------------------------------------------*/
1048 static int
1049 on(void)
1050 {
1051  /*
1052  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1053  * from within an interrupt context. Abort, but pretend everything is OK.
1054  */
1055  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1056  PRINTF("on: Interrupt context but BLE in progress\n");
1057  return RF_CORE_CMD_OK;
1058  }
1059 
1060  /*
1061  * Request the HF XOSC as the source for the HF clock. Needed before we can
1062  * use the FS. This will only request, it will _not_ perform the switch.
1063  */
1065 
1066  if(rf_is_on()) {
1067  PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
1068  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
1069  return RF_CORE_CMD_OK;
1070  }
1071 
1072  if(rf_core_boot() != RF_CORE_CMD_OK) {
1073  PRINTF("on: rf_core_boot() failed\n");
1074  return RF_CORE_CMD_ERROR;
1075  }
1076 
1077  init_rx_buffers();
1078 
1080 
1081  /*
1082  * Trigger a switch to the XOSC, so that we can subsequently use the RF FS
1083  * This will block until the XOSC is actually ready, but give how we
1084  * requested it early on, this won't be too long a wait/
1085  */
1087 
1088  if(rf_radio_setup() != RF_CORE_CMD_OK) {
1089  PRINTF("on: radio_setup() failed\n");
1090  return RF_CORE_CMD_ERROR;
1091  }
1092 
1093  return rx_on();
1094 }
1095 /*---------------------------------------------------------------------------*/
1096 static int
1097 off(void)
1098 {
1099  /*
1100  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1101  * from within an interrupt context. Abort, but pretend everything is OK.
1102  */
1103  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1104  PRINTF("off: Interrupt context but BLE in progress\n");
1105  return RF_CORE_CMD_OK;
1106  }
1107 
1108  while(transmitting());
1109 
1110  /* stopping the rx explicitly results in lower sleep-mode power usage */
1111  rx_off();
1113 
1114  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
1115 
1116  /* Switch HF clock source to the RCOSC to preserve power */
1118 
1119  /* We pulled the plug, so we need to restore the status manually */
1120  ((rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
1121 
1122  /*
1123  * Just in case there was an ongoing RX (which started after we begun the
1124  * shutdown sequence), we don't want to leave the buffer in state == ongoing
1125  */
1126  ((rfc_dataEntry_t *)rx_buf_0)->status = DATA_ENTRY_STATUS_PENDING;
1127  ((rfc_dataEntry_t *)rx_buf_1)->status = DATA_ENTRY_STATUS_PENDING;
1128  ((rfc_dataEntry_t *)rx_buf_2)->status = DATA_ENTRY_STATUS_PENDING;
1129  ((rfc_dataEntry_t *)rx_buf_3)->status = DATA_ENTRY_STATUS_PENDING;
1130 
1131  return RF_CORE_CMD_OK;
1132 }
1133 /*---------------------------------------------------------------------------*/
1134 static radio_result_t
1135 get_value(radio_param_t param, radio_value_t *value)
1136 {
1137  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1138 
1139  if(!value) {
1140  return RADIO_RESULT_INVALID_VALUE;
1141  }
1142 
1143  switch(param) {
1144  case RADIO_PARAM_POWER_MODE:
1145  /* On / off */
1146  *value = rf_is_on() ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
1147  return RADIO_RESULT_OK;
1148  case RADIO_PARAM_CHANNEL:
1149  *value = (radio_value_t)cmd->channel;
1150  return RADIO_RESULT_OK;
1151  case RADIO_PARAM_PAN_ID:
1152  *value = (radio_value_t)cmd->localPanID;
1153  return RADIO_RESULT_OK;
1154  case RADIO_PARAM_16BIT_ADDR:
1155  *value = (radio_value_t)cmd->localShortAddr;
1156  return RADIO_RESULT_OK;
1157  case RADIO_PARAM_RX_MODE:
1158  *value = 0;
1159  if(cmd->frameFiltOpt.frameFiltEn) {
1160  *value |= RADIO_RX_MODE_ADDRESS_FILTER;
1161  }
1162  if(cmd->frameFiltOpt.autoAckEn) {
1163  *value |= RADIO_RX_MODE_AUTOACK;
1164  }
1165 
1166  return RADIO_RESULT_OK;
1167  case RADIO_PARAM_TXPOWER:
1168  *value = get_tx_power();
1169  return RADIO_RESULT_OK;
1170  case RADIO_PARAM_CCA_THRESHOLD:
1171  *value = cmd->ccaRssiThr;
1172  return RADIO_RESULT_OK;
1173  case RADIO_PARAM_RSSI:
1174  *value = get_rssi();
1175 
1176  if(*value == RF_CMD_CCA_REQ_RSSI_UNKNOWN) {
1177  return RADIO_RESULT_ERROR;
1178  } else {
1179  return RADIO_RESULT_OK;
1180  }
1181  case RADIO_CONST_CHANNEL_MIN:
1182  *value = IEEE_MODE_CHANNEL_MIN;
1183  return RADIO_RESULT_OK;
1184  case RADIO_CONST_CHANNEL_MAX:
1185  *value = IEEE_MODE_CHANNEL_MAX;
1186  return RADIO_RESULT_OK;
1187  case RADIO_CONST_TXPOWER_MIN:
1188  *value = OUTPUT_POWER_MIN;
1189  return RADIO_RESULT_OK;
1190  case RADIO_CONST_TXPOWER_MAX:
1191  *value = OUTPUT_POWER_MAX;
1192  return RADIO_RESULT_OK;
1193  default:
1194  return RADIO_RESULT_NOT_SUPPORTED;
1195  }
1196 }
1197 /*---------------------------------------------------------------------------*/
1198 static radio_result_t
1199 set_value(radio_param_t param, radio_value_t value)
1200 {
1201  uint8_t was_off = 0;
1202  radio_result_t rv = RADIO_RESULT_OK;
1203  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1204 
1205  switch(param) {
1206  case RADIO_PARAM_POWER_MODE:
1207  if(value == RADIO_POWER_MODE_ON) {
1208  if(on() != RF_CORE_CMD_OK) {
1209  PRINTF("set_value: on() failed (1)\n");
1210  return RADIO_RESULT_ERROR;
1211  }
1212  return RADIO_RESULT_OK;
1213  }
1214  if(value == RADIO_POWER_MODE_OFF) {
1215  off();
1216  return RADIO_RESULT_OK;
1217  }
1218  return RADIO_RESULT_INVALID_VALUE;
1219  case RADIO_PARAM_CHANNEL:
1220  if(value < IEEE_MODE_CHANNEL_MIN ||
1221  value > IEEE_MODE_CHANNEL_MAX) {
1222  return RADIO_RESULT_INVALID_VALUE;
1223  }
1224 
1225  if(cmd->channel == (uint8_t)value) {
1226  /* We already have that very same channel configured.
1227  * Nothing to do here. */
1228  return RADIO_RESULT_OK;
1229  }
1230 
1231  cmd->channel = (uint8_t)value;
1232  break;
1233  case RADIO_PARAM_PAN_ID:
1234  cmd->localPanID = (uint16_t)value;
1235  break;
1236  case RADIO_PARAM_16BIT_ADDR:
1237  cmd->localShortAddr = (uint16_t)value;
1238  break;
1239  case RADIO_PARAM_RX_MODE:
1240  {
1241  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
1242  RADIO_RX_MODE_AUTOACK)) {
1243  return RADIO_RESULT_INVALID_VALUE;
1244  }
1245 
1246  cmd->frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0;
1247  cmd->frameFiltOpt.frameFiltStop = 1;
1248  cmd->frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0;
1249  cmd->frameFiltOpt.slottedAckEn = 0;
1250  cmd->frameFiltOpt.autoPendEn = 0;
1251  cmd->frameFiltOpt.defaultPend = 0;
1252  cmd->frameFiltOpt.bPendDataReqOnly = 0;
1253  cmd->frameFiltOpt.bPanCoord = 0;
1254  cmd->frameFiltOpt.bStrictLenFilter = 0;
1255  break;
1256  }
1257  case RADIO_PARAM_TXPOWER:
1258  if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
1259  return RADIO_RESULT_INVALID_VALUE;
1260  }
1261 
1262  set_tx_power(value);
1263 
1264  return RADIO_RESULT_OK;
1265  case RADIO_PARAM_CCA_THRESHOLD:
1266  cmd->ccaRssiThr = (int8_t)value;
1267  break;
1268  default:
1269  return RADIO_RESULT_NOT_SUPPORTED;
1270  }
1271 
1272  /* If we reach here we had no errors. Apply new settings */
1273  if(!rf_is_on()) {
1274  was_off = 1;
1275  if(on() != RF_CORE_CMD_OK) {
1276  PRINTF("set_value: on() failed (2)\n");
1277  return RADIO_RESULT_ERROR;
1278  }
1279  }
1280 
1281  if(rx_off() != RF_CORE_CMD_OK) {
1282  PRINTF("set_value: rx_off() failed\n");
1283  rv = RADIO_RESULT_ERROR;
1284  }
1285 
1286  if(rx_on() != RF_CORE_CMD_OK) {
1287  PRINTF("set_value: rx_on() failed\n");
1288  rv = RADIO_RESULT_ERROR;
1289  }
1290 
1291  /* If we were off, turn back off */
1292  if(was_off) {
1293  off();
1294  }
1295 
1296  return rv;
1297 }
1298 /*---------------------------------------------------------------------------*/
1299 static radio_result_t
1300 get_object(radio_param_t param, void *dest, size_t size)
1301 {
1302  uint8_t *target;
1303  uint8_t *src;
1304  int i;
1305  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1306 
1307  if(param == RADIO_PARAM_64BIT_ADDR) {
1308  if(size != 8 || !dest) {
1309  return RADIO_RESULT_INVALID_VALUE;
1310  }
1311 
1312  target = dest;
1313  src = (uint8_t *)(&cmd->localExtAddr);
1314 
1315  for(i = 0; i < 8; i++) {
1316  target[i] = src[7 - i];
1317  }
1318 
1319  return RADIO_RESULT_OK;
1320  }
1321  return RADIO_RESULT_NOT_SUPPORTED;
1322 }
1323 /*---------------------------------------------------------------------------*/
1324 static radio_result_t
1325 set_object(radio_param_t param, const void *src, size_t size)
1326 {
1327  uint8_t was_off = 0;
1328  radio_result_t rv;
1329  int i;
1330  uint8_t *dst;
1331  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1332 
1333  if(param == RADIO_PARAM_64BIT_ADDR) {
1334  if(size != 8 || !src) {
1335  return RADIO_RESULT_INVALID_VALUE;
1336  }
1337 
1338  dst = (uint8_t *)(&cmd->localExtAddr);
1339 
1340  for(i = 0; i < 8; i++) {
1341  dst[i] = ((uint8_t *)src)[7 - i];
1342  }
1343 
1344  if(!rf_is_on()) {
1345  was_off = 1;
1346  if(on() != RF_CORE_CMD_OK) {
1347  PRINTF("set_object: on() failed\n");
1348  return RADIO_RESULT_ERROR;
1349  }
1350  }
1351 
1352  if(rx_off() != RF_CORE_CMD_OK) {
1353  PRINTF("set_object: rx_off() failed\n");
1354  rv = RADIO_RESULT_ERROR;
1355  }
1356 
1357  if(rx_on() != RF_CORE_CMD_OK) {
1358  PRINTF("set_object: rx_on() failed\n");
1359  rv = RADIO_RESULT_ERROR;
1360  }
1361 
1362  /* If we were off, turn back off */
1363  if(was_off) {
1364  off();
1365  }
1366 
1367  return rv;
1368  }
1369  return RADIO_RESULT_NOT_SUPPORTED;
1370 }
1371 /*---------------------------------------------------------------------------*/
1372 const struct radio_driver ieee_mode_driver = {
1373  init,
1374  prepare,
1375  transmit,
1376  send,
1377  read_frame,
1378  channel_clear,
1381  on,
1382  off,
1383  get_value,
1384  set_value,
1385  get_object,
1386  set_object,
1387 };
1388 /*---------------------------------------------------------------------------*/
1389 /**
1390  * @}
1391  * @}
1392  */
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
Header file for the real-time timer module.
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
Definition: rf-core.c:269
Header file for the radio API
Header file with macros which rename TI CC26xxware functions.
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:135
void lpm_sleep(void)
Enter sleep mode.
Definition: lpm.c:479
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not...
Definition: radio.h:255
Default definitions of C compiler quirk work-arounds.
Header file for the CC13xx/CC26xx BLE driver.
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:242
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:258
uint8_t rf_ble_is_active()
Check whether the BLE beacond is currently active.
Definition: rf-ble.c:203
void oscillators_switch_to_hf_xosc(void)
Performs the switch to the XOSC.
Definition: oscillators.c:116
Header file for the energy estimation mechanism
The structure of a device driver for a radio in Contiki.
Definition: radio.h:237
void lpm_register_module(lpm_registered_module_t *module)
Register a module for LPM notifications.
Definition: lpm.c:498
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
Definition: radio.h:261
Header file for the Rime buffer (packetbuf) management
#define LPM_MODULE(n, m, s, w, l)
Declare a variable to be used in order to get notifications from LPM.
Definition: lpm.h:92
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:273
static uint8_t get_cca_info(void)
Returns CCA information.
Definition: ieee-mode.c:306
void rf_core_setup_interrupts()
Setup RF core interrupts.
Definition: rf-core.c:370
Header file for the CC13xx/CC26xx RF core driver.
Header file for the Rime address representation
int(* off)(void)
Turn the radio off.
Definition: radio.h:267
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
Definition: rf-core.c:110
#define NULL
The null pointer.
void oscillators_switch_to_hf_rc(void)
Switches MF and HF clock source to be the HF RC OSC.
Definition: oscillators.c:134
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
Definition: radio.h:88
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
Definition: rf-core.c:303
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Definition: radio.h:204
static uint8_t transmitting(void)
Check the RF's TX status.
Definition: ieee-mode.c:267
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
Definition: rf-core.c:403
uint8_t rf_core_boot()
Boot the RF Core.
Definition: rf-core.c:348
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:280
int(* on)(void)
Turn the radio on.
Definition: radio.h:264
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
Definition: rf-core.c:433
static uint8_t rf_is_on(void)
Checks whether the RFC domain is accessible and the RFC is in IEEE RX.
Definition: ieee-mode.c:249
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
Definition: rf-core.c:119
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:270
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:248
static radio_value_t get_rssi(void)
Reads the current signal strength (RSSI)
Definition: ieee-mode.c:344
#define RF_RADIO_OP_GET_STATUS(a)
Returns the current status of a running Radio Op command.
Definition: ieee-mode.c:126
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
Definition: rf-core.c:418
Header file for Rime statistics
Header file for the CC13xx/CC26xx UART driver.
static uint8_t rf_cmd_ieee_rx()
Set up radio in IEEE802.15.4 RX mode.
Definition: ieee-mode.c:470
Header file for the CC13xx/CC26xx oscillator control.
void oscillators_request_hf_xosc(void)
Requests the HF XOSC as the source for the HF clock, but does not perform the actual switch...
Definition: oscillators.c:94
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:245
void rf_core_init_radio_op(rfc_radioOp_t *op, uint16_t len, uint16_t command)
Prepare a buffer to host a Radio Op.
Definition: rf-core.c:424
void rf_core_cmd_done_dis()
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
Definition: rf-core.c:412
Include file for the Contiki low-layer network stack (NETSTACK)
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:286
A data strcuture representing the radio's primary mode of operation.
Definition: rf-core.h:93
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
Definition: rf-core.c:185