/* ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @defgroup ADC ADC Driver * @brief Generic ADC Driver. * @details This module implements a generic ADC (Analog to Digital Converter) * driver supporting a variety of buffer and conversion modes. * @pre In order to use the ADC driver the @p HAL_USE_ADC option * must be enabled in @p halconf.h. * * @section adc_1 Driver State Machine * The driver implements a state machine internally, not all the driver * functionalities can be used in any moment, any transition not explicitly * shown in the following diagram has to be considered an error and shall * be captured by an assertion (if enabled). * @if LATEX_PDF * @dot digraph example { rankdir="LR"; size="5, 7"; node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"]; edge [fontname=Helvetica, fontsize=8]; stop [label="ADC_STOP\nLow Power"]; uninit [label="ADC_UNINIT", style="bold"]; ready [label="ADC_READY\nClock Enabled"]; active [label="ADC_ACTIVE\nConverting"]; error [label="ADC_ERROR\nError"]; complete [label="ADC_COMPLETE\nComplete"]; uninit -> stop [label="\n adcInit()", constraint=false]; stop -> ready [label="\nadcStart()"]; ready -> ready [label="\nadcStart()\nadcStopConversion()"]; ready -> stop [label="\nadcStop()"]; stop -> stop [label="\nadcStop()"]; ready -> active [label="\nadcStartConversion() (async)\nadcConvert() (sync)"]; active -> ready [label="\nadcStopConversion()\nsync return"]; active -> active [label="\nasync callback (half buffer, circular)\nasync callback (full buffer)\n>acg_endcb<"]; active -> complete [label="\n\nasync callback (full buffer)\n>end_cb<"]; active -> error [label="\n\nasync callback (error)\n>error_cb<"]; complete -> active [label="\nadcStartConversionI()\nthen\ncallback return"]; complete -> ready [label="\ncallback return"]; error -> active [label="\nadcStartConversionI()\nthen\ncallback return"]; error -> ready [label="\ncallback return"]; } * @enddot * @else * @dot digraph example { rankdir="LR"; node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.9", height="0.9"]; edge [fontname=Helvetica, fontsize=8]; stop [label="ADC_STOP\nLow Power"]; uninit [label="ADC_UNINIT", style="bold"]; ready [label="ADC_READY\nClock Enabled"]; active [label="ADC_ACTIVE\nConverting"]; error [label="ADC_ERROR\nError"]; complete [label="ADC_COMPLETE\nComplete"]; uninit -> stop [label="\n adcInit()", constraint=false]; stop -> ready [label="\nadcStart()"]; ready -> ready [label="\nadcStart()\nadcStopConversion()"]; ready -> stop [label="\nadcStop()"]; stop -> stop [label="\nadcStop()"]; ready -> active [label="\nadcStartConversion() (async)\nadcConvert() (sync)"]; active -> ready [label="\nadcStopConversion()\nsync return"]; active -> active [label="\nasync callback (half buffer, circular)\nasync callback (full buffer)\n>acg_endcb<"]; active -> complete [label="\n\nasync callback (full buffer)\n>end_cb<"]; active -> error [label="\n\nasync callback (error)\n>error_cb<"]; complete -> active [label="\nadcStartConversionI()\nthen\ncallback return"]; complete -> ready [label="\ncallback return"]; error -> active [label="\nadcStartConversionI()\nthen\ncallback return"]; error -> ready [label="\ncallback return"]; } * @enddot * @endif * * @section adc_2 ADC Operations * The ADC driver is quite complex, an explanation of the terminology and of * the operational details follows. * * @subsection adc_2_1 ADC Conversion Groups * The @p ADCConversionGroup is the objects that specifies a physical * conversion operation. This structure contains some standard fields and * several implementation-dependent fields.
* The standard fields define the CG mode, the number of channels belonging * to the CG and the optional callbacks.
* The implementation-dependent fields specify the physical ADC operation * mode, the analog channels belonging to the group and any other * implementation-specific setting. Usually the extra fields just mirror * the physical ADC registers, please refer to the vendor's MCU Reference * Manual for details about the available settings. Details are also available * into the documentation of the ADC low level drivers and in the various * sample applications. * * @subsection adc_2_2 ADC Conversion Modes * The driver supports several conversion modes: * - One Shot, the driver performs a single group conversion then stops. * - Linear Buffer, the driver performs a series of group conversions * then stops. This mode is like a one shot conversion repeated N times, * the buffer pointer increases after each conversion. The buffer is * organized as an S(CG)*N samples matrix, when S(CG) is the conversion * group size (number of channels) and N is the buffer depth (number of * repeated conversions). * - Circular Buffer, much like the linear mode but the operation does * not stop when the buffer is filled, it is automatically restarted * with the buffer pointer wrapping back to the buffer base. * . * @subsection adc_2_3 ADC Callbacks * The driver is able to invoke callbacks during the conversion process. A * callback is invoked when the operation has been completed or, in circular * mode, when the buffer has been filled and the operation is restarted. In * circular mode a callback is also invoked when the buffer is half filled.
* The "half filled" and "filled" callbacks in circular mode allow to * implement "streaming processing" of the sampled data, while the driver is * busy filling one half of the buffer the application can process the * other half, this allows for continuous interleaved operations. * * The driver is not thread safe for performance reasons, if you need to access * the ADC bus from multiple threads then use the @p adcAcquireBus() and * @p adcReleaseBus() APIs in order to gain exclusive access. * * @ingroup HAL_NORMAL_DRIVERS */