Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: owtrnu.cpp
- Revision:
- 0:70c3bea805ee
- Child:
- 1:dcf2f8359398
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/owtrnu.cpp Tue Nov 30 22:11:18 2010 +0000
@@ -0,0 +1,598 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
+// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name of Dallas Semiconductor
+// shall not be used except as stated in the Dallas Semiconductor
+// Branding Policy.
+//---------------------------------------------------------------------------
+//
+// owTranU.C - Transport functions for 1-Wire Net
+// using the DS2480B (U) serial interface chip.
+//
+// Version: 2.01
+//
+// History: 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
+// 1.03 -> 2.00 Changed 'MLan' to 'ow'. Added support for
+// multiple ports.
+// 2.00 -> 2.01 Added support for owError library
+// 2.01 -> 2.10 Added SMALLINT for small processors and error
+// handling plus the raw memory utilities.
+// 2.10 -> 3.00 Added memory bank functionality
+// Added file I/O operations
+//
+
+#include "./Headers/ownet.h"
+#include "./Headers/ds2480.h"
+// external defined in ds2480ut.c
+extern SMALLINT UBaud[MAX_PORTNUM];
+extern SMALLINT UMode[MAX_PORTNUM];
+extern SMALLINT USpeed[MAX_PORTNUM];
+extern uchar SerialNum[MAX_PORTNUM][8];
+
+// local static functions
+static SMALLINT Write_Scratchpad(int,uchar *,int,SMALLINT);
+static SMALLINT Copy_Scratchpad(int,int,SMALLINT);
+
+//--------------------------------------------------------------------------
+// The 'owBlock' transfers a block of data to and from the
+// 1-Wire Net with an optional reset at the begining of communication.
+// The result is returned in the same buffer.
+//
+// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
+// indicate the symbolic port number.
+// 'do_reset' - cause a owTouchReset to occure at the begining of
+// communication TRUE(1) or not FALSE(0)
+// 'tran_buf' - pointer to a block of unsigned
+// chars of length 'tran_len' that will be sent
+// to the 1-Wire Net
+// 'tran_len' - length in bytes to transfer
+
+// Supported devices: all
+//
+// Returns: TRUE (1) : The optional reset returned a valid
+// presence (do_reset == TRUE) or there
+// was no reset required.
+// FALSE (0): The reset did not return a valid prsence
+// (do_reset == TRUE).
+//
+// The maximum tran_length is (160)
+//
+SMALLINT owBlock(int portnum, SMALLINT do_reset, uchar *tran_buf, SMALLINT tran_len)
+{
+ uchar sendpacket[320];
+ uchar sendlen=0,i;
+
+ // check for a block too big
+ if (tran_len > 160)
+ {
+ OWERROR(OWERROR_BLOCK_TOO_BIG);
+ return FALSE;
+ }
+
+ // check if need to do a owTouchReset first
+ if (do_reset)
+ {
+ if (!owTouchReset(portnum))
+ {
+ OWERROR(OWERROR_NO_DEVICES_ON_NET);
+ return FALSE;
+ }
+ }
+
+ // construct the packet to send to the DS2480
+ // check if correct mode
+ if (UMode[portnum] != MODSEL_DATA)
+ {
+ UMode[portnum] = MODSEL_DATA;
+ sendpacket[sendlen++] = MODE_DATA;
+ }
+
+ // add the bytes to send
+// pos = sendlen;
+ for (i = 0; i < tran_len; i++)
+ {
+ sendpacket[sendlen++] = tran_buf[i];
+
+ // check for duplication of data that looks like COMMAND mode
+ if (tran_buf[i] == MODE_COMMAND)
+ sendpacket[sendlen++] = tran_buf[i];
+ }
+
+ // flush the buffers
+ FlushCOM(portnum);
+
+ // send the packet
+ if (WriteCOM(portnum,sendlen,sendpacket))
+ {
+ // read back the response
+ if (ReadCOM(portnum,tran_len,tran_buf) == tran_len)
+ return TRUE;
+ else
+ OWERROR(OWERROR_READCOM_FAILED);
+ }
+ else
+ OWERROR(OWERROR_WRITECOM_FAILED);
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect(portnum);
+
+ return FALSE;
+}
+
+//--------------------------------------------------------------------------
+// Read a Universal Data Packet from a standard NVRAM iButton
+// and return it in the provided buffer. The page that the
+// packet resides on is 'start_page'. Note that this function is limited
+// to single page packets. The buffer 'read_buf' must be at least
+// 29 bytes long.
+//
+// The Universal Data Packet always start on page boundaries but
+// can end anywhere. The length is the number of data bytes not
+// including the length byte and the CRC16 bytes. There is one
+// length byte. The CRC16 is first initialized to the starting
+// page number. This provides a check to verify the page that
+// was intended is being read. The CRC16 is then calculated over
+// the length and data bytes. The CRC16 is then inverted and stored
+// low byte first followed by the high byte.
+//
+// Supported devices: DS1992, DS1993, DS1994, DS1995, DS1996, DS1982,
+// DS1985, DS1986, DS2407, and DS1971.
+//
+// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
+// indicate the symbolic port number.
+// 'do_access' - flag to indicate if an 'owAccess' should be
+// peformed at the begining of the read. This may
+// be FALSE (0) if the previous call was to read the
+// previous page (start_page-1).
+// 'start_page' - page number to start the read from
+// 'read_buf' - pointer to a location to store the data read
+//
+// Returns: >=0 success, number of data bytes in the buffer
+// -1 failed to read a valid UDP
+//
+//
+SMALLINT owReadPacketStd(int portnum, SMALLINT do_access, int start_page, uchar *read_buf)
+{
+ uchar i,length,sendlen=0,head_len=0;
+ uchar sendpacket[50];
+ unsigned short lastcrc16;
+
+ // check if access header is done
+ // (only use if in sequention read with one access at begining)
+ if (do_access)
+ {
+ // match command
+ sendpacket[sendlen++] = 0x55;
+ for (i = 0; i < 8; i++)
+ sendpacket[sendlen++] = SerialNum[portnum][i];
+ // read memory command
+ sendpacket[sendlen++] = 0xF0;
+ // write the target address
+ sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
+ sendpacket[sendlen++] = (start_page >> 3);
+ // check for DS1982 exception (redirection byte)
+ if (SerialNum[portnum][0] == 0x09)
+ sendpacket[sendlen++] = 0xFF;
+ // record the header length
+ head_len = sendlen;
+ }
+ // read the entire page length byte
+ for (i = 0; i < 32; i++)
+ sendpacket[sendlen++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (owBlock(portnum,do_access,sendpacket,sendlen))
+ {
+ // seed crc with page number
+ setcrc16(portnum,(unsigned short)start_page);
+
+ // attempt to read UDP from sendpacket
+ length = sendpacket[head_len];
+ docrc16(portnum,(unsigned short)length);
+
+ // verify length is not too large
+ if (length <= 29)
+ {
+ // loop to read packet including CRC
+ for (i = 0; i < length; i++)
+ {
+ read_buf[i] = sendpacket[i+1+head_len];
+ docrc16(portnum,read_buf[i]);
+ }
+
+ // read and compute the CRC16
+ docrc16(portnum,sendpacket[i+1+head_len]);
+ lastcrc16 = docrc16(portnum,sendpacket[i+2+head_len]);
+
+ // verify the CRC16 is correct
+ if (lastcrc16 == 0xB001)
+ return length; // return number of byte in record
+ else
+ OWERROR(OWERROR_CRC_FAILED);
+ }
+ else
+ OWERROR(OWERROR_INCORRECT_CRC_LENGTH);
+ }
+ else
+ OWERROR(OWERROR_BLOCK_FAILED);
+
+ // failed block or incorrect CRC
+ return -1;
+}
+
+//--------------------------------------------------------------------------
+// Write a Universal Data Packet onto a standard NVRAM 1-Wire device
+// on page 'start_page'. This function is limited to UDPs that
+// fit on one page. The data to write is provided as a buffer
+// 'write_buf' with a length 'write_len'.
+//
+// The Universal Data Packet always start on page boundaries but
+// can end anywhere. The length is the number of data bytes not
+// including the length byte and the CRC16 bytes. There is one
+// length byte. The CRC16 is first initialized to the starting
+// page number. This provides a check to verify the page that
+// was intended is being read. The CRC16 is then calculated over
+// the length and data bytes. The CRC16 is then inverted and stored
+// low byte first followed by the high byte.
+//
+// Supported devices: is_eprom=0
+// DS1992, DS1993, DS1994, DS1995, DS1996
+// is_eprom=1, crc_type=0(CRC8)
+// DS1982
+// is_eprom=1, crc_type=1(CRC16)
+// DS1985, DS1986, DS2407
+//
+// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
+// indicate the symbolic port number.
+// 'start_page' - page number to write packet to
+// 'write_buf' - pointer to buffer containing data to write
+// 'write_len' - number of data byte in write_buf
+// 'is_eprom' - flag set if device is an EPROM (1 EPROM, 0 NVRAM)
+// 'crc_type' - if is_eprom=1 then indicates CRC type
+// (0 CRC8, 1 CRC16)
+//
+// Returns: TRUE(1) success, packet written
+// FALSE(0) failure to write, contact lost or device locked
+//
+SMALLINT owWritePacketStd(int portnum, int start_page, uchar *write_buf,
+ SMALLINT write_len, SMALLINT is_eprom, SMALLINT crc_type)
+{
+ uchar construct_buffer[32];
+ uchar i,buffer_cnt=0,start_address,do_access;
+ unsigned short lastcrc16=0;
+
+ // check to see if data too long to fit on device
+ if (write_len > 29)
+ return FALSE;
+
+ // seed crc with page number
+ setcrc16(portnum,(unsigned short)start_page);
+
+ // set length byte
+ construct_buffer[buffer_cnt++] = (uchar)(write_len);
+ docrc16(portnum,(unsigned short)write_len);
+
+ // fill in the data to write
+ for (i = 0; i < write_len; i++)
+ {
+ lastcrc16 = docrc16(portnum,write_buf[i]);
+ construct_buffer[buffer_cnt++] = write_buf[i];
+ }
+
+ // add the crc
+ construct_buffer[buffer_cnt++] = (uchar)(~(lastcrc16 & 0xFF));
+ construct_buffer[buffer_cnt++] = (uchar)(~((lastcrc16 & 0xFF00) >> 8));
+
+ // check if not EPROM
+ if (!is_eprom)
+ {
+ // write the page
+ if (!Write_Scratchpad(portnum,construct_buffer,start_page,buffer_cnt))
+ {
+ OWERROR(OWERROR_WRITE_SCRATCHPAD_FAILED);
+ return FALSE;
+ }
+
+ // copy the scratchpad
+ if (!Copy_Scratchpad(portnum,start_page,buffer_cnt))
+ {
+ OWERROR(OWERROR_COPY_SCRATCHPAD_FAILED);
+ return FALSE;
+ }
+
+ // copy scratch pad was good then success
+ return TRUE;
+ }
+ // is EPROM
+ else
+ {
+ // calculate the start address
+ start_address = ((start_page >> 3) << 8) | ((start_page << 5) & 0xFF);
+ do_access = TRUE;
+ // loop to program each byte
+ for (i = 0; i < buffer_cnt; i++)
+ {
+ if (owProgramByte(portnum,construct_buffer[i], start_address + i,
+ 0x0F, crc_type, do_access) != construct_buffer[i])
+ {
+ OWERROR(OWERROR_PROGRAM_BYTE_FAILED);
+ return FALSE;
+ }
+ do_access = FALSE;
+ }
+ return TRUE;
+ }
+}
+
+//--------------------------------------------------------------------------
+// Write a byte to an EPROM 1-Wire device.
+//
+// Supported devices: crc_type=0(CRC8)
+// DS1982
+// crc_type=1(CRC16)
+// DS1985, DS1986, DS2407
+//
+// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
+// indicate the symbolic port number.
+// 'write_byte' - byte to program
+// 'addr' - address of byte to program
+// 'write_cmd' - command used to write (0x0F reg mem, 0x55 status)
+// 'crc_type' - CRC used (0 CRC8, 1 CRC16)
+// 'do_access' - Flag to access device for each byte
+// (0 skip access, 1 do the access)
+// WARNING, only use do_access=0 if programing the NEXT
+// byte immediatly after the previous byte.
+//
+// Returns: >=0 success, this is the resulting byte from the program
+// effort
+// -1 error, device not connected or program pulse voltage
+// not available
+//
+SMALLINT owProgramByte(int portnum, SMALLINT write_byte, int addr, SMALLINT write_cmd,
+ SMALLINT crc_type, SMALLINT do_access)
+{
+ unsigned short lastcrc16;
+ uchar lastcrc8;
+
+ // optionally access the device
+ if (do_access)
+ {
+ if (!owAccess(portnum))
+ {
+ OWERROR(OWERROR_ACCESS_FAILED);
+ return -1;
+ }
+
+ // send the write command
+ if (!owWriteByte(portnum,write_cmd))
+ {
+ OWERROR(OWERROR_WRITE_BYTE_FAILED);
+ return -1;
+ }
+
+ // send the address
+ if (!owWriteByte(portnum,addr & 0xFF) || !owWriteByte(portnum,addr >> 8))
+ {
+ OWERROR(OWERROR_WRITE_BYTE_FAILED);
+ return -1;
+ }
+ }
+
+ // send the data to write
+ if (!owWriteByte(portnum,write_byte))
+ {
+ OWERROR(OWERROR_WRITE_BYTE_FAILED);
+ return -1;
+ }
+
+ // read the CRC
+ if (crc_type == 0)
+ {
+ // calculate CRC8
+ if (do_access)
+ {
+ setcrc8(portnum,0);
+ docrc8(portnum,(uchar)write_cmd);
+ docrc8(portnum,(uchar)(addr & 0xFF));
+ docrc8(portnum,(uchar)(addr >> 8));
+ }
+ else
+ setcrc8(portnum,(uchar)(addr & 0xFF));
+
+ docrc8(portnum,(uchar)write_byte);
+ // read and calculate the read crc
+ lastcrc8 = docrc8(portnum,(uchar)owReadByte(portnum));
+ // crc should now be 0x00
+ if (lastcrc8 != 0)
+ {
+ OWERROR(OWERROR_CRC_FAILED);
+ return -1;
+ }
+ }
+ else
+ {
+ // CRC16
+ if (do_access)
+ {
+ setcrc16(portnum,0);
+ docrc16(portnum,(unsigned short)write_cmd);
+ docrc16(portnum,(unsigned short)(addr & 0xFF));
+ docrc16(portnum,(unsigned short)(addr >> 8));
+ }
+ else
+ setcrc16(portnum,(unsigned short)addr);
+ docrc16(portnum,(unsigned short)write_byte);
+ // read and calculate the read crc
+ docrc16(portnum,( unsigned short)owReadByte(portnum));
+ lastcrc16 = docrc16(portnum,( unsigned short)owReadByte(portnum));
+ // crc should now be 0xB001
+ if (lastcrc16 != 0xB001)
+ {
+ OWERROR(OWERROR_CRC_FAILED);
+ return -1;
+ }
+ }
+
+ // send the program pulse
+ if (!owProgramPulse(portnum))
+ {
+ OWERROR(OWERROR_PROGRAM_PULSE_FAILED);
+ return -1;
+ }
+
+ // read back and return the resulting byte
+ return owReadByte(portnum);
+}
+
+//--------------------------------------------------------------------------
+// Write the scratchpad of a standard NVRam device such as the DS1992,3,4
+// and verify its contents.
+//
+// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
+// indicate the symbolic port number.
+// 'write_buf' - pointer to buffer containing data to write
+// 'start_page' - page number to write packet to
+// 'write_len' - number of data byte in write_buf
+//
+// Returns: TRUE(1) success, the data was written and verified
+// FALSE(0) failure, the data could not be written
+//
+//
+SMALLINT Write_Scratchpad(int portnum, uchar *write_buf, int start_page, SMALLINT write_len)
+{
+ uchar i,sendlen=0;
+ uchar sendpacket[50];
+
+ // match command
+ sendpacket[sendlen++] = 0x55;
+ for (i = 0; i < 8; i++)
+ sendpacket[sendlen++] = SerialNum[portnum][i];
+ // write scratchpad command
+ sendpacket[sendlen++] = 0x0F;
+ // write the target address
+ sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
+ sendpacket[sendlen++] = (start_page >> 3);
+
+ // write packet bytes
+ for (i = 0; i < write_len; i++)
+ sendpacket[sendlen++] = write_buf[i];
+
+ // send/recieve the transfer buffer
+ if (owBlock(portnum,TRUE,sendpacket,sendlen))
+ {
+ // now attempt to read back to check
+ sendlen = 0;
+ // match command
+ sendpacket[sendlen++] = 0x55;
+ for (i = 0; i < 8; i++)
+ sendpacket[sendlen++] = SerialNum[portnum][i];
+ // read scratchpad command
+ sendpacket[sendlen++] = 0xAA;
+ // read the target address, offset and data
+ for (i = 0; i < (write_len + 3); i++)
+ sendpacket[sendlen++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (owBlock(portnum,TRUE,sendpacket,sendlen))
+ {
+ // check address and offset of scratchpad read
+ if ((sendpacket[10] != ((start_page << 5) & 0xFF)) ||
+ (sendpacket[11] != (start_page >> 3)) ||
+ (sendpacket[12] != (write_len - 1)))
+ {
+ OWERROR(OWERROR_READ_VERIFY_FAILED);
+ return FALSE;
+ }
+
+ // verify each data byte
+ for (i = 0; i < write_len; i++)
+ if (sendpacket[i+13] != write_buf[i])
+ {
+ OWERROR(OWERROR_WRITE_VERIFY_FAILED);
+ return FALSE;
+ }
+
+ // must have verified
+ return TRUE;
+ }
+ else
+ OWERROR(OWERROR_BLOCK_FAILED);
+ }
+ else
+ OWERROR(OWERROR_BLOCK_FAILED);
+
+ // failed a block tranfer
+ return FALSE;
+}
+
+//--------------------------------------------------------------------------
+// Copy the contents of the scratchpad to its intended nv ram page. The
+// page and length of the data is needed to build the authorization bytes
+// to copy.
+//
+// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
+// indicate the symbolic port number.
+// 'start_page' - page number to write packet to
+// 'write_len' - number of data bytes that are being copied
+//
+// Returns: TRUE(1) success
+// FALSE(0) failure
+//
+SMALLINT Copy_Scratchpad(int portnum, int start_page, SMALLINT write_len)
+{
+ uchar i,sendlen=0;
+ uchar sendpacket[50];
+
+ // match command
+ sendpacket[sendlen++] = 0x55;
+ for (i = 0; i < 8; i++)
+ sendpacket[sendlen++] = SerialNum[portnum][i];
+ // copy scratchpad command
+ sendpacket[sendlen++] = 0x55;
+ // write the target address
+ sendpacket[sendlen++] = ((start_page << 5) & 0xFF);
+ sendpacket[sendlen++] = (start_page >> 3);
+ sendpacket[sendlen++] = write_len - 1;
+ // read copy result
+ sendpacket[sendlen++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (owBlock(portnum,TRUE,sendpacket,sendlen))
+ {
+ // check address and offset of scratchpad read
+ if ((sendpacket[10] != ((start_page << 5) & 0xFF)) ||
+ (sendpacket[11] != (start_page >> 3)) ||
+ (sendpacket[12] != (write_len - 1)) ||
+ (sendpacket[13] & 0xF0))
+ {
+ OWERROR(OWERROR_READ_VERIFY_FAILED);
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+ else
+ OWERROR(OWERROR_BLOCK_FAILED);
+
+ // failed a block tranfer
+ return FALSE;
+}
+