Commit | Line | Data |
---|---|---|
bba33fe1 JM |
1 | /* Dallas 1-Wire bus routines */ |
2 | ||
3 | #if defined(__XC) | |
4 | #include <xc.h> /* XC8 General Include File */ | |
5 | #elif defined(HI_TECH_C) | |
6 | #include <htc.h> /* HiTech General Include File */ | |
7 | #endif | |
8 | ||
9 | #include <stdint.h> /* For uint8_t definition */ | |
10 | #include <stdbool.h> /* For true/false definition */ | |
11 | ||
12 | #include "system.h" | |
13 | #include "user.h" | |
14 | #include "onewire.h" | |
15 | ||
16 | // fast way, macros | |
17 | #define OWLOW { PORTAbits.RA5 = 0; TRISAbits.TRISA5 = 0; } | |
18 | #define OWHIGH { PORTAbits.RA5 = 1; TRISAbits.TRISA5 = 0; } | |
19 | #define OWTRI { TRISAbits.TRISA5 = 1; } | |
20 | #define OWREAD (PORTAbits.RA5) | |
21 | ||
22 | ||
23 | // slow way, causes a function call | |
24 | inline void drive_OW_low(void) | |
25 | { | |
26 | PORTAbits.RA5 = 0; | |
27 | TRISAbits.TRISA5 = 0; | |
28 | } | |
29 | ||
30 | inline void drive_OW_high(void) | |
31 | { | |
32 | PORTAbits.RA5 = 1; | |
33 | TRISAbits.TRISA5 = 0; | |
34 | } | |
35 | ||
36 | inline void float_OW(void) | |
37 | { | |
38 | TRISAbits.TRISA5 = 1; | |
39 | } | |
40 | ||
41 | inline bool read_OW(void) | |
42 | { | |
43 | TRISAbits.TRISA5 = 1; | |
44 | return PORTAbits.RA5; | |
45 | } | |
46 | ||
47 | ||
48 | /* start the 1-Wire bus | |
49 | * | |
50 | */ | |
51 | void OW_start(void) | |
52 | { | |
53 | //drive_OW_high(); | |
54 | float_OW(); | |
55 | } | |
56 | ||
57 | /* reset the bus, test for presence signal */ | |
58 | bool OW_reset(void) | |
59 | { | |
60 | bool presence = 0; | |
61 | ||
62 | OWLOW; //drive_OW_low(); | |
63 | DelayUs(250); | |
64 | DelayUs(250); | |
65 | OWTRI; //float_OW(); // let it float high | |
66 | DelayUs(70); | |
67 | presence = OWREAD; //read_OW(); // now sample | |
68 | DelayUs(215); | |
69 | DelayUs(215); | |
70 | ||
71 | return ! presence; | |
72 | } | |
73 | ||
74 | void OW_write_bit(bool val) | |
75 | { | |
76 | #if 0 // Maxim dev note 2420 | |
77 | drive_OW_low(); | |
78 | DelayUs(3); | |
79 | if (val) float_OW(); | |
80 | DelayUs(60); | |
81 | float_OW(); | |
82 | DelayUs(2); | |
83 | #else | |
84 | OWLOW; | |
85 | NOP(); | |
86 | NOP(); | |
87 | // NOP(); // doc one for other delays | |
88 | if (val) OWTRI; | |
89 | DelayUs(60); | |
90 | OWTRI; | |
91 | NOP(); | |
92 | NOP(); | |
93 | #endif | |
94 | } | |
95 | ||
96 | bool OW_read_bit() | |
97 | { | |
98 | bool val; | |
99 | #if 0 /* Maxim dev note 2420 */ | |
100 | drive_OW_low(); | |
101 | DelayUs(6); | |
102 | float_OW(); | |
103 | DelayUs(4); | |
104 | val = read_OW(); | |
105 | DelayUs(50); | |
106 | #else | |
107 | OWLOW; | |
108 | // NOP(); | |
109 | NOP(); | |
110 | NOP(); | |
111 | NOP(); | |
112 | NOP(); | |
113 | NOP(); | |
114 | OWTRI; | |
115 | // NOP(); | |
116 | NOP(); | |
117 | NOP(); | |
118 | NOP(); | |
119 | val = read_OW(); | |
120 | DelayUs(50); | |
121 | ||
122 | #endif | |
123 | return val; | |
124 | } | |
125 | ||
126 | void OW_write_byte(unsigned char byte) | |
127 | { | |
128 | for (char i=8; i!=0; i--) | |
129 | { | |
130 | OW_write_bit( byte & 0x01 ); | |
131 | byte >>= 1; | |
132 | } | |
133 | } | |
134 | ||
135 | unsigned char OW_read_byte(void) | |
136 | { | |
137 | unsigned char byte = 0; | |
138 | for (char i=8; i!=0; i--) | |
139 | { | |
140 | byte >>= 1; | |
141 | if (OW_read_bit()) | |
142 | byte |= 0x80; | |
143 | ||
144 | } | |
145 | return byte; | |
146 | } | |
147 | ||
148 | static const unsigned char dscrc_table[] = { | |
149 | 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, | |
150 | 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, | |
151 | 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, | |
152 | 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, | |
153 | 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, | |
154 | 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, | |
155 | 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, | |
156 | 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, | |
157 | 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, | |
158 | 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, | |
159 | 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, | |
160 | 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, | |
161 | 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, | |
162 | 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, | |
163 | 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, | |
164 | 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53 | |
165 | }; | |
166 | ||
167 | unsigned char romid[8]; | |
168 | char LastDiscrepancy = 0; | |
169 | char LastFamilyDiscrepancy = 0; | |
170 | char LastDeviceFlag = false; | |
171 | unsigned char crc8; | |
172 | ||
173 | static unsigned char docrc8(unsigned char value) | |
174 | { | |
175 | crc8 = dscrc_table[crc8 ^ value]; | |
176 | return crc8; | |
177 | } | |
178 | ||
179 | /* enumerate the devices */ | |
180 | bool OW_search() | |
181 | { | |
182 | char id_bit_number = 1; | |
183 | char last_zero = 0; | |
184 | char rom_byte_number = 0; | |
185 | char search_result = 0; | |
186 | unsigned char rom_byte_mask = 1; | |
187 | unsigned char search_direction; | |
188 | ||
189 | crc8 = 0; | |
190 | ||
191 | // do not interrupt us | |
192 | int_disable(); | |
193 | ||
194 | // if the last call was not the last one | |
195 | if (!LastDeviceFlag) { | |
196 | if (!OW_reset()) | |
197 | { | |
198 | msg_write("Reset said nothing there.\r\n"); | |
199 | // reset the search | |
200 | LastDiscrepancy = 0; | |
201 | LastDeviceFlag = 0; | |
202 | LastFamilyDiscrepancy = 0; | |
203 | int_enable(); | |
204 | return 0; | |
205 | } | |
206 | ||
207 | // issue the search command | |
208 | OW_write_byte(0xF0); | |
209 | ||
210 | // loop to do the search | |
211 | do { | |
212 | // read a bit and its complement | |
213 | bool id_bit = OW_read_bit(); | |
214 | DelayUs(6); | |
215 | bool cmp_id_bit = OW_read_bit(); | |
216 | ||
217 | // check for no devices on bus | |
218 | if (id_bit && cmp_id_bit) { | |
219 | break; | |
220 | } | |
221 | ||
222 | if (id_bit != cmp_id_bit) { | |
223 | // all devices have a 0 here, or they all have a 1 | |
224 | search_direction = id_bit; | |
225 | } else { | |
226 | // both bits zero, so both 0 and 1 exist | |
227 | ||
228 | // if this discrepancy is before the Last Discrepancy | |
229 | // on a previous next then pick the same as last time | |
230 | if (id_bit_number < LastDiscrepancy) { | |
231 | search_direction = ((romid[rom_byte_number] & rom_byte_mask) > 0); | |
232 | } else { | |
233 | // if equal to last pick 1, if not then pick 0 | |
234 | search_direction = (id_bit_number == LastDiscrepancy); | |
235 | } | |
236 | ||
237 | // if 0 was picked then record its position in LastZero | |
238 | if (search_direction == 0) | |
239 | { | |
240 | last_zero = id_bit_number; | |
241 | // check for last discrepancy in family | |
242 | if (last_zero < 9) | |
243 | LastFamilyDiscrepancy = last_zero; | |
244 | } | |
245 | } | |
246 | ||
247 | // set or clear the bit in the ROM byte rom_byte_number | |
248 | // with mask rom_byte_mask | |
249 | if (search_direction == 1) | |
250 | romid[rom_byte_number] |= rom_byte_mask; | |
251 | else | |
252 | romid[rom_byte_number] &= ~rom_byte_mask; | |
253 | ||
254 | // serial number search direction write bit | |
255 | OW_write_bit(search_direction); | |
256 | ||
257 | // increment the byte counter id_bit_number | |
258 | // and shift the mask rom_byte_mask | |
259 | id_bit_number++; | |
260 | rom_byte_mask <<= 1; | |
261 | ||
262 | // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask | |
263 | if (rom_byte_mask == 0) | |
264 | { | |
265 | docrc8(romid[rom_byte_number]); // accumulate the CRC | |
266 | rom_byte_number++; | |
267 | rom_byte_mask = 1; | |
268 | } | |
269 | } while (rom_byte_number < 8); // loop until all rom bytes 0-7 | |
270 | } // end of not-last-device | |
271 | ||
272 | // if the search was succesful then | |
273 | if (!(id_bit_number < 65 || crc8 != 0)) | |
274 | { | |
275 | // search successful | |
276 | LastDiscrepancy = last_zero; | |
277 | ||
278 | // check for last device | |
279 | if (LastDiscrepancy == 0) | |
280 | LastDeviceFlag = true; | |
281 | ||
282 | search_result = true; | |
283 | } | |
284 | ||
285 | if (!search_result || !romid[0]) | |
286 | { | |
287 | LastDiscrepancy = 0; | |
288 | LastDeviceFlag = false; | |
289 | LastFamilyDiscrepancy = 0; | |
290 | search_result = false; | |
291 | } | |
292 | ||
293 | int_enable(); | |
294 | return search_result; | |
295 | } | |
296 | ||
297 | ||
298 | void OW_search_init() | |
299 | { | |
300 | LastDiscrepancy = 0; | |
301 | LastDeviceFlag = false; | |
302 | LastFamilyDiscrepancy = 0; | |
303 | ||
304 | for (int j=0; j<8; j++) romid[j]=0; | |
305 | } | |
306 | ||
307 | ||
308 | /* ask the (lone) device for its Serial number */ | |
309 | void OW_identify() | |
310 | { | |
311 | int_disable(); | |
312 | OW_reset(); | |
313 | // read ROM command | |
314 | OW_write_byte(0x33); | |
315 | for (int j=0; j<8; j++) | |
316 | romid[j] = OW_read_byte(); | |
317 | int_enable(); | |
318 | } | |
319 | ||
320 | /* is anyone parasite powered ? */ | |
321 | bool OW_parasite(void) | |
322 | { | |
323 | int_disable(); | |
324 | OW_reset(); | |
325 | OW_write_byte(0xCC); // skip the rom command | |
326 | OW_write_byte(0xB4); // are you parasite powered ? | |
327 | bool no = OW_read_bit(); | |
328 | int_enable(); | |
329 | return !no; | |
330 | } | |
331 | ||
332 | /* select a specific device, | |
333 | * if family==0 select all devices (skip rom) | |
334 | */ | |
335 | static void OW_select_id(void) | |
336 | { | |
337 | if (romid[0] == 0) { | |
338 | OW_write_byte(0xCC); // all devices for now | |
339 | } else { | |
340 | OW_write_byte(0x55); // match rom | |
341 | for (int8_t j=0; j<8; j++) { | |
342 | OW_write_byte(romid[j]); | |
343 | } | |
344 | } | |
345 | } | |
346 | ||
347 | ||
348 | /* read a memory block eg scratchpad 0xBE */ | |
349 | void OW_read_block(uint8_t code, uint8_t * data, uint8_t len) | |
350 | { | |
351 | int_disable(); | |
352 | OW_reset(); | |
353 | OW_select_id(); | |
354 | OW_write_byte(code); | |
355 | for (int8_t j=0; j<len; j++) | |
356 | data[j] = OW_read_byte(); | |
357 | int_enable(); | |
358 | } | |
359 | ||
360 | /* write a memory block to device, eg scratchpad 0x4E */ | |
361 | void OW_write_block(uint8_t code, uint8_t * data, uint8_t len) | |
362 | { | |
363 | int_disable(); | |
364 | OW_reset(); | |
365 | OW_select_id(); | |
366 | OW_write_byte(code); | |
367 | for (int8_t j=0; j<len; j++) { | |
368 | OW_write_byte(data[j]); | |
369 | } | |
370 | int_enable(); | |
371 | } | |
372 | ||
373 | ||
374 | // perform temperature conversion | |
375 | void OW_convert() | |
376 | { | |
377 | // first see if anyone is parasitic | |
378 | bool para = OW_parasite(); | |
379 | ||
380 | int_disable(); | |
381 | OW_reset(); // all command start with reset | |
382 | OW_select_id(); | |
383 | //OW_write_byte(0xCC); // all devices | |
384 | OW_write_byte(0x44); // convert | |
385 | if (para) { | |
386 | // hard high for 750mS | |
387 | OWHIGH; | |
388 | DelayUs(250000); | |
389 | DelayUs(250000); | |
390 | DelayUs(250000); | |
391 | DelayUs(250000); | |
392 | } else { | |
393 | // keep polling until its done | |
394 | // device will reply with 0 'pull low' whilst convert in progress | |
395 | do { | |
396 | DelayUs(1000); | |
397 | } while (!OW_read_bit()); | |
398 | } | |
399 | int_enable(); | |
400 | } | |
401 | ||
402 | /* Available commands :- | |
403 | * 33h - read rom (sends 8 bytes) | |
404 | * 55h - match rom (reads 8 bytes) | |
405 | * F0h - search rom (enumeration mode) | |
406 | * ECh - alarm search | |
407 | * CC - skip rom command | |
408 | * | |
409 | * followed by.... | |
410 | * 44h - convert temperature | |
411 | * 48h - copy scratchpad -> eeprom | |
412 | * 4Eh - write scratchpad (send 3 bytes ) | |
413 | * BEh - read scratchpad ( 8 bytes + crc) | |
414 | * B8h - recall EEPROM -> scratchpad | |
415 | * B4h - read power supply (read 1 bit) | |
416 | */ |