Contiki-NG
prop-mode.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, 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-prop
33 * @{
34 *
35 * \file
36 * Implementation of the CC13xx prop mode NETSTACK_RADIO driver
37 */
38/*---------------------------------------------------------------------------*/
39#include "contiki.h"
40#include "dev/radio.h"
41#include "dev/cc26xx-uart.h"
42#include "dev/oscillators.h"
43#include "dev/watchdog.h"
44#include "net/packetbuf.h"
45#include "net/netstack.h"
46#include "sys/energest.h"
47#include "sys/clock.h"
48#include "sys/critical.h"
49#include "sys/rtimer.h"
50#include "sys/cc.h"
51#include "lpm.h"
52#include "ti-lib.h"
53#include "rf-core/rf-core.h"
54#include "rf-core/rf-switch.h"
55#include "rf-core/rf-ble.h"
56#include "rf-core/prop-mode.h"
57#include "rf-core/dot-15-4g.h"
58/*---------------------------------------------------------------------------*/
59/* RF core and RF HAL API */
60#include "hw_rfc_dbell.h"
61#include "hw_rfc_pwr.h"
62/*---------------------------------------------------------------------------*/
63/* RF Core Mailbox API */
64#include "driverlib/rf_mailbox.h"
65#include "driverlib/rf_common_cmd.h"
66#include "driverlib/rf_data_entry.h"
67#include "driverlib/rf_prop_mailbox.h"
68#include "driverlib/rf_prop_cmd.h"
69/*---------------------------------------------------------------------------*/
70/* CC13xxware patches */
71#include "rf_patches/rf_patch_cpe_genfsk.h"
72#include "rf_patches/rf_patch_rfe_genfsk.h"
73/*---------------------------------------------------------------------------*/
74#include "rf-core/smartrf-settings.h"
75/*---------------------------------------------------------------------------*/
76#include <stdint.h>
77#include <string.h>
78#include <stdio.h>
79#include <stdbool.h>
80/*---------------------------------------------------------------------------*/
81#define DEBUG 0
82#if DEBUG
83#define PRINTF(...) printf(__VA_ARGS__)
84#else
85#define PRINTF(...)
86#endif
87/*---------------------------------------------------------------------------*/
88/* Data entry status field constants */
89#define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */
90#define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */
91#define DATA_ENTRY_STATUS_BUSY 0x02 /* Ongoing r/w */
92#define DATA_ENTRY_STATUS_FINISHED 0x03 /* Free to use and to free */
93#define DATA_ENTRY_STATUS_UNFINISHED 0x04 /* Partial RX entry */
94/*---------------------------------------------------------------------------*/
95/* Data whitener. 1: Whitener, 0: No whitener */
96#ifdef PROP_MODE_CONF_DW
97#define PROP_MODE_DW PROP_MODE_CONF_DW
98#else
99#define PROP_MODE_DW 0
100#endif
101
102#ifdef PROP_MODE_CONF_USE_CRC16
103#define PROP_MODE_USE_CRC16 PROP_MODE_CONF_USE_CRC16
104#else
105#define PROP_MODE_USE_CRC16 0
106#endif
107/*---------------------------------------------------------------------------*/
108/**
109 * \brief Returns the current status of a running Radio Op command
110 * \param a A pointer with the buffer used to initiate the command
111 * \return The value of the Radio Op buffer's status field
112 *
113 * This macro can be used to e.g. return the status of a previously
114 * initiated background operation, or of an immediate command
115 */
116#define RF_RADIO_OP_GET_STATUS(a) GET_FIELD_V(a, radioOp, status)
117/*---------------------------------------------------------------------------*/
118#ifdef PROP_MODE_CONF_RSSI_THRESHOLD
119#define PROP_MODE_RSSI_THRESHOLD PROP_MODE_CONF_RSSI_THRESHOLD
120#else
121#define PROP_MODE_RSSI_THRESHOLD 0xA6
122#endif
123
124static int8_t rssi_threshold = PROP_MODE_RSSI_THRESHOLD;
125/*---------------------------------------------------------------------------*/
126#if MAC_CONF_WITH_TSCH
127static volatile rfc_dataEntry_t *packet_being_received;
128#endif
129/*---------------------------------------------------------------------------*/
130static int on(void);
131static int off(void);
132
133static rfc_propRxOutput_t rx_stats;
134/*---------------------------------------------------------------------------*/
135/* Defines and variables related to the .15.4g PHY HDR */
136#define DOT_4G_PHR_LEN 2
137
138/* PHY HDR bits */
139#define DOT_4G_PHR_CRC16 0x10
140#define DOT_4G_PHR_DW 0x08
141
142#if PROP_MODE_USE_CRC16
143/* CRC16 */
144#define DOT_4G_PHR_CRC_BIT DOT_4G_PHR_CRC16
145#define CRC_LEN 2
146#else
147/* CRC32 */
148#define DOT_4G_PHR_CRC_BIT 0
149#define CRC_LEN 4
150#endif
151
152#if PROP_MODE_DW
153#define DOT_4G_PHR_DW_BIT DOT_4G_PHR_DW
154#else
155#define DOT_4G_PHR_DW_BIT 0
156#endif
157/*---------------------------------------------------------------------------*/
158/*
159 * The maximum number of bytes this driver can accept from the MAC layer for
160 * transmission or will deliver to the MAC layer after reception. Includes
161 * the MAC header and payload, but not the CRC.
162 *
163 * Unlike typical 2.4GHz radio drivers, this driver supports the .15.4g
164 * 32-bit CRC option.
165 *
166 * This radio hardware is perfectly happy to transmit frames longer than 127
167 * bytes, which is why it's OK to end up transmitting 125 payload bytes plus
168 * a 4-byte CRC.
169 *
170 * In the future we can change this to support transmission of long frames,
171 * for example as per .15.4g, which defines 2047 as the maximum frame size.
172 * The size of the TX and RX buffers would need to be adjusted accordingly.
173 */
174#define MAX_PAYLOAD_LEN 125
175/*---------------------------------------------------------------------------*/
176/* TX power table for the 431-527MHz band */
177#ifdef PROP_MODE_CONF_TX_POWER_431_527
178#define PROP_MODE_TX_POWER_431_527 PROP_MODE_CONF_TX_POWER_431_527
179#else
180#define PROP_MODE_TX_POWER_431_527 prop_mode_tx_power_431_527
181#endif
182/*---------------------------------------------------------------------------*/
183/* TX power table for the 779-930MHz band */
184#ifdef PROP_MODE_CONF_TX_POWER_779_930
185#define PROP_MODE_TX_POWER_779_930 PROP_MODE_CONF_TX_POWER_779_930
186#else
187#define PROP_MODE_TX_POWER_779_930 prop_mode_tx_power_779_930
188#endif
189/*---------------------------------------------------------------------------*/
190/* Select power table based on the frequency band */
191#if DOT_15_4G_FREQUENCY_BAND_ID==DOT_15_4G_FREQUENCY_BAND_470
192#define TX_POWER_DRIVER PROP_MODE_TX_POWER_431_527
193#else
194#define TX_POWER_DRIVER PROP_MODE_TX_POWER_779_930
195#endif
196/*---------------------------------------------------------------------------*/
197extern const prop_mode_tx_power_config_t TX_POWER_DRIVER[];
198
199/* Max and Min Output Power in dBm */
200#define OUTPUT_POWER_MAX (TX_POWER_DRIVER[0].dbm)
201#define OUTPUT_POWER_UNKNOWN 0xFFFF
202
203/* Default TX Power - position in output_power[] */
204static const prop_mode_tx_power_config_t *tx_power_current = &TX_POWER_DRIVER[1];
205/*---------------------------------------------------------------------------*/
206#ifdef PROP_MODE_CONF_LO_DIVIDER
207#define PROP_MODE_LO_DIVIDER PROP_MODE_CONF_LO_DIVIDER
208#else
209#define PROP_MODE_LO_DIVIDER 0x05
210#endif
211/*---------------------------------------------------------------------------*/
212#ifdef PROP_MODE_CONF_RX_BUF_CNT
213#define PROP_MODE_RX_BUF_CNT PROP_MODE_CONF_RX_BUF_CNT
214#else
215#define PROP_MODE_RX_BUF_CNT 4
216#endif
217/*---------------------------------------------------------------------------*/
218#define DATA_ENTRY_LENSZ_NONE 0
219#define DATA_ENTRY_LENSZ_BYTE 1
220#define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
221
222/* The size of the metadata (excluding the packet length field) */
223#define RX_BUF_METADATA_SIZE \
224 (CRC_LEN * RF_CORE_RX_BUF_INCLUDE_CRC \
225 + RF_CORE_RX_BUF_INCLUDE_RSSI \
226 + RF_CORE_RX_BUF_INCLUDE_CORR \
227 + 4 * RF_CORE_RX_BUF_INCLUDE_TIMESTAMP)
228
229/* The offset of the packet length in a rx buffer */
230#define RX_BUF_LENGTH_OFFSET sizeof(rfc_dataEntry_t)
231/* The offset of the packet data in a rx buffer */
232#define RX_BUF_DATA_OFFSET (RX_BUF_LENGTH_OFFSET + DOT_4G_PHR_LEN)
233
234#define ALIGN_TO_4(size) (((size) + 3) & ~3)
235
236#define RX_BUF_SIZE ALIGN_TO_4(RX_BUF_DATA_OFFSET \
237 + MAX_PAYLOAD_LEN \
238 + RX_BUF_METADATA_SIZE)
239
240/*
241 * RX buffers.
242 * PROP_MODE_RX_BUF_CNT buffers of RX_BUF_SIZE bytes each. The start of each
243 * buffer must be 4-byte aligned, therefore RX_BUF_SIZE must divide by 4
244 */
245static uint8_t rx_buf[PROP_MODE_RX_BUF_CNT][RX_BUF_SIZE] CC_ALIGN(4);
246
247/* The RX Data Queue */
248static dataQueue_t rx_data_queue = { 0 };
249
250/* Receive entry pointer to keep track of read items */
251volatile static uint8_t *rx_read_entry;
252/*---------------------------------------------------------------------------*/
253/*
254 * Increasing this number causes unicast Tx immediately after broadcast Rx to have
255 * negative synchronization errors ("dr" in TSCH logs); decreasing it: the opposite.
256 */
257#define RAT_TIMESTAMP_OFFSET_SUB_GHZ USEC_TO_RADIO(160 * 6 - 240)
258/*---------------------------------------------------------------------------*/
259/* The outgoing frame buffer */
260#define TX_BUF_PAYLOAD_LEN 180
261#define TX_BUF_HDR_LEN 2
262
263static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4);
264/*---------------------------------------------------------------------------*/
265static uint8_t
266rf_is_on(void)
267{
268 if(!rf_core_is_accessible()) {
269 return 0;
270 }
271
272 return smartrf_settings_cmd_prop_rx_adv.status == RF_CORE_RADIO_OP_STATUS_ACTIVE;
273}
274/*---------------------------------------------------------------------------*/
275static uint8_t
276transmitting(void)
277{
278 return smartrf_settings_cmd_prop_tx_adv.status == RF_CORE_RADIO_OP_STATUS_ACTIVE;
279}
280/*---------------------------------------------------------------------------*/
281static radio_value_t
282get_rssi(void)
283{
284 uint32_t cmd_status;
285 int8_t rssi;
286 uint8_t attempts = 0;
287 uint8_t was_off = 0;
288 rfc_CMD_GET_RSSI_t cmd;
289
290 /* If we are off, turn on first */
291 if(!rf_is_on()) {
292 was_off = 1;
293 if(on() != RF_CORE_CMD_OK) {
294 PRINTF("get_rssi: on() failed\n");
295 return RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
296 }
297 }
298
299 rssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
300
301 while((rssi == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN || rssi == 0) && ++attempts < 10) {
302 memset(&cmd, 0x00, sizeof(cmd));
303 cmd.commandNo = CMD_GET_RSSI;
304
305 if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
306 PRINTF("get_rssi: CMDSTA=0x%08lx\n", cmd_status);
307 break;
308 } else {
309 /* Current RSSI in bits 23:16 of cmd_status */
310 rssi = (cmd_status >> 16) & 0xFF;
311 }
312 }
313
314 /* If we were off, turn back off */
315 if(was_off) {
316 off();
317 }
318
319 return rssi;
320}
321/*---------------------------------------------------------------------------*/
322static uint8_t
323get_channel(void)
324{
325 uint32_t freq_khz;
326
327 freq_khz = smartrf_settings_cmd_fs.frequency * 1000;
328
329 /*
330 * For some channels, fractFreq * 1000 / 65536 will return 324.99xx.
331 * Casting the result to uint32_t will truncate decimals resulting in the
332 * function returning channel - 1 instead of channel. Thus, we do a quick
333 * positive integer round up.
334 */
335 freq_khz += (((smartrf_settings_cmd_fs.fractFreq * 1000) + 65535) / 65536);
336
337 return (freq_khz - DOT_15_4G_CHAN0_FREQUENCY) / DOT_15_4G_CHANNEL_SPACING;
338}
339/*---------------------------------------------------------------------------*/
340static void
341set_channel(uint8_t channel)
342{
343 uint32_t new_freq;
344 uint16_t freq, frac;
345
346 new_freq = DOT_15_4G_CHAN0_FREQUENCY + (channel * DOT_15_4G_CHANNEL_SPACING);
347
348 freq = (uint16_t)(new_freq / 1000);
349 frac = (new_freq - (freq * 1000)) * 65536 / 1000;
350
351 PRINTF("set_channel: %u = 0x%04x.0x%04x (%lu)\n", channel, freq, frac,
352 new_freq);
353
354 smartrf_settings_cmd_prop_radio_div_setup.centerFreq = freq;
355 smartrf_settings_cmd_fs.frequency = freq;
356 smartrf_settings_cmd_fs.fractFreq = frac;
357}
358/*---------------------------------------------------------------------------*/
359static uint8_t
360get_tx_power_array_last_element(void)
361{
362 const prop_mode_tx_power_config_t *array = TX_POWER_DRIVER;
363 uint8_t count = 0;
364
365 while(array->tx_power != OUTPUT_POWER_UNKNOWN) {
366 count++;
367 array++;
368 }
369 return count - 1;
370}
371/*---------------------------------------------------------------------------*/
372/* Returns the current TX power in dBm */
373static radio_value_t
374get_tx_power(void)
375{
376 return tx_power_current->dbm;
377}
378/*---------------------------------------------------------------------------*/
379/*
380 * The caller must make sure to send a new CMD_PROP_RADIO_DIV_SETUP to the
381 * radio after calling this function.
382 */
383static void
384set_tx_power(radio_value_t power)
385{
386 int i;
387
388 for(i = get_tx_power_array_last_element(); i >= 0; --i) {
389 if(power <= TX_POWER_DRIVER[i].dbm) {
390 /*
391 * Merely save the value. It will be used in all subsequent usages of
392 * CMD_PROP_RADIO_DIV_SETP, including one immediately after this function
393 * has returned
394 */
395 tx_power_current = &TX_POWER_DRIVER[i];
396
397 return;
398 }
399 }
400}
401/*---------------------------------------------------------------------------*/
402static int
403prop_div_radio_setup(void)
404{
405 uint32_t cmd_status;
406 rfc_radioOp_t *cmd = (rfc_radioOp_t *)&smartrf_settings_cmd_prop_radio_div_setup;
407
408 rf_switch_select_path(RF_SWITCH_PATH_SUBGHZ);
409
410 /* Adjust loDivider depending on the selected band */
411 smartrf_settings_cmd_prop_radio_div_setup.loDivider = PROP_MODE_LO_DIVIDER;
412
413 /* Update to the correct TX power setting */
414 smartrf_settings_cmd_prop_radio_div_setup.txPower = tx_power_current->tx_power;
415
416 /* Adjust RF Front End and Bias based on the board */
417 smartrf_settings_cmd_prop_radio_div_setup.config.frontEndMode =
418 RF_CORE_PROP_FRONT_END_MODE;
419 smartrf_settings_cmd_prop_radio_div_setup.config.biasMode =
420 RF_CORE_PROP_BIAS_MODE;
421
422 /* Send Radio setup to RF Core */
423 if(rf_core_send_cmd((uint32_t)cmd, &cmd_status) != RF_CORE_CMD_OK) {
424 PRINTF("prop_div_radio_setup: DIV_SETUP, CMDSTA=0x%08lx, status=0x%04x\n",
425 cmd_status, cmd->status);
426 return RF_CORE_CMD_ERROR;
427 }
428
429 /* Wait until radio setup is done */
430 if(rf_core_wait_cmd_done(cmd) != RF_CORE_CMD_OK) {
431 PRINTF("prop_div_radio_setup: DIV_SETUP wait, CMDSTA=0x%08lx,"
432 "status=0x%04x\n", cmd_status, cmd->status);
433 return RF_CORE_CMD_ERROR;
434 }
435
436 return RF_CORE_CMD_OK;
437}
438/*---------------------------------------------------------------------------*/
439static uint8_t
440rf_cmd_prop_rx()
441{
442 uint32_t cmd_status;
443 volatile rfc_CMD_PROP_RX_ADV_t *cmd_rx_adv;
444 int ret;
445
446 cmd_rx_adv = (rfc_CMD_PROP_RX_ADV_t *)&smartrf_settings_cmd_prop_rx_adv;
447 cmd_rx_adv->status = RF_CORE_RADIO_OP_STATUS_IDLE;
448
449 cmd_rx_adv->rxConf.bIncludeCrc = RF_CORE_RX_BUF_INCLUDE_CRC;
450 cmd_rx_adv->rxConf.bAppendRssi = RF_CORE_RX_BUF_INCLUDE_RSSI;
451 cmd_rx_adv->rxConf.bAppendTimestamp = RF_CORE_RX_BUF_INCLUDE_TIMESTAMP;
452 cmd_rx_adv->rxConf.bAppendStatus = RF_CORE_RX_BUF_INCLUDE_CORR;
453
454 /*
455 * Set the max Packet length. This is for the payload only.
456 */
457 cmd_rx_adv->maxPktLen = RADIO_PHY_OVERHEAD + MAX_PAYLOAD_LEN;
458
459 ret = rf_core_send_cmd((uint32_t)cmd_rx_adv, &cmd_status);
460
461 if(ret != RF_CORE_CMD_OK) {
462 PRINTF("rf_cmd_prop_rx: send_cmd ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
463 ret, cmd_status, cmd_rx_adv->status);
464 return RF_CORE_CMD_ERROR;
465 }
466
467 RTIMER_BUSYWAIT_UNTIL(cmd_rx_adv->status == RF_CORE_RADIO_OP_STATUS_ACTIVE,
468 RF_CORE_ENTER_RX_TIMEOUT);
469
470 /* Wait to enter RX */
471 if(cmd_rx_adv->status != RF_CORE_RADIO_OP_STATUS_ACTIVE) {
472 PRINTF("rf_cmd_prop_rx: CMDSTA=0x%08lx, status=0x%04x\n",
473 cmd_status, cmd_rx_adv->status);
474 return RF_CORE_CMD_ERROR;
475 }
476
477 return ret;
478}
479/*---------------------------------------------------------------------------*/
480static void
481init_rx_buffers(void)
482{
483 rfc_dataEntry_t *entry;
484 int i;
485
486 for(i = 0; i < PROP_MODE_RX_BUF_CNT; i++) {
487 entry = (rfc_dataEntry_t *)rx_buf[i];
488 entry->status = DATA_ENTRY_STATUS_PENDING;
489 entry->config.type = DATA_ENTRY_TYPE_GEN;
490 entry->config.lenSz = DATA_ENTRY_LENSZ_WORD;
491 entry->length = RX_BUF_SIZE - 8;
492 if(i == PROP_MODE_RX_BUF_CNT - 1) {
493 entry->pNextEntry = rx_buf[0];
494 } else {
495 entry->pNextEntry = rx_buf[i + 1];
496 }
497 }
498}
499/*---------------------------------------------------------------------------*/
500static int
501rx_on_prop(void)
502{
503 int ret;
504
505 if(rf_is_on()) {
506 PRINTF("rx_on_prop: We were on. PD=%u, RX=0x%04x\n",
507 rf_core_is_accessible(), smartrf_settings_cmd_prop_rx_adv.status);
508 return RF_CORE_CMD_OK;
509 }
510
511 /* Put CPE in RX using the currently configured parameters */
512 ret = rf_cmd_prop_rx();
513
514 if(ret) {
515 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
516 }
517
518 return ret;
519}
520/*---------------------------------------------------------------------------*/
521static int
522rx_off_prop(void)
523{
524 uint32_t cmd_status;
525 int ret;
526
527#if MAC_CONF_WITH_TSCH
528 /* Failsafe in case this variable failed to clear as part of normal operation */
529 packet_being_received = NULL;
530#endif /* MAC_CONF_WITH_TSCH */
531
532 /* If we are off, do nothing */
533 if(!rf_is_on()) {
534 return RF_CORE_CMD_OK;
535 }
536
537 /* Wait for ongoing ACK TX to finish */
538 RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
539
540 /* Send a CMD_ABORT command to RF Core */
541 if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
542 PRINTF("rx_off_prop: CMD_ABORT status=0x%08lx\n", cmd_status);
543 /* Continue nonetheless */
544 }
545
546 RTIMER_BUSYWAIT_UNTIL(!rf_is_on(), RF_CORE_TURN_OFF_TIMEOUT);
547
548 if(smartrf_settings_cmd_prop_rx_adv.status == PROP_DONE_STOPPED ||
549 smartrf_settings_cmd_prop_rx_adv.status == PROP_DONE_ABORT) {
550 /* Stopped gracefully */
551 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
552 ret = RF_CORE_CMD_OK;
553 } else {
554 PRINTF("rx_off_prop: status=0x%04x\n",
555 smartrf_settings_cmd_prop_rx_adv.status);
556 ret = RF_CORE_CMD_ERROR;
557 }
558
559 return ret;
560}
561/*---------------------------------------------------------------------------*/
562static uint8_t
563request(void)
564{
565 /*
566 * We rely on the RDC layer to turn us on and off. Thus, if we are on we
567 * will only allow sleep, standby otherwise
568 */
569 if(rf_is_on()) {
570 return LPM_MODE_SLEEP;
571 }
572
573 return LPM_MODE_MAX_SUPPORTED;
574}
575/*---------------------------------------------------------------------------*/
576LPM_MODULE(prop_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
577/*---------------------------------------------------------------------------*/
578static int
579prop_fs(void)
580{
581 uint32_t cmd_status;
582 rfc_radioOp_t *cmd = (rfc_radioOp_t *)&smartrf_settings_cmd_fs;
583
584 /* Send the command to the RF Core */
585 if(rf_core_send_cmd((uint32_t)cmd, &cmd_status) != RF_CORE_CMD_OK) {
586 PRINTF("prop_fs: CMD_FS, CMDSTA=0x%08lx, status=0x%04x\n",
587 cmd_status, cmd->status);
588 return RF_CORE_CMD_ERROR;
589 }
590
591 /* Wait until the command is done */
592 if(rf_core_wait_cmd_done(cmd) != RF_CORE_CMD_OK) {
593 PRINTF("prop_fs: CMD_FS wait, CMDSTA=0x%08lx, status=0x%04x\n",
594 cmd_status, cmd->status);
595 return RF_CORE_CMD_ERROR;
596 }
597
598 return RF_CORE_CMD_OK;
599}
600/*---------------------------------------------------------------------------*/
601static void
602soft_off_prop(void)
603{
604 uint32_t cmd_status;
605 volatile rfc_radioOp_t *cmd = rf_core_get_last_radio_op();
606
607 if(!rf_core_is_accessible()) {
608 return;
609 }
610
611 /* Send a CMD_ABORT command to RF Core */
612 if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
613 PRINTF("soft_off_prop: CMD_ABORT status=0x%08lx\n", cmd_status);
614 return;
615 }
616
617 RTIMER_BUSYWAIT_UNTIL((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) !=
618 RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING, RF_CORE_TURN_OFF_TIMEOUT);
619}
620/*---------------------------------------------------------------------------*/
621static uint8_t
622soft_on_prop(void)
623{
624 if(prop_div_radio_setup() != RF_CORE_CMD_OK) {
625 PRINTF("soft_on_prop: prop_div_radio_setup() failed\n");
626 return RF_CORE_CMD_ERROR;
627 }
628
629 if(prop_fs() != RF_CORE_CMD_OK) {
630 PRINTF("soft_on_prop: prop_fs() failed\n");
631 return RF_CORE_CMD_ERROR;
632 }
633
634 return rx_on_prop();
635}
636/*---------------------------------------------------------------------------*/
637static const rf_core_primary_mode_t mode_prop = {
638 soft_off_prop,
639 soft_on_prop,
640 rf_is_on,
641 RAT_TIMESTAMP_OFFSET_SUB_GHZ
642};
643/*---------------------------------------------------------------------------*/
644static int
645init(void)
646{
647 lpm_register_module(&prop_lpm_module);
648
649 if(ti_lib_chipinfo_chip_family_is_cc13xx() == false) {
650 return RF_CORE_CMD_ERROR;
651 }
652
653 /* Initialise RX buffers */
654 memset(rx_buf, 0, sizeof(rx_buf));
655
656 /* Set of RF Core data queue. Circular buffer, no last entry */
657 rx_data_queue.pCurrEntry = rx_buf[0];
658 rx_data_queue.pLastEntry = NULL;
659
660 /* Initialize current read pointer to first element (used in ISR) */
661 rx_read_entry = rx_buf[0];
662
663 smartrf_settings_cmd_prop_rx_adv.pQueue = &rx_data_queue;
664 smartrf_settings_cmd_prop_rx_adv.pOutput = (uint8_t *)&rx_stats;
665
667
668 if(on() != RF_CORE_CMD_OK) {
669 PRINTF("init: on() failed\n");
670 return RF_CORE_CMD_ERROR;
671 }
672
673 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
674
676
678
679 process_start(&rf_core_process, NULL);
680
681 return 1;
682}
683/*---------------------------------------------------------------------------*/
684static int
685prepare(const void *payload, unsigned short payload_len)
686{
687 if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > MAX_PAYLOAD_LEN) {
688 return RADIO_TX_ERR;
689 }
690
691 memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, payload_len);
692 return 0;
693}
694/*---------------------------------------------------------------------------*/
695static int
696transmit(unsigned short transmit_len)
697{
698 int ret;
699 uint8_t was_off = 0;
700 uint32_t cmd_status;
701 volatile rfc_CMD_PROP_TX_ADV_t *cmd_tx_adv;
702
703 /* Length in .15.4g PHY HDR. Includes the CRC but not the HDR itself */
704 uint16_t total_length;
705
706 if(transmit_len > MAX_PAYLOAD_LEN) {
707 PRINTF("transmit: too long\n");
708 return RADIO_TX_ERR;
709 }
710
711 if(!rf_is_on()) {
712 was_off = 1;
713 if(on() != RF_CORE_CMD_OK) {
714 PRINTF("transmit: on() failed\n");
715 return RADIO_TX_ERR;
716 }
717 }
718
719 /*
720 * Prepare the .15.4g PHY header
721 * MS=0, Length MSBits=0, DW and CRC configurable
722 * Total length = transmit_len (payload) + CRC length
723 *
724 * The Radio will flip the bits around, so tx_buf[0] must have the length
725 * LSBs (PHR[15:8] and tx_buf[1] will have PHR[7:0]
726 */
727 total_length = transmit_len + CRC_LEN;
728
729 tx_buf[0] = total_length & 0xFF;
730 tx_buf[1] = (total_length >> 8) + DOT_4G_PHR_DW_BIT + DOT_4G_PHR_CRC_BIT;
731
732 /* Prepare the CMD_PROP_TX_ADV command */
733 cmd_tx_adv = (rfc_CMD_PROP_TX_ADV_t *)&smartrf_settings_cmd_prop_tx_adv;
734
735 /*
736 * pktLen: Total number of bytes in the TX buffer, including the header if
737 * one exists, but not including the CRC (which is not present in the buffer)
738 */
739 cmd_tx_adv->pktLen = transmit_len + DOT_4G_PHR_LEN;
740 cmd_tx_adv->pPkt = tx_buf;
741
742 /* Abort RX */
743 rx_off_prop();
744
745 /* Enable the LAST_COMMAND_DONE interrupt to wake us up */
746 rf_core_cmd_done_en(false);
747
748 ret = rf_core_send_cmd((uint32_t)cmd_tx_adv, &cmd_status);
749
750 if(ret) {
751 /* If we enter here, TX actually started */
752 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
753
754 /* Idle away while the command is running */
755 while((cmd_tx_adv->status & RF_CORE_RADIO_OP_MASKED_STATUS)
756 == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
757 /* Note: for now sleeping while Tx'ing in polling mode is disabled.
758 * To enable it:
759 * 1) make the `lpm_sleep()` call here unconditional;
760 * 2) change the radio ISR priority to allow radio ISR to interrupt rtimer ISR.
761 */
762 if(!rf_core_poll_mode) {
763 lpm_sleep();
764 }
765 }
766
767 if(cmd_tx_adv->status == RF_CORE_RADIO_OP_STATUS_PROP_DONE_OK) {
768 /* Sent OK */
769 ret = RADIO_TX_OK;
770 } else {
771 /* Operation completed, but frame was not sent */
772 PRINTF("transmit: Not Sent OK status=0x%04x\n",
773 cmd_tx_adv->status);
774 ret = RADIO_TX_ERR;
775 }
776 } else {
777 /* Failure sending the CMD_PROP_TX command */
778 PRINTF("transmit: PROP_TX_ERR ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
779 ret, cmd_status, cmd_tx_adv->status);
780 ret = RADIO_TX_ERR;
781 }
782
783 /*
784 * Update ENERGEST state here, before a potential call to off(), which
785 * will correctly update it if required.
786 */
787 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
788
789 /*
790 * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
791 * except when we are transmitting
792 */
794
795 /* Workaround. Set status to IDLE */
796 cmd_tx_adv->status = RF_CORE_RADIO_OP_STATUS_IDLE;
797
798 rx_on_prop();
799
800 if(was_off) {
801 off();
802 }
803
804 return ret;
805}
806/*---------------------------------------------------------------------------*/
807static int
808send(const void *payload, unsigned short payload_len)
809{
810 prepare(payload, payload_len);
811 return transmit(payload_len);
812}
813/*---------------------------------------------------------------------------*/
814static void
815release_data_entry(void)
816{
817 rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
818 uint8_t *data_ptr = &entry->data;
819 int_master_status_t interrupt_status;
820
821 /* Clear the length field (2 bytes) */
822 data_ptr[0] = 0;
823 data_ptr[1] = 0;
824
825 /* Set status to 0 "Pending" in element */
826 entry->status = DATA_ENTRY_STATUS_PENDING;
827 rx_read_entry = entry->pNextEntry;
828
829 interrupt_status = critical_enter();
830 if(rf_core_rx_is_full) {
831 rf_core_rx_is_full = false;
832 PRINTF("RXQ was full, re-enabling radio!\n");
833 rx_on_prop();
834 }
835 critical_exit(interrupt_status);
836
837}
838/*---------------------------------------------------------------------------*/
839static int
840read_frame(void *buf, unsigned short buf_len)
841{
842 rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
843 uint8_t *data_ptr;
844 int len = 0;
845 uint32_t rat_timestamp;
846
847 int is_found = 0;
848 /* Go through all RX buffers and check their status */
849 do {
850 if(entry->status >= DATA_ENTRY_STATUS_BUSY) {
851 is_found = 1;
852 break;
853 }
854
855 entry = (rfc_dataEntryGeneral_t *)entry->pNextEntry;
856 } while(entry != (rfc_dataEntryGeneral_t *)rx_read_entry);
857
858 if(is_found == 0) {
859 /* No available data */
860 return 0;
861 }
862
863 rx_read_entry = (volatile uint8_t *)entry;
864
865 /* wait for entry to become finished */
866 rtimer_clock_t t0 = RTIMER_NOW();
867 while(entry->status == DATA_ENTRY_STATUS_BUSY
868 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + RADIO_FRAME_DURATION(MAX_PAYLOAD_LEN)));
869
870#if MAC_CONF_WITH_TSCH
871 /* Make sure the flag is reset */
872 packet_being_received = NULL;
873#endif
874
875 if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
876 /* No available data */
877 return 0;
878 }
879
880 /*
881 * First 2 bytes in the data entry are the length.
882 * Our data entry consists of:
883 * Payload + RSSI (1 byte) + Timestamp (4 bytes) + Status (1 byte)
884 * This length includes all of those.
885 */
886 data_ptr = &entry->data;
887 len = (*(uint16_t *)data_ptr);
888
889 if(len <= RX_BUF_METADATA_SIZE) {
890 PRINTF("RF: too short!");
891
892 release_data_entry();
893 return 0;
894 }
895
896 data_ptr += 2;
897 len -= RX_BUF_METADATA_SIZE;
898
899 if(len > buf_len) {
900 PRINTF("RF: too long\n");
901
902 release_data_entry();
903 return 0;
904 }
905
906 memcpy(buf, data_ptr, len);
907
908 /* get the RSSI and status */
909 rf_core_last_rssi = (int8_t)data_ptr[len];
910 rf_core_last_corr_lqi = data_ptr[len + 5];
911
912 /* get the timestamp */
913 memcpy(&rat_timestamp, data_ptr + len + 1, 4);
914
915 rf_core_last_packet_timestamp = rf_core_convert_rat_to_rtimer(rat_timestamp);
916
917 if(!rf_core_poll_mode) {
918 /* Not in poll mode: packetbuf should not be accessed in interrupt context.
919 * In poll mode, the last packet RSSI and link quality can be obtained through
920 * RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
921 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf_core_last_rssi);
922 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf_core_last_corr_lqi);
923 }
924
925 release_data_entry();
926
927 return len;
928}
929/*---------------------------------------------------------------------------*/
930static int
931channel_clear(void)
932{
933 uint8_t was_off = 0;
934 uint32_t cmd_status;
935 int8_t rssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
936
937 /*
938 * If we are in the middle of a BLE operation, we got called by ContikiMAC
939 * from within an interrupt context. Indicate a clear channel
940 */
941 if(rf_ble_is_active() == RF_BLE_ACTIVE) {
942 return RF_CORE_CCA_CLEAR;
943 }
944
945 if(!rf_core_is_accessible()) {
946 was_off = 1;
947 if(on() != RF_CORE_CMD_OK) {
948 PRINTF("channel_clear: on() failed\n");
949 if(was_off) {
950 off();
951 }
952 return RF_CORE_CCA_CLEAR;
953 }
954 } else {
955 if(transmitting()) {
956 PRINTF("channel_clear: called while in TX\n");
957 return RF_CORE_CCA_CLEAR;
958 }
959 }
960
961 while(rssi == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN || rssi == 0) {
962 if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_GET_RSSI), &cmd_status)
963 != RF_CORE_CMD_OK) {
964 break;
965 }
966 /* Current RSSI in bits 23:16 of cmd_status */
967 rssi = (cmd_status >> 16) & 0xFF;
968 }
969
970 if(was_off) {
971 off();
972 }
973
974 if(rssi >= rssi_threshold) {
975 return RF_CORE_CCA_BUSY;
976 }
977
978 return RF_CORE_CCA_CLEAR;
979}
980/*---------------------------------------------------------------------------*/
981static int
982receiving_packet(void)
983{
984 if(!rf_is_on()) {
985 return 0;
986 }
987
988#if MAC_CONF_WITH_TSCH
989 /*
990 * Under TSCH operation, we rely on "hints" from the MDMSOFT interrupt
991 * flag. This flag is set by the radio upon sync word detection, but it is
992 * not cleared automatically by hardware. We store state in a variable after
993 * first call. The assumption is that the TSCH code will keep calling us
994 * until frame reception has completed, at which point we can clear MDMSOFT.
995 */
996 if(packet_being_received == NULL) {
997 /* Look for the modem synchronization word detection interrupt flag.
998 * This flag is raised when the synchronization word is received.
999 */
1000 if(HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFHWIFG) & RFC_DBELL_RFHWIFG_MDMSOFT) {
1001 packet_being_received = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
1002 }
1003 } else {
1004 /* After the start of the packet: reset the Rx flag once the packet is finished */
1005 if(packet_being_received->status >= DATA_ENTRY_FINISHED) {
1006 /* Clear the modem sync flag */
1007 ti_lib_rfc_hw_int_clear(RFC_DBELL_RFHWIFG_MDMSOFT);
1008 packet_being_received = NULL;
1009 }
1010 }
1011
1012 return packet_being_received != NULL;
1013#else
1014 /*
1015 * Under CSMA operation, there is no immediately straightforward logic as to
1016 * when it's OK to clear the MDMSOFT interrupt flag:
1017 *
1018 * - We cannot re-use the same logic as above, since CSMA may bail out of
1019 * frame TX immediately after a single call this function here. In this
1020 * scenario, is_receiving_packet would remain equal to one and we would
1021 * therefore erroneously signal ongoing RX in subsequent calls to this
1022 * function here, even _after_ reception has completed.
1023 * - We can neither clear inside read_frame() nor inside the RX frame
1024 * interrupt handler (remember, we are not in poll mode under CSMA),
1025 * since we risk clearing MDMSOFT after we have seen a sync word for the
1026 * _next_ frame. If this happens, this function here would incorrectly
1027 * return 0 during RX of this next frame.
1028 *
1029 * So to avoid a very convoluted logic of how to handle MDMSOFT, we simply
1030 * perform a clear channel assessment here: We interpret channel activity
1031 * as frame reception.
1032 */
1033
1034 if(channel_clear() == RF_CORE_CCA_CLEAR) {
1035 return 0;
1036 }
1037
1038 return 1;
1039
1040#endif
1041}
1042/*---------------------------------------------------------------------------*/
1043static int
1044pending_packet(void)
1045{
1046 int rv = 0;
1047 volatile rfc_dataEntry_t *entry = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
1048
1049 /* Go through all RX buffers and check their status */
1050 do {
1051 if(entry->status >= DATA_ENTRY_STATUS_BUSY) {
1052 rv = 1;
1053 if(!rf_core_poll_mode) {
1054 process_poll(&rf_core_process);
1055 }
1056 }
1057
1058 entry = (rfc_dataEntry_t *)entry->pNextEntry;
1059 } while(entry != (rfc_dataEntry_t *)rx_data_queue.pCurrEntry);
1060
1061 /* If we didn't find an entry at status finished, no frames are pending */
1062 return rv;
1063}
1064/*---------------------------------------------------------------------------*/
1065static int
1066on(void)
1067{
1068 /*
1069 * If we are in the middle of a BLE operation, we got called by ContikiMAC
1070 * from within an interrupt context. Abort, but pretend everything is OK.
1071 */
1072 if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1073 return RF_CORE_CMD_OK;
1074 }
1075
1076 if(rf_is_on()) {
1077 PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
1078 smartrf_settings_cmd_prop_rx_adv.status);
1079 return RF_CORE_CMD_OK;
1080 }
1081
1082 /*
1083 * Request the HF XOSC as the source for the HF clock. Needed before we can
1084 * use the FS. This will only request, it will _not_ perform the switch.
1085 */
1087
1088 if(!rf_core_is_accessible()) {
1089 if(rf_core_power_up() != RF_CORE_CMD_OK) {
1090 PRINTF("on: rf_core_power_up() failed\n");
1091
1093
1094 return RF_CORE_CMD_ERROR;
1095 }
1096
1097 /* Keep track of RF Core mode */
1099
1100 /* Apply patches to radio core */
1101 rf_patch_cpe_genfsk();
1102 while(!HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG));
1103 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
1104 rf_patch_rfe_genfsk();
1105
1106 /* Initialize bus request */
1107 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
1108 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) =
1109 CMDR_DIR_CMD_1BYTE(CMD_BUS_REQUEST, 1);
1110
1111 /* set VCOLDO reference */
1112 ti_lib_rfc_adi3vco_ldo_voltage_mode(true);
1113
1114 /* Let CC13xxware automatically set a correct value for RTRIM for us */
1115 ti_lib_rfc_rtrim((rfc_radioOp_t *)&smartrf_settings_cmd_prop_radio_div_setup);
1116
1117 /* Make sure BUS_REQUEST is done */
1118 while(!HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG));
1119 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
1120
1121 if(rf_core_start_rat() != RF_CORE_CMD_OK) {
1122 PRINTF("on: rf_core_start_rat() failed\n");
1123
1125
1126 return RF_CORE_CMD_ERROR;
1127 }
1128 }
1129
1131
1132 init_rx_buffers();
1133
1134 /*
1135 * Trigger a switch to the XOSC, so that we can subsequently use the RF FS
1136 * This will block until the XOSC is actually ready, but give how we
1137 * requested it early on, this won't be too long a wait/
1138 */
1140
1141 if(prop_div_radio_setup() != RF_CORE_CMD_OK) {
1142 PRINTF("on: prop_div_radio_setup() failed\n");
1144 return RF_CORE_CMD_ERROR;
1145 }
1146
1147 if(prop_fs() != RF_CORE_CMD_OK) {
1148 PRINTF("on: prop_fs() failed\n");
1149 return RF_CORE_CMD_ERROR;
1150 }
1151
1152 if(rx_on_prop() != RF_CORE_CMD_OK) {
1153
1154 if((rf_core_cmd_status() & RF_CORE_CMDSTA_RESULT_MASK) != RF_CORE_CMDSTA_SCHEDULING_ERR) {
1155 PRINTF("on: failed with status=0x%08lx\n", rf_core_cmd_status());
1156 return RF_CORE_CMD_ERROR;
1157 }
1158
1159 /* Looks like a command was alredy pending on radio. */
1160 /* Abort any existing commands */
1161 uint32_t status;
1162 if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &status) == RF_CORE_CMD_ERROR) {
1163 PRINTF("on: CMD_ABORT status=0x%08lx\n", rf_core_cmd_status());
1164 return RF_CORE_CMD_ERROR;
1165 }
1166
1167 /* Retry setup */
1168 if(soft_on_prop() != RF_CORE_CMD_OK) {
1169 PRINTF("on: retry with status=0x%08lx\n", rf_core_cmd_status());
1170 return RF_CORE_CMD_ERROR;
1171 }
1172 }
1173
1174 return RF_CORE_CMD_OK;
1175}
1176/*---------------------------------------------------------------------------*/
1177static int
1178off(void)
1179{
1180 int i;
1181 rfc_dataEntry_t *entry;
1182
1183 /*
1184 * If we are in the middle of a BLE operation, we got called by ContikiMAC
1185 * from within an interrupt context. Abort, but pretend everything is OK.
1186 */
1187 if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1188 return RF_CORE_CMD_OK;
1189 }
1190
1191 rx_off_prop();
1193
1194 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
1195
1196#if !CC2650_FAST_RADIO_STARTUP
1197 /* Switch HF clock source to the RCOSC to preserve power */
1199#endif
1200
1201 /* We pulled the plug, so we need to restore the status manually */
1202 smartrf_settings_cmd_prop_rx_adv.status = RF_CORE_RADIO_OP_STATUS_IDLE;
1203
1204 /*
1205 * Just in case there was an ongoing RX (which started after we begun the
1206 * shutdown sequence), we don't want to leave the buffer in state == ongoing
1207 */
1208 for(i = 0; i < PROP_MODE_RX_BUF_CNT; i++) {
1209 entry = (rfc_dataEntry_t *)rx_buf[i];
1210 if(entry->status == DATA_ENTRY_STATUS_BUSY) {
1211 entry->status = DATA_ENTRY_STATUS_PENDING;
1212 }
1213 }
1214
1215 return RF_CORE_CMD_OK;
1216}
1217/*---------------------------------------------------------------------------*/
1218/* Enable or disable CCA before sending */
1219static radio_result_t
1220set_send_on_cca(uint8_t enable)
1221{
1222 if(enable) {
1223 /* this driver does not have support for CCA on Tx */
1225 }
1226 return RADIO_RESULT_OK;
1227}
1228/*---------------------------------------------------------------------------*/
1229static radio_result_t
1230get_value(radio_param_t param, radio_value_t *value)
1231{
1232 if(!value) {
1234 }
1235
1236 switch(param) {
1238 /* On / off */
1240 return RADIO_RESULT_OK;
1242 *value = (radio_value_t)get_channel();
1243 return RADIO_RESULT_OK;
1245 *value = 0;
1246 if(rf_core_poll_mode) {
1247 *value |= RADIO_RX_MODE_POLL_MODE;
1248 }
1249 return RADIO_RESULT_OK;
1251 *value = 0;
1252 return RADIO_RESULT_OK;
1254 *value = get_tx_power();
1255 return RADIO_RESULT_OK;
1257 *value = rssi_threshold;
1258 return RADIO_RESULT_OK;
1259 case RADIO_PARAM_RSSI:
1260 *value = get_rssi();
1261
1262 if(*value == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN) {
1263 return RADIO_RESULT_ERROR;
1264 } else {
1265 return RADIO_RESULT_OK;
1266 }
1268 *value = 0;
1269 return RADIO_RESULT_OK;
1271 *value = DOT_15_4G_CHANNEL_MAX;
1272 return RADIO_RESULT_OK;
1274 *value = TX_POWER_DRIVER[get_tx_power_array_last_element()].dbm;
1275 return RADIO_RESULT_OK;
1277 *value = OUTPUT_POWER_MAX;
1278 return RADIO_RESULT_OK;
1280 *value = rf_core_last_rssi;
1281 return RADIO_RESULT_OK;
1283 *value = rf_core_last_corr_lqi;
1284 return RADIO_RESULT_OK;
1286 /* 2 header bytes, 2 or 4 bytes CRC */
1287 *value = (radio_value_t)(DOT_4G_PHR_LEN + CRC_LEN);
1288 return RADIO_RESULT_OK;
1290 *value = (radio_value_t)RADIO_BYTE_AIR_TIME;
1291 return RADIO_RESULT_OK;
1293 *value = (radio_value_t)RADIO_DELAY_BEFORE_TX;
1294 return RADIO_RESULT_OK;
1296 *value = (radio_value_t)RADIO_DELAY_BEFORE_RX;
1297 return RADIO_RESULT_OK;
1299 *value = (radio_value_t)RADIO_DELAY_BEFORE_DETECT;
1300 return RADIO_RESULT_OK;
1301 case RADIO_CONST_MAX_PAYLOAD_LEN:
1302 *value = (radio_value_t)MAX_PAYLOAD_LEN;
1303 return RADIO_RESULT_OK;
1304 default:
1306 }
1307}
1308/*---------------------------------------------------------------------------*/
1309static radio_result_t
1310set_value(radio_param_t param, radio_value_t value)
1311{
1313 uint8_t old_poll_mode;
1314
1315 switch(param) {
1317 if(value == RADIO_POWER_MODE_ON) {
1318 if(on() != RF_CORE_CMD_OK) {
1319 PRINTF("set_value: on() failed (1)\n");
1320 return RADIO_RESULT_ERROR;
1321 }
1322 return RADIO_RESULT_OK;
1323 }
1324 if(value == RADIO_POWER_MODE_OFF) {
1325 off();
1326 return RADIO_RESULT_OK;
1327 }
1330 if(value < 0 ||
1331 value > DOT_15_4G_CHANNEL_MAX) {
1333 }
1334
1335 if(get_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 set_channel((uint8_t)value);
1342 break;
1343
1345 if(value & ~(RADIO_RX_MODE_POLL_MODE)) {
1347 }
1348
1349 old_poll_mode = rf_core_poll_mode;
1350 rf_core_poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
1351 if(rf_core_poll_mode == old_poll_mode) {
1352 return RADIO_RESULT_OK;
1353 }
1354 break;
1355
1357 if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
1359 }
1360 return set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
1361
1363 if(value < TX_POWER_DRIVER[get_tx_power_array_last_element()].dbm ||
1364 value > OUTPUT_POWER_MAX) {
1366 }
1367
1368 soft_off_prop();
1369
1370 set_tx_power(value);
1371
1372 if(soft_on_prop() != RF_CORE_CMD_OK) {
1373 PRINTF("set_value: soft_on_prop() failed\n");
1374 rv = RADIO_RESULT_ERROR;
1375 }
1376
1377 return rv;
1378
1380 rssi_threshold = (int8_t)value;
1381 break;
1382 default:
1384 }
1385
1386 /* If off, the new configuration will be applied the next time radio is started */
1387 if(!rf_is_on()) {
1388 return RADIO_RESULT_OK;
1389 }
1390
1391 /* If we reach here we had no errors. Apply new settings */
1392 if(rx_off_prop() != RF_CORE_CMD_OK) {
1393 PRINTF("set_value: rx_off_prop() failed\n");
1394 rv = RADIO_RESULT_ERROR;
1395 }
1396
1397 /* Restart the radio timer (RAT).
1398 This causes resynchronization between RAT and RTC: useful for TSCH. */
1399 if(rf_core_restart_rat() != RF_CORE_CMD_OK) {
1400 PRINTF("set_value: rf_core_restart_rat() failed\n");
1401 /* do not set the error */
1402 } else {
1404 }
1405
1406 if(soft_on_prop() != RF_CORE_CMD_OK) {
1407 PRINTF("set_value: soft_on_prop() failed\n");
1408 rv = RADIO_RESULT_ERROR;
1409 }
1410
1411 return rv;
1412}
1413/*---------------------------------------------------------------------------*/
1414static radio_result_t
1415get_object(radio_param_t param, void *dest, size_t size)
1416{
1418 if(size != sizeof(rtimer_clock_t) || !dest) {
1420 }
1421 *(rtimer_clock_t *)dest = rf_core_last_packet_timestamp;
1422
1423 return RADIO_RESULT_OK;
1424 }
1425
1427}
1428/*---------------------------------------------------------------------------*/
1429static radio_result_t
1430set_object(radio_param_t param, const void *src, size_t size)
1431{
1433}
1434/*---------------------------------------------------------------------------*/
1435const struct radio_driver prop_mode_driver = {
1436 init,
1437 prepare,
1438 transmit,
1439 send,
1440 read_frame,
1444 on,
1445 off,
1446 get_value,
1447 set_value,
1448 get_object,
1449 set_object,
1450};
1451/*---------------------------------------------------------------------------*/
1452/**
1453 * @}
1454 */
Header file with descriptors for the various modes of operation defined in IEEE 802....
Header file for the CC13xx/CC26xx UART driver.
Default definitions of C compiler quirk work-arounds.
Header file for the energy estimation mechanism.
static uint8_t get_channel()
Get the current operating channel.
Definition: cc2538-rf.c:165
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:175
#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
static volatile uint64_t count
Num.
Definition: clock.c:50
static void critical_exit(int_master_status_t status)
Exit a critical section and restore the master interrupt.
Definition: critical.h:81
static int_master_status_t critical_enter()
Enter a critical section.
Definition: critical.h:65
INT_MASTER_STATUS_DATATYPE int_master_status_t
Master interrupt state representation data type.
Definition: int-master.h:62
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_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition: radio.h:453
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition: radio.h:466
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
@ RADIO_RESULT_ERROR
An error occurred when getting/setting the parameter, but the arguments were otherwise correct.
Definition: radio.h:480
@ RADIO_RESULT_NOT_SUPPORTED
The parameter is not supported.
Definition: radio.h:473
@ RADIO_RESULT_INVALID_VALUE
The value argument was incorrect.
Definition: radio.h:474
@ RADIO_RESULT_OK
The parameter was set/read successfully.
Definition: radio.h:472
@ 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:330
@ 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:278
@ 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:335
@ 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:236
@ 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:347
@ RADIO_PARAM_TXPOWER
Transmission power in dBm.
Definition: radio.h:192
@ 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:341
@ RADIO_CONST_CHANNEL_MAX
The highest radio channel number.
Definition: radio.h:308
@ 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:313
@ RADIO_CONST_CHANNEL_MIN
The lowest radio channel number.
Definition: radio.h:303
@ RADIO_CONST_TXPOWER_MAX
The maximum transmission power in dBm.
Definition: radio.h:318
@ 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:353
@ 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:387
@ RADIO_POWER_MODE_ON
Radio powered on and able to receive frames.
Definition: radio.h:392
@ RADIO_TX_ERR
An error occurred during transmission.
Definition: radio.h:498
@ RADIO_TX_OK
TX was successful and where an ACK was requested one was received.
Definition: radio.h:490
uint8_t rf_ble_is_active()
Check whether the BLE beacond is currently active.
Definition: rf-ble.c:262
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
void rf_core_cmd_done_dis(void)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
Definition: rf-core.c:542
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
Definition: rf-core.c:387
uint32_t rf_core_cmd_status(void)
Get the status of the last issued radio command.
Definition: rf-core.c:250
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
Definition: rf-core.c:156
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
Definition: rf-core.c:147
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
Definition: rf-core.c:549
int rf_core_power_up()
Turn on power to the RFC and boot it.
Definition: rf-core.c:278
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
Definition: rf-core.c:425
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
Definition: rf-core.c:228
uint32_t rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
Convert from RAT timestamp to rtimer ticks.
Definition: rf-core.c:667
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
Definition: rf-core.c:528
uint8_t rf_core_restart_rat(void)
Restart the CM0 RAT.
Definition: rf-core.c:475
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
Definition: rf-core.c:564
void rf_core_setup_interrupts(void)
Setup RF core interrupts.
Definition: rf-core.c:494
uint8_t rf_core_rat_init(void)
Initialize the RAT to RTC conversion machinery.
Definition: rf-core.c:592
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:603
uint8_t rf_core_start_rat(void)
Start the CM0 RAT.
Definition: rf-core.c:327
#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
#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 CC13xx prop mode NETSTACK_RADIO driver.
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:526
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:762
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:572
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:748
int(* off)(void)
Turn the radio off.
Definition: radio.h:721
int(* init)(void)
Initialise the radio hardware.
Definition: radio.h:547
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:623
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:676
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:779
int(* on)(void)
Turn the radio on.
Definition: radio.h:703
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:611
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver's buffers.
Definition: radio.h:689
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:733
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:664
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.