Contiki-NG
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/linkaddr.h"
49#include "net/netstack.h"
50#include "sys/energest.h"
51#include "sys/clock.h"
52#include "sys/rtimer.h"
53#include "sys/ctimer.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-switch.h"
59#include "rf-core/rf-ble.h"
60/*---------------------------------------------------------------------------*/
61/* RF core and RF HAL API */
62#include "hw_rfc_dbell.h"
63#include "hw_rfc_pwr.h"
64/*---------------------------------------------------------------------------*/
65/* RF Core Mailbox API */
66#include "rf-core/api/ieee_cmd.h"
67#include "rf-core/api/ieee_mailbox.h"
68#include "driverlib/rf_mailbox.h"
69#include "driverlib/rf_common_cmd.h"
70#include "driverlib/rf_data_entry.h"
71/*---------------------------------------------------------------------------*/
72#include "smartrf-settings.h"
73/*---------------------------------------------------------------------------*/
74#include <stdint.h>
75#include <string.h>
76#include <stdio.h>
77#include <stdbool.h>
78/*---------------------------------------------------------------------------*/
79#define DEBUG 0
80#if DEBUG
81#define PRINTF(...) printf(__VA_ARGS__)
82#else
83#define PRINTF(...)
84#endif
85
86/* Configuration to enable/disable auto ACKs in IEEE mode */
87#ifdef IEEE_MODE_CONF_AUTOACK
88#define IEEE_MODE_AUTOACK IEEE_MODE_CONF_AUTOACK
89#else
90#define IEEE_MODE_AUTOACK 1
91#endif /* IEEE_MODE_CONF_AUTOACK */
92
93/* Configuration to enable/disable frame filtering in IEEE mode */
94#ifdef IEEE_MODE_CONF_PROMISCOUS
95#define IEEE_MODE_PROMISCOUS IEEE_MODE_CONF_PROMISCOUS
96#else
97#define IEEE_MODE_PROMISCOUS 0
98#endif /* IEEE_MODE_CONF_PROMISCOUS */
99
100#ifdef IEEE_MODE_CONF_RSSI_THRESHOLD
101#define IEEE_MODE_RSSI_THRESHOLD IEEE_MODE_CONF_RSSI_THRESHOLD
102#else
103#define IEEE_MODE_RSSI_THRESHOLD 0xA6
104#endif /* IEEE_MODE_CONF_RSSI_THRESHOLD */
105/*---------------------------------------------------------------------------*/
106#define STATUS_CRC_FAIL 0x80 /* bit 7 */
107#define STATUS_REJECT_FRAME 0x40 /* bit 6 */
108#define STATUS_CORRELATION 0x3f /* bits 0-5 */
109/*---------------------------------------------------------------------------*/
110/* Data entry status field constants */
111#define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */
112#define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */
113#define DATA_ENTRY_STATUS_BUSY 0x02 /* Ongoing r/w */
114#define DATA_ENTRY_STATUS_FINISHED 0x03 /* Free to use and to free */
115#define DATA_ENTRY_STATUS_UNFINISHED 0x04 /* Partial RX entry */
116/*---------------------------------------------------------------------------*/
117/* RF stats data structure */
118static uint8_t rf_stats[16] = { 0 };
119/*---------------------------------------------------------------------------*/
120/* The size of the RF commands buffer */
121#define RF_CMD_BUFFER_SIZE 128
122/*---------------------------------------------------------------------------*/
123#define RAT_TIMESTAMP_OFFSET_2_4_GHZ 0
124/*---------------------------------------------------------------------------*/
125/**
126 * \brief Returns the current status of a running Radio Op command
127 * \param a A pointer with the buffer used to initiate the command
128 * \return The value of the Radio Op buffer's status field
129 *
130 * This macro can be used to e.g. return the status of a previously
131 * initiated background operation, or of an immediate command
132 */
133#define RF_RADIO_OP_GET_STATUS(a) (((rfc_radioOp_t *)a)->status)
134/*---------------------------------------------------------------------------*/
135#define IEEE_MODE_CHANNEL_MIN 11
136#define IEEE_MODE_CHANNEL_MAX 26
137/*---------------------------------------------------------------------------*/
138/* TX Power dBm lookup table - values from SmartRF Studio */
139typedef struct output_config {
140 radio_value_t dbm;
141 uint16_t tx_power; /* Value for the CMD_RADIO_SETUP.txPower field */
142} output_config_t;
143
144static const output_config_t output_power[] = {
145 { 5, 0x9330 },
146 { 4, 0x9324 },
147 { 3, 0x5a1c },
148 { 2, 0x4e18 },
149 { 1, 0x4214 },
150 { 0, 0x3161 },
151 { -3, 0x2558 },
152 { -6, 0x1d52 },
153 { -9, 0x194e },
154 {-12, 0x144b },
155 {-15, 0x0ccb },
156 {-18, 0x0cc9 },
157 {-21, 0x0cc7 },
158};
159
160#define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t))
161
162/* Max and Min Output Power in dBm */
163#define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].dbm)
164#define OUTPUT_POWER_MAX (output_power[0].dbm)
165#define OUTPUT_POWER_UNKNOWN 0xFFFF
166
167/* Default TX Power - position in output_power[] */
168static const output_config_t *tx_power_current = &output_power[0];
169/*---------------------------------------------------------------------------*/
170static rfc_CMD_IEEE_MOD_FILT_t filter_cmd;
171/*---------------------------------------------------------------------------*/
172/*
173 * Buffers used to send commands to the RF core (generic and IEEE commands).
174 * Some of those buffers are re-usable, some are not.
175 *
176 * If you are uncertain, declare a new buffer.
177 */
178/*
179 * A buffer to send a CMD_IEEE_RX and to subsequently monitor its status
180 * Do not use this buffer for any commands other than CMD_IEEE_RX
181 */
182static uint8_t cmd_ieee_rx_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN(4);
183/*---------------------------------------------------------------------------*/
184/*
185 * The number of bytes appended at the end of an outgoing frame as a footer
186 * Currently fixed at 2 bytes for IEEE 802.15.4 compliance.
187 */
188#define CHECKSUM_LEN 2
189
190/*
191 * The maximum number of bytes this driver can accept from the MAC layer for
192 * transmission or will deliver to the MAC layer after reception. Includes
193 * the MAC header and payload, but not the FCS.
194 */
195#define MAX_PAYLOAD_LEN (127 - CHECKSUM_LEN)
196/*---------------------------------------------------------------------------*/
197#define DATA_ENTRY_LENSZ_NONE 0
198#define DATA_ENTRY_LENSZ_BYTE 1
199#define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
200
201/* The size of the metadata (excluding the packet length field) */
202#define RX_BUF_METADATA_SIZE \
203 (2 * RF_CORE_RX_BUF_INCLUDE_CRC \
204 + RF_CORE_RX_BUF_INCLUDE_RSSI \
205 + RF_CORE_RX_BUF_INCLUDE_CORR \
206 + 4 * RF_CORE_RX_BUF_INCLUDE_TIMESTAMP)
207
208/* The offset of the packet length in a rx buffer */
209#define RX_BUF_LENGTH_OFFSET sizeof(rfc_dataEntry_t)
210/* The offset of the packet data in a rx buffer */
211#define RX_BUF_DATA_OFFSET (RX_BUF_LENGTH_OFFSET + 1)
212
213#define RX_BUF_SIZE (RX_BUF_DATA_OFFSET \
214 + MAX_PAYLOAD_LEN \
215 + RX_BUF_METADATA_SIZE)
216
217/* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */
218static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN(4);
219static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4);
220static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN(4);
221static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN(4);
222
223/* The RX Data Queue */
224static dataQueue_t rx_data_queue = { 0 };
225
226/* Receive entry pointer to keep track of read items */
227volatile static uint8_t *rx_read_entry;
228/*---------------------------------------------------------------------------*/
229/* The outgoing frame buffer */
230#define TX_BUF_PAYLOAD_LEN 180
231#define TX_BUF_HDR_LEN 2
232
233static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4);
234/*---------------------------------------------------------------------------*/
235#ifdef IEEE_MODE_CONF_BOARD_OVERRIDES
236#define IEEE_MODE_BOARD_OVERRIDES IEEE_MODE_CONF_BOARD_OVERRIDES
237#else
238#define IEEE_MODE_BOARD_OVERRIDES
239#endif
240/*---------------------------------------------------------------------------*/
241/* Overrides for IEEE 802.15.4, differential mode */
242static uint32_t ieee_overrides[] = {
243 0x00354038, /* Synth: Set RTRIM (POTAILRESTRIM) to 5 */
244 0x4001402D, /* Synth: Correct CKVD latency setting (address) */
245 0x00608402, /* Synth: Correct CKVD latency setting (value) */
246// 0x4001405D, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (address) */
247// 0x1801F800, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (value) */
248 0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */
249 0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */
250 0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */
251 0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */
252 0x002B50DC, /* Adjust AGC DC filter */
253 0x05000243, /* Increase synth programming timeout */
254 0x002082C3, /* Increase synth programming timeout */
255 IEEE_MODE_BOARD_OVERRIDES
256 0xFFFFFFFF, /* End of override list */
257};
258/*---------------------------------------------------------------------------*/
259static int on(void);
260static int off(void);
261/*---------------------------------------------------------------------------*/
262/**
263 * \brief Checks whether the RFC domain is accessible and the RFC is in IEEE RX
264 * \return 1: RFC in RX mode (and therefore accessible too). 0 otherwise
265 */
266static uint8_t
268{
269 if(!rf_core_is_accessible()) {
270 return 0;
271 }
272
273 return RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_CORE_RADIO_OP_STATUS_ACTIVE;
274}
275/*---------------------------------------------------------------------------*/
276/**
277 * \brief Check the RF's TX status
278 * \return 1 RF is transmitting
279 * \return 0 RF is not transmitting
280 *
281 * TX mode may be triggered either by a CMD_IEEE_TX or by the automatic
282 * transmission of an ACK frame.
283 */
284static uint8_t
286{
287 uint32_t cmd_status;
288 rfc_CMD_IEEE_CCA_REQ_t cmd;
289
290 /* If we are off, we are not in TX */
291 if(!rf_core_is_accessible()) {
292 return 0;
293 }
294
295 memset(&cmd, 0x00, sizeof(cmd));
296
297 cmd.commandNo = CMD_IEEE_CCA_REQ;
298
299 if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
300 PRINTF("transmitting: CMDSTA=0x%08lx\n", cmd_status);
301 return 0;
302 }
303
304 if((cmd.currentRssi == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN) &&
305 (cmd.ccaInfo.ccaEnergy == RF_CORE_CMD_CCA_REQ_CCA_STATE_BUSY)) {
306 return 1;
307 }
308
309 return 0;
310}
311/*---------------------------------------------------------------------------*/
312/**
313 * \brief Returns CCA information
314 * \return RF_CORE_GET_CCA_INFO_ERROR if the RF was not on
315 * \return On success, the return value is formatted as per the ccaInfo field
316 * of CMD_IEEE_CCA_REQ
317 *
318 * It is the caller's responsibility to make sure the RF is on. This function
319 * will return RF_CORE_GET_CCA_INFO_ERROR if the RF is off
320 *
321 * This function will in fact wait for a valid CCA state
322 */
323static uint8_t
325{
326 uint32_t cmd_status;
327 rfc_CMD_IEEE_CCA_REQ_t cmd;
328
329 if(!rf_is_on()) {
330 PRINTF("get_cca_info: Not on\n");
331 return RF_CORE_GET_CCA_INFO_ERROR;
332 }
333
334 memset(&cmd, 0x00, sizeof(cmd));
335 cmd.ccaInfo.ccaState = RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID;
336
337 while(cmd.ccaInfo.ccaState == RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID) {
338 memset(&cmd, 0x00, sizeof(cmd));
339 cmd.commandNo = CMD_IEEE_CCA_REQ;
340
341 if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
342 PRINTF("get_cca_info: CMDSTA=0x%08lx\n", cmd_status);
343
344 return RF_CORE_GET_CCA_INFO_ERROR;
345 }
346 }
347
348 /* We have a valid CCA state. Return the CCA Info */
349 return *((uint8_t *)&cmd.ccaInfo);
350}
351/*---------------------------------------------------------------------------*/
352/**
353 * \brief Reads the current signal strength (RSSI)
354 * \return The current RSSI in dBm or CMD_GET_RSSI_UNKNOWN
355 *
356 * This function reads the current RSSI on the currently configured
357 * channel.
358 */
359static radio_value_t
361{
362 uint32_t cmd_status;
363 uint8_t was_off = 0;
364 rfc_CMD_IEEE_CCA_REQ_t cmd;
365
366 /* If we are off, turn on first */
367 if(!rf_is_on()) {
368 was_off = 1;
369 if(on() != RF_CORE_CMD_OK) {
370 PRINTF("get_rssi: on() failed\n");
371 return RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
372 }
373 }
374
375 memset(&cmd, 0x00, sizeof(cmd));
376 cmd.ccaInfo.ccaEnergy = RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID;
377
378 while(cmd.ccaInfo.ccaEnergy == RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID) {
379 memset(&cmd, 0x00, sizeof(cmd));
380 cmd.commandNo = CMD_IEEE_CCA_REQ;
381
382 if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
383 PRINTF("get_rssi: CMDSTA=0x%08lx\n", cmd_status);
384
385 /* Make sure to return RSSI unknown */
386 cmd.currentRssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
387 break;
388 }
389 }
390
391 /* If we were off, turn back off */
392 if(was_off) {
393 off();
394 }
395
396 return cmd.currentRssi;
397}
398/*---------------------------------------------------------------------------*/
399/* Returns the current TX power in dBm */
400static radio_value_t
401get_tx_power(void)
402{
403 return tx_power_current->dbm;
404}
405/*---------------------------------------------------------------------------*/
406/*
407 * Set TX power to 'at least' power dBm
408 * This works with a lookup table. If the value of 'power' does not exist in
409 * the lookup table, TXPOWER will be set to the immediately higher available
410 * value
411 */
412static void
413set_tx_power(radio_value_t power)
414{
415 uint32_t cmd_status;
416 int i;
417 rfc_CMD_SET_TX_POWER_t cmd;
418
419 /* First, find the correct setting and save it */
420 for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) {
421 if(power <= output_power[i].dbm) {
422 tx_power_current = &output_power[i];
423 break;
424 }
425 }
426
427 /*
428 * If the core is not accessible, the new setting will be applied next
429 * time we send CMD_RADIO_SETUP, so we don't need to do anything further.
430 * If the core is accessible, we can apply the new setting immediately with
431 * CMD_SET_TX_POWER
432 */
433 if(rf_core_is_accessible() == RF_CORE_NOT_ACCESSIBLE) {
434 return;
435 }
436
437 memset(&cmd, 0x00, sizeof(cmd));
438 cmd.commandNo = CMD_SET_TX_POWER;
439 cmd.txPower = output_power[i].tx_power;
440
441 if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
442 PRINTF("set_tx_power: CMDSTA=0x%08lx\n", cmd_status);
443 }
444}
445/*---------------------------------------------------------------------------*/
446static uint8_t
447rf_radio_setup()
448{
449 uint32_t cmd_status;
450 rfc_CMD_RADIO_SETUP_t cmd;
451
452 rf_switch_select_path(RF_SWITCH_PATH_2_4GHZ);
453
454 /* Create radio setup command */
455 rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_RADIO_SETUP);
456
457 cmd.txPower = tx_power_current->tx_power;
458 cmd.pRegOverride = ieee_overrides;
459 cmd.config.frontEndMode = RF_CORE_RADIO_SETUP_FRONT_END_MODE;
460 cmd.config.biasMode = RF_CORE_RADIO_SETUP_BIAS_MODE;
461 cmd.mode = 1;
462
463 /* Send Radio setup to RF Core */
464 if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) != RF_CORE_CMD_OK) {
465 PRINTF("rf_radio_setup: CMD_RADIO_SETUP, CMDSTA=0x%08lx, status=0x%04x\n",
466 cmd_status, cmd.status);
467 return RF_CORE_CMD_ERROR;
468 }
469
470 /* Wait until radio setup is done */
471 if(rf_core_wait_cmd_done(&cmd) != RF_CORE_CMD_OK) {
472 PRINTF("rf_radio_setup: CMD_RADIO_SETUP wait, CMDSTA=0x%08lx, status=0x%04x\n",
473 cmd_status, cmd.status);
474 return RF_CORE_CMD_ERROR;
475 }
476
477 return RF_CORE_CMD_OK;
478}
479/*---------------------------------------------------------------------------*/
480/**
481 * \brief Set up radio in IEEE802.15.4 RX mode
482 *
483 * \return RF_CORE_CMD_OK Succeeded
484 * \return RF_CORE_CMD_ERROR Failed
485 *
486 * This function assumes that cmd_ieee_rx_buf has been previously populated
487 * with correct values. This can be done through init_rf_params (sets defaults)
488 * or through Contiki's extended RF API (set_value, set_object)
489 */
490static uint8_t
492{
493 uint32_t cmd_status;
494 int ret;
495
496 ret = rf_core_send_cmd((uint32_t)cmd_ieee_rx_buf, &cmd_status);
497
498 if(ret != RF_CORE_CMD_OK) {
499 PRINTF("rf_cmd_ieee_rx: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
500 ret, cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
501 return RF_CORE_CMD_ERROR;
502 }
503
504 RTIMER_BUSYWAIT_UNTIL(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_CORE_RADIO_OP_STATUS_ACTIVE,
505 RF_CORE_ENTER_RX_TIMEOUT);
506
507 /* Wait to enter RX */
508 if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE) {
509 PRINTF("rf_cmd_ieee_rx: CMDSTA=0x%08lx, status=0x%04x\n",
510 cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
511 return RF_CORE_CMD_ERROR;
512 }
513
514 return ret;
515}
516/*---------------------------------------------------------------------------*/
517static void
518init_rx_buffers(void)
519{
520 rfc_dataEntry_t *entry;
521
522 entry = (rfc_dataEntry_t *)rx_buf_0;
523 entry->pNextEntry = rx_buf_1;
524 entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
525 entry->length = sizeof(rx_buf_0) - sizeof(*entry);
526
527 entry = (rfc_dataEntry_t *)rx_buf_1;
528 entry->pNextEntry = rx_buf_2;
529 entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
530 entry->length = sizeof(rx_buf_0) - sizeof(*entry);
531
532 entry = (rfc_dataEntry_t *)rx_buf_2;
533 entry->pNextEntry = rx_buf_3;
534 entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
535 entry->length = sizeof(rx_buf_0) - sizeof(*entry);
536
537 entry = (rfc_dataEntry_t *)rx_buf_3;
538 entry->pNextEntry = rx_buf_0;
539 entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
540 entry->length = sizeof(rx_buf_0) - sizeof(*entry);
541}
542/*---------------------------------------------------------------------------*/
543static void
544init_rf_params(void)
545{
546 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
547
548 memset(cmd_ieee_rx_buf, 0x00, RF_CMD_BUFFER_SIZE);
549
550 cmd->commandNo = CMD_IEEE_RX;
551 cmd->status = RF_CORE_RADIO_OP_STATUS_IDLE;
552 cmd->pNextOp = NULL;
553 cmd->startTime = 0x00000000;
554 cmd->startTrigger.triggerType = TRIG_NOW;
555 cmd->condition.rule = COND_NEVER;
556 cmd->channel = IEEE802154_DEFAULT_CHANNEL;
557
558 cmd->rxConfig.bAutoFlushCrc = 1;
559 cmd->rxConfig.bAutoFlushIgn = 0;
560 cmd->rxConfig.bIncludePhyHdr = 0;
561 cmd->rxConfig.bIncludeCrc = RF_CORE_RX_BUF_INCLUDE_CRC;
562 cmd->rxConfig.bAppendRssi = RF_CORE_RX_BUF_INCLUDE_RSSI;
563 cmd->rxConfig.bAppendCorrCrc = RF_CORE_RX_BUF_INCLUDE_CORR;
564 cmd->rxConfig.bAppendSrcInd = 0;
565 cmd->rxConfig.bAppendTimestamp = RF_CORE_RX_BUF_INCLUDE_TIMESTAMP;
566
567 cmd->pRxQ = &rx_data_queue;
568 cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats;
569
570#if IEEE_MODE_PROMISCOUS
571 cmd->frameFiltOpt.frameFiltEn = 0;
572#else
573 cmd->frameFiltOpt.frameFiltEn = 1;
574#endif
575
576 cmd->frameFiltOpt.frameFiltStop = 1;
577
578#if IEEE_MODE_AUTOACK
579 cmd->frameFiltOpt.autoAckEn = 1;
580#else
581 cmd->frameFiltOpt.autoAckEn = 0;
582#endif
583
584 cmd->frameFiltOpt.slottedAckEn = 0;
585 cmd->frameFiltOpt.autoPendEn = 0;
586 cmd->frameFiltOpt.defaultPend = 0;
587 cmd->frameFiltOpt.bPendDataReqOnly = 0;
588 cmd->frameFiltOpt.bPanCoord = 0;
589 cmd->frameFiltOpt.maxFrameVersion = 2;
590 cmd->frameFiltOpt.bStrictLenFilter = 0;
591
592 /* Receive all frame types */
593 cmd->frameTypes.bAcceptFt0Beacon = 1;
594 cmd->frameTypes.bAcceptFt1Data = 1;
595 cmd->frameTypes.bAcceptFt2Ack = 1;
596 cmd->frameTypes.bAcceptFt3MacCmd = 1;
597 cmd->frameTypes.bAcceptFt4Reserved = 1;
598 cmd->frameTypes.bAcceptFt5Reserved = 1;
599 cmd->frameTypes.bAcceptFt6Reserved = 1;
600 cmd->frameTypes.bAcceptFt7Reserved = 1;
601
602 /* Configure CCA settings */
603 cmd->ccaOpt.ccaEnEnergy = 1;
604 cmd->ccaOpt.ccaEnCorr = 1;
605 cmd->ccaOpt.ccaEnSync = 1;
606 cmd->ccaOpt.ccaCorrOp = 1;
607 cmd->ccaOpt.ccaSyncOp = 0;
608 cmd->ccaOpt.ccaCorrThr = 3;
609
610 cmd->ccaRssiThr = IEEE_MODE_RSSI_THRESHOLD;
611
612 cmd->numExtEntries = 0x00;
613 cmd->numShortEntries = 0x00;
614 cmd->pExtEntryList = 0;
615 cmd->pShortEntryList = 0;
616
617 cmd->endTrigger.triggerType = TRIG_NEVER;
618 cmd->endTime = 0x00000000;
619
620 /* set address filter command */
621 filter_cmd.commandNo = CMD_IEEE_MOD_FILT;
622 memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt, sizeof(cmd->frameFiltOpt));
623 memcpy(&filter_cmd.newFrameTypes, &cmd->frameTypes, sizeof(cmd->frameTypes));
624}
625/*---------------------------------------------------------------------------*/
626static int
627rx_on(void)
628{
629 int ret;
630
631 /* Get status of running IEEE_RX (if any) */
632 if(rf_is_on()) {
633 PRINTF("rx_on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
634 RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
635 return RF_CORE_CMD_OK;
636 }
637
638 /* Put CPE in RX using the currently configured parameters */
639 ret = rf_cmd_ieee_rx();
640
641 if(ret) {
642 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
643 }
644
645 return ret;
646}
647/*---------------------------------------------------------------------------*/
648static int
649rx_off(void)
650{
651 uint32_t cmd_status;
652 int ret;
653
654 /* If we are off, do nothing */
655 if(!rf_is_on()) {
656 return RF_CORE_CMD_OK;
657 }
658
659 /* Wait for ongoing ACK TX to finish */
660 RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
661
662 /* Send a CMD_ABORT command to RF Core */
663 if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
664 PRINTF("RX off: CMD_ABORT status=0x%08lx\n", cmd_status);
665 /* Continue nonetheless */
666 }
667
668 RTIMER_BUSYWAIT_UNTIL(!rf_is_on(), RF_CORE_TURN_OFF_TIMEOUT);
669
670 if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED ||
671 RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) {
672 /* Stopped gracefully */
673 ret = RF_CORE_CMD_OK;
674 } else {
675 PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
676 ret = RF_CORE_CMD_ERROR;
677 }
678
679 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
680
681 return ret;
682}
683/*---------------------------------------------------------------------------*/
684static uint8_t
685request(void)
686{
687 /*
688 * We rely on the RDC layer to turn us on and off. Thus, if we are on we
689 * will only allow sleep, standby otherwise
690 */
691 if(rf_is_on()) {
692 return LPM_MODE_SLEEP;
693 }
694
695 return LPM_MODE_MAX_SUPPORTED;
696}
697/*---------------------------------------------------------------------------*/
698LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
699/*---------------------------------------------------------------------------*/
700static void
701soft_off(void)
702{
703 uint32_t cmd_status;
704 volatile rfc_radioOp_t *cmd = rf_core_get_last_radio_op();
705
706 if(!rf_core_is_accessible()) {
707 return;
708 }
709
710 PRINTF("soft_off: Aborting 0x%04x, Status=0x%04x\n", cmd->commandNo,
711 cmd->status);
712
713 /* Send a CMD_ABORT command to RF Core */
714 if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
715 PRINTF("soft_off: CMD_ABORT status=0x%08lx\n", cmd_status);
716 return;
717 }
718
719 RTIMER_BUSYWAIT_UNTIL((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) !=
720 RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING, RF_CORE_TURN_OFF_TIMEOUT);
721}
722/*---------------------------------------------------------------------------*/
723static uint8_t
724soft_on(void)
725{
726 if(rf_radio_setup() != RF_CORE_CMD_OK) {
727 PRINTF("on: radio_setup() failed\n");
728 return RF_CORE_CMD_ERROR;
729 }
730
731 return rx_on();
732}
733/*---------------------------------------------------------------------------*/
734static const rf_core_primary_mode_t mode_ieee = {
735 soft_off,
736 soft_on,
737 rf_is_on,
738 RAT_TIMESTAMP_OFFSET_2_4_GHZ
739};
740/*---------------------------------------------------------------------------*/
741static int
742init(void)
743{
744 lpm_register_module(&cc26xx_rf_lpm_module);
745
747
748 /* Initialise RX buffers */
749 memset(rx_buf_0, 0, RX_BUF_SIZE);
750 memset(rx_buf_1, 0, RX_BUF_SIZE);
751 memset(rx_buf_2, 0, RX_BUF_SIZE);
752 memset(rx_buf_3, 0, RX_BUF_SIZE);
753
754 /* Set of RF Core data queue. Circular buffer, no last entry */
755 rx_data_queue.pCurrEntry = rx_buf_0;
756
757 rx_data_queue.pLastEntry = NULL;
758
759 /* Initialize current read pointer to first element (used in ISR) */
760 rx_read_entry = rx_buf_0;
761
762 /* Populate the RF parameters data structure with default values */
763 init_rf_params();
764
765 if(on() != RF_CORE_CMD_OK) {
766 PRINTF("init: on() failed\n");
767 return RF_CORE_CMD_ERROR;
768 }
769
770 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
771
773
775
776 process_start(&rf_core_process, NULL);
777 return 1;
778}
779/*---------------------------------------------------------------------------*/
780static int
781prepare(const void *payload, unsigned short payload_len)
782{
783 if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > MAX_PAYLOAD_LEN) {
784 return RADIO_TX_ERR;
785 }
786
787 memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, payload_len);
788 return 0;
789}
790/*---------------------------------------------------------------------------*/
791static int
792transmit(unsigned short transmit_len)
793{
794 int ret;
795 uint8_t was_off = 0;
796 uint32_t cmd_status;
797 uint16_t stat;
798 uint8_t tx_active = 0;
799 rtimer_clock_t t0;
800 volatile rfc_CMD_IEEE_TX_t cmd;
801
802 if(transmit_len > MAX_PAYLOAD_LEN) {
803 PRINTF("transmit: too long\n");
804 return RADIO_TX_ERR;
805 }
806
807 if(!rf_is_on()) {
808 was_off = 1;
809 if(on() != RF_CORE_CMD_OK) {
810 PRINTF("transmit: on() failed\n");
811 return RADIO_TX_ERR;
812 }
813 }
814
815 /*
816 * We are certainly not TXing a frame as a result of CMD_IEEE_TX, but we may
817 * be in the process of TXing an ACK. In that case, wait for the TX to finish
818 * or return after approx TX_WAIT_TIMEOUT
819 */
820 t0 = RTIMER_NOW();
821
822 do {
823 tx_active = transmitting();
824 } while(tx_active == 1 &&
825 (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + RF_CORE_TX_TIMEOUT)));
826
827 if(tx_active) {
828 PRINTF("transmit: Already TXing and wait timed out\n");
829
830 if(was_off) {
831 off();
832 }
833
834 return RADIO_TX_COLLISION;
835 }
836
837 /* Send the CMD_IEEE_TX command */
838 rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_IEEE_TX);
839
840 cmd.payloadLen = transmit_len;
841 cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN];
842
843 cmd.startTime = 0;
844 cmd.startTrigger.triggerType = TRIG_NOW;
845
846 /* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */
848
849 ret = rf_core_send_cmd((uint32_t)&cmd, &cmd_status);
850
851 if(ret) {
852 /* If we enter here, TX actually started */
853 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
854
855 /* Idle away while the command is running */
856 while((cmd.status & RF_CORE_RADIO_OP_MASKED_STATUS)
857 == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
858 /* Note: for now sleeping while Tx'ing in polling mode is disabled.
859 * To enable it:
860 * 1) make the `lpm_sleep()` call here unconditional;
861 * 2) change the radio ISR priority to allow radio ISR to interrupt rtimer ISR.
862 */
863 if(!rf_core_poll_mode) {
864 lpm_sleep();
865 }
866 }
867
868 stat = cmd.status;
869
870 if(stat == RF_CORE_RADIO_OP_STATUS_IEEE_DONE_OK) {
871 /* Sent OK */
872 ret = RADIO_TX_OK;
873 } else {
874 /* Operation completed, but frame was not sent */
875 PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", ret,
876 cmd_status, stat);
877 ret = RADIO_TX_ERR;
878 }
879 } else {
880 /* Failure sending the CMD_IEEE_TX command */
881 PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
882 ret, cmd_status, cmd.status);
883
884 ret = RADIO_TX_ERR;
885 }
886
887 /*
888 * Update ENERGEST state here, before a potential call to off(), which
889 * will correctly update it if required.
890 */
891 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
892
893 /*
894 * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
895 * except when we are transmitting
896 */
898
899 if(was_off) {
900 off();
901 }
902
903 return ret;
904}
905/*---------------------------------------------------------------------------*/
906static int
907send(const void *payload, unsigned short payload_len)
908{
909 prepare(payload, payload_len);
910 return transmit(payload_len);
911}
912/*---------------------------------------------------------------------------*/
913static void
914release_data_entry(void)
915{
916 rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
917
918 /* Clear the length byte */
919 rx_read_entry[8] = 0;
920
921 /* Set status to 0 "Pending" in element */
922 entry->status = DATA_ENTRY_STATUS_PENDING;
923 rx_read_entry = entry->pNextEntry;
924}
925/*---------------------------------------------------------------------------*/
926static int
927read_frame(void *buf, unsigned short buf_len)
928{
929 int len = 0;
930 rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
931 uint32_t rat_timestamp;
932
933 /* wait for entry to become finished */
934 rtimer_clock_t t0 = RTIMER_NOW();
935 while(entry->status == DATA_ENTRY_STATUS_BUSY
936 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + RADIO_FRAME_DURATION(MAX_PAYLOAD_LEN)));
937
938 if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
939 /* No available data */
940 return 0;
941 }
942
943 len = rx_read_entry[RX_BUF_LENGTH_OFFSET];
944 if(len <= RX_BUF_METADATA_SIZE) {
945 PRINTF("RF: too short!");
946
947 release_data_entry();
948 return 0;
949 }
950
951 len -= RX_BUF_METADATA_SIZE;
952 if(len > buf_len) {
953 PRINTF("RF: too long\n");
954
955 release_data_entry();
956 return 0;
957 }
958
959 memcpy(buf, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET, len);
960
961 rf_core_last_rssi = (int8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len];
962 rf_core_last_corr_lqi = (uint8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 1] & STATUS_CORRELATION;
963
964 /* get the timestamp */
965 memcpy(&rat_timestamp, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET + len + 2, 4);
966
967 rf_core_last_packet_timestamp = rf_core_convert_rat_to_rtimer(rat_timestamp);
968
969 if(!rf_core_poll_mode) {
970 /* Not in poll mode: packetbuf should not be accessed in interrupt context.
971 * In poll mode, the last packet RSSI and link quality can be obtained through
972 * RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
973 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf_core_last_rssi);
974 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf_core_last_corr_lqi);
975 }
976
977 release_data_entry();
978
979 return len;
980}
981/*---------------------------------------------------------------------------*/
982static int
983channel_clear(void)
984{
985 uint8_t was_off = 0;
986 uint8_t cca_info;
987 int ret = RF_CORE_CCA_CLEAR;
988
989 /*
990 * If we are in the middle of a BLE operation, we got called by ContikiMAC
991 * from within an interrupt context. Indicate a clear channel
992 */
993 if(rf_ble_is_active() == RF_BLE_ACTIVE) {
994 PRINTF("channel_clear: Interrupt context but BLE in progress\n");
995 return RF_CORE_CCA_CLEAR;
996 }
997
998 if(rf_is_on()) {
999 /*
1000 * Wait for potential leftover ACK still being sent.
1001 * Strictly speaking, if we are TXing an ACK then the channel is not clear.
1002 * However, channel_clear is only ever called to determine whether there is
1003 * someone else's packet in the air, not ours.
1004 *
1005 * We could probably even simply return that the channel is clear
1006 */
1007 RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
1008 } else {
1009 was_off = 1;
1010 if(on() != RF_CORE_CMD_OK) {
1011 PRINTF("channel_clear: on() failed\n");
1012 if(was_off) {
1013 off();
1014 }
1015 return RF_CORE_CCA_CLEAR;
1016 }
1017 }
1018
1019 cca_info = get_cca_info();
1020
1021 if(cca_info == RF_CORE_GET_CCA_INFO_ERROR) {
1022 PRINTF("channel_clear: CCA error\n");
1023 ret = RF_CORE_CCA_CLEAR;
1024 } else {
1025 /*
1026 * cca_info bits 1:0 - ccaStatus
1027 * Return 1 (clear) if idle or invalid.
1028 */
1029 ret = (cca_info & 0x03) != RF_CORE_CMD_CCA_REQ_CCA_STATE_BUSY;
1030 }
1031
1032 if(was_off) {
1033 off();
1034 }
1035
1036 return ret;
1037}
1038/*---------------------------------------------------------------------------*/
1039static int
1040receiving_packet(void)
1041{
1042 uint8_t cca_info;
1043
1044 /*
1045 * If we are in the middle of a BLE operation, we got called by ContikiMAC
1046 * from within an interrupt context. We are not receiving
1047 */
1048 if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1049 PRINTF("receiving_packet: Interrupt context but BLE in progress\n");
1050 return 0;
1051 }
1052
1053 /* If we are off, we are not receiving */
1054 if(!rf_is_on()) {
1055 PRINTF("receiving_packet: We were off\n");
1056 return 0;
1057 }
1058
1059 /* If we are transmitting (can only be an ACK here), we are not receiving */
1060 if(transmitting()) {
1061 PRINTF("receiving_packet: We were TXing\n");
1062 return 0;
1063 }
1064
1065 cca_info = get_cca_info();
1066
1067 /* If we can't read CCA info, return "not receiving" */
1068 if(cca_info == RF_CORE_GET_CCA_INFO_ERROR) {
1069 return 0;
1070 }
1071
1072 /* If sync has been seen, return 1 (receiving) */
1073 if(cca_info & RF_CORE_CMD_CCA_REQ_CCA_SYNC_BUSY) {
1074 return 1;
1075 }
1076
1077 return 0;
1078}
1079/*---------------------------------------------------------------------------*/
1080static int
1081pending_packet(void)
1082{
1083 volatile rfc_dataEntry_t *entry = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
1084 int rv = 0;
1085
1086 /* Go through all RX buffers and check their status */
1087 do {
1088 if(entry->status == DATA_ENTRY_STATUS_FINISHED
1089 || entry->status == DATA_ENTRY_STATUS_BUSY) {
1090 rv = 1;
1091 if(!rf_core_poll_mode) {
1092 process_poll(&rf_core_process);
1093 }
1094 }
1095
1096 entry = (rfc_dataEntry_t *)entry->pNextEntry;
1097 } while(entry != (rfc_dataEntry_t *)rx_data_queue.pCurrEntry);
1098
1099 /* If we didn't find an entry at status finished, no frames are pending */
1100 return rv;
1101}
1102/*---------------------------------------------------------------------------*/
1103static int
1104on(void)
1105{
1106 /*
1107 * If we are in the middle of a BLE operation, we got called by ContikiMAC
1108 * from within an interrupt context. Abort, but pretend everything is OK.
1109 */
1110 if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1111 PRINTF("on: Interrupt context but BLE in progress\n");
1112 return RF_CORE_CMD_OK;
1113 }
1114
1115 /*
1116 * Request the HF XOSC as the source for the HF clock. Needed before we can
1117 * use the FS. This will only request, it will _not_ perform the switch.
1118 */
1120
1121 if(rf_is_on()) {
1122 PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
1123 RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
1124 return RF_CORE_CMD_OK;
1125 }
1126
1127 init_rx_buffers();
1128
1129 /*
1130 * Trigger a switch to the XOSC, so that we can subsequently use the RF FS
1131 * This will block until the XOSC is actually ready, but give how we
1132 * requested it early on, this won't be too long a wait.
1133 * This should be done before starting the RAT.
1134 */
1136
1137 if(rf_core_boot() != RF_CORE_CMD_OK) {
1138 PRINTF("on: rf_core_boot() failed\n");
1139 return RF_CORE_CMD_ERROR;
1140 }
1141
1143
1144 if(rf_radio_setup() != RF_CORE_CMD_OK) {
1145 PRINTF("on: radio_setup() failed\n");
1146 return RF_CORE_CMD_ERROR;
1147 }
1148
1149 return rx_on();
1150}
1151/*---------------------------------------------------------------------------*/
1152static int
1153off(void)
1154{
1155 /*
1156 * If we are in the middle of a BLE operation, we got called by ContikiMAC
1157 * from within an interrupt context. Abort, but pretend everything is OK.
1158 */
1159 if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1160 PRINTF("off: Interrupt context but BLE in progress\n");
1161 return RF_CORE_CMD_OK;
1162 }
1163
1164 RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
1165
1166 /* stopping the rx explicitly results in lower sleep-mode power usage */
1167 rx_off();
1169
1170 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
1171
1172#if !CC2650_FAST_RADIO_STARTUP
1173 /* Switch HF clock source to the RCOSC to preserve power.
1174 * This must be done after stopping RAT.
1175 */
1177#endif
1178
1179 /* We pulled the plug, so we need to restore the status manually */
1180 ((rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
1181
1182 /*
1183 * Just in case there was an ongoing RX (which started after we begun the
1184 * shutdown sequence), we don't want to leave the buffer in state == ongoing
1185 */
1186 if(((rfc_dataEntry_t *)rx_buf_0)->status == DATA_ENTRY_STATUS_BUSY) {
1187 ((rfc_dataEntry_t *)rx_buf_0)->status = DATA_ENTRY_STATUS_PENDING;
1188 }
1189 if(((rfc_dataEntry_t *)rx_buf_1)->status == DATA_ENTRY_STATUS_BUSY) {
1190 ((rfc_dataEntry_t *)rx_buf_1)->status = DATA_ENTRY_STATUS_PENDING;
1191 }
1192 if(((rfc_dataEntry_t *)rx_buf_2)->status == DATA_ENTRY_STATUS_BUSY) {
1193 ((rfc_dataEntry_t *)rx_buf_2)->status = DATA_ENTRY_STATUS_PENDING;
1194 }
1195 if(((rfc_dataEntry_t *)rx_buf_3)->status == DATA_ENTRY_STATUS_BUSY) {
1196 ((rfc_dataEntry_t *)rx_buf_3)->status = DATA_ENTRY_STATUS_PENDING;
1197 }
1198
1199 return RF_CORE_CMD_OK;
1200}
1201/*---------------------------------------------------------------------------*/
1202/* Enable or disable CCA before sending */
1203static radio_result_t
1204set_send_on_cca(uint8_t enable)
1205{
1206 if(enable) {
1207 /* this driver does not have support for CCA on Tx */
1209 }
1210 return RADIO_RESULT_OK;
1211}
1212/*---------------------------------------------------------------------------*/
1213static radio_result_t
1214get_value(radio_param_t param, radio_value_t *value)
1215{
1216 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1217
1218 if(!value) {
1220 }
1221
1222 switch(param) {
1224 /* On / off */
1226 return RADIO_RESULT_OK;
1228 *value = (radio_value_t)cmd->channel;
1229 return RADIO_RESULT_OK;
1230 case RADIO_PARAM_PAN_ID:
1231 *value = (radio_value_t)cmd->localPanID;
1232 return RADIO_RESULT_OK;
1234 *value = (radio_value_t)cmd->localShortAddr;
1235 return RADIO_RESULT_OK;
1237 *value = 0;
1238 if(cmd->frameFiltOpt.frameFiltEn) {
1240 }
1241 if(cmd->frameFiltOpt.autoAckEn) {
1242 *value |= RADIO_RX_MODE_AUTOACK;
1243 }
1244 if(rf_core_poll_mode) {
1245 *value |= RADIO_RX_MODE_POLL_MODE;
1246 }
1247
1248 return RADIO_RESULT_OK;
1250 *value = 0;
1251 return RADIO_RESULT_OK;
1253 *value = get_tx_power();
1254 return RADIO_RESULT_OK;
1256 *value = cmd->ccaRssiThr;
1257 return RADIO_RESULT_OK;
1258 case RADIO_PARAM_RSSI:
1259 *value = get_rssi();
1260
1261 if(*value == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN) {
1262 return RADIO_RESULT_ERROR;
1263 } else {
1264 return RADIO_RESULT_OK;
1265 }
1267 *value = IEEE_MODE_CHANNEL_MIN;
1268 return RADIO_RESULT_OK;
1270 *value = IEEE_MODE_CHANNEL_MAX;
1271 return RADIO_RESULT_OK;
1273 *value = OUTPUT_POWER_MIN;
1274 return RADIO_RESULT_OK;
1276 *value = OUTPUT_POWER_MAX;
1277 return RADIO_RESULT_OK;
1279 *value = rf_core_last_rssi;
1280 return RADIO_RESULT_OK;
1282 *value = rf_core_last_corr_lqi;
1283 return RADIO_RESULT_OK;
1285 *value = (radio_value_t)RADIO_PHY_OVERHEAD;
1286 return RADIO_RESULT_OK;
1288 *value = (radio_value_t)RADIO_BYTE_AIR_TIME;
1289 return RADIO_RESULT_OK;
1291 *value = (radio_value_t)RADIO_DELAY_BEFORE_TX;
1292 return RADIO_RESULT_OK;
1294 *value = (radio_value_t)RADIO_DELAY_BEFORE_RX;
1295 return RADIO_RESULT_OK;
1297 *value = (radio_value_t)RADIO_DELAY_BEFORE_DETECT;
1298 return RADIO_RESULT_OK;
1299 case RADIO_CONST_MAX_PAYLOAD_LEN:
1300 *value = (radio_value_t)MAX_PAYLOAD_LEN;
1301 return RADIO_RESULT_OK;
1302 default:
1304 }
1305}
1306/*---------------------------------------------------------------------------*/
1307static radio_result_t
1308set_value(radio_param_t param, radio_value_t value)
1309{
1311 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1312 uint8_t old_poll_mode;
1313
1314 switch(param) {
1316 if(value == RADIO_POWER_MODE_ON) {
1317 if(on() != RF_CORE_CMD_OK) {
1318 PRINTF("set_value: on() failed (1)\n");
1319 return RADIO_RESULT_ERROR;
1320 }
1321 return RADIO_RESULT_OK;
1322 }
1323 if(value == RADIO_POWER_MODE_OFF) {
1324 off();
1325 return RADIO_RESULT_OK;
1326 }
1329 if(value < IEEE_MODE_CHANNEL_MIN ||
1330 value > IEEE_MODE_CHANNEL_MAX) {
1332 }
1333
1334 /* Note: this return may lead to long periods when RAT and RTC are not resynchronized */
1335 if(cmd->channel == (uint8_t)value) {
1336 /* We already have that very same channel configured.
1337 * Nothing to do here. */
1338 return RADIO_RESULT_OK;
1339 }
1340
1341 cmd->channel = (uint8_t)value;
1342 break;
1343 case RADIO_PARAM_PAN_ID:
1344 cmd->localPanID = (uint16_t)value;
1345 break;
1347 cmd->localShortAddr = (uint16_t)value;
1348 break;
1350 {
1351 if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
1354 }
1355
1356 cmd->frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0;
1357 cmd->frameFiltOpt.frameFiltStop = 1;
1358 cmd->frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0;
1359 cmd->frameFiltOpt.slottedAckEn = 0;
1360 cmd->frameFiltOpt.autoPendEn = 0;
1361 cmd->frameFiltOpt.defaultPend = 0;
1362 cmd->frameFiltOpt.bPendDataReqOnly = 0;
1363 cmd->frameFiltOpt.bPanCoord = 0;
1364 cmd->frameFiltOpt.bStrictLenFilter = 0;
1365
1366 old_poll_mode = rf_core_poll_mode;
1367 rf_core_poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
1368 if(rf_core_poll_mode == old_poll_mode) {
1369 uint32_t cmd_status;
1370
1371 /* do not turn the radio on and off, just send an update command */
1372 memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt, sizeof(cmd->frameFiltOpt));
1373
1374 if(rf_core_send_cmd((uint32_t)&filter_cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
1375 PRINTF("setting address filter failed: CMDSTA=0x%08lx\n", cmd_status);
1376 return RADIO_RESULT_ERROR;
1377 }
1378 return RADIO_RESULT_OK;
1379 }
1380 break;
1381 }
1382
1384 if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
1386 }
1387 return set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
1388
1390 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
1392 }
1393
1394 set_tx_power(value);
1395
1396 return RADIO_RESULT_OK;
1397
1399 cmd->ccaRssiThr = (int8_t)value;
1400 break;
1401
1402 default:
1404 }
1405
1406 /* If off, the new configuration will be applied the next time radio is started */
1407 if(!rf_is_on()) {
1408 return RADIO_RESULT_OK;
1409 }
1410
1411 /* If we reach here we had no errors. Apply new settings */
1412 if(rx_off() != RF_CORE_CMD_OK) {
1413 PRINTF("set_value: rx_off() failed\n");
1414 rv = RADIO_RESULT_ERROR;
1415 }
1416
1417 /* Restart the radio timer (RAT).
1418 This causes resynchronization between RAT and RTC: useful for TSCH. */
1419 if(rf_core_restart_rat() == RF_CORE_CMD_OK) {
1421 }
1422
1423 if(rx_on() != RF_CORE_CMD_OK) {
1424 PRINTF("set_value: rx_on() failed\n");
1425 rv = RADIO_RESULT_ERROR;
1426 }
1427
1428 return rv;
1429}
1430/*---------------------------------------------------------------------------*/
1431static radio_result_t
1432get_object(radio_param_t param, void *dest, size_t size)
1433{
1434 uint8_t *target;
1435 uint8_t *src;
1436 int i;
1437 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1438
1439 if(param == RADIO_PARAM_64BIT_ADDR) {
1440 if(size != 8 || !dest) {
1442 }
1443
1444 target = dest;
1445 src = (uint8_t *)(&cmd->localExtAddr);
1446
1447 for(i = 0; i < 8; i++) {
1448 target[i] = src[7 - i];
1449 }
1450
1451 return RADIO_RESULT_OK;
1452 }
1453
1455 if(size != sizeof(rtimer_clock_t) || !dest) {
1457 }
1458 *(rtimer_clock_t *)dest = rf_core_last_packet_timestamp;
1459
1460 return RADIO_RESULT_OK;
1461 }
1462
1464}
1465/*---------------------------------------------------------------------------*/
1466static radio_result_t
1467set_object(radio_param_t param, const void *src, size_t size)
1468{
1470 int i;
1471 uint8_t *dst;
1472 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1473
1474 if(param == RADIO_PARAM_64BIT_ADDR) {
1475 if(size != 8 || !src) {
1477 }
1478
1479 dst = (uint8_t *)(&cmd->localExtAddr);
1480
1481 for(i = 0; i < 8; i++) {
1482 dst[i] = ((uint8_t *)src)[7 - i];
1483 }
1484
1485 /* If off, the new configuration will be applied the next time radio is started */
1486 if(!rf_is_on()) {
1487 return RADIO_RESULT_OK;
1488 }
1489
1490 if(rx_off() != RF_CORE_CMD_OK) {
1491 PRINTF("set_object: rx_off() failed\n");
1492 rv = RADIO_RESULT_ERROR;
1493 }
1494
1495 if(rx_on() != RF_CORE_CMD_OK) {
1496 PRINTF("set_object: rx_on() failed\n");
1497 rv = RADIO_RESULT_ERROR;
1498 }
1499
1500 return rv;
1501 }
1503}
1504/*---------------------------------------------------------------------------*/
1505const struct radio_driver ieee_mode_driver = {
1506 init,
1507 prepare,
1508 transmit,
1509 send,
1510 read_frame,
1514 on,
1515 off,
1516 get_value,
1517 set_value,
1518 get_object,
1519 set_object,
1520};
1521/*---------------------------------------------------------------------------*/
1522/**
1523 * @}
1524 * @}
1525 */
Header file for the CC13xx/CC26xx UART driver.
Default definitions of C compiler quirk work-arounds.
Header file for the callback timer.
Header file for the energy estimation mechanism.
#define LPM_MODULE(n, m, s, w, l)
Declare a variable to be used in order to get notifications from LPM.
Definition: lpm.h:96
void lpm_sleep(void)
Enter sleep mode.
Definition: lpm.c:379
void lpm_register_module(lpm_registered_module_t *module)
Register a module for LPM notifications.
Definition: lpm.c:545
void oscillators_switch_to_hf_xosc(void)
Performs the switch to the XOSC.
Definition: oscillators.c:116
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
void oscillators_switch_to_hf_rc(void)
Switches MF and HF clock source to be the HF RC OSC.
Definition: oscillators.c:134
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
#define RADIO_RX_MODE_ADDRESS_FILTER
Enable address-based frame filtering.
Definition: radio.h:451
#define RADIO_RX_MODE_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition: radio.h:461
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition: radio.h:474
enum radio_result_e radio_result_t
Radio return values when setting or getting radio parameters.
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
#define RADIO_RX_MODE_AUTOACK
Enable automatic transmission of ACK frames.
Definition: radio.h:456
@ RADIO_RESULT_ERROR
An error occurred when getting/setting the parameter, but the arguments were otherwise correct.
Definition: radio.h:488
@ RADIO_RESULT_NOT_SUPPORTED
The parameter is not supported.
Definition: radio.h:481
@ RADIO_RESULT_INVALID_VALUE
The value argument was incorrect.
Definition: radio.h:482
@ RADIO_RESULT_OK
The parameter was set/read successfully.
Definition: radio.h:480
@ RADIO_PARAM_POWER_MODE
When getting the value of this parameter, the radio driver should indicate whether the radio is on or...
Definition: radio.h:119
@ RADIO_CONST_PHY_OVERHEAD
The physical layer header (PHR) + MAC layer footer (MFR) overhead in bytes.
Definition: radio.h:338
@ RADIO_PARAM_RSSI
Received signal strength indicator in dBm.
Definition: radio.h:218
@ RADIO_PARAM_LAST_PACKET_TIMESTAMP
Last packet timestamp, of type rtimer_clock_t.
Definition: radio.h:286
@ RADIO_PARAM_LAST_RSSI
The RSSI value of the last received packet.
Definition: radio.h:226
@ RADIO_CONST_BYTE_AIR_TIME
The air time of one byte in usec, e.g.
Definition: radio.h:343
@ RADIO_PARAM_RX_MODE
Radio receiver mode determines if the radio has address filter (RADIO_RX_MODE_ADDRESS_FILTER) and aut...
Definition: radio.h:173
@ RADIO_PARAM_CHANNEL
Channel used for radio communication.
Definition: radio.h:134
@ RADIO_PARAM_LAST_LINK_QUALITY
Link quality indicator of the last received packet.
Definition: radio.h:244
@ RADIO_CONST_DELAY_BEFORE_RX
The delay in usec between turning on the radio and it being actually listening (able to hear a preamb...
Definition: radio.h:355
@ RADIO_PARAM_TXPOWER
Transmission power in dBm.
Definition: radio.h:192
@ RADIO_PARAM_64BIT_ADDR
Long (64 bits) address for the radio, which is used by the address filter.
Definition: radio.h:263
@ RADIO_CONST_DELAY_BEFORE_TX
The delay in usec between a call to the radio API's transmit function and the end of SFD transmission...
Definition: radio.h:349
@ RADIO_CONST_CHANNEL_MAX
The highest radio channel number.
Definition: radio.h:316
@ RADIO_PARAM_PAN_ID
The personal area network identifier (PAN ID), which is used by the h/w frame filtering functionality...
Definition: radio.h:150
@ RADIO_PARAM_CCA_THRESHOLD
Clear channel assessment threshold in dBm.
Definition: radio.h:205
@ RADIO_CONST_TXPOWER_MIN
The minimum transmission power in dBm.
Definition: radio.h:321
@ RADIO_CONST_CHANNEL_MIN
The lowest radio channel number.
Definition: radio.h:311
@ RADIO_CONST_TXPOWER_MAX
The maximum transmission power in dBm.
Definition: radio.h:326
@ RADIO_CONST_DELAY_BEFORE_DETECT
The delay in usec between the end of SFD reception for an incoming frame and the radio API starting t...
Definition: radio.h:361
@ RADIO_PARAM_16BIT_ADDR
The short address (16 bits) for the radio, which is used by the h/w filter.
Definition: radio.h:166
@ RADIO_PARAM_TX_MODE
Radio transmission mode determines if the radio has send on CCA (RADIO_TX_MODE_SEND_ON_CCA) enabled o...
Definition: radio.h:180
@ RADIO_POWER_MODE_OFF
Radio powered off and in the lowest possible power consumption state.
Definition: radio.h:395
@ RADIO_POWER_MODE_ON
Radio powered on and able to receive frames.
Definition: radio.h:400
@ RADIO_TX_COLLISION
TX failed due to a collision.
Definition: radio.h:511
@ RADIO_TX_ERR
An error occurred during transmission.
Definition: radio.h:506
@ RADIO_TX_OK
TX was successful and where an ACK was requested one was received.
Definition: radio.h:498
uint8_t rf_ble_is_active()
Check whether the BLE beacond is currently active.
Definition: rf-ble.c:262
#define RF_RADIO_OP_GET_STATUS(a)
Returns the current status of a running Radio Op command.
Definition: ieee-mode.c:133
static radio_value_t get_rssi(void)
Reads the current signal strength (RSSI)
Definition: ieee-mode.c:360
static uint8_t transmitting(void)
Check the RF's TX status.
Definition: ieee-mode.c:285
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:267
static uint8_t rf_cmd_ieee_rx()
Set up radio in IEEE802.15.4 RX mode.
Definition: ieee-mode.c:491
static uint8_t get_cca_info(void)
Returns CCA information.
Definition: ieee-mode.c:324
void rf_core_cmd_done_dis(void)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
Definition: rf-core.c:540
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:553
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
Definition: rf-core.c:385
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
Definition: rf-core.c:154
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
Definition: rf-core.c:145
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
Definition: rf-core.c:547
uint8_t rf_core_boot()
Boot the RF Core.
Definition: rf-core.c:451
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
Definition: rf-core.c:423
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
Definition: rf-core.c:226
uint32_t rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
Convert from RAT timestamp to rtimer ticks.
Definition: rf-core.c:665
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
Definition: rf-core.c:526
uint8_t rf_core_restart_rat(void)
Restart the CM0 RAT.
Definition: rf-core.c:473
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
Definition: rf-core.c:562
void rf_core_setup_interrupts(void)
Setup RF core interrupts.
Definition: rf-core.c:492
uint8_t rf_core_rat_init(void)
Initialize the RAT to RTC conversion machinery.
Definition: rf-core.c:590
uint8_t rf_core_check_rat_overflow(void)
Check if RAT overflow has occured and increment the overflow counter if so.
Definition: rf-core.c:601
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
Header file for the link-layer address representation.
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
Definition: mac.h:52
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the CC13xx/CC26xx oscillator control.
Header file for the Packet buffer (packetbuf) management.
Header file for the radio API.
Header file for the CC13xx/CC26xx BLE driver.
Header file for the CC13xx/CC26xx RF core driver.
Header file with definitions related to RF switch support.
Header file for the real-time timer module.
The structure of a Contiki-NG radio device driver.
Definition: radio.h:534
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:770
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:580
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:756
int(* off)(void)
Turn the radio off.
Definition: radio.h:729
int(* init)(void)
Initialise the radio hardware.
Definition: radio.h:555
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:631
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:684
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:787
int(* on)(void)
Turn the radio on.
Definition: radio.h:711
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:619
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver's buffers.
Definition: radio.h:697
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:741
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:672
A data strcuture representing the radio's primary mode of operation.
Definition: rf-core.h:125
Header file with macros which rename TI CC26xxware functions.