Initial import of onewire-to-usb bridge
[onewire] / onewire.c
CommitLineData
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
24inline void drive_OW_low(void)
25{
26 PORTAbits.RA5 = 0;
27 TRISAbits.TRISA5 = 0;
28}
29
30inline void drive_OW_high(void)
31{
32 PORTAbits.RA5 = 1;
33 TRISAbits.TRISA5 = 0;
34}
35
36inline void float_OW(void)
37{
38 TRISAbits.TRISA5 = 1;
39}
40
41inline bool read_OW(void)
42{
43 TRISAbits.TRISA5 = 1;
44 return PORTAbits.RA5;
45}
46
47
48/* start the 1-Wire bus
49 *
50 */
51void OW_start(void)
52{
53 //drive_OW_high();
54 float_OW();
55}
56
57/* reset the bus, test for presence signal */
58bool 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
74void 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
96bool 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
126void 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
135unsigned 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
148static 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
167unsigned char romid[8];
168char LastDiscrepancy = 0;
169char LastFamilyDiscrepancy = 0;
170char LastDeviceFlag = false;
171unsigned char crc8;
172
173static unsigned char docrc8(unsigned char value)
174{
175 crc8 = dscrc_table[crc8 ^ value];
176 return crc8;
177}
178
179/* enumerate the devices */
180bool 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
298void 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 */
309void 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 ? */
321bool 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 */
335static 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 */
349void 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 */
361void 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
375void 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 */