|
ChibiOS/RT
2.5.1 |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 00003 2011,2012 Giovanni Di Sirio. 00004 00005 This file is part of ChibiOS/RT. 00006 00007 ChibiOS/RT is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 ChibiOS/RT is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 /** 00022 * @file adc.h 00023 * @brief ADC Driver macros and structures. 00024 * 00025 * @addtogroup ADC 00026 * @{ 00027 */ 00028 00029 #ifndef _ADC_H_ 00030 #define _ADC_H_ 00031 00032 #if HAL_USE_ADC || defined(__DOXYGEN__) 00033 00034 /*===========================================================================*/ 00035 /* Driver constants. */ 00036 /*===========================================================================*/ 00037 00038 /*===========================================================================*/ 00039 /* Driver pre-compile time settings. */ 00040 /*===========================================================================*/ 00041 00042 /** 00043 * @name ADC configuration options 00044 * @{ 00045 */ 00046 /** 00047 * @brief Enables synchronous APIs. 00048 * @note Disabling this option saves both code and data space. 00049 */ 00050 #if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) 00051 #define ADC_USE_WAIT TRUE 00052 #endif 00053 00054 /** 00055 * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. 00056 * @note Disabling this option saves both code and data space. 00057 */ 00058 #if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 00059 #define ADC_USE_MUTUAL_EXCLUSION TRUE 00060 #endif 00061 /** @} */ 00062 00063 /*===========================================================================*/ 00064 /* Derived constants and error checks. */ 00065 /*===========================================================================*/ 00066 00067 #if ADC_USE_WAIT && !CH_USE_SEMAPHORES 00068 #error "ADC driver requires CH_USE_SEMAPHORES when ADC_USE_WAIT is enabled" 00069 #endif 00070 00071 /*===========================================================================*/ 00072 /* Driver data structures and types. */ 00073 /*===========================================================================*/ 00074 00075 /** 00076 * @brief Driver state machine possible states. 00077 */ 00078 typedef enum { 00079 ADC_UNINIT = 0, /**< Not initialized. */ 00080 ADC_STOP = 1, /**< Stopped. */ 00081 ADC_READY = 2, /**< Ready. */ 00082 ADC_ACTIVE = 3, /**< Converting. */ 00083 ADC_COMPLETE = 4, /**< Conversion complete. */ 00084 ADC_ERROR = 5 /**< Conversion complete. */ 00085 } adcstate_t; 00086 00087 #include "adc_lld.h" 00088 00089 /*===========================================================================*/ 00090 /* Driver macros. */ 00091 /*===========================================================================*/ 00092 00093 /** 00094 * @name Low Level driver helper macros 00095 * @{ 00096 */ 00097 #if ADC_USE_WAIT || defined(__DOXYGEN__) 00098 /** 00099 * @brief Resumes a thread waiting for a conversion completion. 00100 * 00101 * @param[in] adcp pointer to the @p ADCDriver object 00102 * 00103 * @notapi 00104 */ 00105 #define _adc_reset_i(adcp) { \ 00106 if ((adcp)->thread != NULL) { \ 00107 Thread *tp = (adcp)->thread; \ 00108 (adcp)->thread = NULL; \ 00109 tp->p_u.rdymsg = RDY_RESET; \ 00110 chSchReadyI(tp); \ 00111 } \ 00112 } 00113 00114 /** 00115 * @brief Resumes a thread waiting for a conversion completion. 00116 * 00117 * @param[in] adcp pointer to the @p ADCDriver object 00118 * 00119 * @notapi 00120 */ 00121 #define _adc_reset_s(adcp) { \ 00122 if ((adcp)->thread != NULL) { \ 00123 Thread *tp = (adcp)->thread; \ 00124 (adcp)->thread = NULL; \ 00125 chSchWakeupS(tp, RDY_RESET); \ 00126 } \ 00127 } 00128 00129 /** 00130 * @brief Wakes up the waiting thread. 00131 * 00132 * @param[in] adcp pointer to the @p ADCDriver object 00133 * 00134 * @notapi 00135 */ 00136 #define _adc_wakeup_isr(adcp) { \ 00137 chSysLockFromIsr(); \ 00138 if ((adcp)->thread != NULL) { \ 00139 Thread *tp; \ 00140 tp = (adcp)->thread; \ 00141 (adcp)->thread = NULL; \ 00142 tp->p_u.rdymsg = RDY_OK; \ 00143 chSchReadyI(tp); \ 00144 } \ 00145 chSysUnlockFromIsr(); \ 00146 } 00147 00148 /** 00149 * @brief Wakes up the waiting thread with a timeout message. 00150 * 00151 * @param[in] adcp pointer to the @p ADCDriver object 00152 * 00153 * @notapi 00154 */ 00155 #define _adc_timeout_isr(adcp) { \ 00156 chSysLockFromIsr(); \ 00157 if ((adcp)->thread != NULL) { \ 00158 Thread *tp; \ 00159 tp = (adcp)->thread; \ 00160 (adcp)->thread = NULL; \ 00161 tp->p_u.rdymsg = RDY_TIMEOUT; \ 00162 chSchReadyI(tp); \ 00163 } \ 00164 chSysUnlockFromIsr(); \ 00165 } 00166 00167 #else /* !ADC_USE_WAIT */ 00168 #define _adc_reset_i(adcp) 00169 #define _adc_reset_s(adcp) 00170 #define _adc_wakeup_isr(adcp) 00171 #define _adc_timeout_isr(adcp) 00172 #endif /* !ADC_USE_WAIT */ 00173 00174 /** 00175 * @brief Common ISR code, half buffer event. 00176 * @details This code handles the portable part of the ISR code: 00177 * - Callback invocation. 00178 * . 00179 * @note This macro is meant to be used in the low level drivers 00180 * implementation only. 00181 * 00182 * @param[in] adcp pointer to the @p ADCDriver object 00183 * 00184 * @notapi 00185 */ 00186 #define _adc_isr_half_code(adcp) { \ 00187 if ((adcp)->grpp->end_cb != NULL) { \ 00188 (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth / 2); \ 00189 } \ 00190 } 00191 00192 /** 00193 * @brief Common ISR code, full buffer event. 00194 * @details This code handles the portable part of the ISR code: 00195 * - Callback invocation. 00196 * - Waiting thread wakeup, if any. 00197 * - Driver state transitions. 00198 * . 00199 * @note This macro is meant to be used in the low level drivers 00200 * implementation only. 00201 * 00202 * @param[in] adcp pointer to the @p ADCDriver object 00203 * 00204 * @notapi 00205 */ 00206 #define _adc_isr_full_code(adcp) { \ 00207 if ((adcp)->grpp->circular) { \ 00208 /* Callback handling.*/ \ 00209 if ((adcp)->grpp->end_cb != NULL) { \ 00210 if ((adcp)->depth > 1) { \ 00211 /* Invokes the callback passing the 2nd half of the buffer.*/ \ 00212 size_t half = (adcp)->depth / 2; \ 00213 size_t half_index = half * (adcp)->grpp->num_channels; \ 00214 (adcp)->grpp->end_cb(adcp, (adcp)->samples + half_index, half); \ 00215 } \ 00216 else { \ 00217 /* Invokes the callback passing the whole buffer.*/ \ 00218 (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth); \ 00219 } \ 00220 } \ 00221 } \ 00222 else { \ 00223 /* End conversion.*/ \ 00224 adc_lld_stop_conversion(adcp); \ 00225 if ((adcp)->grpp->end_cb != NULL) { \ 00226 (adcp)->state = ADC_COMPLETE; \ 00227 if ((adcp)->depth > 1) { \ 00228 /* Invokes the callback passing the 2nd half of the buffer.*/ \ 00229 size_t half = (adcp)->depth / 2; \ 00230 size_t half_index = half * (adcp)->grpp->num_channels; \ 00231 (adcp)->grpp->end_cb(adcp, (adcp)->samples + half_index, half); \ 00232 } \ 00233 else { \ 00234 /* Invokes the callback passing the whole buffer.*/ \ 00235 (adcp)->grpp->end_cb(adcp, (adcp)->samples, (adcp)->depth); \ 00236 } \ 00237 if ((adcp)->state == ADC_COMPLETE) \ 00238 (adcp)->state = ADC_READY; \ 00239 } \ 00240 else \ 00241 (adcp)->state = ADC_READY; \ 00242 (adcp)->grpp = NULL; \ 00243 _adc_wakeup_isr(adcp); \ 00244 } \ 00245 } 00246 00247 /** 00248 * @brief Common ISR code, error event. 00249 * @details This code handles the portable part of the ISR code: 00250 * - Callback invocation. 00251 * - Waiting thread timeout signaling, if any. 00252 * - Driver state transitions. 00253 * . 00254 * @note This macro is meant to be used in the low level drivers 00255 * implementation only. 00256 * 00257 * @param[in] adcp pointer to the @p ADCDriver object 00258 * @param[in] err platform dependent error code 00259 * 00260 * @notapi 00261 */ 00262 #define _adc_isr_error_code(adcp, err) { \ 00263 adc_lld_stop_conversion(adcp); \ 00264 if ((adcp)->grpp->error_cb != NULL) { \ 00265 (adcp)->state = ADC_ERROR; \ 00266 (adcp)->grpp->error_cb(adcp, err); \ 00267 if ((adcp)->state == ADC_ERROR) \ 00268 (adcp)->state = ADC_READY; \ 00269 } \ 00270 (adcp)->grpp = NULL; \ 00271 _adc_timeout_isr(adcp); \ 00272 } 00273 /** @} */ 00274 00275 /*===========================================================================*/ 00276 /* External declarations. */ 00277 /*===========================================================================*/ 00278 00279 #ifdef __cplusplus 00280 extern "C" { 00281 #endif 00282 void adcInit(void); 00283 void adcObjectInit(ADCDriver *adcp); 00284 void adcStart(ADCDriver *adcp, const ADCConfig *config); 00285 void adcStop(ADCDriver *adcp); 00286 void adcStartConversion(ADCDriver *adcp, 00287 const ADCConversionGroup *grpp, 00288 adcsample_t *samples, 00289 size_t depth); 00290 void adcStartConversionI(ADCDriver *adcp, 00291 const ADCConversionGroup *grpp, 00292 adcsample_t *samples, 00293 size_t depth); 00294 void adcStopConversion(ADCDriver *adcp); 00295 void adcStopConversionI(ADCDriver *adcp); 00296 #if ADC_USE_WAIT 00297 msg_t adcConvert(ADCDriver *adcp, 00298 const ADCConversionGroup *grpp, 00299 adcsample_t *samples, 00300 size_t depth); 00301 #endif 00302 #if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) 00303 void adcAcquireBus(ADCDriver *adcp); 00304 void adcReleaseBus(ADCDriver *adcp); 00305 #endif /* ADC_USE_MUTUAL_EXCLUSION */ 00306 #ifdef __cplusplus 00307 } 00308 #endif 00309 00310 #endif /* HAL_USE_ADC */ 00311 00312 #endif /* _ADC_H_ */ 00313 00314 /** @} */