thermistor: Now works
[simavr] / examples / board_reprap / thermistor.c
1 /*
2         thermistor.c
3
4         Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <stdlib.h>
23 #include <pthread.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <unistd.h>
28
29 #include "avr_adc.h"
30
31 #include "thermistor.h"
32
33 /*
34  * called the ADC could use a new value
35  * The value returned is NOT in "ADC" mode, it's in millivolts
36  */
37 static void thermistor_in_hook(struct avr_irq_t * irq, uint32_t value, void * param)
38 {
39         thermistor_p p = (thermistor_p)param;
40         avr_adc_mux_t v = *((avr_adc_mux_t*)&value);
41
42 //      printf("%s(%2d/%2d)\n", __func__, p->adc_mux_number, v.src);
43
44         if (v.src != p->adc_mux_number)
45                 return;
46
47         short *t = p->table;
48         for (int ei = 0; ei < p->table_entries; ei++, t += 2) {
49                 if (t[1] <= p->current) {
50                 //      printf("%s(%2d) %.2f matches %3dC is %d adc\n", __func__, v.src,
51                 //                      p->current, t[1], t[0] / p->oversampling);
52                         avr_raise_irq(p->irq + IRQ_TERM_ADC_VALUE_OUT,
53                                                  ((t[0] / p->oversampling) * 5000) / 0x3ff);
54                         return;
55                 }
56         }
57         printf("%s(%d) temperature out of range (%.2f), we're screwed\n",
58                         __func__, p->adc_mux_number, p->current);
59 }
60
61 static const char * irq_names[IRQ_TERM_COUNT] = {
62         [IRQ_TERM_ADC_TRIGGER_IN] = "8<thermistor.trigger",
63         [IRQ_TERM_TEMP_VALUE_OUT] = "16>thermistor.out",
64 };
65
66 void
67 thermistor_init(
68                 struct avr_t * avr,
69                 thermistor_p p,
70                 int adc_mux_number,
71                 short * table,
72                 int     table_entries,
73                 int oversampling,
74                 float start_temp )
75 {
76         p->avr = avr;
77         p->irq = avr_alloc_irq(&avr->irq_pool, 0, IRQ_TERM_COUNT, irq_names);
78         avr_irq_register_notify(p->irq + IRQ_TERM_ADC_TRIGGER_IN, thermistor_in_hook, p);
79
80         p->oversampling = oversampling;
81         p->table = table;
82         p->table_entries = table_entries;
83         p->adc_mux_number = adc_mux_number;
84         p->current = p->target = start_temp;
85
86         avr_irq_t * src = avr_io_getirq(p->avr, AVR_IOCTL_ADC_GETIRQ, ADC_IRQ_OUT_TRIGGER);
87         avr_irq_t * dst = avr_io_getirq(p->avr, AVR_IOCTL_ADC_GETIRQ, adc_mux_number);
88         if (src && dst) {
89                 avr_connect_irq(src, p->irq + IRQ_TERM_ADC_TRIGGER_IN);
90                 avr_connect_irq(p->irq + IRQ_TERM_ADC_VALUE_OUT, dst);
91         }
92         printf("%s on ADC %d start %.2f\n", __func__, adc_mux_number, p->current);
93 }
94
95 void
96 thermistor_set_temp(
97                 thermistor_p t,
98                 float temp )
99 {
100
101 }