thermo.c

Go to the documentation of this file.
00001 
00041 #include "hw/thermo_map.h"
00042 #include "hw/hw_thermo.h"
00043 
00044 #include "cfg/cfg_thermo.h"
00045 
00046 #include <cfg/module.h>
00047 #include <cfg/macros.h>
00048 #include <cfg/debug.h>
00049 
00050 #include <drv/thermo.h>
00051 #include <drv/timer.h>
00052 #include <drv/ntc.h>
00053 
00054 
00055 
00056 
00058 static Timer thermo_timer;
00059 
00060 typedef struct ThermoControlDev
00061 {
00062     deg_t          hifi_samples[CONFIG_THERMO_HIFI_NUM_SAMPLES];
00063     deg_t          cur_hifi_sample;
00064     deg_t          target;
00065     thermostatus_t status;
00066     ticks_t        expire;
00067 } ThermoControlDev;
00068 
00070 ThermoControlDev devs[THERMO_CNT];
00071 
00072 
00076 thermostatus_t thermo_status(ThermoDev dev)
00077 {
00078     return devs[dev].status;
00079 }
00080 
00081 
00085 static void thermo_do(ThermoDev index)
00086 {
00087     ThermoControlDev* dev = &devs[index];
00088     deg_t cur_temp;
00089     deg_t tolerance = thermo_hw_tolerance(index);
00090 
00091     cur_temp = thermo_hw_read(index);
00092 
00093     // Store the sample into the hifi FIFO buffer for later interpolation
00094     dev->hifi_samples[dev->cur_hifi_sample] = cur_temp;
00095     if (++dev->cur_hifi_sample == CONFIG_THERMO_HIFI_NUM_SAMPLES)
00096         dev->cur_hifi_sample = 0;
00097 
00098     cur_temp = thermo_readTemperature(index);
00099 
00100     if (cur_temp == NTC_SHORT_CIRCUIT || cur_temp == NTC_OPEN_CIRCUIT)
00101     {
00102         if (cur_temp == NTC_SHORT_CIRCUIT)
00103         {
00104             #ifdef _DEBUG
00105             if (!(dev->status & THERMOERRF_NTCSHORT))
00106                 kprintf("dev[%d], thermo_do: NTC_SHORT\n",index);
00107             #endif
00108             dev->status |= THERMOERRF_NTCSHORT;
00109         }
00110         else
00111         {
00112             #ifdef _DEBUG
00113             if (!(dev->status & THERMOERRF_NTCOPEN))
00114                 kprintf("dev[%d], thermo_do: NTC_OPEN\n", index);
00115             #endif
00116             dev->status |= THERMOERRF_NTCOPEN;
00117         }
00118 
00119         /* Reset timeout when there is an ntc error */
00120         dev->expire = thermo_hw_timeout(index) + timer_clock();
00121         thermo_hw_off(index);
00122         return;
00123     }
00124     dev->status &= ~(THERMOERRF_NTCOPEN | THERMOERRF_NTCSHORT);
00125 
00126     if ((cur_temp < dev->target - tolerance) || (cur_temp > dev->target + tolerance))
00127     {
00128         dev->status &= ~THERMO_TGT_REACH;
00129 
00130         /* Check for timeout */
00131         if (timer_clock() - dev->expire > 0)
00132         {
00133             dev->status |= THERMOERRF_TIMEOUT;
00134             kprintf("dev[%d], thermo_do: TIMEOUT\n", index);
00135         }
00136     }
00137     else /* In target */
00138     {
00139         /* Clear errors */
00140         dev->status &= ~THERMO_ERRMASK;
00141         dev->status |= THERMO_TGT_REACH;
00142 
00143         /* Reset timeout in case we go out of target in the future */
00144         dev->expire = thermo_hw_timeout(index) + timer_clock();
00145     }
00146 
00147     if (cur_temp < dev->target)
00148         dev->status = (dev->status | THERMO_HEATING) & ~THERMO_FREEZING;
00149     else
00150         dev->status = (dev->status & ~THERMO_HEATING) | THERMO_FREEZING;
00151 
00152     thermo_hw_set(index, dev->target, cur_temp);
00153 
00154 }
00155 
00156 
00160 static void thermo_softint(void)
00161 {
00162     int i;
00163     for (i = 0; i < THERMO_CNT; ++i)
00164         if (devs[i].status & THERMO_ACTIVE)
00165             thermo_do((ThermoDev)i);
00166 
00167     timer_add(&thermo_timer);
00168 }
00169 
00170 
00174 void thermo_setTarget(ThermoDev dev, deg_t temperature)
00175 {
00176     ASSERT(dev < THERMO_CNT);
00177     devs[dev].target = temperature;
00178     devs[dev].expire = timer_clock() + thermo_hw_timeout(dev);
00179 
00180     kprintf("setTarget dev[%d], T[%d.%d]\n", dev, temperature / 10, temperature % 10);
00181 }
00182 
00186 void thermo_start(ThermoDev dev)
00187 {
00188     int i;
00189     deg_t temp;
00190 
00191     ASSERT(dev < THERMO_CNT);
00192 
00193     devs[dev].status |= THERMO_ACTIVE;
00194 
00195     /* Initialize the hifi FIFO with a constant value (the current temperature) */
00196     temp = thermo_hw_read(dev);
00197     for (i = 0; i < CONFIG_THERMO_HIFI_NUM_SAMPLES; ++i)
00198         devs[dev].hifi_samples[i] = temp;
00199     devs[dev].cur_hifi_sample = 0;
00200 
00201     /* Reset timeout */
00202     devs[dev].expire = timer_clock() + thermo_hw_timeout(dev);
00203 }
00204 
00208 void thermo_stop(ThermoDev dev)
00209 {
00210     ASSERT(dev < THERMO_CNT);
00211 
00212     devs[dev].status &= ~THERMO_ACTIVE;
00213     thermo_hw_off(dev);
00214 }
00215 
00216 
00220 void thermo_clearErrors(ThermoDev dev)
00221 {
00222     ASSERT(dev < THERMO_CNT);
00223     devs[dev].status &= ~(THERMO_ERRMASK);
00224 }
00225 
00226 
00230 deg_t thermo_readTemperature(ThermoDev dev)
00231 {
00232     int i;
00233     long accum = 0;
00234 
00235     MOD_CHECK(thermo);
00236 
00237     for (i = 0; i < CONFIG_THERMO_HIFI_NUM_SAMPLES; i++)
00238         accum += devs[dev].hifi_samples[i];
00239 
00240     return (deg_t)(accum / CONFIG_THERMO_HIFI_NUM_SAMPLES);
00241 }
00242 
00243 MOD_DEFINE(thermo)
00244 
00245 
00248 void thermo_init(void)
00249 {
00250     THERMO_HW_INIT;
00251 
00252     /* Set all status to off */
00253     for (int i = 0; i < THERMO_CNT; i++)
00254         devs[i].status = THERMO_OFF;
00255 
00256     MOD_INIT(thermo);
00257 
00258     timer_setDelay(&thermo_timer, ms_to_ticks(CONFIG_THERMO_INTERVAL_MS));
00259     timer_setSoftint(&thermo_timer, (Hook)thermo_softint, 0);
00260     timer_add(&thermo_timer);
00261 }