1 /*
2 * Copyright (c) 2017 - 2023, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35 /**
36 * @file
37 * This file implements RSSI calculations for 802.15.4 driver.
38 *
39 */
40 #include "nrf_802154_rssi.h"
41 #include "nrf_802154_nrfx_addons.h"
42 #include "nrf_802154_const.h"
43
44 #include "nrfx.h"
45 #include <stdint.h>
46
47 #include "platform/nrf_802154_temperature.h"
48
49 #if defined(NRF52_SERIES)
50
51 /* Implementation for nRF52 family. */
nrf_802154_rssi_sample_temp_corr_value_get(uint8_t rssi_sample)52 int8_t nrf_802154_rssi_sample_temp_corr_value_get(uint8_t rssi_sample)
53 {
54 (void)rssi_sample;
55
56 int8_t temp = nrf_802154_temperature_get();
57 int8_t result;
58
59 #if defined(NRF52840_XXAA) || defined(NRF52833_XXAA)
60 /* Implementation based on Errata 153 for nRF52840 SoC and Errata 225 for nRF52833 SoCs.. */
61 if (temp <= -30)
62 {
63 result = 3;
64 }
65 else if (temp <= -10)
66 {
67 result = 2;
68 }
69 else if (temp <= 10)
70 {
71 result = 1;
72 }
73 else if (temp <= 30)
74 {
75 result = 0;
76 }
77 else if (temp <= 50)
78 {
79 result = -1;
80 }
81 else if (temp <= 70)
82 {
83 result = -2;
84 }
85 else if (temp <= 85)
86 {
87 result = -3;
88 }
89 else
90 {
91 // nRF52840 cannot work for a temperature above 85 degrees Celsius, so this part won't affect its operation,
92 // even if it isn't present in its errata.
93 result = -4;
94 }
95 #else
96 /* Implementation for other SoCs from nRF52 family */
97 result = 0;
98 #endif
99 return result;
100 }
101
102 #else
103
104 /** Macro for calculating x raised to the power of 2. */
105 #define POW_2(x) ((x) * (x))
106 /** Macro for calculating x raised to the power of 3. */
107 #define POW_3(x) ((x) * POW_2(x))
108
109 /**
110 * @brief Polynomial coefficients of the correction equation.
111 *
112 * Coefficients were calculated as round(x * RSSI_COEFF_BASE) based on Errata 87.
113 */
114 #define RSSI_COEFF_A0 30198989L /* Initial value: 7.2 */
115 #define RSSI_COEFF_A1 6543114L /* Initial value: 1.56 */
116 #define RSSI_COEFF_A2 41524L /* Initial value: 9.9e-3 */
117 #define RSSI_COEFF_A3 205L /* Initial value: 4.9e-5 */
118 #define RSSI_COEFF_TEMP 209715L /* Initial value: 0.05 */
119 /** @brief Value used to increase precision of calculations. */
120 #define RSSI_COEFF_BASE (1UL << 22U)
121
122 /**
123 * @brief Normalizes intermediate RSSI value by dividing and rounding.
124 *
125 * @param[in] rssi_value Intermediate RSSI value to be normalized.
126 *
127 * @returns normalized rssi_value.
128 */
normalize_rssi(int32_t rssi_value)129 static int8_t normalize_rssi(int32_t rssi_value)
130 {
131 uint32_t abs_rssi_value;
132
133 abs_rssi_value = (rssi_value < 0) ? (-rssi_value) : rssi_value;
134 abs_rssi_value = (abs_rssi_value + (RSSI_COEFF_BASE / 2)) / RSSI_COEFF_BASE;
135
136 return (rssi_value < 0) ? (-(int8_t)abs_rssi_value) : ((int8_t)abs_rssi_value);
137 }
138
139 /* Implementation based on Errata 87 for nRF53 family. */
nrf_802154_rssi_sample_temp_corr_value_get(uint8_t rssi_sample)140 int8_t nrf_802154_rssi_sample_temp_corr_value_get(uint8_t rssi_sample)
141 {
142 int32_t temp;
143 int32_t rssi_sample_i32;
144 int8_t compensated_rssi;
145
146 temp = (int32_t)nrf_802154_temperature_get();
147 rssi_sample_i32 = (int32_t)rssi_sample;
148
149 compensated_rssi = normalize_rssi((RSSI_COEFF_A1 * rssi_sample_i32)
150 + (RSSI_COEFF_A3 * POW_3(rssi_sample_i32))
151 - (RSSI_COEFF_A2 * POW_2(rssi_sample_i32))
152 - (RSSI_COEFF_TEMP * temp) - RSSI_COEFF_A0);
153
154 return compensated_rssi - (int8_t)rssi_sample;
155 }
156
157 #endif
158
nrf_802154_rssi_sample_corrected_get(uint8_t rssi_sample)159 uint8_t nrf_802154_rssi_sample_corrected_get(uint8_t rssi_sample)
160 {
161 return rssi_sample + nrf_802154_rssi_sample_temp_corr_value_get(rssi_sample);
162 }
163
nrf_802154_rssi_lqi_corrected_get(uint8_t lqi)164 uint8_t nrf_802154_rssi_lqi_corrected_get(uint8_t lqi)
165 {
166 return lqi - nrf_802154_rssi_sample_temp_corr_value_get(lqi);
167 }
168
nrf_802154_rssi_ed_corrected_get(int16_t ed)169 int16_t nrf_802154_rssi_ed_corrected_get(int16_t ed)
170 {
171 return ed - nrf_802154_rssi_sample_temp_corr_value_get(ed);
172 }
173
nrf_802154_rssi_cca_ed_threshold_corrected_get(uint8_t cca_ed)174 uint8_t nrf_802154_rssi_cca_ed_threshold_corrected_get(uint8_t cca_ed)
175 {
176 return cca_ed - nrf_802154_rssi_sample_temp_corr_value_get(cca_ed);
177 }
178
nrf_802154_rssi_ed_sample_convert(uint8_t ed_sample)179 uint8_t nrf_802154_rssi_ed_sample_convert(uint8_t ed_sample)
180 {
181 int16_t result;
182
183 result = nrf_802154_rssi_ed_corrected_get(ed_sample);
184 result = ED_RESULT_MAX * (result - EDSAMPLE_MIN_REPORTED_VALUE) /
185 (EDSAMPLE_MAX_REPORTED_VALUE - EDSAMPLE_MIN_REPORTED_VALUE);
186
187 if (result < 0)
188 {
189 result = 0;
190 }
191
192 if (result > ED_RESULT_MAX)
193 {
194 result = ED_RESULT_MAX;
195 }
196
197 return (uint8_t)result;
198 }
199
nrf_802154_rssi_dbm_from_energy_level_calculate(uint8_t energy_level)200 int8_t nrf_802154_rssi_dbm_from_energy_level_calculate(uint8_t energy_level)
201 {
202 return ((int16_t)(EDSAMPLE_MAX_REPORTED_VALUE - EDSAMPLE_MIN_REPORTED_VALUE) *
203 ((int16_t)energy_level)) /
204 ED_RESULT_MAX + EDSAMPLE_MIN_REPORTED_VALUE + ED_RSSIOFFS;
205 }
206