1 /***************************************************************************//**
2  * @file
3  * @brief Digital to Analog Converter (DAC) peripheral API
4  * @author Energy Micro AS
5  * @version 3.0.0
6  *******************************************************************************
7  * @section License
8  * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
9  *******************************************************************************
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute it
13  * freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must not
16  *    claim that you wrote the original software.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  *    misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  *
21  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
22  * obligation to support this Software. Energy Micro AS is providing the
23  * Software "AS IS", with no express or implied warranties of any kind,
24  * including, but not limited to, any implied warranties of merchantability
25  * or fitness for any particular purpose or warranties against infringement
26  * of any proprietary rights of a third party.
27  *
28  * Energy Micro AS will not be liable for any consequential, incidental, or
29  * special damages, or any other relief, or for any claim by any third party,
30  * arising from your use of this Software.
31  *
32  ******************************************************************************/
33 #ifndef __EM_DAC_H
34 #define __EM_DAC_H
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 #include <stdbool.h>
41 #include "em_part.h"
42 
43 /***************************************************************************//**
44  * @addtogroup EM_Library
45  * @{
46  ******************************************************************************/
47 
48 /***************************************************************************//**
49  * @addtogroup DAC
50  * @{
51  ******************************************************************************/
52 
53 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
54 
55 /** Validation of DAC register block pointer reference for assert statements. */
56 #define DAC_REF_VALID(ref)    ((ref) == DAC0)
57 
58 /** @endcond */
59 
60 /*******************************************************************************
61  ********************************   ENUMS   ************************************
62  ******************************************************************************/
63 
64 /** Conversion mode. */
65 typedef enum
66 {
67   dacConvModeContinuous = _DAC_CTRL_CONVMODE_CONTINUOUS, /**< Continuous mode. */
68   dacConvModeSampleHold = _DAC_CTRL_CONVMODE_SAMPLEHOLD, /**< Sample/hold mode. */
69   dacConvModeSampleOff  = _DAC_CTRL_CONVMODE_SAMPLEOFF   /**< Sample/shut off mode. */
70 } DAC_ConvMode_TypeDef;
71 
72 /** Output mode. */
73 typedef enum
74 {
75   dacOutputDisable = _DAC_CTRL_OUTMODE_DISABLE, /**< Output to pin and ADC disabled. */
76   dacOutputPin     = _DAC_CTRL_OUTMODE_PIN,     /**< Output to pin only. */
77   dacOutputADC     = _DAC_CTRL_OUTMODE_ADC,     /**< Output to ADC only */
78   dacOutputPinADC  = _DAC_CTRL_OUTMODE_PINADC   /**< Output to pin and ADC. */
79 } DAC_Output_TypeDef;
80 
81 
82 /** Peripheral Reflex System signal used to trigger single sample. */
83 typedef enum
84 {
85   dacPRSSELCh0 = _DAC_CH0CTRL_PRSSEL_PRSCH0, /**< PRS channel 0. */
86   dacPRSSELCh1 = _DAC_CH0CTRL_PRSSEL_PRSCH1, /**< PRS channel 1. */
87   dacPRSSELCh2 = _DAC_CH0CTRL_PRSSEL_PRSCH2, /**< PRS channel 2. */
88   dacPRSSELCh3 = _DAC_CH0CTRL_PRSSEL_PRSCH3, /**< PRS channel 3. */
89   dacPRSSELCh4 = _DAC_CH0CTRL_PRSSEL_PRSCH4, /**< PRS channel 4. */
90   dacPRSSELCh5 = _DAC_CH0CTRL_PRSSEL_PRSCH5, /**< PRS channel 5. */
91   dacPRSSELCh6 = _DAC_CH0CTRL_PRSSEL_PRSCH6, /**< PRS channel 6. */
92   dacPRSSELCh7 = _DAC_CH0CTRL_PRSSEL_PRSCH7  /**< PRS channel 7. */
93 } DAC_PRSSEL_TypeDef;
94 
95 
96 /** Reference voltage for DAC. */
97 typedef enum
98 {
99   dacRef1V25 = _DAC_CTRL_REFSEL_1V25, /**< Internal 1.25V bandgap reference. */
100   dacRef2V5  = _DAC_CTRL_REFSEL_2V5,  /**< Internal 2.5V bandgap reference. */
101   dacRefVDD  = _DAC_CTRL_REFSEL_VDD   /**< VDD reference. */
102 } DAC_Ref_TypeDef;
103 
104 
105 /** Refresh interval. */
106 typedef enum
107 {
108   dacRefresh8  = _DAC_CTRL_REFRSEL_8CYCLES,  /**< Refresh every 8 prescaled cycles. */
109   dacRefresh16 = _DAC_CTRL_REFRSEL_16CYCLES, /**< Refresh every 16 prescaled cycles. */
110   dacRefresh32 = _DAC_CTRL_REFRSEL_32CYCLES, /**< Refresh every 32 prescaled cycles. */
111   dacRefresh64 = _DAC_CTRL_REFRSEL_64CYCLES  /**< Refresh every 64 prescaled cycles. */
112 } DAC_Refresh_TypeDef;
113 
114 
115 /*******************************************************************************
116  *******************************   STRUCTS   ***********************************
117  ******************************************************************************/
118 
119 /** DAC init structure, common for both channels. */
120 typedef struct
121 {
122   /** Refresh interval. Only used if REFREN bit set for a DAC channel. */
123   DAC_Refresh_TypeDef  refresh;
124 
125   /** Reference voltage to use. */
126   DAC_Ref_TypeDef      reference;
127 
128   /** Output mode */
129   DAC_Output_TypeDef   outMode;
130 
131   /** Conversion mode. */
132   DAC_ConvMode_TypeDef convMode;
133 
134   /**
135    * Prescaler used to get DAC clock. Derived as follows:
136    * DACclk=HFPERclk/(2^prescale). The DAC clock should be <= 1MHz.
137    */
138   uint8_t              prescale;
139 
140   /** Enable/disable use of low pass filter on output. */
141   bool                 lpEnable;
142 
143   /** Enable/disable reset of prescaler on ch0 start. */
144   bool                 ch0ResetPre;
145 
146   /** Enable/disable output enable control by CH1 PRS signal. */
147   bool                 outEnablePRS;
148 
149   /** Enable/disable sine mode. */
150   bool                 sineEnable;
151 
152   /** Select if single ended or differential mode. */
153   bool                 diff;
154 } DAC_Init_TypeDef;
155 
156 /** Default config for DAC init structure. */
157 #define DAC_INIT_DEFAULT                                                 \
158   { dacRefresh8,              /* Refresh every 8 prescaled cycles. */    \
159     dacRef1V25,               /* 1.25V internal reference. */            \
160     dacOutputPin,             /* Output to pin only. */                  \
161     dacConvModeContinuous,    /* Continuous mode. */                     \
162     0,                        /* No prescaling. */                       \
163     false,                    /* Do not enable low pass filter. */       \
164     false,                    /* Do not reset prescaler on ch0 start. */ \
165     false,                    /* DAC output enable always on. */         \
166     false,                    /* Disable sine mode. */                   \
167     false                     /* Single ended mode. */                   \
168   }
169 
170 
171 /** DAC channel init structure. */
172 typedef struct
173 {
174   /** Enable channel. */
175   bool               enable;
176 
177   /**
178    * Peripheral reflex system trigger enable. If false, channel is triggered
179    * by writing to CHnDATA.
180    */
181   bool               prsEnable;
182 
183   /**
184    * Enable/disable automatic refresh of channel. Refresh interval must be
185    * defined in common control init, please see DAC_Init().
186    */
187   bool               refreshEnable;
188 
189   /**
190    * Peripheral reflex system trigger selection. Only applicable if @p prsEnable
191    * is enabled.
192    */
193   DAC_PRSSEL_TypeDef prsSel;
194 } DAC_InitChannel_TypeDef;
195 
196 /** Default config for DAC channel init structure. */
197 #define DAC_INITCHANNEL_DEFAULT                                           \
198   { false,              /* Leave channel disabled when init done. */      \
199     false,              /* Disable PRS triggering. */                     \
200     false,              /* Channel not refreshed automatically. */        \
201     dacPRSSELCh0        /* Select PRS ch0 (if PRS triggering enabled). */ \
202   }
203 
204 
205 /*******************************************************************************
206  *****************************   PROTOTYPES   **********************************
207  ******************************************************************************/
208 
209 void DAC_Enable(DAC_TypeDef *dac, unsigned int ch, bool enable);
210 void DAC_Init(DAC_TypeDef *dac, const DAC_Init_TypeDef *init);
211 void DAC_InitChannel(DAC_TypeDef *dac,
212                      const DAC_InitChannel_TypeDef *init,
213                      unsigned int ch);
214 
215 /***************************************************************************//**
216  * @brief
217  *   Clear one or more pending DAC interrupts.
218  *
219  * @param[in] dac
220  *   Pointer to DAC peripheral register block.
221  *
222  * @param[in] flags
223  *   Pending DAC interrupt source to clear. Use a bitwise logic OR combination of
224  *   valid interrupt flags for the DAC module (DAC_IF_nnn).
225  ******************************************************************************/
DAC_IntClear(DAC_TypeDef * dac,uint32_t flags)226 __STATIC_INLINE void DAC_IntClear(DAC_TypeDef *dac, uint32_t flags)
227 {
228   dac->IFC = flags;
229 }
230 
231 
232 /***************************************************************************//**
233  * @brief
234  *   Disable one or more DAC interrupts.
235  *
236  * @param[in] dac
237  *   Pointer to DAC peripheral register block.
238  *
239  * @param[in] flags
240  *   DAC interrupt sources to disable. Use a bitwise logic OR combination of
241  *   valid interrupt flags for the DAC module (DAC_IF_nnn).
242  ******************************************************************************/
DAC_IntDisable(DAC_TypeDef * dac,uint32_t flags)243 __STATIC_INLINE void DAC_IntDisable(DAC_TypeDef *dac, uint32_t flags)
244 {
245   dac->IEN &= ~(flags);
246 }
247 
248 
249 /***************************************************************************//**
250  * @brief
251  *   Enable one or more DAC interrupts.
252  *
253  * @note
254  *   Depending on the use, a pending interrupt may already be set prior to
255  *   enabling the interrupt. Consider using DAC_IntClear() prior to enabling
256  *   if such a pending interrupt should be ignored.
257  *
258  * @param[in] dac
259  *   Pointer to DAC peripheral register block.
260  *
261  * @param[in] flags
262  *   DAC interrupt sources to enable. Use a bitwise logic OR combination of
263  *   valid interrupt flags for the DAC module (DAC_IF_nnn).
264  ******************************************************************************/
DAC_IntEnable(DAC_TypeDef * dac,uint32_t flags)265 __STATIC_INLINE void DAC_IntEnable(DAC_TypeDef *dac, uint32_t flags)
266 {
267   dac->IEN |= flags;
268 }
269 
270 
271 /***************************************************************************//**
272  * @brief
273  *   Get pending DAC interrupt flags.
274  *
275  * @note
276  *   The event bits are not cleared by the use of this function.
277  *
278  * @param[in] dac
279  *   Pointer to DAC peripheral register block.
280  *
281  * @return
282  *   DAC interrupt sources pending. A bitwise logic OR combination of valid
283  *   interrupt flags for the DAC module (DAC_IF_nnn).
284  ******************************************************************************/
DAC_IntGet(DAC_TypeDef * dac)285 __STATIC_INLINE uint32_t DAC_IntGet(DAC_TypeDef *dac)
286 {
287   return(dac->IF);
288 }
289 
290 
291 /***************************************************************************//**
292  * @brief
293  *   Set one or more pending DAC interrupts from SW.
294  *
295  * @param[in] dac
296  *   Pointer to DAC peripheral register block.
297  *
298  * @param[in] flags
299  *   DAC interrupt sources to set to pending. Use a bitwise logic OR combination
300  *   of valid interrupt flags for the DAC module (DAC_IF_nnn).
301  ******************************************************************************/
DAC_IntSet(DAC_TypeDef * dac,uint32_t flags)302 __STATIC_INLINE void DAC_IntSet(DAC_TypeDef *dac, uint32_t flags)
303 {
304   dac->IFS = flags;
305 }
306 
307 uint8_t DAC_PrescaleCalc(uint32_t dacFreq, uint32_t hfperFreq);
308 void DAC_Reset(DAC_TypeDef *dac);
309 
310 /** @} (end addtogroup DAC) */
311 /** @} (end addtogroup EM_Library) */
312 
313 #ifdef __cplusplus
314 }
315 #endif
316 
317 #endif /* __EM_DAC_H */
318