BeRTOS
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