diff options
Diffstat (limited to 'src/pmdas/roomtemp/mlan/mlantrnu.c')
-rw-r--r-- | src/pmdas/roomtemp/mlan/mlantrnu.c | 579 |
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; +} + + |