4 * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
9 * \brief Phase control driver (implementation)
12 * \author Francesco Sacchi <batt@develer.com>
17 *#* Revision 1.1 2005/11/04 18:06:44 bernie
18 *#* Import into DevLib.
20 *#* Revision 1.1 2005/05/24 09:17:58 batt
21 *#* Move drivers to top-level.
23 *#* Revision 1.14 2005/05/20 12:21:05 batt
26 *#* Revision 1.13 2005/05/09 16:34:14 batt
27 *#* Change some function names to accomplish coding standard; Add debug phase_initialized; Change duty_t and power_t to uint16_t.
29 *#* Revision 1.12 2005/05/04 17:22:30 batt
30 *#* Workaround a Doxygen parsing problem.
32 *#* Revision 1.11 2005/05/02 09:05:03 batt
33 *#* Rename duty_t and power_t in triac_duty_t and triac_power_t
35 *#* Revision 1.10 2005/05/02 08:48:55 batt
36 *#* Disable interrupt only when necessary.
38 *#* Revision 1.9 2005/04/29 11:52:51 batt
39 *#* Remove debug printf; Add a comment.
41 *#* Revision 1.8 2005/04/29 10:22:56 batt
42 *#* Avoid retriggering TRIAC on low duty-cycle.
44 *#* Revision 1.7 2005/04/29 09:54:36 batt
45 *#* Convert to new timer.
47 *#* Revision 1.6 2005/04/28 17:11:53 batt
48 *#* Expand abbreviation.
50 *#* Revision 1.5 2005/04/28 15:10:11 batt
51 *#* Use timer API to add and set events.
53 *#* Revision 1.4 2005/04/28 12:04:46 batt
54 *#* Add some comments.
56 *#* Revision 1.3 2005/04/28 10:35:45 batt
57 *#* Complete phase_setpower.
59 *#* Revision 1.2 2005/04/27 19:22:49 batt
60 *#* Add duty_t, power_t, MAX_DUTY and MAX_POWER
62 *#* Revision 1.1 2005/04/27 17:13:56 batt
63 *#* Add triac phase control driver.
67 #include <drv/timer.h>
70 #include <cfg/macros.h>
72 #include <cfg/compiler.h>
76 #include <drv/phase.h>
80 /*! Array of triacs */
81 static Triac triacs[TRIAC_CNT];
83 DB(bool phase_initialized;)
86 * Zerocross interrupt, call when 220V cross zero.
88 * This function turn off all triacs that have duty < 100%
89 * and arm the triac timers for phase control.
90 * This function is frequency adaptive so can work both at 50 or 60Hz.
92 DEFINE_ZEROCROSS_ISR()
95 static ticks_t prev_time;
98 now = timer_clock_unlocked();
99 period = now - prev_time;
101 for (dev = 0; dev < TRIAC_CNT; dev++)
103 /* Only turn off triac if duty is != 100% */
104 if (triacs[dev].duty != TRIAC_MAX_DUTY)
106 /* Compute delay from duty */
107 timer_setDelay(&triacs[dev].timer, ((period * (TRIAC_MAX_DUTY - triacs[dev].duty) + TRIAC_MAX_DUTY / 2) / TRIAC_MAX_DUTY));
109 /* This check avoids inserting the same timer twice
110 * in case of an intempestive zerocross or spike */
111 if (triacs[dev].running)
113 timer_abort(&triacs[dev].timer);
114 //kprintf("[%lu]\n", timer_clock());
117 triacs[dev].running = true;
118 timer_add(&triacs[dev].timer);
126 * Set duty of the triac channel \a dev (interrupt safe).
128 void phase_setDuty(TriacDev dev, triac_duty_t duty)
131 IRQ_SAVE_DISABLE(flags);
133 phase_setDutyUnlock(dev,duty);
141 * Set duty of the triac channel \a dev (NOT INTERRUPT SAFE).
143 void phase_setDutyUnlock(TriacDev dev, triac_duty_t duty)
145 triacs[dev].duty = MIN(duty, (triac_duty_t)TRIAC_MAX_DUTY);
151 * Set power of the triac channel \a dev (interrupt safe).
153 * This function approsimate the sine wave to a triangular wave to compute
156 void phase_setPower(TriacDev dev, triac_power_t power)
158 bool greater_fifty = false;
161 power = MIN(power, (triac_power_t)TRIAC_MAX_POWER);
163 if (power > TRIAC_MAX_POWER / 2)
165 greater_fifty = true;
166 power = TRIAC_MAX_POWER - power;
169 duty = TRIAC_POWER_K * sqrt(power);
172 duty = TRIAC_MAX_DUTY - duty;
173 phase_setDuty(dev, duty);
179 * Soft int for each \a _dev triac.
181 * The triacs are turned on at different time to achieve phase control.
183 static void phase_softint(void *_dev)
185 TriacDev dev = (TriacDev)_dev;
187 /* Only turn on if duty is !=0 */
188 if (triacs[dev].duty)
190 triacs[dev].running = false;
196 * Initialize phase control driver
198 void phase_init(void)
203 /* Init timers and ensure that all triac are off */
204 for (dev = 0; dev < TRIAC_CNT; dev++)
206 triacs[dev].duty = 0;
207 triacs[dev].running = false;
210 timer_set_event_softint(&triacs[dev].timer, (Hook)phase_softint, (void *)dev);
212 IRQ_SAVE_DISABLE(flags);
214 /* Init zero cross interrupt */
216 DB(phase_initialized = true;)