phase.c
Go to the documentation of this file.
00001
00039 #include "hw/hw_phase.h"
00040
00041 #include <cfg/macros.h>
00042 #include <cfg/compiler.h>
00043
00044 #include <cpu/irq.h>
00045 #include <cpu/types.h>
00046
00047 #include <drv/timer.h>
00048 #include <drv/phase.h>
00049
00050 #include <math.h>
00051
00053 static Triac triacs[TRIAC_CNT];
00054
00055 DB(bool phase_initialized;)
00056
00064 DEFINE_ZEROCROSS_ISR()
00065 {
00066     ticks_t period, now;
00067     static ticks_t prev_time;
00068     TriacDev dev;
00069
00070     now = timer_clock_unlocked();
00071     period = now - prev_time;
00072
00073     for (dev = 0; dev < TRIAC_CNT; dev++)
00074     {
00075         /* Only turn off triac if duty is != 100% */
00076         if (triacs[dev].duty != CONFIG_TRIAC_MAX_DUTY)
00077             TRIAC_OFF(dev);
00078         /* Compute delay from duty */
00079         timer_setDelay(&triacs[dev].timer, DIV_ROUND(period * (CONFIG_TRIAC_MAX_DUTY - triacs[dev].duty), CONFIG_TRIAC_MAX_DUTY));
00080
00081         /* This check avoids inserting the same timer twice
00082          * in case of an intempestive zerocross or spike */
00083         if (triacs[dev].running)
00084         {
00085             timer_abort(&triacs[dev].timer);
00086             //kprintf("[%lu]\n", timer_clock());
00087         }
00088
00089         triacs[dev].running = true;
00090         timer_add(&triacs[dev].timer);
00091     }
00092     prev_time = now;
00093 }
00094
00095
00096
00100 void phase_setDuty(TriacDev dev, triac_duty_t duty)
00101 {
00102     cpu_flags_t flags;
00103     IRQ_SAVE_DISABLE(flags);
00104
00105     phase_setDutyUnlock(dev,duty);
00106
00107     IRQ_RESTORE(flags);
00108 }
00109
00110
00111
00115 void phase_setDutyUnlock(TriacDev dev, triac_duty_t duty)
00116 {
00117     triacs[dev].duty = MIN(duty, (triac_duty_t)CONFIG_TRIAC_MAX_DUTY);
00118 }
00119
00120
00121
00128 void phase_setPower(TriacDev dev, triac_power_t power)
00129 {
00130     bool greater_fifty = false;
00131     triac_duty_t duty;
00132
00133     power = MIN(power, (triac_power_t)CONFIG_TRIAC_MAX_POWER);
00134
00135     if (power > CONFIG_TRIAC_MAX_POWER / 2)
00136     {
00137         greater_fifty = true;
00138         power = CONFIG_TRIAC_MAX_POWER - power;
00139     }
00140
00141     duty = TRIAC_POWER_K * sqrt(power);
00142
00143     if (greater_fifty)
00144         duty = CONFIG_TRIAC_MAX_DUTY - duty;
00145     phase_setDuty(dev, duty);
00146 }
00147
00148
00149
00155 static void phase_softint(void *_dev)
00156 {
00157     TriacDev dev = (TriacDev)_dev;
00158
00159     /* Only turn on if duty is !=0 */
00160     if (triacs[dev].duty)
00161         TRIAC_ON(dev);
00162     triacs[dev].running = false;
00163 }
00164
00165
00166
00170 void phase_init(void)
00171 {
00172     cpu_flags_t flags;
00173     TriacDev dev;
00174
00175     /* Init timers and ensure that all triac are off */
00176     for (dev = 0; dev < TRIAC_CNT; dev++)
00177     {
00178         triacs[dev].duty = 0;
00179         triacs[dev].running = false;
00180         SET_TRIAC_DDR(dev);
00181         TRIAC_OFF(dev);
00182         timer_setSoftint(&triacs[dev].timer, (Hook)phase_softint, (void *)dev);
00183     }
00184     IRQ_SAVE_DISABLE(flags);
00185
00186     /* Init zero cross interrupt */
00187     PHASE_HW_INIT;
00188     DB(phase_initialized = true;)
00189     IRQ_RESTORE(flags);
00190 }
00191