1 /**
2  * @file xmc_dac.c
3  * @date 2015-06-19
4  *
5  * @cond
6  **********************************************************************************
7  * XMClib v2.1.24 - XMC Peripheral Driver Library
8  *
9  * Copyright (c) 2015-2019, Infineon Technologies AG
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification,are permitted provided that the following conditions are met:
14  *
15  *   Redistributions of source code must retain the above copyright notice,
16  *   this list of conditions and the following disclaimer.
17  *
18  *   Redistributions in binary form must reproduce the above copyright notice,
19  *   this list of conditions and the following disclaimer in the documentation
20  *   and/or other materials provided with the distribution.
21  *
22  *   Neither the name of the copyright holders nor the names of its contributors
23  *   may be used to endorse or promote products derived from this software without
24  *   specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30  * LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * To improve the quality of the software, users are encouraged to share
39  * modifications, enhancements or bug fixes with Infineon Technologies AG
40  * dave@infineon.com).
41  **********************************************************************************
42  *
43  * Change History
44  * --------------
45  *
46  * 2015-02-18:
47  *     - Initial version
48  *
49  * 2015-06-19:
50  *     - Removed GetDriverVersion API
51  * @endcond
52  *
53  */
54 
55 /*******************************************************************************
56  * HEADER FILES
57  *******************************************************************************/
58 
59 #include <xmc_dac.h>
60 #include <xmc_scu.h>
61 
62 /* DAC peripheral is not available on XMC1X devices. */
63 #if defined(DAC)
64 
65 /*******************************************************************************
66  * MACROS
67  *******************************************************************************/
68 
69 #define XMC_DAC_MIN_FREQ_DIVIDER (16U)
70 #define XMC_DAC_MAX_FREQ_DIVIDER (1048576U)
71 #define XMC_DAC_DAC0PATL_PAT_BITSIZE (5U)
72 
73 /*******************************************************************************
74  * API IMPLEMENTATION
75  *******************************************************************************/
76 
77 /* API to enable the DAC module */
XMC_DAC_Enable(XMC_DAC_t * const dac)78 void XMC_DAC_Enable(XMC_DAC_t *const dac)
79 {
80   XMC_UNUSED_ARG(dac);
81 
82 #if defined(CLOCK_GATING_SUPPORTED)
83   XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_DAC);
84 #endif
85   XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_DAC);
86 }
87 
88 /* API to disable the DAC module */
XMC_DAC_Disable(XMC_DAC_t * const dac)89 void XMC_DAC_Disable(XMC_DAC_t *const dac)
90 {
91   XMC_UNUSED_ARG(dac);
92 
93   XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_DAC);
94 #if defined(CLOCK_GATING_SUPPORTED)
95   XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_DAC);
96 #endif
97 }
98 
99 /* API to check whether DAC is enabled */
XMC_DAC_IsEnabled(const XMC_DAC_t * const dac)100 bool XMC_DAC_IsEnabled(const XMC_DAC_t *const dac)
101 {
102   bool status;
103 
104   XMC_UNUSED_ARG(dac);
105 
106   status = XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_DAC);
107   if(status == true)
108   {
109     status = false;
110   }
111   else
112   {
113     status = true;
114   }
115   return (status);
116 }
117 
118 /* API to initialize DAC channel configuration */
XMC_DAC_CH_Init(XMC_DAC_t * const dac,const uint8_t channel,const XMC_DAC_CH_CONFIG_t * const config)119 void XMC_DAC_CH_Init(XMC_DAC_t *const dac, const uint8_t channel, const XMC_DAC_CH_CONFIG_t *const config)
120 {
121   XMC_DAC_Enable(dac);
122 
123   dac->DACCFG[channel].low = config->cfg0;
124   dac->DACCFG[channel].high = config->cfg1;
125   if (channel < XMC_DAC_NO_CHANNELS)
126   {
127     XMC_DAC_CH_EnableOutput(dac, channel);
128   }
129 }
130 
131 /* API to set the waveform frequency except in Ramp and Pattern generation mode. */
XMC_DAC_CH_SetFrequency(XMC_DAC_t * const dac,const uint8_t channel,const uint32_t frequency)132 XMC_DAC_CH_STATUS_t XMC_DAC_CH_SetFrequency(XMC_DAC_t *const dac,
133                                             const uint8_t channel,
134                                             const uint32_t frequency)
135 {
136   uint32_t divider;
137   XMC_DAC_CH_STATUS_t status;
138 
139   XMC_ASSERT("XMC_DAC_CH_SetFrequency: frequency must be greater than zero", frequency > 0U);
140 
141   divider = XMC_SCU_CLOCK_GetPeripheralClockFrequency() / frequency;
142 
143   if (divider < XMC_DAC_MIN_FREQ_DIVIDER)
144   {
145     status = XMC_DAC_CH_STATUS_ERROR_FREQ2HIGH;
146   }
147   else if (divider >= XMC_DAC_MAX_FREQ_DIVIDER)
148   {
149     status = XMC_DAC_CH_STATUS_ERROR_FREQ2LOW;
150   }
151   else {
152     dac->DACCFG[channel].low = (dac->DACCFG[channel].low & (uint32_t)(~DAC_DAC0CFG0_FREQ_Msk)) |
153                                (divider << DAC_DAC0CFG0_FREQ_Pos);
154     status = XMC_DAC_CH_STATUS_OK;
155   }
156 
157   return status;
158 }
159 
160 /* API to set the waveform frequency in Ramp Mode. */
XMC_DAC_CH_SetRampFrequency(XMC_DAC_t * const dac,const uint8_t channel,const uint32_t frequency)161 XMC_DAC_CH_STATUS_t XMC_DAC_CH_SetRampFrequency(XMC_DAC_t *const dac,
162                                                 const uint8_t channel,
163                                                 const uint32_t frequency)
164 {
165   uint32_t stop;
166   uint32_t start;
167 
168   start = dac->DACDATA[channel];
169   stop = (dac->DAC01DATA >> (channel * DAC_DAC01DATA_DATA1_Pos)) & (uint32_t)DAC_DAC01DATA_DATA0_Msk;
170 
171   return XMC_DAC_CH_SetFrequency(dac, channel, frequency * ((stop - start) + 1U));
172 }
173 
174 /* API to start the operation in Single Value Mode. */
XMC_DAC_CH_StartSingleValueMode(XMC_DAC_t * const dac,const uint8_t channel)175 XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartSingleValueMode(XMC_DAC_t *const dac, const uint8_t channel)
176 {
177   XMC_ASSERT("XMC_DAC_CH_StartSingleValueMode: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
178   XMC_ASSERT("XMC_DAC_CH_StartSingleValueMode: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
179   XMC_ASSERT("XMC_DAC_CH_StartSingleValueMode: dac module not enabled\n", XMC_DAC_IsEnabled(dac));
180 
181   XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_SINGLE);
182 
183   return XMC_DAC_CH_STATUS_OK;
184 }
185 
186 /* API to start the operation in Data Mode. */
XMC_DAC_CH_StartDataMode(XMC_DAC_t * const dac,const uint8_t channel,const XMC_DAC_CH_TRIGGER_t trigger,const uint32_t frequency)187 XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartDataMode(XMC_DAC_t *const dac,
188                                              const uint8_t channel,
189                                              const XMC_DAC_CH_TRIGGER_t trigger,
190                                              const uint32_t frequency)
191 {
192   XMC_DAC_CH_STATUS_t status = XMC_DAC_CH_STATUS_OK;
193 
194   XMC_ASSERT("XMC_DAC_CH_StartDataMode: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
195   XMC_ASSERT("XMC_DAC_CH_StartDataMode: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
196   XMC_ASSERT("XMC_DAC_CH_StartDataMode: dac module not enabled\n", XMC_DAC_IsEnabled(dac));
197 
198   XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_IDLE);
199 
200   if (trigger == XMC_DAC_CH_TRIGGER_INTERNAL)
201   {
202     status = XMC_DAC_CH_SetFrequency(dac, channel, frequency);
203   }
204 
205   if (status == XMC_DAC_CH_STATUS_OK)
206   {
207     XMC_DAC_CH_SetTrigger(dac, channel, trigger);
208     XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_DATA);
209   }
210 
211   return status;
212 }
213 
214 /* API to start the operation in Ramp Mode. */
XMC_DAC_CH_StartRampMode(XMC_DAC_t * const dac,const uint8_t channel,const uint16_t start,const uint16_t stop,const XMC_DAC_CH_TRIGGER_t trigger,const uint32_t frequency)215 XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartRampMode(XMC_DAC_t *const dac,
216                                              const uint8_t channel,
217                                              const uint16_t start,
218                                              const uint16_t stop,
219                                              const XMC_DAC_CH_TRIGGER_t trigger,
220                                              const uint32_t frequency)
221 {
222   XMC_DAC_CH_STATUS_t status = XMC_DAC_CH_STATUS_OK;
223 
224   XMC_ASSERT("XMC_DAC_CH_StartRampMode: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
225   XMC_ASSERT("XMC_DAC_CH_StartRampMode: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
226   XMC_ASSERT("XMC_DAC_CH_StartRampMode: dac module not enabled\n", XMC_DAC_IsEnabled(dac));
227 
228   XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_IDLE);
229 
230   XMC_DAC_CH_SetRampStart(dac, channel, start);
231   XMC_DAC_CH_SetRampStop(dac, channel, stop);
232   XMC_DAC_CH_SetTrigger(dac, channel, trigger);
233 
234   if (trigger == XMC_DAC_CH_TRIGGER_INTERNAL)
235   {
236     status = XMC_DAC_CH_SetRampFrequency(dac, channel, frequency);
237   }
238 
239   if (status == XMC_DAC_CH_STATUS_OK)
240   {
241     XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_RAMP);
242   }
243 
244   return status;
245 }
246 
247 /* API to start the operation in Pattern Mode. */
XMC_DAC_CH_StartPatternMode(XMC_DAC_t * const dac,const uint8_t channel,const uint8_t * const pattern,const XMC_DAC_CH_PATTERN_SIGN_OUTPUT_t sign_output,const XMC_DAC_CH_TRIGGER_t trigger,const uint32_t frequency)248 XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartPatternMode(XMC_DAC_t *const dac,
249                                                 const uint8_t channel,
250                                                 const uint8_t *const pattern,
251                                                 const XMC_DAC_CH_PATTERN_SIGN_OUTPUT_t sign_output,
252                                                 const XMC_DAC_CH_TRIGGER_t trigger,
253                                                 const uint32_t frequency)
254 {
255   XMC_DAC_CH_STATUS_t status = XMC_DAC_CH_STATUS_OK;
256 
257   XMC_ASSERT("XMC_DAC_CH_StartPatternMode: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
258   XMC_ASSERT("XMC_DAC_CH_StartPatternMode: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
259   XMC_ASSERT("XMC_DAC_CH_StartPatternMode: dac module not enabled\n", XMC_DAC_IsEnabled(dac));
260 
261   XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_IDLE);
262 
263   if (trigger == XMC_DAC_CH_TRIGGER_INTERNAL)
264   {
265     status = XMC_DAC_CH_SetFrequency(dac, channel, frequency * XMC_DAC_SAMPLES_PER_PERIOD);
266   }
267 
268   if (status == XMC_DAC_CH_STATUS_OK)
269   {
270     XMC_DAC_CH_SetPattern(dac, channel, pattern);
271     if (XMC_DAC_CH_PATTERN_SIGN_OUTPUT_ENABLED == sign_output)
272     {
273       XMC_DAC_CH_EnablePatternSignOutput(dac, channel);
274     }
275     else
276     {
277       XMC_DAC_CH_DisablePatternSignOutput(dac, channel);
278     }
279     XMC_DAC_CH_SetTrigger(dac, channel, trigger);
280     XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_PATTERN);
281   }
282 
283   return status;
284 }
285 
286 /* API to start the operation in Noise Mode. */
XMC_DAC_CH_StartNoiseMode(XMC_DAC_t * const dac,const uint8_t channel,const XMC_DAC_CH_TRIGGER_t trigger,const uint32_t frequency)287 XMC_DAC_CH_STATUS_t XMC_DAC_CH_StartNoiseMode(XMC_DAC_t *const dac,
288                                               const uint8_t channel,
289                                               const XMC_DAC_CH_TRIGGER_t trigger,
290                                               const uint32_t frequency)
291 {
292   XMC_DAC_CH_STATUS_t status = XMC_DAC_CH_STATUS_OK;
293 
294   XMC_ASSERT("XMC_DAC_CH_StartNoiseMode: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
295   XMC_ASSERT("XMC_DAC_CH_StartNoiseMode: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
296   XMC_ASSERT("XMC_DAC_CH_StartNoiseMode: dac module not enabled\n", XMC_DAC_IsEnabled(dac));
297 
298   XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_IDLE);
299 
300   if (trigger == XMC_DAC_CH_TRIGGER_INTERNAL)
301   {
302     status = XMC_DAC_CH_SetFrequency(dac, channel, frequency);
303   }
304 
305   if (status == XMC_DAC_CH_STATUS_OK)
306   {
307     XMC_DAC_CH_SetTrigger(dac, channel, trigger);
308     XMC_DAC_CH_SetMode(dac, channel, XMC_DAC_CH_MODE_NOISE);
309   }
310 
311   return status;
312 }
313 
314 /* API to write the pattern data table. */
XMC_DAC_CH_SetPattern(XMC_DAC_t * const dac,uint8_t channel,const uint8_t * const data)315 void XMC_DAC_CH_SetPattern(XMC_DAC_t *const dac, uint8_t channel, const uint8_t *const data)
316 {
317   uint32_t index;
318   uint32_t temp;
319 
320   XMC_ASSERT("XMC_DAC_CH_SetPattern: dac parameter not valid\n", XMC_DAC_IS_DAC_VALID(dac));
321   XMC_ASSERT("XMC_DAC_CH_SetPattern: channel parameter not valid\n", XMC_DAC_IS_CHANNEL_VALID(channel));
322   XMC_ASSERT("XMC_DAC_CH_SetPattern: dac module not enabled\n", XMC_DAC_IsEnabled(dac));
323 
324   temp = data[0U];
325   for(index = 1U; index < 6U; ++index)
326   {
327     temp |= (uint32_t)data[index] << (index * XMC_DAC_DAC0PATL_PAT_BITSIZE);
328   }
329   dac->DACPAT[channel].low = temp;
330 
331   temp = data[6U];
332   for(index = 1U; index < 6U; ++index)
333   {
334     temp |= (uint32_t)data[index + 6U] << (index * XMC_DAC_DAC0PATL_PAT_BITSIZE);
335   }
336   dac->DACPAT[channel].high = temp;
337 }
338 
339 #endif /* defined(DAC) */
340