1 /*
2  * Copyright (c) 2016-2019, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*!****************************************************************************
33  *  @file       ADC.h
34  *  @brief      Analog to Digital Conversion (ADC) Input Driver
35  *
36  *  @anchor ti_drivers_ADC_Overview
37  *  # Overview
38  *
39  *  The ADC driver allows you to manage an Analog to Digital peripheral via
40  *  simple and portable APIs. This driver supports sampling and converting
41  *  raw values into microvolts.
42  *
43  *  <hr>
44  *  @anchor ti_drivers_ADC_Usage
45  *  # Usage
46  *
47  *  This documentation provides a basic @ref ti_drivers_ADC_Synopsis
48  *  "usage summary" and a set of @ref ti_drivers_ADC_Examples "examples"
49  *  in the form of commented code fragments. Detailed descriptions of the
50  *  APIs are provided in subsequent sections.
51  *
52  *  @anchor ti_drivers_ADC_Synopsis
53  *  ## Synopsis
54  *  @anchor ti_drivers_ADC_Synopsis_Code
55  *  @code
56  *  // Import ADC Driver definitions
57  *  #include <ti/drivers/ADC.h>
58  *
59  *  // Define name for ADC channel index
60  *  #define THERMOCOUPLE_OUT  0
61  *
62  *  // One-time init of ADC driver
63  *  ADC_init();
64  *
65  *  // initialize optional ADC parameters
66  *  ADC_Params params;
67  *  ADC_Params_init(&params);
68  *  params.isProtected = true;
69  *
70  *  // Open ADC channels for usage
71  *  ADC_Handle adcHandle = ADC_open(THERMOCOUPLE_OUT, &params);
72  *
73  *  // Sample the analog output from the Thermocouple
74  *  ADC_convert(adcHandle, &result);
75  *
76  *  // Convert the sample to microvolts
77  *  resultUv = ADC_convertToMicroVolts(adcHandle, result);
78  *
79  *  ADC_close(adcHandle);
80  *  @endcode
81  *
82  *  <hr>
83  *  @anchor ti_drivers_ADC_Examples
84  *  # Examples
85  *
86  *  @li @ref ti_drivers_ADC_Examples_open "Opening an ADC instance"
87  *  @li @ref ti_drivers_ADC_Examples_convert "Taking an ADC sample"
88  *  @li @ref ti_drivers_ADC_Examples_convert_microvolts "Converting a sample to microvolts"
89  *
90  *  @anchor ti_drivers_ADC_Examples_open
91  *  ## Opening an ADC instance
92  *
93  *  @code
94  *  ADC_Handle adc;
95  *  ADC_Params params;
96  *
97  *  ADC_Params_init(&params);
98  *
99  *  adc = ADC_open(0, &params);
100  *  if (adc == NULL) {
101  *      // ADC_open() failed
102  *      while (1) {}
103  *  }
104  *  @endcode
105  *
106  *  @anchor ti_drivers_ADC_Examples_convert
107  *  ## Taking an ADC sample
108  *
109  *  An ADC conversion with an ADC peripheral is started by calling
110  *  ADC_convert(). The result value is returned by ADC_convert()
111  *  once the conversion is finished.
112  *
113  *  @code
114  *  int_fast16_t res;
115  *  uint_fast16_t adcValue;
116  *
117  *  res = ADC_convert(adc, &adcValue);
118  *  if (res == ADC_STATUS_SUCCESS)
119  *  {
120  *      print(adcValue);
121  *  }
122  *  @endcode
123  *
124  *  @anchor ti_drivers_ADC_Examples_convert_microvolts
125  *  ## Converting a sample to microvolts
126  *
127  *  The result value returned by ADC_convert() is a raw value. The
128  *  following uses ADC_convertToMicroVolts() to convert the raw value
129  *  into microvolts.
130  *  @code
131  *  int_fast16_t res;
132  *  uint_fast16_t adcValue;
133  *  uint32_t adcValueUv;
134  *
135  *  res = ADC_convert(adc, &adcValue);
136  *  if (res == ADC_STATUS_SUCCESS)
137  *  {
138  *      adcValueUv = ADC_convertToMicroVolts(adc, adcValue);
139  *  }
140  *  @endcode
141  *
142  *  <hr>
143  *  @anchor ti_drivers_ADC_Configuration
144  *  # Configuration
145  *
146  *  Refer to the @ref driver_configuration "Driver's Configuration" section
147  *  for driver configuration information.
148  *  <hr>
149  ******************************************************************************
150  */
151 
152 #ifndef ti_drivers_ADC__include
153 #define ti_drivers_ADC__include
154 
155 #include <stdbool.h>
156 #include <stdint.h>
157 
158 #ifdef __cplusplus
159 extern "C" {
160 #endif
161 
162 /*!
163  *  @deprecated ADC_convertRawToMicroVolts() is succeeded by
164  *  ADC_convertToMicroVolts().
165  */
166 #define ADC_convertRawToMicroVolts ADC_convertToMicroVolts
167 
168 /*!
169  *  @defgroup ADC_CONTROL ADC_control command and status codes
170  *  These ADC macros are reservations for ADC.h
171  *  @{
172  */
173 
174 /*!
175  * @hideinitializer
176  * Common ADC_control command code reservation offset.
177  * ADC driver implementations should offset command codes with ADC_CMD_RESERVED
178  * growing positively
179  *
180  * Example implementation specific command codes:
181  * @code
182  * #define ADCXYZ_CMD_COMMAND0      ADC_CMD_RESERVED + 0
183  * #define ADCXYZ_CMD_COMMAND1      ADC_CMD_RESERVED + 1
184  * @endcode
185  */
186 #define ADC_CMD_RESERVED           (32)
187 
188 /*!
189  * @hideinitializer
190  * Common ADC_control status code reservation offset.
191  * ADC driver implementations should offset status codes with
192  * ADC_STATUS_RESERVED growing negatively.
193  *
194  * Example implementation specific status codes:
195  * @code
196  * #define ADCXYZ_STATUS_ERROR0     ADC_STATUS_RESERVED - 0
197  * #define ADCXYZ_STATUS_ERROR1     ADC_STATUS_RESERVED - 1
198  * #define ADCXYZ_STATUS_ERROR2     ADC_STATUS_RESERVED - 2
199  * @endcode
200  */
201 #define ADC_STATUS_RESERVED        (-32)
202 
203 /*!
204  * @brief   Successful status code returned by ADC_control().
205  *
206  * ADC_control() returns ADC_STATUS_SUCCESS if the control code was executed
207  * successfully.
208  *  @{
209  *  @ingroup ADC_CONTROL
210  */
211 #define ADC_STATUS_SUCCESS         (0)
212 
213 /*!
214  * @brief   Generic error status code returned by ADC_control().
215  *
216  * ADC_control() returns ADC_STATUS_ERROR if the control code was not executed
217  * successfully.
218  */
219 #define ADC_STATUS_ERROR           (-1)
220 
221 /*!
222  * @brief   An error status code returned by ADC_control() for undefined
223  * command codes.
224  *
225  * ADC_control() returns ADC_STATUS_UNDEFINEDCMD if the control code is not
226  * recognized by the driver implementation.
227  */
228 #define ADC_STATUS_UNDEFINEDCMD    (-2)
229 /** @}*/
230 
231 /**
232  *  @defgroup ADC_CMD Command Codes
233  *  ADC_CMD_* macros are general command codes for ADC_control(). Not all ADC
234  *  driver implementations support these command codes.
235  *  @{
236  *  @ingroup ADC_CONTROL
237  */
238 
239 /* Add ADC_CMD_<commands> here */
240 
241 /** @}*/
242 
243 /** @}*/
244 
245 /*!
246  *  @brief      A handle that is returned from an ADC_open() call.
247  */
248 typedef struct ADC_Config_ *ADC_Handle;
249 
250 /*!
251  *  @brief  ADC Parameters used with ADC_open().
252  *
253  *  ADC_Params_init() must be called prior to setting fields in
254  *  this structure.
255  *
256  *  @sa     ADC_Params_init()
257  */
258 typedef struct {
259     void    *custom;        /*!< Custom argument used by driver
260                                 implementation */
261     bool    isProtected;    /*!< By default ADC uses a semaphore
262                                 to guarantee thread safety. Setting
263                                 this parameter to 'false' will eliminate
264                                 the usage of a semaphore for thread
265                                 safety. The user is then responsible
266                                 for ensuring that parallel invocations
267                                 of ADC_convert() are thread safe. */
268 } ADC_Params;
269 
270 /*!
271  *  @private
272  *  @brief      A function pointer to a driver specific implementation of
273  *              ADC_close().
274  */
275 typedef void (*ADC_CloseFxn) (ADC_Handle handle);
276 
277 /*!
278  *  @private
279  *  @brief      A function pointer to a driver specific implementation of
280  *              ADC_control().
281  */
282 typedef int_fast16_t (*ADC_ControlFxn) (ADC_Handle handle, uint_fast16_t cmd,
283     void *arg);
284 
285 /*!
286  *  @private
287  *  @brief      A function pointer to a driver specific implementation of
288  *              ADC_ConvertFxn().
289  */
290 typedef int_fast16_t (*ADC_ConvertFxn) (ADC_Handle handle, uint16_t *value);
291 
292 /*!
293  *  @private
294  *  @brief      A function pointer to a driver specific implementation of
295  *              ADC_convertToMicroVolts().
296  */
297 typedef uint32_t (*ADC_ConvertToMicroVoltsFxn) (ADC_Handle handle,
298     uint16_t adcValue);
299 
300 /*!
301  *  @private
302  *  @brief      A function pointer to a driver specific implementation of
303  *              ADC_init().
304  */
305 typedef void (*ADC_InitFxn) (ADC_Handle handle);
306 
307 /*!
308  *  @private
309  *  @brief      A function pointer to a driver specific implementation of
310  *              ADC_open().
311  */
312 typedef ADC_Handle (*ADC_OpenFxn) (ADC_Handle handle, ADC_Params *params);
313 
314 /*!
315  *  @brief      The definition of an ADC function table that contains the
316  *              required set of functions to control a specific ADC driver
317  *              implementation.
318  */
319 typedef struct {
320     /*! Function to close the specified peripheral */
321     ADC_CloseFxn      closeFxn;
322 
323     /*! Function to perform implementation specific features */
324     ADC_ControlFxn    controlFxn;
325 
326     /*! Function to initiate an ADC single channel conversion */
327     ADC_ConvertFxn    convertFxn;
328 
329     /*! Function to convert ADC result to microvolts */
330     ADC_ConvertToMicroVoltsFxn convertToMicroVolts;
331 
332     /*! Function to initialize the given data object */
333     ADC_InitFxn       initFxn;
334 
335     /*! Function to open the specified peripheral */
336     ADC_OpenFxn       openFxn;
337 } ADC_FxnTable;
338 
339 /*!
340  *  @brief ADC driver's custom @ref driver_configuration "configuration"
341  *  structure.
342  *
343  *  @sa     ADC_init()
344  *  @sa     ADC_open()
345  */
346 typedef struct ADC_Config_ {
347     /*! Pointer to a @ref driver_function_table "function pointer table"
348      *  with driver-specific implementations of ADC APIs */
349     ADC_FxnTable const *fxnTablePtr;
350 
351     /*! Pointer to a driver specific @ref driver_objects "data object". */
352     void               *object;
353 
354     /*! Pointer to a driver specific @ref driver_hardware_attributes
355      *  "hardware attributes structure". */
356     void         const *hwAttrs;
357 } ADC_Config;
358 
359 /*!
360  *  @brief  Function to close an ADC driver instance
361  *
362  *  @pre        ADC_open() has to be called first.
363  *
364  *  @param[in]  handle An #ADC_Handle returned from ADC_open()
365  */
366 extern void ADC_close(ADC_Handle handle);
367 
368 /*!
369  *  @brief  Function performs implementation specific features on a
370  *          driver instance.
371  *
372  *  @pre    ADC_open() has to be called first.
373  *
374  *  @param[in]  handle   An #ADC_Handle returned from ADC_open()
375  *
376  *  @param[in]  cmd     A command value defined by the device specific
377  *                      implementation
378  *
379  *  @param[in]  arg     An optional R/W (read/write) argument that is
380  *                      accompanied with @p cmd
381  *
382  *  @return Implementation specific return codes. Negative values indicate
383  *          unsuccessful operations.
384  *
385  *  @retval #ADC_STATUS_SUCCESS The call was successful.
386  *  @retval #ADC_STATUS_UNDEFINEDCMD The @p cmd value is not supported by
387  *                                   the device specific implementation.
388  */
389 extern int_fast16_t ADC_control(ADC_Handle handle, uint_fast16_t cmd,
390     void *arg);
391 
392 /*!
393  *  @brief  Function to perform an ADC conversion
394  *
395  *  Function to perform a single channel sample conversion.
396  *
397  *  @pre    ADC_open() has been called
398  *
399  *  @param[in]      handle    An #ADC_Handle returned from ADC_open()
400  *  @param[in,out]  value     A pointer to a uint16_t to store the conversion
401  *                            result
402  *
403  *  @retval #ADC_STATUS_SUCCESS  The conversion was successful.
404  *  @retval #ADC_STATUS_ERROR    The conversion failed and @p value is
405  *                               invalid.
406  *
407  *  @sa     ADC_convertToMicroVolts()
408  */
409 extern int_fast16_t ADC_convert(ADC_Handle handle, uint16_t *value);
410 
411 /*!
412  *  @brief  Function to convert a raw ADC sample into microvolts.
413  *
414  *  @pre    ADC_convert() has to be called first.
415  *
416  *  @param[in]  handle      An #ADC_Handle returned from ADC_open()
417  *
418  *  @param[in]  adcValue    A sampling result return from ADC_convert()
419  *
420  *  @return @p adcValue converted into microvolts
421  *
422  *  @sa     ADC_convert()
423  */
424 extern uint32_t ADC_convertToMicroVolts(ADC_Handle handle,
425     uint16_t adcValue);
426 
427 /*!
428  *  @brief  Function to initialize the ADC driver.
429  *
430  *  This function must also be called before any other ADC driver APIs.
431  */
432 extern void ADC_init(void);
433 
434 /*!
435  *  @brief  Function to initialize the ADC peripheral
436  *
437  *  Function to initialize the ADC peripheral specified by the
438  *  particular index value.
439  *
440  *  @pre    ADC_init() has been called
441  *
442  *  @param[in]  index     Index in the @p ADC_Config[] array.
443  *  @param[in]  params    Pointer to an initialized #ADC_Params structure.
444  *                        If NULL, the default #ADC_Params values are used.
445  *
446  *  @return An #ADC_Handle on success or NULL on error.
447  *
448  *  @sa     ADC_init()
449  *  @sa     ADC_close()
450  */
451 extern ADC_Handle ADC_open(uint_least8_t index, ADC_Params *params);
452 
453 /*!
454  *  @brief  Initialize an #ADC_Params structure to its default values.
455  *
456  *  @param[in]  params  A pointer to an #ADC_Params structure.
457  *
458  *  Default values are:
459  *  @arg #ADC_Params.custom = NULL
460  *  @arg #ADC_Params.isProtected = true
461  */
462 extern void ADC_Params_init(ADC_Params *params);
463 
464 #ifdef __cplusplus
465 }
466 #endif
467 
468 #endif /* ti_drivers_ADC__include */
469