phase.c

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