ChibiOS/HAL  6.1.0
hal_dac.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 /**
18  * @file hal_dac.c
19  * @brief DAC Driver code.
20  *
21  * @addtogroup DAC
22  * @{
23  */
24 
25 #include "hal.h"
26 
27 #if (HAL_USE_DAC == TRUE) || defined(__DOXYGEN__)
28 
29 /*===========================================================================*/
30 /* Driver local definitions. */
31 /*===========================================================================*/
32 
33 /*===========================================================================*/
34 /* Driver exported variables. */
35 /*===========================================================================*/
36 
37 /*===========================================================================*/
38 /* Driver local variables. */
39 /*===========================================================================*/
40 
41 /*===========================================================================*/
42 /* Driver local functions. */
43 /*===========================================================================*/
44 
45 /*===========================================================================*/
46 /* Driver exported functions. */
47 /*===========================================================================*/
48 
49 /**
50  * @brief DAC Driver initialization.
51  * @note This function is implicitly invoked by @p halInit(), there is
52  * no need to explicitly initialize the driver.
53  *
54  * @init
55  */
56 void dacInit(void) {
57 
58  dac_lld_init();
59 }
60 
61 /**
62  * @brief Initializes the standard part of a @p DACDriver structure.
63  *
64  * @param[out] dacp pointer to the @p DACDriver object
65  *
66  * @init
67  */
68 void dacObjectInit(DACDriver *dacp) {
69 
70  dacp->state = DAC_STOP;
71  dacp->config = NULL;
72 #if DAC_USE_WAIT
73  dacp->thread = NULL;
74 #endif
75 #if DAC_USE_MUTUAL_EXCLUSION
76  osalMutexObjectInit(&dacp->mutex);
77 #endif
78 #if defined(DAC_DRIVER_EXT_INIT_HOOK)
79  DAC_DRIVER_EXT_INIT_HOOK(dacp);
80 #endif
81 }
82 
83 /**
84  * @brief Configures and activates the DAC peripheral.
85  *
86  * @param[in] dacp pointer to the @p DACDriver object
87  * @param[in] config pointer to the @p DACConfig object, it can be
88  * @p NULL if the low level driver implementation
89  * supports a default configuration
90  *
91  * @api
92  */
93 void dacStart(DACDriver *dacp, const DACConfig *config) {
94 
95  osalDbgCheck(dacp != NULL);
96 
97  osalSysLock();
98 
99  osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
100  "invalid state");
101 
102  dacp->config = config;
103  dac_lld_start(dacp);
104  dacp->state = DAC_READY;
105 
106  osalSysUnlock();
107 }
108 
109 /**
110  * @brief Deactivates the DAC peripheral.
111  * @note Deactivating the peripheral also enforces a release of the slave
112  * select line.
113  *
114  * @param[in] dacp pointer to the @p DACDriver object
115  *
116  * @api
117  */
118 void dacStop(DACDriver *dacp) {
119 
120  osalDbgCheck(dacp != NULL);
121 
122  osalSysLock();
123 
124  osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
125  "invalid state");
126 
127  dac_lld_stop(dacp);
128  dacp->config = NULL;
129  dacp->state = DAC_STOP;
130 
131  osalSysUnlock();
132 }
133 
134 /**
135  * @brief Outputs a value directly on a DAC channel.
136  *
137  * @param[in] dacp pointer to the @p DACDriver object
138  * @param[in] channel DAC channel number
139  * @param[in] sample value to be output
140  *
141  * @xclass
142  */
143 void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample) {
144 
145  osalDbgCheck(channel < DAC_MAX_CHANNELS);
146  osalDbgAssert(dacp->state == DAC_READY, "invalid state");
147 
148  dac_lld_put_channel(dacp, channel, sample);
149 }
150 
151 /**
152  * @brief Starts a DAC conversion.
153  * @details Starts an asynchronous conversion operation.
154  * @note The buffer is organized as a matrix of M*N elements where M is the
155  * channels number configured into the conversion group and N is the
156  * buffer depth. The samples are sequentially written into the buffer
157  * with no gaps.
158  *
159  * @param[in] dacp pointer to the @p DACDriver object
160  * @param[in] grpp pointer to a @p DACConversionGroup object
161  * @param[in] samples pointer to the samples buffer
162  * @param[in] depth buffer depth (matrix rows number). The buffer depth
163  * must be one or an even number.
164  *
165  * @api
166  */
168  const DACConversionGroup *grpp,
169  dacsample_t *samples,
170  size_t depth) {
171 
172  osalSysLock();
173  dacStartConversionI(dacp, grpp, samples, depth);
174  osalSysUnlock();
175 }
176 
177 /**
178  * @brief Starts a DAC conversion.
179  * @details Starts an asynchronous conversion operation.
180  * @post The callbacks associated to the conversion group will be invoked
181  * on buffer fill and error events.
182  * @note The buffer is organized as a matrix of M*N elements where M is the
183  * channels number configured into the conversion group and N is the
184  * buffer depth. The samples are sequentially written into the buffer
185  * with no gaps.
186  *
187  * @param[in] dacp pointer to the @p DACDriver object
188  * @param[in] grpp pointer to a @p DACConversionGroup object
189  * @param[in] samples pointer to the samples buffer
190  * @param[in] depth buffer depth (matrix rows number). The buffer depth
191  * must be one or an even number.
192  *
193  * @iclass
194  */
196  const DACConversionGroup *grpp,
197  dacsample_t *samples,
198  size_t depth) {
199 
201  osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
202  ((depth == 1) || ((depth & 1) == 0)));
203  osalDbgAssert((dacp->state == DAC_READY) ||
204  (dacp->state == DAC_COMPLETE) ||
205  (dacp->state == DAC_ERROR),
206  "not ready");
207 
208  dacp->samples = samples;
209  dacp->depth = depth;
210  dacp->grpp = grpp;
211  dacp->state = DAC_ACTIVE;
213 }
214 
215 /**
216  * @brief Stops an ongoing conversion.
217  * @details This function stops the currently ongoing conversion and returns
218  * the driver in the @p DAC_READY state. If there was no conversion
219  * being processed then the function does nothing.
220  *
221  * @param[in] dacp pointer to the @p DACDriver object
222  *
223  * @api
224  */
226 
227  osalDbgCheck(dacp != NULL);
228 
229  osalSysLock();
230 
231  osalDbgAssert((dacp->state == DAC_READY) ||
232  (dacp->state == DAC_ACTIVE),
233  "invalid state");
234 
235  if (dacp->state != DAC_READY) {
237  dacp->grpp = NULL;
238  dacp->state = DAC_READY;
239  _dac_reset_s(dacp);
240  }
241 
242  osalSysUnlock();
243 }
244 
245 /**
246  * @brief Stops an ongoing conversion.
247  * @details This function stops the currently ongoing conversion and returns
248  * the driver in the @p DAC_READY state. If there was no conversion
249  * being processed then the function does nothing.
250  *
251  * @param[in] dacp pointer to the @p DACDriver object
252  *
253  * @iclass
254  */
256 
258  osalDbgCheck(dacp != NULL);
259  osalDbgAssert((dacp->state == DAC_READY) ||
260  (dacp->state == DAC_ACTIVE) ||
261  (dacp->state == DAC_COMPLETE),
262  "invalid state");
263 
264  if (dacp->state != DAC_READY) {
266  dacp->grpp = NULL;
267  dacp->state = DAC_READY;
268  _dac_reset_i(dacp);
269  }
270 }
271 
272 #if (DAC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
273 /**
274  * @brief Performs a DAC conversion.
275  * @details Performs a synchronous conversion operation.
276  * @note The buffer is organized as a matrix of M*N elements where M is the
277  * channels number configured into the conversion group and N is the
278  * buffer depth. The samples are sequentially written into the buffer
279  * with no gaps.
280  *
281  * @param[in] dacp pointer to the @p DACDriver object
282  * @param[in] grpp pointer to a @p DACConversionGroup object
283  * @param[out] samples pointer to the samples buffer
284  * @param[in] depth buffer depth (matrix rows number). The buffer depth
285  * must be one or an even number.
286  * @return The operation result.
287  * @retval MSG_OK Conversion finished.
288  * @retval MSG_RESET The conversion has been stopped using
289  * @p acdStopConversion() or @p acdStopConversionI(),
290  * the result buffer may contain incorrect data.
291  * @retval MSG_TIMEOUT The conversion has been stopped because an hardware
292  * error.
293  *
294  * @api
295  */
297  const DACConversionGroup *grpp,
298  dacsample_t *samples,
299  size_t depth) {
300  msg_t msg;
301 
302  osalSysLock();
303 
304  dacStartConversionI(dacp, grpp, samples, depth);
305  msg = osalThreadSuspendS(&dacp->thread);
306 
307  osalSysUnlock();
308  return msg;
309 }
310 #endif /* DAC_USE_WAIT == TRUE */
311 
312 #if (DAC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
313 /**
314  * @brief Gains exclusive access to the DAC bus.
315  * @details This function tries to gain ownership to the DAC bus, if the bus
316  * is already being used then the invoking thread is queued.
317  * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
318  * must be enabled.
319  *
320  * @param[in] dacp pointer to the @p DACDriver object
321  *
322  * @api
323  */
325 
326  osalDbgCheck(dacp != NULL);
327 
328  osalMutexLock(&dacp->mutex);
329 }
330 
331 /**
332  * @brief Releases exclusive access to the DAC bus.
333  * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
334  * must be enabled.
335  *
336  * @param[in] dacp pointer to the @p DACDriver object
337  *
338  * @api
339  */
341 
342  osalDbgCheck(dacp != NULL);
343 
344  osalMutexUnlock(&dacp->mutex);
345 }
346 #endif /* DAC_USE_MUTUAL_EXCLUSION == TRUE */
347 
348 #endif /* HAL_USE_DAC == TRUE */
349 
350 /** @} */
static void osalMutexObjectInit(mutex_t *mp)
Initializes s mutex_t object.
Definition: osal.h:681
void dacStartConversion(DACDriver *dacp, const DACConversionGroup *grpp, dacsample_t *samples, size_t depth)
Starts a DAC conversion.
Definition: hal_dac.c:167
#define _dac_reset_s(dacp)
Resumes a thread waiting for a conversion completion.
Definition: hal_dac.h:120
msg_t osalThreadSuspendS(thread_reference_t *trp)
Sends the current thread sleeping and sets a reference variable.
Definition: osal.c:185
msg_t dacConvert(DACDriver *dacp, const DACConversionGroup *grpp, dacsample_t *samples, size_t depth)
Performs a DAC conversion.
Definition: hal_dac.c:296
Driver configuration structure.
Definition: hal_dac_lld.h:131
void dacInit(void)
DAC Driver initialization.
Definition: hal_dac.c:56
uint32_t dacchannel_t
Type of a DAC channel index.
Definition: hal_dac_lld.h:68
dacsample_t * samples
Samples buffer pointer.
Definition: hal_dac_lld.h:151
HAL subsystem header.
thread_reference_t thread
Waiting thread.
Definition: hal_dac_lld.h:164
#define osalDbgCheckClassI()
I-Class state check.
Definition: osal.h:292
void dacObjectInit(DACDriver *dacp)
Initializes the standard part of a DACDriver structure.
Definition: hal_dac.c:68
void osalMutexLock(mutex_t *mp)
Locks the specified mutex.
Definition: osal.c:384
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition: osal.h:540
void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp, dacsample_t *samples, size_t depth)
Starts a DAC conversion.
Definition: hal_dac.c:195
void dac_lld_start(DACDriver *dacp)
Configures and activates the DAC peripheral.
Definition: hal_dac_lld.c:77
int32_t msg_t
Type of a message.
Definition: osal.h:160
void dacAcquireBus(DACDriver *dacp)
Gains exclusive access to the DAC bus.
Definition: hal_dac.c:324
void dacReleaseBus(DACDriver *dacp)
Releases exclusive access to the DAC bus.
Definition: hal_dac.c:340
void dac_lld_stop(DACDriver *dacp)
Deactivates the DAC peripheral.
Definition: hal_dac_lld.c:98
Structure representing a DAC driver.
Definition: hal_dac_lld.h:139
void dac_lld_init(void)
Low level DAC driver initialization.
Definition: hal_dac_lld.c:63
dacstate_t state
Driver state.
Definition: hal_dac_lld.h:143
#define osalDbgCheck(c)
Function parameters check.
Definition: osal.h:278
#define DAC_MAX_CHANNELS
Maximum number of DAC channels per unit.
Definition: hal_dac_lld.h:37
mutex_t mutex
Mutex protecting the bus.
Definition: hal_dac_lld.h:170
DAC Conversion group structure.
Definition: hal_dac_lld.h:112
void dac_lld_put_channel(DACDriver *dacp, dacchannel_t channel, dacsample_t sample)
Outputs a value directly on a DAC channel.
Definition: hal_dac_lld.c:120
void dacStop(DACDriver *dacp)
Deactivates the DAC peripheral.
Definition: hal_dac.c:118
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition: osal.h:530
uint16_t depth
Samples buffer size.
Definition: hal_dac_lld.h:155
void dac_lld_start_conversion(DACDriver *dacp)
Starts a DAC conversion.
Definition: hal_dac_lld.c:145
void dacPutChannelX(DACDriver *dacp, dacchannel_t channel, dacsample_t sample)
Outputs a value directly on a DAC channel.
Definition: hal_dac.c:143
#define osalDbgAssert(c, remark)
Condition assertion.
Definition: osal.h:258
void dacStopConversion(DACDriver *dacp)
Stops an ongoing conversion.
Definition: hal_dac.c:225
void osalMutexUnlock(mutex_t *mp)
Unlocks the specified mutex.
Definition: osal.c:404
void dacStopConversionI(DACDriver *dacp)
Stops an ongoing conversion.
Definition: hal_dac.c:255
void dacStart(DACDriver *dacp, const DACConfig *config)
Configures and activates the DAC peripheral.
Definition: hal_dac.c:93
uint16_t dacsample_t
Type representing a DAC sample.
Definition: hal_dac_lld.h:78
#define _dac_reset_i(dacp)
Resumes a thread waiting for a conversion completion.
Definition: hal_dac.h:111
void dac_lld_stop_conversion(DACDriver *dacp)
Stops an ongoing conversion.
Definition: hal_dac_lld.c:160
const DACConversionGroup * grpp
Conversion group.
Definition: hal_dac_lld.h:147
const DACConfig * config
Current configuration data.
Definition: hal_dac_lld.h:159