iLLD_TC27xD  1.0
IfxCcu6_PwmHl.c
Go to the documentation of this file.
1 /**
2  * \file IfxCcu6_PwmHl.c
3  * \brief CCU6 PWMHL details
4  *
5  * \version iLLD_1_0_0_11_0
6  * \copyright Copyright (c) 2013 Infineon Technologies AG. All rights reserved.
7  *
8  *
9  * IMPORTANT NOTICE
10  *
11  *
12  * Infineon Technologies AG (Infineon) is supplying this file for use
13  * exclusively with Infineon's microcontroller products. This file can be freely
14  * distributed within development tools that are supporting such microcontroller
15  * products.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
18  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
20  * INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
21  * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
22  *
23  */
24 
25 /******************************************************************************/
26 /*----------------------------------Includes----------------------------------*/
27 /******************************************************************************/
28 
29 #include "IfxCcu6_PwmHl.h"
30 #include "_Utilities/Ifx_Assert.h"
31 #include "stddef.h"
32 #include "string.h"
33 
34 /** \addtogroup IfxLld_Ccu6_PwmHl_StdIf_Functions
35  * \{ */
36 /******************************************************************************/
37 /*------------------------Inline Function Prototypes--------------------------*/
38 /******************************************************************************/
39 
40 /** \brief Inverts the active state
41  * \param activeState Active state
42  * \return State
43  */
45 
46 /******************************************************************************/
47 /*-----------------------Private Function Prototypes--------------------------*/
48 /******************************************************************************/
49 
50 /** \brief Turn-off the complementary PWM generation mode.
51  *
52  * \note The changes are not applied until Timer->applyUpdate() is called.
53  * \note This function will set the ON time to ZERO, overriding previous call to
54  * IfxCcu6_PwmHl_setOnTime().
55  * \note This function will disable PWM in all channels, overriding previous call to
56  * IfxCcu6_PwmHl_setupChannels().
57  * \param driver CCU6 PWM driver
58  * \return None
59  */
60 static void IfxCcu6_PwmHl_disable(IfxCcu6_PwmHl *driver);
61 
62 /** \brief Turn-on the complementary PWM generation mode.
63  *
64  * \note The changes are not applied until Timer->applyUpdate() is called.
65  * \note This function will disable PWM in all channels, overriding previous call to
66  * IfxCcu6_PwmHl_setupChannels().
67  * \param driver CCU6 PWM driver
68  * \return None
69  */
70 static void IfxCcu6_PwmHl_enable(IfxCcu6_PwmHl *driver);
71 
72 /** \brief Sets up the output pins
73  * \param module Pointer to register base
74  * \param config CCU6 : PWM HL configuration
75  * \return None
76  */
77 static void IfxCcu6_PwmHl_setOutputPins(Ifx_CCU6 *module, const IfxCcu6_PwmHl_Config *config);
78 
79 /** \brief Updates the x output duty cycle in center aligned and center aligned inverted modes
80  * \param driver CCU6 PWM driver
81  * \param tOn T on
82  * \return None
83  */
84 static void IfxCcu6_PwmHl_updateCenterAligned(IfxCcu6_PwmHl *driver, Ifx_TimerValue *tOn);
85 
86 /** \brief Updates the x output duty cycle in edge aligned modes (left and right aligned)
87  * \param driver CCU6 PWM driver
88  * \param tOn T on
89  * \return None
90  */
91 static void IfxCcu6_PwmHl_updateEdgeAligned(IfxCcu6_PwmHl *driver, Ifx_TimerValue *tOn);
92 
93 /** \brief Set the outputs to inactive
94  * \param driver CCU6 PWM driver
95  * \param tOn T on
96  * \return None
97  */
98 static void IfxCcu6_PwmHl_updateOff(IfxCcu6_PwmHl *driver, Ifx_TimerValue *tOn);
99 
100 /** \} */
101 
102 /******************************************************************************/
103 /*------------------------Private Variables/Constants-------------------------*/
104 /******************************************************************************/
105 
106 static const IfxCcu6_PwmHl_Mode IfxCcu6_PwmHl_modes[Ifx_Pwm_Mode_count] = {
107  {FALSE, IfxCcu6_PwmHl_updateCenterAligned}, // Ifx_Pwm_Mode_centerAligned
108  {TRUE, IfxCcu6_PwmHl_updateCenterAligned}, // Ifx_Pwm_Mode_centerAlignedInverted
109  {FALSE, IfxCcu6_PwmHl_updateEdgeAligned }, // Ifx_Pwm_Mode_leftAligned
110  {TRUE, IfxCcu6_PwmHl_updateEdgeAligned }, // Ifx_Pwm_Mode_rightAligned
111  {FALSE, IfxCcu6_PwmHl_updateOff } // Ifx_Pwm_Mode_off
112 };
113 
114 /******************************************************************************/
115 /*---------------------Inline Function Implementations------------------------*/
116 /******************************************************************************/
117 
119 {
121 }
122 
123 
124 /******************************************************************************/
125 /*-------------------------Function Implementations---------------------------*/
126 /******************************************************************************/
127 
128 static void IfxCcu6_PwmHl_disable(IfxCcu6_PwmHl *driver)
129 {
130  IfxCcu6_TimerWithTrigger *timer = driver->timer;
131  Ifx_CCU6 *module = timer->ccu6;
132  Ifx_CCU6_CMPSTAT cmpstat;
133 
134  Ifx_TimerValue tOn[3] = {0, 0, 0};
135  IfxCcu6_PwmHl_setOnTime(driver, tOn); /* FIXME move to IfxCcu6_PwmHl_updateOff() */
136 
137  /** - All TOP and BOTTOM channel (COUTx) states equals CC6xST */
138  cmpstat.U = 0;
139  //cmpstat.B.T13IM = 0;
140  //cmpstat.B.COUT63PS = 0;
141  //cmpstat.B.CC60PS = 0;
142  //cmpstat.B.CC61PS = 0;
143  //cmpstat.B.CC62PS = 0;
144  //cmpstat.B.COUT60PS = 0;
145  //cmpstat.B.COUT61PS = 0;
146  //cmpstat.B.COUT62PS = 0;
147  module->CMPSTAT.U = cmpstat.U;
148 
149  {
150  /* set all into stuck-states */
151  //boolean active[6] = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};
152  boolean active[6] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
153  boolean stuckState[6] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
154  IfxCcu6_PwmHl_setupChannels(driver, active, stuckState);
155  }
156 }
157 
158 
159 static void IfxCcu6_PwmHl_enable(IfxCcu6_PwmHl *driver)
160 {
162  Ifx_CCU6 *module = timer->ccu6;
163  /** - All TOP and BOTTOM channel (COUTx) states equals CC6xST */
164  Ifx_CCU6_CMPSTAT cmpstat;
165  cmpstat.U = 0;
166  //cmpstat.B.T13IM = 0;
167  //cmpstat.B.COUT63PS = 0;
168  //cmpstat.B.CC60PS = 0;
169  //cmpstat.B.CC61PS = 0;
170  //cmpstat.B.CC62PS = 0;
171  cmpstat.B.COUT60PS = 1;
172  cmpstat.B.COUT61PS = 1;
173  cmpstat.B.COUT62PS = 1;
174  module->CMPSTAT.U = cmpstat.U;
175  {
176  /* set all into non stuck-states */
177  boolean active[6] = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};
178  boolean stuckState[6] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
179  IfxCcu6_PwmHl_setupChannels(driver, active, stuckState);
180  }
181 }
182 
183 
185 {
186  return IfxStdIf_Timer_tickToS(driver->timer->base.clockFreq, driver->base.deadtime);
187 }
188 
189 
191 {
192  return IfxStdIf_Timer_tickToS(driver->timer->base.clockFreq, driver->base.minPulse - driver->base.deadtime);
193 }
194 
195 
197 {
198  return driver->base.mode;
199 }
200 
201 
203 {
204  boolean result = TRUE;
205 
206  IfxCcu6_TimerWithTrigger *timer = config->timer;
207  Ifx_CCU6 *module = timer->ccu6;
208 
209  driver->base.mode = Ifx_Pwm_Mode_init;
210  driver->timer = timer;
211  driver->base.setMode = 0;
212  driver->base.inverted = FALSE;
213  driver->base.ccxActiveState = config->base.ccxActiveState;
214  driver->base.coutxActiveState = config->base.coutxActiveState;
215 
217 
218  IfxCcu6_PwmHl_setDeadtime(driver, config->base.deadtime);
219  IfxCcu6_PwmHl_setMinPulse(driver, config->base.minPulse);
220 
223 
224  unsigned int passiveState;
225  Ifx_CCU6_PSLR pslr;
226  Ifx_CCU6_MODCTR modctr;
227  Ifx_CCU6_MCMOUTS mcmouts;
228  Ifx_CCU6_MCMCTR mcmctr;
229 
230  /** - All T12 channels (0,1,2) are set in compare mode */
231 
235 
236  /** - Enable T12 modulation mode */
237  modctr.U = module->MODCTR.U;
238  modctr.B.MCMEN = 1;
239  modctr.B.T12MODEN = 0x3FU;
240  module->MODCTR.U = modctr.U;
241 
243 
245 
246  mcmctr.U = module->MCMCTR.U;
247  mcmctr.B.STE12D = FALSE;
248  mcmctr.B.STE12U = FALSE;
249  mcmctr.B.STE13U = FALSE;
250  module->MCMCTR.U = mcmctr.U;
251 
255 
256  /* Configure the passive state */
257  pslr.B.PSL = 0;
258  passiveState = (config->base.ccxActiveState == Ifx_ActiveState_high) ? 0 : 1;
259  pslr.B.PSL |= (passiveState << 0);
260  pslr.B.PSL |= (passiveState << 2);
261  pslr.B.PSL |= (passiveState << 4);
262 
263  passiveState = (config->base.coutxActiveState == Ifx_ActiveState_high) ? 0 : 1;
264  pslr.B.PSL |= (passiveState << 1);
265  pslr.B.PSL |= (passiveState << 3);
266  pslr.B.PSL |= (passiveState << 5);
267 
268  module->PSLR.B.PSL = pslr.B.PSL;
269 
271 
273  IfxCcu6_PwmHl_updateOff(driver, tOn); /* tOn do not need defined values */
274 
275  mcmouts.U = module->MCMOUTS.U;
276  mcmouts.B.MCMPS = 0x3F;
277  mcmouts.B.STRMCM = 1;
278  module->MCMOUTS.U = mcmouts.U;
279 
280  IfxCcu6_PwmHl_setOutputPins(module, config);
281 
282  //config->base.emergencyEnabled;
283 
284  /* Transfer the shadow registers */
286 
287  return result;
288 }
289 
290 
292 {
294  config->timer = NULL_PTR;
295  config->cc0 = NULL_PTR;
296  config->cc1 = NULL_PTR;
297  config->cc2 = NULL_PTR;
298  config->cout0 = NULL_PTR;
299  config->cout1 = NULL_PTR;
300  config->cout2 = NULL_PTR;
301 }
302 
303 
305 {
306  Ifx_TimerValue value = IfxStdIf_Timer_sToTick(driver->timer->base.clockFreq, deadtime);
307 
308  /* FIXME warn if dead time in out of range: > 1/2 period, ... */
309  driver->base.deadtime = __minu(__minu(value, driver->timer->base.period / 2), 255);
310 
312  return TRUE;
313 }
314 
315 
317 {
318  Ifx_TimerValue value = IfxStdIf_Timer_sToTick(driver->timer->base.clockFreq, minPulse);
319 
320  driver->base.minPulse = value + driver->base.deadtime;
321  driver->base.maxPulse = driver->timer->base.period - driver->base.minPulse;
322 
323  return TRUE;
324 }
325 
326 
328 {
329  boolean result = TRUE;
330  IfxCcu6_PwmHl_Base *base = &driver->base;
331 
332  if (base->mode != mode)
333  {
334  if ((mode >= Ifx_Pwm_Mode_count) || (IfxCcu6_PwmHl_modes[mode].update == NULL_PTR))
335  {
336  mode = Ifx_Pwm_Mode_off;
337  result = FALSE;
338  }
339 
340  base->mode = mode;
341  driver->update = IfxCcu6_PwmHl_modes[mode].update;
342 
343  if (base->mode == Ifx_Pwm_Mode_off)
344  {
345  IfxCcu6_PwmHl_disable(driver);
346  }
347  else
348  {
349  IfxCcu6_PwmHl_enable(driver);
350  }
351  }
352 
353  return result;
354 }
355 
356 
358 {
359  // Period = 12
360  // Ton = 2
361  // Center-aligned (the CCx equals CC6xST):
362  // T12PR = (Period/2)-1
363  // T12 = 0 1 2 3 4 5 6 5 4 3 2 1 0 1 2 3
364  // CC6xR = (Period - Ton) / 2 = 5
365  // CC6xST = 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0
366  // Right-aligned (the CCx equals CC6xST):
367  // T12PR = (Period-1)
368  // T12 = 0 1 2 3 4 5 6 7 8 9 10 11 0 1 2 3
369  // CC6xR = (Period - Ton) = 10
370  // CC6xST = 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0
371  // Left-aligned (the CCx equals ~CC6xST):
372  // T12PR = (Period-1)
373  // T12 = 0 1 2 3 4 5 6 7 8 9 10 11 0 1 2 3
374  // CC6xR = Ton = 2
375  // CC6xST = 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0
377  Ifx_CCU6 *module = timer->ccu6;
378  int i;
379  int channels = driver->base.channelCount;
380  Ifx_TimerValue period = driver->timer->base.period;
381 
382  for (i = 0; i < channels; i++)
383  {
384  Ifx_TimerValue cmp;
385  Ifx_TimerValue tOnX = tOn[i];
386 
387  if (tOnX < driver->base.minPulse)
388  {
389  tOnX = 0;
390  }
391  else if (tOnX > driver->base.maxPulse)
392  {
393  tOnX = period;
394  }
395  else
396  {}
397 
398  cmp = (period - tOnX);
399  cmp = cmp >> ((driver->base.mode == Ifx_Pwm_Mode_centerAligned) ? 1 : 0);
400  IfxCcu6_setT12CompareValue(module, i, (uint16)cmp);
401  }
402 }
403 
404 
405 static void IfxCcu6_PwmHl_setOutputPins(Ifx_CCU6 *module, const IfxCcu6_PwmHl_Config *config)
406 {
407  if (config->cc0 != NULL_PTR)
408  {
409  IfxCcu6_initCc60OutPin(config->cc0, config->base.outputMode, config->base.outputDriver);
410  }
411 
412  if (config->cc1 != NULL_PTR)
413  {
414  IfxCcu6_initCc61OutPin(config->cc1, config->base.outputMode, config->base.outputDriver);
415  }
416 
417  if (config->cc2 != NULL_PTR)
418  {
419  IfxCcu6_initCc62OutPin(config->cc2, config->base.outputMode, config->base.outputDriver);
420  }
421 
422  if (config->cout0 != NULL_PTR)
423  {
424  IfxCcu6_initCout60Pin(config->cout0, config->base.outputMode, config->base.outputDriver);
425  }
426 
427  if (config->cout1 != NULL_PTR)
428  {
429  IfxCcu6_initCout61Pin(config->cout1, config->base.outputMode, config->base.outputDriver);
430  }
431 
432  if (config->cout2 != NULL_PTR)
433  {
434  IfxCcu6_initCout62Pin(config->cout2, config->base.outputMode, config->base.outputDriver);
435  }
436 }
437 
438 
439 void IfxCcu6_PwmHl_setupChannels(IfxCcu6_PwmHl *driver, boolean *activeCh, boolean *stuckSt)
440 {
441  IfxCcu6_TimerWithTrigger *timer = driver->timer;
442  Ifx_CCU6 *module = timer->ccu6;
443  {
444  uint8 pattern;
445 
446  pattern = 0;
447  pattern |= ((activeCh[0] != FALSE) ? 1 : 0) << 0;
448  pattern |= ((activeCh[1] != FALSE) ? 1 : 0) << 1;
449  pattern |= ((activeCh[2] != FALSE) ? 1 : 0) << 2;
450  pattern |= ((activeCh[3] != FALSE) ? 1 : 0) << 3;
451  pattern |= ((activeCh[4] != FALSE) ? 1 : 0) << 4;
452  pattern |= ((activeCh[5] != FALSE) ? 1 : 0) << 5;
453 
454  IfxCcu6_setMultiChannelPwmPattern(module, pattern);
455  }
456  {
457  Ifx_CCU6_PSLR pslr;
458  pslr.U = module->PSLR.U;
459  pslr.B.PSL = 0;
460 
461  // top:
462  pslr.B.PSL |= ((activeCh[0] == FALSE) ? ((stuckSt[0] == FALSE) ? 0 : 1) : 0) << 0;
463  pslr.B.PSL |= ((activeCh[2] == FALSE) ? ((stuckSt[2] == FALSE) ? 0 : 1) : 0) << 2;
464  pslr.B.PSL |= ((activeCh[4] == FALSE) ? ((stuckSt[4] == FALSE) ? 0 : 1) : 0) << 4;
465 
466  // bottom:
467  pslr.B.PSL |= ((activeCh[1] == FALSE) ? ((stuckSt[1] == FALSE) ? 0 : 1) : 0) << 1;
468  pslr.B.PSL |= ((activeCh[3] == FALSE) ? ((stuckSt[3] == FALSE) ? 0 : 1) : 0) << 3;
469  pslr.B.PSL |= ((activeCh[5] == FALSE) ? ((stuckSt[5] == FALSE) ? 0 : 1) : 0) << 5;
470  module->PSLR.U = pslr.U;
471  }
472 }
473 
474 
476 {
477  /* Ensure the stdif is reset to zeros */
478  memset(stdif, 0, sizeof(IfxStdIf_PwmHl));
479 
480  /* *INDENT-OFF* Note: this file was indented manually by the author. */
481  /* Set the API link */
482  stdif->driver = driver;
492  /* *INDENT-ON* */
493 
494  return TRUE;
495 }
496 
497 
498 static void IfxCcu6_PwmHl_updateCenterAligned(IfxCcu6_PwmHl *driver, Ifx_TimerValue *tOn)
499 {
500  IfxCcu6_PwmHl_setOnTime(driver, tOn);
501 }
502 
503 
504 static void IfxCcu6_PwmHl_updateEdgeAligned(IfxCcu6_PwmHl *driver, Ifx_TimerValue *tOn)
505 {
506  IfxCcu6_PwmHl_setOnTime(driver, tOn);
507 }
508 
509 
510 static void IfxCcu6_PwmHl_updateOff(IfxCcu6_PwmHl *driver, Ifx_TimerValue *tOn)
511 {
512  /* Nothing to do */
513 }