DAC merge and rework, part 1.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5911 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
6514f4422c
commit
e01bc962c7
|
@ -0,0 +1,324 @@
|
||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file dac.h
|
||||||
|
* @brief DAC Driver macros and structures.
|
||||||
|
*
|
||||||
|
* @addtogroup DAC
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DAC_H_
|
||||||
|
#define _DAC_H_
|
||||||
|
|
||||||
|
#if HAL_USE_DAC || defined(__DOXYGEN__)
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver constants. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver pre-compile time settings. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name DAC configuration options
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief Enables synchronous APIs.
|
||||||
|
* @note Disabling this option saves both code and data space.
|
||||||
|
*/
|
||||||
|
#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
|
||||||
|
#define DAC_USE_WAIT TRUE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
|
||||||
|
* @note Disabling this option saves both code and data space.
|
||||||
|
*/
|
||||||
|
#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||||
|
#define DAC_USE_MUTUAL_EXCLUSION TRUE
|
||||||
|
#endif
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Derived constants and error checks. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#if DAC_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES
|
||||||
|
#error "DAC_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver data structures and types. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Driver state machine possible states.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
DAC_UNINIT = 0, /**< Not initialized. */
|
||||||
|
DAC_STOP = 1, /**< Stopped. */
|
||||||
|
DAC_READY = 2, /**< Ready. */
|
||||||
|
DAC_ACTIVE = 3, /**< Exchanging data. */
|
||||||
|
DAC_COMPLETE = 4, /**< Asynchronous operation complete. */
|
||||||
|
DAC_ERROR = 5 /**< Error. */
|
||||||
|
} dacstate_t;
|
||||||
|
|
||||||
|
#include "dac_lld.h"
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Driver macros. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Low Level driver helper macros
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#if DAC_USE_WAIT || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Waits for operation completion.
|
||||||
|
* @details This function waits for the driver to complete the current
|
||||||
|
* operation.
|
||||||
|
* @pre An operation must be running while the function is invoked.
|
||||||
|
* @note No more than one thread can wait on a DAC driver using
|
||||||
|
* this function.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
#define _dac_wait_s(dacp) { \
|
||||||
|
chDbgAssert((dacp)->thread == NULL, \
|
||||||
|
"_dac_wait_s(), #1", "already waiting"); \
|
||||||
|
(dacp)->thread = chThdSelf(); \
|
||||||
|
chSchGoSleepS(THD_STATE_SUSPENDED); \
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Resumes a thread waiting for a conversion completion.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
#define _dac_reset_i(dacp) { \
|
||||||
|
if ((dacp)->thread != NULL) { \
|
||||||
|
Thread *tp = (dacp)->thread; \
|
||||||
|
(dacp)->thread = NULL; \
|
||||||
|
tp->p_u.rdymsg = RDY_RESET; \
|
||||||
|
chSchReadyI(tp); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resumes a thread waiting for a conversion completion.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
#define _dac_reset_s(dacp) { \
|
||||||
|
if ((dacp)->thread != NULL) { \
|
||||||
|
Thread *tp = (dacp)->thread; \
|
||||||
|
(dacp)->thread = NULL; \
|
||||||
|
chSchWakeupS(tp, RDY_RESET); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wakes up the waiting thread.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
#define _dac_wakeup_isr(dacp) { \
|
||||||
|
chSysLockFromIsr(); \
|
||||||
|
if ((dacp)->thread != NULL) { \
|
||||||
|
Thread *tp; \
|
||||||
|
tp = (dacp)->thread; \
|
||||||
|
(dacp)->thread = NULL; \
|
||||||
|
tp->p_u.rdymsg = RDY_OK; \
|
||||||
|
chSchReadyI(tp); \
|
||||||
|
} \
|
||||||
|
chSysUnlockFromIsr(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wakes up the waiting thread with a timeout message.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
#define _dac_timeout_isr(dacp) { \
|
||||||
|
chSysLockFromIsr(); \
|
||||||
|
if ((dacp)->thread != NULL) { \
|
||||||
|
Thread *tp; \
|
||||||
|
tp = (dacp)->thread; \
|
||||||
|
(dacp)->thread = NULL; \
|
||||||
|
tp->p_u.rdymsg = RDY_TIMEOUT; \
|
||||||
|
chSchReadyI(tp); \
|
||||||
|
} \
|
||||||
|
chSysUnlockFromIsr(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !DAC_USE_WAIT */
|
||||||
|
#define _dac_wait_s(dacp)
|
||||||
|
#define _dac_reset_i(dacp)
|
||||||
|
#define _dac_reset_s(dacp)
|
||||||
|
#define _dac_wakeup_isr(dacp)
|
||||||
|
#define _dac_timeout_isr(dacp)
|
||||||
|
#endif /* !DAC_USE_WAIT */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Common ISR code, half buffer event.
|
||||||
|
* @details This code handles the portable part of the ISR code:
|
||||||
|
* - Callback invocation.
|
||||||
|
* .
|
||||||
|
* @note This macro is meant to be used in the low level drivers
|
||||||
|
* implementation only.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
#define _dac_isr_half_code(dacp) { \
|
||||||
|
if ((dacp)->grpp->end_cb != NULL) { \
|
||||||
|
(dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth / 2); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Common ISR code, full buffer event.
|
||||||
|
* @details This code handles the portable part of the ISR code:
|
||||||
|
* - Callback invocation.
|
||||||
|
* - Waiting thread wakeup, if any.
|
||||||
|
* - Driver state transitions.
|
||||||
|
* .
|
||||||
|
* @note This macro is meant to be used in the low level drivers
|
||||||
|
* implementation only.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
#define _dac_isr_full_code(dacp) { \
|
||||||
|
if ((dacp)->grpp->circular) { \
|
||||||
|
/* Callback handling.*/ \
|
||||||
|
if ((dacp)->grpp->end_cb != NULL) { \
|
||||||
|
if ((dacp)->depth > 1) { \
|
||||||
|
/* Invokes the callback passing the 2nd half of the buffer.*/ \
|
||||||
|
size_t half = (dacp)->depth / 2; \
|
||||||
|
size_t half_index = half * (dacp)->grpp->num_channels; \
|
||||||
|
(dacp)->grpp->end_cb(dacp, (dacp)->samples + half_index, half); \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
/* Invokes the callback passing the whole buffer.*/ \
|
||||||
|
(dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
/* End conversion.*/ \
|
||||||
|
dac_lld_stop_conversion(dacp); \
|
||||||
|
if ((dacp)->grpp->end_cb != NULL) { \
|
||||||
|
(dacp)->state = DAC_COMPLETE; \
|
||||||
|
if ((dacp)->depth > 1) { \
|
||||||
|
/* Invokes the callback passing the 2nd half of the buffer.*/ \
|
||||||
|
size_t half = (dacp)->depth / 2; \
|
||||||
|
size_t half_index = half * (dacp)->grpp->num_channels; \
|
||||||
|
(dacp)->grpp->end_cb(dacp, (dacp)->samples + half_index, half); \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
/* Invokes the callback passing the whole buffer.*/ \
|
||||||
|
(dacp)->grpp->end_cb(dacp, (dacp)->samples, (dacp)->depth); \
|
||||||
|
} \
|
||||||
|
if ((dacp)->state == DAC_COMPLETE) { \
|
||||||
|
(dacp)->state = DAC_READY; \
|
||||||
|
(dacp)->grpp = NULL; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
(dacp)->state = DAC_READY; \
|
||||||
|
(dacp)->grpp = NULL; \
|
||||||
|
} \
|
||||||
|
_dac_wakeup_isr(dacp); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Common ISR code, error event.
|
||||||
|
* @details This code handles the portable part of the ISR code:
|
||||||
|
* - Callback invocation.
|
||||||
|
* - Waiting thread timeout signaling, if any.
|
||||||
|
* - Driver state transitions.
|
||||||
|
* .
|
||||||
|
* @note This macro is meant to be used in the low level drivers
|
||||||
|
* implementation only.
|
||||||
|
*
|
||||||
|
* @param[in] dacp pointer to the @p DACDriver object
|
||||||
|
* @param[in] err platform dependent error code
|
||||||
|
*
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
#define _dac_isr_error_code(dacp, err) { \
|
||||||
|
dac_lld_stop_conversion(dacp); \
|
||||||
|
if ((dacp)->grpp->error_cb != NULL) { \
|
||||||
|
(dacp)->state = DAC_ERROR; \
|
||||||
|
(dacp)->grpp->error_cb(dacp, err); \
|
||||||
|
if ((dacp)->state == DAC_ERROR) \
|
||||||
|
(dacp)->state = DAC_READY; \
|
||||||
|
} \
|
||||||
|
(dacp)->grpp = NULL; \
|
||||||
|
_dac_timeout_isr(dacp); \
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* External declarations. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void dacInit(void);
|
||||||
|
void dacObjectInit(DACDriver *dacp);
|
||||||
|
void dacStart(DACDriver *dacp, const DACConfig *config);
|
||||||
|
void dacStop(DACDriver *dacp);
|
||||||
|
void dacStartSend(DACDriver *dacp);
|
||||||
|
#if DAC_USE_WAIT
|
||||||
|
void dacSend(DACDriver *dacp);
|
||||||
|
#endif /* DAC_USE_WAIT */
|
||||||
|
#if DAC_USE_MUTUAL_EXCLUSION
|
||||||
|
void dacAcquireBus(DACDriver *dacp);
|
||||||
|
void dacReleaseBus(DACDriver *dacp);
|
||||||
|
#endif /* DAC_USE_MUTUAL_EXCLUSION */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAL_USE_DAC */
|
||||||
|
|
||||||
|
#endif /* _DAC_H_ */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -244,13 +244,14 @@ typedef enum {
|
||||||
* @notapi
|
* @notapi
|
||||||
*/
|
*/
|
||||||
#define _spi_wakeup_isr(spip) { \
|
#define _spi_wakeup_isr(spip) { \
|
||||||
|
chSysLockFromIsr(); \
|
||||||
if ((spip)->thread != NULL) { \
|
if ((spip)->thread != NULL) { \
|
||||||
Thread *tp = (spip)->thread; \
|
Thread *tp = (spip)->thread; \
|
||||||
(spip)->thread = NULL; \
|
(spip)->thread = NULL; \
|
||||||
chSysLockFromIsr(); \
|
tp->p_u.rdymsg = RDY_OK; \
|
||||||
chSchReadyI(tp); \
|
chSchReadyI(tp); \
|
||||||
chSysUnlockFromIsr(); \
|
|
||||||
} \
|
} \
|
||||||
|
chSysUnlockFromIsr(); \
|
||||||
}
|
}
|
||||||
#else /* !SPI_USE_WAIT */
|
#else /* !SPI_USE_WAIT */
|
||||||
#define _spi_wait_s(spip)
|
#define _spi_wait_s(spip)
|
||||||
|
|
|
@ -0,0 +1,286 @@
|
||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file dac.c
|
||||||
|
* @brief DAC Driver code.
|
||||||
|
*
|
||||||
|
* @addtogroup DAC
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ch.h"
|
||||||
|
#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
|
||||||
|
#if CH_USE_MUTEXES
|
||||||
|
chMtxInit(&dacp->mutex);
|
||||||
|
#else
|
||||||
|
chSemInit(&dacp->semaphore, 1);
|
||||||
|
#endif
|
||||||
|
#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) {
|
||||||
|
|
||||||
|
chDbgCheck((dacp != NULL) && (config != NULL), "dacStart");
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
chDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
|
||||||
|
"dacStart(), #1", "invalid state");
|
||||||
|
dacp->config = config;
|
||||||
|
dac_lld_start(dacp);
|
||||||
|
dacp->state = DAC_READY;
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
||||||
|
|
||||||
|
chDbgCheck(dacp != NULL, "dacStop");
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
chDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
|
||||||
|
"dacStop(), #1", "invalid state");
|
||||||
|
dac_lld_stop(dacp);
|
||||||
|
dacp->state = DAC_STOP;
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
dacStartConversionI(dacp, grpp, samples, depth);
|
||||||
|
chSysUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
||||||
|
|
||||||
|
chDbgCheckClassI();
|
||||||
|
chDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
|
||||||
|
((depth == 1) || ((depth & 1) == 0)),
|
||||||
|
"dacStartConversionI");
|
||||||
|
chDbgAssert((dacp->state == DAC_READY) ||
|
||||||
|
(dacp->state == DAC_COMPLETE) ||
|
||||||
|
(dacp->state == DAC_ERROR),
|
||||||
|
"dacStartConversionI(), #1", "not ready");
|
||||||
|
|
||||||
|
dacp->samples = samples;
|
||||||
|
dacp->depth = depth;
|
||||||
|
dacp->grpp = grpp;
|
||||||
|
dacp->state = DAC_ACTIVE;
|
||||||
|
dac_lld_start_conversion(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 RDY_OK Conversion finished.
|
||||||
|
* @retval RDY_RESET The conversion has been stopped using
|
||||||
|
* @p acdStopConversion() or @p acdStopConversionI(),
|
||||||
|
* the result buffer may contain incorrect data.
|
||||||
|
* @retval RDY_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;
|
||||||
|
|
||||||
|
chSysLock();
|
||||||
|
chDbgAssert(dacp->thread == NULL, "dacConvert(), #1", "already waiting");
|
||||||
|
dacStartConversionI(dacp, grpp, samples, depth);
|
||||||
|
_dac_wait_s(dacp);
|
||||||
|
msg = chThdSelf()->p_u.rdymsg;
|
||||||
|
chSysUnlock();
|
||||||
|
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) {
|
||||||
|
|
||||||
|
chDbgCheck(dacp != NULL, "dacAcquireBus");
|
||||||
|
|
||||||
|
#if CH_USE_MUTEXES
|
||||||
|
chMtxLock(&dacp->mutex);
|
||||||
|
#elif CH_USE_SEMAPHORES
|
||||||
|
chSemWait(&dacp->semaphore);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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) {
|
||||||
|
|
||||||
|
chDbgCheck(dacp != NULL, "dacReleaseBus");
|
||||||
|
|
||||||
|
#if CH_USE_MUTEXES
|
||||||
|
(void)dacp;
|
||||||
|
chMtxUnlock();
|
||||||
|
#elif CH_USE_SEMAPHORES
|
||||||
|
chSemSignal(&dacp->semaphore);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* DAC_USE_MUTUAL_EXCLUSION */
|
||||||
|
|
||||||
|
#endif /* HAL_USE_DAC */
|
||||||
|
|
||||||
|
/** @} */
|
Loading…
Reference in New Issue