/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 2011,2012 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 . --- 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)\nasync callback (full buffer circular)\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)\nasync callback (full buffer circular)\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 * linear and circular modes 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 IO */