Line No. | Rev | Author | Line |
---|---|---|---|
1 | 6 | kaklik | //***************************************************************************** |
2 | // File Name : dallas.c |
||
3 | // Title : Dallas 1-Wire Library |
||
4 | // Revision : 6 |
||
5 | // Notes : |
||
6 | // Target MCU : Atmel AVR series |
||
7 | // Editor Tabs : 4 |
||
8 | // |
||
9 | //***************************************************************************** |
||
10 | |||
11 | //----- Include Files --------------------------------------------------------- |
||
12 | #include <avr/io.h> // include I/O definitions (port names, pin names, etc) |
||
13 | #include <avr/interrupt.h> // include interrupt support |
||
14 | #include <string.h> // include string support |
||
15 | #include "rprintf.h" // include rprintf function library |
||
16 | #include "timer128.h" // include timer function library |
||
17 | #include "dallas.h" // include dallas support |
||
18 | |||
19 | //----- Global Variables ------------------------------------------------------- |
||
20 | static u08 last_discrep = 0; // last discrepancy for FindDevices |
||
21 | static u08 done_flag = 0; // done flag for FindDevices |
||
22 | |||
23 | u08 dallas_crc; // current crc global variable |
||
24 | u08 dallas_crc_table[] = // dallas crc lookup table |
||
25 | { |
||
26 | 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, |
||
27 | 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, |
||
28 | 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, |
||
29 | 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, |
||
30 | 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, |
||
31 | 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, |
||
32 | 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, |
||
33 | 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, |
||
34 | 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, |
||
35 | 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, |
||
36 | 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, |
||
37 | 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, |
||
38 | 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, |
||
39 | 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, |
||
40 | 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, |
||
41 | 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53 |
||
42 | }; |
||
43 | |||
44 | //----- Functions -------------------------------------------------------------- |
||
45 | |||
46 | /*-------------------------------------------------------------------------- |
||
47 | * dallasFindNextDevice: find the next device on the bus |
||
48 | * input................ rom_id - pointer to store the rom id found |
||
49 | * returns.............. true or false if a device was found |
||
50 | *-------------------------------------------------------------------------*/ |
||
51 | u08 dallasFindNextDevice(dallas_rom_id_T* rom_id); |
||
52 | |||
53 | void dallasDelayUs(u16 us) |
||
54 | { |
||
55 | while(us--) // 6 cycles |
||
56 | { |
||
57 | asm volatile ("nop"); |
||
58 | asm volatile ("nop"); |
||
59 | asm volatile ("nop"); |
||
60 | asm volatile ("nop"); |
||
61 | asm volatile ("nop"); |
||
62 | asm volatile ("nop"); |
||
63 | asm volatile ("nop"); |
||
64 | } // loop jump 2 cycles |
||
65 | } |
||
66 | |||
67 | void dallasInit(void) |
||
68 | { |
||
69 | } |
||
70 | |||
71 | u08 dallasReset(void) |
||
72 | { |
||
73 | u08 presence = DALLAS_PRESENCE; |
||
74 | |||
75 | cli(); |
||
76 | |||
77 | // pull line low |
||
78 | sbi(DALLAS_DDR, DALLAS_PIN); |
||
79 | cbi(DALLAS_PORT, DALLAS_PIN); |
||
80 | |||
81 | // wait for presence |
||
82 | dallasDelayUs(480); |
||
83 | |||
84 | // allow line to return high |
||
85 | cbi(DALLAS_DDR, DALLAS_PIN); |
||
86 | sbi(DALLAS_PORT, DALLAS_PIN); |
||
87 | |||
88 | // wait for presence |
||
89 | dallasDelayUs(70); |
||
90 | |||
91 | // if device is not present, pin will be 1 |
||
92 | if (inb(DALLAS_PORTIN) & 0x01<<DALLAS_PIN) |
||
93 | presence = DALLAS_NO_PRESENCE; |
||
94 | |||
95 | // wait for end of timeslot |
||
96 | dallasDelayUs(410); |
||
97 | |||
98 | sei(); |
||
99 | |||
100 | // now that we have reset, let's check bus health |
||
101 | // it should be noted that a delay may be needed here for devices that |
||
102 | // send out an alarming presence pulse signal after a reset |
||
103 | cbi(DALLAS_DDR, DALLAS_PIN); |
||
104 | sbi(DALLAS_PORT, DALLAS_PIN); |
||
105 | //dallasDelayUs(200); |
||
106 | if (!(inb(DALLAS_PORTIN) & (0x01<<DALLAS_PIN))) // it should be pulled up to high |
||
107 | return DALLAS_BUS_ERROR; |
||
108 | |||
109 | return presence; |
||
110 | } |
||
111 | |||
112 | u08 dallasReadBit(void) |
||
113 | { |
||
114 | u08 bit = 0; |
||
115 | |||
116 | // pull line low to start timeslot |
||
117 | sbi(DALLAS_DDR, DALLAS_PIN); |
||
118 | cbi(DALLAS_PORT, DALLAS_PIN); |
||
119 | |||
120 | // delay appropriate time |
||
121 | dallasDelayUs(6); |
||
122 | |||
123 | // release the bus |
||
124 | cbi(DALLAS_DDR, DALLAS_PIN); |
||
125 | sbi(DALLAS_PORT, DALLAS_PIN); |
||
126 | |||
127 | // delay appropriate time |
||
128 | dallasDelayUs(9); |
||
129 | |||
130 | // read the pin and set the variable to 1 if the pin is high |
||
131 | if (inb(DALLAS_PORTIN) & 0x01<<DALLAS_PIN) |
||
132 | bit = 1; |
||
133 | |||
134 | // finish read timeslot |
||
135 | dallasDelayUs(55); |
||
136 | |||
137 | return bit; |
||
138 | } |
||
139 | |||
140 | void dallasWriteBit(u08 bit) |
||
141 | { |
||
142 | // drive bus low |
||
143 | sbi(DALLAS_DDR, DALLAS_PIN); |
||
144 | cbi(DALLAS_PORT, DALLAS_PIN); |
||
145 | |||
146 | // delay the proper time if we want to write a 0 or 1 |
||
147 | if (bit) |
||
148 | dallasDelayUs(6); |
||
149 | else |
||
150 | dallasDelayUs(60); |
||
151 | |||
152 | // release bus |
||
153 | cbi(DALLAS_DDR, DALLAS_PIN); |
||
154 | sbi(DALLAS_PORT, DALLAS_PIN); |
||
155 | |||
156 | // delay the proper time if we want to write a 0 or 1 |
||
157 | if (bit) |
||
158 | dallasDelayUs(64); |
||
159 | else |
||
160 | dallasDelayUs(10); |
||
161 | } |
||
162 | |||
163 | u08 dallasReadByte(void) |
||
164 | { |
||
165 | u08 i; |
||
166 | u08 byte = 0; |
||
167 | |||
168 | cli(); |
||
169 | |||
170 | // read all 8 bits |
||
171 | for(i=0;i<8;i++) |
||
172 | { |
||
173 | if (dallasReadBit()) |
||
174 | byte |= 0x01<<i; |
||
175 | |||
176 | // allow a us delay between each read |
||
177 | dallasDelayUs(1); |
||
178 | } |
||
179 | |||
180 | sei(); |
||
181 | |||
182 | return byte; |
||
183 | } |
||
184 | |||
185 | void dallasWriteByte(u08 byte) |
||
186 | { |
||
187 | u08 i; |
||
188 | |||
189 | cli(); |
||
190 | |||
191 | // write all 8 bits |
||
192 | for(i=0;i<8;i++) |
||
193 | { |
||
194 | dallasWriteBit((byte>>i) & 0x01); |
||
195 | |||
196 | // allow a us delay between each write |
||
197 | dallasDelayUs(1); |
||
198 | } |
||
199 | |||
200 | sei(); |
||
201 | } |
||
202 | |||
203 | u08 dallasReadRAM(dallas_rom_id_T* rom_id, u16 addr, u08 len, u08 *data) |
||
204 | { |
||
205 | u08 i; |
||
206 | u08 error; |
||
207 | |||
208 | union int16_var_U |
||
209 | { |
||
210 | u16 i16; |
||
211 | u08 i08[2]; |
||
212 | } int16_var; |
||
213 | |||
214 | // first make sure we actually have something to do |
||
215 | if (data == NULL) |
||
216 | return DALLAS_NULL_POINTER; |
||
217 | if (len == 0) |
||
218 | return DALLAS_ZERO_LEN; |
||
219 | |||
220 | // reset the bus and request the device |
||
221 | error = dallasMatchROM(rom_id); |
||
222 | if (error != DALLAS_NO_ERROR) |
||
223 | return error; |
||
224 | |||
225 | // enter read mode |
||
226 | dallasWriteByte(DALLAS_READ_MEMORY); |
||
227 | |||
228 | // write address one byte at a time |
||
229 | int16_var.i16 = addr; |
||
230 | dallasWriteByte(int16_var.i08[0]); |
||
231 | dallasWriteByte(int16_var.i08[1]); |
||
232 | |||
233 | // read data from device 1 byte at a time |
||
234 | for(i=0;i<len;i++) |
||
235 | data[i] = dallasReadByte(); |
||
236 | |||
237 | return DALLAS_NO_ERROR; |
||
238 | } |
||
239 | |||
240 | u08 dallasWriteRAM(dallas_rom_id_T* rom_id, u16 addr, u08 len, u08* data) |
||
241 | { |
||
242 | u08 i; |
||
243 | u08 error; |
||
244 | |||
245 | union int16_var_U |
||
246 | { |
||
247 | u16 i16; |
||
248 | u08 i08[2]; |
||
249 | } int16_var; |
||
250 | |||
251 | // first make sure we actually have something to do |
||
252 | if (data == NULL) |
||
253 | return DALLAS_NULL_POINTER; |
||
254 | if (len == 0) |
||
255 | return DALLAS_ZERO_LEN; |
||
256 | |||
257 | // reset the bus and request the device |
||
258 | error = dallasMatchROM(rom_id); |
||
259 | if (error != DALLAS_NO_ERROR) |
||
260 | return error; |
||
261 | |||
262 | // enter write mode |
||
263 | dallasWriteByte(DALLAS_WRITE_MEMORY); |
||
264 | |||
265 | // write address one byte at a time |
||
266 | int16_var.i16 = addr; |
||
267 | dallasWriteByte(int16_var.i08[0]); |
||
268 | dallasWriteByte(int16_var.i08[1]); |
||
269 | |||
270 | // write data one byte at a time |
||
271 | for(i=0;i<len;i++) |
||
272 | { |
||
273 | dallasWriteByte(data[i]); |
||
274 | |||
275 | // future: Check CRC16, for now just read it so we can go on |
||
276 | dallasReadByte(); |
||
277 | dallasReadByte(); |
||
278 | |||
279 | // verify the data |
||
280 | if (dallasReadByte() != data[i]) |
||
281 | return DALLAS_VERIFY_ERROR; |
||
282 | } |
||
283 | |||
284 | return DALLAS_NO_ERROR; |
||
285 | } |
||
286 | |||
287 | void dallasWaitUntilDone(void) |
||
288 | { |
||
289 | //timerPause(6); |
||
290 | |||
291 | // wait until we recieve a one |
||
292 | cli(); |
||
293 | while(!dallasReadBit()); |
||
294 | sei(); |
||
295 | } |
||
296 | |||
297 | u08 dallasReadROM(dallas_rom_id_T* rom_id) |
||
298 | { |
||
299 | u08 i; |
||
300 | |||
301 | // reset the 1-wire bus and look for presence |
||
302 | i = dallasReset(); |
||
303 | if (i != DALLAS_PRESENCE) |
||
304 | return i; |
||
305 | |||
306 | // send READ ROM command |
||
307 | dallasWriteByte(DALLAS_READ_ROM); |
||
308 | |||
309 | // get the device's ID 1 byte at a time |
||
310 | for(i=0;i<8;i++) |
||
311 | rom_id->byte[i] = dallasReadByte(); |
||
312 | |||
313 | return DALLAS_NO_ERROR; |
||
314 | } |
||
315 | |||
316 | u08 dallasMatchROM(dallas_rom_id_T* rom_id) |
||
317 | { |
||
318 | u08 i; |
||
319 | |||
320 | // reset the 1-wire and look for presence |
||
321 | i = dallasReset(); |
||
322 | if (i != DALLAS_PRESENCE) |
||
323 | return i; |
||
324 | |||
325 | // send MATCH ROM command |
||
326 | dallasWriteByte(DALLAS_MATCH_ROM); |
||
327 | |||
328 | // write id one byte at a time |
||
329 | for(i=0;i<8;i++) |
||
330 | dallasWriteByte(rom_id->byte[i]); |
||
331 | |||
332 | return DALLAS_NO_ERROR; |
||
333 | } |
||
334 | |||
335 | void dallasPrintROM(dallas_rom_id_T* rom_id) |
||
336 | { |
||
337 | s08 i; |
||
338 | |||
339 | // print out the rom in the format: xx xx xx xx xx xx xx xx |
||
340 | for(i=7;i>=0;i--) |
||
341 | { |
||
342 | rprintfu08(rom_id->byte[i]); |
||
343 | rprintfChar(' '); |
||
344 | } |
||
345 | |||
346 | // print out the rom in the format: 0xXXXXXXXXXXXXXXXX |
||
347 | rprintfProgStrM(" (0x"); |
||
348 | for(i=7;i>=0;i--) |
||
349 | { |
||
350 | rprintfu08(rom_id->byte[i]); |
||
351 | } |
||
352 | rprintfProgStrM("ULL)"); |
||
353 | |||
354 | } |
||
355 | |||
356 | u08 dallasAddressCheck(dallas_rom_id_T* rom_id, u08 family) |
||
357 | { |
||
358 | // u08 i; |
||
359 | |||
360 | // dallas_crc = 0; |
||
361 | |||
362 | // for(i=1;i<7;i++) |
||
363 | // { |
||
364 | // dallasCRC(rom_id->byte[i]); |
||
365 | // rprintfu08(rom_id->byte[i]); |
||
366 | // rprintfChar(' '); |
||
367 | // } |
||
368 | // rprintfCRLF(); |
||
369 | |||
370 | // rprintfu08(dallas_crc); |
||
371 | // rprintfCRLF(); |
||
372 | |||
373 | //run CRC on address |
||
374 | |||
375 | //make sure we have the correct family |
||
376 | if (rom_id->byte[DALLAS_FAMILY_IDX] == family) |
||
377 | return DALLAS_NO_ERROR; |
||
378 | |||
379 | return DALLAS_ADDRESS_ERROR; |
||
380 | } |
||
381 | |||
382 | u08 dallasCRC(u08 i) |
||
383 | { |
||
384 | // update the crc global variable and return it |
||
385 | dallas_crc = dallas_crc_table[dallas_crc^i]; |
||
386 | return dallas_crc; |
||
387 | } |
||
388 | |||
389 | u08 dallasFindDevices(dallas_rom_id_T rom_id[]) |
||
390 | { |
||
391 | u08 num_found = 0; |
||
392 | dallas_rom_id_T id; |
||
393 | |||
394 | // reset the rom search last discrepancy global |
||
395 | last_discrep = 0; |
||
396 | done_flag = FALSE; |
||
397 | |||
398 | // check to make sure presence is detected before we start |
||
399 | if (dallasReset() == DALLAS_PRESENCE) |
||
400 | { |
||
401 | // --> stang |
||
402 | //while (dallasFindNextDevice(&rom_id[num_found]) && (num_found<DALLAS_MAX_DEVICES)) |
||
403 | // num_found++; |
||
404 | |||
405 | // continues until no additional devices are found |
||
406 | while (dallasFindNextDevice(&id) && (num_found<DALLAS_MAX_DEVICES)) |
||
407 | memcpy(&rom_id[num_found++], &id, 8); |
||
408 | } |
||
409 | |||
410 | return num_found; |
||
411 | } |
||
412 | |||
413 | u08 dallasFindNextDevice(dallas_rom_id_T* rom_id) |
||
414 | { |
||
415 | u08 bit; |
||
416 | u08 i = 0; |
||
417 | u08 bit_index = 1; |
||
418 | u08 byte_index = 0; |
||
419 | u08 bit_mask = 1; |
||
420 | u08 discrep_marker = 0; |
||
421 | |||
422 | // reset the CRC |
||
423 | dallas_crc = 0; |
||
424 | |||
425 | if (done_flag || dallasReset() != DALLAS_PRESENCE) |
||
426 | { |
||
427 | // no more devices parts detected |
||
428 | return FALSE; |
||
429 | } |
||
430 | |||
431 | // send search ROM command |
||
432 | dallasWriteByte(DALLAS_SEARCH_ROM); |
||
433 | |||
434 | // loop until through all 8 ROM bytes |
||
435 | while(byte_index<8) |
||
436 | { |
||
437 | // read line 2 times to determine status of devices |
||
438 | // 00 - devices connected to bus with conflicting bits |
||
439 | // 01 - all devices have a 0 in this position |
||
440 | // 10 - all devices ahve a 1 in this position |
||
441 | // 11 - there are no devices connected to bus |
||
442 | i = 0; |
||
443 | cli(); |
||
444 | if (dallasReadBit()) |
||
445 | i = 2; // store the msb if 1 |
||
446 | dallasDelayUs(120); |
||
447 | if (dallasReadBit()) |
||
448 | i |= 1; // store the lsb if 1 |
||
449 | sei(); |
||
450 | |||
451 | if (i==3) |
||
452 | { |
||
453 | // there are no devices on the 1-wire |
||
454 | break; |
||
455 | } |
||
456 | else |
||
457 | { |
||
458 | if (i>0) |
||
459 | { |
||
460 | // all devices coupled have 0 or 1 |
||
461 | // shift 1 to determine if the msb is 0 or 1 |
||
462 | bit = i>>1; |
||
463 | } |
||
464 | else |
||
465 | { |
||
466 | // if this discrepancy is before the last discrepancy on a |
||
467 | // previous FindNextDevice then pick the same as last time |
||
468 | if (bit_index<last_discrep) |
||
469 | bit = ((rom_id->byte[byte_index] & bit_mask) > 0); |
||
470 | else |
||
471 | bit = (bit_index==last_discrep); |
||
472 | |||
473 | // if 0 was picked then record position with bit mask |
||
474 | if (!bit) |
||
475 | discrep_marker = bit_index; |
||
476 | } |
||
477 | |||
478 | // isolate bit in rom_id->byte[byte_index] with bit mask |
||
479 | if (bit) |
||
480 | rom_id->byte[byte_index] |= bit_mask; |
||
481 | else |
||
482 | rom_id->byte[byte_index] &= ~bit_mask; |
||
483 | |||
484 | // ROM search write |
||
485 | cli(); |
||
486 | dallasWriteBit(bit); |
||
487 | sei(); |
||
488 | |||
489 | // ncrement bit index counter and shift the bit mask |
||
490 | bit_index++; |
||
491 | bit_mask <<= 1; |
||
492 | |||
493 | if (!bit_mask) |
||
494 | { |
||
495 | // if the mask is 0 then go to new ROM |
||
496 | // accumulate the CRC and incriment the byte index and bit mask |
||
497 | dallasCRC(rom_id->byte[byte_index]); |
||
498 | byte_index++; |
||
499 | bit_mask++; |
||
500 | } |
||
501 | } |
||
502 | } |
||
503 | |||
504 | if ((bit_index < 65) || dallas_crc) |
||
505 | { |
||
506 | // search was unsuccessful - reset the last discrepancy to 0 and return false |
||
507 | last_discrep = 0; |
||
508 | return FALSE; |
||
509 | } |
||
510 | |||
511 | // search was successful, so set last_discrep and done_flag |
||
512 | last_discrep = discrep_marker; |
||
513 | done_flag = (last_discrep==0); |
||
514 | |||
515 | return TRUE; |
||
516 | } |
||
517 | |||
518 | void dallasPrintError(u08 error) |
||
519 | { |
||
520 | // if there was not an error, return |
||
521 | if (error == DALLAS_NO_ERROR) |
||
522 | return; |
||
523 | |||
524 | // print header message |
||
525 | rprintfProgStrM("ERROR "); |
||
526 | rprintfChar(error); |
||
527 | rprintfProgStrM(": "); |
||
528 | |||
529 | // print custom error message |
||
530 | switch (error) |
||
531 | { |
||
532 | case DALLAS_NO_PRESENCE: |
||
533 | rprintfProgStrM("no presence detected"); |
||
534 | break; |
||
535 | case DALLAS_INVALID_CHANNEL: |
||
536 | rprintfProgStrM("Invalid Chan"); |
||
537 | break; |
||
538 | case DALLAS_VERIFY_ERROR: |
||
539 | rprintfProgStrM("Verify"); |
||
540 | break; |
||
541 | case DALLAS_ADDRESS_ERROR: |
||
542 | rprintfProgStrM("Bad Addr"); |
||
543 | break; |
||
544 | case DALLAS_CRC_ERROR: |
||
545 | rprintfProgStrM("Data CRC"); |
||
546 | break; |
||
547 | case DALLAS_DEVICE_ERROR: |
||
548 | rprintfProgStrM("No response"); |
||
549 | break; |
||
550 | case DALLAS_FORMAT_ERROR: |
||
551 | rprintfProgStrM("Bad return format"); |
||
552 | break; |
||
553 | case DALLAS_NULL_POINTER: |
||
554 | rprintfProgStrM("Null Pointer"); |
||
555 | break; |
||
556 | case DALLAS_ZERO_LEN: |
||
557 | rprintfProgStrM("RAM rd/wr 0 bytes"); |
||
558 | break; |
||
559 | case DALLAS_BUS_ERROR: |
||
560 | rprintfProgStrM("Bus error, check pullup"); |
||
561 | break; |
||
562 | case DALLAS_RESOLUTION_ERROR: |
||
563 | rprintfProgStrM("resolution out of range"); |
||
564 | break; |
||
565 | default: |
||
566 | rprintfProgStrM("Unknown"); |
||
567 | } |
||
568 | rprintfCRLF(); |
||
569 | } |
Powered by WebSVN v2.8.3