1 //---------------------------------------------------------------------------
2 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
18 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
22 // Except as contained in this notice, the name of Dallas Semiconductor
23 // shall not be used except as stated in the Dallas Semiconductor
25 //---------------------------------------------------------------------------
27 // owNetU.C - Network functions for 1-Wire Net devices
28 // using the DS2480/DS2480B (U) serial interface chip.
32 // 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
33 // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for
41 static int bitacc(int,int,int,uchar *);
44 uchar SerialNum[MAX_PORTNUM][8];
46 // local variables for this module to hold search state information
47 static int LastDiscrepancy[MAX_PORTNUM];
48 static int LastFamilyDiscrepancy[MAX_PORTNUM];
49 static int LastDevice[MAX_PORTNUM];
51 //--------------------------------------------------------------------------
52 // The 'owFirst' finds the first device on the 1-Wire Net This function
53 // contains one parameter 'alarm_only'. When
54 // 'alarm_only' is TRUE (1) the find alarm command 0xEC is
55 // sent instead of the normal search command 0xF0.
56 // Using the find alarm command 0xEC will limit the search to only
57 // 1-Wire devices that are in an 'alarm' state.
59 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
60 // indicate the symbolic port number.
61 // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not
62 // perform reset before search.
63 // 'alarm_only' - TRUE (1) the find alarm command 0xEC is
64 // sent instead of the normal search command 0xF0
66 // Returns: TRUE (1) : when a 1-Wire device was found and it's
67 // Serial Number placed in the global SerialNum
68 // FALSE (0): There are no devices on the 1-Wire Net.
70 int owFirst(int portnum, int do_reset, int alarm_only)
72 // reset the search state
73 LastDiscrepancy[portnum] = 0;
74 LastDevice[portnum] = FALSE;
75 LastFamilyDiscrepancy[portnum] = 0;
77 return owNext(portnum, do_reset, alarm_only);
80 //--------------------------------------------------------------------------
81 // The 'owNext' function does a general search. This function
82 // continues from the previos search state. The search state
83 // can be reset by using the 'owFirst' function.
84 // This function contains one parameter 'alarm_only'.
85 // When 'alarm_only' is TRUE (1) the find alarm command
86 // 0xEC is sent instead of the normal search command 0xF0.
87 // Using the find alarm command 0xEC will limit the search to only
88 // 1-Wire devices that are in an 'alarm' state.
90 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
91 // OpenCOM to indicate the port number.
92 // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not
93 // perform reset before search.
94 // 'alarm_only' - TRUE (1) the find alarm command 0xEC is
95 // sent instead of the normal search command 0xF0
97 // Returns: TRUE (1) : when a 1-Wire device was found and it's
98 // Serial Number placed in the global SerialNum
99 // FALSE (0): when no new device was found. Either the
100 // last search was the last device or there
101 // are no devices on the 1-Wire Net.
103 int owNext(int portnum, int do_reset, int alarm_only)
105 int i,tmp_last_desc,pos;
106 uchar tmp_serial_num[8];
107 uchar readbuffer[20],sendpacket[40];
111 // if the last call was the last one
112 if (LastDevice[portnum])
115 LastDiscrepancy[portnum] = 0;
116 LastDevice[portnum] = FALSE;
117 LastFamilyDiscrepancy[portnum] = 0;
121 // check if reset first is requested
125 // if there are no parts on 1-wire, return FALSE
126 if (!owTouchReset(portnum))
129 LastDiscrepancy[portnum] = 0;
130 LastFamilyDiscrepancy[portnum] = 0;
135 // build the command stream
136 // call a function that may add the change mode command to the buff
137 // check if correct mode
138 if (UMode[portnum] != MODSEL_DATA)
140 UMode[portnum] = MODSEL_DATA;
141 sendpacket[sendlen++] = MODE_DATA;
146 sendpacket[sendlen++] = 0xEC; // issue the alarming search command
148 sendpacket[sendlen++] = 0xF0; // issue the search command
150 // change back to command mode
151 UMode[portnum] = MODSEL_COMMAND;
152 sendpacket[sendlen++] = MODE_COMMAND;
155 sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHON | USpeed[portnum]);
157 // change back to data mode
158 UMode[portnum] = MODSEL_DATA;
159 sendpacket[sendlen++] = MODE_DATA;
161 // set the temp Last Descrep to none
162 tmp_last_desc = 0xFF;
164 // add the 16 bytes of the search
166 for (i = 0; i < 16; i++)
167 sendpacket[sendlen++] = 0;
169 // only modify bits if not the first search
170 if (LastDiscrepancy[portnum] != 0xFF)
172 // set the bits in the added buffer
173 for (i = 0; i < 64; i++)
175 // before last discrepancy
176 if (i < (LastDiscrepancy[portnum] - 1))
177 bitacc(WRITE_FUNCTION,
178 bitacc(READ_FUNCTION,0,i,&SerialNum[portnum][0]),
181 // at last discrepancy
182 else if (i == (LastDiscrepancy[portnum] - 1))
183 bitacc(WRITE_FUNCTION,1,
186 // after last discrepancy so leave zeros
190 // change back to command mode
191 UMode[portnum] = MODSEL_COMMAND;
192 sendpacket[sendlen++] = MODE_COMMAND;
195 sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed[portnum]);
201 if (WriteCOM(portnum,sendlen,sendpacket))
203 // read back the 1 byte response
204 if (ReadCOM(portnum,17,readbuffer) == 17)
206 // interpret the bit stream
207 for (i = 0; i < 64; i++)
209 // get the SerialNum bit
210 bitacc(WRITE_FUNCTION,
211 bitacc(READ_FUNCTION,0,(short)(i * 2 + 1),&readbuffer[1]),
214 // check LastDiscrepancy
215 if ((bitacc(READ_FUNCTION,0,(short)(i * 2),&readbuffer[1]) == 1) &&
216 (bitacc(READ_FUNCTION,0,(short)(i * 2 + 1),&readbuffer[1]) == 0))
218 tmp_last_desc = i + 1;
219 // check LastFamilyDiscrepancy
221 LastFamilyDiscrepancy[portnum] = i + 1;
227 for (i = 0; i < 8; i++)
228 lastcrc8 = docrc8(portnum,tmp_serial_num[i]);
231 if ((lastcrc8 != 0) || (LastDiscrepancy[portnum] == 63) || (tmp_serial_num[0] == 0))
233 // error during search
235 LastDiscrepancy[portnum] = 0;
236 LastDevice[portnum] = FALSE;
237 LastFamilyDiscrepancy[portnum] = 0;
244 if ((tmp_last_desc == LastDiscrepancy[portnum]) || (tmp_last_desc == 0xFF))
245 LastDevice[portnum] = TRUE;
247 // copy the SerialNum to the buffer
248 for (i = 0; i < 8; i++)
249 SerialNum[portnum][i] = tmp_serial_num[i];
252 LastDiscrepancy[portnum] = tmp_last_desc;
258 // an error occured so re-sync with DS2480
259 DS2480Detect(portnum);
262 LastDiscrepancy[portnum] = 0;
263 LastDevice[portnum] = FALSE;
264 LastFamilyDiscrepancy[portnum] = 0;
269 //--------------------------------------------------------------------------
270 // The 'owSerialNum' function either reads or sets the SerialNum buffer
271 // that is used in the search functions 'owFirst' and 'owNext'.
272 // This function contains two parameters, 'serialnum_buf' is a pointer
273 // to a buffer provided by the caller. 'serialnum_buf' should point to
274 // an array of 8 unsigned chars. The second parameter is a flag called
275 // 'do_read' that is TRUE (1) if the operation is to read and FALSE
276 // (0) if the operation is to set the internal SerialNum buffer from
277 // the data in the provided buffer.
279 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
280 // OpenCOM to indicate the port number.
281 // 'serialnum_buf' - buffer to that contains the serial number to set
282 // when do_read = FALSE (0) and buffer to get the serial
283 // number when do_read = TRUE (1).
284 // 'do_read' - flag to indicate reading (1) or setting (0) the current
287 void owSerialNum(int portnum, uchar *serialnum_buf, int do_read)
291 // read the internal buffer and place in 'serialnum_buf'
294 for (i = 0; i < 8; i++)
295 serialnum_buf[i] = SerialNum[portnum][i];
297 // set the internal buffer from the data in 'serialnum_buf'
300 for (i = 0; i < 8; i++)
301 SerialNum[portnum][i] = serialnum_buf[i];
305 //--------------------------------------------------------------------------
306 // Setup the search algorithm to find a certain family of devices
307 // the next time a search function is called 'owNext'.
309 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
310 // OpenCOM to indicate the port number.
311 // 'search_family' - family code type to set the search algorithm to find
314 void owFamilySearchSetup(int portnum, int search_family)
318 // set the search state to find search_family type devices
319 SerialNum[portnum][0] = (uchar)search_family;
320 for (i = 1; i < 8; i++)
321 SerialNum[portnum][i] = 0;
322 LastDiscrepancy[portnum] = 64;
323 LastDevice[portnum] = FALSE;
326 //--------------------------------------------------------------------------
327 // Set the current search state to skip the current family code.
329 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
330 // OpenCOM to indicate the port number.
332 void owSkipFamily(int portnum)
334 // set the Last discrepancy to last family discrepancy
335 LastDiscrepancy[portnum] = LastFamilyDiscrepancy[portnum];
337 // check for end of list
338 if (LastDiscrepancy[portnum] == 0)
339 LastDevice[portnum] = TRUE;
342 //--------------------------------------------------------------------------
343 // The 'owAccess' function resets the 1-Wire and sends a MATCH Serial
344 // Number command followed by the current SerialNum code. After this
345 // function is complete the 1-Wire device is ready to accept device-specific
348 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
349 // OpenCOM to indicate the port number.
351 // Returns: TRUE (1) : reset indicates present and device is ready
353 // FALSE (0): reset does not indicate presence or echos 'writes'
356 int owAccess(int portnum)
362 if (owTouchReset(portnum))
364 // create a buffer to use with block function
365 // match Serial Number command 0x55
366 sendpacket[0] = 0x55;
368 for (i = 1; i < 9; i++)
369 sendpacket[i] = SerialNum[portnum][i-1];
371 // send/recieve the transfer buffer
372 if (owBlock(portnum,FALSE,sendpacket,9))
374 // verify that the echo of the writes was correct
375 for (i = 1; i < 9; i++)
376 if (sendpacket[i] != SerialNum[portnum][i-1])
378 if (sendpacket[0] != 0x55)
385 // reset or match echo failed
389 //----------------------------------------------------------------------
390 // The function 'owVerify' verifies that the current device
391 // is in contact with the 1-Wire Net.
392 // Using the find alarm command 0xEC will verify that the device
393 // is in contact with the 1-Wire Net and is in an 'alarm' state.
395 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
396 // OpenCOM to indicate the port number.
397 // 'alarm_only' - TRUE (1) the find alarm command 0xEC
398 // is sent instead of the normal search
401 // Returns: TRUE (1) : when the 1-Wire device was verified
402 // to be on the 1-Wire Net
403 // with alarm_only == FALSE
404 // or verified to be on the 1-Wire Net
405 // AND in an alarm state when
406 // alarm_only == TRUE.
407 // FALSE (0): the 1-Wire device was not on the
408 // 1-Wire Net or if alarm_only
409 // == TRUE, the device may be on the
410 // 1-Wire Net but in a non-alarm state.
412 int owVerify(int portnum, int alarm_only)
414 int i,sendlen=0,goodbits=0,cnt=0,s,tst;
415 uchar sendpacket[50];
417 // construct the search rom
419 sendpacket[sendlen++] = 0xEC; // issue the alarming search command
421 sendpacket[sendlen++] = 0xF0; // issue the search command
422 // set all bits at first
423 for (i = 1; i <= 24; i++)
424 sendpacket[sendlen++] = 0xFF;
425 // now set or clear apropriate bits for search
426 for (i = 0; i < 64; i++)
427 bitacc(WRITE_FUNCTION,bitacc(READ_FUNCTION,0,i,&SerialNum[portnum][0]),(int)((i+1)*3-1),&sendpacket[1]);
429 // send/recieve the transfer buffer
430 if (owBlock(portnum,TRUE,sendpacket,sendlen))
432 // check results to see if it was a success
433 for (i = 0; i < 192; i += 3)
435 tst = (bitacc(READ_FUNCTION,0,i,&sendpacket[1]) << 1) |
436 bitacc(READ_FUNCTION,0,(int)(i+1),&sendpacket[1]);
438 s = bitacc(READ_FUNCTION,0,cnt++,&SerialNum[portnum][0]);
440 if (tst == 0x03) // no device on line
442 goodbits = 0; // number of good bits set to zero
446 if (((s == 0x01) && (tst == 0x02)) ||
447 ((s == 0x00) && (tst == 0x01)) ) // correct bit
448 goodbits++; // count as a good bit
451 // check too see if there were enough good bits to be successful
456 // block fail or device not present
460 //----------------------------------------------------------------------
461 // Perform a overdrive MATCH command to select the 1-Wire device with
462 // the address in the ID data register.
464 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
465 // OpenCOM to indicate the port number.
467 // Returns: TRUE: If the device is present on the 1-Wire Net and
468 // can do overdrive then the device is selected.
469 // FALSE: Device is not present or not capable of overdrive.
471 // *Note: This function could be converted to send DS2480
472 // commands in one packet.
474 int owOverdriveAccess(int portnum)
477 int i, bad_echo = FALSE;
479 // make sure normal level
480 owLevel(portnum,MODE_NORMAL);
482 // force to normal communication speed
483 owSpeed(portnum,MODE_NORMAL);
485 // call the 1-Wire Net reset function
486 if (owTouchReset(portnum))
488 // send the match command 0x69
489 if (owWriteByte(portnum,0x69))
491 // switch to overdrive communication speed
492 owSpeed(portnum,MODE_OVERDRIVE);
494 // create a buffer to use with block function
496 for (i = 0; i < 8; i++)
497 sendpacket[i] = SerialNum[portnum][i];
499 // send/recieve the transfer buffer
500 if (owBlock(portnum,FALSE,sendpacket,8))
502 // verify that the echo of the writes was correct
503 for (i = 0; i < 8; i++)
504 if (sendpacket[i] != SerialNum[portnum][i])
506 // if echo ok then success
513 // failure, force back to normal communication speed
514 owSpeed(portnum,MODE_NORMAL);
519 //--------------------------------------------------------------------------
520 // Bit utility to read and write a bit in the buffer 'buf'.
522 // 'op' - operation (1) to set and (0) to read
523 // 'state' - set (1) or clear (0) if operation is write (1)
524 // 'loc' - bit number location to read or write
525 // 'buf' - pointer to array of bytes that contains the bit
528 // Returns: 1 if operation is set (1)
529 // 0/1 state of bit number 'loc' if operation is reading
531 int bitacc(int op, int state, int loc, uchar *buf)
536 nbit = loc - (nbyt * 8);
538 if (op == WRITE_FUNCTION)
541 buf[nbyt] |= (0x01 << nbit);
543 buf[nbyt] &= ~(0x01 << nbit);
548 return ((buf[nbyt] >> nbit) & 0x01);