diff options
Diffstat (limited to 'src/pmdas/roomtemp/mlan')
-rw-r--r-- | src/pmdas/roomtemp/mlan/GNUmakefile | 45 | ||||
-rw-r--r-- | src/pmdas/roomtemp/mlan/ds2480.h | 183 | ||||
-rw-r--r-- | src/pmdas/roomtemp/mlan/ds2480ut.c | 206 | ||||
-rw-r--r-- | src/pmdas/roomtemp/mlan/linuxlnk.c | 443 | ||||
-rw-r--r-- | src/pmdas/roomtemp/mlan/mlan.h | 94 | ||||
-rw-r--r-- | src/pmdas/roomtemp/mlan/mlanllu.c | 499 | ||||
-rw-r--r-- | src/pmdas/roomtemp/mlan/mlannetu.c | 599 | ||||
-rw-r--r-- | src/pmdas/roomtemp/mlan/mlansesu.c | 102 | ||||
-rw-r--r-- | src/pmdas/roomtemp/mlan/mlantrnu.c | 579 |
9 files changed, 2750 insertions, 0 deletions
diff --git a/src/pmdas/roomtemp/mlan/GNUmakefile b/src/pmdas/roomtemp/mlan/GNUmakefile new file mode 100644 index 0000000..f6e33ae --- /dev/null +++ b/src/pmdas/roomtemp/mlan/GNUmakefile @@ -0,0 +1,45 @@ +#!gmake +# +# Copyright (c) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + +TOPDIR = ../../../.. +include $(TOPDIR)/src/include/builddefs + +CFILES=mlannetu.c mlansesu.c mlanllu.c linuxlnk.c ds2480ut.c mlantrnu.c +HFILES=mlan.h ds2480.h +STATICLIBTARGET = libmlan.a +LDIRT = libmlan.a +LCFLAGS = -g + +default : $(STATICLIBTARGET) + +ifeq "$(findstring $(TARGET_OS),solaris linux)" "" +default: +else +default : $(STATICLIBTARGET) +endif + +.NOTPARALLEL: + +install : + +default_pcp : default + +install_pcp : install + +include $(BUILDRULES) diff --git a/src/pmdas/roomtemp/mlan/ds2480.h b/src/pmdas/roomtemp/mlan/ds2480.h new file mode 100644 index 0000000..139e2c4 --- /dev/null +++ b/src/pmdas/roomtemp/mlan/ds2480.h @@ -0,0 +1,183 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// DS2480.H - This file contains the DS2480 constants +// +// Version: 1.03 +// History: 1.02 -> 1.03 Make sure uchar is not defined twice. +// +// + +// typedefs +#ifndef UCHAR + #define UCHAR + typedef unsigned char uchar; +#endif + +// Mode Commands +#define MODE_DATA 0xE1 +#define MODE_COMMAND 0xE3 +#define MODE_STOP_PULSE 0xF1 + +// Return byte value +#define RB_CHIPID_MASK 0x1C +#define RB_RESET_MASK 0x03 +#define RB_1WIRESHORT 0x00 +#define RB_PRESENCE 0x01 +#define RB_ALARMPRESENCE 0x02 +#define RB_NOPRESENCE 0x03 + +#define RB_BIT_MASK 0x03 +#define RB_BIT_ONE 0x03 +#define RB_BIT_ZERO 0x00 + +// Masks for all bit ranges +#define CMD_MASK 0x80 +#define FUNCTSEL_MASK 0x60 +#define BITPOL_MASK 0x10 +#define SPEEDSEL_MASK 0x0C +#define MODSEL_MASK 0x02 +#define PARMSEL_MASK 0x70 +#define PARMSET_MASK 0x0E + +// Command or config bit +#define CMD_COMM 0x81 +#define CMD_CONFIG 0x01 + +// Function select bits +#define FUNCTSEL_BIT 0x00 +#define FUNCTSEL_SEARCHON 0x30 +#define FUNCTSEL_SEARCHOFF 0x20 +#define FUNCTSEL_RESET 0x40 +#define FUNCTSEL_CHMOD 0x60 + +// Bit polarity/Pulse voltage bits +#define BITPOL_ONE 0x10 +#define BITPOL_ZERO 0x00 +#define BITPOL_5V 0x00 +#define BITPOL_12V 0x10 + +// One Wire speed bits +#define SPEEDSEL_STD 0x00 +#define SPEEDSEL_FLEX 0x04 +#define SPEEDSEL_OD 0x08 +#define SPEEDSEL_PULSE 0x0C + +// Data/Command mode select bits +#define MODSEL_DATA 0x00 +#define MODSEL_COMMAND 0x02 + +// 5V Follow Pulse select bits (If 5V pulse +// will be following the next byte or bit.) +#define PRIME5V_TRUE 0x02 +#define PRIME5V_FALSE 0x00 + +// Parameter select bits +#define PARMSEL_PARMREAD 0x00 +#define PARMSEL_SLEW 0x10 +#define PARMSEL_12VPULSE 0x20 +#define PARMSEL_5VPULSE 0x30 +#define PARMSEL_WRITE1LOW 0x40 +#define PARMSEL_SAMPLEOFFSET 0x50 +#define PARMSEL_ACTIVEPULLUPTIME 0x60 +#define PARMSEL_BAUDRATE 0x70 + +// Pull down slew rate. +#define PARMSET_Slew15Vus 0x00 +#define PARMSET_Slew2p2Vus 0x02 +#define PARMSET_Slew1p65Vus 0x04 +#define PARMSET_Slew1p37Vus 0x06 +#define PARMSET_Slew1p1Vus 0x08 +#define PARMSET_Slew0p83Vus 0x0A +#define PARMSET_Slew0p7Vus 0x0C +#define PARMSET_Slew0p55Vus 0x0E + +// 12V programming pulse time table +#define PARMSET_32us 0x00 +#define PARMSET_64us 0x02 +#define PARMSET_128us 0x04 +#define PARMSET_256us 0x06 +#define PARMSET_512us 0x08 +#define PARMSET_1024us 0x0A +#define PARMSET_2048us 0x0C +#define PARMSET_infinite 0x0E + +// 5V strong pull up pulse time table +#define PARMSET_16p4ms 0x00 +#define PARMSET_65p5ms 0x02 +#define PARMSET_131ms 0x04 +#define PARMSET_262ms 0x06 +#define PARMSET_524ms 0x08 +#define PARMSET_1p05s 0x0A +#define PARMSET_2p10s 0x0C +#define PARMSET_infinite 0x0E + +// Write 1 low time +#define PARMSET_Write8us 0x00 +#define PARMSET_Write9us 0x02 +#define PARMSET_Write10us 0x04 +#define PARMSET_Write11us 0x06 +#define PARMSET_Write12us 0x08 +#define PARMSET_Write13us 0x0A +#define PARMSET_Write14us 0x0C +#define PARMSET_Write15us 0x0E + +// Data sample offset and Write 0 recovery time +#define PARMSET_SampOff3us 0x00 +#define PARMSET_SampOff4us 0x02 +#define PARMSET_SampOff5us 0x04 +#define PARMSET_SampOff6us 0x06 +#define PARMSET_SampOff7us 0x08 +#define PARMSET_SampOff8us 0x0A +#define PARMSET_SampOff9us 0x0C +#define PARMSET_SampOff10us 0x0E + +// Active pull up on time +#define PARMSET_PullUp0p0us 0x00 +#define PARMSET_PullUp0p5us 0x02 +#define PARMSET_PullUp1p0us 0x04 +#define PARMSET_PullUp1p5us 0x06 +#define PARMSET_PullUp2p0us 0x08 +#define PARMSET_PullUp2p5us 0x0A +#define PARMSET_PullUp3p0us 0x0C +#define PARMSET_PullUp3p5us 0x0E + +// Baud rate bits +#define PARMSET_9600 0x00 +#define PARMSET_19200 0x02 +#define PARMSET_57600 0x04 +#define PARMSET_115200 0x06 + +// DS2480 program voltage available +#define DS2480PROG_MASK 0x20 + +// mode bit flags +#define MODE_NORMAL 0x00 +#define MODE_OVERDRIVE 0x01 +#define MODE_STRONG5 0x02 +#define MODE_PROGRAM 0x04 +#define MODE_BREAK 0x08 + diff --git a/src/pmdas/roomtemp/mlan/ds2480ut.c b/src/pmdas/roomtemp/mlan/ds2480ut.c new file mode 100644 index 0000000..d353743 --- /dev/null +++ b/src/pmdas/roomtemp/mlan/ds2480ut.c @@ -0,0 +1,206 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// ds2480ut.c - DS2480 utility functions. +// +// Version: 1.03 +// +// History: 1.00 -> 1.01 Default PDSRC changed from 0.83 to 1.37V/us +// in DS2480Detect. Changed to use msDelay instead +// of Delay. +// +// 1.01 -> 1.02 Changed global declarations from 'uchar' to 'int'. +// Changed DSO/WORT from 7 to 10us in DS2480Detect. +// +// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility + +#include "ds2480.h" +#include "mlan.h" + +// external COM functions required +extern void FlushCOM(void); +extern int WriteCOM(int, uchar *); +extern int ReadCOM(int, uchar *); +extern void BreakCOM(void); +//extern void SetBaudCOM(uchar); +extern void msDelay(int); + +// exportable functions +int DS2480Detect(void); +int DS2480ChangeBaud(uchar); + +// global DS2480 state +int UMode = MODSEL_COMMAND; // current DS2480 command or data mode stateuchar +int UBaud = PARMSET_9600; // current DS2480 baud rate +int USpeed = SPEEDSEL_FLEX; // current DS2480 MicroLAN communication speed +int ULevel = MODE_NORMAL; // current DS2480 MicroLAN level + +//--------------------------------------------------------------------------- +// Attempt to resyc and detect a DS2480 +// +// Returns: TRUE - DS2480 detected successfully +// FALSE - Could not detect DS2480 +// +int DS2480Detect(void) +{ + uchar sendpacket[10],readbuffer[10]; + short sendlen=0; + + // reset modes + UMode = MODSEL_COMMAND; + UBaud = PARMSET_9600; + USpeed = SPEEDSEL_FLEX; + + // set the baud rate to 9600 + SetBaudCOM((uchar)UBaud); + + // send a break to reset the DS2480 + BreakCOM(); + + // delay to let line settle + msDelay(2); + + // flush the buffers + FlushCOM(); + + // send the timing byte + sendpacket[0] = 0xC1; + if (WriteCOM(1,sendpacket) != 1) + return FALSE; + + // set the FLEX configuration parameters + // default PDSRC = 1.37Vus + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SLEW | PARMSET_Slew1p37Vus; + // default W1LT = 12us + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_WRITE1LOW | PARMSET_Write12us; + // default DSO/WORT = 10us + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_SAMPLEOFFSET | PARMSET_SampOff10us; + + // construct the command to read the baud rate (to test command block) + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); + + // also do 1 bit operation (to test 1-Wire block) + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_BIT | UBaud | BITPOL_ONE; + + // flush the buffers + FlushCOM(); + + // send the packet + if (WriteCOM(sendlen,sendpacket)) + { + // read back the response + if (ReadCOM(5,readbuffer) == 5) + { + // look at the baud rate and bit operation + // to see if the response makes sense + if (((readbuffer[3] & 0xF1) == 0x00) && + ((readbuffer[3] & 0x0E) == UBaud) && + ((readbuffer[4] & 0xF0) == 0x90) && + ((readbuffer[4] & 0x0C) == UBaud)) + return TRUE; + } + } + + return FALSE; +} + + +//--------------------------------------------------------------------------- +// Change the DS2480 from the current baud rate to the new baud rate. +// +// 'newbaud' - the new baud rate to change to, defined as: +// PARMSET_9600 0x00 +// PARMSET_19200 0x02 +// PARMSET_57600 0x04 +// PARMSET_115200 0x06 +// +// Returns: current DS2480 baud rate. +// +int DS2480ChangeBaud(uchar newbaud) +{ + int rt=FALSE; + uchar readbuffer[5],sendpacket[5],sendpacket2[5]; + int sendlen=0,sendlen2=0; + + // see if diffenent then current baud rate + if (UBaud == newbaud) + return TRUE; + else + { + // build the command packet + // check if correct mode + if (UMode != MODSEL_COMMAND) + { + UMode = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + // build the command + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_BAUDRATE | newbaud; + + // flush the buffers + FlushCOM(); + + // send the packet + if (!WriteCOM(sendlen,sendpacket)) + rt = FALSE; + else + { + // make sure buffer is flushed + msDelay(5); + + // change our baud rate + SetBaudCOM(newbaud); + UBaud = newbaud; + + // wait for things to settle + msDelay(5); + + // build a command packet to read back baud rate + sendpacket2[sendlen2++] = CMD_CONFIG | PARMSEL_PARMREAD | (PARMSEL_BAUDRATE >> 3); + + // flush the buffers + FlushCOM(); + + // send the packet + if (WriteCOM(sendlen2,sendpacket2)) + { + // read back the 1 byte response + if (ReadCOM(1,readbuffer) == 1) + { + // verify correct baud + if (((readbuffer[0] & 0x0E) == (sendpacket[sendlen-1] & 0x0E))) + rt = TRUE; + } + } + } + } + + // if lost communication with DS2480 then reset + if (rt != TRUE) + DS2480Detect(); + + return UBaud; +} diff --git a/src/pmdas/roomtemp/mlan/linuxlnk.c b/src/pmdas/roomtemp/mlan/linuxlnk.c new file mode 100644 index 0000000..aa20695 --- /dev/null +++ b/src/pmdas/roomtemp/mlan/linuxlnk.c @@ -0,0 +1,443 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// TODO.C - COM functions required by MLANLL.C, MLANTRNU, MLANNETU.C and +// MLanFile.C for MLANU to communicate with the DS2480 based +// Universal Serial Adapter 'U'. Fill in the platform specific code. +// +// Version: 1.02 +// +// History: 1.00 -> 1.01 Added function msDelay. +// +// 1.01 -> 1.02 Changed to generic OpenCOM/CloseCOM for easier +// use with other platforms. +// + +//-------------------------------------------------------------------------- +// Copyright (C) 1998 Andrea Chambers and University of Newcastle upon Tyne, +// 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 THE UNIVERSITY OF NEWCASTLE UPON TYNE OR ANDREA CHAMBERS +// 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. +//--------------------------------------------------------------------------- +// +// LinuxLNK.C - COM functions required by MLANLLU.C, MLANTRNU.C, MLANNETU.C +// and MLanFile.C for MLANU to communicate with the DS2480 based +// Universal Serial Adapter 'U'. Platform specific code. +// +// Version: 1.03 +// History: 1.00 -> 1.03 modifications by David Smiczek +// Changed to use generic OpenCOM/CloseCOM +// Pass port name to OpenCOM instead of hard coded +// Changed msDelay to handle long delays +// Reformatted to look like 'TODO.C' +// Added #include "ds2480.h" to use constants. +// Added function SetBaudCOM() +// Added function msGettick() +// Removed delay from WriteCOM(), used tcdrain() +// Added wait for byte available with timeout using +// select() in ReadCOM() +/* + cfmakeraw function from nut-0.45.0 package + common.c - common useful functions + + Copyright (C) 2000 Russell Kroll <rkroll@exploits.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <time.h> +#include <termios.h> +#include <sys/time.h> + +#include "mlan.h" +#include "ds2480.h" +#include "pmapi.h" + +// Exportable functions required for MLANLL.C, MLANTRNU.C, or MLANNETU.C +void FlushCOM(void); +int WriteCOM(int, unsigned char*); +int ReadCOM(int, unsigned char*); +void BreakCOM(void); +void msDelay(int); +long msGettick(void); + +// Exportable functions for opening/closing serial port +int OpenCOM(char *); +void CloseCOM(void); + +// LinuxLNK global +int fd; + +#ifdef IS_SOLARIS +int cfmakeraw(struct termios *termios_p) +{ + termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP + |INLCR|IGNCR|ICRNL|IXON); + termios_p->c_oflag &= ~OPOST; + termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + termios_p->c_cflag &= ~(CSIZE|PARENB); + termios_p->c_cflag |= CS8; + return 0; +} +#endif + +//-------------------------------------------------------------------------- +// Write an array of bytes to the COM port, verify that it was +// sent out. Assume that baud rate has been set. +// +// Returns 1 for success and 0 for failure +// +int WriteCOM(int outlen, uchar *outbuf) +{ + long count = outlen; + int i; + int sts; + + if (MLanDebug) { + fprintf(stderr, "WriteCOM: calling write: %d bytes:", outlen); + for (i = 0; i < outlen; i++) fprintf(stderr, " %02x", 0xff & outbuf[i]); + fputc('\n', stderr); + fflush(stderr); + } + + i = write(fd, outbuf, outlen); + + if (MLanDebug) { + fprintf(stderr, "WriteCOM: write returns %d\nWriteCOM: calling tcdrain\n", i); + fflush(stderr); + } + + sts = tcdrain(fd); + + if (MLanDebug) { + fprintf(stderr, "WriteCOM: tcdrain returns %d\n", sts); + fflush(stderr); + } + + return (i == count); +} + + +//-------------------------------------------------------------------------- +// Read an array of bytes to the COM port, verify that it was +// sent out. Assume that baud rate has been set. +// +// Returns number of characters read +// +int ReadCOM(int inlen, uchar *inbuf) +{ + fd_set filedescr; + struct timeval tval; + int cnt; + int sts; + + if (MLanDebug) { + fprintf(stderr, "ReadCOM: calling read: want %d bytes:", inlen); + fflush(stderr); + } + + // loop to wait until each byte is available and read it + for (cnt = 0; cnt < inlen; cnt++) + { + // set a descriptor to wait for a character available + FD_ZERO(&filedescr); + FD_SET(fd,&filedescr); + // set timeout to 10ms + tval.tv_sec = 0; + tval.tv_usec = 10000; + + // if byte available read or return bytes read + if (0 != select(fd+1,&filedescr,NULL,NULL,&tval)) { + if ((sts = read(fd,&inbuf[cnt],1)) != 1) { + if (MLanDebug) { + fprintf(stderr, ": read returns %d, got %d bytes\n", sts, cnt); + fflush(stderr); + } + return cnt; + } + if (MLanDebug) { + fprintf(stderr, " %02x", 0xff & inbuf[cnt]); + fflush(stderr); + } + } + else { + if (MLanDebug) { + fprintf(stderr, ": select timeout, got %d bytes\n", cnt); + fflush(stderr); + } + return cnt; + } + + } + + // success, so return desired length + if (MLanDebug) { + fprintf(stderr, ": got 'em all\n"); + fflush(stderr); + } + return inlen; +} + + +//--------------------------------------------------------------------------- +// Description: +// flush the rx and tx buffers +// +void FlushCOM(void) +{ + tcflush (fd, TCIOFLUSH); +} + + +//-------------------------------------------------------------------------- +// Description: +// Delay for at least 'len' ms +// +void msDelay(int len) +{ + struct timespec s; // Set aside memory space on the stack + + s.tv_sec = len / 1000; + s.tv_nsec = (len - (s.tv_sec * 1000)) * 1000000; + nanosleep(&s, NULL); +} + + +//-------------------------------------------------------------------------- +// Description: +// Send a break on the com port for at least 2 ms +// +void BreakCOM(void) +{ + int duration = 0; // see man termios break may be + tcsendbreak(fd, duration); // too long +} + + +//--------------------------------------------------------------------------- +// Attempt to open a com port. +// Set the starting baud rate to 9600. +// +// 'port_zstr' - zero terminate port name. Format is platform +// dependent. +// +// Returns: TRUE - success, COM port opened +// +int OpenCOM(char *port_zstr) +{ + struct termios t; // see man termios - declared as above + int rc; + + fd = open(port_zstr, O_RDWR|O_NONBLOCK); + if (fd<0) return fd; + rc = tcgetattr (fd, &t); + if (rc < 0) + { + int tmp; + tmp = oserror(); + close(fd); + setoserror(tmp); + return rc; + } + if (MLanDebug) { + fprintf(stderr, "OpenCOM: initial tty settings\niflag: %07o oflag: %07o lflag: %07o cflag: %07o\n", (unsigned int)t.c_iflag, (unsigned int)t.c_oflag, (unsigned int)t.c_lflag, (unsigned int)t.c_cflag); + fflush(stderr); + } + + cfsetospeed(&t, B9600); + cfsetispeed (&t, B9600); + +#ifdef IRIX +// IRIX tty games ... +// +// per the Linux man page cfmakeraw sets the terminal attributes as follows: +// + t.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + t.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON); + t.c_oflag &= ~OPOST; + t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + t.c_cflag &= ~(CSIZE|PARENB); + t.c_cflag |= CS8; +// to this we have to clear the additional IRIX goodies like: +// + t.c_iflag &= ~(IXANY|IGNPAR); + t.c_oflag &= ~(TAB3); +// and finally, CLOCAL is in c_cflag, not c_lflag +// + t.c_cflag |= CLOCAL; // ignore modem signals +#else +// assumed to be Linux +// + cfmakeraw(&t); // don't generate signals, translate or echo + t.c_lflag |= CLOCAL; // ignore modem signals +#endif + + if (MLanDebug) { + fprintf(stderr, "OpenCOM: new tty settings\niflag: %07o oflag: %07o lflag: %07o cflag: %07o\n", (unsigned int)t.c_iflag, (unsigned int)t.c_oflag, (unsigned int)t.c_lflag, (unsigned int)t.c_cflag); + fprintf(stderr, "OpenCOM: calling tcsetattr\n"); + fflush(stderr); + } + rc = tcsetattr (fd, TCSAFLUSH, &t); + if (MLanDebug) { + fprintf(stderr, "OpenCOM: tcsetattr returns %d\n", rc); + fflush(stderr); + } + if (rc < 0) + { + int tmp; + tmp = oserror(); + close(fd); + setoserror(tmp); + return rc; + } + + return fd; +} + + +//--------------------------------------------------------------------------- +// Closes the connection to the port. +// +void CloseCOM(void) +{ + FlushCOM(); + close(fd); +} + + +//-------------------------------------------------------------------------- +// Set the baud rate on the com port. The possible baud rates for +// 'new_baud' are: +// +// PARMSET_9600 0x00 +// PARMSET_19200 0x02 +// PARMSET_57600 0x04 +// PARMSET_115200 0x06 +// +void SetBaudCOM(int new_baud) +{ + struct termios t; + int rc; + speed_t baud = B0; + + // read the attribute structure + rc = tcgetattr(fd, &t); + if (rc < 0) + { + close(fd); + return; + } + + // convert parameter to linux baud rate + switch(new_baud) + { + case PARMSET_9600: + baud = B9600; + break; + case PARMSET_19200: + baud = B19200; + break; + case PARMSET_57600: +#ifdef B57600 + baud = B57600; + break; +#else +#define ERR_MSG_57600 "SetBaudCOM: no support for 57600 baud, sorry!" + write(2, ERR_MSG_57600, strlen(ERR_MSG_57600)); + exit(1); +#endif + case PARMSET_115200: +#ifdef B115200 + baud = B115200; + break; +#else +#define ERR_MSG_115200 "SetBaudCOM: no support for 115200 baud, sorry!" + write(2, ERR_MSG_115200, strlen(ERR_MSG_115200)); + exit(1); +#endif + } + + // set baud in structure + cfsetospeed(&t, baud); + cfsetispeed(&t, baud); + + // change baud on port + rc = tcsetattr(fd, TCSAFLUSH, &t); + if (rc < 0) + close(fd); +} + + +//-------------------------------------------------------------------------- +// Get the current millisecond tick count. Does not have to represent +// an actual time, it just needs to be an incrementing timer. +// +long msGettick(void) +{ + struct timezone tmzone; + struct timeval tmval; + long ms; + + gettimeofday(&tmval,&tmzone); + ms = (tmval.tv_sec & 0xFFFF) * 1000 + tmval.tv_usec / 1000; + return ms; +} + diff --git a/src/pmdas/roomtemp/mlan/mlan.h b/src/pmdas/roomtemp/mlan/mlan.h new file mode 100644 index 0000000..4ca742b --- /dev/null +++ b/src/pmdas/roomtemp/mlan/mlan.h @@ -0,0 +1,94 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// MLan.H - Include file for MicroLAN library +// +// Version: 1.03 +// History: 1.02 -> 1.03 Make sure uchar is not defined twice. +// + +// Typedefs +#ifndef UCHAR + #define UCHAR + typedef unsigned char uchar; +#endif +#if 0 +// not needed most places - kenmcd +typedef unsigned short ushort; +typedef unsigned long ulong; +#endif + +// general defines +#define WRITE_FUNCTION 1 +#define READ_FUNCTION 0 + +// error codes +#define READ_ERROR -1 +#define INVALID_DIR -2 +#define NO_FILE -3 +#define WRITE_ERROR -4 +#define WRONG_TYPE -5 +#define FILE_TOO_BIG -6 + +// Misc +#define FALSE 0 +#define TRUE 1 + +// mode bit flags +#define MODE_NORMAL 0x00 +#define MODE_OVERDRIVE 0x01 +#define MODE_STRONG5 0x02 +#define MODE_PROGRAM 0x04 +#define MODE_BREAK 0x08 + +// product families +#define TEMP_FAMILY 0x10 +#define SWITCH_FAMILY 0x12 +#define COUNT_FAMILY 0x1D +#define DIR_FAMILY 0x01 + +// externs +extern uchar DOWCRC; + +// debugging +extern int MLanDebug; + +// function prototypes +extern int Aquire1WireNet(char *, char *); +extern void Release1WireNet(char *); +extern int MLanAccess(void); +extern int MLanBlock(int DoReset, uchar *TransferBuffer, int TransferLen); +extern void MLanFamilySearchSetup(int SearchFamily); +extern int MLanLevel(int NewLevel); +extern int MLanNext(int DoReset, int OnlyAlarmingDevices); +extern void MLanSerialNum(uchar *SerialNumBuf, int DoRead); +extern int MLanTouchByte(int sendbyte); +extern int MLanVerify(int OnlyAlarmingDevices); +extern uchar dowcrc(uchar x); +extern void msDelay(int len); +extern int DS2480ChangeBaud(uchar newbaud); +extern void SetBaudCOM(int new_baud); + diff --git a/src/pmdas/roomtemp/mlan/mlanllu.c b/src/pmdas/roomtemp/mlan/mlanllu.c new file mode 100644 index 0000000..91b23f0 --- /dev/null +++ b/src/pmdas/roomtemp/mlan/mlanllu.c @@ -0,0 +1,499 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// MLanLLU.C - Link Layer MicroLAN functions using the DS2480 (U) +// serial interface chip. +// +// Version: 1.03 +// +// History: 1.00 -> 1.01 DS2480 version number now ignored in +// MLanTouchReset. +// 1.02 -> 1.03 Removed caps in #includes for Linux capatibility +// Removed #include <windows.h> +// Add #include "mlan.h" to define TRUE,FALSE + +#include "ds2480.h" +#include "mlan.h" + +// external COM functions required +extern void FlushCOM(void); +extern int WriteCOM(int, uchar *); +extern int ReadCOM(int, uchar *); +//extern void SetBaudCOM(int); + +// external DS2480 utility function +extern int DS2480Detect(void); +//extern int DS2480ChangeBaud(int); + +// local functions +int MLanTouchReset(void); +int MLanTouchBit(int sendbit); +int MLanTouchByte(int sendbyte); +int MLanWriteByte(int sendbyte); +int MLanReadByte(void); +int MLanSpeed(int); +int MLanLevel(int); +int MLanProgramPulse(void); + +// external globals +extern int UMode; // current DS2480 command or data mode state +extern int UBaud; // current DS2480 baud rate +extern int USpeed; // current DS2480 MicroLAN communication speed +extern int ULevel; // current DS2480 MicroLAN level + +// local varable flag, true if program voltage available +static int ProgramAvailable=FALSE; + + +//-------------------------------------------------------------------------- +// Reset all of the devices on the MicroLAN and return the result. +// +// Returns: TRUE(1): presense pulse(s) detected, device(s) reset +// FALSE(0): no presense pulses detected +// +// WARNING: This routine will not function correctly on some +// Alarm reset types of the DS1994/DS1427/DS2404 with +// Rev 1 and 2 of the DS2480. +// +int MLanTouchReset(void) +{ + uchar readbuffer[10],sendpacket[10]; + int sendlen=0; + + // make sure normal level + MLanLevel(MODE_NORMAL); + + // check if correct mode + if (UMode != MODSEL_COMMAND) + { + UMode = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // construct the command + sendpacket[sendlen++] = (uchar)(CMD_COMM | FUNCTSEL_RESET | USpeed); + + // flush the buffers + FlushCOM(); + + // send the packet + if (WriteCOM(sendlen,sendpacket)) + { + // read back the 1 byte response + if (ReadCOM(1,readbuffer) == 1) + { + // make sure this byte looks like a reset byte + if (((readbuffer[0] & RB_RESET_MASK) == RB_PRESENCE) || + ((readbuffer[0] & RB_RESET_MASK) == RB_ALARMPRESENCE)) + { + // check if programming voltage available + ProgramAvailable = ((readbuffer[0] & 0x20) == 0x20); + return TRUE; + } + else + return FALSE; + } + } + + // an error occured so re-sync with DS2480 + DS2480Detect(); + + return FALSE; +} + + +//-------------------------------------------------------------------------- +// Send 1 bit of communication to the MicroLAN and return the +// result 1 bit read from the MicroLAN. The parameter 'sendbit' +// least significant bit is used and the least significant bit +// of the result is the return bit. +// +// 'sendbit' - the least significant bit is the bit to send +// +// Returns: 0: 0 bit read from sendbit +// 1: 1 bit read from sendbit +// +int MLanTouchBit(int sendbit) +{ + uchar readbuffer[10],sendpacket[10]; + int sendlen=0; + + // make sure normal level + MLanLevel(MODE_NORMAL); + + // check if correct mode + if (UMode != MODSEL_COMMAND) + { + UMode = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // construct the command + sendpacket[sendlen] = (sendbit != 0) ? BITPOL_ONE : BITPOL_ZERO; + sendpacket[sendlen++] |= CMD_COMM | FUNCTSEL_BIT | USpeed; + + // flush the buffers + FlushCOM(); + + // send the packet + if (WriteCOM(sendlen,sendpacket)) + { + // read back the response + if (ReadCOM(1,readbuffer) == 1) + { + // interpret the response + if (((readbuffer[0] & 0xE0) == 0x80) && + ((readbuffer[0] & RB_BIT_MASK) == RB_BIT_ONE)) + return 1; + else + return 0; + } + } + + // an error occured so re-sync with DS2480 + DS2480Detect(); + + return 0; +} + + +//-------------------------------------------------------------------------- +// Send 8 bits of communication to the MicroLAN and verify that the +// 8 bits read from the MicroLAN is the same (write operation). +// The parameter 'sendbyte' least significant 8 bits are used. +// +// 'sendbyte' - 8 bits to send (least significant byte) +// +// Returns: TRUE: bytes written and echo was the same +// FALSE: echo was not the same +// +int MLanWriteByte(int sendbyte) +{ + return (MLanTouchByte(sendbyte) == sendbyte) ? TRUE : FALSE; +} + + +//-------------------------------------------------------------------------- +// Send 8 bits of read communication to the MicroLAN and and return the +// result 8 bits read from the MicroLAN. +// +// Returns: 8 bytes read from MicroLAN +// +int MLanReadByte(void) +{ + return MLanTouchByte(0xFF); +} + + +//-------------------------------------------------------------------------- +// Send 8 bits of communication to the MicroLAN and return the +// result 8 bits read from the MicroLAN. The parameter 'sendbyte' +// least significant 8 bits are used and the least significant 8 bits +// of the result is the return byte. +// +// 'sendbyte' - 8 bits to send (least significant byte) +// +// Returns: 8 bytes read from sendbyte +// +int MLanTouchByte(int sendbyte) +{ + uchar readbuffer[10],sendpacket[10]; + int sendlen=0; + + // make sure normal level + MLanLevel(MODE_NORMAL); + + // check if correct mode + if (UMode != MODSEL_DATA) + { + UMode = MODSEL_DATA; + sendpacket[sendlen++] = MODE_DATA; + } + + // add the byte to send + sendpacket[sendlen++] = (uchar)sendbyte; + + // check for duplication of data that looks like COMMAND mode + if (sendbyte == MODE_COMMAND) + sendpacket[sendlen++] = (uchar)sendbyte; + + // flush the buffers + FlushCOM(); + + // send the packet + if (WriteCOM(sendlen,sendpacket)) + { + // read back the 1 byte response + if (ReadCOM(1,readbuffer) == 1) + { + // return the response + return (int)readbuffer[0]; + } + } + + // an error occured so re-sync with DS2480 + DS2480Detect(); + + return 0; +} + + +//-------------------------------------------------------------------------- +// Set the MicroLAN communucation speed. +// +// 'NewSpeed' - new speed defined as +// MODE_NORMAL 0x00 +// MODE_OVERDRIVE 0x01 +// +// Returns: current MicroLAN speed +// +int MLanSpeed(int NewSpeed) +{ + uchar sendpacket[5]; + short sendlen=0; + int rt = FALSE; + + // check if change from current mode + if (((NewSpeed == MODE_OVERDRIVE) && + (USpeed != SPEEDSEL_OD)) || + ((NewSpeed == MODE_NORMAL) && + (USpeed != SPEEDSEL_FLEX))) + { + if (NewSpeed == MODE_OVERDRIVE) + { + // if overdrive then switch to 115200 baud + if (DS2480ChangeBaud(PARMSET_57600) == PARMSET_57600) + { + USpeed = SPEEDSEL_OD; + rt = TRUE; + } + } + else if (NewSpeed == MODE_NORMAL) + { + // else normal so set to 9600 baud + if (DS2480ChangeBaud(PARMSET_9600) == PARMSET_9600) + { + USpeed = SPEEDSEL_FLEX; + rt = TRUE; + } + } + + // if baud rate is set correctly then change DS2480 speed + if (rt) + { + // check if correct mode + if (UMode != MODSEL_COMMAND) + { + UMode = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // proceed to set the DS2480 communication speed + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_SEARCHOFF | USpeed; + + // send the packet + if (!WriteCOM(sendlen,sendpacket)) + { + rt = FALSE; + // lost communication with DS2480 then reset + DS2480Detect(); + } + } + } + + // return the current speed + return (USpeed == SPEEDSEL_OD) ? MODE_OVERDRIVE : MODE_NORMAL; +} + + +//-------------------------------------------------------------------------- +// Set the MicroLAN line level. The values for NewLevel are +// as follows: +// +// 'NewLevel' - new level defined as +// MODE_NORMAL 0x00 +// MODE_STRONG5 0x02 +// MODE_PROGRAM 0x04 +// MODE_BREAK 0x08 (not supported) +// +// Returns: current MicroLAN level +// +int MLanLevel(int NewLevel) +{ + uchar sendpacket[10],readbuffer[10]; + short sendlen=0; + short rt=FALSE; + + // check if need to change level + if (NewLevel != ULevel) + { + // check if just putting back to normal + if (NewLevel == MODE_NORMAL) + { + // check if correct mode + if (UMode != MODSEL_COMMAND) + { + UMode = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // stop pulse command + sendpacket[sendlen++] = MODE_STOP_PULSE; + + // flush the buffers + FlushCOM(); + + // send the packet + if (WriteCOM(sendlen,sendpacket)) + { + // read back the 1 byte response + if (ReadCOM(1,readbuffer) == 1) + { + // check response byte + if ((readbuffer[0] & 0xE0) == 0xE0) + { + rt = TRUE; + ULevel = MODE_NORMAL; + } + } + } + } + // set new level + else + { + // check if correct mode + if (UMode != MODSEL_COMMAND) + { + UMode = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // strong 5 volts + if (NewLevel == MODE_STRONG5) + { + // set the SPUD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_5VPULSE | PARMSET_infinite; + // add the command to begin the pulse + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_5V; + } + // 12 volts + else if (NewLevel == MODE_PROGRAM) + { + // check if programming voltage available + if (!ProgramAvailable) + return MODE_NORMAL; + + // set the PPD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_infinite; + // add the command to begin the pulse + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | SPEEDSEL_PULSE | BITPOL_12V; + } + + // flush the buffers + FlushCOM(); + + // send the packet + if (WriteCOM(sendlen,sendpacket)) + { + // read back the 1 byte response from setting time limit + if (ReadCOM(1,readbuffer) == 1) + { + // check response byte + if ((readbuffer[0] & 0x81) == 0) + { + ULevel = NewLevel; + rt = TRUE; + } + } + } + } + + // if lost communication with DS2480 then reset + if (rt != TRUE) + DS2480Detect(); + } + + // return the current level + return ULevel; +} + + +//-------------------------------------------------------------------------- +// This procedure creates a fixed 480 microseconds 12 volt pulse +// on the MicroLAN for programming EPROM iButtons. +// +// Returns: TRUE successful +// FALSE program voltage not available +// +int MLanProgramPulse(void) +{ + uchar sendpacket[10],readbuffer[10]; + short sendlen=0; + + // check if programming voltage available + if (!ProgramAvailable) + return FALSE; + + // make sure normal level + MLanLevel(MODE_NORMAL); + + // check if correct mode + if (UMode != MODSEL_COMMAND) + { + UMode = MODSEL_COMMAND; + sendpacket[sendlen++] = MODE_COMMAND; + } + + // set the SPUD time value + sendpacket[sendlen++] = CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_512us; + + // pulse command + sendpacket[sendlen++] = CMD_COMM | FUNCTSEL_CHMOD | BITPOL_12V | SPEEDSEL_PULSE; + + // flush the buffers + FlushCOM(); + + // send the packet + if (WriteCOM(sendlen,sendpacket)) + { + // read back the 2 byte response + if (ReadCOM(2,readbuffer) == 2) + { + // check response byte + if (((readbuffer[0] | CMD_CONFIG) == + (CMD_CONFIG | PARMSEL_12VPULSE | PARMSET_512us)) && + ((readbuffer[1] & 0xFC) == + (0xFC & (CMD_COMM | FUNCTSEL_CHMOD | BITPOL_12V | SPEEDSEL_PULSE)))) + return TRUE; + } + } + + // an error occured so re-sync with DS2480 + DS2480Detect(); + + return FALSE; +} + 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); +} diff --git a/src/pmdas/roomtemp/mlan/mlansesu.c b/src/pmdas/roomtemp/mlan/mlansesu.c new file mode 100644 index 0000000..b46c349 --- /dev/null +++ b/src/pmdas/roomtemp/mlan/mlansesu.c @@ -0,0 +1,102 @@ +//--------------------------------------------------------------------------- +// 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. +//--------------------------------------------------------------------------- +// +// MLanSesU.C - Aquire and release a Session on the 1-Wire Net. +// +// Version: 1.03 +// + +#include "pmapi.h" +#include "mlan.h" + +// external function prototypes +extern int OpenCOM(char *); +extern void CloseCOM(void); +extern int DS2480Detect(void); + +// local function prototypes +int Aquire1WireNet(char *, char *); +void Release1WireNet(char *); + +// keep port name for later message when closing +char portname[128]; + +// debugging +int MLanDebug = 0; + +//--------------------------------------------------------------------------- +// Attempt to aquire a 1-Wire net using a com port and a DS2480 based +// adapter. +// +// 'port_zstr' - zero terminated port name. For this platform +// use format COMX where X is the port number. +// 'return_msg' - zero terminated return message. +// +// Returns: TRUE - success, COM port opened +// +int Aquire1WireNet(char *port_zstr, char *return_msg) +{ + int cnt=0; + portname[0] = 0; + + // attempt to open the communications port + if (OpenCOM(port_zstr) >= 0) + cnt += sprintf(&return_msg[cnt],"%s opened\n",port_zstr); + else + { + cnt += sprintf(&return_msg[cnt],"Could not open port %s: %s," + " aborting.\nClosing port %s.\n",port_zstr,osstrerror(),port_zstr); + return FALSE; + } + + // detect DS2480 + if (DS2480Detect()) + cnt += sprintf(&return_msg[cnt],"DS2480-based adapter detected\n"); + else + { + cnt += sprintf(&return_msg[cnt],"DS2480-based adapter not detected, aborting program\n"); + cnt += sprintf(&return_msg[cnt],"Closing port %s.\n",port_zstr); + CloseCOM(); + return FALSE; + } + + // success + sprintf(portname,"%s",port_zstr); + return TRUE; +} + + +//--------------------------------------------------------------------------- +// Release the previously aquired a 1-Wire net. +// +// 'return_msg' - zero terminated return message. +// +void Release1WireNet(char *return_msg) +{ + // close the communications port + sprintf(return_msg,"Closing port %s.\n",portname); + CloseCOM(); +} 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; +} + + |