1 /*
2 * Copyright (c) 2017 Oticon A/S
3 * Copyright (c) 2023 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * This file includes miscellaneous utility functions used by the RADIO model
8 * but no significant logic *
9 */
10 #include <string.h>
11 #include "bs_tracing.h"
12 #include "bs_utils.h"
13 #include "bs_pc_2G4.h"
14 #include "bs_pc_2G4_utils.h"
15 #include "NRF_RADIO.h"
16 #include "NRF_HWLowL.h"
17 #include "time_machine_if.h"
18 #include "NRF_RADIO_timings.h"
19
nrfra_check_crc_conf_ble(void)20 static void nrfra_check_crc_conf_ble(void) {
21 if ( (NRF_RADIO_regs.CRCCNF & RADIO_CRCCNF_LEN_Msk)
22 != (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) ) {
23 bs_trace_error_line_time(
24 "NRF_RADIO: CRCCNF Only 3 bytes CRC is supported in BLE mode (CRCCNF=%u)\n",
25 NRF_RADIO_regs.CRCCNF & RADIO_CRCCNF_LEN_Msk);
26 }
27 }
28
nrfra_check_ble1M_conf(void)29 static void nrfra_check_ble1M_conf(void){
30 int checked =NRF_RADIO_regs.PCNF0 &
31 (RADIO_PCNF0_PLEN_Msk
32 | RADIO_PCNF0_S1LEN_Msk
33 | RADIO_PCNF0_S0LEN_Msk
34 | RADIO_PCNF0_LFLEN_Msk);
35
36 int check = ( ( 8 << RADIO_PCNF0_LFLEN_Pos )
37 | ( 1 << RADIO_PCNF0_S0LEN_Pos )
38 | ( 0 << RADIO_PCNF0_S1LEN_Pos )
39 | ( RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos ) );
40
41 if (checked != check) {
42 bs_trace_error_line_time(
43 "NRF_RADIO: For 1 Mbps only BLE packet format is supported so far (PCNF0=%u)\n",
44 NRF_RADIO_regs.PCNF0);
45 }
46
47 nrfra_check_crc_conf_ble();
48 }
49
50
nrfra_check_ble2M_conf(void)51 static void nrfra_check_ble2M_conf(void){
52 int checked =NRF_RADIO_regs.PCNF0 &
53 (RADIO_PCNF0_PLEN_Msk
54 | RADIO_PCNF0_S1LEN_Msk
55 | RADIO_PCNF0_S0LEN_Msk
56 | RADIO_PCNF0_LFLEN_Msk);
57
58 int check = ( ( 8 << RADIO_PCNF0_LFLEN_Pos )
59 | ( 1 << RADIO_PCNF0_S0LEN_Pos )
60 | ( 0 << RADIO_PCNF0_S1LEN_Pos )
61 | ( RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos ) );
62
63 if (checked != check) {
64 bs_trace_error_line_time(
65 "NRF_RADIO: For 2 Mbps only BLE packet format is supported so far (PCNF0=%u)\n",
66 NRF_RADIO_regs.PCNF0);
67 }
68
69 nrfra_check_crc_conf_ble();
70 }
71
nrfra_check_802154_conf(void)72 static void nrfra_check_802154_conf(void){
73 int checked, check;
74
75 //Overall packet structure:
76 checked =NRF_RADIO_regs.PCNF0 &
77 ( RADIO_PCNF0_TERMLEN_Msk
78 | RADIO_PCNF0_CRCINC_Msk
79 | RADIO_PCNF0_PLEN_Msk
80 | RADIO_PCNF0_CILEN_Msk
81 | RADIO_PCNF0_S1INCL_Msk
82 | RADIO_PCNF0_S1LEN_Msk
83 | RADIO_PCNF0_S0LEN_Msk
84 | RADIO_PCNF0_LFLEN_Msk);
85
86 check = (
87 //TERM = 0
88 RADIO_PCNF0_CRCINC_Msk
89 | ( RADIO_PCNF0_PLEN_32bitZero << RADIO_PCNF0_PLEN_Pos )
90 //CILEN = 0
91 //S1INCL = 0
92 | ( 0 << RADIO_PCNF0_S1LEN_Pos )
93 | ( 0 << RADIO_PCNF0_S0LEN_Pos )
94 | ( 8 << RADIO_PCNF0_LFLEN_Pos )
95 );
96 if (checked != check) {
97 bs_trace_error_line_time(
98 "%s w 15.4 modulation only the 802154 packet format is supported so far (PCNF0=%u)\n",
99 __func__, NRF_RADIO_regs.PCNF0);
100 }
101
102 checked = NRF_RADIO_regs.PCNF1 &
103 ( RADIO_PCNF1_WHITEEN_Msk
104 | RADIO_PCNF1_ENDIAN_Msk
105 | RADIO_PCNF1_BALEN_Msk
106 | RADIO_PCNF1_STATLEN_Msk );
107
108 check = (0 << RADIO_PCNF1_WHITEEN_Pos)
109 | (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos)
110 | (0 << RADIO_PCNF1_BALEN_Pos) // => 1 byte for SFD
111 | (0 << RADIO_PCNF1_STATLEN_Pos);
112
113 if (checked != check) {
114 bs_trace_error_line_time(
115 "%s w 15.4 modulation only the 802154 packet format is supported so far (PCNF1=%u)\n",
116 __func__, NRF_RADIO_regs.PCNF1);
117 }
118
119 //CRC:
120 if ( (NRF_RADIO_regs.CRCCNF & RADIO_CRCCNF_LEN_Msk)
121 != (RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos) ) {
122 bs_trace_error_line_time(
123 "%s CRCCNF Only 2 bytes CRC is supported in 15.4 mode (CRCCNF=%u)\n",
124 __func__,
125 NRF_RADIO_regs.CRCCNF & RADIO_CRCCNF_LEN_Msk);
126 }
127 }
128
129 /*
130 * A few checks to ensure the model is only used with the currently supported packet format
131 */
nrfra_check_packet_conf(void)132 void nrfra_check_packet_conf(void){
133
134 if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_1Mbit) {
135 nrfra_check_ble1M_conf();
136 } else if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_2Mbit) {
137 nrfra_check_ble2M_conf();
138 } else if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ieee802154_250Kbit) {
139 nrfra_check_802154_conf();
140 } else {
141 bs_trace_error_line_time(
142 "NRF_RADIO: Only 1&2 Mbps BLE & 802.15.4 packet formats supported so far (MODE=%u)\n",
143 NRF_RADIO_regs.MODE);
144 }
145 }
146
nrfra_RSSI_value_to_modem_format(double rssi_value)147 uint32_t nrfra_RSSI_value_to_modem_format(double rssi_value){
148 rssi_value = -BS_MAX(rssi_value,-127);
149 rssi_value = BS_MAX(rssi_value,0);
150 return (uint32_t)rssi_value;
151 }
152
nrfra_dBm_to_modem_LQIformat(double rssi_value)153 uint8_t nrfra_dBm_to_modem_LQIformat(double rssi_value){
154 //PRF[dBm] = ED_RSSIOFFS + VALHARDWARE
155 //ED_RSSIOFFS = -93
156 //=> VALHARDWARE = PRF[dBm] - ED_RSSIOFFS = PRF[dBm] + 93
157 rssi_value +=93;
158 rssi_value = BS_MAX(rssi_value,0);
159 rssi_value = BS_MIN(rssi_value,255);
160 return (uint8_t)rssi_value;
161 }
162
nrfra_LQIformat_to_dBm(uint value)163 double nrfra_LQIformat_to_dBm(uint value){
164 //PRF[dBm] = ED_RSSIOFFS + VALHARDWARE
165 //ED_RSSIOFFS = -93
166 return (double)value - 93;
167 }
168
nrfra_is_HW_TIFS_enabled()169 int nrfra_is_HW_TIFS_enabled() {
170 if ( ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_END_DISABLE_Msk )
171 && ( ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_DISABLED_RXEN_Msk )
172 || ( NRF_RADIO_regs.SHORTS & RADIO_SHORTS_DISABLED_TXEN_Msk ) )
173 ){
174 return 1;
175 }
176 return 0;
177 }
178
179 /**
180 * Prepare a Phy Rxv2 request structure
181 * based on the radio registers configuration.
182 *
183 * Note: The abort substructure is NOT filled.
184 */
nrfra_prep_rx_request(p2G4_rxv2_t * rx_req,p2G4_address_t * rx_addresses)185 void nrfra_prep_rx_request(p2G4_rxv2_t *rx_req, p2G4_address_t *rx_addresses) {
186
187 //TOLOW: Add support for other packet formats and bitrates
188 uint8_t preamble_length;
189 uint8_t address_length;
190 uint8_t header_length;
191 uint64_t address;
192 bs_time_t pre_trunc;
193 uint16_t sync_threshold;
194
195 uint32_t freq_off = NRF_RADIO_regs.FREQUENCY & RADIO_FREQUENCY_FREQUENCY_Msk;
196 double bits_per_us;
197
198 if ((NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_1Mbit)
199 || (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_2Mbit)
200 || (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_LR125Kbit)
201 || (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_LR500Kbit)
202 ) {
203 //Note: We only support address 0 being used
204 address = ( ( NRF_RADIO_regs.PREFIX0 & RADIO_PREFIX0_AP0_Msk ) << 24 )
205 | (NRF_RADIO_regs.BASE0 >> 8);
206 }
207
208 if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_1Mbit) {
209 //Note that we only support BLE packet formats by now (so we ignore the configuration of the preamble and just assume it is what it needs to be)
210 //we rely on the Tx side error/warning being enough to warn users that we do not support other formats
211 preamble_length = 1; //1 byte
212 address_length = 4;
213 header_length = 2;
214 rx_req->radio_params.modulation = P2G4_MOD_BLE;
215 bits_per_us = 1;
216 pre_trunc = 0; //The modem can lose a lot of preamble and sync (~7µs), we leave it as 0 by now to avoid a behavior change
217 sync_threshold = 2; //(<) we tolerate less than 2 errors in the preamble and sync word together (old number, probably does not reflect the actual RADIO performance)
218 } else if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_2Mbit) {
219 preamble_length = 2; //2 bytes
220 address_length = 4;
221 header_length = 2;
222 rx_req->radio_params.modulation = P2G4_MOD_BLE2M;
223 bits_per_us = 2;
224 pre_trunc = 0; //The modem can lose a lot of preamble and sync (~7µs), we leave it as 0 by now to avoid a behavior change
225 sync_threshold = 2;
226 } else if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ieee802154_250Kbit) {
227 preamble_length = 4;
228 address_length = 1;
229 header_length = 0;
230 address = NRF_RADIO_regs.SFD & RADIO_SFD_SFD_Msk;
231 rx_req->radio_params.modulation = P2G4_MOD_154_250K_DSS;
232 bits_per_us = 0.25;
233 pre_trunc = 104; //The modem seems to be able to sync with just 3 sybmols of the preamble == lossing 13symbols|26bits|104us
234 sync_threshold = 0;
235 }
236
237 rx_req->coding_rate = 0;
238
239 p2G4_freq_t center_freq;
240 p2G4_freq_from_d(freq_off, 1, ¢er_freq);
241 rx_req->radio_params.center_freq = center_freq;
242
243 rx_req->error_calc_rate = bits_per_us*1000000;
244 rx_req->antenna_gain = 0;
245
246 rx_req->header_duration = header_length*8/bits_per_us;
247 rx_req->header_threshold = 0; //(<=) we tolerate 0 bit errors in the header which will be found in the crc (we may want to tune this)
248 rx_req->sync_threshold = sync_threshold;
249 rx_req->acceptable_pre_truncation = pre_trunc;
250
251 rx_addresses[0] = address;
252 rx_req->n_addr = 1;
253
254 rx_req->pream_and_addr_duration = (preamble_length + address_length)*8/bits_per_us;
255
256 rx_req->scan_duration = 0xFFFFFFFF; //the phy does not support infinite scans.. but this is 1 hour..
257 rx_req->forced_packet_duration = UINT32_MAX; //we follow the transmitted packet (assuming no length errors by now)
258
259 //attempt to receive
260 rx_req->start_time = hwll_phy_time_from_dev(tm_get_abs_time());
261
262 rx_req->resp_type = 0;
263 }
264
265 /**
266 * Prepare a Phy Tx request structure
267 * based on the radio registers configuration.
268 *
269 * Note: The abort substructure is NOT filled.
270 */
nrfra_prep_tx_request(p2G4_txv2_t * tx_req,uint packet_size,bs_time_t packet_duration)271 void nrfra_prep_tx_request(p2G4_txv2_t *tx_req, uint packet_size, bs_time_t packet_duration) {
272
273 if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_1Mbit) {
274 tx_req->radio_params.modulation = P2G4_MOD_BLE;
275 } else if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_2Mbit) {
276 tx_req->radio_params.modulation = P2G4_MOD_BLE2M;
277 } else if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ieee802154_250Kbit) {
278 tx_req->radio_params.modulation = P2G4_MOD_154_250K_DSS;
279 }
280
281 if ((NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_1Mbit)
282 || (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_2Mbit)
283 || (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_LR125Kbit)
284 || (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ble_LR500Kbit)
285 ) {
286 //Note: we only support BALEN = 3 (== BLE 4 byte addresses)
287 //Note: We only support address 0 being used
288 tx_req->phy_address = ( ( NRF_RADIO_regs.PREFIX0 & RADIO_PREFIX0_AP0_Msk ) << 24 )
289 | (NRF_RADIO_regs.BASE0 >> 8);
290 } else if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ieee802154_250Kbit) {
291 tx_req->phy_address = NRF_RADIO_regs.SFD & RADIO_SFD_SFD_Msk;
292 }
293
294 {
295 double TxPower = (int8_t)( NRF_RADIO_regs.TXPOWER & RADIO_TXPOWER_TXPOWER_Msk); //the cast is to sign extend it
296 tx_req->power_level = p2G4_power_from_d(TxPower); //Note that any possible Tx antenna or PA gain would need to be included here
297 }
298
299 { //Note only default freq. map supported
300 uint32_t freq_off = NRF_RADIO_regs.FREQUENCY & RADIO_FREQUENCY_FREQUENCY_Msk;
301 p2G4_freq_t center_freq;
302 p2G4_freq_from_d(freq_off, 1, ¢er_freq);
303 tx_req->radio_params.center_freq = center_freq;
304 }
305 tx_req->packet_size = packet_size; //Not including preamble or address
306
307 {
308 bs_time_t tx_start_time = tm_get_abs_time() + nrfra_timings_get_TX_chain_delay();
309 tx_req->start_tx_time = hwll_phy_time_from_dev(tx_start_time);
310 tx_req->start_packet_time = tx_req->start_tx_time ;
311 tx_req->end_tx_time = tx_req->start_tx_time + packet_duration;
312 tx_req->end_packet_time = tx_req->end_tx_time;
313 }
314 tx_req->coding_rate = 0;
315 }
316
317 /**
318 * Prepare a Phy CCA request structure
319 * based on the radio registers configuration.
320 *
321 * Note: The abort substructure is NOT filled.
322 */
nrfra_prep_cca_request(p2G4_cca_t * cca_req,bool CCA_not_ED)323 void nrfra_prep_cca_request(p2G4_cca_t *cca_req, bool CCA_not_ED) {
324
325 cca_req->start_time = hwll_phy_time_from_dev(tm_get_abs_time()); //We start right now
326 cca_req->antenna_gain = 0;
327
328 uint32_t freq_off = NRF_RADIO_regs.FREQUENCY & RADIO_FREQUENCY_FREQUENCY_Msk;
329 p2G4_freq_t center_freq;
330 p2G4_freq_from_d(freq_off, 1, ¢er_freq);
331 cca_req->radio_params.center_freq = center_freq;
332
333 if (NRF_RADIO_regs.MODE == RADIO_MODE_MODE_Ieee802154_250Kbit) {
334 cca_req->radio_params.modulation = P2G4_MOD_154_250K_DSS;
335 } else {
336 bs_trace_error_line_time("CCA procedure only supported with 15.4 modulation\n");
337 }
338
339 int symbol_time = 16; //micros
340
341 if (CCA_not_ED) { //CCA request
342 uint edthreshold = (NRF_RADIO_regs.CCACTRL & RADIO_CCACTRL_CCAEDTHRES_Msk) >> RADIO_CCACTRL_CCAEDTHRES_Pos;
343 uint CCAMode = (NRF_RADIO_regs.CCACTRL & RADIO_CCACTRL_CCAMODE_Msk) >> RADIO_CCACTRL_CCAMODE_Pos;
344 double carrier_detect_level = -110; //dBm : Any detectable signal by the modem
345
346 cca_req->scan_duration = 8*symbol_time;
347 cca_req->scan_period = 2*symbol_time; //let's measure 4 times (model design choice)
348
349 if (CCAMode == RADIO_CCACTRL_CCAMODE_EdMode) {
350 cca_req->rssi_threshold = p2G4_RSSI_value_from_dBm(nrfra_LQIformat_to_dBm(edthreshold));
351 cca_req->mod_threshold = p2G4_RSSI_value_from_dBm(100/*dBm*/); //not used
352 cca_req->stop_when_found = 0;
353 } else if (CCAMode == RADIO_CCACTRL_CCAMODE_CarrierMode) {
354 cca_req->stop_when_found = 1;
355 cca_req->rssi_threshold = p2G4_RSSI_value_from_dBm(100/*dBm*/); //not used
356 cca_req->mod_threshold = p2G4_RSSI_value_from_dBm(carrier_detect_level);
357 //The Phy does not support detecting just based on something close enough in the correlator output
358 //so we ignore CCACTRL.CCACORRCNT & CCACTRL.CCACORRTHRES
359 } else if ((CCAMode == RADIO_CCACTRL_CCAMODE_CarrierAndEdMode)
360 || (CCAMode == RADIO_CCACTRL_CCAMODE_CarrierOrEdMode) ) {
361 cca_req->stop_when_found = 1;
362 cca_req->rssi_threshold = p2G4_RSSI_value_from_dBm(nrfra_LQIformat_to_dBm(edthreshold));
363 cca_req->mod_threshold = p2G4_RSSI_value_from_dBm(carrier_detect_level);
364 } else if (CCAMode == RADIO_CCACTRL_CCAMODE_EdModeTest1) {
365 cca_req->rssi_threshold = p2G4_RSSI_value_from_dBm(nrfra_LQIformat_to_dBm(edthreshold));
366 cca_req->mod_threshold = p2G4_RSSI_value_from_dBm(100/*dBm*/); //not used
367 cca_req->stop_when_found = 2;
368 } else {
369 bs_trace_error_time_line("%s, CCAMODE=%i support not yet implemented\n",
370 __func__, CCAMode);
371 }
372 } else { //ED request
373 cca_req->scan_duration = 8 * symbol_time * ((NRF_RADIO_regs.EDCNT & RADIO_EDCNT_EDCNT_Msk) + 1);
374 cca_req->scan_period = 2 * symbol_time; //let's measure 4 times per EDCNT (model design choice)
375 cca_req->rssi_threshold = p2G4_RSSI_value_from_dBm(100/*dBm*/); //not used
376 cca_req->mod_threshold = p2G4_RSSI_value_from_dBm(100/*dBm*/); //not used
377 cca_req->stop_when_found = 0;
378 }
379 }
380
381
382 /**
383 * Return the CRC length in bytes
384 */
nrfra_get_crc_length()385 uint nrfra_get_crc_length(){
386 return (NRF_RADIO_regs.CRCCNF & RADIO_CRCCNF_LEN_Msk) >> RADIO_CRCCNF_LEN_Pos;
387 }
388
389 /*
390 * Return the payload length, NOT including the CRC length
391 */
nrfra_get_payload_length(uint8_t * buf)392 uint nrfra_get_payload_length(uint8_t *buf){
393 int S0Len;
394 int LFLenb, LFLenB;
395 uint payload_len = 0;
396 S0Len = (NRF_RADIO_regs.PCNF0 & RADIO_PCNF0_S0LEN_Msk) >> RADIO_PCNF0_S0LEN_Pos;
397
398 LFLenb = (NRF_RADIO_regs.PCNF0 & RADIO_PCNF0_LFLEN_Msk) >> RADIO_PCNF0_LFLEN_Pos;
399 LFLenB = (LFLenb + 7)/8;
400
401 for (int i = 0; i < LFLenB; i++){
402 payload_len += buf[S0Len+i] << i*8;
403 }
404
405 if (NRF_RADIO_regs.PCNF0 & RADIO_PCNF0_CRCINC_Msk) {
406 int crc_len = nrfra_get_crc_length();
407 if (payload_len >= crc_len) {
408 payload_len -= crc_len;
409 } else {
410 bs_trace_error_time_line("Programmed payload length (%i) smaller than CRC length (%i), "
411 "while it was configured as including the CRC.. => SW programming error\n",
412 payload_len, crc_len);
413 }
414 }
415 return payload_len;
416 }
417
418 /**
419 * Assemble a packet to be transmitted out thru the air into tx_buf[]
420 * Omitting the preamble and address/sync flag
421 *
422 * Return copied payload size (after S0 + len + S1) into tx_buf[]
423 * (without the CRC)
424 *
425 * Note: When adding support for CodedPhy and or other packet formats,
426 * this needs to be reworked together with the start_Tx()
427 * function, as it is all way too interdependent
428 */
nrfra_tx_copy_payload(uint8_t * tx_buf)429 uint nrfra_tx_copy_payload(uint8_t *tx_buf){
430 int S0Len, S1LenB, LFLenB; //All in bytes
431 int LFLenb, S1LenAirb;
432 int i;
433 uint payload_len;
434
435 S0Len = (NRF_RADIO_regs.PCNF0 & RADIO_PCNF0_S0LEN_Msk) >> RADIO_PCNF0_S0LEN_Pos;
436
437
438 S1LenAirb = (NRF_RADIO_regs.PCNF0 & RADIO_PCNF0_S1LEN_Msk) >> RADIO_PCNF0_S1LEN_Pos;
439 S1LenB = (S1LenAirb + 7)/8; //This is just : S1Offset = ceil(PCNF0.S1LEN / 8)
440
441 LFLenb = (NRF_RADIO_regs.PCNF0 & RADIO_PCNF0_LFLEN_Msk) >> RADIO_PCNF0_LFLEN_Pos;
442 LFLenB = (LFLenb + 7)/8;
443
444 //copy from RAM to Tx buffer
445 i = 0;
446 if (S0Len) {
447 tx_buf[0] = ((uint8_t*)NRF_RADIO_regs.PACKETPTR)[0];
448 i++;
449 }
450 for (int j = 0; j < LFLenB; j++){ //Copy up to 2 Length bytes
451 tx_buf[i] = ((uint8_t*)NRF_RADIO_regs.PACKETPTR)[i];
452 i++;
453 }
454 int S1Off = 0;
455 if ( NRF_RADIO_regs.PCNF0 & ( RADIO_PCNF0_S1INCL_Include << RADIO_PCNF0_S1INCL_Pos ) ) {
456 if (S1LenB == 0) {
457 S1Off = 1; //We skip 1 S1 byte in RAM
458 }
459 /*
460 * If S1INCL and S1LEN > 0, the assumption is that the
461 * the size in RAM will just be the same as in air
462 * TODO: this behavior needs to be confirmed
463 */
464 }
465
466 payload_len = nrfra_get_payload_length(tx_buf);
467 int copy_len = payload_len + S1LenB;
468 memcpy(&tx_buf[i], &((uint8_t*)NRF_RADIO_regs.PACKETPTR)[i + S1Off], copy_len);
469 return payload_len;
470 }
471