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, &center_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, &center_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, &center_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