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