Contiki-NG
rat.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020, Institute of Electronics and Computer Science (EDI)
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 * \addtogroup cc13xx-cc26xx-rf-rat
32 * @{
33 *
34 * \file
35 * Implementation of the CC13xx/CC26xx RAT (Radio Timer) upkeep.
36 * \author
37 * Atis Elsts <atis.elsts@edi.lv>
38 */
39/*---------------------------------------------------------------------------*/
40#include "rf/rat.h"
41#include "rf/radio-mode.h"
42/*---------------------------------------------------------------------------*/
43#include <ti/drivers/rf/RF.h>
44/*---------------------------------------------------------------------------*/
45/* RAT has 32-bit register, overflows once ~18 minutes */
46#define RAT_RANGE 4294967296ull
47#define RAT_ONE_QUARTER (RAT_RANGE / (uint32_t)4)
48#define RAT_ONE_THIRD (RAT_RANGE / (uint32_t)3)
49#define RAT_THREE_QUARTERS (RAT_ONE_QUARTER * 3)
50#define RTIMER_TO_RAT(x) ((x) * (RAT_SECOND / RTIMER_SECOND))
51/*---------------------------------------------------------------------------*/
52static void
53check_rat_overflow(void)
54{
55 const bool was_off = !radio_mode->rx_is_active();
56
57 if(was_off) {
58 RF_runDirectCmd(radio_mode->rf_handle, CMD_NOP);
59 }
60
61 const uint32_t current_value = RF_getCurrentTime();
62
63 static bool initial_iteration = true;
64 static uint32_t last_value;
65
66 if(initial_iteration) {
67 /* First time checking overflow will only store the current value */
68 initial_iteration = false;
69 } else {
70 /* Overflow happens when the previous reading is bigger than the current one */
71 if(current_value < last_value) {
72 /* Overflow detected */
73 radio_mode->rat.last_overflow = RTIMER_NOW();
74 radio_mode->rat.overflow_count += 1;
75 }
76 }
77
78 last_value = current_value;
79
80 if(was_off) {
81 RF_yield(radio_mode->rf_handle);
82 }
83}
84/*---------------------------------------------------------------------------*/
85static void
86rat_overflow_cb(void *arg)
87{
88 check_rat_overflow();
89 /* Check next time after half of the RAT interval */
90 const clock_time_t two_quarters = (2 * RAT_ONE_QUARTER * CLOCK_SECOND) / RAT_SECOND;
91 ctimer_set(&radio_mode->rat.overflow_timer, two_quarters, rat_overflow_cb, NULL);
92}
93/*---------------------------------------------------------------------------*/
94void
95rat_init(void)
96{
97 check_rat_overflow();
98 const clock_time_t one_third = (RAT_ONE_THIRD * CLOCK_SECOND) / RAT_SECOND;
99 ctimer_set(&radio_mode->rat.overflow_timer, one_third, rat_overflow_cb, NULL);
100}
101/*---------------------------------------------------------------------------*/
102uint32_t
103rat_to_timestamp(const uint32_t rat_ticks, int32_t offset_ticks)
104{
105 check_rat_overflow();
106
107 uint64_t adjusted_overflow_count = radio_mode->rat.overflow_count;
108
109 /* If the timestamp is in the 4th quarter and the last overflow was recently,
110 * assume that the timestamp refers to the time before the overflow */
111 if(rat_ticks > RAT_THREE_QUARTERS) {
112 const rtimer_clock_t one_quarter = (RAT_ONE_QUARTER * RTIMER_SECOND) / RAT_SECOND;
113 if(RTIMER_CLOCK_LT(RTIMER_NOW(), radio_mode->rat.last_overflow + one_quarter)) {
114 adjusted_overflow_count -= 1;
115 }
116 }
117
118 /* Add the overflowed time to the timestamp */
119 const uint64_t rat_ticks_adjusted = (uint64_t)rat_ticks + (uint64_t)RAT_RANGE * adjusted_overflow_count;
120
121 return RAT_TO_RTIMER(rat_ticks_adjusted + offset_ticks);
122}
123/*---------------------------------------------------------------------------*/
124/**
125 * @}
126 */
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
Header file of the generic radio mode API.
Header file of the CC13xx/CC26xx RAT timer handler.