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-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 /*---------------------------------------------------------------------------*/
52 static void
53 check_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 /*---------------------------------------------------------------------------*/
85 static void
86 rat_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 /*---------------------------------------------------------------------------*/
94 void
95 rat_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 /*---------------------------------------------------------------------------*/
102 uint32_t
103 rat_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  */
Header file of the generic radio mode API.
Header file of the CC13xx/CC26xx RAT timer handler.
#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
#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