nrf_csense.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "sdk_common.h"
  41. #if NRF_MODULE_ENABLED(NRF_CSENSE)
  42. #include <string.h>
  43. #include <nrfx.h>
  44. #include "nrf_csense.h"
  45. #include "nrf_peripherals.h"
  46. #include "nrf_assert.h"
  47. #if defined(__CC_ARM)
  48. #elif defined(__ICCARM__)
  49. #elif defined(__GNUC__)
  50. #ifndef __CLZ
  51. #define __CLZ(x) __builtin_clz(x)
  52. #endif
  53. #endif
  54. APP_TIMER_DEF(nrf_csense_timer);
  55. typedef struct
  56. {
  57. nrf_csense_event_handler_t event_handler; //!< Event handler for module.
  58. nrfx_drv_state_t state; //!< State of module.
  59. uint32_t ticks; //!< Timeout ticks of app_timer instance controlling csense module.
  60. uint16_t raw_analog_values[MAX_ANALOG_INPUTS]; //!< Raw values of measurements.
  61. uint8_t enabled_analog_channels_mask; //!< Mask of enabled channels.
  62. } nrf_csense_t;
  63. /* Module instance. */
  64. static nrf_csense_t m_nrf_csense;
  65. /* First of touch elements instances that creates linked list. */
  66. static nrf_csense_instance_t * mp_nrf_csense_instance_head;
  67. /* Buffer for values got from measurements. */
  68. static uint16_t m_values_buffer[NRF_CSENSE_MAX_PADS_NUMBER];
  69. /**
  70. * @brief Function for handling time-outs.
  71. *
  72. * @param[in] p_context General purpose pointer. Will be passed to the time-out handler
  73. * when the timer expires.
  74. */
  75. static void csense_timer_handler(void * p_context)
  76. {
  77. if (m_nrf_csense.state != NRFX_DRV_STATE_POWERED_ON)
  78. {
  79. return;
  80. }
  81. if (nrf_drv_csense_sample() == NRF_ERROR_BUSY)
  82. {
  83. return;
  84. }
  85. }
  86. /**
  87. * @brief Function for updating maximum or minimum value.
  88. *
  89. * @param [in] p_instance Pointer to csense instance.
  90. * @param [in] p_pad Pointer to pad which should be checked for minimum or maximum value.
  91. */
  92. __STATIC_INLINE void min_or_max_update(nrf_csense_instance_t const * p_instance,
  93. nrf_csense_pad_t * p_pad)
  94. {
  95. uint16_t val = m_nrf_csense.raw_analog_values[p_pad->analog_input_number];
  96. if (p_instance->min_max[p_pad->pad_index].min_value > val)
  97. {
  98. p_instance->min_max[p_pad->pad_index].min_value = val;
  99. }
  100. if (p_instance->min_max[p_pad->pad_index].max_value < val)
  101. {
  102. p_instance->min_max[p_pad->pad_index].max_value = val;
  103. }
  104. }
  105. /**
  106. * @brief Function for calculating proportions on slider pad.
  107. *
  108. * @note This function help to self calibrate the pads.
  109. *
  110. * @param [in] p_instance Pointer to csense instance.
  111. * @param [in] p_pad Pointer to pad to calculate ratio for.
  112. *
  113. * @return Difference between maximum and minimum values read on pads or 0 if minimum is bigger than maximum.
  114. *
  115. */
  116. __STATIC_INLINE uint16_t ratio_calculate(nrf_csense_instance_t const * p_instance,
  117. nrf_csense_pad_t * p_pad)
  118. {
  119. if (p_instance->min_max[p_pad->pad_index].max_value > p_instance->min_max[p_pad->pad_index].min_value)
  120. {
  121. uint16_t scale;
  122. scale = (uint16_t)(p_instance->min_max[p_pad->pad_index].max_value -
  123. p_instance->min_max[p_pad->pad_index].min_value);
  124. return scale;
  125. }
  126. else
  127. {
  128. return 0;
  129. }
  130. }
  131. /**
  132. * @brief Function for calculating step.
  133. *
  134. * Function calculates step for slider basing on index of touched pads and values measured on
  135. * them and neighboring pads.
  136. *
  137. * @param[in] p_instance Pointer to csense instance.
  138. * @param[in] pad_index Index of the pad.
  139. *
  140. * @return Detected touched step.
  141. */
  142. static uint16_t calculate_step(nrf_csense_instance_t * p_instance,
  143. uint8_t pad_index)
  144. {
  145. uint16_t step = 0;
  146. uint32_t values_sum;
  147. uint32_t values_product;
  148. pad_index += 1;
  149. values_sum = m_values_buffer[pad_index] + m_values_buffer[pad_index - 1] +
  150. m_values_buffer[pad_index + 1];
  151. values_product = (uint32_t)(p_instance->steps-1) *
  152. (m_values_buffer[pad_index - 1] * (pad_index - 2)
  153. + m_values_buffer[pad_index] * (pad_index - 1)
  154. + m_values_buffer[pad_index + 1] * (pad_index));
  155. step = 1 + ROUNDED_DIV(values_product, (values_sum * (p_instance->number_of_pads - 1))); // Add 1 to the result of the division
  156. // to get the appropriate range of values.
  157. memset((void*)m_values_buffer, 0, sizeof(m_values_buffer));
  158. return step;
  159. }
  160. /**
  161. * @brief Function for finding mask of touched pads.
  162. *
  163. * @param [in] p_instance Pointer to csense instance.
  164. *
  165. * @return Mask of touched pads.
  166. */
  167. static uint32_t find_touched_mask(nrf_csense_instance_t const * p_instance)
  168. {
  169. uint32_t touched_mask = 0;
  170. uint16_t max_value = 0;
  171. uint16_t ratio;
  172. nrf_csense_pad_t * p_pad;
  173. for (p_pad = p_instance->p_nrf_csense_pad; NULL != p_pad; p_pad = p_pad->p_next_pad) // run through all pads and look for those with biggest value
  174. {
  175. min_or_max_update(p_instance, p_pad);
  176. ratio = ratio_calculate(p_instance, p_pad);
  177. if (ratio == 0)
  178. {
  179. return 0;
  180. }
  181. uint16_t val =
  182. (uint16_t)(((uint32_t)(m_nrf_csense.raw_analog_values[p_pad->analog_input_number] -
  183. p_instance->min_max[p_pad->pad_index].min_value) *
  184. NRF_CSENSE_MAX_VALUE) / ratio);
  185. m_values_buffer[p_pad->pad_index+1] = val;
  186. if (val > max_value)
  187. {
  188. max_value = val;
  189. touched_mask = (1UL << (p_pad->pad_index));
  190. }
  191. else if (val == max_value)
  192. {
  193. max_value = val;
  194. touched_mask |= (1UL << (p_pad->pad_index));
  195. }
  196. }
  197. return touched_mask;
  198. }
  199. /**
  200. * @brief Function for finding touched pad.
  201. *
  202. * If there is more than one pad connected to an analog channel this functions which one was actually touched. This is done by
  203. * comparing values of neighboring pads.
  204. *
  205. * @param [in] instance Pointer to csense instance.
  206. * @param [in] touched_mask Mask of touched pads.
  207. *
  208. * @return Touched pad.
  209. */
  210. static uint16_t find_touched_pad(nrf_csense_instance_t const * p_instance,
  211. uint32_t touched_mask)
  212. {
  213. uint8_t i;
  214. uint8_t biggest_deviation = 0;
  215. uint8_t temp_biggest = 0;
  216. uint16_t pad = UINT16_MAX;
  217. static uint16_t previous_pad = 0;
  218. for (i = 0; i < (p_instance->number_of_pads); i++)
  219. {
  220. if ((1UL << i) & touched_mask)
  221. {
  222. temp_biggest = m_values_buffer[i];
  223. temp_biggest += m_values_buffer[i + 2];
  224. if ((i != 0) && (i != ((p_instance->number_of_pads-1))))
  225. {
  226. temp_biggest /= 2;
  227. }
  228. if ((temp_biggest > NRF_CSENSE_PAD_DEVIATION) &&
  229. (temp_biggest > biggest_deviation))
  230. {
  231. biggest_deviation = temp_biggest;
  232. pad = i;
  233. }
  234. }
  235. }
  236. if (pad == UINT16_MAX)
  237. {
  238. pad = previous_pad;
  239. }
  240. else
  241. {
  242. previous_pad = pad;
  243. }
  244. return pad;
  245. }
  246. /**
  247. * @brief Function for finding touched step.
  248. *
  249. * @param [in] instance Pointer to csense instance.
  250. *
  251. * @return Detected touched step.
  252. */
  253. static uint16_t find_touched_step(nrf_csense_instance_t * p_instance)
  254. {
  255. uint32_t touched_mask = 0;
  256. uint16_t pad = 0;
  257. uint16_t step;
  258. touched_mask = find_touched_mask(p_instance);
  259. if (touched_mask == 0)
  260. {
  261. return UINT16_MAX;
  262. }
  263. if ((touched_mask & (-(int32_t)touched_mask)) == touched_mask) // Check if there is only one pad with greatest value.
  264. {
  265. pad = 31 - __CLZ(touched_mask);
  266. }
  267. else
  268. {
  269. pad = find_touched_pad(p_instance, touched_mask);
  270. }
  271. step = calculate_step(p_instance, pad);
  272. return step;
  273. }
  274. /**
  275. * @brief Event handler for csense.
  276. *
  277. * param [in] p_event_struct Pointer to event structure.
  278. */
  279. static void csense_event_handler(nrf_drv_csense_evt_t * p_event_struct)
  280. {
  281. nrf_csense_evt_t event;
  282. static uint16_t prev_analog_values[MAX_ANALOG_INPUTS];
  283. bool touched = false;
  284. nrf_csense_instance_t * instance;
  285. uint8_t i;
  286. if ((m_nrf_csense.enabled_analog_channels_mask & (1UL << (p_event_struct->analog_channel))) == 0)
  287. {
  288. return;
  289. }
  290. m_nrf_csense.raw_analog_values[p_event_struct->analog_channel] = p_event_struct->read_value;
  291. if (nrf_drv_csense_is_busy())
  292. {
  293. return;
  294. }
  295. for (instance = mp_nrf_csense_instance_head; instance != NULL;
  296. instance = instance->p_next_instance) // run through all instances
  297. {
  298. if (instance->is_active)
  299. {
  300. event.p_instance = instance;
  301. nrf_csense_pad_t * p_pad = instance->p_nrf_csense_pad;
  302. for (i = 0; i < MAX_ANALOG_INPUTS; i++)
  303. {
  304. if ((m_nrf_csense.raw_analog_values[i] <
  305. (prev_analog_values[i] - NRF_CSENSE_PAD_HYSTERESIS)) ||
  306. (m_nrf_csense.raw_analog_values[i] >
  307. (prev_analog_values[i] + NRF_CSENSE_PAD_HYSTERESIS)))
  308. {
  309. touched = true;
  310. break;
  311. }
  312. }
  313. if (touched)
  314. {
  315. touched = false;
  316. for (p_pad = instance->p_nrf_csense_pad; p_pad != NULL;
  317. p_pad = p_pad->p_next_pad)
  318. {
  319. if (m_nrf_csense.raw_analog_values[p_pad->analog_input_number] >
  320. p_pad->threshold)
  321. {
  322. touched = true;
  323. break;
  324. }
  325. }
  326. }
  327. else
  328. {
  329. continue;
  330. }
  331. // Specify the event
  332. if ((instance->is_touched) && touched)
  333. {
  334. // dragged
  335. if (instance->number_of_pads > 1)
  336. {
  337. event.params.slider.step = find_touched_step(instance);
  338. event.nrf_csense_evt_type = NRF_CSENSE_SLIDER_EVT_DRAGGED;
  339. m_nrf_csense.event_handler(&event);
  340. }
  341. }
  342. else if ((!(instance->is_touched)) && touched)
  343. {
  344. // pressed
  345. if (instance->number_of_pads > 1)
  346. {
  347. event.params.slider.step = find_touched_step(instance);
  348. event.nrf_csense_evt_type = NRF_CSENSE_SLIDER_EVT_PRESSED;
  349. }
  350. else
  351. {
  352. event.nrf_csense_evt_type = NRF_CSENSE_BTN_EVT_PRESSED;
  353. }
  354. instance->is_touched = true;
  355. m_nrf_csense.event_handler(&event);
  356. }
  357. else if ((instance->is_touched) && (!touched))
  358. {
  359. // released
  360. if (instance->number_of_pads > 1)
  361. {
  362. event.params.slider.step = find_touched_step(instance);
  363. event.nrf_csense_evt_type = NRF_CSENSE_SLIDER_EVT_RELEASED;
  364. }
  365. else
  366. {
  367. event.nrf_csense_evt_type = NRF_CSENSE_BTN_EVT_RELEASED;
  368. }
  369. instance->is_touched = false;
  370. m_nrf_csense.event_handler(&event);
  371. }
  372. else
  373. {
  374. // nothing changed
  375. }
  376. }
  377. touched = false;
  378. }
  379. memset(m_values_buffer, 0, sizeof(m_values_buffer));
  380. memcpy(prev_analog_values, m_nrf_csense.raw_analog_values,
  381. sizeof(m_nrf_csense.raw_analog_values));
  382. }
  383. ret_code_t nrf_csense_init(nrf_csense_event_handler_t event_handler,
  384. uint32_t ticks)
  385. {
  386. ASSERT(event_handler != NULL);
  387. ASSERT(m_nrf_csense.state == NRFX_DRV_STATE_UNINITIALIZED);
  388. ret_code_t err_code;
  389. static const nrf_drv_csense_config_t m_csense_config =
  390. {
  391. .output_pin = NRF_CSENSE_OUTPUT_PIN
  392. };
  393. m_nrf_csense.event_handler = event_handler;
  394. m_nrf_csense.ticks = ticks;
  395. mp_nrf_csense_instance_head = NULL;
  396. err_code = app_timer_create(&nrf_csense_timer, APP_TIMER_MODE_REPEATED, csense_timer_handler);
  397. if (err_code != NRF_SUCCESS)
  398. {
  399. return err_code;
  400. }
  401. err_code = nrf_drv_csense_init(&m_csense_config, csense_event_handler);
  402. if (err_code != NRF_SUCCESS)
  403. {
  404. return err_code;
  405. }
  406. m_nrf_csense.state = NRFX_DRV_STATE_INITIALIZED;
  407. return NRF_SUCCESS;
  408. }
  409. ret_code_t nrf_csense_uninit(void)
  410. {
  411. ASSERT(m_nrf_csense.state != NRFX_DRV_STATE_UNINITIALIZED);
  412. ret_code_t err_code;
  413. nrf_csense_instance_t ** pp_instance = &mp_nrf_csense_instance_head;
  414. err_code = nrf_drv_csense_uninit();
  415. if (err_code != NRF_SUCCESS)
  416. {
  417. return err_code;
  418. }
  419. if (m_nrf_csense.enabled_analog_channels_mask != 0)
  420. {
  421. err_code = app_timer_stop(nrf_csense_timer);
  422. if (err_code != NRF_SUCCESS)
  423. {
  424. return err_code;
  425. }
  426. }
  427. while ((*pp_instance) != NULL)
  428. {
  429. nrf_csense_instance_t ** pp_instance_next = (&(*pp_instance)->p_next_instance);
  430. (*pp_instance) = NULL;
  431. pp_instance = pp_instance_next;
  432. }
  433. memset((void *)&m_nrf_csense, 0, sizeof(nrf_csense_t));
  434. m_nrf_csense.state = NRFX_DRV_STATE_UNINITIALIZED;
  435. return NRF_SUCCESS;
  436. }
  437. ret_code_t nrf_csense_add(nrf_csense_instance_t * const p_instance)
  438. {
  439. ASSERT(m_nrf_csense.state != NRFX_DRV_STATE_UNINITIALIZED);
  440. ASSERT(p_instance->p_next_instance == NULL);
  441. ASSERT(p_instance != NULL);
  442. ret_code_t err_code;
  443. nrf_csense_instance_t ** pp_instance = &mp_nrf_csense_instance_head;
  444. while ((*pp_instance) != NULL)
  445. {
  446. ASSERT((*pp_instance) != p_instance);
  447. pp_instance = &((*pp_instance)->p_next_instance);
  448. }
  449. *pp_instance = p_instance;
  450. err_code = nrf_csense_enable(p_instance);
  451. return err_code;
  452. }
  453. ret_code_t nrf_csense_enable(nrf_csense_instance_t * const p_instance)
  454. {
  455. ASSERT(m_nrf_csense.state != NRFX_DRV_STATE_UNINITIALIZED);
  456. ASSERT(p_instance != NULL);
  457. ret_code_t err_code;
  458. nrf_csense_pad_t const * p_pad;
  459. uint8_t analog_channels_mask = 0;
  460. if (m_nrf_csense.enabled_analog_channels_mask == 0)
  461. {
  462. err_code = app_timer_start(nrf_csense_timer, m_nrf_csense.ticks, NULL);
  463. if (err_code != NRF_SUCCESS)
  464. {
  465. return err_code;
  466. }
  467. }
  468. p_instance->is_active = true;
  469. for (p_pad = p_instance->p_nrf_csense_pad; p_pad != NULL; p_pad = p_pad->p_next_pad)
  470. {
  471. p_instance->min_max[p_pad->pad_index].min_value = UINT16_MAX;
  472. // If channel was already enabled skip it.
  473. if ((m_nrf_csense.enabled_analog_channels_mask & (1UL << (p_pad->analog_input_number))) == 0)
  474. {
  475. analog_channels_mask |= (1UL << (p_pad->analog_input_number));
  476. m_nrf_csense.enabled_analog_channels_mask |= (1UL << (p_pad->analog_input_number));
  477. }
  478. }
  479. m_nrf_csense.state = NRFX_DRV_STATE_POWERED_ON;
  480. nrf_drv_csense_channels_enable(analog_channels_mask);
  481. return NRF_SUCCESS;
  482. }
  483. ret_code_t nrf_csense_disable(nrf_csense_instance_t * const p_instance)
  484. {
  485. ASSERT(m_nrf_csense.state == NRFX_DRV_STATE_POWERED_ON);
  486. ret_code_t err_code;
  487. nrf_csense_instance_t * p_instance_temp = mp_nrf_csense_instance_head;
  488. nrf_csense_pad_t const * p_pad;
  489. uint8_t channels_mask = 0;
  490. uint8_t instance_channels_mask = 0;
  491. for (p_instance_temp = mp_nrf_csense_instance_head; p_instance_temp != NULL;
  492. p_instance_temp = p_instance_temp->p_next_instance)
  493. {
  494. for (p_pad = p_instance_temp->p_nrf_csense_pad; p_pad != NULL; p_pad = p_pad->p_next_pad)
  495. {
  496. if (p_instance_temp == p_instance)
  497. {
  498. instance_channels_mask |= (1UL << (p_pad->analog_input_number));
  499. p_instance->is_active = false;
  500. }
  501. else
  502. {
  503. channels_mask |= (1UL << (p_pad->analog_input_number));
  504. }
  505. }
  506. }
  507. nrf_drv_csense_channels_disable((~channels_mask) & instance_channels_mask);
  508. m_nrf_csense.enabled_analog_channels_mask = channels_mask;
  509. if (m_nrf_csense.enabled_analog_channels_mask == 0)
  510. {
  511. err_code = app_timer_stop(nrf_csense_timer);
  512. if (err_code != NRF_SUCCESS)
  513. {
  514. return err_code;
  515. }
  516. m_nrf_csense.state = NRFX_DRV_STATE_INITIALIZED;
  517. }
  518. return NRF_SUCCESS;
  519. }
  520. ret_code_t nrf_csense_ticks_set(uint32_t ticks)
  521. {
  522. ASSERT(m_nrf_csense.state != NRFX_DRV_STATE_UNINITIALIZED);
  523. ret_code_t err_code;
  524. if (nrf_drv_csense_is_busy())
  525. {
  526. return NRF_ERROR_BUSY;
  527. }
  528. m_nrf_csense.ticks = ticks;
  529. if (m_nrf_csense.state == NRFX_DRV_STATE_POWERED_ON)
  530. {
  531. err_code = app_timer_stop(nrf_csense_timer);
  532. if (err_code != NRF_SUCCESS)
  533. {
  534. return err_code;
  535. }
  536. err_code = app_timer_start(nrf_csense_timer, ticks, NULL);
  537. if (err_code != NRF_SUCCESS)
  538. {
  539. return err_code;
  540. }
  541. }
  542. return NRF_SUCCESS;
  543. }
  544. ret_code_t nrf_csense_steps_set(nrf_csense_instance_t * const p_instance, uint16_t steps)
  545. {
  546. if (p_instance->is_active)
  547. {
  548. return NRF_ERROR_INVALID_STATE;
  549. }
  550. p_instance->steps = steps;
  551. return NRF_SUCCESS;
  552. }
  553. #endif //NRF_MODULE_ENABLED(NRF_CSENSE)