ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_nrf5_sdk15_communication_radio.c
Go to the documentation of this file.
1 
13 #if RUUVI_NRF5_SDK15_RADIO_ENABLED
14 #include "ruuvi_driver_error.h"
15 #include "ruuvi_nrf5_sdk15_error.h"
18 
19 
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include "nordic_common.h"
23 #include "nrf_soc.h"
24 #include "nrf_sdh.h"
25 #include "nrf_sdh_ble.h"
26 #include "nrf_sdm.h"
27 #include "ble_advdata.h"
28 #include "ble_radio_notification.h"
29 #include "sdk_errors.h"
30 
32 static ri_radio_activity_interrupt_fp_t on_radio_activity_callback = NULL;
33 static ri_radio_modulation_t m_modulation; //<! Modulation for radio ops.
34 
36 #ifndef PHY_RAM_START
37 # define PHY_RAM_START 0x20000000
38 #endif
39 
48 static void on_radio_evt (bool active)
49 {
50  // Convert to Ruuvi enum
51  ri_radio_activity_evt_t evt = active ?
53 
54  // Call common event handler if set
55  if (NULL != on_radio_activity_callback) { on_radio_activity_callback (evt); }
56 }
57 
59 {
60  rd_status_t status = RD_SUCCESS;
61  ret_code_t err_code = NRF_SUCCESS;
62 
63  if (ri_radio_is_init())
64  {
65  status |= RD_ERROR_INVALID_STATE;
66  }
67  else if (!ri_radio_supports (modulation))
68  {
69  status |= RD_ERROR_INVALID_PARAM;
70  }
71  else
72  {
73  err_code = nrf_sdh_enable_request();
74  RD_ERROR_CHECK (err_code, NRF_SUCCESS);
75  // Configure the BLE stack using the default settings.
76  // Fetch the start address of the application RAM.
77  uint32_t ram_start = 0;
78  // As of SD 6.1.1, only one advertising configuration is allowed.
79  err_code |= nrf_sdh_ble_default_cfg_set (RUUVI_NRF5_SDK15_BLE4_STACK_CONN_TAG,
80  &ram_start);
81  RD_ERROR_CHECK (err_code, NRF_SUCCESS);
82  // TODO - find the correct way to define large enough GATT queue for extended GATT event.
83  //ble_cfg_t conn_cfg = { 0 };
84  //conn_cfg.conn_cfg.conn_cfg_tag = RUUVI_NRF5_SDK15_BLE4_STACK_CONN_TAG;
85  //err_code |= sd_ble_cfg_set (BLE_CONN_CFG_GATTS, &conn_cfg, ram_start);
86  // Enable BLE stack.
87  err_code |= nrf_sdh_ble_enable (&ram_start);
88  // Enable connection event extension for faster data rate
89  static ble_opt_t opt = {0};
90  opt.common_opt.conn_evt_ext.enable = true;
91  err_code |= sd_ble_opt_set (BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
92  RD_ERROR_CHECK (err_code, NRF_SUCCESS);
93  // Initialize radio interrupts
94  err_code |= ble_radio_notification_init (RUUVI_NRF5_SDK15_RADIO_IRQ_PRIORITY,
95  NRF_RADIO_NOTIFICATION_DISTANCE_800US,
96  on_radio_evt);
97  // Store desired modulation
98  m_modulation = modulation;
99  }
100 
101  return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code) | status;
102 }
103 
105 {
106  // Ask everything nicely to shut down.
107  nrf_sdh_disable_request();
108  // Shut everything down by force.
109  sd_softdevice_disable();
110  on_radio_activity_callback = NULL;
111  return RD_SUCCESS;
112 }
113 
124 rd_status_t ri_radio_address_get (uint64_t * const address)
125 {
126  uint32_t status = NRF_SUCCESS;
127  rd_status_t err_code = RD_SUCCESS;
128  uint64_t mac = 0;
129 
130  if (!ri_radio_is_init())
131  {
132  // Random static BLE address has 2 top bits set
133  mac |= (uint64_t) ( (NRF_FICR->DEVICEADDR[0] >> 0) & 0xFF) << 0;
134  mac |= (uint64_t) ( (NRF_FICR->DEVICEADDR[0] >> 8) & 0xFF) << 8;
135  mac |= (uint64_t) ( (NRF_FICR->DEVICEADDR[0] >> 16) & 0xFF) << 16;
136  mac |= (uint64_t) ( (NRF_FICR->DEVICEADDR[0] >> 24) & 0xFF) << 24;
137  mac |= (uint64_t) ( (NRF_FICR->DEVICEADDR[1] >> 0) & 0xFF) << 32;
138  mac |= (uint64_t) ( (NRF_FICR->DEVICEADDR[1] >> 8 | 0xC0) & 0xFF) << 40;
139  }
140  else
141  {
142  ble_gap_addr_t addr;
143  addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
144  status |= sd_ble_gap_addr_get (&addr);
145  mac |= (uint64_t) (addr.addr[0]) << 0;
146  mac |= (uint64_t) (addr.addr[1]) << 8;
147  mac |= (uint64_t) (addr.addr[2]) << 16;
148  mac |= (uint64_t) (addr.addr[3]) << 24;
149  mac |= (uint64_t) (addr.addr[4]) << 32;
150  mac |= (uint64_t) (addr.addr[5]) << 40;
151  }
152 
153  *address = mac;
154  return ruuvi_nrf5_sdk15_to_ruuvi_error (status) | err_code;
155 }
156 
157 rd_status_t ri_radio_address_set (const uint64_t address)
158 {
159  ble_gap_addr_t addr;
160  addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
161  addr.addr[0] = address >> 0;
162  addr.addr[1] = address >> 8;
163  addr.addr[2] = address >> 16;
164  addr.addr[3] = address >> 24;
165  addr.addr[4] = address >> 32;
166  addr.addr[5] = address >> 40;
167  return ruuvi_nrf5_sdk15_to_ruuvi_error (sd_ble_gap_addr_set (&addr));
168 }
169 
170 
172 {
173  // Warn user if CB is not NULL and non-null pointer is set, do not overwrite previous pointer.
174  if (NULL != handler && NULL != on_radio_activity_callback)
175  {
177  }
178  else
179  {
180  on_radio_activity_callback = handler;
181  }
182 }
183 
184 bool ri_radio_is_init (void)
185 {
186  return nrf_sdh_is_enabled();
187 }
188 
190 {
191  rd_status_t err_code = RD_SUCCESS;
192 
193  if (NULL == p_modulation)
194  {
195  err_code = RD_ERROR_NULL;
196  }
197  else if (!ri_radio_is_init())
198  {
199  err_code = RD_ERROR_INVALID_STATE;
200  }
201  else
202  {
203  *p_modulation = m_modulation;
204  }
205 
206  return err_code;
207 }
208 
209 
210 uint8_t ruuvi_nrf5_sdk15_radio_phy_get (void)
211 {
212  uint8_t nrf_modulation = BLE_GAP_PHY_NOT_SET;
213  ri_radio_modulation_t modulation;
214  rd_status_t err_code = ri_radio_get_modulation (&modulation);
215 
216  if (RD_SUCCESS == err_code)
217  {
218  switch (modulation)
219  {
221  nrf_modulation = BLE_GAP_PHY_CODED;
222  break;
223 
224  case RI_RADIO_BLE_1MBPS:
225  nrf_modulation = BLE_GAP_PHY_1MBPS;
226  break;
227 
228  case RI_RADIO_BLE_2MBPS:
229  nrf_modulation = BLE_GAP_PHY_2MBPS;
230  break;
231 
232  default:
233  nrf_modulation = BLE_GAP_PHY_NOT_SET;
234  break;
235  }
236  }
237 
238  return nrf_modulation;
239 }
240 
241 void ruuvi_nrf5_sdk15_radio_channels_set (uint8_t * const nrf_channels,
242  const ri_radio_channels_t channels)
243 {
244  memset (nrf_channels, 0, sizeof (ble_gap_ch_mask_t));
245  nrf_channels[4] |= (!channels.channel_37) << 5;
246  nrf_channels[4] |= (!channels.channel_38) << 6;
247  nrf_channels[4] |= (!channels.channel_39) << 7;
248 }
249 
251 {
252  bool supported = false;
253 
254  switch (modulation)
255  {
257 # if S140
258  supported = true;
259 # else
260  supported = false;
261 # endif
262  break;
263 
264  case RI_RADIO_BLE_1MBPS:
265  supported = true;
266  break;
267 
268  case RI_RADIO_BLE_2MBPS:
269  supported = true;
270  break;
271 
272  default:
273  supported = false;
274  break;
275  }
276 
277  return supported;
278 }
279 
280 #endif
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
#define RD_ERROR_NULL
Null Pointer.
#define RD_ERROR_FATAL
Program should always reset after this.
uint32_t rd_status_t
bitfield for representing errors
rd_status_t ruuvi_nrf5_sdk15_to_ruuvi_error(const ret_code_t error)
convert nrf5 sdk15 error code into Ruuvi error code.
#define RD_ERROR_CHECK(error, mask)
Shorthand macro for calling the rd_error_check with current file & line.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
void ri_radio_activity_callback_set(const ri_radio_activity_interrupt_fp_t handler)
Setup radio activity interrupt.
rd_status_t ri_radio_get_modulation(ri_radio_modulation_t *const p_modulation)
Get the modulation used by application.
bool ri_radio_is_init()
Check if radio is initialized.
ri_radio_activity_evt_t
radio activity event type.
rd_status_t ri_radio_init(const ri_radio_modulation_t modulation)
Enable radio stack for an user. This function also starts radio activity callbacks internally.
rd_status_t ri_radio_uninit()
Release radio stack.
rd_status_t ri_radio_address_get(uint64_t *const address)
bool ri_radio_supports(ri_radio_modulation_t modulation)
Check if radio supports given modulation.
void(* ri_radio_activity_interrupt_fp_t)(const ri_radio_activity_evt_t evt)
Type of radio activity interrupt. This is common to all radio modules, i,e, the callback gets called ...
ri_radio_modulation_t
type of radio modulation to be used.
rd_status_t ri_radio_address_set(uint64_t const address)
@ RI_RADIO_AFTER
Event is after radio activity, i.e. radio was turned off.
@ RI_RADIO_BEFORE
Event is before radio goes active, i.e. radio turns on soon.
@ RI_RADIO_BLE_1MBPS
"Normal" BLE 4 modulation
@ RI_RADIO_BLE_2MBPS
"Fast BLE". Advertising uses 1MBPS primary advertisement followed by 2 MBit/s extended advertisement.
@ RI_RADIO_BLE_125KBPS
Also known as BLE Long Range S=8.
#define RUUVI_NRF5_SDK15_RADIO_IRQ_PRIORITY
priorities 0,1, 4,5 are reserved by SD
#define RUUVI_NRF5_SDK15_BLE4_STACK_CONN_TAG
< Check if NRF_NFC is required
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Bitfield to describe related sensor data.
uint8_t channel_37
BLE channel 37, 2402 MHz.
uint8_t channel_39
BLE channel 39, 2480 MHz.
uint8_t channel_38
BLE channel 38, 2426 MHz.