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.2 2006/07/19 12:56:26 bernie
18 *#* Convert to new Doxygen style.
20 *#* Revision 1.1 2005/11/04 18:06:44 bernie
21 *#* Import into DevLib.
23 *#* Revision 1.1 2005/05/24 09:17:58 batt
24 *#* Move drivers to top-level.
26 *#* Revision 1.14 2005/05/20 12:21:05 batt
29 *#* Revision 1.13 2005/05/09 16:34:14 batt
30 *#* Change some function names to accomplish coding standard; Add debug phase_initialized; Change duty_t and power_t to uint16_t.
32 *#* Revision 1.12 2005/05/04 17:22:30 batt
33 *#* Workaround a Doxygen parsing problem.
35 *#* Revision 1.11 2005/05/02 09:05:03 batt
36 *#* Rename duty_t and power_t in triac_duty_t and triac_power_t
38 *#* Revision 1.10 2005/05/02 08:48:55 batt
39 *#* Disable interrupt only when necessary.
41 *#* Revision 1.9 2005/04/29 11:52:51 batt
42 *#* Remove debug printf; Add a comment.
44 *#* Revision 1.8 2005/04/29 10:22:56 batt
45 *#* Avoid retriggering TRIAC on low duty-cycle.
47 *#* Revision 1.7 2005/04/29 09:54:36 batt
48 *#* Convert to new timer.
50 *#* Revision 1.6 2005/04/28 17:11:53 batt
51 *#* Expand abbreviation.
53 *#* Revision 1.5 2005/04/28 15:10:11 batt
54 *#* Use timer API to add and set events.
56 *#* Revision 1.4 2005/04/28 12:04:46 batt
57 *#* Add some comments.
59 *#* Revision 1.3 2005/04/28 10:35:45 batt
60 *#* Complete phase_setpower.
62 *#* Revision 1.2 2005/04/27 19:22:49 batt
63 *#* Add duty_t, power_t, MAX_DUTY and MAX_POWER
65 *#* Revision 1.1 2005/04/27 17:13:56 batt
66 *#* Add triac phase control driver.
70 #include <drv/timer.h>
73 #include <cfg/macros.h>
75 #include <cfg/compiler.h>
79 #include <drv/phase.h>
83 /** Array of triacs */
84 static Triac triacs[TRIAC_CNT];
86 DB(bool phase_initialized;)
89 * Zerocross interrupt, call when 220V cross zero.
91 * This function turn off all triacs that have duty < 100%
92 * and arm the triac timers for phase control.
93 * This function is frequency adaptive so can work both at 50 or 60Hz.
95 DEFINE_ZEROCROSS_ISR()
98 static ticks_t prev_time;
101 now = timer_clock_unlocked();
102 period = now - prev_time;
104 for (dev = 0; dev < TRIAC_CNT; dev++)
106 /* Only turn off triac if duty is != 100% */
107 if (triacs[dev].duty != TRIAC_MAX_DUTY)
109 /* Compute delay from duty */
110 timer_setDelay(&triacs[dev].timer, ((period * (TRIAC_MAX_DUTY - triacs[dev].duty) + TRIAC_MAX_DUTY / 2) / TRIAC_MAX_DUTY));
112 /* This check avoids inserting the same timer twice
113 * in case of an intempestive zerocross or spike */
114 if (triacs[dev].running)
116 timer_abort(&triacs[dev].timer);
117 //kprintf("[%lu]\n", timer_clock());
120 triacs[dev].running = true;
121 timer_add(&triacs[dev].timer);
129 * Set duty of the triac channel \a dev (interrupt safe).
131 void phase_setDuty(TriacDev dev, triac_duty_t duty)
134 IRQ_SAVE_DISABLE(flags);
136 phase_setDutyUnlock(dev,duty);
144 * Set duty of the triac channel \a dev (NOT INTERRUPT SAFE).
146 void phase_setDutyUnlock(TriacDev dev, triac_duty_t duty)
148 triacs[dev].duty = MIN(duty, (triac_duty_t)TRIAC_MAX_DUTY);
154 * Set power of the triac channel \a dev (interrupt safe).
156 * This function approsimate the sine wave to a triangular wave to compute
159 void phase_setPower(TriacDev dev, triac_power_t power)
161 bool greater_fifty = false;
164 power = MIN(power, (triac_power_t)TRIAC_MAX_POWER);
166 if (power > TRIAC_MAX_POWER / 2)
168 greater_fifty = true;
169 power = TRIAC_MAX_POWER - power;
172 duty = TRIAC_POWER_K * sqrt(power);
175 duty = TRIAC_MAX_DUTY - duty;
176 phase_setDuty(dev, duty);
182 * Soft int for each \a _dev triac.
184 * The triacs are turned on at different time to achieve phase control.
186 static void phase_softint(void *_dev)
188 TriacDev dev = (TriacDev)_dev;
190 /* Only turn on if duty is !=0 */
191 if (triacs[dev].duty)
193 triacs[dev].running = false;
199 * Initialize phase control driver
201 void phase_init(void)
206 /* Init timers and ensure that all triac are off */
207 for (dev = 0; dev < TRIAC_CNT; dev++)
209 triacs[dev].duty = 0;
210 triacs[dev].running = false;
213 timer_set_event_softint(&triacs[dev].timer, (Hook)phase_softint, (void *)dev);
215 IRQ_SAVE_DISABLE(flags);
217 /* Init zero cross interrupt */
219 DB(phase_initialized = true;)