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 //---------------------------------------------------------------------------
29 // Minimal access routines for TINI internal one-wire bus patched together
30 // from Dallas example code (hence the copyright notice above).
32 // Kevin Vigor, 11/20/2000
39 /* The internal 1-wire bus is hooked to P3.5, a.k.a T1 */
40 /* The "activity" LED is also hooked to this line. */
41 #define INT_OW_PORT T1
43 // global variables for this module to hold search state information
44 static int LastDiscrepancy;
45 static int LastFamilyDiscrepancy;
46 static int LastDevice;
47 static unsigned char SerialNum[8];
49 //--------------------------------------------------------------------------
50 // Reset all of the devices on the 1-Wire Net and return the result.
52 // Returns: TRUE(1): presense pulse(s) detected, device(s) reset
53 // FALSE(0): no presense pulses detected
55 unsigned char owTouchReset(void)
59 /* Code stolen straight from appnote 126. */
60 INT_OW_PORT = 0; /* drive bus low. */
61 msDelay(480); /* sleep 480 ms */
62 INT_OW_PORT = 1; /* bus high. */
64 result = INT_OW_PORT; /* get presence detect pulse. */
70 //--------------------------------------------------------------------------
71 // Send 1 bit of communication to the 1-Wire Net and return the
72 // result 1 bit read from the 1-Wire Net. The parameter 'sendbit'
73 // least significant bit is used and the least significant bit
74 // of the result is the return bit.
76 // Returns: 0: 0 bit read from sendbit
77 // 1: 1 bit read from sendbit
79 unsigned char owTouchBit(unsigned char sendbit)
83 INT_OW_PORT = 0; /* start timeslot. */
86 INT_OW_PORT = sendbit; /* send bit out. */
88 result = INT_OW_PORT; /* sample result @ 10 ms. */
89 msDelay(50); /* Kill rest of slot. */
90 INT_OW_PORT = 1; /* timeslot done. */
91 msDelay(5); /* Just to make sure... */
96 //--------------------------------------------------------------------------
97 // Send 8 bits of communication to the 1-Wire Net and return the
98 // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte'
99 // least significant 8 bits are used and the least significant 8 bits
100 // of the result is the return byte.
102 // 'sendbyte' - 8 bits to send (least significant byte)
104 // Returns: 8 bytes read from sendbyte
106 unsigned char owTouchByte(unsigned char sendbyte)
109 unsigned char result = 0;
111 for (i = 0; i < 8; i++)
113 result |= (owTouchBit(sendbyte & 1) << i);
120 //--------------------------------------------------------------------------
121 // Send 8 bits of communication to the 1-Wire Net and verify that the
122 // 8 bits read from the 1-Wire Net is the same (write operation).
123 // The parameter 'sendbyte' least significant 8 bits are used.
125 // 'sendbyte' - 8 bits to send (least significant byte)
127 // Returns: TRUE: bytes written and echo was the same
128 // FALSE: echo was not the same
130 unsigned char owWriteByte(unsigned char sendbyte)
132 return (owTouchByte(sendbyte) == sendbyte) ? TRUE : FALSE;
135 //--------------------------------------------------------------------------
136 // Send 8 bits of read communication to the 1-Wire Net and and return the
137 // result 8 bits read from the 1-Wire Net.
139 // Returns: 8 bytes read from 1-Wire Net
141 unsigned char owReadByte(void)
143 return owTouchByte(0xFF);
146 //--------------------------------------------------------------------------
148 // Delay for at least 'len' ms
150 void msDelay(unsigned int len)
152 len; /* shut compiler up. */
161 orl a, r1 ; quick out for zero case.
165 cjne r0, #0, _sleep1msLoop
176 djnz r0, _sleep1msLoop ; 3 cycles x 1 = 3 cycles
177 ; 10 cycles per iter; we want 9.216, but more is better
179 djnz r1, _sleep1msLoop
185 //--------------------------------------------------------------------------
186 // The 'owBlock' transfers a block of data to and from the
187 // 1-Wire Net with an optional reset at the begining of communication.
188 // The result is returned in the same buffer.
190 // 'do_reset' - cause a owTouchReset to occure at the begining of
191 // communication TRUE(1) or not FALSE(0)
192 // 'tran_buf' - pointer to a block of unsigned
193 // chars of length 'TranferLength' that will be sent
195 // 'tran_len' - length in bytes to transfer
197 // Supported devices: all
199 // Returns: TRUE (1) : The optional reset returned a valid
200 // presence (do_reset == TRUE) or there
201 // was no reset required.
202 // FALSE (0): The reset did not return a valid prsence
203 // (do_reset == TRUE).
205 // The maximum tran_len is 64
207 unsigned char owBlock(unsigned char do_reset,
208 unsigned char *tran_buf,
209 unsigned char tran_len)
213 // check for a block too big
217 // check if need to do a owTouchReset first
224 // send and receive the buffer
225 for (i = 0; i < tran_len; i++)
226 tran_buf[i] = owTouchByte(tran_buf[i]);
231 //--------------------------------------------------------------------------
232 // The 'owFirst' finds the first device on the 1-Wire Net This function
233 // contains one parameter 'alarm_only'. When
234 // 'alarm_only' is TRUE (1) the find alarm command 0xEC is
235 // sent instead of the normal search command 0xF0.
236 // Using the find alarm command 0xEC will limit the search to only
237 // 1-Wire devices that are in an 'alarm' state.
239 // 'do_reset' - TRUE (1)
240 // perform reset before search.
241 // 'alarm_only' - TRUE (1) the find alarm command 0xEC is
242 // sent instead of the normal search command 0xF0
244 // Returns: TRUE (1) : when a 1-Wire device was found and it's
245 // Serial Number placed in the global SerialNum[portnum]
246 // FALSE (0): There are no devices on the 1-Wire Net.
248 unsigned char owFirst(unsigned char do_reset, unsigned char alarm_only)
250 // reset the search state
253 LastFamilyDiscrepancy = 0;
255 return owNext(do_reset,alarm_only);
258 //--------------------------------------------------------------------------
259 // The 'owNext' function does a general search. This function
260 // continues from the previos search state. The search state
261 // can be reset by using the 'owFirst' function.
262 // This function contains one parameter 'alarm_only'.
263 // When 'alarm_only' is TRUE (1) the find alarm command
264 // 0xEC is sent instead of the normal search command 0xF0.
265 // Using the find alarm command 0xEC will limit the search to only
266 // 1-Wire devices that are in an 'alarm' state.
268 // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not
269 // perform reset before search.
270 // 'alarm_only' - TRUE (1) the find alarm command 0xEC is
271 // sent instead of the normal search command 0xF0
273 // Returns: TRUE (1) : when a 1-Wire device was found and it's
274 // Serial Number placed in the global SerialNum[portnum]
275 // FALSE (0): when no new device was found. Either the
276 // last search was the last device or there
277 // are no devices on the 1-Wire Net.
279 unsigned char owNext(unsigned char do_reset, unsigned char alarm_only)
281 int bit_test, search_direction, bit_number;
282 int last_zero, serial_byte_number, next_result;
283 unsigned char serial_byte_mask;
284 unsigned char lastcrc8;
286 // initialize for search
289 serial_byte_number = 0;
290 serial_byte_mask = 1;
294 // if the last call was not the last one
297 // check if reset first is requested
301 // if there are no parts on 1-wire, return FALSE
306 LastFamilyDiscrepancy = 0;
311 // If finding alarming devices issue a different command
313 owWriteByte(0xEC); // issue the alarming search command
315 owWriteByte(0xF0); // issue the search command
317 // loop to do the search
320 // read a bit and its compliment
321 bit_test = owTouchBit(1) << 1;
322 bit_test |= owTouchBit(1);
324 // check for no devices on 1-wire
331 // all devices coupled have 0 or 1
334 search_direction = !(bit_test & 0x01); // bit write value for search
338 // if this discrepancy if before the Last Discrepancy
339 // on a previous next then pick the same as last time
340 if (bit_number < LastDiscrepancy)
341 search_direction = ((SerialNum[serial_byte_number] & serial_byte_mask) > 0);
343 // if equal to last pick 1, if not then pick 0
344 search_direction = (bit_number == LastDiscrepancy);
346 // if 0 was picked then record its position in LastZero
347 if (search_direction == 0)
348 last_zero = bit_number;
350 // check for Last discrepancy in family
352 LastFamilyDiscrepancy = last_zero;
355 // set or clear the bit in the SerialNum byte serial_byte_number
356 // with mask serial_byte_mask
357 if (search_direction == 1)
358 SerialNum[serial_byte_number] |= serial_byte_mask;
360 SerialNum[serial_byte_number] &= ~serial_byte_mask;
362 // serial number search direction write bit
363 owTouchBit(search_direction);
365 // increment the byte counter bit_number
366 // and shift the mask serial_byte_mask
368 serial_byte_mask <<= 1;
370 // if the mask is 0 then go to new SerialNum byte serial_byte_number
372 if (serial_byte_mask == 0)
374 lastcrc8 = docrc8(lastcrc8,SerialNum[serial_byte_number]); // accumulate the CRC
375 serial_byte_number++;
376 serial_byte_mask = 1;
380 while(serial_byte_number < 8); // loop until through all SerialNum bytes 0-7
382 // if the search was successful then
383 if (!((bit_number < 65) || lastcrc8))
385 // search successful so set LastDiscrepancy,LastDevice,next_result
386 LastDiscrepancy = last_zero;
387 LastDevice = (LastDiscrepancy == 0);
392 // if no device found then reset counters so next 'next' will be
394 if (!next_result || !SerialNum[0])
398 LastFamilyDiscrepancy = 0;
405 //--------------------------------------------------------------------------
406 // The 'owSerialNum' function either reads or sets the SerialNum buffer
407 // that is used in the search functions 'owFirst' and 'owNext'.
408 // This function contains two parameters, 'serialnum_buf' is a pointer
409 // to a buffer provided by the caller. 'serialnum_buf' should point to
410 // an array of 8 unsigned chars. The second parameter is a flag called
411 // 'do_read' that is TRUE (1) if the operation is to read and FALSE
412 // (0) if the operation is to set the internal SerialNum buffer from
413 // the data in the provided buffer.
415 // 'serialnum_buf' - buffer to that contains the serial number to set
416 // when do_read = FALSE (0) and buffer to get the serial
417 // number when do_read = TRUE (1).
418 // 'do_read' - flag to indicate reading (1) or setting (0) the current
421 void owSerialNum(unsigned char *serialnum_buf, unsigned char do_read)
425 // read the internal buffer and place in 'serialnum_buf'
428 for (i = 0; i < 8; i++)
430 serialnum_buf[i] = SerialNum[i];
433 // set the internal buffer from the data in 'serialnum_buf'
436 for (i = 0; i < 8; i++)
438 SerialNum[i] = serialnum_buf[i];