BeRTOS
|
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