nrfx_saadc.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
  1. /**
  2. * Copyright (c) 2015 - 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 <nrfx.h>
  41. #if NRFX_CHECK(NRFX_SAADC_ENABLED)
  42. #include <nrfx_saadc.h>
  43. #define NRFX_LOG_MODULE SAADC
  44. #include <nrfx_log.h>
  45. #if !defined(NRFX_SAADC_API_V2)
  46. #define EVT_TO_STR(event) \
  47. (event == NRF_SAADC_EVENT_STARTED ? "NRF_SAADC_EVENT_STARTED" : \
  48. (event == NRF_SAADC_EVENT_END ? "NRF_SAADC_EVENT_END" : \
  49. (event == NRF_SAADC_EVENT_DONE ? "NRF_SAADC_EVENT_DONE" : \
  50. (event == NRF_SAADC_EVENT_RESULTDONE ? "NRF_SAADC_EVENT_RESULTDONE" : \
  51. (event == NRF_SAADC_EVENT_CALIBRATEDONE ? "NRF_SAADC_EVENT_CALIBRATEDONE" : \
  52. (event == NRF_SAADC_EVENT_STOPPED ? "NRF_SAADC_EVENT_STOPPED" : \
  53. "UNKNOWN EVENT"))))))
  54. typedef enum
  55. {
  56. NRF_SAADC_STATE_IDLE = 0,
  57. NRF_SAADC_STATE_BUSY = 1,
  58. NRF_SAADC_STATE_CALIBRATION = 2
  59. } nrf_saadc_state_t;
  60. typedef struct
  61. {
  62. nrf_saadc_input_t pselp;
  63. nrf_saadc_input_t pseln;
  64. } nrf_saadc_psel_buffer;
  65. /** @brief SAADC control block.*/
  66. typedef struct
  67. {
  68. nrfx_saadc_event_handler_t event_handler; ///< Event handler function pointer.
  69. volatile nrf_saadc_value_t * p_buffer; ///< Sample buffer.
  70. volatile uint16_t buffer_size; ///< Size of the sample buffer.
  71. volatile nrf_saadc_value_t * p_secondary_buffer; ///< Secondary sample buffer.
  72. volatile nrf_saadc_state_t adc_state; ///< State of the SAADC.
  73. uint32_t limits_enabled_flags; ///< Enabled limits flags.
  74. uint16_t secondary_buffer_size; ///< Size of the secondary buffer.
  75. uint16_t buffer_size_left; ///< When low power mode is active indicates how many samples left to convert on current buffer.
  76. nrf_saadc_psel_buffer psel[NRF_SAADC_CHANNEL_COUNT]; ///< Pin configurations of SAADC channels.
  77. nrfx_drv_state_t state; ///< Driver initialization state.
  78. uint8_t active_channels; ///< Number of enabled SAADC channels.
  79. bool low_power_mode; ///< Indicates if low power mode is active.
  80. bool conversions_end; ///< When low power mode is active indicates end of conversions on current buffer.
  81. } nrfx_saadc_cb_t;
  82. static nrfx_saadc_cb_t m_cb;
  83. #define LOW_LIMIT_TO_FLAG(channel) ((2 * channel + 1))
  84. #define HIGH_LIMIT_TO_FLAG(channel) ((2 * channel))
  85. #define FLAG_IDX_TO_EVENT(idx) ((nrf_saadc_event_t)((uint32_t)NRF_SAADC_EVENT_CH0_LIMITH + \
  86. 4 * idx))
  87. #define LIMIT_EVENT_TO_CHANNEL(event) (uint8_t)(((uint32_t)event - \
  88. (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) / 8)
  89. #define LIMIT_EVENT_TO_LIMIT_TYPE(event)((((uint32_t)event - (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) & 4) \
  90. ? NRF_SAADC_LIMIT_LOW : NRF_SAADC_LIMIT_HIGH)
  91. #define HW_TIMEOUT 10000
  92. void nrfx_saadc_irq_handler(void)
  93. {
  94. if (nrf_saadc_event_check(NRF_SAADC_EVENT_END))
  95. {
  96. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  97. NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_END));
  98. if (!m_cb.low_power_mode || m_cb.conversions_end)
  99. {
  100. nrfx_saadc_evt_t evt;
  101. evt.type = NRFX_SAADC_EVT_DONE;
  102. evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer;
  103. evt.data.done.size = m_cb.buffer_size;
  104. if (m_cb.p_secondary_buffer == NULL)
  105. {
  106. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  107. }
  108. else
  109. {
  110. m_cb.buffer_size_left = m_cb.secondary_buffer_size;
  111. m_cb.p_buffer = m_cb.p_secondary_buffer;
  112. m_cb.buffer_size = m_cb.secondary_buffer_size;
  113. m_cb.p_secondary_buffer = NULL;
  114. if (!m_cb.low_power_mode)
  115. {
  116. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  117. }
  118. }
  119. m_cb.event_handler(&evt);
  120. m_cb.conversions_end = false;
  121. }
  122. }
  123. if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
  124. {
  125. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  126. NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STARTED));
  127. if (m_cb.buffer_size_left > m_cb.active_channels)
  128. {
  129. // More samples to convert than for single event.
  130. m_cb.buffer_size_left -= m_cb.active_channels;
  131. nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size -
  132. m_cb.buffer_size_left],
  133. m_cb.active_channels);
  134. }
  135. else if ((m_cb.buffer_size_left == m_cb.active_channels) &&
  136. (m_cb.p_secondary_buffer != NULL))
  137. {
  138. // Samples to convert for one event, prepare next buffer.
  139. m_cb.conversions_end = true;
  140. m_cb.buffer_size_left = 0;
  141. nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer,
  142. m_cb.active_channels);
  143. }
  144. else if (m_cb.buffer_size_left == m_cb.active_channels)
  145. {
  146. // Samples to convert for one event, but no second buffer.
  147. m_cb.conversions_end = true;
  148. m_cb.buffer_size_left = 0;
  149. }
  150. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  151. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  152. }
  153. if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE))
  154. {
  155. nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
  156. NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_CALIBRATEDONE));
  157. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  158. nrfx_saadc_evt_t evt;
  159. evt.type = NRFX_SAADC_EVT_CALIBRATEDONE;
  160. m_cb.event_handler(&evt);
  161. }
  162. if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
  163. {
  164. nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
  165. NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STOPPED));
  166. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  167. }
  168. else
  169. {
  170. uint32_t limit_flags = m_cb.limits_enabled_flags;
  171. uint32_t flag_idx;
  172. nrf_saadc_event_t event;
  173. while (limit_flags)
  174. {
  175. flag_idx = __CLZ(limit_flags);
  176. limit_flags &= ~((1UL << 31) >> flag_idx);
  177. event = FLAG_IDX_TO_EVENT(flag_idx);
  178. if (nrf_saadc_event_check(event))
  179. {
  180. nrf_saadc_event_clear(event);
  181. nrfx_saadc_evt_t evt;
  182. evt.type = NRFX_SAADC_EVT_LIMIT;
  183. evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event);
  184. evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event);
  185. NRFX_LOG_DEBUG("Event limit, channel: %d, limit type: %d.",
  186. evt.data.limit.channel,
  187. evt.data.limit.limit_type);
  188. m_cb.event_handler(&evt);
  189. }
  190. }
  191. }
  192. }
  193. nrfx_err_t nrfx_saadc_init(nrfx_saadc_config_t const * p_config,
  194. nrfx_saadc_event_handler_t event_handler)
  195. {
  196. NRFX_ASSERT(p_config);
  197. NRFX_ASSERT(event_handler);
  198. nrfx_err_t err_code;
  199. if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
  200. {
  201. err_code = NRFX_ERROR_INVALID_STATE;
  202. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  203. __func__,
  204. NRFX_LOG_ERROR_STRING_GET(err_code));
  205. return err_code;
  206. }
  207. m_cb.event_handler = event_handler;
  208. nrf_saadc_resolution_set(p_config->resolution);
  209. nrf_saadc_oversample_set(p_config->oversample);
  210. m_cb.low_power_mode = p_config->low_power_mode;
  211. m_cb.state = NRFX_DRV_STATE_INITIALIZED;
  212. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  213. m_cb.active_channels = 0;
  214. m_cb.limits_enabled_flags = 0;
  215. m_cb.conversions_end = false;
  216. nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
  217. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  218. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  219. nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
  220. NRFX_IRQ_PRIORITY_SET(SAADC_IRQn, p_config->interrupt_priority);
  221. NRFX_IRQ_ENABLE(SAADC_IRQn);
  222. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  223. if (m_cb.low_power_mode)
  224. {
  225. nrf_saadc_int_enable(NRF_SAADC_INT_STARTED);
  226. }
  227. nrf_saadc_enable();
  228. err_code = NRFX_SUCCESS;
  229. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  230. return err_code;
  231. }
  232. void nrfx_saadc_uninit(void)
  233. {
  234. NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
  235. nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
  236. NRFX_IRQ_DISABLE(SAADC_IRQn);
  237. nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
  238. // Wait for ADC being stopped.
  239. bool result;
  240. NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED), HW_TIMEOUT, 0, result);
  241. NRFX_ASSERT(result);
  242. nrf_saadc_disable();
  243. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  244. for (uint32_t channel = 0; channel < NRF_SAADC_CHANNEL_COUNT; ++channel)
  245. {
  246. if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED)
  247. {
  248. nrfx_err_t err_code = nrfx_saadc_channel_uninit(channel);
  249. NRFX_ASSERT(err_code == NRFX_SUCCESS);
  250. }
  251. }
  252. m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
  253. }
  254. nrfx_err_t nrfx_saadc_channel_init(uint8_t channel,
  255. nrf_saadc_channel_config_t const * const p_config)
  256. {
  257. NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
  258. NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
  259. // Oversampling can be used only with one channel.
  260. NRFX_ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) ||
  261. (m_cb.active_channels == 0));
  262. #if defined(SAADC_CH_PSELP_PSELP_VDDHDIV5)
  263. NRFX_ASSERT((p_config->pin_p <= NRF_SAADC_INPUT_VDDHDIV5) &&
  264. (p_config->pin_p > NRF_SAADC_INPUT_DISABLED));
  265. NRFX_ASSERT(p_config->pin_n <= NRF_SAADC_INPUT_VDDHDIV5);
  266. #else
  267. NRFX_ASSERT((p_config->pin_p <= NRF_SAADC_INPUT_VDD) &&
  268. (p_config->pin_p > NRF_SAADC_INPUT_DISABLED));
  269. NRFX_ASSERT(p_config->pin_n <= NRF_SAADC_INPUT_VDD);
  270. #endif
  271. nrfx_err_t err_code;
  272. // A channel can only be initialized if the driver is in the idle state.
  273. if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
  274. {
  275. err_code = NRFX_ERROR_BUSY;
  276. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  277. __func__,
  278. NRFX_LOG_ERROR_STRING_GET(err_code));
  279. return err_code;
  280. }
  281. #ifdef NRF52_PAN_74
  282. if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) ||
  283. (p_config->acq_time == NRF_SAADC_ACQTIME_5US))
  284. {
  285. nrf_saadc_disable();
  286. }
  287. #endif //NRF52_PAN_74
  288. if (m_cb.psel[channel].pselp == NRF_SAADC_INPUT_DISABLED)
  289. {
  290. ++m_cb.active_channels;
  291. }
  292. m_cb.psel[channel].pselp = p_config->pin_p;
  293. m_cb.psel[channel].pseln = p_config->pin_n;
  294. nrf_saadc_channel_init(channel, p_config);
  295. #ifdef NRF52_PAN_74
  296. if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) ||
  297. (p_config->acq_time == NRF_SAADC_ACQTIME_5US))
  298. {
  299. nrf_saadc_enable();
  300. }
  301. #endif //NRF52_PAN_74
  302. NRFX_LOG_INFO("Channel initialized: %d.", channel);
  303. err_code = NRFX_SUCCESS;
  304. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  305. return err_code;
  306. }
  307. nrfx_err_t nrfx_saadc_channel_uninit(uint8_t channel)
  308. {
  309. NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
  310. NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
  311. nrfx_err_t err_code;
  312. // A channel can only be uninitialized if the driver is in the idle state.
  313. if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
  314. {
  315. err_code = NRFX_ERROR_BUSY;
  316. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  317. __func__,
  318. NRFX_LOG_ERROR_STRING_GET(err_code));
  319. return err_code;
  320. }
  321. if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED)
  322. {
  323. --m_cb.active_channels;
  324. }
  325. m_cb.psel[channel].pselp = NRF_SAADC_INPUT_DISABLED;
  326. m_cb.psel[channel].pseln = NRF_SAADC_INPUT_DISABLED;
  327. nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
  328. nrfx_saadc_limits_set(channel, NRFX_SAADC_LIMITL_DISABLED, NRFX_SAADC_LIMITH_DISABLED);
  329. NRFX_LOG_INFO("Channel denitialized: %d.", channel);
  330. err_code = NRFX_SUCCESS;
  331. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  332. return err_code;
  333. }
  334. uint32_t nrfx_saadc_sample_task_get(void)
  335. {
  336. return nrf_saadc_task_address_get(
  337. m_cb.low_power_mode ? NRF_SAADC_TASK_START : NRF_SAADC_TASK_SAMPLE);
  338. }
  339. nrfx_err_t nrfx_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value)
  340. {
  341. nrfx_err_t err_code;
  342. if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
  343. {
  344. err_code = NRFX_ERROR_BUSY;
  345. NRFX_LOG_WARNING("Function: %s error code: %s.",
  346. __func__,
  347. NRFX_LOG_ERROR_STRING_GET(err_code));
  348. return err_code;
  349. }
  350. m_cb.adc_state = NRF_SAADC_STATE_BUSY;
  351. nrf_saadc_int_disable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END);
  352. nrf_saadc_buffer_init(p_value, 1);
  353. if (m_cb.active_channels > 1)
  354. {
  355. for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
  356. {
  357. nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED);
  358. }
  359. }
  360. nrf_saadc_channel_input_set(channel, m_cb.psel[channel].pselp, m_cb.psel[channel].pseln);
  361. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  362. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  363. bool result;
  364. NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_END), HW_TIMEOUT, 0, result);
  365. NRFX_ASSERT(result);
  366. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  367. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  368. NRFX_LOG_INFO("Conversion value: %d, channel %d.", *p_value, channel);
  369. if (m_cb.active_channels > 1)
  370. {
  371. for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i)
  372. {
  373. nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln);
  374. }
  375. }
  376. if (m_cb.low_power_mode)
  377. {
  378. nrf_saadc_int_enable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END);
  379. }
  380. else
  381. {
  382. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  383. }
  384. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  385. err_code = NRFX_SUCCESS;
  386. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  387. __func__,
  388. NRFX_LOG_ERROR_STRING_GET(err_code));
  389. return err_code;
  390. }
  391. nrfx_err_t nrfx_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size)
  392. {
  393. NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
  394. NRFX_ASSERT((size % m_cb.active_channels) == 0);
  395. nrfx_err_t err_code;
  396. nrf_saadc_int_disable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE);
  397. if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION)
  398. {
  399. nrf_saadc_int_enable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE);
  400. err_code = NRFX_ERROR_BUSY;
  401. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  402. __func__,
  403. NRFX_LOG_ERROR_STRING_GET(err_code));
  404. return err_code;
  405. }
  406. if (m_cb.adc_state == NRF_SAADC_STATE_BUSY)
  407. {
  408. if ( m_cb.p_secondary_buffer)
  409. {
  410. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  411. err_code = NRFX_ERROR_BUSY;
  412. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  413. __func__,
  414. NRFX_LOG_ERROR_STRING_GET(err_code));
  415. return err_code;
  416. }
  417. else
  418. {
  419. m_cb.p_secondary_buffer = p_buffer;
  420. m_cb.secondary_buffer_size = size;
  421. if (!m_cb.low_power_mode)
  422. {
  423. while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0);
  424. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  425. nrf_saadc_buffer_init(p_buffer, size);
  426. }
  427. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  428. err_code = NRFX_SUCCESS;
  429. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  430. __func__,
  431. NRFX_LOG_ERROR_STRING_GET(err_code));
  432. return err_code;
  433. }
  434. }
  435. nrf_saadc_int_enable(NRF_SAADC_INT_END);
  436. m_cb.adc_state = NRF_SAADC_STATE_BUSY;
  437. m_cb.p_buffer = p_buffer;
  438. m_cb.buffer_size = size;
  439. m_cb.p_secondary_buffer = NULL;
  440. NRFX_LOG_INFO("Function: %s, buffer length: %d, active channels: %d.",
  441. __func__,
  442. size,
  443. m_cb.active_channels);
  444. if (m_cb.low_power_mode)
  445. {
  446. m_cb.buffer_size_left = size;
  447. nrf_saadc_buffer_init(p_buffer, m_cb.active_channels);
  448. }
  449. else
  450. {
  451. nrf_saadc_buffer_init(p_buffer, size);
  452. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  453. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  454. }
  455. err_code = NRFX_SUCCESS;
  456. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  457. return err_code;
  458. }
  459. nrfx_err_t nrfx_saadc_sample()
  460. {
  461. NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
  462. nrfx_err_t err_code = NRFX_SUCCESS;
  463. if (m_cb.adc_state != NRF_SAADC_STATE_BUSY)
  464. {
  465. err_code = NRFX_ERROR_INVALID_STATE;
  466. }
  467. else if (m_cb.low_power_mode)
  468. {
  469. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  470. }
  471. else
  472. {
  473. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  474. }
  475. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  476. return err_code;
  477. }
  478. nrfx_err_t nrfx_saadc_calibrate_offset()
  479. {
  480. NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
  481. nrfx_err_t err_code;
  482. if (m_cb.adc_state != NRF_SAADC_STATE_IDLE)
  483. {
  484. err_code = NRFX_ERROR_BUSY;
  485. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  486. __func__,
  487. NRFX_LOG_ERROR_STRING_GET(err_code));
  488. return err_code;
  489. }
  490. m_cb.adc_state = NRF_SAADC_STATE_CALIBRATION;
  491. nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
  492. nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE);
  493. nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);
  494. err_code = NRFX_SUCCESS;
  495. NRFX_LOG_INFO("Function: %s, error code: %s.",
  496. __func__,
  497. NRFX_LOG_ERROR_STRING_GET(err_code));
  498. return err_code;
  499. }
  500. bool nrfx_saadc_is_busy(void)
  501. {
  502. return (m_cb.adc_state != NRF_SAADC_STATE_IDLE);
  503. }
  504. void nrfx_saadc_abort(void)
  505. {
  506. if (nrfx_saadc_is_busy())
  507. {
  508. nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
  509. nrf_saadc_int_enable(NRF_SAADC_INT_STOPPED);
  510. nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
  511. if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION)
  512. {
  513. m_cb.adc_state = NRF_SAADC_STATE_IDLE;
  514. }
  515. else
  516. {
  517. // Wait for ADC being stopped.
  518. bool result;
  519. NRFX_WAIT_FOR((m_cb.adc_state == NRF_SAADC_STATE_IDLE), HW_TIMEOUT, 0, result);
  520. NRFX_ASSERT(result);
  521. }
  522. nrf_saadc_int_disable(NRF_SAADC_INT_STOPPED);
  523. m_cb.p_buffer = 0;
  524. m_cb.p_secondary_buffer = 0;
  525. NRFX_LOG_INFO("Conversion aborted.");
  526. }
  527. }
  528. void nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high)
  529. {
  530. NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
  531. NRFX_ASSERT(m_cb.event_handler); // only non blocking mode supported
  532. NRFX_ASSERT(limit_low >= NRFX_SAADC_LIMITL_DISABLED);
  533. NRFX_ASSERT(limit_high <= NRFX_SAADC_LIMITH_DISABLED);
  534. NRFX_ASSERT(limit_low < limit_high);
  535. nrf_saadc_channel_limits_set(channel, limit_low, limit_high);
  536. uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW);
  537. if (limit_low == NRFX_SAADC_LIMITL_DISABLED)
  538. {
  539. m_cb.limits_enabled_flags &= ~(0x80000000 >> LOW_LIMIT_TO_FLAG(channel));
  540. nrf_saadc_int_disable(int_mask);
  541. }
  542. else
  543. {
  544. m_cb.limits_enabled_flags |= (0x80000000 >> LOW_LIMIT_TO_FLAG(channel));
  545. nrf_saadc_int_enable(int_mask);
  546. }
  547. int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH);
  548. if (limit_high == NRFX_SAADC_LIMITH_DISABLED)
  549. {
  550. m_cb.limits_enabled_flags &= ~(0x80000000 >> HIGH_LIMIT_TO_FLAG(channel));
  551. nrf_saadc_int_disable(int_mask);
  552. }
  553. else
  554. {
  555. m_cb.limits_enabled_flags |= (0x80000000 >> HIGH_LIMIT_TO_FLAG(channel));
  556. nrf_saadc_int_enable(int_mask);
  557. }
  558. }
  559. #endif // !defined(NRFX_SAADC_API_V2)
  560. #if defined(NRFX_SAADC_API_V2) || defined(__NRFX_DOXYGEN__)
  561. #if defined(NRF52_SERIES) && !defined(USE_WORKAROUND_FOR_ANOMALY_212)
  562. // ANOMALY 212 - SAADC events are missing when switching from single channel
  563. // to multi channel configuration with burst enabled.
  564. #define USE_WORKAROUND_FOR_ANOMALY_212 1
  565. #endif
  566. #if defined(NRF53_SERIES) || defined(NRF91_SERIES)
  567. // Make sure that SAADC is stopped before channel configuration.
  568. #define STOP_SAADC_ON_CHANNEL_CONFIG 1
  569. // Make sure that SAADC calibration samples do not affect next conversions.
  570. #define INTERCEPT_SAADC_CALIBRATION_SAMPLES 1
  571. #endif
  572. /** @brief SAADC driver states.*/
  573. typedef enum
  574. {
  575. NRF_SAADC_STATE_UNINITIALIZED = 0,
  576. NRF_SAADC_STATE_IDLE,
  577. NRF_SAADC_STATE_SIMPLE_MODE,
  578. NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE,
  579. NRF_SAADC_STATE_ADV_MODE,
  580. NRF_SAADC_STATE_ADV_MODE_SAMPLE,
  581. NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED,
  582. NRF_SAADC_STATE_CALIBRATION
  583. } nrf_saadc_state_t;
  584. /** @brief SAADC control block.*/
  585. typedef struct
  586. {
  587. nrfx_saadc_event_handler_t event_handler; ///< Event handler function pointer.
  588. nrf_saadc_value_t * p_buffer_primary; ///< Pointer to the primary result buffer.
  589. nrf_saadc_value_t * p_buffer_secondary; ///< Pointer to the secondary result buffer.
  590. #if NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
  591. nrf_saadc_value_t calib_samples[6]; ///< Scratch buffer for calibration samples.
  592. #endif
  593. uint16_t size_primary; ///< Size of the primary result buffer.
  594. uint16_t size_secondary; ///< Size of the secondary result buffer.
  595. uint16_t samples_converted; ///< Number of samples present in result buffer when in the blocking mode.
  596. nrf_saadc_input_t channels_pselp[SAADC_CH_NUM]; ///< Array holding each channel positive input.
  597. nrf_saadc_input_t channels_pseln[SAADC_CH_NUM]; ///< Array holding each channel negative input.
  598. nrf_saadc_state_t saadc_state; ///< State of the SAADC driver.
  599. uint8_t channels_configured; ///< Bitmask of the configured channels.
  600. uint8_t channels_activated; ///< Bitmask of the activated channels.
  601. uint8_t channels_activated_count; ///< Number of the activated channels.
  602. uint8_t limits_low_activated; ///< Bitmask of the activated low limits.
  603. uint8_t limits_high_activated; ///< Bitmask of the activated high limits.
  604. bool start_on_end; ///< Flag indicating if the START task is to be triggered on the END event.
  605. bool oversampling_without_burst; ///< Flag indicating whether oversampling without burst is configured.
  606. } nrfx_saadc_cb_t;
  607. static nrfx_saadc_cb_t m_cb;
  608. #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
  609. static void saadc_anomaly_212_workaround_apply(void)
  610. {
  611. uint32_t c[SAADC_CH_NUM];
  612. uint32_t l[SAADC_CH_NUM];
  613. for (uint32_t i = 0; i < SAADC_CH_NUM; i++)
  614. {
  615. c[i] = NRF_SAADC->CH[i].CONFIG;
  616. l[i] = NRF_SAADC->CH[i].LIMIT;
  617. }
  618. nrf_saadc_resolution_t resolution = nrf_saadc_resolution_get();
  619. uint32_t u640 = *(volatile uint32_t *)0x40007640;
  620. uint32_t u644 = *(volatile uint32_t *)0x40007644;
  621. uint32_t u648 = *(volatile uint32_t *)0x40007648;
  622. *(volatile uint32_t *)0x40007FFC = 0;
  623. *(volatile uint32_t *)0x40007FFC = 1;
  624. for (uint32_t i = 0; i < SAADC_CH_NUM; i++)
  625. {
  626. NRF_SAADC->CH[i].CONFIG = c[i];
  627. NRF_SAADC->CH[i].LIMIT = l[i];
  628. }
  629. *(volatile uint32_t *)0x40007640 = u640;
  630. *(volatile uint32_t *)0x40007644 = u644;
  631. *(volatile uint32_t *)0x40007648 = u648;
  632. nrf_saadc_resolution_set(resolution);
  633. }
  634. #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
  635. static nrfx_err_t saadc_channel_count_get(uint32_t ch_to_activate_mask,
  636. uint8_t * p_active_ch_count)
  637. {
  638. NRFX_ASSERT(ch_to_activate_mask);
  639. NRFX_ASSERT(ch_to_activate_mask < (1uL << SAADC_CH_NUM));
  640. uint8_t active_ch_count = 0;
  641. for (uint32_t ch_mask = 1; ch_mask < (1uL << SAADC_CH_NUM); ch_mask <<= 1)
  642. {
  643. if (ch_to_activate_mask & ch_mask)
  644. {
  645. // Check if requested channels are configured.
  646. if (!(m_cb.channels_configured & ch_mask))
  647. {
  648. return NRFX_ERROR_INVALID_PARAM;
  649. }
  650. active_ch_count++;
  651. }
  652. }
  653. *p_active_ch_count = active_ch_count;
  654. return NRFX_SUCCESS;
  655. }
  656. static bool saadc_busy_check(void)
  657. {
  658. if ((m_cb.saadc_state == NRF_SAADC_STATE_IDLE) ||
  659. (m_cb.saadc_state == NRF_SAADC_STATE_ADV_MODE) ||
  660. (m_cb.saadc_state == NRF_SAADC_STATE_SIMPLE_MODE))
  661. {
  662. return false;
  663. }
  664. else
  665. {
  666. return true;
  667. }
  668. }
  669. static void saadc_generic_mode_set(uint32_t ch_to_activate_mask,
  670. nrf_saadc_resolution_t resolution,
  671. nrf_saadc_oversample_t oversampling,
  672. nrf_saadc_burst_t burst,
  673. nrfx_saadc_event_handler_t event_handler)
  674. {
  675. #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_212)
  676. saadc_anomaly_212_workaround_apply();
  677. #endif
  678. #if NRFX_CHECK(STOP_SAADC_ON_CHANNEL_CONFIG)
  679. nrf_saadc_int_disable(NRF_SAADC_INT_STOPPED);
  680. nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
  681. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
  682. {}
  683. nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
  684. #endif
  685. m_cb.limits_low_activated = 0;
  686. m_cb.limits_high_activated = 0;
  687. m_cb.p_buffer_primary = NULL;
  688. m_cb.p_buffer_secondary = NULL;
  689. m_cb.event_handler = event_handler;
  690. m_cb.channels_activated = ch_to_activate_mask;
  691. m_cb.samples_converted = 0;
  692. nrf_saadc_resolution_set(resolution);
  693. nrf_saadc_oversample_set(oversampling);
  694. if (event_handler)
  695. {
  696. nrf_saadc_int_set(NRF_SAADC_INT_STARTED |
  697. NRF_SAADC_INT_STOPPED |
  698. NRF_SAADC_INT_END);
  699. }
  700. else
  701. {
  702. nrf_saadc_int_set(0);
  703. }
  704. for (uint32_t ch_pos = 0; ch_pos < SAADC_CH_NUM; ch_pos++)
  705. {
  706. nrf_saadc_burst_t burst_to_set;
  707. nrf_saadc_input_t pselp;
  708. nrf_saadc_input_t pseln;
  709. if (ch_to_activate_mask & (1uL << ch_pos))
  710. {
  711. pselp = m_cb.channels_pselp[ch_pos];
  712. pseln = m_cb.channels_pseln[ch_pos];
  713. burst_to_set = burst;
  714. }
  715. else
  716. {
  717. pselp = NRF_SAADC_INPUT_DISABLED;
  718. pseln = NRF_SAADC_INPUT_DISABLED;
  719. burst_to_set = NRF_SAADC_BURST_DISABLED;
  720. }
  721. nrf_saadc_burst_set(ch_pos, burst_to_set);
  722. nrf_saadc_channel_input_set(ch_pos, pselp, pseln);
  723. }
  724. }
  725. nrfx_err_t nrfx_saadc_init(uint8_t interrupt_priority)
  726. {
  727. nrfx_err_t err_code;
  728. if (m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED)
  729. {
  730. err_code = NRFX_ERROR_INVALID_STATE;
  731. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  732. __func__,
  733. NRFX_LOG_ERROR_STRING_GET(err_code));
  734. return err_code;
  735. }
  736. m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
  737. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  738. nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
  739. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  740. nrf_saadc_int_set(0);
  741. NRFX_IRQ_ENABLE(SAADC_IRQn);
  742. NRFX_IRQ_PRIORITY_SET(SAADC_IRQn, interrupt_priority);
  743. err_code = NRFX_SUCCESS;
  744. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  745. return err_code;
  746. }
  747. void nrfx_saadc_uninit(void)
  748. {
  749. nrfx_saadc_abort();
  750. NRFX_IRQ_DISABLE(SAADC_IRQn);
  751. nrf_saadc_disable();
  752. m_cb.saadc_state = NRF_SAADC_STATE_UNINITIALIZED;
  753. }
  754. nrfx_err_t nrfx_saadc_channels_config(nrfx_saadc_channel_t const * p_channels,
  755. uint32_t channel_count)
  756. {
  757. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
  758. NRFX_ASSERT(channel_count <= SAADC_CH_NUM);
  759. if (saadc_busy_check())
  760. {
  761. return NRFX_ERROR_BUSY;
  762. }
  763. m_cb.channels_configured = 0;
  764. uint8_t i = 0;
  765. for (; i < SAADC_CH_NUM; i++)
  766. {
  767. m_cb.channels_pselp[i] = NRF_SAADC_INPUT_DISABLED;
  768. m_cb.channels_pseln[i] = NRF_SAADC_INPUT_DISABLED;
  769. }
  770. for (i = 0; i < channel_count; i++)
  771. {
  772. if (m_cb.channels_configured & (1uL << p_channels[i].channel_index))
  773. {
  774. // This channel is already configured!
  775. return NRFX_ERROR_INVALID_PARAM;
  776. }
  777. nrf_saadc_channel_init(p_channels[i].channel_index,
  778. &p_channels[i].channel_config);
  779. NRFX_ASSERT(p_channels[i].pin_p);
  780. m_cb.channels_pselp[p_channels[i].channel_index] = p_channels[i].pin_p;
  781. m_cb.channels_pseln[p_channels[i].channel_index] = p_channels[i].pin_n;
  782. m_cb.channels_configured |= 1U << p_channels[i].channel_index;
  783. }
  784. return NRFX_SUCCESS;
  785. }
  786. nrfx_err_t nrfx_saadc_simple_mode_set(uint32_t channel_mask,
  787. nrf_saadc_resolution_t resolution,
  788. nrf_saadc_oversample_t oversampling,
  789. nrfx_saadc_event_handler_t event_handler)
  790. {
  791. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
  792. if (saadc_busy_check())
  793. {
  794. return NRFX_ERROR_BUSY;
  795. }
  796. uint8_t active_ch_count;
  797. nrfx_err_t err = saadc_channel_count_get(channel_mask, &active_ch_count);
  798. if (err != NRFX_SUCCESS)
  799. {
  800. return err;
  801. }
  802. nrf_saadc_burst_t burst;
  803. if (oversampling == NRF_SAADC_OVERSAMPLE_DISABLED)
  804. {
  805. burst = NRF_SAADC_BURST_DISABLED;
  806. }
  807. else
  808. {
  809. // Burst is implicitly enabled if oversampling is enabled.
  810. burst = NRF_SAADC_BURST_ENABLED;
  811. }
  812. saadc_generic_mode_set(channel_mask,
  813. resolution,
  814. oversampling,
  815. burst,
  816. event_handler);
  817. m_cb.channels_activated_count = active_ch_count;
  818. m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE;
  819. return NRFX_SUCCESS;
  820. }
  821. nrfx_err_t nrfx_saadc_advanced_mode_set(uint32_t channel_mask,
  822. nrf_saadc_resolution_t resolution,
  823. nrfx_saadc_adv_config_t const * p_config,
  824. nrfx_saadc_event_handler_t event_handler)
  825. {
  826. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
  827. NRFX_ASSERT(p_config);
  828. if (saadc_busy_check())
  829. {
  830. return NRFX_ERROR_BUSY;
  831. }
  832. uint8_t active_ch_count;
  833. nrfx_err_t err = saadc_channel_count_get(channel_mask, &active_ch_count);
  834. if (err != NRFX_SUCCESS)
  835. {
  836. return err;
  837. }
  838. if ((p_config->internal_timer_cc) && ((active_ch_count > 1) || (!event_handler)))
  839. {
  840. return NRFX_ERROR_NOT_SUPPORTED;
  841. }
  842. bool oversampling_without_burst = false;
  843. if ((p_config->oversampling != NRF_SAADC_OVERSAMPLE_DISABLED) &&
  844. (p_config->burst == NRF_SAADC_BURST_DISABLED))
  845. {
  846. if (active_ch_count > 1)
  847. {
  848. // Oversampling without burst is possible only on single channel.
  849. return NRFX_ERROR_NOT_SUPPORTED;
  850. }
  851. else
  852. {
  853. oversampling_without_burst = true;
  854. }
  855. }
  856. saadc_generic_mode_set(channel_mask,
  857. resolution,
  858. p_config->oversampling,
  859. p_config->burst,
  860. event_handler);
  861. if (p_config->internal_timer_cc)
  862. {
  863. nrf_saadc_continuous_mode_enable(p_config->internal_timer_cc);
  864. }
  865. else
  866. {
  867. nrf_saadc_continuous_mode_disable();
  868. }
  869. m_cb.channels_activated_count = active_ch_count;
  870. m_cb.start_on_end = p_config->start_on_end;
  871. m_cb.oversampling_without_burst = oversampling_without_burst;
  872. m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE;
  873. return NRFX_SUCCESS;
  874. }
  875. nrfx_err_t nrfx_saadc_buffer_set(nrf_saadc_value_t * p_buffer, uint16_t size)
  876. {
  877. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
  878. if (m_cb.p_buffer_secondary)
  879. {
  880. return NRFX_ERROR_ALREADY_INITIALIZED;
  881. }
  882. if (!nrfx_is_in_ram(p_buffer))
  883. {
  884. return NRFX_ERROR_INVALID_ADDR;
  885. }
  886. if ((size % m_cb.channels_activated_count != 0) ||
  887. (size >= (1uL << SAADC_EASYDMA_MAXCNT_SIZE)) ||
  888. (!size))
  889. {
  890. return NRFX_ERROR_INVALID_LENGTH;
  891. }
  892. switch (m_cb.saadc_state)
  893. {
  894. case NRF_SAADC_STATE_SIMPLE_MODE:
  895. if (m_cb.channels_activated_count != size)
  896. {
  897. return NRFX_ERROR_INVALID_LENGTH;
  898. }
  899. m_cb.size_primary = size;
  900. m_cb.p_buffer_primary = p_buffer;
  901. break;
  902. case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
  903. nrf_saadc_buffer_init(p_buffer, size);
  904. /* fall-through */
  905. case NRF_SAADC_STATE_ADV_MODE:
  906. /* fall-through */
  907. case NRF_SAADC_STATE_ADV_MODE_SAMPLE:
  908. if (m_cb.p_buffer_primary)
  909. {
  910. m_cb.size_secondary = size;
  911. m_cb.p_buffer_secondary = p_buffer;
  912. }
  913. else
  914. {
  915. m_cb.size_primary = size;
  916. m_cb.p_buffer_primary = p_buffer;
  917. }
  918. break;
  919. default:
  920. return NRFX_ERROR_INVALID_STATE;
  921. }
  922. return NRFX_SUCCESS;
  923. }
  924. nrfx_err_t nrfx_saadc_mode_trigger(void)
  925. {
  926. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
  927. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_IDLE);
  928. if (!m_cb.p_buffer_primary)
  929. {
  930. return NRFX_ERROR_NO_MEM;
  931. }
  932. nrfx_err_t result = NRFX_SUCCESS;
  933. switch (m_cb.saadc_state)
  934. {
  935. case NRF_SAADC_STATE_SIMPLE_MODE:
  936. nrf_saadc_enable();
  937. // When in simple blocking or non-blocking mode, buffer size is equal to activated channel count.
  938. // Single SAMPLE task is enough to obtain one sample on each activated channel.
  939. // This will result in buffer being filled with samples and therefore END event will appear.
  940. nrf_saadc_buffer_init(m_cb.p_buffer_primary, m_cb.size_primary);
  941. if (m_cb.event_handler)
  942. {
  943. m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE;
  944. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  945. }
  946. else
  947. {
  948. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  949. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
  950. {}
  951. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  952. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  953. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_END))
  954. {}
  955. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  956. nrf_saadc_disable();
  957. }
  958. break;
  959. case NRF_SAADC_STATE_ADV_MODE:
  960. nrf_saadc_enable();
  961. if (m_cb.event_handler)
  962. {
  963. // When in advanced non-blocking mode, latch whole buffer in EasyDMA.
  964. // END event will arrive when whole buffer is filled with samples.
  965. m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE_SAMPLE;
  966. nrf_saadc_buffer_init(m_cb.p_buffer_primary, m_cb.size_primary);
  967. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  968. break;
  969. }
  970. // When in advanced blocking mode, latch single chunk of buffer in EasyDMA.
  971. // Each chunk consists of single sample from each activated channels.
  972. // END event will arrive when single chunk is filled with samples.
  973. nrf_saadc_buffer_init(&m_cb.p_buffer_primary[m_cb.samples_converted],
  974. m_cb.channels_activated_count);
  975. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  976. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
  977. {}
  978. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  979. if (m_cb.oversampling_without_burst)
  980. {
  981. // Oversampling without burst is possible only on single channel.
  982. // In this configuration more than one SAMPLE task is needed to obtain single sample.
  983. uint32_t samples_to_take =
  984. nrf_saadc_oversample_sample_count_get(nrf_saadc_oversample_get());
  985. for (uint32_t sample_idx = 0; sample_idx < samples_to_take; sample_idx++)
  986. {
  987. nrf_saadc_event_clear(NRF_SAADC_EVENT_DONE);
  988. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  989. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_DONE))
  990. {}
  991. }
  992. }
  993. else
  994. {
  995. // Single SAMPLE task is enough to obtain one sample on each activated channel.
  996. // This will result in chunk being filled with samples and therefore END event will appear.
  997. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  998. }
  999. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_END))
  1000. {}
  1001. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  1002. m_cb.samples_converted += m_cb.channels_activated_count;
  1003. if (m_cb.samples_converted < m_cb.size_primary)
  1004. {
  1005. result = NRFX_ERROR_BUSY;
  1006. }
  1007. else
  1008. {
  1009. m_cb.samples_converted = 0;
  1010. m_cb.p_buffer_primary = m_cb.p_buffer_secondary;
  1011. m_cb.size_primary = m_cb.size_secondary;
  1012. m_cb.p_buffer_secondary = NULL;
  1013. }
  1014. nrf_saadc_disable();
  1015. break;
  1016. default:
  1017. result = NRFX_ERROR_INVALID_STATE;
  1018. break;
  1019. }
  1020. return result;
  1021. }
  1022. void nrfx_saadc_abort(void)
  1023. {
  1024. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
  1025. if (!m_cb.event_handler)
  1026. {
  1027. m_cb.p_buffer_primary = NULL;
  1028. m_cb.p_buffer_secondary = NULL;
  1029. m_cb.samples_converted = 0;
  1030. }
  1031. else
  1032. {
  1033. nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
  1034. if (m_cb.saadc_state == NRF_SAADC_STATE_CALIBRATION)
  1035. {
  1036. // STOPPED event does not appear when the calibration is ongoing
  1037. m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
  1038. }
  1039. }
  1040. }
  1041. nrfx_err_t nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high)
  1042. {
  1043. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
  1044. NRFX_ASSERT(limit_high >= limit_low);
  1045. if (!m_cb.event_handler)
  1046. {
  1047. return NRFX_ERROR_FORBIDDEN;
  1048. }
  1049. if ((m_cb.saadc_state == NRF_SAADC_STATE_IDLE) ||
  1050. (m_cb.saadc_state == NRF_SAADC_STATE_CALIBRATION))
  1051. {
  1052. return NRFX_ERROR_INVALID_STATE;
  1053. }
  1054. if (!(m_cb.channels_activated & (1uL << channel)))
  1055. {
  1056. return NRFX_ERROR_INVALID_PARAM;
  1057. }
  1058. nrf_saadc_channel_limits_set(channel, limit_low, limit_high);
  1059. uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW);
  1060. if (limit_low == INT16_MIN)
  1061. {
  1062. m_cb.limits_low_activated &= ~(1uL << channel);
  1063. nrf_saadc_int_disable(int_mask);
  1064. }
  1065. else
  1066. {
  1067. m_cb.limits_low_activated |= (1uL << channel);
  1068. nrf_saadc_int_enable(int_mask);
  1069. }
  1070. int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH);
  1071. if (limit_high == INT16_MAX)
  1072. {
  1073. m_cb.limits_high_activated &= ~(1uL << channel);
  1074. nrf_saadc_int_disable(int_mask);
  1075. }
  1076. else
  1077. {
  1078. m_cb.limits_high_activated |= (1uL << channel);
  1079. nrf_saadc_int_enable(int_mask);
  1080. }
  1081. return NRFX_SUCCESS;
  1082. }
  1083. nrfx_err_t nrfx_saadc_offset_calibrate(nrfx_saadc_event_handler_t event_handler)
  1084. {
  1085. NRFX_ASSERT(m_cb.saadc_state != NRF_SAADC_STATE_UNINITIALIZED);
  1086. if (saadc_busy_check())
  1087. {
  1088. return NRFX_ERROR_BUSY;
  1089. }
  1090. m_cb.saadc_state = NRF_SAADC_STATE_CALIBRATION;
  1091. m_cb.event_handler = event_handler;
  1092. nrf_saadc_enable();
  1093. #if NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
  1094. nrf_saadc_buffer_init(m_cb.calib_samples, NRFX_ARRAY_SIZE(m_cb.calib_samples));
  1095. if (event_handler)
  1096. {
  1097. nrf_saadc_int_set(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_CALIBRATEDONE);
  1098. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  1099. }
  1100. else
  1101. {
  1102. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  1103. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
  1104. {}
  1105. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  1106. nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);
  1107. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE))
  1108. {}
  1109. nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
  1110. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  1111. nrf_saadc_disable();
  1112. m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
  1113. }
  1114. #else
  1115. nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);
  1116. if (event_handler)
  1117. {
  1118. nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE);
  1119. }
  1120. else
  1121. {
  1122. while (!nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE))
  1123. {}
  1124. nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
  1125. nrf_saadc_disable();
  1126. m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
  1127. }
  1128. #endif // NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
  1129. return NRFX_SUCCESS;
  1130. }
  1131. static void saadc_event_started_handle(void)
  1132. {
  1133. nrfx_saadc_evt_t evt_data;
  1134. switch (m_cb.saadc_state)
  1135. {
  1136. case NRF_SAADC_STATE_ADV_MODE_SAMPLE:
  1137. evt_data.type = NRFX_SAADC_EVT_READY;
  1138. m_cb.event_handler(&evt_data);
  1139. if (nrf_saadc_continuous_mode_enable_check())
  1140. {
  1141. // Trigger internal timer
  1142. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  1143. }
  1144. m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED;
  1145. if (m_cb.p_buffer_secondary)
  1146. {
  1147. nrf_saadc_buffer_init(m_cb.p_buffer_secondary,
  1148. m_cb.size_secondary);
  1149. }
  1150. /* fall-through */
  1151. case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
  1152. if (!m_cb.p_buffer_secondary)
  1153. {
  1154. // Send next buffer request only if it was not provided earlier,
  1155. // before conversion start or outside of user's callback context.
  1156. evt_data.type = NRFX_SAADC_EVT_BUF_REQ;
  1157. m_cb.event_handler(&evt_data);
  1158. }
  1159. break;
  1160. case NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE:
  1161. nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
  1162. break;
  1163. #if NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
  1164. case NRF_SAADC_STATE_CALIBRATION:
  1165. nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET);
  1166. break;
  1167. #endif
  1168. default:
  1169. break;
  1170. }
  1171. }
  1172. static void saadc_event_end_handle(void)
  1173. {
  1174. nrfx_saadc_evt_t evt_data;
  1175. evt_data.type = NRFX_SAADC_EVT_DONE;
  1176. evt_data.data.done.p_buffer = m_cb.p_buffer_primary;
  1177. evt_data.data.done.size = m_cb.size_primary;
  1178. m_cb.event_handler(&evt_data);
  1179. switch (m_cb.saadc_state)
  1180. {
  1181. case NRF_SAADC_STATE_SIMPLE_MODE_SAMPLE:
  1182. nrf_saadc_disable();
  1183. m_cb.saadc_state = NRF_SAADC_STATE_SIMPLE_MODE;
  1184. break;
  1185. case NRF_SAADC_STATE_ADV_MODE_SAMPLE_STARTED:
  1186. m_cb.p_buffer_primary = m_cb.p_buffer_secondary;
  1187. m_cb.size_primary = m_cb.size_secondary;
  1188. m_cb.p_buffer_secondary = NULL;
  1189. if (m_cb.p_buffer_primary)
  1190. {
  1191. if (m_cb.start_on_end)
  1192. {
  1193. nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  1194. }
  1195. }
  1196. else
  1197. {
  1198. nrf_saadc_disable();
  1199. m_cb.saadc_state = NRF_SAADC_STATE_ADV_MODE;
  1200. evt_data.type = NRFX_SAADC_EVT_FINISHED;
  1201. m_cb.event_handler(&evt_data);
  1202. }
  1203. break;
  1204. default:
  1205. break;
  1206. }
  1207. }
  1208. static void saadc_event_limits_handle(uint8_t limits_activated, nrf_saadc_limit_t limit_type)
  1209. {
  1210. while (limits_activated)
  1211. {
  1212. uint8_t channel = __CLZ(__RBIT((uint32_t)limits_activated));
  1213. limits_activated &= ~(1uL << channel);
  1214. nrf_saadc_event_t event = nrf_saadc_limit_event_get(channel, limit_type);
  1215. if (nrf_saadc_event_check(event))
  1216. {
  1217. nrf_saadc_event_clear(event);
  1218. nrfx_saadc_evt_t evt_data;
  1219. evt_data.type = NRFX_SAADC_EVT_LIMIT;
  1220. evt_data.data.limit.channel = channel;
  1221. evt_data.data.limit.limit_type = limit_type;
  1222. m_cb.event_handler(&evt_data);
  1223. }
  1224. }
  1225. }
  1226. void nrfx_saadc_irq_handler(void)
  1227. {
  1228. if (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
  1229. {
  1230. nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
  1231. saadc_event_started_handle();
  1232. }
  1233. if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
  1234. {
  1235. nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
  1236. // If there was ongoing conversion the STOP task also triggers the END event
  1237. m_cb.size_primary = nrf_saadc_amount_get();
  1238. m_cb.p_buffer_secondary = NULL;
  1239. /* fall-through to the END event handler */
  1240. }
  1241. if (nrf_saadc_event_check(NRF_SAADC_EVENT_END))
  1242. {
  1243. nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
  1244. #if NRFX_CHECK(INTERCEPT_SAADC_CALIBRATION_SAMPLES)
  1245. // When samples are intercepted into scratch buffer during calibration,
  1246. // END event appears when the calibration finishes. This event should be ignored.
  1247. if (m_cb.saadc_state != NRF_SAADC_STATE_CALIBRATION)
  1248. #endif
  1249. {
  1250. saadc_event_end_handle();
  1251. }
  1252. }
  1253. saadc_event_limits_handle(m_cb.limits_low_activated, NRF_SAADC_LIMIT_LOW);
  1254. saadc_event_limits_handle(m_cb.limits_high_activated, NRF_SAADC_LIMIT_HIGH);
  1255. if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE))
  1256. {
  1257. nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
  1258. nrf_saadc_disable();
  1259. m_cb.saadc_state = NRF_SAADC_STATE_IDLE;
  1260. nrfx_saadc_evt_t evt_data;
  1261. evt_data.type = NRFX_SAADC_EVT_CALIBRATEDONE;
  1262. m_cb.event_handler(&evt_data);
  1263. }
  1264. }
  1265. #endif // defined(NRFX_SAADC_API_V2) || defined(__NRFX_DOXYGEN__)
  1266. #endif // NRFX_CHECK(NRFX_SAADC_ENABLED)