/*
    ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
                 2011,2012,2013 Giovanni Di Sirio.

    This file is part of ChibiOS/RT.

    ChibiOS/RT is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    ChibiOS/RT is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

                                      ---

    A special exception to the GPL can be applied should you wish to distribute
    a combined work that includes ChibiOS/RT, without being obliged to provide
    the source code for any proprietary components. See the file exception.txt
    for full details of how and when the exception can be applied.
*/

/**
 * @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.<br>
 * The standard fields define the CG mode, the number of channels belonging
 * to the CG and the optional callbacks.<br>
 * 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:
 * - <b>One Shot</b>, the driver performs a single group conversion then stops.
 * - <b>Linear Buffer</b>, 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).
 * - <b>Circular Buffer</b>, 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.<br>
 * 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 IO
 */
