summaryrefslogtreecommitdiff
path: root/src/pmdas/roomtemp/mlan/mlantrnu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/roomtemp/mlan/mlantrnu.c')
-rw-r--r--src/pmdas/roomtemp/mlan/mlantrnu.c579
1 files changed, 579 insertions, 0 deletions
diff --git a/src/pmdas/roomtemp/mlan/mlantrnu.c b/src/pmdas/roomtemp/mlan/mlantrnu.c
new file mode 100644
index 0000000..5a0b376
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/mlantrnu.c
@@ -0,0 +1,579 @@
+//---------------------------------------------------------------------------
+// Copyright (C) 1999 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.
+//---------------------------------------------------------------------------
+//
+// MLanTranU.C - Transport functions for MicroLAN 1-Wire devices
+// using the DS2480 (U) serial interface chip.
+//
+// Version: 1.03
+//
+// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility
+//
+
+#include "ds2480.h"
+#include "mlan.h"
+
+// external low-level functions required
+extern int MLanTouchReset(void);
+extern int MLanWriteByte(int);
+extern int MLanReadByte(void);
+extern int MLanProgramPulse(void);
+
+// external network-level functions required
+extern int MLanAccess();
+
+// external COM functions required
+extern void FlushCOM(void);
+extern int WriteCOM(int, uchar *);
+extern int ReadCOM(int, uchar *);
+
+// other external functions
+extern int DS2480Detect(void);
+extern uchar dowcrc(uchar);
+
+// external globals
+extern int UMode;
+extern int UBaud;
+extern int USpeed;
+extern uchar SerialNum[8];
+extern uchar DOWCRC;
+
+// local exportable functions
+int MLanBlock(int, uchar *, int);
+int MLanReadPacketStd(int, int, uchar *);
+int MLanWritePacketStd(int, uchar *, int, int, int);
+int MLanProgramByte(int, int, int, int, int);
+
+// local functions
+static int Write_Scratchpad(uchar *, int, int);
+static int Copy_Scratchpad(int, int);
+unsigned short crc16(int);
+
+// global variable
+unsigned short CRC16;
+
+
+//--------------------------------------------------------------------------
+// The 'MLanBlock' transfers a block of data to and from the
+// MicroLAN with an optional reset at the begining of communication.
+// The result is returned in the same buffer.
+//
+// 'DoReset' - cause a MLanTouchReset to occure at the begining of
+// communication TRUE(1) or not FALSE(0)
+// 'TransferBuffer' - pointer to a block of unsigned
+// chars of length 'TranferLength' that will be sent
+// to the MicroLAN
+// 'TranferLength' - length in bytes to transfer
+
+// Supported devices: all
+//
+// Returns: TRUE (1) : The optional reset returned a valid
+// presence (DoReset == TRUE) or there
+// was no reset required.
+// FALSE (0): The reset did not return a valid prsence
+// (DoReset == TRUE).
+//
+// The maximum TransferLength is 64
+//
+int MLanBlock(int DoReset, uchar *TransferBuffer, int TransferLen)
+{
+ uchar sendpacket[150];
+ int sendlen=0,i;
+
+ // check for a block too big
+ if (TransferLen > 64)
+ return FALSE;
+
+ // check if need to do a MLanTouchReset first
+ if (DoReset)
+ {
+ if (!MLanTouchReset())
+ return FALSE;
+ }
+
+ // construct the packet to send to the DS2480
+ // check if correct mode
+ if (UMode != MODSEL_DATA)
+ {
+ UMode = MODSEL_DATA;
+ sendpacket[sendlen++] = MODE_DATA;
+ }
+
+ // add the bytes to send
+ for (i = 0; i < TransferLen; i++)
+ {
+ sendpacket[sendlen++] = TransferBuffer[i];
+
+ // check for duplication of data that looks like COMMAND mode
+ if (TransferBuffer[i] == MODE_COMMAND)
+ sendpacket[sendlen++] = TransferBuffer[i];
+ }
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the response
+ if (ReadCOM(TransferLen,TransferBuffer) == TransferLen)
+ return TRUE;
+ }
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect();
+
+ 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 'StartPage'. Note that this function is limited
+// to single page packets. The buffer 'ReadBuffer' 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.
+//
+// 'DoAccess' - flag to indicate if an 'MLanAccess' should be
+// peformed at the begining of the read. This may
+// be FALSE (0) if the previous call was to read the
+// previous page (StartPage-1).
+// 'StartPage' - page number to start the read from
+// 'ReadBuffer' - 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
+//
+//
+int MLanReadPacketStd(int DoAccess, int StartPage, uchar *ReadBuffer)
+{
+ int i,length,TranCnt=0,HeadLen=0;
+ uchar TranBuf[50];
+
+ // check if access header is done
+ // (only use if in sequention read with one access at begining)
+ if (DoAccess)
+ {
+ // match command
+ TranBuf[TranCnt++] = 0x55;
+ for (i = 0; i < 8; i++)
+ TranBuf[TranCnt++] = SerialNum[i];
+ // read memory command
+ TranBuf[TranCnt++] = 0xF0;
+ // write the target address
+ TranBuf[TranCnt++] = ((StartPage << 5) & 0xFF);
+ TranBuf[TranCnt++] = (StartPage >> 3);
+ // check for DS1982 exception (redirection byte)
+ if (SerialNum[0] == 0x09)
+ TranBuf[TranCnt++] = 0xFF;
+ // record the header length
+ HeadLen = TranCnt;
+ }
+ // read the entire page length byte
+ for (i = 0; i < 32; i++)
+ TranBuf[TranCnt++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(DoAccess,TranBuf,TranCnt))
+ {
+ // seed crc with page number
+ CRC16 = StartPage;
+
+ // attempt to read UDP from TranBuf
+ length = TranBuf[HeadLen];
+ crc16(length);
+
+ // verify length is not too large
+ if (length <= 29)
+ {
+ // loop to read packet including CRC
+ for (i = 0; i < length; i++)
+ {
+ ReadBuffer[i] = TranBuf[i+1+HeadLen];
+ crc16(ReadBuffer[i]);
+ }
+
+ // read and compute the CRC16
+ crc16(TranBuf[i+1+HeadLen]);
+ crc16(TranBuf[i+2+HeadLen]);
+
+ // verify the CRC16 is correct
+ if (CRC16 == 0xB001)
+ return length; // return number of byte in record
+ }
+ }
+
+ // failed block or incorrect CRC
+ return -1;
+}
+
+
+//--------------------------------------------------------------------------
+// Write a Universal Data Packet onto a standard NVRAM 1-Wire device
+// on page 'StartPage'. This function is limited to UDPs that
+// fit on one page. The data to write is provided as a buffer
+// 'WriteBuffer' with a length 'WriteLength'.
+//
+// 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: DeviceEPROM=0
+// DS1992, DS1993, DS1994, DS1995, DS1996
+// DeviceEPROM=1, EPROMCRCType=0(CRC8)
+// DS1982
+// DeviceEPROM=1, EPROMCRCType=1(CRC16)
+// DS1985, DS1986, DS2407
+//
+// 'StartPage' - page number to write packet to
+// 'WriteBuffer' - pointer to buffer containing data to write
+// 'WriteLength' - number of data byte in WriteBuffer
+// 'DeviceEPROM' - flag set if device is an EPROM (1 EPROM, 0 NVRAM)
+// 'EPROMCRCType' - if DeviceEPROM=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
+//
+//
+int MLanWritePacketStd(int StartPage, uchar *WriteBuffer,
+ int WriteLength, int DeviceEPROM, int EPROMCRCType)
+{
+ uchar construct_buffer[32];
+ int i,buffer_cnt=0,start_address,do_access;
+
+ // check to see if data too long to fit on device
+ if (WriteLength > 29)
+ return FALSE;
+
+ // seed crc with page number
+ CRC16 = StartPage;
+
+ // set length byte
+ construct_buffer[buffer_cnt++] = (uchar)(WriteLength);
+ crc16(WriteLength);
+
+ // fill in the data to write
+ for (i = 0; i < WriteLength; i++)
+ {
+ crc16(WriteBuffer[i]);
+ construct_buffer[buffer_cnt++] = WriteBuffer[i];
+ }
+
+ // add the crc
+ construct_buffer[buffer_cnt++] = (uchar)(~(CRC16 & 0xFF));
+ construct_buffer[buffer_cnt++] = (uchar)(~((CRC16 & 0xFF00) >> 8));
+
+ // check if not EPROM
+ if (!DeviceEPROM)
+ {
+ // write the page
+ if (!Write_Scratchpad(construct_buffer,StartPage,buffer_cnt))
+ return FALSE;
+
+ // copy the scratchpad
+ if (!Copy_Scratchpad(StartPage,buffer_cnt))
+ return FALSE;
+
+ // copy scratch pad was good then success
+ return TRUE;
+ }
+ // is EPROM
+ else
+ {
+ // calculate the start address
+ start_address = ((StartPage >> 3) << 8) | ((StartPage << 5) & 0xFF);
+ do_access = TRUE;
+ // loop to program each byte
+ for (i = 0; i < buffer_cnt; i++)
+ {
+ if (MLanProgramByte(construct_buffer[i], start_address + i,
+ 0x0F, EPROMCRCType, do_access) != construct_buffer[i])
+ return FALSE;
+ do_access = FALSE;
+ }
+ return TRUE;
+ }
+}
+
+
+//--------------------------------------------------------------------------
+// Write a byte to an EPROM 1-Wire device.
+//
+// Supported devices: CRCType=0(CRC8)
+// DS1982
+// CRCType=1(CRC16)
+// DS1985, DS1986, DS2407
+//
+// 'WRByte' - byte to program
+// 'Addr' - address of byte to program
+// 'WriteCommand' - command used to write (0x0F reg mem, 0x55 status)
+// 'CRCType' - CRC used (0 CRC8, 1 CRC16)
+// 'DoAccess' - Flag to access device for each byte
+// (0 skip access, 1 do the access)
+// WARNING, only use DoAccess=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
+//
+int MLanProgramByte(int WRByte, int Addr, int WriteCommand,
+ int CRCType, int DoAccess)
+{
+ // optionally access the device
+ if (DoAccess)
+ {
+ if (!MLanAccess())
+ return -1;
+
+ // send the write command
+ if (!MLanWriteByte(WriteCommand))
+ return -1;
+
+ // send the address
+ if (!MLanWriteByte(Addr & 0xFF))
+ return -1;
+ if (!MLanWriteByte(Addr >> 8))
+ return -1;
+ }
+
+ // send the data to write
+ if (!MLanWriteByte(WRByte))
+ return -1;
+
+ // read the CRC
+ if (CRCType == 0)
+ {
+ // calculate CRC8
+ if (DoAccess)
+ {
+ DOWCRC = 0;
+ dowcrc((uchar)WriteCommand);
+ dowcrc((uchar)(Addr & 0xFF));
+ dowcrc((uchar)(Addr >> 8));
+ }
+ else
+ DOWCRC = (uchar)(Addr & 0xFF);
+
+ dowcrc((uchar)WRByte);
+ // read and calculate the read crc
+ dowcrc((uchar)MLanReadByte());
+ // crc should now be 0x00
+ if (DOWCRC != 0)
+ return -1;
+ }
+ else
+ {
+ // CRC16
+ if (DoAccess)
+ {
+ CRC16 = 0;
+ crc16(WriteCommand);
+ crc16(Addr & 0xFF);
+ crc16(Addr >> 8);
+ }
+ else
+ CRC16 = Addr;
+ crc16(WRByte);
+ // read and calculate the read crc
+ crc16(MLanReadByte());
+ crc16(MLanReadByte());
+ // crc should now be 0xB001
+ if (CRC16 != 0xB001)
+ return -1;
+ }
+
+ // send the program pulse
+ if (!MLanProgramPulse())
+ return -1;
+
+ // read back and return the resulting byte
+ return MLanReadByte();
+}
+
+
+//--------------------------------------------------------------------------
+// Write the scratchpad of a standard NVRam device such as the DS1992,3,4
+// and verify its contents.
+//
+// 'WriteBuffer' - pointer to buffer containing data to write
+// 'StartPage' - page number to write packet to
+// 'WriteLength' - number of data byte in WriteBuffer
+//
+// Returns: TRUE(1) success, the data was written and verified
+// FALSE(0) failure, the data could not be written
+//
+//
+int Write_Scratchpad(uchar *WriteBuffer, int StartPage, int WriteLength)
+{
+ int i,TranCnt=0;
+ uchar TranBuf[50];
+
+ // match command
+ TranBuf[TranCnt++] = 0x55;
+ for (i = 0; i < 8; i++)
+ TranBuf[TranCnt++] = SerialNum[i];
+ // write scratchpad command
+ TranBuf[TranCnt++] = 0x0F;
+ // write the target address
+ TranBuf[TranCnt++] = ((StartPage << 5) & 0xFF);
+ TranBuf[TranCnt++] = (StartPage >> 3);
+
+ // write packet bytes
+ for (i = 0; i < WriteLength; i++)
+ TranBuf[TranCnt++] = WriteBuffer[i];
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(TRUE,TranBuf,TranCnt))
+ {
+ // now attempt to read back to check
+ TranCnt = 0;
+ // match command
+ TranBuf[TranCnt++] = 0x55;
+ for (i = 0; i < 8; i++)
+ TranBuf[TranCnt++] = SerialNum[i];
+ // read scratchpad command
+ TranBuf[TranCnt++] = 0xAA;
+ // read the target address, offset and data
+ for (i = 0; i < (WriteLength + 3); i++)
+ TranBuf[TranCnt++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(TRUE,TranBuf,TranCnt))
+ {
+ // check address and offset of scratchpad read
+ if ((TranBuf[10] != (int)((StartPage << 5) & 0xFF)) ||
+ (TranBuf[11] != (int)(StartPage >> 3)) ||
+ (TranBuf[12] != (int)(WriteLength - 1)))
+ return FALSE;
+
+ // verify each data byte
+ for (i = 0; i < WriteLength; i++)
+ if (TranBuf[i+13] != WriteBuffer[i])
+ return FALSE;
+
+ // must have verified
+ return TRUE;
+ }
+ }
+
+ // 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.
+//
+// 'StartPage' - page number to write packet to
+// 'WriteLength' - number of data bytes that are being copied
+//
+// Returns: TRUE(1) success
+// FALSE(0) failure
+//
+int Copy_Scratchpad(int StartPage, int WriteLength)
+{
+ int i,TranCnt=0;
+ uchar TranBuf[50];
+
+ // match command
+ TranBuf[TranCnt++] = 0x55;
+ for (i = 0; i < 8; i++)
+ TranBuf[TranCnt++] = SerialNum[i];
+ // copy scratchpad command
+ TranBuf[TranCnt++] = 0x55;
+ // write the target address
+ TranBuf[TranCnt++] = ((StartPage << 5) & 0xFF);
+ TranBuf[TranCnt++] = (StartPage >> 3);
+ TranBuf[TranCnt++] = WriteLength - 1;
+ // read copy result
+ TranBuf[TranCnt++] = 0xFF;
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(TRUE,TranBuf,TranCnt))
+ {
+ // check address and offset of scratchpad read
+ if ((TranBuf[10] != (int)((StartPage << 5) & 0xFF)) ||
+ (TranBuf[11] != (int)(StartPage >> 3)) ||
+ (TranBuf[12] != (int)(WriteLength - 1)) ||
+ (TranBuf[13] & 0xF0))
+ return FALSE;
+ else
+ return TRUE;
+ }
+
+ // failed a block tranfer
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Calculate a new CRC16 from the input data integer. Return the current
+// CRC16 and also update the global variable CRC16.
+//
+// 'data' - data to perform a CRC16 on
+//
+// Returns: the current CRC16
+//
+static short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
+
+unsigned short crc16(int data)
+{
+ data = (data ^ (CRC16 & 0xff)) & 0xff;
+ CRC16 >>= 8;
+
+ if (oddparity[data & 0xf] ^ oddparity[data >> 4])
+ CRC16 ^= 0xc001;
+
+ data <<= 6;
+ CRC16 ^= data;
+ data <<= 1;
+ CRC16 ^= data;
+
+ return CRC16;
+}
+
+