Mercurial > ~darius > hgwebdir.cgi > stm32temp
annotate 1wire.c @ 83:05ba84c7da97
Add a flash layer for compatibility (in future).
Fix SPI flash block writing.
White space fixes.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Mon, 02 Mar 2015 14:32:08 +1030 |
parents | cc998b0b2bae |
children |
rev | line source |
---|---|
13 | 1 /* |
2 * Various 1 wire routines | |
3 * Search routine is copied from the Dallas owpd library with mods | |
4 * available from here http://www.ibutton.com/software/1wire/wirekit.html | |
5 * | |
6 * $Id$ | |
7 * | |
8 * Copyright (c) 2004 | |
9 * Daniel O'Connor <darius@dons.net.au>. All rights reserved. | |
10 * | |
11 * Redistribution and use in source and binary forms, with or without | |
12 * modification, are permitted provided that the following conditions | |
13 * are met: | |
14 * 1. Redistributions of source code must retain the above copyright | |
15 * notice, this list of conditions and the following disclaimer. | |
16 * 2. Redistributions in binary form must reproduce the above copyright | |
17 * notice, this list of conditions and the following disclaimer in the | |
18 * documentation and/or other materials provided with the distribution. | |
19 * | |
20 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE | |
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 * SUCH DAMAGE. | |
31 */ | |
32 | |
33 /* | |
34 * No user servicable parts inside | |
35 * | |
36 * Modify 1wire-config.h | |
37 */ | |
38 | |
39 #include <stdio.h> | |
40 #include <stdint.h> | |
41 #include "1wire-config.h" | |
42 #include "1wire.h" | |
43 | |
44 static uint8_t OW_LastDevice = 0; | |
45 static uint8_t OW_LastDiscrepancy = 0; | |
46 static uint8_t OW_LastFamilyDiscrepancy = 0; | |
47 | |
48 const PROGMEM char *OWProgROM_Status[] = { | |
49 "OK", | |
50 "no HW support", | |
51 "Invalid params", | |
52 "module missing/broken" | |
53 }; | |
54 | |
55 /*----------------------------------------------------------------------------- | |
56 * Configure the IO port as we need | |
57 */ | |
58 void | |
59 OWInit(void) { | |
60 OWBUSINIT(); | |
61 OWSETBUSHIGH(); | |
62 } | |
63 | |
64 /*----------------------------------------------------------------------------- | |
65 * Generate a 1-Wire reset, return 0 if presence pulse was found, 1 if it | |
66 * wasn't, or 2 if the line appears to be being held low. | |
67 * | |
68 * (NOTE: Does not handle alarm presence from DS2404/DS1994) | |
68
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
69 * |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
70 * XXX: should use #defines |
13 | 71 */ |
72 uint8_t | |
73 OWTouchReset(void) { | |
74 uint8_t i; | |
75 | |
76 OWDELAY_G; | |
77 | |
78 /* Check the bus isn't being held low (ie it's broken) Do it after | |
79 * the delay so we guarantee we don't see a slave from a previous | |
80 * comms attempt | |
81 */ | |
82 #if 1 | |
83 OWSETREAD(); | |
84 if(OWREADBUS() == 0) | |
85 return 2; | |
86 #endif | |
87 | |
88 OWSETBUSLOW(); | |
89 OWDELAY_H; | |
90 OWSETBUSHIGH(); | |
91 OWDELAY_I; | |
92 | |
93 OWSETREAD(); | |
94 i = OWREADBUS(); | |
95 | |
96 OWDELAY_J; | |
97 return(i); | |
98 } | |
99 | |
100 /*----------------------------------------------------------------------------- | |
101 * Send a 1-wire write bit. | |
102 */ | |
103 void | |
104 OWWriteBit(uint8_t bit) { | |
105 OWDELAY_I; | |
106 | |
107 if (bit) { | |
108 OWSETBUSLOW(); | |
109 OWDELAY_A; | |
110 OWSETBUSHIGH(); | |
111 OWDELAY_B; | |
112 } else { | |
113 OWSETBUSLOW(); | |
114 OWDELAY_C; | |
115 OWSETBUSHIGH(); | |
116 OWDELAY_D; | |
117 } | |
118 } | |
119 | |
120 /*----------------------------------------------------------------------------- | |
121 * Read a bit from the 1-wire bus and return it. | |
122 */ | |
123 uint8_t | |
124 OWReadBit(void) { | |
125 uint8_t i; | |
126 | |
127 OWDELAY_I; | |
128 | |
129 OWSETBUSLOW(); | |
130 OWDELAY_A; | |
131 OWSETBUSHIGH(); | |
132 OWDELAY_E; | |
133 OWSETREAD(); | |
134 i = OWREADBUS(); | |
135 OWDELAY_F; | |
136 return(i); | |
137 } | |
138 | |
139 /*----------------------------------------------------------------------------- | |
140 * Write a byte to the 1-wire bus | |
141 */ | |
142 void | |
143 OWWriteByte(uint8_t data) { | |
144 uint8_t i; | |
145 | |
146 /* Send LSB first */ | |
147 for (i = 0; i < 8; i++) { | |
148 OWWriteBit(data & 0x01); | |
149 data >>= 1; | |
150 } | |
151 } | |
152 | |
153 /*----------------------------------------------------------------------------- | |
154 * Read a byte from the 1-wire bus | |
155 */ | |
156 uint8_t | |
157 OWReadByte(void) { | |
158 int i, result = 0; | |
159 | |
160 for (i = 0; i < 8; i++) { | |
161 result >>= 1; | |
162 if (OWReadBit()) | |
163 result |= 0x80; | |
164 } | |
165 return(result); | |
166 } | |
167 | |
168 /*----------------------------------------------------------------------------- | |
169 * Write a 1-wire data byte and return the sampled result. | |
170 */ | |
171 uint8_t | |
172 OWTouchByte(uint8_t data) { | |
173 uint8_t i, result = 0; | |
174 | |
175 for (i = 0; i < 8; i++) { | |
176 result >>= 1; | |
177 | |
178 /* If sending a 1 then read a bit, otherwise write a 0 */ | |
179 if (data & 0x01) { | |
180 if (OWReadBit()) | |
181 result |= 0x80; | |
182 } else | |
183 OWWriteBit(0); | |
184 | |
185 data >>= 1; | |
186 } | |
187 | |
188 return(result); | |
189 } | |
190 | |
191 /*----------------------------------------------------------------------------- | |
192 * Write a block of bytes to the 1-wire bus and return the sampled result in | |
193 * the same buffer | |
194 */ | |
195 void | |
196 OWBlock(uint8_t *data, int len) { | |
197 int i; | |
198 | |
199 for (i = 0; i < len; i++) | |
200 data[i] = OWTouchByte(data[i]); | |
201 } | |
202 | |
203 | |
204 /*----------------------------------------------------------------------------- | |
205 * Send a 1 wire command to a device, or all if no ROM ID provided | |
68
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
206 * Returns same values as OWTouchReset |
13 | 207 */ |
68
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
208 uint8_t |
13 | 209 OWSendCmd(uint8_t *ROM, uint8_t cmd) { |
210 uint8_t i; | |
211 | |
68
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
212 if ((i = OWTouchReset()) != 0) |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
213 return i; |
13 | 214 |
215 if (ROM == NULL) | |
216 OWWriteByte(OW_SKIP_ROM_CMD); | |
217 else { | |
218 OWWriteByte(OW_MATCH_ROM_CMD); | |
219 for (i = 0; i < 8; i++) | |
220 OWWriteByte(ROM[i]); | |
221 } | |
222 OWWriteByte(cmd); | |
68
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
223 |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
224 return 0; |
13 | 225 } |
226 | |
227 /*----------------------------------------------------------------------------- | |
228 * Search algorithm from App note 187 (and 162) | |
229 * | |
230 * OWFirst/OWNext return.. | |
231 * 1 when something is found, | |
232 * 0 no more modules | |
233 * -1 if no presence pulse, | |
234 * -2 if bad CRC, | |
235 * -3 if bad wiring. | |
236 */ | |
237 uint8_t | |
238 OWFirst(uint8_t *ROM, uint8_t do_reset, uint8_t alarm_only) { | |
239 /* Reset state */ | |
240 OW_LastDiscrepancy = 0; | |
241 OW_LastDevice = 0; | |
242 OW_LastFamilyDiscrepancy = 0; | |
243 | |
244 /* Go looking */ | |
245 return (OWNext(ROM, do_reset, alarm_only)); | |
246 } | |
247 | |
248 /* Returns 1 when something is found, 0 if nothing left */ | |
249 uint8_t | |
250 OWNext(uint8_t *ROM, uint8_t do_reset, uint8_t alarm_only) { | |
251 uint8_t bit_test, search_direction, bit_number; | |
252 uint8_t last_zero, rom_byte_number, rom_byte_mask; | |
253 uint8_t lastcrc8, crcaccum; | |
254 int8_t next_result; | |
255 | |
256 /* Init for search */ | |
257 bit_number = 1; | |
258 last_zero = 0; | |
259 rom_byte_number = 0; | |
260 rom_byte_mask = 1; | |
261 next_result = OW_NOMODULES; | |
262 lastcrc8 = 0; | |
263 crcaccum = 0; | |
264 | |
265 /* if the last call was not the last one */ | |
266 if (!OW_LastDevice) { | |
267 /* check if reset first is requested */ | |
268 if (do_reset) { | |
269 /* reset the 1-wire | |
270 * if there are no parts on 1-wire, return 0 */ | |
271 OWPUTSP(PSTR("Resetting\r\n")); | |
272 switch (OWTouchReset()) { | |
273 case 0: | |
274 OWPUTSP(PSTR("Found device(s)\r\n")); | |
275 break; | |
276 | |
277 case 1: | |
278 /* reset the search */ | |
279 OW_LastDiscrepancy = 0; | |
280 OW_LastFamilyDiscrepancy = 0; | |
281 OWPUTSP(PSTR("No devices on bus\r\n")); | |
282 return OW_NOPRESENCE; | |
283 break; | |
284 | |
285 case 2: | |
286 /* reset the search */ | |
287 OW_LastDiscrepancy = 0; | |
288 OW_LastFamilyDiscrepancy = 0; | |
289 OWPUTSP(PSTR("Bus appears to be being held low\r\n")); | |
290 return OW_BADWIRE; | |
291 break; | |
292 | |
293 } | |
294 } | |
295 | |
296 /* If finding alarming devices issue a different command */ | |
297 if (alarm_only) | |
298 OWWriteByte(OW_SEARCH_ALRM_CMD); /* issue the alarming search command */ | |
299 else | |
300 OWWriteByte(OW_SEARCH_ROM_CMD); /* issue the search command */ | |
301 | |
302 /* pause before beginning the search */ | |
303 OWDELAY_I; | |
304 OWDELAY_I; | |
305 OWDELAY_I; | |
306 | |
307 /* loop to do the search */ | |
308 do { | |
309 /* read a bit and its compliment */ | |
310 bit_test = OWReadBit() << 1; | |
311 bit_test |= OWReadBit(); | |
312 | |
313 OWPRINTFP(PSTR("bit_test = %d\r\n"), bit_test); | |
314 | |
315 /* check for no devices on 1-wire */ | |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
316 if (bit_test == 3) |
13 | 317 return(OW_BADWIRE); |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
318 |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
319 /* all devices coupled have 0 or 1 */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
320 if (bit_test > 0) |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
321 search_direction = !(bit_test & 0x01); /* bit write value for search */ |
13 | 322 else { |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
323 /* if this discrepancy is before the Last Discrepancy |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
324 * on a previous OWNext then pick the same as last time */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
325 if (bit_number < OW_LastDiscrepancy) |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
326 search_direction = ((ROM[rom_byte_number] & rom_byte_mask) > 0); |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
327 else |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
328 /* if equal to last pick 1, if not then pick 0 */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
329 search_direction = (bit_number == OW_LastDiscrepancy); |
13 | 330 |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
331 /* if 0 was picked then record its position in LastZero */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
332 if (search_direction == 0) { |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
333 last_zero = bit_number; |
13 | 334 |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
335 /* check for Last discrepancy in family */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
336 if (last_zero < 9) |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
337 OW_LastFamilyDiscrepancy = last_zero; |
13 | 338 } |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
339 } |
13 | 340 |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
341 /* set or clear the bit in the ROM byte rom_byte_number |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
342 * with mask rom_byte_mask */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
343 if (search_direction == 1) |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
344 ROM[rom_byte_number] |= rom_byte_mask; |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
345 else |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
346 ROM[rom_byte_number] &= ~rom_byte_mask; |
13 | 347 |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
348 /* serial number search direction write bit */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
349 OWWriteBit(search_direction); |
13 | 350 |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
351 /* increment the byte counter bit_number |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
352 * and shift the mask rom_byte_mask */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
353 bit_number++; |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
354 rom_byte_mask <<= 1; |
13 | 355 |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
356 /* if the mask is 0 then go to new ROM byte rom_byte_number |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
357 * and reset mask */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
358 if (rom_byte_mask == 0) { |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
359 OWCRC(ROM[rom_byte_number], &crcaccum); /* accumulate the CRC */ |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
360 lastcrc8 = crcaccum; |
13 | 361 |
39
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
362 rom_byte_number++; |
969bb070b181
- Remove superfluous debug message.
Daniel O'Connor <darius@dons.net.au>
parents:
13
diff
changeset
|
363 rom_byte_mask = 1; |
13 | 364 } |
365 } while (rom_byte_number < 8); /* loop until through all ROM bytes 0-7 */ | |
366 | |
367 /* if the search was successful then */ | |
368 if (!(bit_number < 65) || lastcrc8) { | |
369 if (lastcrc8) { | |
370 OWPRINTFP(PSTR("Bad CRC (%d)\r\n"), lastcrc8); | |
371 next_result = OW_BADCRC; | |
372 } else { | |
373 /* search successful so set LastDiscrepancy,LastDevice,next_result */ | |
374 OW_LastDiscrepancy = last_zero; | |
375 OW_LastDevice = (OW_LastDiscrepancy == 0); | |
376 OWPRINTFP(PSTR("Last device = %d\r\n"), OW_LastDevice); | |
377 next_result = OW_FOUND; | |
378 } | |
379 } | |
380 } | |
381 | |
382 /* if no device found then reset counters so next 'next' will be | |
383 * like a first */ | |
384 if (next_result != OW_FOUND || ROM[0] == 0) { | |
385 OW_LastDiscrepancy = 0; | |
386 OW_LastDevice = 0; | |
387 OW_LastFamilyDiscrepancy = 0; | |
388 } | |
389 | |
390 if (next_result == OW_FOUND && ROM[0] == 0x00) | |
391 next_result = OW_BADWIRE; | |
392 | |
393 return next_result; | |
394 | |
395 } | |
396 | |
397 uint8_t PROGMEM dscrc_table[] = { | |
398 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, | |
399 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, | |
400 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, | |
401 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, | |
402 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, | |
403 219, 133,103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, | |
404 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, | |
405 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, | |
406 140,210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113,147, 205, | |
407 17, 79, 173, 243, 112, 46, 204, 146, 211,141, 111, 49, 178, 236, 14, 80, | |
408 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82,176, 238, | |
409 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, | |
410 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, | |
411 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, | |
412 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, | |
413 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 | |
414 }; | |
415 | |
416 /*----------------------------------------------------------------------------- | |
417 * Update *crc based on the value of x | |
418 */ | |
419 void | |
420 OWCRC(uint8_t x, uint8_t *crc) { | |
421 *crc = pgm_read_byte(&dscrc_table[(*crc) ^ x]); | |
422 } | |
423 | |
424 /*----------------------------------------------------------------------------- | |
425 * Program a DS2502's memory | |
426 * | |
427 * Arguments | |
428 * ROM - ROM ID (or NULL to send SKIP_ROM) | |
429 * start - Start address (bytes) | |
430 * len - Length of data to write | |
431 * data - Data to write | |
432 * exact - If true, only accept exact matches for programming, | |
433 * otherwise only ensure the bits we requested were | |
434 * programmed [to 0] | |
435 * status - If true program status rather than memory | |
436 * | |
437 * Returns.. | |
438 * 0 if all is OK | |
439 * 1 if the programming is not possible | |
440 * 2 if the parameters were invalid | |
441 * 3 if the DS2502 didn't respond appropriately (also happens if the | |
442 * module doesn't exist) | |
443 */ | |
444 #if defined(OWSETVPPON) && defined(OWSETVPPOFF) | |
445 uint8_t | |
446 OWProgROM(uint8_t *ROM, uint8_t start, uint8_t len, uint8_t *data, uint8_t exact, uint8_t status) { | |
447 uint8_t crc, i, tmp; | |
448 | |
449 /* Stupid programmer detection */ | |
450 if (status) { | |
451 if (start + len > 3) | |
452 return(2); | |
453 } else { | |
454 if (start + len > 127) | |
455 return(2); | |
456 } | |
457 | |
458 if (len < 1) | |
459 return(2); | |
460 | |
461 OWDELAY_I; | |
462 if (OWTouchReset() != 0) { | |
463 cons_putsP(PSTR("No presence pulse\r\n")); | |
464 return(3); | |
465 } | |
466 | |
467 crc = 0; | |
468 | |
469 /* Send the command */ | |
470 if (status) { | |
471 OWSendCmd(ROM, OW_WRITE_STATUS); | |
472 OWCRC(OW_WRITE_STATUS, &crc); | |
473 } else { | |
474 OWSendCmd(ROM, OW_WRITE_MEMORY); | |
475 OWCRC(OW_WRITE_MEMORY, &crc); | |
476 } | |
477 | |
478 /* And the start address | |
479 * (2 bytes even though one would do) | |
480 */ | |
481 OWWriteByte(start); | |
482 OWCRC(start, &crc); | |
483 | |
484 OWWriteByte(0x00); | |
485 OWCRC(0x00, &crc); | |
486 | |
487 for (i = 0; i < len; i++) { | |
488 cons_putsP(PSTR("Programming ")); | |
489 cons_puts_hex(data[i]); | |
490 cons_putsP(PSTR(" to ")); | |
491 cons_puts_hex(start + i); | |
492 cons_putsP(PSTR("\r\n")); | |
493 | |
494 OWWriteByte(data[i]); | |
495 OWCRC(data[i], &crc); | |
496 | |
497 tmp = OWReadByte(); | |
498 | |
499 if (crc != tmp) { | |
500 cons_putsP(PSTR("CRC mismatch ")); | |
501 cons_puts_hex(crc); | |
502 cons_putsP(PSTR(" vs ")); | |
503 cons_puts_hex(tmp); | |
504 cons_putsP(PSTR("\r\n")); | |
505 | |
506 OWTouchReset(); | |
507 return(3); | |
508 } | |
509 | |
510 OWSETVPPON(); | |
511 OWDELAY_H; | |
512 OWSETVPPOFF(); | |
513 | |
514 tmp = OWReadByte(); | |
515 | |
516 /* Check the bits we turned off are off */ | |
517 /* | |
518 for (i = 0; i < 8; i++) | |
519 if (!(data[i] & 1 << i) && (tmp & 1 << i)) | |
520 return(-3); | |
521 */ | |
522 if ((!data[i] & tmp) != 0) { | |
523 cons_putsP(PSTR("Readback mismatch ")); | |
524 cons_puts_hex(data[i]); | |
525 cons_putsP(PSTR(" vs ")); | |
526 cons_puts_hex(data[i]); | |
527 cons_putsP(PSTR("\r\n")); | |
528 | |
529 OWTouchReset(); | |
530 return(3); | |
531 } | |
532 | |
533 /* The DS2502 loads it's CRC register with the address of the | |
534 * next byte */ | |
535 crc = 0; | |
536 OWCRC(start + i + 1, &crc); | |
537 } | |
538 | |
539 return(0); | |
540 } | |
541 #else | |
542 uint8_t | |
543 OWProgROM(uint8_t *ROM __attribute((unused)), uint8_t start __attribute((unused)), uint8_t len __attribute((unused)), uint8_t *data __attribute((unused)), uint8_t exact __attribute((unused)), uint8_t status __attribute((unused))) { | |
544 return(1); | |
545 } | |
546 #endif | |
547 | |
548 /* | |
549 * OWGetTemp | |
550 * | |
551 * Get the temperature from a 1wire bus module | |
552 * | |
553 * Returns temperature in hundredths of a degree or OW_TEMP_xxx on | |
554 * error. | |
555 */ | |
556 int16_t | |
557 OWGetTemp(uint8_t *ROM) { | |
558 int8_t i; | |
559 uint8_t crc, buf[9]; | |
560 int16_t temp; | |
561 int16_t tfrac; | |
562 | |
563 if (ROM[0] != OW_FAMILY_TEMP) | |
564 return OW_TEMP_WRONG_FAM; | |
565 | |
68
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
566 switch (OWSendCmd(ROM, OW_CONVERTT_CMD)) { |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
567 case 0: |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
568 break; |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
569 |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
570 case 1: |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
571 case 2: |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
572 return OW_TEMP_NO_ROM; |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
573 } |
cc998b0b2bae
Handle missing modules in OWGetTemp.
Daniel O'Connor <darius@dons.net.au>
parents:
39
diff
changeset
|
574 |
13 | 575 i = 0; |
576 | |
577 /* Wait for the conversion */ | |
578 while (OWReadBit() == 0) | |
579 i = 1; | |
580 | |
581 /* Check that we talked to a module and it did something */ | |
582 if (i == 0) { | |
583 return OW_TEMP_NO_ROM; | |
584 } | |
585 | |
586 OWSendCmd(ROM, OW_RD_SCR_CMD); | |
587 crc = 0; | |
588 for (i = 0; i < 8; i++) { | |
589 buf[i] = OWReadByte(); | |
590 OWCRC(buf[i], &crc); | |
591 } | |
592 buf[i] = OWReadByte(); | |
593 if (crc != buf[8]) | |
594 return OW_TEMP_CRC_ERR; | |
595 temp = buf[0]; | |
596 if (buf[1] & 0x80) | |
597 temp -= 256; | |
598 | |
599 /* Chop off 0.5 degree bit */ | |
600 temp >>= 1; | |
601 | |
602 /* Calulate the fractional remainder */ | |
603 tfrac = buf[7] - buf[6]; | |
604 | |
605 /* Work in 100'th of degreess to save on floats */ | |
606 tfrac *= (int16_t)100; | |
607 | |
608 /* Divide by count */ | |
609 tfrac /= buf[7]; | |
610 | |
611 /* Subtract 0.25 deg from temp */ | |
612 tfrac += 75; | |
613 if (tfrac < 100) | |
614 temp--; | |
615 else | |
616 tfrac -= 100; | |
617 | |
618 i = temp; | |
619 temp *= 100; | |
620 temp += tfrac; | |
621 | |
622 return(temp); | |
623 } | |
624 | |
625 /* | |
626 * OWTempStatusStr | |
627 * | |
628 * Return a string for each OW_TEMP_xxx error code | |
629 * | |
630 * shrt = 1 returns short strings | |
631 * | |
632 */ | |
633 const char * | |
634 OWTempStatusStr(int16_t val, uint8_t shrt) { | |
635 if (val > OW_TEMP_BADVAL) { | |
636 if (shrt) | |
637 return PSTR("OK"); | |
638 else | |
639 return PSTR("OK"); | |
640 } | |
641 | |
642 switch (val) { | |
643 case OW_TEMP_WRONG_FAM: | |
644 if (shrt) | |
645 return PSTR("WrFam"); | |
646 else | |
647 return PSTR("Wrong family"); | |
648 break; | |
649 case OW_TEMP_CRC_ERR: | |
650 if (shrt) | |
651 return PSTR("CRCErr"); | |
652 else | |
653 return PSTR("CRC Error"); | |
654 break; | |
655 case OW_TEMP_NO_ROM: | |
656 if (shrt) | |
657 return PSTR("NoROM"); | |
658 else | |
659 return PSTR("ROM did not reply"); | |
660 break; | |
661 default: | |
662 if (shrt) | |
663 return PSTR("???"); | |
664 else | |
665 return PSTR("Unknown error code"); | |
666 break; | |
667 } | |
668 } |