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 // owTranU.C - Transport functions for 1-Wire Net
28 // using the DS2480 (U) serial interface chip.
32 // History: 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 Write_Scratchpad(int,uchar *,int,int);
42 static int Copy_Scratchpad(int,int,int);
44 //--------------------------------------------------------------------------
45 // The 'owBlock' transfers a block of data to and from the
46 // 1-Wire Net with an optional reset at the begining of communication.
47 // The result is returned in the same buffer.
49 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
50 // indicate the symbolic port number.
51 // 'do_reset' - cause a owTouchReset to occure at the begining of
52 // communication TRUE(1) or not FALSE(0)
53 // 'tran_buf' - pointer to a block of unsigned
54 // chars of length 'tran_len' that will be sent
56 // 'tran_len' - length in bytes to transfer
58 // Supported devices: all
60 // Returns: TRUE (1) : The optional reset returned a valid
61 // presence (do_reset == TRUE) or there
62 // was no reset required.
63 // FALSE (0): The reset did not return a valid prsence
64 // (do_reset == TRUE).
66 // The maximum tran_length is 64
68 int owBlock(int portnum, int do_reset, uchar *tran_buf, int tran_len)
70 uchar sendpacket[150];
73 // check for a block too big
77 // check if need to do a owTouchReset first
80 if (!owTouchReset(portnum))
84 // construct the packet to send to the DS2480
85 // check if correct mode
86 if (UMode[portnum] != MODSEL_DATA)
88 UMode[portnum] = MODSEL_DATA;
89 sendpacket[sendlen++] = MODE_DATA;
92 // add the bytes to send
94 for (i = 0; i < tran_len; i++)
96 sendpacket[sendlen++] = tran_buf[i];
98 // check for duplication of data that looks like COMMAND mode
99 if (tran_buf[i] == MODE_COMMAND)
100 sendpacket[sendlen++] = tran_buf[i];
107 if (WriteCOM(portnum,sendlen,sendpacket))
109 // read back the response
110 if (ReadCOM(portnum,tran_len,tran_buf) == tran_len)
114 // an error occured so re-sync with DS2480
115 DS2480Detect(portnum);
120 //--------------------------------------------------------------------------
121 // Read a Universal Data Packet from a standard NVRAM iButton
122 // and return it in the provided buffer. The page that the
123 // packet resides on is 'start_page'. Note that this function is limited
124 // to single page packets. The buffer 'read_buf' must be at least
127 // The Universal Data Packet always start on page boundaries but
128 // can end anywhere. The length is the number of data bytes not
129 // including the length byte and the CRC16 bytes. There is one
130 // length byte. The CRC16 is first initialized to the starting
131 // page number. This provides a check to verify the page that
132 // was intended is being read. The CRC16 is then calculated over
133 // the length and data bytes. The CRC16 is then inverted and stored
134 // low byte first followed by the high byte.
136 // Supported devices: DS1992, DS1993, DS1994, DS1995, DS1996, DS1982,
137 // DS1985, DS1986, DS2407, and DS1971.
139 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
140 // indicate the symbolic port number.
141 // 'do_access' - flag to indicate if an 'owAccess' should be
142 // peformed at the begining of the read. This may
143 // be FALSE (0) if the previous call was to read the
144 // previous page (start_page-1).
145 // 'start_page' - page number to start the read from
146 // 'read_buf' - pointer to a location to store the data read
148 // Returns: >=0 success, number of data bytes in the buffer
149 // -1 failed to read a valid UDP
152 int owReadPacketStd(int portnum, int do_access, int start_page, uchar *read_buf)
154 int i,length,sendlen=0,head_len=0;
155 uchar sendpacket[50];
158 // check if access header is done
159 // (only use if in sequention read with one access at begining)
163 sendpacket[sendlen++] = 0x55;
164 for (i = 0; i < 8; i++)
165 sendpacket[sendlen++] = SerialNum[portnum][i];
166 // read memory command
167 sendpacket[sendlen++] = 0xF0;
168 // write the target address
169 sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
170 sendpacket[sendlen++] = (start_page >> 3);
171 // check for DS1982 exception (redirection byte)
172 if (SerialNum[portnum][0] == 0x09)
173 sendpacket[sendlen++] = 0xFF;
174 // record the header length
177 // read the entire page length byte
178 for (i = 0; i < 32; i++)
179 sendpacket[sendlen++] = 0xFF;
181 // send/recieve the transfer buffer
182 if (owBlock(portnum,do_access,sendpacket,sendlen))
184 // seed crc with page number
185 setcrc16(portnum,(ushort)start_page);
187 // attempt to read UDP from sendpacket
188 length = sendpacket[head_len];
189 docrc16(portnum,(ushort)length);
191 // verify length is not too large
194 // loop to read packet including CRC
195 for (i = 0; i < length; i++)
197 read_buf[i] = sendpacket[i+1+head_len];
198 docrc16(portnum,read_buf[i]);
201 // read and compute the CRC16
202 docrc16(portnum,sendpacket[i+1+head_len]);
203 lastcrc16 = docrc16(portnum,sendpacket[i+2+head_len]);
205 // verify the CRC16 is correct
206 if (lastcrc16 == 0xB001)
207 return length; // return number of byte in record
211 // failed block or incorrect CRC
215 //--------------------------------------------------------------------------
216 // Write a Universal Data Packet onto a standard NVRAM 1-Wire device
217 // on page 'start_page'. This function is limited to UDPs that
218 // fit on one page. The data to write is provided as a buffer
219 // 'write_buf' with a length 'write_len'.
221 // The Universal Data Packet always start on page boundaries but
222 // can end anywhere. The length is the number of data bytes not
223 // including the length byte and the CRC16 bytes. There is one
224 // length byte. The CRC16 is first initialized to the starting
225 // page number. This provides a check to verify the page that
226 // was intended is being read. The CRC16 is then calculated over
227 // the length and data bytes. The CRC16 is then inverted and stored
228 // low byte first followed by the high byte.
230 // Supported devices: is_eprom=0
231 // DS1992, DS1993, DS1994, DS1995, DS1996
232 // is_eprom=1, crc_type=0(CRC8)
234 // is_eprom=1, crc_type=1(CRC16)
235 // DS1985, DS1986, DS2407
237 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
238 // indicate the symbolic port number.
239 // 'start_page' - page number to write packet to
240 // 'write_buf' - pointer to buffer containing data to write
241 // 'write_len' - number of data byte in write_buf
242 // 'is_eprom' - flag set if device is an EPROM (1 EPROM, 0 NVRAM)
243 // 'crc_type' - if is_eprom=1 then indicates CRC type
246 // Returns: TRUE(1) success, packet written
247 // FALSE(0) failure to write, contact lost or device locked
250 int owWritePacketStd(int portnum, int start_page, uchar *write_buf,
251 int write_len, int is_eprom, int crc_type)
253 uchar construct_buffer[32];
254 int i,buffer_cnt=0,start_address,do_access;
257 // check to see if data too long to fit on device
261 // seed crc with page number
262 setcrc16(portnum,(ushort)start_page);
265 construct_buffer[buffer_cnt++] = (uchar)(write_len);
266 docrc16(portnum,(ushort)write_len);
268 // fill in the data to write
269 for (i = 0; i < write_len; i++)
271 lastcrc16 = docrc16(portnum,write_buf[i]);
272 construct_buffer[buffer_cnt++] = write_buf[i];
276 construct_buffer[buffer_cnt++] = (uchar)(~(lastcrc16 & 0xFF));
277 construct_buffer[buffer_cnt++] = (uchar)(~((lastcrc16 & 0xFF00) >> 8));
279 // check if not EPROM
283 if (!Write_Scratchpad(portnum,construct_buffer,start_page,buffer_cnt))
286 // copy the scratchpad
287 if (!Copy_Scratchpad(portnum,start_page,buffer_cnt))
290 // copy scratch pad was good then success
296 // calculate the start address
297 start_address = ((start_page >> 3) << 8) | ((start_page << 5) & 0xFF);
299 // loop to program each byte
300 for (i = 0; i < buffer_cnt; i++)
302 if (owProgramByte(portnum,construct_buffer[i], start_address + i,
303 0x0F, crc_type, do_access) != construct_buffer[i])
311 //--------------------------------------------------------------------------
312 // Write a byte to an EPROM 1-Wire device.
314 // Supported devices: crc_type=0(CRC8)
317 // DS1985, DS1986, DS2407
319 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
320 // indicate the symbolic port number.
321 // 'write_byte' - byte to program
322 // 'addr' - address of byte to program
323 // 'write_cmd' - command used to write (0x0F reg mem, 0x55 status)
324 // 'crc_type' - CRC used (0 CRC8, 1 CRC16)
325 // 'do_access' - Flag to access device for each byte
326 // (0 skip access, 1 do the access)
327 // WARNING, only use do_access=0 if programing the NEXT
328 // byte immediatly after the previous byte.
330 // Returns: >=0 success, this is the resulting byte from the program
332 // -1 error, device not connected or program pulse voltage
335 int owProgramByte(int portnum, int write_byte, int addr, int write_cmd,
336 int crc_type, int do_access)
341 // optionally access the device
344 if (!owAccess(portnum))
347 // send the write command
348 if (!owWriteByte(portnum,write_cmd))
352 if (!owWriteByte(portnum,addr & 0xFF))
354 if (!owWriteByte(portnum,addr >> 8))
358 // send the data to write
359 if (!owWriteByte(portnum,write_byte))
369 docrc8(portnum,(uchar)write_cmd);
370 docrc8(portnum,(uchar)(addr & 0xFF));
371 docrc8(portnum,(uchar)(addr >> 8));
374 setcrc8(portnum,(uchar)(addr & 0xFF));
376 docrc8(portnum,(uchar)write_byte);
377 // read and calculate the read crc
378 lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum));
379 // crc should now be 0x00
389 docrc16(portnum,(ushort)write_cmd);
390 docrc16(portnum,(ushort)(addr & 0xFF));
391 docrc16(portnum,(ushort)(addr >> 8));
394 setcrc16(portnum,(ushort)addr);
395 docrc16(portnum,(ushort)write_byte);
396 // read and calculate the read crc
397 docrc16(portnum,(ushort)owReadByte(portnum));
398 lastcrc16 = docrc16(portnum,(ushort)owReadByte(portnum));
399 // crc should now be 0xB001
400 if (lastcrc16 != 0xB001)
404 // send the program pulse
405 if (!owProgramPulse(portnum))
408 // read back and return the resulting byte
409 return owReadByte(portnum);
412 //--------------------------------------------------------------------------
413 // Write the scratchpad of a standard NVRam device such as the DS1992,3,4
414 // and verify its contents.
416 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
417 // indicate the symbolic port number.
418 // 'write_buf' - pointer to buffer containing data to write
419 // 'start_page' - page number to write packet to
420 // 'write_len' - number of data byte in write_buf
422 // Returns: TRUE(1) success, the data was written and verified
423 // FALSE(0) failure, the data could not be written
426 int Write_Scratchpad(int portnum, uchar *write_buf, int start_page, int write_len)
429 uchar sendpacket[50];
432 sendpacket[sendlen++] = 0x55;
433 for (i = 0; i < 8; i++)
434 sendpacket[sendlen++] = SerialNum[portnum][i];
435 // write scratchpad command
436 sendpacket[sendlen++] = 0x0F;
437 // write the target address
438 sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
439 sendpacket[sendlen++] = (start_page >> 3);
441 // write packet bytes
442 for (i = 0; i < write_len; i++)
443 sendpacket[sendlen++] = write_buf[i];
445 // send/recieve the transfer buffer
446 if (owBlock(portnum,TRUE,sendpacket,sendlen))
448 // now attempt to read back to check
451 sendpacket[sendlen++] = 0x55;
452 for (i = 0; i < 8; i++)
453 sendpacket[sendlen++] = SerialNum[portnum][i];
454 // read scratchpad command
455 sendpacket[sendlen++] = 0xAA;
456 // read the target address, offset and data
457 for (i = 0; i < (write_len + 3); i++)
458 sendpacket[sendlen++] = 0xFF;
460 // send/recieve the transfer buffer
461 if (owBlock(portnum,TRUE,sendpacket,sendlen))
463 // check address and offset of scratchpad read
464 if ((sendpacket[10] != (int)((start_page << 5) & 0xFF)) ||
465 (sendpacket[11] != (int)(start_page >> 3)) ||
466 (sendpacket[12] != (int)(write_len - 1)))
469 // verify each data byte
470 for (i = 0; i < write_len; i++)
471 if (sendpacket[i+13] != write_buf[i])
474 // must have verified
479 // failed a block tranfer
483 //--------------------------------------------------------------------------
484 // Copy the contents of the scratchpad to its intended nv ram page. The
485 // page and length of the data is needed to build the authorization bytes
488 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
489 // indicate the symbolic port number.
490 // 'start_page' - page number to write packet to
491 // 'write_len' - number of data bytes that are being copied
493 // Returns: TRUE(1) success
496 int Copy_Scratchpad(int portnum, int start_page, int write_len)
499 uchar sendpacket[50];
502 sendpacket[sendlen++] = 0x55;
503 for (i = 0; i < 8; i++)
504 sendpacket[sendlen++] = SerialNum[portnum][i];
505 // copy scratchpad command
506 sendpacket[sendlen++] = 0x55;
507 // write the target address
508 sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
509 sendpacket[sendlen++] = (start_page >> 3);
510 sendpacket[sendlen++] = write_len - 1;
512 sendpacket[sendlen++] = 0xFF;
514 // send/recieve the transfer buffer
515 if (owBlock(portnum,TRUE,sendpacket,sendlen))
517 // check address and offset of scratchpad read
518 if ((sendpacket[10] != (int)((start_page << 5) & 0xFF)) ||
519 (sendpacket[11] != (int)(start_page >> 3)) ||
520 (sendpacket[12] != (int)(write_len - 1)) ||
521 (sendpacket[13] & 0xF0))
527 // failed a block tranfer