Initial import of onewire-to-usb bridge
[onewire] / onewire.c
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  */