/* 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 . */ /** * @file dac.c * @brief DAC Driver code. * * @addtogroup DAC * @{ */ #include "hal.h" #if HAL_USE_DAC || defined(__DOXYGEN__) /*===========================================================================*/ /* Driver local definitions. */ /*===========================================================================*/ /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ /*===========================================================================*/ /* Driver local variables. */ /*===========================================================================*/ /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ /** * @brief DAC Driver initialization. * @note This function is implicitly invoked by @p halInit(), there is * no need to explicitly initialize the driver. * * @init */ void dacInit(void) { dac_lld_init(); } /** * @brief Initializes the standard part of a @p DACDriver structure. * * @param[out] dacp pointer to the @p DACDriver object * * @init */ void dacObjectInit(DACDriver *dacp) { dacp->state = DAC_STOP; dacp->config = NULL; #if DAC_USE_WAIT dacp->thread = NULL; #endif /* DAC_USE_WAIT */ #if DAC_USE_MUTUAL_EXCLUSION osalMutexObjectInit(&dacp->mutex); #endif /* DAC_USE_MUTUAL_EXCLUSION */ #if defined(DAC_DRIVER_EXT_INIT_HOOK) DAC_DRIVER_EXT_INIT_HOOK(dacp); #endif } /** * @brief Configures and activates the DAC peripheral. * * @param[in] dacp pointer to the @p DACDriver object * @param[in] config pointer to the @p DACConfig object * * @api */ void dacStart(DACDriver *dacp, const DACConfig *config) { osalDbgCheck((dacp != NULL) && (config != NULL)); osalSysLock(); osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), "invalid state"); dacp->config = config; dac_lld_start(dacp); dacp->state = DAC_READY; osalSysUnlock(); } /** * @brief Deactivates the DAC peripheral. * @note Deactivating the peripheral also enforces a release of the slave * select line. * * @param[in] dacp pointer to the @p DACDriver object * * @api */ void dacStop(DACDriver *dacp) { osalDbgCheck(dacp != NULL); osalSysLock(); osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), "invalid state"); dac_lld_stop(dacp); dacp->state = DAC_STOP; osalSysUnlock(); } /** * @brief Starts a DAC conversion. * @details Starts an asynchronous conversion operation. * @note The buffer is organized as a matrix of M*N elements where M is the * channels number configured into the conversion group and N is the * buffer depth. The samples are sequentially written into the buffer * with no gaps. * * @param[in] dacp pointer to the @p DACDriver object * @param[in] grpp pointer to a @p DACConversionGroup object * @param[in] samples pointer to the samples buffer * @param[in] depth buffer depth (matrix rows number). The buffer depth * must be one or an even number. * * @api */ void dacStartConversion(DACDriver *dacp, const DACConversionGroup *grpp, const dacsample_t *samples, size_t depth) { osalSysLock(); dacStartConversionI(dacp, grpp, samples, depth); osalSysUnlock(); } /** * @brief Starts a DAC conversion. * @details Starts an asynchronous conversion operation. * @post The callbacks associated to the conversion group will be invoked * on buffer fill and error events. * @note The buffer is organized as a matrix of M*N elements where M is the * channels number configured into the conversion group and N is the * buffer depth. The samples are sequentially written into the buffer * with no gaps. * * @param[in] dacp pointer to the @p DACDriver object * @param[in] grpp pointer to a @p DACConversionGroup object * @param[in] samples pointer to the samples buffer * @param[in] depth buffer depth (matrix rows number). The buffer depth * must be one or an even number. * * @iclass */ void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp, const dacsample_t *samples, size_t depth) { osalDbgCheckClassI(); osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) && ((depth == 1) || ((depth & 1) == 0))); osalDbgAssert((dacp->state == DAC_READY) || (dacp->state == DAC_COMPLETE) || (dacp->state == DAC_ERROR), "not ready"); dacp->samples = samples; dacp->depth = depth; dacp->grpp = grpp; dacp->state = DAC_ACTIVE; dac_lld_start_conversion(dacp); } /** * @brief Stops an ongoing conversion. * @details This function stops the currently ongoing conversion and returns * the driver in the @p DAC_READY state. If there was no conversion * being processed then the function does nothing. * * @param[in] dacp pointer to the @p DACDriver object * * @api */ void dacStopConversion(DACDriver *dacp) { osalDbgCheck(dacp != NULL); osalSysLock(); osalDbgAssert((dacp->state == DAC_READY) || (dacp->state == DAC_ACTIVE), "invalid state"); if (dacp->state != DAC_READY) { dac_lld_stop_conversion(dacp); dacp->grpp = NULL; dacp->state = DAC_READY; _dac_reset_s(dacp); } osalSysUnlock(); } /** * @brief Stops an ongoing conversion. * @details This function stops the currently ongoing conversion and returns * the driver in the @p DAC_READY state. If there was no conversion * being processed then the function does nothing. * * @param[in] dacp pointer to the @p DACDriver object * * @iclass */ void dacStopConversionI(DACDriver *dacp) { osalDbgCheckClassI(); osalDbgCheck(dacp != NULL); osalDbgAssert((dacp->state == DAC_READY) || (dacp->state == DAC_ACTIVE) || (dacp->state == DAC_COMPLETE), "invalid state"); if (dacp->state != DAC_READY) { dac_lld_stop_conversion(dacp); dacp->grpp = NULL; dacp->state = DAC_READY; _dac_reset_i(dacp); } } #if DAC_USE_WAIT || defined(__DOXYGEN__) /** * @brief Performs a DAC conversion. * @details Performs a synchronous conversion operation. * @note The buffer is organized as a matrix of M*N elements where M is the * channels number configured into the conversion group and N is the * buffer depth. The samples are sequentially written into the buffer * with no gaps. * * @param[in] dacp pointer to the @p DACDriver object * @param[in] grpp pointer to a @p DACConversionGroup object * @param[out] samples pointer to the samples buffer * @param[in] depth buffer depth (matrix rows number). The buffer depth * must be one or an even number. * @return The operation result. * @retval MSG_OK Conversion finished. * @retval MSG_RESET The conversion has been stopped using * @p acdStopConversion() or @p acdStopConversionI(), * the result buffer may contain incorrect data. * @retval MSG_TIMEOUT The conversion has been stopped because an hardware * error. * * @api */ msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp, const dacsample_t *samples, size_t depth) { msg_t msg; osalSysLock(); dacStartConversionI(dacp, grpp, samples, depth); msg = osalThreadSuspendS(&dacp->thread); osalSysUnlock(); return msg; } #endif /* DAC_USE_WAIT */ #if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) /** * @brief Gains exclusive access to the DAC bus. * @details This function tries to gain ownership to the DAC bus, if the bus * is already being used then the invoking thread is queued. * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION * must be enabled. * * @param[in] dacp pointer to the @p DACDriver object * * @api */ void dacAcquireBus(DACDriver *dacp) { osalDbgCheck(dacp != NULL); osalMutexLock(&dacp->mutex); } /** * @brief Releases exclusive access to the DAC bus. * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION * must be enabled. * * @param[in] dacp pointer to the @p DACDriver object * * @api */ void dacReleaseBus(DACDriver *dacp) { osalDbgCheck(dacp != NULL); osalMutexUnlock(&dacp->mutex); } #endif /* DAC_USE_MUTUAL_EXCLUSION */ #endif /* HAL_USE_DAC */ /** @} */