sdadc_callback.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /**
  2. * \file
  3. *
  4. * \brief SAM Sigma-Delta Analog-to-Digital Converter Driver
  5. *
  6. * Copyright (C) 2015 Atmel Corporation. All rights reserved.
  7. *
  8. * \asf_license_start
  9. *
  10. * \page License
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. *
  18. * 2. Redistributions in binary form must reproduce the above copyright notice,
  19. * this list of conditions and the following disclaimer in the documentation
  20. * and/or other materials provided with the distribution.
  21. *
  22. * 3. The name of Atmel may not be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * 4. This software may only be redistributed and used in connection with an
  26. * Atmel microcontroller product.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
  29. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  30. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  31. * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
  32. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  36. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * \asf_license_stop
  41. *
  42. */
  43. /*
  44. * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
  45. */
  46. #include "sdadc_callback.h"
  47. struct sdadc_module *_sdadc_instances[SDADC_INST_NUM];
  48. static void _sdadc_interrupt_handler(const uint8_t instance)
  49. {
  50. struct sdadc_module *module = _sdadc_instances[instance];
  51. /* get interrupt flags and mask out enabled callbacks */
  52. uint32_t flags = module->hw->INTFLAG.reg;
  53. if (flags & SDADC_INTFLAG_RESRDY) {
  54. if ((module->enabled_callback_mask & (1 << SDADC_CALLBACK_READ_BUFFER)) &&
  55. (module->registered_callback_mask & (1 << SDADC_CALLBACK_READ_BUFFER))) {
  56. /* clear interrupt flag */
  57. module->hw->INTFLAG.reg = SDADC_INTFLAG_RESRDY;
  58. /* store SDADC result in job buffer */
  59. *(module->job_buffer++) = ((int32_t)(module->hw->RESULT.reg << 8)) >> 8;
  60. if (--module->remaining_conversions > 0) {
  61. if (module->software_trigger == true) {
  62. sdadc_start_conversion(module);
  63. }
  64. } else {
  65. if (module->job_status == STATUS_BUSY) {
  66. /* job is complete. update status,disable interrupt
  67. *and call callback */
  68. module->job_status = STATUS_OK;
  69. sdadc_disable_interrupt(module, SDADC_INTERRUPT_RESULT_READY);
  70. (module->callback[SDADC_CALLBACK_READ_BUFFER])(module);
  71. }
  72. }
  73. }
  74. }
  75. if (flags & SDADC_INTFLAG_WINMON) {
  76. module->hw->INTFLAG.reg = SDADC_INTFLAG_WINMON;
  77. if ((module->enabled_callback_mask & (1 << SDADC_CALLBACK_WINDOW)) &&
  78. (module->registered_callback_mask & (1 << SDADC_CALLBACK_WINDOW))) {
  79. (module->callback[SDADC_CALLBACK_WINDOW])(module);
  80. }
  81. }
  82. if (flags & SDADC_INTFLAG_OVERRUN) {
  83. module->hw->INTFLAG.reg = SDADC_INTFLAG_OVERRUN;
  84. if ((module->enabled_callback_mask & (1 << SDADC_CALLBACK_ERROR)) &&
  85. (module->registered_callback_mask & (1 << SDADC_CALLBACK_ERROR))) {
  86. (module->callback[SDADC_CALLBACK_ERROR])(module);
  87. }
  88. }
  89. }
  90. /** Interrupt handler for the SDADC module. */
  91. void SDADC_Handler(void)
  92. {
  93. _sdadc_interrupt_handler(0);
  94. }
  95. /**
  96. * \brief Registers a callback.
  97. *
  98. * Registers a callback function which is implemented by the user.
  99. *
  100. * \note The callback must be enabled by for the interrupt handler to call it
  101. * when the condition for the callback is met.
  102. *
  103. * \param[in] module Pointer to SDADC software instance struct
  104. * \param[in] callback_func Pointer to callback function
  105. * \param[in] callback_type Callback type given by an enum
  106. *
  107. */
  108. void sdadc_register_callback(
  109. struct sdadc_module *const module,
  110. sdadc_callback_t callback_func,
  111. enum sdadc_callback callback_type)
  112. {
  113. /* Sanity check arguments */
  114. Assert(module);
  115. Assert(callback_func);
  116. /* Register callback function */
  117. module->callback[callback_type] = callback_func;
  118. /* Set the bit corresponding to the callback_type */
  119. module->registered_callback_mask |= (1 << callback_type);
  120. }
  121. /**
  122. * \brief Unregisters a callback.
  123. *
  124. * Unregisters a callback function which is implemented by the user.
  125. *
  126. * \param[in] module Pointer to SDADC software instance struct
  127. * \param[in] callback_type Callback type given by an enum
  128. *
  129. */
  130. void sdadc_unregister_callback(
  131. struct sdadc_module *const module,
  132. enum sdadc_callback callback_type)
  133. {
  134. /* Sanity check arguments */
  135. Assert(module);
  136. /* Unregister callback function */
  137. module->callback[callback_type] = NULL;
  138. /* Clear the bit corresponding to the callback_type */
  139. module->registered_callback_mask &= ~(1 << callback_type);
  140. }
  141. /**
  142. * \brief Read multiple samples from SDADC.
  143. *
  144. * Read \c samples from the SDADC into the \c buffer.
  145. * If there is no hardware trigger defined (event action) the
  146. * driver will retrigger the SDADC conversion whenever a conversion
  147. * is complete until \c samples has been acquired. To avoid
  148. * jitter in the sampling frequency using an event trigger is advised.
  149. *
  150. * \param[in] module_inst Pointer to the SDADC software instance struct
  151. * \param[in] samples Number of samples to acquire
  152. * \param[out] buffer Buffer to store the SDADC samples
  153. *
  154. * \return Status of the job start.
  155. * \retval STATUS_OK The conversion job was started successfully and is
  156. * in progress
  157. * \retval STATUS_BUSY The SDADC is already busy with another job
  158. */
  159. enum status_code sdadc_read_buffer_job(
  160. struct sdadc_module *const module_inst,
  161. int32_t *buffer,
  162. uint16_t samples)
  163. {
  164. Assert(module_inst);
  165. Assert(samples);
  166. Assert(buffer);
  167. if(module_inst->remaining_conversions != 0 ||
  168. module_inst->job_status == STATUS_BUSY){
  169. return STATUS_BUSY;
  170. }
  171. module_inst->job_status = STATUS_BUSY;
  172. module_inst->remaining_conversions = samples;
  173. module_inst->job_buffer = buffer;
  174. sdadc_enable_interrupt(module_inst, SDADC_INTERRUPT_RESULT_READY);
  175. if(module_inst->software_trigger == true) {
  176. sdadc_start_conversion(module_inst);
  177. }
  178. return STATUS_OK;
  179. }
  180. /**
  181. * \brief Gets the status of a job.
  182. *
  183. * Gets the status of an ongoing or the last job.
  184. *
  185. * \param [in] module_inst Pointer to the SDADC software instance struct
  186. * \param [in] type Type of job to abort
  187. *
  188. * \return Status of the job.
  189. */
  190. enum status_code sdadc_get_job_status(
  191. struct sdadc_module *module_inst,
  192. enum sdadc_job_type type)
  193. {
  194. /* Sanity check arguments */
  195. Assert(module_inst);
  196. if (type == SDADC_JOB_READ_BUFFER ) {
  197. return module_inst->job_status;
  198. } else {
  199. return STATUS_ERR_INVALID_ARG;
  200. }
  201. }
  202. /**
  203. * \brief Aborts an ongoing job.
  204. *
  205. * Aborts an ongoing job with given type.
  206. *
  207. * \param [in] module_inst Pointer to the SDADC software instance struct
  208. * \param [in] type Type of job to abort
  209. */
  210. void sdadc_abort_job(
  211. struct sdadc_module *module_inst,
  212. enum sdadc_job_type type)
  213. {
  214. /* Sanity check arguments */
  215. Assert(module_inst);
  216. if (type == SDADC_JOB_READ_BUFFER) {
  217. /* Disable interrupt */
  218. sdadc_disable_interrupt(module_inst, SDADC_INTERRUPT_RESULT_READY);
  219. /* Mark job as aborted */
  220. module_inst->job_status = STATUS_ABORTED;
  221. module_inst->remaining_conversions = 0;
  222. }
  223. }