1 #define DEBUG_OW_TRNU 0
5 //---------------------------------------------------------------------------
6 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included
16 // in all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
22 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 // OTHER DEALINGS IN THE SOFTWARE.
26 // Except as contained in this notice, the name of Dallas Semiconductor
27 // shall not be used except as stated in the Dallas Semiconductor
29 //---------------------------------------------------------------------------
31 // owTranU.C - Transport functions for 1-Wire Net
32 // using the DS2480 (U) serial interface chip.
36 // History: 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
37 // 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for
45 static int Write_Scratchpad(int,uchar *,int,int);
46 static int Copy_Scratchpad(int,int,int);
48 //--------------------------------------------------------------------------
49 // The 'owBlock' transfers a block of data to and from the
50 // 1-Wire Net with an optional reset at the begining of communication.
51 // The result is returned in the same buffer.
53 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
54 // indicate the symbolic port number.
55 // 'do_reset' - cause a owTouchReset to occure at the begining of
56 // communication TRUE(1) or not FALSE(0)
57 // 'tran_buf' - pointer to a block of unsigned
58 // chars of length 'tran_len' that will be sent
60 // 'tran_len' - length in bytes to transfer
62 // Supported devices: all
64 // Returns: TRUE (1) : The optional reset returned a valid
65 // presence (do_reset == TRUE) or there
66 // was no reset required.
67 // FALSE (0): The reset did not return a valid prsence
68 // (do_reset == TRUE).
70 // The maximum tran_length is 64
72 int owBlock(int portnum, int do_reset, uchar *tran_buf, int tran_len)
74 uchar sendpacket[150];
77 // check for a block too big
81 // check if need to do a owTouchReset first
84 if (!owTouchReset(portnum))
88 // construct the packet to send to the DS2480
89 // check if correct mode
90 if (UMode[portnum] != MODSEL_DATA)
92 UMode[portnum] = MODSEL_DATA;
93 sendpacket[sendlen++] = MODE_DATA;
96 // add the bytes to send
98 for (i = 0; i < tran_len; i++)
100 sendpacket[sendlen++] = tran_buf[i];
102 // check for duplication of data that looks like COMMAND mode
103 if (tran_buf[i] == MODE_COMMAND)
104 sendpacket[sendlen++] = tran_buf[i];
111 if (WriteCOM(portnum,sendlen,sendpacket))
113 // read back the response
114 if (ReadCOM(portnum,tran_len,tran_buf) == tran_len) {
119 // an error occured so re-sync with DS2480
120 DS2480Detect(portnum);
125 //--------------------------------------------------------------------------
126 // Read a Universal Data Packet from a standard NVRAM iButton
127 // and return it in the provided buffer. The page that the
128 // packet resides on is 'start_page'. Note that this function is limited
129 // to single page packets. The buffer 'read_buf' must be at least
132 // The Universal Data Packet always start on page boundaries but
133 // can end anywhere. The length is the number of data bytes not
134 // including the length byte and the CRC16 bytes. There is one
135 // length byte. The CRC16 is first initialized to the starting
136 // page number. This provides a check to verify the page that
137 // was intended is being read. The CRC16 is then calculated over
138 // the length and data bytes. The CRC16 is then inverted and stored
139 // low byte first followed by the high byte.
141 // Supported devices: DS1992, DS1993, DS1994, DS1995, DS1996, DS1982,
142 // DS1985, DS1986, DS2407, and DS1971.
144 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
145 // indicate the symbolic port number.
146 // 'do_access' - flag to indicate if an 'owAccess' should be
147 // peformed at the begining of the read. This may
148 // be FALSE (0) if the previous call was to read the
149 // previous page (start_page-1).
150 // 'start_page' - page number to start the read from
151 // 'read_buf' - pointer to a location to store the data read
153 // Returns: >=0 success, number of data bytes in the buffer
154 // -1 failed to read a valid UDP
157 int owReadPacketStd(int portnum, int do_access, int start_page, uchar *read_buf)
159 int i,length,sendlen=0,head_len=0;
160 uchar sendpacket[50];
164 printf ("owReadPacketStd: %d %d\n", do_access, start_page);
166 // check if access header is done
167 // (only use if in sequention read with one access at begining)
171 sendpacket[sendlen++] = 0x55;
172 for (i = 0; i < 8; i++)
173 sendpacket[sendlen++] = SerialNum[portnum][i];
174 // read memory command
175 sendpacket[sendlen++] = 0xF0;
176 // write the target address
177 sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
178 sendpacket[sendlen++] = (start_page >> 3);
179 // check for DS1982 exception (redirection byte)
180 if (SerialNum[portnum][0] == 0x09)
181 sendpacket[sendlen++] = 0xFF;
182 // record the header length
185 // read the entire page length byte
186 for (i = 0; i < 32; i++)
187 sendpacket[sendlen++] = 0xFF;
189 // send/recieve the transfer buffer
190 if (owBlock(portnum,do_access,sendpacket,sendlen))
192 // seed crc with page number
193 setcrc16(portnum,(ushort)start_page);
195 // attempt to read UDP from sendpacket
196 length = sendpacket[head_len];
197 docrc16(portnum,(ushort)length);
199 // verify length is not too large
202 // loop to read packet including CRC
203 for (i = 0; i < length; i++)
205 read_buf[i] = sendpacket[i+1+head_len];
206 docrc16(portnum,read_buf[i]);
209 // read and compute the CRC16
210 docrc16(portnum,sendpacket[i+1+head_len]);
211 lastcrc16 = docrc16(portnum,sendpacket[i+2+head_len]);
213 // verify the CRC16 is correct
214 if (lastcrc16 == 0xB001)
215 return length; // return number of byte in record
217 printf ("owReadPacketStd: crc error in page %d\n", start_page);
222 printf ("owReadPacketStd: block>29 : %d\n", length);
224 // failed block or incorrect CRC
228 //--------------------------------------------------------------------------
229 // Write a Universal Data Packet onto a standard NVRAM 1-Wire device
230 // on page 'start_page'. This function is limited to UDPs that
231 // fit on one page. The data to write is provided as a buffer
232 // 'write_buf' with a length 'write_len'.
234 // The Universal Data Packet always start on page boundaries but
235 // can end anywhere. The length is the number of data bytes not
236 // including the length byte and the CRC16 bytes. There is one
237 // length byte. The CRC16 is first initialized to the starting
238 // page number. This provides a check to verify the page that
239 // was intended is being read. The CRC16 is then calculated over
240 // the length and data bytes. The CRC16 is then inverted and stored
241 // low byte first followed by the high byte.
243 // Supported devices: is_eprom=0
244 // DS1992, DS1993, DS1994, DS1995, DS1996
245 // is_eprom=1, crc_type=0(CRC8)
247 // is_eprom=1, crc_type=1(CRC16)
248 // DS1985, DS1986, DS2407
250 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
251 // indicate the symbolic port number.
252 // 'start_page' - page number to write packet to
253 // 'write_buf' - pointer to buffer containing data to write
254 // 'write_len' - number of data byte in write_buf
255 // 'is_eprom' - flag set if device is an EPROM (1 EPROM, 0 NVRAM)
256 // 'crc_type' - if is_eprom=1 then indicates CRC type
259 // Returns: TRUE(1) success, packet written
260 // FALSE(0) failure to write, contact lost or device locked
263 int owWritePacketStd(int portnum, int start_page, uchar *write_buf,
264 int write_len, int is_eprom, int crc_type)
266 uchar construct_buffer[32];
267 int i,buffer_cnt=0,start_address,do_access;
271 printf ("owWritePacketStd: %d %d\n", start_page, write_len);
273 // check to see if data too long to fit on device
274 if (write_len > 29) {
276 printf ("owWritePacketStd: too long\n");
281 // seed crc with page number
282 setcrc16(portnum,(ushort)start_page);
285 construct_buffer[buffer_cnt++] = (uchar)(write_len);
286 docrc16(portnum,(ushort)write_len);
288 // fill in the data to write
289 for (i = 0; i < write_len; i++)
291 lastcrc16 = docrc16(portnum,write_buf[i]);
292 construct_buffer[buffer_cnt++] = write_buf[i];
296 construct_buffer[buffer_cnt++] = (uchar)(~(lastcrc16 & 0xFF));
297 construct_buffer[buffer_cnt++] = (uchar)(~((lastcrc16 & 0xFF00) >> 8));
299 // check if not EPROM
303 if (!Write_Scratchpad(portnum,construct_buffer,start_page,buffer_cnt)) {
305 printf ("owWritePacketStd: couldn't Write_Scratchpad\n");
310 // copy the scratchpad
311 if (!Copy_Scratchpad(portnum,start_page,buffer_cnt)) {
313 printf ("owWritePacketStd: couldn't Copy_Scratchpad\n");
318 // copy scratch pad was good then success
324 // calculate the start address
325 start_address = ((start_page >> 3) << 8) | ((start_page << 5) & 0xFF);
327 // loop to program each byte
328 for (i = 0; i < buffer_cnt; i++)
330 if (owProgramByte(portnum,construct_buffer[i], start_address + i,
331 0x0F, crc_type, do_access) != construct_buffer[i])
339 //--------------------------------------------------------------------------
340 // Write a byte to an EPROM 1-Wire device.
342 // Supported devices: crc_type=0(CRC8)
345 // DS1985, DS1986, DS2407
347 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
348 // indicate the symbolic port number.
349 // 'write_byte' - byte to program
350 // 'addr' - address of byte to program
351 // 'write_cmd' - command used to write (0x0F reg mem, 0x55 status)
352 // 'crc_type' - CRC used (0 CRC8, 1 CRC16)
353 // 'do_access' - Flag to access device for each byte
354 // (0 skip access, 1 do the access)
355 // WARNING, only use do_access=0 if programing the NEXT
356 // byte immediatly after the previous byte.
358 // Returns: >=0 success, this is the resulting byte from the program
360 // -1 error, device not connected or program pulse voltage
363 int owProgramByte(int portnum, int write_byte, int addr, int write_cmd,
364 int crc_type, int do_access)
369 // optionally access the device
372 if (!owAccess(portnum))
375 // send the write command
376 if (!owWriteByte(portnum,write_cmd))
380 if (!owWriteByte(portnum,addr & 0xFF))
382 if (!owWriteByte(portnum,addr >> 8))
386 // send the data to write
387 if (!owWriteByte(portnum,write_byte))
397 docrc8(portnum,(uchar)write_cmd);
398 docrc8(portnum,(uchar)(addr & 0xFF));
399 docrc8(portnum,(uchar)(addr >> 8));
402 setcrc8(portnum,(uchar)(addr & 0xFF));
404 docrc8(portnum,(uchar)write_byte);
405 // read and calculate the read crc
406 lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum));
407 // crc should now be 0x00
417 docrc16(portnum,(ushort)write_cmd);
418 docrc16(portnum,(ushort)(addr & 0xFF));
419 docrc16(portnum,(ushort)(addr >> 8));
422 setcrc16(portnum,(ushort)addr);
423 docrc16(portnum,(ushort)write_byte);
424 // read and calculate the read crc
425 docrc16(portnum,(ushort)owReadByte(portnum));
426 lastcrc16 = docrc16(portnum,(ushort)owReadByte(portnum));
427 // crc should now be 0xB001
428 if (lastcrc16 != 0xB001)
432 // send the program pulse
433 if (!owProgramPulse(portnum))
436 // read back and return the resulting byte
437 return owReadByte(portnum);
440 //--------------------------------------------------------------------------
441 // Write the scratchpad of a standard NVRam device such as the DS1992,3,4
442 // and verify its contents.
444 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
445 // indicate the symbolic port number.
446 // 'write_buf' - pointer to buffer containing data to write
447 // 'start_page' - page number to write packet to
448 // 'write_len' - number of data byte in write_buf
450 // Returns: TRUE(1) success, the data was written and verified
451 // FALSE(0) failure, the data could not be written
454 int Write_Scratchpad(int portnum, uchar *write_buf, int start_page, int write_len)
457 uchar sendpacket[50];
460 printf ("Write_Scratchpad: %d %d\n", start_page, write_len);
463 sendpacket[sendlen++] = 0x55;
464 for (i = 0; i < 8; i++)
465 sendpacket[sendlen++] = SerialNum[portnum][i];
466 // write scratchpad command
467 sendpacket[sendlen++] = 0x0F;
468 // write the target address
469 sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
470 sendpacket[sendlen++] = (start_page >> 3);
472 // write packet bytes
473 for (i = 0; i < write_len; i++)
474 sendpacket[sendlen++] = write_buf[i];
476 // send/recieve the transfer buffer
477 if (owBlock(portnum,TRUE,sendpacket,sendlen))
479 // now attempt to read back to check
482 sendpacket[sendlen++] = 0x55;
483 for (i = 0; i < 8; i++)
484 sendpacket[sendlen++] = SerialNum[portnum][i];
485 // read scratchpad command
486 sendpacket[sendlen++] = 0xAA;
487 // read the target address, offset and data
488 for (i = 0; i < (write_len + 3); i++)
489 sendpacket[sendlen++] = 0xFF;
491 // send/recieve the transfer buffer
492 if (owBlock(portnum,TRUE,sendpacket,sendlen))
494 // check address and offset of scratchpad read
495 if ((sendpacket[10] != (int)((start_page << 5) & 0xFF)) ||
496 (sendpacket[11] != (int)(start_page >> 3)) ||
497 (sendpacket[12] != (int)(write_len - 1))) {
499 printf ("\nWrite_Scratchpad: check failed\n");
504 // verify each data byte
505 for (i = 0; i < write_len; i++)
506 if (sendpacket[i+13] != write_buf[i]) {
508 printf ("\nWrite_Scratchpad: data check failed\n");
513 // must have verified
518 printf ("\nWrite_Scratchpad: owBlock failed\n");
521 // failed a block tranfer
525 //--------------------------------------------------------------------------
526 // Copy the contents of the scratchpad to its intended nv ram page. The
527 // page and length of the data is needed to build the authorization bytes
530 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
531 // indicate the symbolic port number.
532 // 'start_page' - page number to write packet to
533 // 'write_len' - number of data bytes that are being copied
535 // Returns: TRUE(1) success
538 int Copy_Scratchpad(int portnum, int start_page, int write_len)
541 uchar sendpacket[50];
544 printf ("Copy_Scratchpad: %d %d\n", start_page, write_len);
548 sendpacket[sendlen++] = 0x55;
549 for (i = 0; i < 8; i++)
550 sendpacket[sendlen++] = SerialNum[portnum][i];
551 // copy scratchpad command
552 sendpacket[sendlen++] = 0x55;
553 // write the target address
554 sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
555 sendpacket[sendlen++] = (start_page >> 3);
556 sendpacket[sendlen++] = write_len - 1;
558 sendpacket[sendlen++] = 0xFF;
561 printf ("Copy_Scratchpad: %d, %02x %02x %02x %02x\n", sendlen,
562 sendpacket[10],sendpacket[11],sendpacket[12],sendpacket[13]);
564 // send/recieve the transfer buffer
565 if (owBlock(portnum,TRUE,sendpacket,sendlen))
567 // check address and offset of scratchpad read
568 if ((sendpacket[10] != (int)((start_page << 5) & 0xFF)) ||
569 (sendpacket[11] != (int)(start_page >> 3)) ||
570 (sendpacket[12] != (int)(write_len - 1)) ||
571 (sendpacket[13] & 0xF0)) {
573 printf ("Copy_Scratchpad: %d, check failed: %02x %02x %02x %02x\n",
575 sendpacket[10],sendpacket[11],sendpacket[12],sendpacket[13]);
581 printf ("Copy_Scratchpad: %02x %02x %02x %02x\n",
582 sendpacket[10],sendpacket[11],sendpacket[12],sendpacket[13]);
588 printf ("Copy_Scratchpad: owBlock failed\n");
590 // failed a block tranfer