nrf_drv_saadc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include "nrf_drv_saadc.h"
  13. #include "nrf_assert.h"
  14. #include "nordic_common.h"
  15. #include "nrf_drv_common.h"
  16. #include "app_util_platform.h"
  17. typedef enum
  18. {
  19. NRF_SAADC_STATE_IDLE = 0,
  20. NRF_SAADC_STATE_BUSY = 1
  21. } nrf_saadc_state_t;
  22. typedef struct
  23. {
  24. nrf_saadc_input_t pselp;
  25. nrf_saadc_input_t pseln;
  26. } nrf_saadc_psel_buffer;
  27. static const nrf_drv_saadc_config_t m_default_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
  28. /** @brief SAADC control block.*/
  29. typedef struct
  30. {
  31. nrf_drv_saadc_event_handler_t event_handler; ///< Event handler function pointer.
  32. volatile nrf_saadc_value_t * p_buffer; ///< Sample buffer.
  33. volatile uint16_t buffer_size; ///< Size of the sample buffer.
  34. #ifdef NRF52_PAN_28
  35. volatile uint16_t buffer_pos; ///< Current sample buffer position.
  36. #endif
  37. volatile nrf_saadc_value_t * p_secondary_buffer; ///< Secondary sample buffer.
  38. uint32_t limits_enabled_flags; ///< Enabled limits flags.
  39. uint16_t secondary_buffer_size; ///< Size of the secondary buffer.
  40. nrf_saadc_psel_buffer psel[NRF_SAADC_CHANNEL_COUNT]; ///< Pin configurations of SAADC channels.
  41. nrf_drv_state_t state; ///< Driver initialization state.
  42. nrf_saadc_state_t adc_state; ///< State of the SAADC.
  43. #ifdef NRF52_PAN_28
  44. uint8_t scan_pos; ///< Current channel scanning position.
  45. #endif
  46. uint8_t active_channels; ///< Number of enabled SAADC channels.
  47. } nrf_drv_saadc_cb_t;
  48. static nrf_drv_saadc_cb_t m_cb;
  49. #define LOW_LIMIT_TO_FLAG(channel) ((2*channel+1))
  50. #define HIGH_LIMIT_TO_FLAG(channel) ((2*channel))
  51. #define FLAG_IDX_TO_EVENT(idx) ((nrf_saadc_event_t)((uint32_t)NRF_SAADC_EVENT_CH0_LIMITH+4*idx))
  52. #define LIMIT_EVENT_TO_CHANNEL(event)(uint8_t)(((uint32_t)event-(uint32_t)NRF_SAADC_EVENT_CH0_LIMITH)/8)
  53. #define LIMIT_EVENT_TO_LIMIT_TYPE(event)((((uint32_t)event-(uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) & 4) ? \
  54. NRF_SAADC_LIMIT_LOW : NRF_SAADC_LIMIT_HIGH)
  55. #define HW_TIMEOUT 10000
  56. void SAADC_IRQHandler(void)
  57. {
  58. if (nrf_saadc_event_check(NRF_SAADC_EVENT_END))
  59. {
  60. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  61. #ifdef NRF52_PAN_28
  62. if (m_cb.active_channels == 1)
  63. {
  64. #endif
  65. nrf_drv_saadc_evt_t evt;
  66. evt.type = NRF_DRV_SAADC_EVT_DONE;
  67. evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer;
  68. evt.data.done.size = nrf_saadc_amount_get();
  69. if (m_cb.p_secondary_buffer == NULL)
  70. {
  71. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  72. }
  73. else
  74. {
  75. m_cb.p_buffer = m_cb.p_secondary_buffer;
  76. m_cb.buffer_size = m_cb.secondary_buffer_size;
  77. m_cb.p_secondary_buffer = NULL;
  78. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  79. }
  80. m_cb.event_handler(&evt);
  81. #ifdef NRF52_PAN_28
  82. }
  83. else
  84. {
  85. //PAN-28: scan mode is not working correctly, emulated by interrupts
  86. ++(m_cb.buffer_pos);
  87. uint16_t buffer_pos = m_cb.buffer_pos;
  88. if (buffer_pos == m_cb.buffer_size)
  89. {
  90. nrf_drv_saadc_evt_t evt;
  91. evt.type = NRF_DRV_SAADC_EVT_DONE;
  92. evt.data.done.p_buffer = (nrf_saadc_value_t *)(m_cb.p_buffer);
  93. evt.data.done.size = m_cb.buffer_size;
  94. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  95. if (m_cb.p_secondary_buffer == NULL)
  96. {
  97. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  98. }
  99. else
  100. {
  101. (void)nrf_drv_saadc_buffer_convert((nrf_saadc_value_t *)m_cb.p_secondary_buffer, (uint16_t)m_cb.secondary_buffer_size);
  102. }
  103. m_cb.event_handler(&evt);
  104. }
  105. else
  106. {
  107. uint8_t current_scan_pos = m_cb.scan_pos;
  108. nrf_saadc_channel_input_set(current_scan_pos,
  109. NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
  110. nrf_saadc_buffer_init((nrf_saadc_value_t *)(m_cb.p_buffer + m_cb.buffer_pos), 1);
  111. // Find the next enabled channel.
  112. for (++m_cb.scan_pos; m_cb.scan_pos < NRF_SAADC_CHANNEL_COUNT; ++m_cb.scan_pos)
  113. {
  114. if (m_cb.psel[m_cb.scan_pos].pselp)
  115. {
  116. nrf_saadc_channel_input_set(m_cb.scan_pos,
  117. m_cb.psel[m_cb.scan_pos].pselp, m_cb.psel[m_cb.scan_pos].pseln);
  118. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  119. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  120. return;
  121. }
  122. }
  123. //if scanning is done prepare for next round.
  124. for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
  125. {
  126. if (m_cb.psel[i].pselp)
  127. {
  128. m_cb.scan_pos = i;
  129. break;
  130. }
  131. }
  132. nrf_saadc_channel_input_set(m_cb.scan_pos,
  133. m_cb.psel[m_cb.scan_pos].pselp, m_cb.psel[m_cb.scan_pos].pseln);
  134. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  135. }
  136. }
  137. #endif
  138. }
  139. if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
  140. {
  141. nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
  142. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  143. }
  144. else
  145. {
  146. uint32_t limit_flags = m_cb.limits_enabled_flags;
  147. uint32_t flag_idx;
  148. nrf_saadc_event_t event;
  149. while (limit_flags)
  150. {
  151. flag_idx = __CLZ(limit_flags);
  152. limit_flags &= ~((1UL<<31) >> flag_idx);
  153. event = FLAG_IDX_TO_EVENT(flag_idx);
  154. if (nrf_saadc_event_check(event))
  155. {
  156. nrf_saadc_event_clear(event);
  157. nrf_drv_saadc_evt_t evt;
  158. evt.type = NRF_DRV_SAADC_EVT_LIMIT;
  159. evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event);
  160. evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event);
  161. m_cb.event_handler(&evt);
  162. }
  163. }
  164. }
  165. }
  166. ret_code_t nrf_drv_saadc_init(nrf_drv_saadc_config_t const * p_config,
  167. nrf_drv_saadc_event_handler_t event_handler)
  168. {
  169. if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
  170. {
  171. return NRF_ERROR_INVALID_STATE;
  172. }
  173. if (event_handler == NULL)
  174. {
  175. return NRF_ERROR_INVALID_PARAM;
  176. }
  177. if (p_config == NULL)
  178. {
  179. p_config = &m_default_config;
  180. }
  181. m_cb.event_handler = event_handler;
  182. nrf_saadc_resolution_set(p_config->resolution);
  183. nrf_saadc_oversample_set(p_config->oversample);
  184. m_cb.state = NRF_DRV_STATE_INITIALIZED;
  185. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  186. m_cb.active_channels = 0;
  187. m_cb.limits_enabled_flags = 0;
  188. #ifdef NRF52_PAN_28
  189. m_cb.buffer_pos = 0;
  190. #endif
  191. nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
  192. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  193. nrf_drv_common_irq_enable(SAADC_IRQn, p_config->interrupt_priority);
  194. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  195. nrf_saadc_enable();
  196. return NRF_SUCCESS;
  197. }
  198. void nrf_drv_saadc_uninit(void)
  199. {
  200. ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED);
  201. nrf_drv_common_irq_disable(SAADC_IRQn);
  202. nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
  203. // Wait for ADC being stopped.
  204. uint32_t timeout = HW_TIMEOUT;
  205. while (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED) == 0 && timeout > 0)
  206. {
  207. --timeout;
  208. }
  209. ASSERT(timeout > 0);
  210. nrf_saadc_disable();
  211. nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
  212. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  213. for (uint8_t channel = 0; channel < NRF_SAADC_CHANNEL_COUNT; ++channel)
  214. {
  215. if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED)
  216. {
  217. (void)nrf_drv_saadc_channel_uninit(channel);
  218. }
  219. }
  220. m_cb.state = NRF_DRV_STATE_UNINITIALIZED;
  221. }
  222. ret_code_t nrf_drv_saadc_channel_init(uint8_t channel,
  223. nrf_saadc_channel_config_t const * const p_config)
  224. {
  225. ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED);
  226. ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
  227. //Oversampling can be used only with one channel.
  228. ASSERT((nrf_saadc_oversample_get()==NRF_SAADC_OVERSAMPLE_DISABLED) || (m_cb.active_channels == 0));
  229. ASSERT((p_config->pin_p <= NRF_SAADC_INPUT_VDD) && (p_config->pin_p > NRF_SAADC_INPUT_DISABLED));
  230. ASSERT(p_config->pin_n <= NRF_SAADC_INPUT_VDD);
  231. // A channel can only be initialized if the driver is in the idle state.
  232. if (m_cb.adc_state == NRF_SAADC_STATE_BUSY)
  233. {
  234. return NRF_ERROR_BUSY;
  235. }
  236. if (!m_cb.psel[channel].pselp)
  237. {
  238. ++m_cb.active_channels;
  239. }
  240. m_cb.psel[channel].pselp = p_config->pin_p;
  241. m_cb.psel[channel].pseln = p_config->pin_n;
  242. nrf_saadc_channel_init(channel, p_config);
  243. #ifdef NRF52_PAN_28
  244. nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
  245. #else
  246. nrf_saadc_channel_input_set(channel, p_config->pin_p, p_config->pin_n);
  247. #endif
  248. return NRF_SUCCESS;
  249. }
  250. ret_code_t nrf_drv_saadc_channel_uninit(uint8_t channel)
  251. {
  252. ASSERT(channel <= NRF_SAADC_CHANNEL_COUNT)
  253. ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED);
  254. // A channel can only be uninitialized if the driver is in the idle state.
  255. if (m_cb.adc_state == NRF_SAADC_STATE_BUSY)
  256. {
  257. return NRF_ERROR_BUSY;
  258. }
  259. if (m_cb.psel[channel].pselp)
  260. {
  261. --m_cb.active_channels;
  262. }
  263. m_cb.psel[channel].pselp = NRF_SAADC_INPUT_DISABLED;
  264. m_cb.psel[channel].pseln = NRF_SAADC_INPUT_DISABLED;
  265. nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
  266. nrf_drv_saadc_limits_set(channel, NRF_DRV_SAADC_LIMITL_DISABLED, NRF_DRV_SAADC_LIMITH_DISABLED);
  267. return NRF_SUCCESS;
  268. }
  269. ret_code_t nrf_drv_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value)
  270. {
  271. if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
  272. {
  273. return NRF_ERROR_BUSY;
  274. }
  275. m_cb.adc_state = NRF_SAADC_STATE_BUSY;
  276. nrf_saadc_int_disable(NRF_SAADC_INT_END);
  277. nrf_saadc_buffer_init(p_value, 1);
  278. #ifndef NRF52_PAN_28
  279. if (m_cb.active_channels > 1)
  280. {
  281. for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
  282. {
  283. nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
  284. }
  285. }
  286. #endif
  287. nrf_saadc_channel_input_set(channel,
  288. m_cb.psel[channel].pselp, m_cb.psel[channel].pseln);
  289. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  290. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  291. uint32_t timeout = HW_TIMEOUT;
  292. while (0 == nrf_saadc_event_check(NRF_SAADC_EVENT_END) && timeout > 0)
  293. {
  294. timeout--;
  295. }
  296. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  297. #ifdef NRF52_PAN_28
  298. nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
  299. #else
  300. if (m_cb.active_channels > 1)
  301. {
  302. for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
  303. {
  304. nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln);
  305. }
  306. }
  307. #endif
  308. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  309. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  310. return NRF_SUCCESS;
  311. }
  312. ret_code_t nrf_drv_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size)
  313. {
  314. ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED);
  315. nrf_saadc_int_disable(NRF_SAADC_INT_END);
  316. if (m_cb.adc_state == NRF_SAADC_STATE_BUSY)
  317. {
  318. if ( m_cb.p_secondary_buffer)
  319. {
  320. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  321. return NRF_ERROR_BUSY;
  322. }
  323. else
  324. {
  325. m_cb.p_secondary_buffer = p_buffer;
  326. m_cb.secondary_buffer_size = size;
  327. #ifdef NRF52_PAN_28
  328. if (m_cb.active_channels == 1)
  329. #endif
  330. {
  331. while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0);
  332. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  333. nrf_saadc_buffer_init(p_buffer, size);
  334. }
  335. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  336. return NRF_SUCCESS;
  337. }
  338. }
  339. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  340. m_cb.adc_state = NRF_SAADC_STATE_BUSY;
  341. #ifdef NRF52_PAN_28
  342. m_cb.scan_pos = NRF_SAADC_CHANNEL_COUNT;
  343. for (uint8_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
  344. {
  345. if (m_cb.psel[i].pselp)
  346. {
  347. m_cb.scan_pos = i;
  348. break;
  349. }
  350. }
  351. // Find the first enabled channel.
  352. if (m_cb.scan_pos >= NRF_SAADC_CHANNEL_COUNT)
  353. {
  354. return NRF_ERROR_INVALID_STATE;
  355. }
  356. m_cb.buffer_pos = 0;
  357. #endif
  358. m_cb.p_buffer = p_buffer;
  359. m_cb.buffer_size = size;
  360. m_cb.p_secondary_buffer = NULL;
  361. #ifdef NRF52_PAN_28
  362. nrf_saadc_channel_input_set(m_cb.scan_pos,
  363. m_cb.psel[m_cb.scan_pos].pselp, m_cb.psel[m_cb.scan_pos].pseln);
  364. if (m_cb.active_channels == 1)
  365. {
  366. nrf_saadc_buffer_init(p_buffer, size);
  367. }
  368. else
  369. {
  370. nrf_saadc_buffer_init(p_buffer, 1);
  371. }
  372. #else
  373. nrf_saadc_buffer_init(p_buffer, size);
  374. #endif
  375. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  376. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  377. return NRF_SUCCESS;
  378. }
  379. ret_code_t nrf_drv_saadc_sample()
  380. {
  381. ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED);
  382. ret_code_t err_code = NRF_SUCCESS;
  383. if (m_cb.adc_state == NRF_SAADC_STATE_IDLE)
  384. {
  385. err_code = NRF_ERROR_BUSY;
  386. }
  387. else
  388. {
  389. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  390. }
  391. return err_code;
  392. }
  393. bool nrf_drv_saadc_is_busy(void)
  394. {
  395. return (m_cb.adc_state == NRF_SAADC_STATE_BUSY);
  396. }
  397. void nrf_drv_saadc_abort(void)
  398. {
  399. if (nrf_drv_saadc_is_busy())
  400. {
  401. nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
  402. nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
  403. // Wait for ADC being stopped.
  404. uint32_t timeout = HW_TIMEOUT;
  405. while ((m_cb.adc_state != NRF_SAADC_STATE_IDLE) && (timeout > 0))
  406. {
  407. --timeout;
  408. }
  409. ASSERT(timeout > 0);
  410. m_cb.p_buffer = 0;
  411. m_cb.p_secondary_buffer = 0;
  412. }
  413. }
  414. void nrf_drv_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high)
  415. {
  416. ASSERT(m_cb.state != NRF_DRV_STATE_UNINITIALIZED);
  417. ASSERT(m_cb.event_handler); // only non blocking mode supported
  418. ASSERT(limit_low>=NRF_DRV_SAADC_LIMITL_DISABLED);
  419. ASSERT(limit_high<=NRF_DRV_SAADC_LIMITH_DISABLED);
  420. ASSERT(limit_low<limit_high);
  421. nrf_saadc_channel_limits_set(channel, limit_low, limit_high);
  422. uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW);
  423. if (limit_low == NRF_DRV_SAADC_LIMITL_DISABLED)
  424. {
  425. m_cb.limits_enabled_flags &= ~(0x80000000 >> LOW_LIMIT_TO_FLAG(channel));
  426. nrf_saadc_int_disable(int_mask);
  427. }
  428. else
  429. {
  430. m_cb.limits_enabled_flags |= (0x80000000 >> LOW_LIMIT_TO_FLAG(channel));
  431. nrf_saadc_int_enable(int_mask);
  432. }
  433. int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH);
  434. if (limit_high == NRF_DRV_SAADC_LIMITH_DISABLED)
  435. {
  436. m_cb.limits_enabled_flags &= ~(0x80000000 >> HIGH_LIMIT_TO_FLAG(channel));
  437. nrf_saadc_int_disable(int_mask);
  438. }
  439. else
  440. {
  441. m_cb.limits_enabled_flags |= (0x80000000 >> HIGH_LIMIT_TO_FLAG(channel));
  442. nrf_saadc_int_enable(int_mask);
  443. }
  444. }