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 DS2480B (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
35
// 2.00 -> 2.01 Added support for owError library
36
// 2.01 -> 2.10 Added SMALLINT for small processors and error
37
// handling plus the raw memory utilities.
38
// 2.10 -> 3.00 Added memory bank functionality
39
// Added file I/O operations
45
// external functions defined in owllu.c
46
extern SMALLINT owTouchReset(int);
47
extern SMALLINT owWriteByte(int,SMALLINT);
48
extern SMALLINT owReadByte(int);
49
extern SMALLINT owProgramPulse(int);
51
// external network-level functions defined in owsesu.c
52
extern SMALLINT owAccess(int);
54
// external COM functions required defined in system specific link file
55
extern SMALLINT WriteCOM(int,int,uchar *);
56
extern int ReadCOM(int,int,uchar *);
57
extern void FlushCOM(int);
59
// external defined in ds2480ut.c
60
extern SMALLINT DS2480Detect(int);
61
extern SMALLINT UBaud[MAX_PORTNUM];
62
extern SMALLINT UMode[MAX_PORTNUM];
63
extern SMALLINT USpeed[MAX_PORTNUM];
64
extern uchar SerialNum[MAX_PORTNUM][8];
66
// external functions defined in crcutil.c
67
extern void setcrc16(int,ushort);
68
extern ushort docrc16(int,ushort);
69
extern void setcrc8(int,uchar);
70
extern uchar docrc8(int,uchar);
72
// exportable functions defined in owtrnu.c
73
SMALLINT owBlock(int,SMALLINT,uchar *,SMALLINT);
74
SMALLINT owReadPacketStd(int,SMALLINT,int,uchar *);
75
SMALLINT owWritePacketStd(int,int,uchar *,SMALLINT,SMALLINT,SMALLINT);
76
SMALLINT owProgramByte(int,SMALLINT,int,SMALLINT,SMALLINT,SMALLINT);
78
// local static functions
79
static SMALLINT Write_Scratchpad(int,uchar *,int,SMALLINT);
80
static SMALLINT Copy_Scratchpad(int,int,SMALLINT);
82
//--------------------------------------------------------------------------
83
// The 'owBlock' transfers a block of data to and from the
84
// 1-Wire Net with an optional reset at the begining of communication.
85
// The result is returned in the same buffer.
87
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
88
// indicate the symbolic port number.
89
// 'do_reset' - cause a owTouchReset to occure at the begining of
90
// communication TRUE(1) or not FALSE(0)
91
// 'tran_buf' - pointer to a block of unsigned
92
// chars of length 'tran_len' that will be sent
94
// 'tran_len' - length in bytes to transfer
96
// Supported devices: all
98
// Returns: TRUE (1) : The optional reset returned a valid
99
// presence (do_reset == TRUE) or there
100
// was no reset required.
101
// FALSE (0): The reset did not return a valid prsence
102
// (do_reset == TRUE).
104
// The maximum tran_length is 64
106
SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len)
108
uchar sendpacket[150];
109
uchar sendlen=0,pos,i;
111
// check for a block too big
114
OWERROR(OWERROR_BLOCK_TOO_BIG);
118
// check if need to do a owTouchReset first
121
if (!owTouchReset(portnum))
123
OWERROR(OWERROR_NO_DEVICES_ON_NET);
128
// construct the packet to send to the DS2480
129
// check if correct mode
130
if (UMode[portnum] != MODSEL_DATA)
132
UMode[portnum] = MODSEL_DATA;
133
sendpacket[sendlen++] = MODE_DATA;
136
// add the bytes to send
138
for (i = 0; i < tran_len; i++)
140
sendpacket[sendlen++] = tran_buf[i];
142
// check for duplication of data that looks like COMMAND mode
143
if (tran_buf[i] == MODE_COMMAND)
144
sendpacket[sendlen++] = tran_buf[i];
151
if (WriteCOM(portnum,sendlen,sendpacket))
153
// read back the response
154
if (ReadCOM(portnum,tran_len,tran_buf) == tran_len)
157
OWERROR(OWERROR_READCOM_FAILED);
160
OWERROR(OWERROR_WRITECOM_FAILED);
162
// an error occured so re-sync with DS2480
163
DS2480Detect(portnum);
168
//--------------------------------------------------------------------------
169
// Read a Universal Data Packet from a standard NVRAM iButton
170
// and return it in the provided buffer. The page that the
171
// packet resides on is 'start_page'. Note that this function is limited
172
// to single page packets. The buffer 'read_buf' must be at least
175
// The Universal Data Packet always start on page boundaries but
176
// can end anywhere. The length is the number of data bytes not
177
// including the length byte and the CRC16 bytes. There is one
178
// length byte. The CRC16 is first initialized to the starting
179
// page number. This provides a check to verify the page that
180
// was intended is being read. The CRC16 is then calculated over
181
// the length and data bytes. The CRC16 is then inverted and stored
182
// low byte first followed by the high byte.
184
// Supported devices: DS1992, DS1993, DS1994, DS1995, DS1996, DS1982,
185
// DS1985, DS1986, DS2407, and DS1971.
187
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
188
// indicate the symbolic port number.
189
// 'do_access' - flag to indicate if an 'owAccess' should be
190
// peformed at the begining of the read. This may
191
// be FALSE (0) if the previous call was to read the
192
// previous page (start_page-1).
193
// 'start_page' - page number to start the read from
194
// 'read_buf' - pointer to a location to store the data read
196
// Returns: >=0 success, number of data bytes in the buffer
197
// -1 failed to read a valid UDP
200
SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf)
202
uchar i,length,sendlen=0,head_len=0;
203
uchar sendpacket[50];
206
// check if access header is done
207
// (only use if in sequention read with one access at begining)
211
sendpacket[sendlen++] = 0x55;
212
for (i = 0; i < 8; i++)
213
sendpacket[sendlen++] = SerialNum[portnum][i];
214
// read memory command
215
sendpacket[sendlen++] = 0xF0;
216
// write the target address
217
sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
218
sendpacket[sendlen++] = (start_page >> 3);
219
// check for DS1982 exception (redirection byte)
220
if (SerialNum[portnum][0] == 0x09)
221
sendpacket[sendlen++] = 0xFF;
222
// record the header length
225
// read the entire page length byte
226
for (i = 0; i < 32; i++)
227
sendpacket[sendlen++] = 0xFF;
229
// send/recieve the transfer buffer
230
if (owBlock(portnum,do_access,sendpacket,sendlen))
232
// seed crc with page number
233
setcrc16(portnum,(ushort)start_page);
235
// attempt to read UDP from sendpacket
236
length = sendpacket[head_len];
237
docrc16(portnum,(ushort)length);
239
// verify length is not too large
242
// loop to read packet including CRC
243
for (i = 0; i < length; i++)
245
read_buf[i] = sendpacket[i+1+head_len];
246
docrc16(portnum,read_buf[i]);
249
// read and compute the CRC16
250
docrc16(portnum,sendpacket[i+1+head_len]);
251
lastcrc16 = docrc16(portnum,sendpacket[i+2+head_len]);
253
// verify the CRC16 is correct
254
if (lastcrc16 == 0xB001)
255
return length; // return number of byte in record
257
OWERROR(OWERROR_CRC_FAILED);
260
OWERROR(OWERROR_INCORRECT_CRC_LENGTH);
263
OWERROR(OWERROR_BLOCK_FAILED);
265
// failed block or incorrect CRC
269
//--------------------------------------------------------------------------
270
// Write a Universal Data Packet onto a standard NVRAM 1-Wire device
271
// on page 'start_page'. This function is limited to UDPs that
272
// fit on one page. The data to write is provided as a buffer
273
// 'write_buf' with a length 'write_len'.
275
// The Universal Data Packet always start on page boundaries but
276
// can end anywhere. The length is the number of data bytes not
277
// including the length byte and the CRC16 bytes. There is one
278
// length byte. The CRC16 is first initialized to the starting
279
// page number. This provides a check to verify the page that
280
// was intended is being read. The CRC16 is then calculated over
281
// the length and data bytes. The CRC16 is then inverted and stored
282
// low byte first followed by the high byte.
284
// Supported devices: is_eprom=0
285
// DS1992, DS1993, DS1994, DS1995, DS1996
286
// is_eprom=1, crc_type=0(CRC8)
288
// is_eprom=1, crc_type=1(CRC16)
289
// DS1985, DS1986, DS2407
291
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
292
// indicate the symbolic port number.
293
// 'start_page' - page number to write packet to
294
// 'write_buf' - pointer to buffer containing data to write
295
// 'write_len' - number of data byte in write_buf
296
// 'is_eprom' - flag set if device is an EPROM (1 EPROM, 0 NVRAM)
297
// 'crc_type' - if is_eprom=1 then indicates CRC type
300
// Returns: TRUE(1) success, packet written
301
// FALSE(0) failure to write, contact lost or device locked
303
SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf,
304
SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type)
306
uchar construct_buffer[32];
307
uchar i,buffer_cnt=0,start_address,do_access;
310
// check to see if data too long to fit on device
314
// seed crc with page number
315
setcrc16(portnum,(ushort)start_page);
318
construct_buffer[buffer_cnt++] = (uchar)(write_len);
319
docrc16(portnum,(ushort)write_len);
321
// fill in the data to write
322
for (i = 0; i < write_len; i++)
324
lastcrc16 = docrc16(portnum,write_buf[i]);
325
construct_buffer[buffer_cnt++] = write_buf[i];
329
construct_buffer[buffer_cnt++] = (uchar)(~(lastcrc16 & 0xFF));
330
construct_buffer[buffer_cnt++] = (uchar)(~((lastcrc16 & 0xFF00) >> 8));
332
// check if not EPROM
336
if (!Write_Scratchpad(portnum,construct_buffer,start_page,buffer_cnt))
338
OWERROR(OWERROR_WRITE_SCRATCHPAD_FAILED);
342
// copy the scratchpad
343
if (!Copy_Scratchpad(portnum,start_page,buffer_cnt))
345
OWERROR(OWERROR_COPY_SCRATCHPAD_FAILED);
349
// copy scratch pad was good then success
355
// calculate the start address
356
start_address = ((start_page >> 3) << 8) | ((start_page << 5) & 0xFF);
358
// loop to program each byte
359
for (i = 0; i < buffer_cnt; i++)
361
if (owProgramByte(portnum,construct_buffer[i], start_address + i,
362
0x0F, crc_type, do_access) != construct_buffer[i])
364
OWERROR(OWERROR_PROGRAM_BYTE_FAILED);
373
//--------------------------------------------------------------------------
374
// Write a byte to an EPROM 1-Wire device.
376
// Supported devices: crc_type=0(CRC8)
379
// DS1985, DS1986, DS2407
381
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
382
// indicate the symbolic port number.
383
// 'write_byte' - byte to program
384
// 'addr' - address of byte to program
385
// 'write_cmd' - command used to write (0x0F reg mem, 0x55 status)
386
// 'crc_type' - CRC used (0 CRC8, 1 CRC16)
387
// 'do_access' - Flag to access device for each byte
388
// (0 skip access, 1 do the access)
389
// WARNING, only use do_access=0 if programing the NEXT
390
// byte immediatly after the previous byte.
392
// Returns: >=0 success, this is the resulting byte from the program
394
// -1 error, device not connected or program pulse voltage
397
SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd,
398
SMALLINT crc_type, SMALLINT do_access)
403
// optionally access the device
406
if (!owAccess(portnum))
408
OWERROR(OWERROR_ACCESS_FAILED);
412
// send the write command
413
if (!owWriteByte(portnum,write_cmd))
415
OWERROR(OWERROR_WRITE_BYTE_FAILED);
420
if (!owWriteByte(portnum,addr & 0xFF) || !owWriteByte(portnum,addr >> 8))
422
OWERROR(OWERROR_WRITE_BYTE_FAILED);
427
// send the data to write
428
if (!owWriteByte(portnum,write_byte))
430
OWERROR(OWERROR_WRITE_BYTE_FAILED);
441
docrc8(portnum,(uchar)write_cmd);
442
docrc8(portnum,(uchar)(addr & 0xFF));
443
docrc8(portnum,(uchar)(addr >> 8));
446
setcrc8(portnum,(uchar)(addr & 0xFF));
448
docrc8(portnum,(uchar)write_byte);
449
// read and calculate the read crc
450
lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum));
451
// crc should now be 0x00
454
OWERROR(OWERROR_CRC_FAILED);
464
docrc16(portnum,(ushort)write_cmd);
465
docrc16(portnum,(ushort)(addr & 0xFF));
466
docrc16(portnum,(ushort)(addr >> 8));
469
setcrc16(portnum,(ushort)addr);
470
docrc16(portnum,(ushort)write_byte);
471
// read and calculate the read crc
472
docrc16(portnum,(ushort)owReadByte(portnum));
473
lastcrc16 = docrc16(portnum,(ushort)owReadByte(portnum));
474
// crc should now be 0xB001
475
if (lastcrc16 != 0xB001)
477
OWERROR(OWERROR_CRC_FAILED);
482
// send the program pulse
483
if (!owProgramPulse(portnum))
485
OWERROR(OWERROR_PROGRAM_PULSE_FAILED);
489
// read back and return the resulting byte
490
return owReadByte(portnum);
493
//--------------------------------------------------------------------------
494
// Write the scratchpad of a standard NVRam device such as the DS1992,3,4
495
// and verify its contents.
497
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
498
// indicate the symbolic port number.
499
// 'write_buf' - pointer to buffer containing data to write
500
// 'start_page' - page number to write packet to
501
// 'write_len' - number of data byte in write_buf
503
// Returns: TRUE(1) success, the data was written and verified
504
// FALSE(0) failure, the data could not be written
507
SMALLINT Write_Scratchpad(int portnum, uchar *write_buf, int start_page, SMALLINT write_len)
510
uchar sendpacket[50];
513
sendpacket[sendlen++] = 0x55;
514
for (i = 0; i < 8; i++)
515
sendpacket[sendlen++] = SerialNum[portnum][i];
516
// write scratchpad command
517
sendpacket[sendlen++] = 0x0F;
518
// write the target address
519
sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
520
sendpacket[sendlen++] = (start_page >> 3);
522
// write packet bytes
523
for (i = 0; i < write_len; i++)
524
sendpacket[sendlen++] = write_buf[i];
526
// send/recieve the transfer buffer
527
if (owBlock(portnum,TRUE,sendpacket,sendlen))
529
// now attempt to read back to check
532
sendpacket[sendlen++] = 0x55;
533
for (i = 0; i < 8; i++)
534
sendpacket[sendlen++] = SerialNum[portnum][i];
535
// read scratchpad command
536
sendpacket[sendlen++] = 0xAA;
537
// read the target address, offset and data
538
for (i = 0; i < (write_len + 3); i++)
539
sendpacket[sendlen++] = 0xFF;
541
// send/recieve the transfer buffer
542
if (owBlock(portnum,TRUE,sendpacket,sendlen))
544
// check address and offset of scratchpad read
545
if ((sendpacket[10] != ((start_page << 5) & 0xFF)) ||
546
(sendpacket[11] != (start_page >> 3)) ||
547
(sendpacket[12] != (write_len - 1)))
549
OWERROR(OWERROR_READ_VERIFY_FAILED);
553
// verify each data byte
554
for (i = 0; i < write_len; i++)
555
if (sendpacket[i+13] != write_buf[i])
557
OWERROR(OWERROR_WRITE_VERIFY_FAILED);
561
// must have verified
565
OWERROR(OWERROR_BLOCK_FAILED);
568
OWERROR(OWERROR_BLOCK_FAILED);
570
// failed a block tranfer
574
//--------------------------------------------------------------------------
575
// Copy the contents of the scratchpad to its intended nv ram page. The
576
// page and length of the data is needed to build the authorization bytes
579
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
580
// indicate the symbolic port number.
581
// 'start_page' - page number to write packet to
582
// 'write_len' - number of data bytes that are being copied
584
// Returns: TRUE(1) success
587
SMALLINT Copy_Scratchpad(int portnum, int start_page, SMALLINT write_len)
590
uchar sendpacket[50];
593
sendpacket[sendlen++] = 0x55;
594
for (i = 0; i < 8; i++)
595
sendpacket[sendlen++] = SerialNum[portnum][i];
596
// copy scratchpad command
597
sendpacket[sendlen++] = 0x55;
598
// write the target address
599
sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
600
sendpacket[sendlen++] = (start_page >> 3);
601
sendpacket[sendlen++] = write_len - 1;
603
sendpacket[sendlen++] = 0xFF;
605
// send/recieve the transfer buffer
606
if (owBlock(portnum,TRUE,sendpacket,sendlen))
608
// check address and offset of scratchpad read
609
if ((sendpacket[10] != ((start_page << 5) & 0xFF)) ||
610
(sendpacket[11] != (start_page >> 3)) ||
611
(sendpacket[12] != (write_len - 1)) ||
612
(sendpacket[13] & 0xF0))
614
OWERROR(OWERROR_READ_VERIFY_FAILED);
621
OWERROR(OWERROR_BLOCK_FAILED);
623
// failed a block tranfer