summaryrefslogtreecommitdiff
path: root/src/pmdas/roomtemp/mlan/mlannetu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/roomtemp/mlan/mlannetu.c')
-rw-r--r--src/pmdas/roomtemp/mlan/mlannetu.c599
1 files changed, 599 insertions, 0 deletions
diff --git a/src/pmdas/roomtemp/mlan/mlannetu.c b/src/pmdas/roomtemp/mlan/mlannetu.c
new file mode 100644
index 0000000..88ddbbd
--- /dev/null
+++ b/src/pmdas/roomtemp/mlan/mlannetu.c
@@ -0,0 +1,599 @@
+//---------------------------------------------------------------------------
+// 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.
+//---------------------------------------------------------------------------
+//
+// MLanNetU.C - Network 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 MicroLAN functions required
+extern int MLanTouchReset(void);
+extern int MLanTouchBit(int);
+extern int MLanWriteByte(int sendbyte);
+extern int MLanReadByte(void);
+extern int MLanSpeed(int);
+extern int MLanLevel(int);
+extern int MLanBlock(int, uchar *, int);
+
+// external COM functions required
+extern void FlushCOM(void);
+extern int WriteCOM(int, uchar *);
+extern int ReadCOM(int, uchar *);
+
+// external DS2480 utility function
+extern int DS2480Detect(void);
+
+// exportable functions
+int MLanFirst(int,int);
+int MLanNext(int,int);
+void MLanSerialNum(uchar *, int);
+void MLanFamilySearchSetup(int);
+void MLanSkipFamily(void);
+int MLanAccess(void);
+int MLanVerify(int);
+int MLanOverdriveAccess(void);
+
+// local functions
+int bitacc(int, int, int, uchar *);
+uchar dowcrc(uchar);
+
+// global variables for this module to hold search state information
+static int LastDiscrepancy;
+static int LastFamilyDiscrepancy;
+static int LastDevice;
+uchar DOWCRC;
+uchar SerialNum[8];
+
+// external globals
+extern int UMode;
+extern int UBaud;
+extern int USpeed;
+
+//--------------------------------------------------------------------------
+// The 'MLanFirst' finds the first device on the MicroLAN This function
+// contains one parameter 'OnlyAlarmingDevices'. When
+// 'OnlyAlarmingDevices' is TRUE (1) the find alarm command 0xEC is
+// sent instead of the normal search command 0xF0.
+// Using the find alarm command 0xEC will limit the search to only
+// 1-Wire devices that are in an 'alarm' state.
+//
+// 'DoReset' - TRUE (1) perform reset before search, FALSE (0) do not
+// perform reset before search.
+// 'OnlyAlarmDevices' - TRUE (1) the find alarm command 0xEC is
+// sent instead of the normal search command 0xF0
+//
+// Returns: TRUE (1) : when a 1-Wire device was found and it's
+// Serial Number placed in the global SerialNum
+// FALSE (0): There are no devices on the MicroLAN.
+//
+int MLanFirst(int DoReset, int OnlyAlarmingDevices)
+{
+ // reset the search state
+ LastDiscrepancy = 0;
+ LastDevice = FALSE;
+ LastFamilyDiscrepancy = 0;
+
+ return MLanNext(DoReset, OnlyAlarmingDevices);
+}
+
+//--------------------------------------------------------------------------
+// The 'MLanNext' function does a general search. This function
+// continues from the previos search state. The search state
+// can be reset by using the 'MLanFirst' function.
+// This function contains one parameter 'OnlyAlarmingDevices'.
+// When 'OnlyAlarmingDevices' is TRUE (1) the find alarm command
+// 0xEC is sent instead of the normal search command 0xF0.
+// Using the find alarm command 0xEC will limit the search to only
+// 1-Wire devices that are in an 'alarm' state.
+//
+// 'DoReset' - TRUE (1) perform reset before search, FALSE (0) do not
+// perform reset before search.
+// 'OnlyAlarmDevices' - TRUE (1) the find alarm command 0xEC is
+// sent instead of the normal search command 0xF0
+//
+// Returns: TRUE (1) : when a 1-Wire device was found and it's
+// Serial Number placed in the global SerialNum
+// FALSE (0): when no new device was found. Either the
+// last search was the last device or there
+// are no devices on the MicroLAN.
+//
+int MLanNext(int DoReset, int OnlyAlarmingDevices)
+{
+ int i,TempLastDescrepancy,pos;
+ uchar TempSerialNum[8];
+ uchar readbuffer[20],sendpacket[40];
+ int sendlen=0;
+
+ // if the last call was the last one
+ if (LastDevice)
+ {
+ // reset the search
+ LastDiscrepancy = 0;
+ LastDevice = FALSE;
+ LastFamilyDiscrepancy = 0;
+ return FALSE;
+ }
+
+ // check if reset first is requested
+ if (DoReset)
+ {
+ // reset the 1-wire
+ // if there are no parts on 1-wire, return FALSE
+ if (!MLanTouchReset())
+ {
+ // reset the search
+ LastDiscrepancy = 0;
+ LastFamilyDiscrepancy = 0;
+ return FALSE;
+ }
+ }
+
+ // build the command stream
+ // call a function that may add the change mode command to the buff
+ // check if correct mode
+ if (UMode != MODSEL_DATA)
+ {
+ UMode = MODSEL_DATA;
+ sendpacket[sendlen++] = MODE_DATA;
+ }
+
+ // search command
+ if (OnlyAlarmingDevices)
+ sendpacket[sendlen++] = 0xEC; // issue the alarming search command
+ else
+ sendpacket[sendlen++] = 0xF0; // issue the search command
+
+ // change back to command mode
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+
+ // search mode on
+ sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHON | USpeed);
+
+ // change back to data mode
+ UMode = MODSEL_DATA;
+ sendpacket[sendlen++] = MODE_DATA;
+
+ // set the temp Last Descrep to none
+ TempLastDescrepancy = 0xFF;
+
+ // add the 16 bytes of the search
+ pos = sendlen;
+ for (i = 0; i < 16; i++)
+ sendpacket[sendlen++] = 0;
+
+ // only modify bits if not the first search
+ if (LastDiscrepancy != 0xFF)
+ {
+ // set the bits in the added buffer
+ for (i = 0; i < 64; i++)
+ {
+ // before last discrepancy
+ if (i < (LastDiscrepancy - 1))
+ bitacc(WRITE_FUNCTION,
+ bitacc(READ_FUNCTION,0,i,&SerialNum[0]),
+ (short)(i * 2 + 1),
+ &sendpacket[pos]);
+ // at last discrepancy
+ else if (i == (LastDiscrepancy - 1))
+ bitacc(WRITE_FUNCTION,1,
+ (short)(i * 2 + 1),
+ &sendpacket[pos]);
+ // after last discrepancy so leave zeros
+ }
+ }
+
+ // change back to command mode
+ UMode = MODSEL_COMMAND;
+ sendpacket[sendlen++] = MODE_COMMAND;
+
+ // search OFF
+ sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed);
+
+ // flush the buffers
+ FlushCOM();
+
+ // send the packet
+ if (WriteCOM(sendlen,sendpacket))
+ {
+ // read back the 1 byte response
+ if (ReadCOM(17,readbuffer) == 17)
+ {
+ // interpret the bit stream
+ for (i = 0; i < 64; i++)
+ {
+ // get the SerialNum bit
+ bitacc(WRITE_FUNCTION,
+ bitacc(READ_FUNCTION,0,(short)(i * 2 + 1),&readbuffer[1]),
+ i,
+ &TempSerialNum[0]);
+ // check LastDiscrepancy
+ if ((bitacc(READ_FUNCTION,0,(short)(i * 2),&readbuffer[1]) == 1) &&
+ (bitacc(READ_FUNCTION,0,(short)(i * 2 + 1),&readbuffer[1]) == 0))
+ {
+ TempLastDescrepancy = i + 1;
+ // check LastFamilyDiscrepancy
+ if (i < 8)
+ LastFamilyDiscrepancy = i + 1;
+ }
+ }
+
+ // do dowcrc
+ DOWCRC = 0;
+ for (i = 0; i < 8; i++)
+ dowcrc(TempSerialNum[i]);
+
+ // check results
+ if ((DOWCRC != 0) || (LastDiscrepancy == 63) || (TempSerialNum[0] == 0))
+ {
+ // error during search
+ // reset the search
+ LastDiscrepancy = 0;
+ LastDevice = FALSE;
+ LastFamilyDiscrepancy = 0;
+ return FALSE;
+ }
+ // successful search
+ else
+ {
+ // check for lastone
+ if ((TempLastDescrepancy == LastDiscrepancy) || (TempLastDescrepancy == 0xFF))
+ LastDevice = TRUE;
+
+ // copy the SerialNum to the buffer
+ for (i = 0; i < 8; i++)
+ SerialNum[i] = TempSerialNum[i];
+
+ // set the count
+ LastDiscrepancy = TempLastDescrepancy;
+ return TRUE;
+ }
+ }
+ }
+
+ // an error occured so re-sync with DS2480
+ DS2480Detect();
+
+ // reset the search
+ LastDiscrepancy = 0;
+ LastDevice = FALSE;
+ LastFamilyDiscrepancy = 0;
+
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// The 'MLanSerialNum' function either reads or sets the SerialNum buffer
+// that is used in the search functions 'MLanFirst' and 'MLanNext'.
+// This function contains two parameters, 'SerialNumBuf' is a pointer
+// to a buffer provided by the caller. 'SerialNumBuf' should point to
+// an array of 8 unsigned chars. The second parameter is a flag called
+// 'DoRead' that is TRUE (1) if the operation is to read and FALSE
+// (0) if the operation is to set the internal SerialNum buffer from
+// the data in the provided buffer.
+//
+// 'SerialNumBuf' - buffer to that contains the serial number to set
+// when DoRead = FALSE (0) and buffer to get the serial
+// number when DoRead = TRUE (1).
+// 'DoRead' - flag to indicate reading (1) or setting (0) the current
+// serial number.
+//
+void MLanSerialNum(uchar *SerialNumBuf, int DoRead)
+{
+ int i;
+
+ // read the internal buffer and place in 'SerialNumBuf'
+ if (DoRead)
+ {
+ for (i = 0; i < 8; i++)
+ SerialNumBuf[i] = SerialNum[i];
+ }
+ // set the internal buffer from the data in 'SerialNumBuf'
+ else
+ {
+ for (i = 0; i < 8; i++)
+ SerialNum[i] = SerialNumBuf[i];
+ }
+}
+
+
+//--------------------------------------------------------------------------
+// Setup the search algorithm to find a certain family of devices
+// the next time a search function is called 'MLanNext'.
+//
+// 'SearchFamily' - family code type to set the search algorithm to find
+// next.
+//
+void MLanFamilySearchSetup(int SearchFamily)
+{
+ int i;
+
+ // set the search state to find SearchFamily type devices
+ SerialNum[0] = (uchar)SearchFamily;
+ for (i = 1; i < 8; i++)
+ SerialNum[i] = 0;
+ LastDiscrepancy = 64;
+ LastDevice = FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Set the current search state to skip the current family code.
+//
+void MLanSkipFamily(void)
+{
+ // set the Last discrepancy to last family discrepancy
+ LastDiscrepancy = LastFamilyDiscrepancy;
+
+ // check for end of list
+ if (LastDiscrepancy == 0)
+ LastDevice = TRUE;
+}
+
+
+//--------------------------------------------------------------------------
+// The 'MLanAccess' function resets the 1-Wire and sends a MATCH Serial
+// Number command followed by the current SerialNum code. After this
+// function is complete the 1-Wire device is ready to accept device-specific
+// commands.
+//
+// Returns: TRUE (1) : reset indicates present and device is ready
+// for commands.
+// FALSE (0): reset does not indicate presence or echos 'writes'
+// are not correct.
+//
+int MLanAccess(void)
+{
+ uchar TranBuf[9];
+ int i;
+
+ // reset the 1-wire
+ if (MLanTouchReset())
+ {
+ // create a buffer to use with block function
+ // match Serial Number command 0x55
+ TranBuf[0] = 0x55;
+ // Serial Number
+ for (i = 1; i < 9; i++)
+ TranBuf[i] = SerialNum[i-1];
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(FALSE,TranBuf,9))
+ {
+ // verify that the echo of the writes was correct
+ for (i = 1; i < 9; i++)
+ if (TranBuf[i] != SerialNum[i-1])
+ return FALSE;
+ if (TranBuf[0] != 0x55)
+ return FALSE;
+ else
+ return TRUE;
+ }
+ }
+
+ // reset or match echo failed
+ return FALSE;
+}
+
+
+//----------------------------------------------------------------------
+// The function 'MLanVerify' verifies that the current device
+// is in contact with the MicroLAN.
+// Using the find alarm command 0xEC will verify that the device
+// is in contact with the MicroLAN and is in an 'alarm' state.
+//
+// 'OnlyAlarmingDevices' - TRUE (1) the find alarm command 0xEC
+// is sent instead of the normal search
+// command 0xF0.
+//
+// Returns: TRUE (1) : when the 1-Wire device was verified
+// to be on the MicroLAN
+// with OnlyAlarmingDevices == FALSE
+// or verified to be on the MicroLAN
+// AND in an alarm state when
+// OnlyAlarmingDevices == TRUE.
+// FALSE (0): the 1-Wire device was not on the
+// MicroLAN or if OnlyAlarmingDevices
+// == TRUE, the device may be on the
+// MicroLAN but in a non-alarm state.
+//
+int MLanVerify(int OnlyAlarmingDevices)
+{
+ int i,TranCnt=0,goodbits=0,cnt=0,s,tst;
+ uchar TranBuf[50];
+
+ // construct the search rom
+ if (OnlyAlarmingDevices)
+ TranBuf[TranCnt++] = 0xEC; // issue the alarming search command
+ else
+ TranBuf[TranCnt++] = 0xF0; // issue the search command
+ // set all bits at first
+ for (i = 1; i <= 24; i++)
+ TranBuf[TranCnt++] = 0xFF;
+ // now set or clear apropriate bits for search
+ for (i = 0; i < 64; i++)
+ bitacc(WRITE_FUNCTION,bitacc(READ_FUNCTION,0,i,&SerialNum[0]),(int)((i+1)*3-1),&TranBuf[1]);
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(TRUE,TranBuf,TranCnt))
+ {
+ // check results to see if it was a success
+ for (i = 0; i < 192; i += 3)
+ {
+ tst = (bitacc(READ_FUNCTION,0,i,&TranBuf[1]) << 1) |
+ bitacc(READ_FUNCTION,0,(int)(i+1),&TranBuf[1]);
+
+ s = bitacc(READ_FUNCTION,0,cnt++,&SerialNum[0]);
+
+ if (tst == 0x03) // no device on line
+ {
+ goodbits = 0; // number of good bits set to zero
+ break; // quit
+ }
+
+ if (((s == 0x01) && (tst == 0x02)) ||
+ ((s == 0x00) && (tst == 0x01)) ) // correct bit
+ goodbits++; // count as a good bit
+ }
+
+ // check too see if there were enough good bits to be successful
+ if (goodbits >= 8)
+ return TRUE;
+ }
+
+ // block fail or device not present
+ return FALSE;
+}
+
+
+//----------------------------------------------------------------------
+// Perform a overdrive MATCH command to select the 1-Wire device with
+// the address in the ID data register.
+//
+// Returns: TRUE: If the device is present on the MicroLAN and
+// can do overdrive then the device is selected.
+// FALSE: Device is not present or not capable of overdrive.
+//
+// *Note: This function could be converted to send DS2480
+// commands in one packet.
+//
+int MLanOverdriveAccess(void)
+{
+ uchar TranBuf[8];
+ int i, EchoBad = FALSE;
+
+ // make sure normal level
+ MLanLevel(MODE_NORMAL);
+
+ // force to normal communication speed
+ MLanSpeed(MODE_NORMAL);
+
+ // call the MicroLAN reset function
+ if (MLanTouchReset())
+ {
+ // send the match command 0x69
+ if (MLanWriteByte(0x69))
+ {
+ // switch to overdrive communication speed
+ MLanSpeed(MODE_OVERDRIVE);
+
+ // create a buffer to use with block function
+ // Serial Number
+ for (i = 0; i < 8; i++)
+ TranBuf[i] = SerialNum[i];
+
+ // send/recieve the transfer buffer
+ if (MLanBlock(FALSE,TranBuf,8))
+ {
+ // verify that the echo of the writes was correct
+ for (i = 0; i < 8; i++)
+ if (TranBuf[i] != SerialNum[i])
+ EchoBad = TRUE;
+ // if echo ok then success
+ if (!EchoBad)
+ return TRUE;
+ }
+ }
+ }
+
+ // failure, force back to normal communication speed
+ MLanSpeed(MODE_NORMAL);
+
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------
+// Update the Dallas Semiconductor One Wire CRC (DOWCRC) from the global
+// variable DOWCRC and the argument.
+//
+// 'x' - data byte to calculate the 8 bit crc from
+//
+// Returns: the updated DOWCRC.
+//
+uchar dscrc_table[] = {
+ 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
+ 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
+ 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
+ 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
+ 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
+ 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
+ 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
+ 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
+ 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
+ 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
+ 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
+ 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
+ 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
+ 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
+ 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
+ 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
+
+uchar dowcrc(uchar x)
+{
+ DOWCRC = dscrc_table[DOWCRC ^ x];
+ return DOWCRC;
+}
+
+
+//--------------------------------------------------------------------------
+// Bit utility to read and write a bit in the buffer 'buf'.
+//
+// 'op' - operation (1) to set and (0) to read
+// 'state' - set (1) or clear (0) if operation is write (1)
+// 'loc' - bit number location to read or write
+// 'buf' - pointer to array of bytes that contains the bit
+// to read or write
+//
+// Returns: 1 if operation is set (1)
+// 0/1 state of bit number 'loc' if operation is reading
+//
+int bitacc(int op, int state, int loc, uchar *buf)
+{
+ int nbyt,nbit;
+
+ nbyt = (loc / 8);
+ nbit = loc - (nbyt * 8);
+
+ if (op == WRITE_FUNCTION)
+ {
+ if (state)
+ buf[nbyt] |= (0x01 << nbit);
+ else
+ buf[nbyt] &= ~(0x01 << nbit);
+
+ return 1;
+ }
+ else
+ return ((buf[nbyt] >> nbit) & 0x01);
+}