thermo.c
Go to the documentation of this file.00001
00047 #include "hw/thermo_map.h"
00048 #include "hw/hw_thermo.h"
00049
00050 #include "cfg/cfg_thermo.h"
00051
00052 #include <cfg/module.h>
00053 #include <cfg/macros.h>
00054 #include <cfg/debug.h>
00055
00056 #define LOG_LEVEL CONFIG_THERMO_LOG_LEVEL
00057 #define LOG_VERBOSITY CONFIG_THERMO_LOG_FORMAT
00058 #include <cfg/log.h>
00059
00060 #include <drv/thermo.h>
00061 #include <drv/timer.h>
00062 #include <drv/ntc.h>
00063
00064 #include <kern/proc.h>
00065
00066 #define THERMO_OFF 0
00067 #define THERMO_HEATING BV(0)
00068 #define THERMO_FREEZING BV(1)
00069 #define THERMO_TGT_REACH BV(2)
00070 #define THERMOERRF_NTCSHORT BV(3)
00071 #define THERMOERRF_NTCOPEN BV(4)
00072 #define THERMOERRF_TIMEOUT BV(5)
00073 #define THERMO_ACTIVE BV(6)
00074 #define THERMO_TIMER BV(7)
00075
00076 #define THERMO_ERRMASK (THERMOERRF_NTCSHORT | THERMOERRF_NTCOPEN | THERMOERRF_TIMEOUT)
00077
00078
00079 #if CONFIG_KERN
00080
00081 static PROC_DEFINE_STACK(thermo_poll_stack, 400);
00082 #else
00083
00084 static Timer thermo_timer;
00085 #endif
00086
00087 typedef struct ThermoControlDev
00088 {
00089 deg_t hifi_samples[CONFIG_THERMO_HIFI_NUM_SAMPLES];
00090 deg_t cur_hifi_sample;
00091 deg_t target;
00092 thermostatus_t status;
00093 ticks_t expire;
00094 ticks_t on_time;
00095 } ThermoControlDev;
00096
00098 ThermoControlDev devs[THERMO_CNT];
00099
00103 thermostatus_t thermo_status(ThermoDev dev)
00104 {
00105 ASSERT(dev < THERMO_CNT);
00106 return devs[dev].status;
00107 }
00108
00109
00113 static void thermo_do(ThermoDev index)
00114 {
00115 ThermoControlDev* dev = &devs[index];
00116 deg_t cur_temp;
00117 deg_t tolerance = thermo_hw_tolerance(index);
00118
00119 cur_temp = thermo_hw_read(index);
00120
00121
00122 dev->hifi_samples[dev->cur_hifi_sample] = cur_temp;
00123 if (++dev->cur_hifi_sample == CONFIG_THERMO_HIFI_NUM_SAMPLES)
00124 dev->cur_hifi_sample = 0;
00125
00126 cur_temp = thermo_readTemperature(index);
00127
00128 if (cur_temp == NTC_SHORT_CIRCUIT || cur_temp == NTC_OPEN_CIRCUIT)
00129 {
00130 if (cur_temp == NTC_SHORT_CIRCUIT)
00131 {
00132 LOG_INFOB(if (!(dev->status & THERMOERRF_NTCSHORT))
00133 LOG_INFO("dev[%d], thermo_do: NTC_SHORT\n",index););
00134
00135 dev->status |= THERMOERRF_NTCSHORT;
00136 }
00137 else
00138 {
00139
00140 LOG_INFOB(if (!(dev->status & THERMOERRF_NTCOPEN))
00141 LOG_INFO("dev[%d], thermo_do: NTC_OPEN\n", index););
00142
00143 dev->status |= THERMOERRF_NTCOPEN;
00144 }
00145
00146
00147 dev->expire = thermo_hw_timeout(index) + timer_clock();
00148 thermo_hw_off(index);
00149 return;
00150 }
00151 dev->status &= ~(THERMOERRF_NTCOPEN | THERMOERRF_NTCSHORT);
00152
00153 if ((cur_temp < dev->target - tolerance) || (cur_temp > dev->target + tolerance))
00154 {
00155 dev->status &= ~THERMO_TGT_REACH;
00156
00157
00158 if (timer_clock() - dev->expire > 0)
00159 {
00160 dev->status |= THERMOERRF_TIMEOUT;
00161 LOG_INFO("dev[%d], thermo_do: TIMEOUT\n", index);
00162 }
00163 }
00164 else
00165 {
00166
00167 dev->status &= ~THERMO_ERRMASK;
00168 dev->status |= THERMO_TGT_REACH;
00169
00170
00171 dev->expire = thermo_hw_timeout(index) + timer_clock();
00172 }
00173
00174 if (cur_temp < dev->target)
00175 dev->status = (dev->status | THERMO_HEATING) & ~THERMO_FREEZING;
00176 else
00177 dev->status = (dev->status & ~THERMO_HEATING) | THERMO_FREEZING;
00178
00179 thermo_hw_set(index, dev->target, cur_temp);
00180
00181 }
00182
00183 static void poll(void)
00184 {
00185 for (int i = 0; i < THERMO_CNT; ++i)
00186 if (devs[i].status & THERMO_ACTIVE)
00187 {
00188 LOG_INFO("THERMO [%d] on_time[%ld],\n", i, ticks_to_ms(devs[i].on_time));
00189 if ((devs[i].status & THERMO_TIMER) && (devs[i].on_time - timer_clock() < 0))
00190 {
00191 thermo_stop(i);
00192 continue;
00193 }
00194
00195 thermo_do((ThermoDev)i);
00196 }
00197 }
00198
00199 #if CONFIG_KERN
00200 static void NORETURN thermo_poll(void)
00201 {
00202 for (;;)
00203 {
00204 poll();
00205 timer_delay(CONFIG_THERMO_INTERVAL_MS);
00206 }
00207 }
00208 #else
00209
00212 static void thermo_softint(void)
00213 {
00214 poll();
00215 timer_add(&thermo_timer);
00216 }
00217 #endif
00218
00223 void thermo_timer(ThermoDev dev, mtime_t on_time)
00224 {
00225 ASSERT(dev < THERMO_CNT);
00226 devs[dev].on_time = timer_clock() + ms_to_ticks(on_time);
00227 devs[dev].status |= THERMO_TIMER;
00228 thermo_start(dev);
00229 }
00230
00231
00235 void thermo_setTarget(ThermoDev dev, deg_t temperature)
00236 {
00237 ASSERT(dev < THERMO_CNT);
00238 devs[dev].target = temperature;
00239 devs[dev].expire = timer_clock() + thermo_hw_timeout(dev);
00240
00241 LOG_INFO("THERMO Set Target dev[%d], T[%d.%d]\n", dev, temperature / 10, temperature % 10);
00242 }
00243
00247 void thermo_start(ThermoDev dev)
00248 {
00249 int i;
00250 deg_t temp;
00251
00252 ASSERT(dev < THERMO_CNT);
00253
00254 devs[dev].status |= THERMO_ACTIVE;
00255 LOG_INFO("THERMO Start dev[%d], status[%04x]\n", dev, devs[dev].status);
00256
00257
00258 temp = thermo_hw_read(dev);
00259 for (i = 0; i < CONFIG_THERMO_HIFI_NUM_SAMPLES; ++i)
00260 devs[dev].hifi_samples[i] = temp;
00261 devs[dev].cur_hifi_sample = 0;
00262
00263
00264 devs[dev].expire = timer_clock() + thermo_hw_timeout(dev);
00265 }
00266
00270 void thermo_stop(ThermoDev dev)
00271 {
00272 ASSERT(dev < THERMO_CNT);
00273
00274 devs[dev].status &= ~THERMO_ACTIVE;
00275 thermo_hw_off(dev);
00276 }
00277
00278
00282 void thermo_clearErrors(ThermoDev dev)
00283 {
00284 ASSERT(dev < THERMO_CNT);
00285 devs[dev].status &= ~(THERMO_ERRMASK);
00286 }
00287
00288
00292 deg_t thermo_readTemperature(ThermoDev dev)
00293 {
00294 int i;
00295 long accum = 0;
00296
00297 MOD_CHECK(thermo);
00298
00299 for (i = 0; i < CONFIG_THERMO_HIFI_NUM_SAMPLES; i++)
00300 accum += devs[dev].hifi_samples[i];
00301
00302 return (deg_t)(accum / CONFIG_THERMO_HIFI_NUM_SAMPLES);
00303 }
00304
00305 MOD_DEFINE(thermo)
00306
00307
00310 void thermo_init(void)
00311 {
00312 THERMO_HW_INIT;
00313
00314
00315 for (int i = 0; i < THERMO_CNT; i++)
00316 devs[i].status = THERMO_OFF;
00317
00318 MOD_INIT(thermo);
00319
00320 #if CONFIG_KERN
00321 proc_new_with_name("Thermo", thermo_poll, NULL, sizeof(thermo_poll_stack), thermo_poll_stack);
00322 #else
00323 timer_setDelay(&thermo_timer, ms_to_ticks(CONFIG_THERMO_INTERVAL_MS));
00324 timer_setSoftint(&thermo_timer, (Hook)thermo_softint, 0);
00325 timer_add(&thermo_timer);
00326 #endif
00327 }