manueller import aus nem CVS checkout (ist eh nur zum testen)
[ds1820tousb.git] / ds1820.c
1 /* $Id: ds1820.c,v 1.3 2010/07/16 19:31:18 simimeie Exp $
2  * USB interface for ds1820
3  * This file handles everything that has to do with the temperature probes.
4  * (C) Michael "Fox" Meier 2009
5  */
6
7 #include "usbdrv/usbdrv.h"
8 #include "ds1wire.h"
9 #include "time.h"
10
11 #include "ds1820.h"
12
13 struct probe ds1820probes[DS1820_MAXPROBES];
14
15 void ds1820init(void) {
16   ds1wire_init(B, 0);
17   ds1wire_reset(B, 0);
18 }
19
20 void ds1820killbus(void) {
21   ds1wire_pulldown(B, 0);
22 }
23
24 static void ds1820write(uint8_t val) {
25   uint8_t i;
26   for (i = 0; i < 8; i++) {
27     if (val & 0x01) {
28       ds1wire_send1(B, 0);
29     } else {
30       ds1wire_send0(B, 0);
31     }
32     val >>= 1;
33   }
34 }
35
36 static uint8_t ds1820read(void) {
37   uint8_t i;
38   uint8_t res = 0;
39   for (i = 0; i < 8; i++) {
40     res |= ((ds1wire_read(B, 0)) << i);
41   }
42   return res;
43 }
44
45 void ds1820queryprobe(uint8_t probenum)
46 {
47   uint8_t i; uint8_t crc = 0;
48   ds1wire_reset(B, 0);
49 #ifdef KISS
50   ds1820write(DS1820_CMD_SKIPROM); /* Skip ROM */
51 #else
52   ds1820write(DS1820_CMD_MATCHROM); /* Match ROM */
53   /* Send 64 bit serial */
54   ds1820write(ds1820probes[probenum].family);
55   crc = ds1wire_calccrc8(crc, ds1820probes[probenum].family);
56   for (i = 0; i < 6; i++) {
57     ds1820write(ds1820probes[probenum].serial[i]);
58     crc = ds1wire_calccrc8(crc, ds1820probes[probenum].serial[i]);
59   }
60   ds1820write(crc);
61 #endif /* KISS */
62   /* Issue 'start temperature conversion' */
63   ds1820write(DS1820_CMD_CONVERTT);
64   if (ds1820probes[probenum].flags & DS1820FLAG_PARASITE) {
65     /* Provide parasite power */
66     ds1wire_parasitepoweron(B, 0);
67   }
68 }
69
70 /* Returns 1 on successful update, 0 otherwise */
71 uint8_t ds1820updateprobe(uint8_t probenum)
72 {
73   uint8_t i; uint8_t crc = 0; uint8_t t1 = 0; uint8_t t2 = 0;
74   if (ds1820probes[probenum].flags & DS1820FLAG_PARASITE) {
75     /* No longer provide parasite power */
76     ds1wire_parasitepoweroff(B, 0);
77   }
78   ds1wire_reset(B, 0);
79 #ifdef KISS
80   ds1820write(DS1820_CMD_SKIPROM); /* Skip ROM */
81 #else
82   ds1820write(DS1820_CMD_MATCHROM); /* Match ROM */
83   /* Send 64 bit serial */
84   ds1820write(ds1820probes[probenum].family);
85   crc = ds1wire_calccrc8(crc, ds1820probes[probenum].family);
86   for (i = 0; i < 6; i++) {
87     ds1820write(ds1820probes[probenum].serial[i]);
88     crc = ds1wire_calccrc8(crc, ds1820probes[probenum].serial[i]);
89   }
90   ds1820write(crc);
91 #endif /* KISS */
92   /* Read Scratchpad */
93   ds1820write(DS1820_CMD_READSCRPAD);
94   crc = 0;
95   for (i = 0; i < 9; i++) {
96     uint8_t v = ds1820read();
97     if (i == 0) { t1 = v; }
98     if (i == 1) { t2 = v; }
99     crc = ds1wire_calccrc8(crc, v);
100   }
101   /* For parasite powered probes, reading 0x50 0x05 (85.0 deg) usually
102    * means the probe has lost power during temperature conversion and
103    * reset (85.0 is the poweron value of the temperature scratchpad).
104    * So we filter the value 85.0 for parasite powered probes. This means
105    * you can never use parasite powered probes for temperatures in this
106    * range. */
107   if ((crc == 0)
108    && (((ds1820probes[probenum].flags & DS1820FLAG_PARASITE) == 0)
109     || (t1 != 0x50) || (t2 != 0x05))) {
110     ds1820probes[probenum].lastts = gettime();
111     ds1820probes[probenum].lasttemp[0] = t1;
112     ds1820probes[probenum].lasttemp[1] = t2;
113     return 1;
114   } else {
115     return 0;
116   }
117 }
118
119 /* This is going to be a tough one:
120  * Scan the bus to find all probes.
121  */
122 void ds1820scan(void) {
123 #ifdef KISS
124   ds1wire_reset(B, 0);
125   ds1820probes[0].flags |= DS1820FLAG_SLOTINUSE;
126   ds1820write(DS1820_CMD_SKIPROM); /* Skip ROM */
127   ds1820write(DS1820_CMD_READPOWER); /* Read power supply */
128   if (ds1wire_read(B, 0) == 0) { /* Parasite powered probes return 0 */
129     ds1820probes[0].flags |= DS1820FLAG_PARASITE;
130   } else {
131     ds1820probes[0].flags &= ~DS1820FLAG_PARASITE;
132   }
133 #else /* KISS */
134   uint8_t lastserialfound[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
135   int8_t lastcolwith0 = -1;
136   int8_t prevcolwith0;
137   int8_t i;
138   uint8_t j;
139   for (i = 0; i < DS1820_MAXPROBES; i++) { /* Clear list of probes */
140     ds1820probes[i].flags = 0;
141   }
142   do {
143     ds1wire_reset(B, 0);
144     prevcolwith0 = lastcolwith0;
145     lastcolwith0 = -1;
146     /* Send scan command */
147     ds1820write(DS1820_CMD_SEARCHROM);
148     for (i = 0; i < 64; i++) {
149       uint8_t val1 = ds1wire_read(B, 0);
150       uint8_t val2 = ds1wire_read(B, 0);
151       if (val1 == val2) { /* Collission */
152         if (val1 == 1) { /* and thus val2 is 1 too */
153           /* Nothing matched on the bus! This is actually pretty fatal! */
154           /* Try to get out alive. Send all 0. */
155           ds1wire_send0(B, 0); lastcolwith0 = -1;
156         } else { /* Both 0 */
157           /* Was that where we stopped last time? */
158           if (prevcolwith0 == i) { /* Send a 1 this time */
159             ds1wire_send1(B, 0);
160             lastserialfound[i >> 3] |= _BV(i & 0x07);
161           } else {
162             lastcolwith0 = i;
163             ds1wire_send0(B, 0);
164             lastserialfound[i >> 3] &= (uint8_t)~_BV(i & 0x07);
165           }
166         }
167       } else { /* val1 != val2 */
168         if (val1 == 0) { /* Was a 0, so select that */
169           ds1wire_send0(B, 0);
170           lastserialfound[i >> 3] &= (uint8_t)~_BV(i & 0x07);
171         } else { /* Was a 1 */
172           ds1wire_send1(B, 0);
173           lastserialfound[i >> 3] |= _BV(i & 0x07);
174         }
175       }
176     }
177     /* lastserialfound now contains the serial of the last probe we found,
178      * AND that probe is selected. */
179     /* Check CRC of serial number. */
180     j = 0; /* Used as CRC here */
181     for (i = 0; i < 8; i++) {
182       j = ds1wire_calccrc8(j, lastserialfound[i]);
183     }
184     if (j == 0) { /* CRC of serial number OK! */
185       for (i = 0; i < DS1820_MAXPROBES; i++) {
186         if ((ds1820probes[i].flags & DS1820FLAG_SLOTINUSE) == 0) {
187           /* Empty slot, use it. */
188           break;
189         }
190       }
191       if (i == DS1820_MAXPROBES) { /* No match. Overwrite last entry. */
192         i = DS1820_MAXPROBES - 1;
193       }
194       ds1820probes[i].flags |= DS1820FLAG_SLOTINUSE;
195       ds1820probes[i].family = lastserialfound[0];
196       for (j = 0; j < 6; j++) {
197         ds1820probes[i].serial[j] = lastserialfound[j+1];
198       }
199       ds1820probes[i].lastts = 0;
200       ds1820probes[i].lasttemp[0] = 0;
201       ds1820probes[i].lasttemp[1] = 0;
202       /* Find out if the probe is parasite powered or not. */
203       ds1820write(DS1820_CMD_READPOWER); /* Read power supply */
204       if (ds1wire_read(B, 0) == 0) { /* Parasite powered probes return 0 */
205         ds1820probes[i].flags |= DS1820FLAG_PARASITE;
206       } else {
207         ds1820probes[i].flags &= ~DS1820FLAG_PARASITE;
208       }
209     }
210   } while (lastcolwith0 >= 0);
211 #endif /* KISS */
212 }
This page took 0.064105 seconds and 3 git commands to generate.