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
7 #include "usbdrv/usbdrv.h"
13 struct probe ds1820probes[DS1820_MAXPROBES];
15 void ds1820init(void) {
20 void ds1820killbus(void) {
21 ds1wire_pulldown(B, 0);
24 static void ds1820write(uint8_t val) {
26 for (i = 0; i < 8; i++) {
36 static uint8_t ds1820read(void) {
39 for (i = 0; i < 8; i++) {
40 res |= ((ds1wire_read(B, 0)) << i);
45 void ds1820queryprobe(uint8_t probenum)
47 uint8_t i; uint8_t crc = 0;
50 ds1820write(DS1820_CMD_SKIPROM); /* Skip ROM */
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]);
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);
70 /* Returns 1 on successful update, 0 otherwise */
71 uint8_t ds1820updateprobe(uint8_t probenum)
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);
80 ds1820write(DS1820_CMD_SKIPROM); /* Skip ROM */
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]);
93 ds1820write(DS1820_CMD_READSCRPAD);
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);
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
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;
119 /* This is going to be a tough one:
120 * Scan the bus to find all probes.
122 void ds1820scan(void) {
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;
131 ds1820probes[0].flags &= ~DS1820FLAG_PARASITE;
134 uint8_t lastserialfound[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
135 int8_t lastcolwith0 = -1;
139 for (i = 0; i < DS1820_MAXPROBES; i++) { /* Clear list of probes */
140 ds1820probes[i].flags = 0;
144 prevcolwith0 = lastcolwith0;
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 */
160 lastserialfound[i >> 3] |= _BV(i & 0x07);
164 lastserialfound[i >> 3] &= (uint8_t)~_BV(i & 0x07);
167 } else { /* val1 != val2 */
168 if (val1 == 0) { /* Was a 0, so select that */
170 lastserialfound[i >> 3] &= (uint8_t)~_BV(i & 0x07);
171 } else { /* Was a 1 */
173 lastserialfound[i >> 3] |= _BV(i & 0x07);
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]);
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. */
191 if (i == DS1820_MAXPROBES) { /* No match. Overwrite last entry. */
192 i = DS1820_MAXPROBES - 1;
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];
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;
207 ds1820probes[i].flags &= ~DS1820FLAG_PARASITE;
210 } while (lastcolwith0 >= 0);